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

192 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 PacketListField, 

28 PadField, 

29 ShortEnumField, 

30 ShortField, 

31 StrFixedLenField, 

32 StrLenField, 

33 XByteField, 

34 XIntField, 

35 XShortField, 

36) 

37from scapy.data import SCTP_SERVICES 

38from scapy.layers.inet import IP, IPerror 

39from scapy.layers.inet6 import IP6Field, IPv6, IPerror6 

40 

41IPPROTO_SCTP = 132 

42 

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

44crc32c_table = [ 

45 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 

46 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, 

47 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 

48 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, 

49 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 

50 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, 

51 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 

52 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, 

53 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 

54 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, 

55 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 

56 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, 

57 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 

58 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, 

59 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 

60 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, 

61 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 

62 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, 

63 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 

64 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, 

65 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 

66 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, 

67 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 

68 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, 

69 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 

70 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, 

71 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 

72 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, 

73 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 

74 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, 

75 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 

76 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, 

77 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 

78 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, 

79 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 

80 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, 

81 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 

82 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, 

83 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 

84 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, 

85 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 

86 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, 

87 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 

88 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, 

89 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 

90 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, 

91 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 

92 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, 

93 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 

94 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, 

95 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 

96 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, 

97 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 

98 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, 

99 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 

100 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, 

101 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 

102 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, 

103 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 

104 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, 

105 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 

106 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, 

107 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 

108 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351, 

109] 

110 

111 

112def crc32c(buf): 

113 crc = 0xffffffff 

114 for c in buf: 

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

116 crc = (~crc) & 0xffffffff 

117 # reverse endianness 

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

119 

120 

121# old checksum (RFC2960) 

122""" 

123BASE = 65521 # largest prime smaller than 65536 

124def update_adler32(adler, buf): 

125 s1 = adler & 0xffff 

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

127 print s1,s2 

128 

129 for c in buf: 

130 print orb(c) 

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

132 s2 = (s2 + s1) % BASE 

133 print s1,s2 

134 return (s2 << 16) + s1 

135 

136def sctp_checksum(buf): 

137 return update_adler32(1, buf) 

138""" 

139 

140hmactypes = { 

141 0: "Reserved1", 

142 1: "SHA-1", 

143 2: "Reserved2", 

144 3: "SHA-256", 

145} 

146 

147sctpchunktypescls = { 

148 0: "SCTPChunkData", 

149 1: "SCTPChunkInit", 

150 2: "SCTPChunkInitAck", 

151 3: "SCTPChunkSACK", 

152 4: "SCTPChunkHeartbeatReq", 

153 5: "SCTPChunkHeartbeatAck", 

154 6: "SCTPChunkAbort", 

155 7: "SCTPChunkShutdown", 

156 8: "SCTPChunkShutdownAck", 

157 9: "SCTPChunkError", 

158 10: "SCTPChunkCookieEcho", 

159 11: "SCTPChunkCookieAck", 

160 14: "SCTPChunkShutdownComplete", 

161 15: "SCTPChunkAuthentication", 

162 64: "SCTPChunkIData", 

163 130: "SCTPChunkReConfig", 

164 132: "SCTPChunkPad", 

165 0x80: "SCTPChunkAddressConfAck", 

166 192: "SCTPChunkForwardTSN", 

167 0xc1: "SCTPChunkAddressConf", 

168 194: "SCTPChunkIForwardTSN", 

169} 

170 

171sctpchunktypes = { 

172 0: "data", 

173 1: "init", 

174 2: "init-ack", 

175 3: "sack", 

176 4: "heartbeat-req", 

177 5: "heartbeat-ack", 

178 6: "abort", 

179 7: "shutdown", 

180 8: "shutdown-ack", 

181 9: "error", 

182 10: "cookie-echo", 

183 11: "cookie-ack", 

184 14: "shutdown-complete", 

185 15: "authentication", 

186 64: "i-data", 

187 130: "re-config", 

188 132: "pad", 

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

190 192: "forward-tsn", 

191 0xc1: "address-configuration", 

192 194: "i-forward-tsn", 

193} 

194 

