Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/scapy/layers/sctp.py: 83%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

201 statements  

1# SPDX-License-Identifier: GPL-2.0-only 

2# This file is part of Scapy 

3# See https://scapy.net/ for more information 

4# Copyright (C) Philippe Biondi <phil@secdev.org> 

5# Copyright (C) 6WIND <olivier.matz@6wind.com> 

6 

7""" 

8SCTP (Stream Control Transmission Protocol). 

9""" 

10 

11import struct 

12 

13from scapy.compat import orb, raw 

14from scapy.volatile import RandBin 

15from scapy.config import conf 

16from scapy.packet import Packet, bind_layers 

17from scapy.fields import ( 

18 BitField, 

19 ByteEnumField, 

20 Field, 

21 FieldLenField, 

22 FieldListField, 

23 IPField, 

24 IntEnumField, 

25 IntField, 

26 MultipleTypeField, 

27 PacketLenField, 

28 PacketListField, 

29 PadField, 

30 ShortEnumField, 

31 ShortField, 

32 StrFixedLenField, 

33 StrLenField, 

34 XByteField, 

35 XIntField, 

36 XShortField, 

37) 

38from scapy.data import SCTP_SERVICES 

39from scapy.layers.inet import IP, IPerror 

40from scapy.layers.inet6 import IP6Field, IPv6, IPerror6, nh_clserror 

41 

42IPPROTO_SCTP = 132 

43 

44# crc32-c (Castagnoli) (crc32c_poly=0x1EDC6F41) 

45crc32c_table = [ 

46 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 

47 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, 

48 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 

49 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, 

50 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 

51 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, 

52 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 

53 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, 

54 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 

55 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, 

56 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 

57 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, 

58 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 

59 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, 

60 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 

61 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, 

62 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 

63 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, 

64 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 

65 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, 

66 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 

67 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, 

68 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 

69 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, 

70 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 

71 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, 

72 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 

73 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, 

74 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 

75 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, 

76 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 

77 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, 

78 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 

79 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, 

80 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 

81 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, 

82 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 

83 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, 

84 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 

85 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, 

86 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 

87 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, 

88 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 

89 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, 

90 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 

91 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, 

92 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 

93 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, 

94 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 

95 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, 

96 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 

97 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, 

98 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 

99 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, 

100 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 

101 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, 

102 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 

103 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, 

104 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 

105 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, 

106 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 

107 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, 

108 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 

109 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351, 

110] 

111 

112 

113def crc32c(buf): 

114 crc = 0xffffffff 

115 for c in buf: 

116 crc = (crc >> 8) ^ crc32c_table[(crc ^ (orb(c))) & 0xFF] 

117 crc = (~crc) & 0xffffffff 

118 # reverse endianness 

119 return struct.unpack(">I", struct.pack("<I", crc))[0] 

120 

121 

122# old checksum (RFC2960) 

123""" 

124BASE = 65521 # largest prime smaller than 65536 

125def update_adler32(adler, buf): 

126 s1 = adler & 0xffff 

127 s2 = (adler >> 16) & 0xffff 

128 print(s1, s2) 

129 

130 for c in buf: 

131 print(orb(c)) 

132 s1 = (s1 + orb(c)) % BASE 

133 s2 = (s2 + s1) % BASE 

134 print(s1, s2) 

135 return (s2 << 16) + s1 

136 

137def sctp_checksum(buf): 

138 return update_adler32(1, buf) 

139""" 

140 

141hmactypes = { 

142 0: "Reserved1", 

143 1: "SHA-1", 

144 2: "Reserved2", 

145 3: "SHA-256", 

146} 

147 

148sctpchunktypescls = { 

149 0: "SCTPChunkData", 

150 1: "SCTPChunkInit", 

151 2: "SCTPChunkInitAck", 

152 3: "SCTPChunkSACK", 

153 4: "SCTPChunkHeartbeatReq", 

154 5: "SCTPChunkHeartbeatAck", 

155 6: "SCTPChunkAbort", 

156 7: "SCTPChunkShutdown", 

157 8: "SCTPChunkShutdownAck", 

158 9: "SCTPChunkError", 

159 10: "SCTPChunkCookieEcho", 

160 11: "SCTPChunkCookieAck", 

161 14: "SCTPChunkShutdownComplete", 

162 15: "SCTPChunkAuthentication", 

163 64: "SCTPChunkIData", 

164 130: "SCTPChunkReConfig", 

165 132: "SCTPChunkPad", 

166 0x80: "SCTPChunkAddressConfAck", 

167 192: "SCTPChunkForwardTSN", 

168 0xc1: "SCTPChunkAddressConf", 

169 194: "SCTPChunkIForwardTSN", 

170} 

