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
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
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>
7"""
8SCTP (Stream Control Transmission Protocol).
9"""
11import struct
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
42IPPROTO_SCTP = 132
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]
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]
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)
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
137def sctp_checksum(buf):
138 return update_adler32(1, buf)
139"""
141hmactypes = {
142 0: "Reserved1",
143 1: "SHA-1",
144 2: "Reserved2",
145 3: "SHA-256",
146}
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}
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}
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}
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}
254# SCTP header
256# Dummy class to guess payload type (variable parameters)
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
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), ]
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
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
291class SCTPerror(SCTP):
292 name = "SCTP in ICMP"
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
303 def mysummary(self):
304 return Packet.mysummary(self)
307nh_clserror[IPPROTO_SCTP] = SCTPerror
309# SCTP Chunk variable params
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}
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
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)
334# dummy class to avoid Raw() after Chunk params
337class _SCTPChunkParam:
338 def extract_padding(self, s):
339 return b"", s[:]
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"), ]
351class SCTPChunkParamIPv4Addr(_SCTPChunkParam, Packet):
352 fields_desc = [ShortEnumField("type", 5, sctpchunkparamtypes),
353 ShortField("len", 8),
354 IPField("addr", "127.0.0.1"), ]
357class SCTPChunkParamIPv6Addr(_SCTPChunkParam, Packet):
358 fields_desc = [ShortEnumField("type", 6, sctpchunkparamtypes),
359 ShortField("len", 20),
360 IP6Field("addr", "::1"), ]
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"), ]
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"), ]
381class SCTPChunkParamCookiePreservative(_SCTPChunkParam, Packet):
382 fields_desc = [ShortEnumField("type", 9, sctpchunkparamtypes),
383 ShortField("len", 8),
384 XIntField("sug_cookie_inc", None), ]
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"), ]
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"), ]
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 ]
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 ]
432class SCTPChunkParamSSNTSNResetReq(_SCTPChunkParam, Packet):
433 fields_desc = [ShortEnumField("type", 15, sctpchunkparamtypes),
434 XShortField("len", 8),
435 XIntField("re_conf_req_seq_num", None),
436 ]
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 ]
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 ]
458class SCTPChunkParamAddIncomingStreamReq(SCTPChunkParamAddOutgoingStreamReq):
459 type = 18
462class SCTPChunkParamECNCapable(_SCTPChunkParam, Packet):
463 fields_desc = [ShortEnumField("type", 0x8000, sctpchunkparamtypes),
464 ShortField("len", 4), ]
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"), ]
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"), ]
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"), ]
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"), ]
510class SCTPChunkParamFwdTSN(_SCTPChunkParam, Packet):
511 fields_desc = [ShortEnumField("type", 0xc000, sctpchunkparamtypes),
512 ShortField("len", 4), ]
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 ]
535class SCTPChunkParamDelIPAddr(SCTPChunkParamAddIPAddr):
536 type = 0xc002
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"), ]
549class SCTPChunkParamSetPrimaryAddr(SCTPChunkParamAddIPAddr):
550 type = 0xc004
553class SCTPChunkParamSuccessIndication(_SCTPChunkParam, Packet):
554 fields_desc = [ShortEnumField("type", 0xc005, sctpchunkparamtypes),
555 ShortField("len", 8),
556 XIntField("correlation_id", None), ]
559class SCTPChunkParamAdaptationLayer(_SCTPChunkParam, Packet):
560 fields_desc = [ShortEnumField("type", 0xc006, sctpchunkparamtypes),
561 ShortField("len", 8),
562 XIntField("indication", None), ]
564# SCTP Chunks
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}
630class _SCTPChunkDataField(PacketLenField):
631 """PacketLenField that dispatches using bind_layers bindings."""
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)
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 ]
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 ]
694class SCTPForwardSkip(_SCTPChunkParam, Packet):
695 fields_desc = [ShortField("stream_id", None),
696 ShortField("stream_seq", None)
697 ]
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 ]
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 ]
719class SCTPChunkIForwardTSN(SCTPChunkForwardTSN):
720 type = 194
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 ]
736class SCTPChunkInitAck(SCTPChunkInit):
737 type = 2
740class GapAckField(Field):
741 def __init__(self, name, default):
742 Field.__init__(self, name, default, "4s")
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)
751 def m2i(self, pkt, x):
752 return "%d:%d" % (struct.unpack(">HH", x))
754 def any2i(self, pkt, x):
755 if isinstance(x, tuple) and len(x) == 2:
756 return "%d:%d" % (x)
757 return x
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 ]
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
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 ]
786class SCTPChunkHeartbeatAck(SCTPChunkHeartbeatReq):
787 type = 5
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 ]
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 ]
808class SCTPChunkShutdownAck(_SCTPChunkGuessPayload, Packet):
809 fields_desc = [ByteEnumField("type", 8, sctpchunktypes),
810 XByteField("flags", None),
811 ShortField("len", 4),
812 ]
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 ]
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 ]
833class SCTPChunkCookieAck(_SCTPChunkGuessPayload, Packet):
834 fields_desc = [ByteEnumField("type", 11, sctpchunktypes),
835 XByteField("flags", None),
836 ShortField("len", 4),
837 ]
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 ]
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 ]
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 ]
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 ]
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 ]
890class SCTPChunkAddressConfAck(SCTPChunkAddressConf):
891 type = 0x80
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)