195sctpchunkparamtypescls = { 

196 1: "SCTPChunkParamHeartbeatInfo", 

197 5: "SCTPChunkParamIPv4Addr", 

198 6: "SCTPChunkParamIPv6Addr", 

199 7: "SCTPChunkParamStateCookie", 

200 8: "SCTPChunkParamUnrocognizedParam", 

201 9: "SCTPChunkParamCookiePreservative", 

202 11: "SCTPChunkParamHostname", 

203 12: "SCTPChunkParamSupportedAddrTypes", 

204 13: "SCTPChunkParamOutgoingSSNResetRequest", 

205 14: "SCTPChunkParamIncomingSSNResetRequest", 

206 15: "SCTPChunkParamSSNTSNResetRequest", 

207 16: "SCTPChunkParamReConfigurationResponse", 

208 17: "SCTPChunkParamAddOutgoingStreamRequest", 

209 18: "SCTPChunkParamAddIncomingStreamRequest", 

210 0x8000: "SCTPChunkParamECNCapable", 

211 0x8002: "SCTPChunkParamRandom", 

212 0x8003: "SCTPChunkParamChunkList", 

213 0x8004: "SCTPChunkParamRequestedHMACFunctions", 

214 0x8008: "SCTPChunkParamSupportedExtensions", 

215 0xc000: "SCTPChunkParamFwdTSN", 

216 0xc001: "SCTPChunkParamAddIPAddr", 

217 0xc002: "SCTPChunkParamDelIPAddr", 

218 0xc003: "SCTPChunkParamErrorIndication", 

219 0xc004: "SCTPChunkParamSetPrimaryAddr", 

220 0xc005: "SCTPChunkParamSuccessIndication", 

221 0xc006: "SCTPChunkParamAdaptationLayer", 

222} 

223 

224sctpchunkparamtypes = { 

225 1: "heartbeat-info", 

226 5: "IPv4", 

227 6: "IPv6", 

228 7: "state-cookie", 

229 8: "unrecognized-param", 

230 9: "cookie-preservative", 

231 11: "hostname", 

232 12: "addrtypes", 

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

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

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

236 16: "re-configuration-response", 

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

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

239 0x8000: "ecn-capable", 

240 0x8002: "random", 

241 0x8003: "chunk-list", 

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

243 0x8008: "supported-extensions", 

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

245 0xc001: "add-IP", 

246 0xc002: "del-IP", 

247 0xc003: "error-indication", 

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

249 0xc005: "success-indication", 

250 0xc006: "adaptation-layer", 

251} 

252 

253# SCTP header 

254 

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

256 

257 

258class _SCTPChunkGuessPayload: 

259 def default_payload_class(self, p): 

260 if len(p) < 4: 

261 return conf.padding_layer 

262 else: 

263 t = orb(p[0]) 

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

265 

266 

267class SCTP(_SCTPChunkGuessPayload, Packet): 

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

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

270 XIntField("tag", 0), 

271 XIntField("chksum", None), ] 

272 

273 def answers(self, other): 

274 if not isinstance(other, SCTP): 

275 return 0 

276 if conf.checkIPsrc: 

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

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

279 return 0 

280 return 1 

281 

282 def post_build(self, p, pay): 

283 p += pay 

284 if self.chksum is None: 

285 crc = crc32c(raw(p)) 

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

287 return p 

288 

289 

290class SCTPerror(SCTP): 

291 name = "SCTP in ICMP" 

292 

293 def answers(self, other): 

294 if not isinstance(other, SCTP): 

295 return 0 

296 if conf.checkIPsrc: 

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

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

299 return 0 

300 return 1 

301 

302 def mysummary(self): 

303 return Packet.mysummary(self) 

304 

305 

306# SCTP Chunk variable params 

307 

308 

309resultcode = { 

310 0: "Success - Nothing to do", 

311 1: "Success - Performed", 

312 2: "Denied", 

313 3: "Error - Wrong SSN", 

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

315 5: "Error - Bad Sequence Number", 

316 6: "In Progress" 

317} 

318 

319 

320class ChunkParamField(PacketListField): 

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

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

323 

324 def m2i(self, p, m): 

325 cls = conf.raw_layer 

326 if len(m) >= 4: 

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

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

329 return cls(m) 

330 

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

332 

333 

334class _SCTPChunkParam: 

335 def extract_padding(self, s): 

336 return b"", s[:] 

337 

338 

339class SCTPChunkParamHeartbeatInfo(_SCTPChunkParam, Packet): 

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

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

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