171 

172sctpchunktypes = { 

173 0: "data", 

174 1: "init", 

175 2: "init-ack", 

176 3: "sack", 

177 4: "heartbeat-req", 

178 5: "heartbeat-ack", 

179 6: "abort", 

180 7: "shutdown", 

181 8: "shutdown-ack", 

182 9: "error", 

183 10: "cookie-echo", 

184 11: "cookie-ack", 

185 14: "shutdown-complete", 

186 15: "authentication", 

187 64: "i-data", 

188 130: "re-config", 

189 132: "pad", 

190 0x80: "address-configuration-ack", 

191 192: "forward-tsn", 

192 0xc1: "address-configuration", 

193 194: "i-forward-tsn", 

194} 

195 

196sctpchunkparamtypescls = { 

197 1: "SCTPChunkParamHeartbeatInfo", 

198 5: "SCTPChunkParamIPv4Addr", 

199 6: "SCTPChunkParamIPv6Addr", 

200 7: "SCTPChunkParamStateCookie", 

201 8: "SCTPChunkParamUnrocognizedParam", 

202 9: "SCTPChunkParamCookiePreservative", 

203 11: "SCTPChunkParamHostname", 

204 12: "SCTPChunkParamSupportedAddrTypes", 

205 13: "SCTPChunkParamOutgoingSSNResetRequest", 

206 14: "SCTPChunkParamIncomingSSNResetRequest", 

207 15: "SCTPChunkParamSSNTSNResetRequest", 

208 16: "SCTPChunkParamReConfigurationResponse", 

209 17: "SCTPChunkParamAddOutgoingStreamRequest", 

210 18: "SCTPChunkParamAddIncomingStreamRequest", 

211 0x8000: "SCTPChunkParamECNCapable", 

212 0x8002: "SCTPChunkParamRandom", 

213 0x8003: "SCTPChunkParamChunkList", 

214 0x8004: "SCTPChunkParamRequestedHMACFunctions", 

215 0x8008: "SCTPChunkParamSupportedExtensions", 

216 0xc000: "SCTPChunkParamFwdTSN", 

217 0xc001: "SCTPChunkParamAddIPAddr", 

218 0xc002: "SCTPChunkParamDelIPAddr", 

219 0xc003: "SCTPChunkParamErrorIndication", 

220 0xc004: "SCTPChunkParamSetPrimaryAddr", 

221 0xc005: "SCTPChunkParamSuccessIndication", 

222 0xc006: "SCTPChunkParamAdaptationLayer", 

223} 

224 

225sctpchunkparamtypes = { 

226 1: "heartbeat-info", 

227 5: "IPv4", 

228 6: "IPv6", 

229 7: "state-cookie", 

230 8: "unrecognized-param", 

231 9: "cookie-preservative", 

232 11: "hostname", 

233 12: "addrtypes", 

234 13: "out-ssn-reset-req", 

235 14: "in-ssn-reset-req", 

236 15: "ssn-tsn-reset-req", 

237 16: "re-configuration-response", 

238 17: "add-outgoing-stream-req", 

239 18: "add-incoming-stream-req", 

240 0x8000: "ecn-capable", 

241 0x8002: "random", 

242 0x8003: "chunk-list", 

243 0x8004: "requested-HMAC-functions", 

244 0x8008: "supported-extensions", 

245 0xc000: "fwd-tsn-supported", 

246 0xc001: "add-IP", 

247 0xc002: "del-IP", 

248 0xc003: "error-indication", 

249 0xc004: "set-primary-addr", 

250 0xc005: "success-indication", 

251 0xc006: "adaptation-layer", 

252} 

253 

254# SCTP header 

255 

256# Dummy class to guess payload type (variable parameters) 

257 

258 

259class _SCTPChunkGuessPayload: 

260 def default_payload_class(self, p): 

261 if len(p) < 4: 

262 return conf.padding_layer 

263 else: 

264 t = orb(p[0]) 

265 return globals().get(sctpchunktypescls.get(t, "Raw"), conf.raw_layer) # noqa: E501 

266 

267 

268class SCTP(_SCTPChunkGuessPayload, Packet): 

269 fields_desc = [ShortEnumField("sport", 0, SCTP_SERVICES), 

270 ShortEnumField("dport", 0, SCTP_SERVICES), 

271 XIntField("tag", 0), 

272 XIntField("chksum", None), ] 

273 

274 def answers(self, other): 

275 if not isinstance(other, SCTP): 

276 return 0 

277 if conf.checkIPsrc: 

278 if not ((self.sport == other.dport) and 

279 (self.dport == other.sport)): 

280 return 0 

281 return 1 

282 

