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)