343 PadField(StrLenField("data", "", 

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

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

346 

347 

348class SCTPChunkParamIPv4Addr(_SCTPChunkParam, Packet): 

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

350 ShortField("len", 8), 

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

352 

353 

354class SCTPChunkParamIPv6Addr(_SCTPChunkParam, Packet): 

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

356 ShortField("len", 20), 

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

358 

359 

360class SCTPChunkParamStateCookie(_SCTPChunkParam, Packet): 

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

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

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

364 PadField(StrLenField("cookie", "", 

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

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

367 

368 

369class SCTPChunkParamUnrocognizedParam(_SCTPChunkParam, Packet): 

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

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

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

373 PadField(StrLenField("param", "", 

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

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

376 

377 

378class SCTPChunkParamCookiePreservative(_SCTPChunkParam, Packet): 

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

380 ShortField("len", 8), 

381 XIntField("sug_cookie_inc", None), ] 

382 

383 

384class SCTPChunkParamHostname(_SCTPChunkParam, Packet): 

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

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

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

388 PadField(StrLenField("hostname", "", 

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

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

391 

392 

393class SCTPChunkParamSupportedAddrTypes(_SCTPChunkParam, Packet): 

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

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

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

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

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

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

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

401 

402 

403class SCTPChunkParamOutSSNResetReq(_SCTPChunkParam, Packet): 

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

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

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

407 XIntField("re_conf_req_seq_num", None), 

408 XIntField("re_conf_res_seq_num", None), 

409 XIntField("tsn", None), 

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

411 XShortField("stream_num", None), 

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

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

414 ] 

415 

416 

417class SCTPChunkParamInSSNResetReq(_SCTPChunkParam, Packet): 

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

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

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

421 XIntField("re_conf_req_seq_num", None), 

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

423 XShortField("stream_num", None), 

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

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

426 ] 

427 

428 

429class SCTPChunkParamSSNTSNResetReq(_SCTPChunkParam, Packet): 

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

431 XShortField("len", 8), 

432 XIntField("re_conf_req_seq_num", None), 

433 ] 

434 

435 

436class SCTPChunkParamReConfigRes(_SCTPChunkParam, Packet): 

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

438 XShortField("len", 12), 

439 XIntField("re_conf_res_seq_num", None), 

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

441 XIntField("sender_next_tsn", None), 

442 XIntField("receiver_next_tsn", None), 

443 ] 

444 

445 

446class SCTPChunkParamAddOutgoingStreamReq(_SCTPChunkParam, Packet): 

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

448 XShortField("len", 12), 

449 XIntField("re_conf_req_seq_num", None), 

450 XShortField("num_new_stream", None), 

451 XShortField("reserved", None), 

452 ] 

453 

454 

455class SCTPChunkParamAddIncomingStreamReq(SCTPChunkParamAddOutgoingStreamReq): 

456 type = 18 

457 

458 

459class SCTPChunkParamECNCapable(_SCTPChunkParam, Packet): 

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

461 ShortField("len", 4), ] 

462 

463 

464class SCTPChunkParamRandom(_SCTPChunkParam, Packet): 

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

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

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

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

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

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

471 

472 

473class SCTPChunkParamChunkList(_SCTPChunkParam, Packet): 

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

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

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

477 PadField(FieldListField("chunk_list", None, 

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

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

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

481 

482 

483class SCTPChunkParamRequestedHMACFunctions(_SCTPChunkParam, Packet): 

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

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

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

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

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

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

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

491 

492 

493class SCTPChunkParamSupportedExtensions(_SCTPChunkParam, Packet): 

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

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

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

497 PadField(FieldListField("supported_extensions", 

498 ["authentication", 

499 "address-configuration", 

500 "address-configuration-ack"], 

501 ByteEnumField("supported_extensions", # noqa: E501 

502 None, sctpchunktypes), 

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

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

505 

506 

507class SCTPChunkParamFwdTSN(_SCTPChunkParam, Packet): 

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

509 ShortField("len", 4), ] 

510 

511 

512class SCTPChunkParamAddIPAddr(_SCTPChunkParam, Packet): 

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

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

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

516 XIntField("correlation_id", None), 

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

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

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

520 MultipleTypeField( 

521 [ 

522 (IPField("addr", "127.0.0.1"), 

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

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

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

526 ], 

527 StrFixedLenField("addr", "", 

528 length_from=lambda pkt: pkt.addr_len)) 

529 ] 

530 

531 

532class SCTPChunkParamDelIPAddr(SCTPChunkParamAddIPAddr): 

533 type = 0xc002 

534 

535 

536class SCTPChunkParamErrorIndication(_SCTPChunkParam, Packet): 

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

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

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

540 XIntField("correlation_id", None), 

541 PadField(StrLenField("error_causes", "", 

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

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

544 

545 

546class SCTPChunkParamSetPrimaryAddr(SCTPChunkParamAddIPAddr): 

547 type = 0xc004 

548 

549 

550class SCTPChunkParamSuccessIndication(_SCTPChunkParam, Packet): 

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

552 ShortField("len", 8), 

553 XIntField("correlation_id", None), ] 

554 

555 

556class SCTPChunkParamAdaptationLayer(_SCTPChunkParam, Packet): 

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

558 ShortField("len", 8), 

559 XIntField("indication", None), ] 

560 

561# SCTP Chunks 

562 

563 

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

565SCTP_PAYLOAD_PROTOCOL_INDENTIFIERS = { 

566 0: 'Reserved', 

567 1: 'IUA', 

568 2: 'M2UA', 

569 3: 'M3UA', 

570 4: 'SUA', 

571 5: 'M2PA', 

572 6: 'V5UA', 

573 7: 'H.248', 

574 8: 'BICC/Q.2150.3', 

575 9: 'TALI', 

576 10: 'DUA', 

577 11: 'ASAP', 

578 12: 'ENRP', 

579 13: 'H.323', 

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

581 15: 'SIMCO', 

582 16: 'DDP Segment Chunk', 

583 17: 'DDP Stream Session Control', 

584 18: 'S1AP', 

585 19: 'RUA', 

586 20: 'HNBAP', 

587 21: 'ForCES-HP', 

588 22: 'ForCES-MP', 

589 23: 'ForCES-LP', 

590 24: 'SBc-AP', 

591 25: 'NBAP', 

592 26: 'Unassigned', 

593 27: 'X2AP', 

594 28: 'IRCP', 

595 29: 'LCS-AP', 

596 30: 'MPICH2', 

597 31: 'SABP', 

598 32: 'FGP', 

599 33: 'PPP', 

600 34: 'CALCAPP', 

601 35: 'SSP', 

602 36: 'NPMP-CONTROL', 

603 37: 'NPMP-DATA', 

604 38: 'ECHO', 

605 39: 'DISCARD', 

606 40: 'DAYTIME', 

607 41: 'CHARGEN', 

608 42: '3GPP RNA', 

609 43: '3GPP M2AP', 

610 44: '3GPP M3AP', 

611 45: 'SSH/SCTP', 

612 46: 'Diameter/SCTP', 

613 47: 'Diameter/DTLS/SCTP', 

614 48: 'R14P', 

615 49: 'Unassigned', 

616 50: 'WebRTC DCEP', 

617 51: 'WebRTC String', 

618 52: 'WebRTC Binary Partial', 

619 53: 'WebRTC Binary', 

620 54: 'WebRTC String Partial', 

621 55: '3GPP PUA', 

622 56: 'WebRTC String Empty', 

623 57: 'WebRTC Binary Empty' 

624} 

625 

626 

627class SCTPChunkData(_SCTPChunkGuessPayload, Packet): 

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

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

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

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

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

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

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

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

636 XIntField("tsn", None), 

637 XShortField("stream_id", None), 

638 XShortField("stream_seq", None), 

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

640 PadField(StrLenField("data", None, length_from=lambda pkt: pkt.len - 16), # noqa: E501 

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

642 ] 

643 

644 

645class SCTPChunkIData(_SCTPChunkGuessPayload, Packet): 

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

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

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

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

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

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

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

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

654 XIntField("tsn", None), 

655 XShortField("stream_id", None), 

656 XShortField("reserved_16", None), 

657 XIntField("message_id", None), 

658 MultipleTypeField( 

659 [ 

660 (IntEnumField("ppid_fsn", None, 

661 SCTP_PAYLOAD_PROTOCOL_INDENTIFIERS), 

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

663 (XIntField("ppid_fsn", None), 

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

665 ], 

666 XIntField("ppid_fsn", None)), 

667 PadField(StrLenField("data", None, 

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

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

670 ] 

671 

672 

673class SCTPForwardSkip(_SCTPChunkParam, Packet): 

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

675 ShortField("stream_seq", None) 

676 ] 

677 

678 

679class SCTPChunkForwardTSN(_SCTPChunkGuessPayload, Packet): 

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

681 XByteField("flags", None), 

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

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

684 IntField("new_tsn", None), 

685 ChunkParamField("skips", None, 

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

687 ] 

688 

689 

690class SCTPIForwardSkip(_SCTPChunkParam, Packet): 

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

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

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

694 IntField("message_id", None) 

695 ] 

696 

697 

698class SCTPChunkIForwardTSN(SCTPChunkForwardTSN): 

699 type = 194 

700 

701 

702class SCTPChunkInit(_SCTPChunkGuessPayload, Packet): 

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

704 XByteField("flags", None), 

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

706 XIntField("init_tag", None), 

707 IntField("a_rwnd", None), 

708 ShortField("n_out_streams", None), 

709 ShortField("n_in_streams", None), 

710 XIntField("init_tsn", None), 

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

712 ] 

713 

714 

715class SCTPChunkInitAck(SCTPChunkInit): 

716 type = 2 

717 

718 

719class GapAckField(Field): 

720 def __init__(self, name, default): 

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

722 

723 def i2m(self, pkt, x): 

724 if x is None: 

725 return b"\0\0\0\0" 

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

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

728 return struct.pack(*args) 

729 

730 def m2i(self, pkt, x): 

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

732 

733 def any2i(self, pkt, x): 

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

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

736 return x 

737 

738 

739class SCTPChunkSACK(_SCTPChunkGuessPayload, Packet): 

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

741 XByteField("flags", None), 

742 ShortField("len", None), 

743 XIntField("cumul_tsn_ack", None), 

744 IntField("a_rwnd", None), 

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

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

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

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

749 ] 

750 

751 def post_build(self, p, pay): 

752 if self.len is None: 

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

754 return p + pay 

755 

756 

757class SCTPChunkHeartbeatReq(_SCTPChunkGuessPayload, Packet): 

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

759 XByteField("flags", None), 

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

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

762 ] 

763 

764 

765class SCTPChunkHeartbeatAck(SCTPChunkHeartbeatReq): 

766 type = 5 

767 

768 

769class SCTPChunkAbort(_SCTPChunkGuessPayload, Packet): 

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

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

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

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

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

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

776 ] 

777 

778 

779class SCTPChunkShutdown(_SCTPChunkGuessPayload, Packet): 

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

781 XByteField("flags", None), 

782 ShortField("len", 8), 

783 XIntField("cumul_tsn_ack", None), 

784 ] 