283 def post_build(self, p, pay): 

284 p += pay 

285 if self.chksum is None: 

286 crc = crc32c(raw(p)) 

287 p = p[:8] + struct.pack(">I", crc) + p[12:] 

288 return p 

289 

290 

291class SCTPerror(SCTP): 

292 name = "SCTP in ICMP" 

293 

294 def answers(self, other): 

295 if not isinstance(other, SCTP): 

296 return 0 

297 if conf.checkIPsrc: 

298 if not ((self.sport == other.sport) and 

299 (self.dport == other.dport)): 

300 return 0 

301 return 1 

302 

303 def mysummary(self): 

304 return Packet.mysummary(self) 

305 

306 

307nh_clserror[IPPROTO_SCTP] = SCTPerror 

308 

309# SCTP Chunk variable params 

310 

311 

312resultcode = { 

313 0: "Success - Nothing to do", 

314 1: "Success - Performed", 

315 2: "Denied", 

316 3: "Error - Wrong SSN", 

317 4: "Error - Request already in progress", 

318 5: "Error - Bad Sequence Number", 

319 6: "In Progress" 

320} 

321 

322 

323class ChunkParamField(PacketListField): 

324 def __init__(self, name, default, count_from=None, length_from=None): 

325 PacketListField.__init__(self, name, default, conf.raw_layer, count_from=count_from, length_from=length_from) # noqa: E501 

326 

327 def m2i(self, p, m): 

328 cls = conf.raw_layer 

329 if len(m) >= 4: 

330 t = orb(m[0]) * 256 + orb(m[1]) 

331 cls = globals().get(sctpchunkparamtypescls.get(t, "Raw"), conf.raw_layer) # noqa: E501 

332 return cls(m) 

333 

334# dummy class to avoid Raw() after Chunk params 

335 

336 

337class _SCTPChunkParam: 

338 def extract_padding(self, s): 

339 return b"", s[:] 

340 

341 

342class SCTPChunkParamHeartbeatInfo(_SCTPChunkParam, Packet): 

343 fields_desc = [ShortEnumField("type", 1, sctpchunkparamtypes), 

344 FieldLenField("len", None, length_of="data", 

345 adjust=lambda pkt, x:x + 4), 

346 PadField(StrLenField("data", "", 

347 length_from=lambda pkt: pkt.len - 4), 

348 4, padwith=b"\x00"), ] 

349 

350 

351class SCTPChunkParamIPv4Addr(_SCTPChunkParam, Packet): 

352 fields_desc = [ShortEnumField("type", 5, sctpchunkparamtypes), 

353 ShortField("len", 8), 

354 IPField("addr", "127.0.0.1"), ] 

355 

356 

357class SCTPChunkParamIPv6Addr(_SCTPChunkParam, Packet): 

358 fields_desc = [ShortEnumField("type", 6, sctpchunkparamtypes), 

359 ShortField("len", 20), 

360 IP6Field("addr", "::1"), ] 

361 

362 

363class SCTPChunkParamStateCookie(_SCTPChunkParam, Packet): 

364 fields_desc = [ShortEnumField("type", 7, sctpchunkparamtypes), 

365 FieldLenField("len", None, length_of="cookie", 

366 adjust=lambda pkt, x:x + 4), 

367 PadField(StrLenField("cookie", "", 

368 length_from=lambda pkt: pkt.len - 4), 

369 4, padwith=b"\x00"), ] 

370 

371 

372class SCTPChunkParamUnrocognizedParam(_SCTPChunkParam, Packet): 

373 fields_desc = [ShortEnumField("type", 8, sctpchunkparamtypes), 

374 FieldLenField("len", None, length_of="param", 

375 adjust=lambda pkt, x:x + 4), 

376 PadField(StrLenField("param", "", 

377 length_from=lambda pkt: pkt.len - 4), 

378 4, padwith=b"\x00"), ] 

379 

380 

381class SCTPChunkParamCookiePreservative(_SCTPChunkParam, Packet): 

382 fields_desc = [ShortEnumField("type", 9, sctpchunkparamtypes), 

383 ShortField("len", 8), 

384 XIntField("sug_cookie_inc", None), ] 

385 

386 

387class SCTPChunkParamHostname(_SCTPChunkParam, Packet): 

388 fields_desc = [ShortEnumField("type", 11, sctpchunkparamtypes), 

389 FieldLenField("len", None, length_of="hostname", 

390 adjust=lambda pkt, x:x + 4), 

391 PadField(StrLenField("hostname", "", 

392 length_from=lambda pkt: pkt.len - 4), 

393 4, padwith=b"\x00"), ] 

394 

395 

396class SCTPChunkParamSupportedAddrTypes(_SCTPChunkParam, Packet): 

397 fields_desc = [ShortEnumField("type", 12, sctpchunkparamtypes), 

398 FieldLenField("len", None, length_of="addr_type_list", 

399 adjust=lambda pkt, x:x + 4), 

400 PadField(FieldListField("addr_type_list", ["IPv4"], 

401 ShortEnumField("addr_type", 5, sctpchunkparamtypes), # noqa: E501 

402 length_from=lambda pkt: pkt.len - 4), # noqa: E501 

403 4, padwith=b"\x00"), ] 

404 

405 

406class SCTPChunkParamOutSSNResetReq(_SCTPChunkParam, Packet): 

407 fields_desc = [ShortEnumField("type", 13, sctpchunkparamtypes), 

408 FieldLenField("len", None, length_of="stream_num_list", 

409 adjust=lambda pkt, x:x + 16), 

410 XIntField("re_conf_req_seq_num", None), 

411 XIntField("re_conf_res_seq_num", None), 

412 XIntField("tsn", None), 

413 PadField(FieldListField("stream_num_list", [], 

414 XShortField("stream_num", None), 

415 length_from=lambda pkt: pkt.len - 16), 

416 4, padwith=b"\x00"), 

417 ] 

418 

419 

420class SCTPChunkParamInSSNResetReq(_SCTPChunkParam, Packet): 

421 fields_desc = [ShortEnumField("type", 14, sctpchunkparamtypes), 

422 FieldLenField("len", None, length_of="stream_num_list", 

423 adjust=lambda pkt, x:x + 8), 

424 XIntField("re_conf_req_seq_num", None), 

425 PadField(FieldListField("stream_num_list", [], 

426 XShortField("stream_num", None), 

427 length_from=lambda pkt: pkt.len - 8), 

428 4, padwith=b"\x00"), 

429 ] 

430 

431 

432class SCTPChunkParamSSNTSNResetReq(_SCTPChunkParam, Packet): 

433 fields_desc = [ShortEnumField("type", 15, sctpchunkparamtypes), 

434 XShortField("len", 8), 

435 XIntField("re_conf_req_seq_num", None), 

436 ] 

437 

438 

439class SCTPChunkParamReConfigRes(_SCTPChunkParam, Packet): 

440 fields_desc = [ShortEnumField("type", 16, sctpchunkparamtypes), 

441 XShortField("len", 12), 

442 XIntField("re_conf_res_seq_num", None), 

443 IntEnumField("result", None, resultcode), 

444 XIntField("sender_next_tsn", None), 

445 XIntField("receiver_next_tsn", None), 

446 ] 

447 

448 

449class SCTPChunkParamAddOutgoingStreamReq(_SCTPChunkParam, Packet): 

450 fields_desc = [ShortEnumField("type", 17, sctpchunkparamtypes), 

451 XShortField("len", 12), 

452 XIntField("re_conf_req_seq_num", None), 

453 XShortField("num_new_stream", None), 

454 XShortField("reserved", None), 

455 ] 

456 

457 

458class SCTPChunkParamAddIncomingStreamReq(SCTPChunkParamAddOutgoingStreamReq): 

459 type = 18 

460 

461 

462class SCTPChunkParamECNCapable(_SCTPChunkParam, Packet): 

463 fields_desc = [ShortEnumField("type", 0x8000, sctpchunkparamtypes), 

464 ShortField("len", 4), ] 

465 

466 

467class SCTPChunkParamRandom(_SCTPChunkParam, Packet): 

468 fields_desc = [ShortEnumField("type", 0x8002, sctpchunkparamtypes), 

469 FieldLenField("len", None, length_of="random", 

470 adjust=lambda pkt, x:x + 4), 

471 PadField(StrLenField("random", RandBin(32), 

472 length_from=lambda pkt: pkt.len - 4), 

473 4, padwith=b"\x00"), ] 

474 

475 

476class SCTPChunkParamChunkList(_SCTPChunkParam, Packet): 

477 fields_desc = [ShortEnumField("type", 0x8003, sctpchunkparamtypes), 

478 FieldLenField("len", None, length_of="chunk_list", 

479 adjust=lambda pkt, x:x + 4), 

480 PadField(FieldListField("chunk_list", None, 

481 ByteEnumField("chunk", None, sctpchunktypes), # noqa: E501 

482 length_from=lambda pkt: pkt.len - 4), # noqa: E501 

483 4, padwith=b"\x00"), ] 

484 

485 

486class SCTPChunkParamRequestedHMACFunctions(_SCTPChunkParam, Packet): 