785 

786 

787class SCTPChunkShutdownAck(_SCTPChunkGuessPayload, Packet): 

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

789 XByteField("flags", None), 

790 ShortField("len", 4), 

791 ] 

792 

793 

794class SCTPChunkError(_SCTPChunkGuessPayload, Packet): 

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

796 XByteField("flags", None), 

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

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

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

800 ] 

801 

802 

803class SCTPChunkCookieEcho(SCTPChunkError): 

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

805 XByteField("flags", None), 

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

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

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

809 ] 

810 

811 

812class SCTPChunkCookieAck(_SCTPChunkGuessPayload, Packet): 

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

814 XByteField("flags", None), 

815 ShortField("len", 4), 

816 ] 

817 

818 

819class SCTPChunkShutdownComplete(_SCTPChunkGuessPayload, Packet): 

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

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

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

823 ShortField("len", 4), 

824 ] 

825 

826 

827class SCTPChunkAuthentication(_SCTPChunkGuessPayload, Packet): 

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

829 XByteField("flags", None), 

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

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

832 ShortField("shared_key_id", None), 

833 ShortField("HMAC_function", None), 

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

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

836 ] 

837 

838 

839class SCTPChunkAddressConf(_SCTPChunkGuessPayload, Packet): 

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

841 XByteField("flags", None), 

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

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

844 IntField("seq", 0), 

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

846 ] 

847 

848 

849class SCTPChunkReConfig(_SCTPChunkGuessPayload, Packet): 

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

851 XByteField("flags", None), 

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

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

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

855 ] 

856 

857 

858class SCTPChunkPad(_SCTPChunkGuessPayload, Packet): 

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

860 XByteField("flags", None), 

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

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

863 PadField(StrLenField("padding", None, 

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

865 4, padwith=b"\x00") 

866 ] 

867 

868 

869class SCTPChunkAddressConfAck(SCTPChunkAddressConf): 

870 type = 0x80 

871 

872 

873bind_layers(IP, SCTP, proto=IPPROTO_SCTP) 

874bind_layers(IPerror, SCTPerror, proto=IPPROTO_SCTP) 

875bind_layers(IPv6, SCTP, nh=IPPROTO_SCTP) 

876bind_layers(IPerror6, SCTPerror, proto=IPPROTO_SCTP)