487 fields_desc = [ShortEnumField("type", 0x8004, sctpchunkparamtypes), 

488 FieldLenField("len", None, length_of="HMAC_functions_list", 

489 adjust=lambda pkt, x:x + 4), 

490 PadField(FieldListField("HMAC_functions_list", ["SHA-1"], 

491 ShortEnumField("HMAC_function", 1, hmactypes), # noqa: E501 

492 length_from=lambda pkt: pkt.len - 4), # noqa: E501 

493 4, padwith=b"\x00"), ] 

494 

495 

496class SCTPChunkParamSupportedExtensions(_SCTPChunkParam, Packet): 

497 fields_desc = [ShortEnumField("type", 0x8008, sctpchunkparamtypes), 

498 FieldLenField("len", None, length_of="supported_extensions", 

499 adjust=lambda pkt, x:x + 4), 

500 PadField(FieldListField("supported_extensions", 

501 ["authentication", 

502 "address-configuration", 

503 "address-configuration-ack"], 

504 ByteEnumField("supported_extensions", # noqa: E501 

505 None, sctpchunktypes), 

506 length_from=lambda pkt: pkt.len - 4), # noqa: E501 

507 4, padwith=b"\x00"), ] 

508 

509 

510class SCTPChunkParamFwdTSN(_SCTPChunkParam, Packet): 

511 fields_desc = [ShortEnumField("type", 0xc000, sctpchunkparamtypes), 

512 ShortField("len", 4), ] 

513 

514 

515class SCTPChunkParamAddIPAddr(_SCTPChunkParam, Packet): 

516 fields_desc = [ShortEnumField("type", 0xc001, sctpchunkparamtypes), 

517 FieldLenField("len", None, length_of="addr", 

518 adjust=lambda pkt, x:x + 12), 

519 XIntField("correlation_id", None), 

520 ShortEnumField("addr_type", 5, sctpchunkparamtypes), 

521 FieldLenField("addr_len", None, length_of="addr", 

522 adjust=lambda pkt, x:x + 4), 

523 MultipleTypeField( 

524 [ 

525 (IPField("addr", "127.0.0.1"), 

526 lambda p: p.addr_type == 5), 

527 (IP6Field("addr", "::1"), 

528 lambda p: p.addr_type == 6), 

529 ], 

530 StrFixedLenField("addr", "", 

531 length_from=lambda pkt: pkt.addr_len)) 

532 ] 

533 

534 

535class SCTPChunkParamDelIPAddr(SCTPChunkParamAddIPAddr): 

536 type = 0xc002 

537 

538 

539class SCTPChunkParamErrorIndication(_SCTPChunkParam, Packet): 

540 fields_desc = [ShortEnumField("type", 0xc003, sctpchunkparamtypes), 

541 FieldLenField("len", None, length_of="error_causes", 

542 adjust=lambda pkt, x:x + 8), 

543 XIntField("correlation_id", None), 

544 PadField(StrLenField("error_causes", "", 

545 length_from=lambda pkt: pkt.len - 4), 

546 4, padwith=b"\x00"), ] 

547 

548 

549class SCTPChunkParamSetPrimaryAddr(SCTPChunkParamAddIPAddr): 

550 type = 0xc004 

551 

552 

553class SCTPChunkParamSuccessIndication(_SCTPChunkParam, Packet): 

554 fields_desc = [ShortEnumField("type", 0xc005, sctpchunkparamtypes), 

555 ShortField("len", 8), 

556 XIntField("correlation_id", None), ] 

557 

558 

559class SCTPChunkParamAdaptationLayer(_SCTPChunkParam, Packet): 

560 fields_desc = [ShortEnumField("type", 0xc006, sctpchunkparamtypes), 

561 ShortField("len", 8), 

562 XIntField("indication", None), ] 

563 

564# SCTP Chunks 

565 

566 

567# Dictionary taken from: http://www.iana.org/assignments/sctp-parameters/sctp-parameters.xhtml # noqa: E501 

568SCTP_PAYLOAD_PROTOCOL_INDENTIFIERS = { 

569 0: 'Reserved', 

570 1: 'IUA', 

571 2: 'M2UA', 

572 3: 'M3UA', 

573 4: 'SUA', 

574 5: 'M2PA', 

575 6: 'V5UA', 

576 7: 'H.248', 

577 8: 'BICC/Q.2150.3', 

578 9: 'TALI', 

579 10: 'DUA', 

580 11: 'ASAP', 

581 12: 'ENRP', 

582 13: 'H.323', 

583 14: 'Q.IPC/Q.2150.3', 

584 15: 'SIMCO', 

585 16: 'DDP Segment Chunk', 

586 17: 'DDP Stream Session Control', 

587 18: 'S1AP', 

588 19: 'RUA', 

589 20: 'HNBAP', 

590 21: 'ForCES-HP', 

591 22: 'ForCES-MP', 

592 23: 'ForCES-LP', 

593 24: 'SBc-AP', 

594 25: 'NBAP', 

595 26: 'Unassigned', 

596 27: 'X2AP', 

597 28: 'IRCP', 

598 29: 'LCS-AP', 

599 30: 'MPICH2', 

600 31: 'SABP', 

601 32: 'FGP', 

602 33: 'PPP', 

603 34: 'CALCAPP', 

604 35: 'SSP', 

605 36: 'NPMP-CONTROL', 

606 37: 'NPMP-DATA', 

607 38: 'ECHO', 

608 39: 'DISCARD', 

609 40: 'DAYTIME', 

610 41: 'CHARGEN', 

611 42: '3GPP RNA', 

612 43: '3GPP M2AP', 

613 44: '3GPP M3AP', 

614 45: 'SSH/SCTP', 

615 46: 'Diameter/SCTP', 

616 47: 'Diameter/DTLS/SCTP', 

617 48: 'R14P', 

618 49: 'Unassigned', 

619 50: 'WebRTC DCEP', 

620 51: 'WebRTC String', 

621 52: 'WebRTC Binary Partial', 

622 53: 'WebRTC Binary', 

623 54: 'WebRTC String Partial', 

624 55: '3GPP PUA', 

625 56: 'WebRTC String Empty', 

626 57: 'WebRTC Binary Empty' 

627} 

628 

629 

630class _SCTPChunkDataField(PacketLenField): 

631 """PacketLenField that dispatches using bind_layers bindings.""" 

632 

633 def m2i(self, pkt, m): 

634 # Only dissect complete messages 

635 if pkt.beginning != 1 or pkt.ending != 1: 

636 return conf.raw_layer(load=m) 

637 # Check bind_layers bindings 

638 for fval, cls in pkt.payload_guess: 

639 if all( 

640 hasattr(pkt, k) and v == pkt.getfieldval(k) 

641 for k, v in fval.items() 

642 ): 

643 return cls(m) 

644 return conf.raw_layer(load=m) 

645 

646 

647class SCTPChunkData(_SCTPChunkGuessPayload, Packet): 

648 # TODO : add a padding function in post build if this layer is used to generate SCTP chunk data # noqa: E501 

649 fields_desc = [ByteEnumField("type", 0, sctpchunktypes), 

650 BitField("reserved", None, 4), 

651 BitField("delay_sack", 0, 1), 

652 BitField("unordered", 0, 1), 

653 BitField("beginning", 0, 1), 

654 BitField("ending", 0, 1), 

655 FieldLenField("len", None, length_of="data", adjust=lambda pkt, x:x + 16), # noqa: E501 

656 XIntField("tsn", None), 

657 XShortField("stream_id", None), 

658 XShortField("stream_seq", None), 

659 IntEnumField("proto_id", None, SCTP_PAYLOAD_PROTOCOL_INDENTIFIERS), # noqa: E501 

660 PadField(_SCTPChunkDataField("data", None, conf.raw_layer, 

661 length_from=lambda pkt: pkt.len - 16), # noqa: E501 

662 4, padwith=b"\x00"), 

663 ] 

664 

665 

666class SCTPChunkIData(_SCTPChunkGuessPayload, Packet): 

667 fields_desc = [ByteEnumField("type", 64, sctpchunktypes), 

668 BitField("reserved", None, 4), 

669 BitField("delay_sack", 0, 1), # immediate bit 

670 BitField("unordered", 0, 1), 

671 BitField("beginning", 0, 1), 

672 BitField("ending", 0, 1), 

673 FieldLenField("len", None, length_of="data", 

674 adjust=lambda pkt, x:x + 20), 

675 XIntField("tsn", None), 

676 XShortField("stream_id", None), 

677 XShortField("reserved_16", None), 

678 XIntField("message_id", None), 

679 MultipleTypeField( 

680 [ 

681 (IntEnumField("ppid_fsn", None, 

682 SCTP_PAYLOAD_PROTOCOL_INDENTIFIERS), 

683 lambda pkt: pkt.beginning == 1), 

684 (XIntField("ppid_fsn", None), 

685 lambda pkt: pkt.beginning == 0), 

686 ], 

687 XIntField("ppid_fsn", None)), 

688 PadField(StrLenField("data", None, 

689 length_from=lambda pkt: pkt.len - 20), 

690 4, padwith=b"\x00"), 

691 ] 

692 

693 

694class SCTPForwardSkip(_SCTPChunkParam, Packet): 

695 fields_desc = [ShortField("stream_id", None), 

696 ShortField("stream_seq", None) 

697 ] 

698 

699 

700class SCTPChunkForwardTSN(_SCTPChunkGuessPayload, Packet): 

701 fields_desc = [ByteEnumField("type", 192, sctpchunktypes), 

702 XByteField("flags", None), 

703 FieldLenField("len", None, length_of="skips", 

704 adjust=lambda pkt, x:x + 8), 

705 IntField("new_tsn", None), 

706 ChunkParamField("skips", None, 

707 length_from=lambda pkt: pkt.len - 8) 

708 ] 

709 

710 

711class SCTPIForwardSkip(_SCTPChunkParam, Packet): 

712 fields_desc = [ShortField("stream_id", None), 

713 BitField("reserved", None, 15), 

714 BitField("unordered", None, 1), 

715 IntField("message_id", None) 

716 ] 

717 

718 

719class SCTPChunkIForwardTSN(SCTPChunkForwardTSN): 

720 type = 194 

721 

722 

723class SCTPChunkInit(_SCTPChunkGuessPayload, Packet): 

724 fields_desc = [ByteEnumField("type", 1, sctpchunktypes), 

725 XByteField("flags", None), 

726 FieldLenField("len", None, length_of="params", adjust=lambda pkt, x:x + 20), # noqa: E501 

727 XIntField("init_tag", None), 

728 IntField("a_rwnd", None), 

729 ShortField("n_out_streams", None), 

730 ShortField("n_in_streams", None), 

731 XIntField("init_tsn", None), 

732 ChunkParamField("params", None, length_from=lambda pkt:pkt.len - 20), # noqa: E501 

733 ] 

734 

735 

736class SCTPChunkInitAck(SCTPChunkInit): 

737 type = 2 

738 

739 

740class GapAckField(Field): 

741 def __init__(self, name, default): 

742 Field.__init__(self, name, default, "4s") 

743 

744 def i2m(self, pkt, x): 

745 if x is None: 

746 return b"\0\0\0\0" 

747 sta, end = [int(e) for e in x.split(':')] 

748 args = tuple([">HH", sta, end]) 

749 return struct.pack(*args) 

750 

751 def m2i(self, pkt, x): 

752 return "%d:%d" % (struct.unpack(">HH", x)) 

753 

754 def any2i(self, pkt, x): 

755 if isinstance(x, tuple) and len(x) == 2: 

756 return "%d:%d" % (x) 

757 return x 

758 

759 

760class SCTPChunkSACK(_SCTPChunkGuessPayload, Packet): 

761 fields_desc = [ByteEnumField("type", 3, sctpchunktypes), 

762 XByteField("flags", None), 

763 ShortField("len", None), 

764 XIntField("cumul_tsn_ack", None), 

765 IntField("a_rwnd", None), 

766 FieldLenField("n_gap_ack", None, count_of="gap_ack_list"), 

767 FieldLenField("n_dup_tsn", None, count_of="dup_tsn_list"), 

768 FieldListField("gap_ack_list", [], GapAckField("gap_ack", None), count_from=lambda pkt:pkt.n_gap_ack), # noqa: E501 

769 FieldListField("dup_tsn_list", [], XIntField("dup_tsn", None), count_from=lambda pkt:pkt.n_dup_tsn), # noqa: E501 

770 ] 

771 

772 def post_build(self, p, pay): 

773 if self.len is None: 

774 p = p[:2] + struct.pack(">H", len(p)) + p[4:] 

775 return p + pay 

776 

777 

778class SCTPChunkHeartbeatReq(_SCTPChunkGuessPayload, Packet): 

779 fields_desc = [ByteEnumField("type", 4, sctpchunktypes), 

780 XByteField("flags", None), 

781 FieldLenField("len", None, length_of="params", adjust=lambda pkt, x:x + 4), # noqa: E501 

782 ChunkParamField("params", None, length_from=lambda pkt:pkt.len - 4), # noqa: E501 

783 ] 

784 

785 

786class SCTPChunkHeartbeatAck(SCTPChunkHeartbeatReq): 

787 type = 5 

788 

789 

790class SCTPChunkAbort(_SCTPChunkGuessPayload, Packet): 

791 fields_desc = [ByteEnumField("type", 6, sctpchunktypes), 

792 BitField("reserved", None, 7), 

793 BitField("TCB", 0, 1), 

794 FieldLenField("len", None, length_of="error_causes", adjust=lambda pkt, x:x + 4), # noqa: E501 

795 PadField(StrLenField("error_causes", "", length_from=lambda pkt: pkt.len - 4), # noqa: E501 

796 4, padwith=b"\x00"), 

797 ] 

798 

799 

800class SCTPChunkShutdown(_SCTPChunkGuessPayload, Packet): 

801 fields_desc = [ByteEnumField("type", 7, sctpchunktypes), 

802 XByteField("flags", None), 

803 ShortField("len", 8), 

804 XIntField("cumul_tsn_ack", None), 

805 ] 

806 

807 

808class SCTPChunkShutdownAck(_SCTPChunkGuessPayload, Packet): 

809 fields_desc = [ByteEnumField("type", 8, sctpchunktypes), 

810 XByteField("flags", None), 

811 ShortField("len", 4), 

812 ] 

813 

814 

815class SCTPChunkError(_SCTPChunkGuessPayload, Packet): 

816 fields_desc = [ByteEnumField("type", 9, sctpchunktypes), 

817 XByteField("flags", None), 

818 FieldLenField("len", None, length_of="error_causes", adjust=lambda pkt, x:x + 4), # noqa: E501 

819 PadField(StrLenField("error_causes", "", length_from=lambda pkt: pkt.len - 4), # noqa: E501 

820 4, padwith=b"\x00"), 

821 ] 

822 

823 

824class SCTPChunkCookieEcho(SCTPChunkError): 

825 fields_desc = [ByteEnumField("type", 10, sctpchunktypes), 

826 XByteField("flags", None), 

827 FieldLenField("len", None, length_of="cookie", adjust=lambda pkt, x:x + 4), # noqa: E501 

828 PadField(StrLenField("cookie", "", length_from=lambda pkt: pkt.len - 4), # noqa: E501 

829 4, padwith=b"\x00"), 

830 ] 

831 

832 

833class SCTPChunkCookieAck(_SCTPChunkGuessPayload, Packet): 

834 fields_desc = [ByteEnumField("type", 11, sctpchunktypes), 

835 XByteField("flags", None), 

836 ShortField("len", 4), 

837 ] 

838 

839 

840class SCTPChunkShutdownComplete(_SCTPChunkGuessPayload, Packet): 

841 fields_desc = [ByteEnumField("type", 14, sctpchunktypes), 

842 BitField("reserved", None, 7), 

843 BitField("TCB", 0, 1), 

844 ShortField("len", 4), 

845 ] 

846 

847 

848class SCTPChunkAuthentication(_SCTPChunkGuessPayload, Packet): 

849 fields_desc = [ByteEnumField("type", 15, sctpchunktypes), 

850 XByteField("flags", None), 

851 FieldLenField("len", None, length_of="HMAC", 

852 adjust=lambda pkt, x:x + 8), 

853 ShortField("shared_key_id", None), 

854 ShortField("HMAC_function", None), 

855 PadField(StrLenField("HMAC", "", length_from=lambda pkt: pkt.len - 8), # noqa: E501 

856 4, padwith=b"\x00"), 

857 ] 

858 

859 

860class SCTPChunkAddressConf(_SCTPChunkGuessPayload, Packet): 

861 fields_desc = [ByteEnumField("type", 0xc1, sctpchunktypes), 

862 XByteField("flags", None), 

863 FieldLenField("len", None, length_of="params", 

864 adjust=lambda pkt, x:x + 8), 

865 IntField("seq", 0), 

866 ChunkParamField("params", None, length_from=lambda pkt:pkt.len - 8), # noqa: E501 

867 ] 

868 

869 

870class SCTPChunkReConfig(_SCTPChunkGuessPayload, Packet): 

871 fields_desc = [ByteEnumField("type", 130, sctpchunktypes), 

872 XByteField("flags", None), 

873 FieldLenField("len", None, length_of="params", 

874 adjust=lambda pkt, x:x + 4), 

875 ChunkParamField("params", None, length_from=lambda pkt: pkt.len - 4), 

876 ] 

877 

878 

879class SCTPChunkPad(_SCTPChunkGuessPayload, Packet): 

880 fields_desc = [ByteEnumField("type", 132, sctpchunktypes), 

881 XByteField("flags", None), 

882 FieldLenField("len", None, length_of="padding", 

883 adjust=lambda pkt, x:x + 8), 

884 PadField(StrLenField("padding", None, 

885 length_from=lambda pkt: pkt.len - 8), 

886 4, padwith=b"\x00") 

887 ] 

888 

889 

890class SCTPChunkAddressConfAck(SCTPChunkAddressConf): 

891 type = 0x80 

892 

893 

894bind_layers(IP, SCTP, proto=IPPROTO_SCTP) 

895bind_layers(IPerror, SCTPerror, proto=IPPROTO_SCTP) 

896bind_layers(IPv6, SCTP, nh=IPPROTO_SCTP) 

897bind_layers(IPerror6, SCTPerror, proto=IPPROTO_SCTP)