2 * Routines for Stream Control Transmission Protocol dissection
3 * It should be compilant to
6 * - http://www.ietf.org/internet-drafts/draft-ietf-tsvwg-sctpimpguide-09.txt
7 * - http://www.ietf.org/internet-drafts/draft-ietf-tsvwg-addip-sctp-08.txt for the add-IP extension
8 * - http://www.ietf.org/internet-drafts/draft-stewart-tsvwg-prsctp-04.txt for the 'Partial Reliability' extension
9 * - another upcoming ID on packetdrop stuff.
10 * Copyright 2000, 2001, 2002, 2003, 2004 Michael Tuexen <tuexen [AT] fh-muenster.de>
11 * Still to do (so stay tuned)
12 * - support for reassembly
13 * - error checking mode
19 * $Id: packet-sctp.c,v 1.72 2004/05/24 02:25:19 guy Exp $
21 * Ethereal - Network traffic analyzer
22 * By Gerald Combs <gerald@ethereal.com>
23 * Copyright 1998 Gerald Combs
25 * Copied from README.developer
27 * This program is free software; you can redistribute it and/or
28 * modify it under the terms of the GNU General Public License
29 * as published by the Free Software Foundation; either version 2
30 * of the License, or (at your option) any later version.
32 * This program is distributed in the hope that it will be useful,
33 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 * GNU General Public License for more details.
37 * You should have received a copy of the GNU General Public License
38 * along with this program; if not, write to the Free Software
39 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
48 #include <epan/packet.h>
51 #include "packet-sctp.h"
52 #include "sctpppids.h"
54 #define NETWORK_BYTE_ORDER FALSE
55 #define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
56 #define UDP_TUNNELING_PORT 9899
58 /* Initialize the protocol and registered fields */
59 static int proto_sctp = -1;
60 static int hf_port = -1;
61 static int hf_source_port = -1;
62 static int hf_destination_port = -1;
63 static int hf_verification_tag = -1;
64 static int hf_checksum = -1;
65 static int hf_checksum_bad = -1;
67 static int hf_chunk_type = -1;
68 static int hf_chunk_flags = -1;
69 static int hf_chunk_bit_1 = -1;
70 static int hf_chunk_bit_2 = -1;
71 static int hf_chunk_length = -1;
72 static int hf_chunk_padding = -1;
73 static int hf_chunk_value = -1;
75 static int hf_initiate_tag = -1;
76 static int hf_init_chunk_initiate_tag = -1;
77 static int hf_init_chunk_adv_rec_window_credit = -1;
78 static int hf_init_chunk_number_of_outbound_streams = -1;
79 static int hf_init_chunk_number_of_inbound_streams = -1;
80 static int hf_init_chunk_initial_tsn = -1;
82 static int hf_initack_chunk_initiate_tag = -1;
83 static int hf_initack_chunk_adv_rec_window_credit = -1;
84 static int hf_initack_chunk_number_of_outbound_streams = -1;
85 static int hf_initack_chunk_number_of_inbound_streams = -1;
86 static int hf_initack_chunk_initial_tsn = -1;
88 static int hf_cumulative_tsn_ack = -1;
90 static int hf_data_chunk_tsn = -1;
91 static int hf_data_chunk_stream_id = -1;
92 static int hf_data_chunk_stream_seq_number = -1;
93 static int hf_data_chunk_payload_proto_id = -1;
95 static int hf_data_chunk_e_bit = -1;
96 static int hf_data_chunk_b_bit = -1;
97 static int hf_data_chunk_u_bit = -1;
99 static int hf_sack_chunk_cumulative_tsn_ack = -1;
100 static int hf_sack_chunk_adv_rec_window_credit = -1;
101 static int hf_sack_chunk_number_of_gap_blocks = -1;
102 static int hf_sack_chunk_number_of_dup_tsns = -1;
103 static int hf_sack_chunk_gap_block_start = -1;
104 static int hf_sack_chunk_gap_block_end = -1;
105 static int hf_sack_chunk_duplicate_tsn = -1;
107 static int hf_shutdown_chunk_cumulative_tsn_ack = -1;
108 static int hf_cookie = -1;
109 static int hf_cwr_chunk_lowest_tsn = -1;
111 static int hf_ecne_chunk_lowest_tsn = -1;
112 static int hf_abort_chunk_t_bit = -1;
113 static int hf_shutdown_complete_chunk_t_bit = -1;
115 static int hf_parameter_type = -1;
116 static int hf_parameter_length = -1;
117 static int hf_parameter_value = -1;
118 static int hf_parameter_padding = -1;
119 static int hf_parameter_bit_1 = -1;
120 static int hf_parameter_bit_2 = -1;
121 static int hf_ipv4_address = -1;
122 static int hf_ipv6_address = -1;
123 static int hf_heartbeat_info = -1;
124 static int hf_state_cookie = -1;
125 static int hf_cookie_preservative_increment = -1;
126 static int hf_hostname = -1;
127 static int hf_supported_address_type = -1;
129 static int hf_cause_code = -1;
130 static int hf_cause_length = -1;
131 static int hf_cause_padding = -1;
132 static int hf_cause_info = -1;
134 static int hf_cause_stream_identifier = -1;
135 static int hf_cause_reserved = -1;
137 static int hf_cause_number_of_missing_parameters = -1;
138 static int hf_cause_missing_parameter_type = -1;
140 static int hf_cause_measure_of_staleness = -1;
142 static int hf_cause_tsn = -1;
144 static int hf_forward_tsn_chunk_tsn = -1;
145 static int hf_forward_tsn_chunk_sid = -1;
146 static int hf_forward_tsn_chunk_ssn = -1;
148 static int hf_asconf_ack_serial = -1;
149 static int hf_asconf_serial = -1;
150 static int hf_correlation_id = -1;
152 static int hf_adap_indication = -1;
154 static int hf_pktdrop_chunk_m_bit = -1;
156 static int hf_pktdrop_chunk_s_bit = -1;
158 static int hf_pktdrop_chunk_b_bit = -1;
159 static int hf_pktdrop_chunk_t_bit = -1;
160 static int hf_pktdrop_chunk_bandwidth = -1;
161 static int hf_pktdrop_chunk_queuesize = -1;
162 static int hf_pktdrop_chunk_truncated_length = -1;
163 static int hf_pktdrop_chunk_reserved = -1;
164 static int hf_pktdrop_chunk_data_field = -1;
166 static dissector_table_t sctp_port_dissector_table;
167 static dissector_table_t sctp_ppi_dissector_table;
168 static heur_dissector_list_t sctp_heur_subdissector_list;
169 static int sctp_tap = -1;
170 static module_t *sctp_module;
172 /* Initialize the subtree pointers */
173 static gint ett_sctp = -1;
174 static gint ett_sctp_chunk = -1;
175 static gint ett_sctp_chunk_parameter = -1;
176 static gint ett_sctp_chunk_cause = -1;
177 static gint ett_sctp_chunk_type = -1;
178 static gint ett_sctp_data_chunk_flags = -1;
179 static gint ett_sctp_abort_chunk_flags = -1;
180 static gint ett_sctp_shutdown_complete_chunk_flags = -1;
181 static gint ett_sctp_pktdrop_chunk_flags = -1;
182 static gint ett_sctp_parameter_type= -1;
183 static gint ett_sctp_sack_chunk_gap_block = -1;
184 static gint ett_sctp_unrecognized_parameter_parameter = -1;
186 static dissector_handle_t data_handle;
188 #define SCTP_DATA_CHUNK_ID 0
189 #define SCTP_INIT_CHUNK_ID 1
190 #define SCTP_INIT_ACK_CHUNK_ID 2
191 #define SCTP_SACK_CHUNK_ID 3
192 #define SCTP_HEARTBEAT_CHUNK_ID 4
193 #define SCTP_HEARTBEAT_ACK_CHUNK_ID 5
194 #define SCTP_ABORT_CHUNK_ID 6
195 #define SCTP_SHUTDOWN_CHUNK_ID 7
196 #define SCTP_SHUTDOWN_ACK_CHUNK_ID 8
197 #define SCTP_ERROR_CHUNK_ID 9
198 #define SCTP_COOKIE_ECHO_CHUNK_ID 10
199 #define SCTP_COOKIE_ACK_CHUNK_ID 11
200 #define SCTP_ECNE_CHUNK_ID 12
201 #define SCTP_CWR_CHUNK_ID 13
202 #define SCTP_SHUTDOWN_COMPLETE_CHUNK_ID 14
203 #define SCTP_FORWARD_TSN_CHUNK_ID 192
204 #define SCTP_ASCONF_ACK_CHUNK_ID 0x80
205 #define SCTP_PKTDROP_CHUNK_ID 0X81
206 #define SCTP_ASCONF_CHUNK_ID 0XC1
207 #define SCTP_IETF_EXT 255
209 static const value_string chunk_type_values[] = {
210 { SCTP_DATA_CHUNK_ID, "DATA" },
211 { SCTP_INIT_CHUNK_ID, "INIT" },
212 { SCTP_INIT_ACK_CHUNK_ID, "INIT_ACK" },
213 { SCTP_SACK_CHUNK_ID, "SACK" },
214 { SCTP_HEARTBEAT_CHUNK_ID, "HEARTBEAT" },
215 { SCTP_HEARTBEAT_ACK_CHUNK_ID, "HEARTBEAT_ACK" },
216 { SCTP_ABORT_CHUNK_ID, "ABORT" },
217 { SCTP_SHUTDOWN_CHUNK_ID, "SHUTDOWN" },
218 { SCTP_SHUTDOWN_ACK_CHUNK_ID, "SHUTDOWN_ACK" },
219 { SCTP_ERROR_CHUNK_ID, "ERROR" },
220 { SCTP_COOKIE_ECHO_CHUNK_ID, "COOKIE_ECHO" },
221 { SCTP_COOKIE_ACK_CHUNK_ID, "COOKIE_ACK" },
222 { SCTP_ECNE_CHUNK_ID, "ECNE" },
223 { SCTP_CWR_CHUNK_ID, "CWR" },
224 { SCTP_SHUTDOWN_COMPLETE_CHUNK_ID, "SHUTDOWN_COMPLETE" },
225 { SCTP_FORWARD_TSN_CHUNK_ID, "FORWARD TSN" },
226 { SCTP_ASCONF_ACK_CHUNK_ID, "ASCONF_ACK" },
227 { SCTP_PKTDROP_CHUNK_ID, "PKTDROP" },
228 { SCTP_ASCONF_CHUNK_ID, "ASCONF" },
229 { SCTP_IETF_EXT, "IETF_EXTENSION" },
232 static const value_string sctp_payload_proto_id_values[] = {
233 { NOT_SPECIFIED_PROTOCOL_ID, "not specified" },
234 { IUA_PAYLOAD_PROTOCOL_ID, "IUA" },
235 { M2UA_PAYLOAD_PROTOCOL_ID, "M2UA" },
236 { M3UA_PAYLOAD_PROTOCOL_ID, "M3UA" },
237 { SUA_PAYLOAD_PROTOCOL_ID, "SUA" },
238 { M2PA_PAYLOAD_PROTOCOL_ID, "M2PA" },
239 { V5UA_PAYLOAD_PROTOCOL_ID, "V5UA" },
240 { H248_PAYLOAD_PROTOCOL_ID, "H.248/MEGACO" },
241 { BICC_PAYLOAD_PROTOCOL_ID, "BICC/Q.2150.3" },
242 { TALI_PAYLOAD_PROTOCOL_ID, "TALI" },
243 { DUA_PAYLOAD_PROTOCOL_ID, "DUA" },
244 { ASAP_PAYLOAD_PROTOCOL_ID, "ASAP" },
245 { ENRP_PAYLOAD_PROTOCOL_ID, "ENRP" },
246 { H323_PAYLOAD_PROTOCOL_ID, "H.323" },
250 #define CHUNK_TYPE_LENGTH 1
251 #define CHUNK_FLAGS_LENGTH 1
252 #define CHUNK_LENGTH_LENGTH 2
253 #define CHUNK_HEADER_LENGTH (CHUNK_TYPE_LENGTH + \
254 CHUNK_FLAGS_LENGTH + \
256 #define CHUNK_HEADER_OFFSET 0
257 #define CHUNK_TYPE_OFFSET CHUNK_HEADER_OFFSET
258 #define CHUNK_FLAGS_OFFSET (CHUNK_TYPE_OFFSET + CHUNK_TYPE_LENGTH)
259 #define CHUNK_LENGTH_OFFSET (CHUNK_FLAGS_OFFSET + CHUNK_FLAGS_LENGTH)
260 #define CHUNK_VALUE_OFFSET (CHUNK_LENGTH_OFFSET + CHUNK_LENGTH_LENGTH)
262 #define PARAMETER_TYPE_LENGTH 2
263 #define PARAMETER_LENGTH_LENGTH 2
264 #define PARAMETER_HEADER_LENGTH (PARAMETER_TYPE_LENGTH + PARAMETER_LENGTH_LENGTH)
266 #define PARAMETER_HEADER_OFFSET 0
267 #define PARAMETER_TYPE_OFFSET PARAMETER_HEADER_OFFSET
268 #define PARAMETER_LENGTH_OFFSET (PARAMETER_TYPE_OFFSET + PARAMETER_TYPE_LENGTH)
269 #define PARAMETER_VALUE_OFFSET (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
271 #define SOURCE_PORT_LENGTH 2
272 #define DESTINATION_PORT_LENGTH 2
273 #define VERIFICATION_TAG_LENGTH 4
274 #define CHECKSUM_LENGTH 4
275 #define COMMON_HEADER_LENGTH (SOURCE_PORT_LENGTH + \
276 DESTINATION_PORT_LENGTH + \
277 VERIFICATION_TAG_LENGTH + \
279 #define SOURCE_PORT_OFFSET 0
280 #define DESTINATION_PORT_OFFSET (SOURCE_PORT_OFFSET + SOURCE_PORT_LENGTH)
281 #define VERIFICATION_TAG_OFFSET (DESTINATION_PORT_OFFSET + DESTINATION_PORT_LENGTH)
282 #define CHECKSUM_OFFSET (VERIFICATION_TAG_OFFSET + VERIFICATION_TAG_LENGTH)
284 #define SCTP_CHECKSUM_NONE 0
285 #define SCTP_CHECKSUM_ADLER32 1
286 #define SCTP_CHECKSUM_CRC32C 2
287 #define SCTP_CHECKSUM_AUTOMATIC 3
289 static gboolean show_always_control_chunks = TRUE;
290 static gint sctp_checksum = SCTP_CHECKSUM_CRC32C;
291 static struct _sctp_info sctp_info;
293 /* adler32.c -- compute the Adler-32 checksum of a data stream
294 * Copyright (C) 1995-1996 Mark Adler
295 * For conditions of distribution and use, see copyright notice in zlib.h
296 * available, e.g. from http://www.cdrom.com/pub/infozip/zlib/
298 * It was modified for the use in this dissector.
301 #define BASE 65521L /* largest prime smaller than 65536 */
302 #define NMAX 5540 /* NMAX is the largest n - 12 such that */
303 /* 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
305 #define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
306 #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
307 #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
308 #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
309 #define DO16(buf) DO8(buf,0); DO8(buf,8);
312 sctp_adler32(const unsigned char* buf, unsigned int len)
314 unsigned int s1 = 1L;
315 unsigned int s2 = 0L;
318 /* handle the first 8 bytes of the datagram */
320 buf += SOURCE_PORT_LENGTH +
321 DESTINATION_PORT_LENGTH +
322 VERIFICATION_TAG_LENGTH;
324 /* handle four 0 bytes as checksum */
325 s2 += CHECKSUM_LENGTH * s1;
326 buf += CHECKSUM_LENGTH;
328 /* now we have 12 bytes handled */
329 len -= COMMON_HEADER_LENGTH;
331 /* handle the rest of the datagram */
333 k = len < NMAX ? len : NMAX;
347 return (s2 << 16) | s1;
350 /* The CRC32C code is taken from draft-ietf-tsvwg-sctpcsum-01.txt.
351 * That code is copyrighted by D. Otis and has been modified.
355 * x^32 + x^28 + x^27 + x^26 + x^25 + x^23 + x^22 + x^20 + x^19 +
356 * x^18 + x^14 + x^13 + x^11 + x^10 + x^9 + x^8 + x^6 + 1
358 * Note that this is not the AUTODIN/HDLC/802.x CRC - it uses a different
362 #define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
363 static guint32 crc_c[256] =
365 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
366 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
367 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
368 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
369 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
370 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
371 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
372 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
373 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
374 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
375 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
376 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
377 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
378 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
379 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
380 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
381 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
382 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
383 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
384 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
385 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
386 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
387 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
388 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
389 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
390 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
391 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
392 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
393 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
394 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
395 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
396 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
397 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
398 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
399 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
400 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
401 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
402 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
403 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
404 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
405 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
406 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
407 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
408 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
409 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
410 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
411 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
412 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
413 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
414 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
415 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
416 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
417 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
418 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
419 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
420 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
421 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
422 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
423 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
424 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
425 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
426 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
427 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
428 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L,
432 sctp_crc32c(const unsigned char* buf, unsigned int len)
437 unsigned char byte0,byte1,byte2,byte3;
439 for (i = 0; i < SOURCE_PORT_LENGTH + DESTINATION_PORT_LENGTH + VERIFICATION_TAG_LENGTH; i++)
441 CRC32C(crc32, buf[i]);
447 for (i = COMMON_HEADER_LENGTH; i < len; i++)
449 CRC32C(crc32, buf[i]);
453 byte0 = result & 0xff;
454 byte1 = (result>>8) & 0xff;
455 byte2 = (result>>16) & 0xff;
456 byte3 = (result>>24) & 0xff;
457 crc32 = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
462 * Routines for dissecting parameters
466 dissect_parameter(tvbuff_t *, packet_info *, proto_tree *, proto_item *, gboolean);
469 dissect_parameters(tvbuff_t *, packet_info *, proto_tree *, proto_item *, gboolean);
472 dissect_error_cause(tvbuff_t *, packet_info *, proto_tree *);
475 dissect_error_causes(tvbuff_t *, packet_info *, proto_tree *);
478 dissect_sctp_chunk(tvbuff_t *, packet_info *, proto_tree *, proto_tree *, gboolean);
481 dissect_sctp_packet(tvbuff_t *, packet_info *, proto_tree *, gboolean);
485 #define HEARTBEAT_INFO_PARAMETER_INFO_OFFSET PARAMETER_VALUE_OFFSET
488 dissect_heartbeat_info_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
490 guint16 heartbeat_info_length;
492 heartbeat_info_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
493 if (heartbeat_info_length > 0)
494 proto_tree_add_item(parameter_tree, hf_heartbeat_info, parameter_tvb, HEARTBEAT_INFO_PARAMETER_INFO_OFFSET, heartbeat_info_length, NETWORK_BYTE_ORDER);
495 proto_item_append_text(parameter_item, " (Information: %u byte%s)", heartbeat_info_length, plurality(heartbeat_info_length, "", "s"));
498 #define IPV4_ADDRESS_LENGTH 4
499 #define IPV4_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
502 dissect_ipv4_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item, proto_item *additional_item, gboolean dissecting_init_init_ack_chunk)
504 proto_tree_add_item(parameter_tree, hf_ipv4_address, parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH, NETWORK_BYTE_ORDER);
505 proto_item_append_text(parameter_item, " (Address: %s)", ip_to_str((const guint8 *)tvb_get_ptr(parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH)));
507 proto_item_append_text(additional_item, "%s", ip_to_str((const guint8 *)tvb_get_ptr(parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH)));
508 if (dissecting_init_init_ack_chunk) {
509 if (sctp_info.number_of_tvbs < MAXIMUM_NUMBER_OF_TVBS)
510 sctp_info.tvb[sctp_info.number_of_tvbs++] = parameter_tvb;
512 sctp_info.incomplete = TRUE;
516 #define IPV6_ADDRESS_LENGTH 16
517 #define IPV6_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
520 dissect_ipv6_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item, proto_item *additional_item, gboolean dissecting_init_init_ack_chunk)
522 proto_tree_add_item(parameter_tree, hf_ipv6_address, parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH, NETWORK_BYTE_ORDER);
523 proto_item_append_text(parameter_item, " (Address: %s)", ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH)));
525 proto_item_append_text(additional_item, "%s", ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH)));
526 if (dissecting_init_init_ack_chunk) {
527 if (sctp_info.number_of_tvbs < MAXIMUM_NUMBER_OF_TVBS)
528 sctp_info.tvb[sctp_info.number_of_tvbs++] = parameter_tvb;
530 sctp_info.incomplete = TRUE;
534 #define STATE_COOKIE_PARAMETER_COOKIE_OFFSET PARAMETER_VALUE_OFFSET
537 dissect_state_cookie_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
539 guint16 state_cookie_length;
541 state_cookie_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
542 if (state_cookie_length > 0)
543 proto_tree_add_item(parameter_tree, hf_state_cookie, parameter_tvb, STATE_COOKIE_PARAMETER_COOKIE_OFFSET, state_cookie_length, NETWORK_BYTE_ORDER);
544 proto_item_append_text(parameter_item, " (Cookie length: %u byte%s)", state_cookie_length, plurality(state_cookie_length, "", "s"));
548 dissect_unrecognized_parameters_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
550 /* FIXME: Does it contain one or more parameters? */
551 dissect_parameter(tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, -1, -1), pinfo, parameter_tree, NULL, FALSE);
554 #define COOKIE_PRESERVATIVE_PARAMETER_INCR_LENGTH 4
555 #define COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET PARAMETER_VALUE_OFFSET
558 dissect_cookie_preservative_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
560 proto_tree_add_item(parameter_tree, hf_cookie_preservative_increment, parameter_tvb, COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET, COOKIE_PRESERVATIVE_PARAMETER_INCR_LENGTH, NETWORK_BYTE_ORDER);
561 proto_item_append_text(parameter_item, " (Increment :%u msec)", tvb_get_ntohl(parameter_tvb, COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET));
564 #define HOSTNAME_OFFSET PARAMETER_VALUE_OFFSET
567 dissect_hostname_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
569 guint16 hostname_length;
571 hostname_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
572 proto_tree_add_item(parameter_tree, hf_hostname, parameter_tvb, HOSTNAME_OFFSET, hostname_length, NETWORK_BYTE_ORDER);
573 proto_item_append_text(parameter_item, " (Hostname: %.*s)", hostname_length, (const char *)tvb_get_ptr(parameter_tvb, HOSTNAME_OFFSET, hostname_length));
577 #define IPv4_ADDRESS_TYPE 5
578 #define IPv6_ADDRESS_TYPE 6
579 #define HOSTNAME_ADDRESS_TYPE 11
581 static const value_string address_types_values[] = {
582 { IPv4_ADDRESS_TYPE, "IPv4 address" },
583 { IPv6_ADDRESS_TYPE, "IPv6 address" },
584 { HOSTNAME_ADDRESS_TYPE, "Hostname address" },
588 #define SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH 2
591 dissect_supported_address_types_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
593 guint16 address_type, number_of_address_types, address_type_number;
596 number_of_address_types = (tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH)
597 / SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH;
599 offset = PARAMETER_VALUE_OFFSET;
600 proto_item_append_text(parameter_item, " (Supported types: ");
601 for(address_type_number = 1; address_type_number <= number_of_address_types; address_type_number++) {
602 proto_tree_add_item(parameter_tree, hf_supported_address_type, parameter_tvb, offset, SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH, NETWORK_BYTE_ORDER);
603 address_type = tvb_get_ntohs(parameter_tvb, offset);
604 switch (address_type) {
605 case IPv4_ADDRESS_TYPE:
606 proto_item_append_text(parameter_item, "IPv4");
608 case IPv6_ADDRESS_TYPE:
609 proto_item_append_text(parameter_item, "IPv6");
611 case HOSTNAME_ADDRESS_TYPE:
612 proto_item_append_text(parameter_item, "hostname");
615 proto_item_append_text(parameter_item, "%u", address_type);
617 if (address_type_number < number_of_address_types)
618 proto_item_append_text(parameter_item, ", ");
619 offset += SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH;
621 proto_item_append_text(parameter_item, ")");
625 dissect_ecn_parameter(tvbuff_t *parameter_tvb _U_)
630 dissect_forward_tsn_supported_parameter(tvbuff_t *parameter_tvb _U_)
634 #define CORRELATION_ID_LENGTH 4
635 #define CORRELATION_ID_OFFSET PARAMETER_VALUE_OFFSET
636 #define ADDRESS_PARAMETER_OFFSET (CORRELATION_ID_OFFSET + CORRELATION_ID_LENGTH)
639 dissect_add_ip_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
641 guint16 address_length;
642 tvbuff_t *address_tvb;
644 address_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
646 proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
647 address_tvb = tvb_new_subset(parameter_tvb, ADDRESS_PARAMETER_OFFSET, address_length, address_length);
648 proto_item_append_text(parameter_item, " (Address: ");
649 dissect_parameter(address_tvb, pinfo, parameter_tree, parameter_item, FALSE);
650 proto_item_append_text(parameter_item, ", correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
654 dissect_del_ip_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
656 guint16 address_length;
657 tvbuff_t *address_tvb;
659 address_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
661 proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
662 address_tvb = tvb_new_subset(parameter_tvb, ADDRESS_PARAMETER_OFFSET, address_length, address_length);
663 proto_item_append_text(parameter_item, " (Address: ");
664 dissect_parameter(address_tvb, pinfo, parameter_tree, parameter_item, FALSE);
665 proto_item_append_text(parameter_item, ", correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
668 #define ERROR_CAUSE_IND_CASUES_OFFSET (CORRELATION_ID_OFFSET + CORRELATION_ID_LENGTH)
671 dissect_error_cause_indication_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
673 guint16 causes_length;
674 tvbuff_t *causes_tvb;
676 proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
677 causes_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
678 causes_tvb = tvb_new_subset(parameter_tvb, ERROR_CAUSE_IND_CASUES_OFFSET, causes_length, causes_length);
679 dissect_error_causes(causes_tvb, pinfo, parameter_tree);
683 dissect_set_primary_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
685 guint16 address_length;
686 tvbuff_t *address_tvb;
688 address_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
690 proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
691 address_tvb = tvb_new_subset(parameter_tvb, ADDRESS_PARAMETER_OFFSET, address_length, address_length);
692 proto_item_append_text(parameter_item, " (Address: ");
693 dissect_parameter(address_tvb, pinfo, parameter_tree, parameter_item, FALSE);
694 proto_item_append_text(parameter_item, ", correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
698 dissect_success_report_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
700 proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
701 proto_item_append_text(parameter_item, " (Correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
704 #define ADAP_INDICATION_LENGTH 4
705 #define ADAP_INDICATION_OFFSET PARAMETER_VALUE_OFFSET
708 dissect_adap_indication_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
710 proto_tree_add_item(parameter_tree, hf_adap_indication, parameter_tvb, ADAP_INDICATION_OFFSET, ADAP_INDICATION_LENGTH, NETWORK_BYTE_ORDER);
711 proto_item_append_text(parameter_item, " (Indication: %u)", tvb_get_ntohl(parameter_tvb, ADAP_INDICATION_OFFSET));
715 dissect_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
717 guint16 type, parameter_value_length;
719 type = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
720 parameter_value_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
722 if (parameter_value_length > 0)
723 proto_tree_add_item(parameter_tree, hf_parameter_value, parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length, NETWORK_BYTE_ORDER);
725 proto_item_append_text(parameter_item, " (Type %u, value length: %u byte%s)", type, parameter_value_length, plurality(parameter_value_length, "", "s"));
728 #define HEARTBEAT_INFO_PARAMETER_ID 0x0001
729 #define IPV4ADDRESS_PARAMETER_ID 0x0005
730 #define IPV6ADDRESS_PARAMETER_ID 0x0006
731 #define STATE_COOKIE_PARAMETER_ID 0x0007
732 #define UNREC_PARA_PARAMETER_ID 0x0008
733 #define COOKIE_PRESERVATIVE_PARAMETER_ID 0x0009
734 #define HOSTNAME_ADDRESS_PARAMETER_ID 0x000b
735 #define SUPPORTED_ADDRESS_TYPES_PARAMETER_ID 0x000c
736 #define ECN_PARAMETER_ID 0x8000
737 #define FORWARD_TSN_SUPPORTED_PARAMETER_ID 0xC000
738 #define ADD_IP_ADDRESS_PARAMETER_ID 0xC001
739 #define DEL_IP_ADDRESS_PARAMETER_ID 0xC002
740 #define ERROR_CAUSE_INDICATION_PARAMETER_ID 0xC003
741 #define SET_PRIMARY_ADDRESS_PARAMETER_ID 0xC004
742 #define SUCCESS_REPORT_PARAMETER_ID 0xC005
743 #define ADAP_LAYER_INDICATION_PARAMETER_ID 0xC006
745 static const value_string parameter_identifier_values[] = {
746 { HEARTBEAT_INFO_PARAMETER_ID, "Heartbeat info" },
747 { IPV4ADDRESS_PARAMETER_ID, "IPv4 address" },
748 { IPV6ADDRESS_PARAMETER_ID, "IPv6 address" },
749 { STATE_COOKIE_PARAMETER_ID, "State cookie" },
750 { UNREC_PARA_PARAMETER_ID, "Unrecognized parameter" },
751 { COOKIE_PRESERVATIVE_PARAMETER_ID, "Cookie preservative" },
752 { HOSTNAME_ADDRESS_PARAMETER_ID, "Hostname address" },
753 { SUPPORTED_ADDRESS_TYPES_PARAMETER_ID, "Supported address types" },
754 { ECN_PARAMETER_ID, "ECN" },
755 { FORWARD_TSN_SUPPORTED_PARAMETER_ID, "Forward TSN supported" },
756 { ADD_IP_ADDRESS_PARAMETER_ID, "Add IP address" },
757 { DEL_IP_ADDRESS_PARAMETER_ID, "Delete IP address" },
758 { ERROR_CAUSE_INDICATION_PARAMETER_ID, "Error cause indication" },
759 { SET_PRIMARY_ADDRESS_PARAMETER_ID, "Set primary address" },
760 { SUCCESS_REPORT_PARAMETER_ID, "Success report" },
761 { ADAP_LAYER_INDICATION_PARAMETER_ID, "Adaptation Layer Indication" },
764 #define SCTP_PARAMETER_BIT_1 0x8000
765 #define SCTP_PARAMETER_BIT_2 0x4000
767 static const true_false_string sctp_parameter_bit_1_value = {
768 "Skip parameter and continue processing of the chunk",
769 "Stop processing of chunk"
772 static const true_false_string sctp_parameter_bit_2_value = {
778 dissect_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *additional_item, gboolean dissecting_init_init_ack_chunk)
780 guint16 type, length, padding_length;
781 proto_item *parameter_item;
782 proto_tree *parameter_tree;
783 proto_item *type_item;
784 proto_tree *type_tree;
786 type = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
787 length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
788 padding_length = tvb_length(parameter_tvb) - length;
790 parameter_item = proto_tree_add_text(chunk_tree, parameter_tvb, PARAMETER_HEADER_OFFSET, tvb_length(parameter_tvb), "%s parameter", val_to_str(type, parameter_identifier_values, "Unknown"));
791 parameter_tree = proto_item_add_subtree(parameter_item, ett_sctp_chunk_parameter);
793 type_item = proto_tree_add_item(parameter_tree, hf_parameter_type, parameter_tvb, PARAMETER_TYPE_OFFSET, PARAMETER_TYPE_LENGTH, NETWORK_BYTE_ORDER);
794 type_tree = proto_item_add_subtree(type_item, ett_sctp_parameter_type);
795 proto_tree_add_item(type_tree, hf_parameter_bit_1, parameter_tvb, PARAMETER_TYPE_OFFSET, PARAMETER_TYPE_LENGTH, NETWORK_BYTE_ORDER);
796 proto_tree_add_item(type_tree, hf_parameter_bit_2, parameter_tvb, PARAMETER_TYPE_OFFSET, PARAMETER_TYPE_LENGTH, NETWORK_BYTE_ORDER);
797 proto_tree_add_item(parameter_tree, hf_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
800 case HEARTBEAT_INFO_PARAMETER_ID:
801 dissect_heartbeat_info_parameter(parameter_tvb, parameter_tree, parameter_item);
803 case IPV4ADDRESS_PARAMETER_ID:
804 dissect_ipv4_parameter(parameter_tvb, parameter_tree, parameter_item, additional_item, dissecting_init_init_ack_chunk);
806 case IPV6ADDRESS_PARAMETER_ID:
807 dissect_ipv6_parameter(parameter_tvb, parameter_tree, parameter_item, additional_item, dissecting_init_init_ack_chunk);
809 case STATE_COOKIE_PARAMETER_ID:
810 dissect_state_cookie_parameter(parameter_tvb, parameter_tree, parameter_item);
812 case UNREC_PARA_PARAMETER_ID:
813 dissect_unrecognized_parameters_parameter(parameter_tvb, pinfo, parameter_tree);
815 case COOKIE_PRESERVATIVE_PARAMETER_ID:
816 dissect_cookie_preservative_parameter(parameter_tvb, parameter_tree, parameter_item);
818 case HOSTNAME_ADDRESS_PARAMETER_ID:
819 dissect_hostname_parameter(parameter_tvb, parameter_tree, parameter_item);
821 case SUPPORTED_ADDRESS_TYPES_PARAMETER_ID:
822 dissect_supported_address_types_parameter(parameter_tvb, parameter_tree, parameter_item);
824 case ECN_PARAMETER_ID:
825 dissect_ecn_parameter(parameter_tvb);
827 case FORWARD_TSN_SUPPORTED_PARAMETER_ID:
828 dissect_forward_tsn_supported_parameter(parameter_tvb);
830 case ADD_IP_ADDRESS_PARAMETER_ID:
831 dissect_add_ip_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
833 case DEL_IP_ADDRESS_PARAMETER_ID:
834 dissect_del_ip_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
836 case ERROR_CAUSE_INDICATION_PARAMETER_ID:
837 dissect_error_cause_indication_parameter(parameter_tvb, pinfo, parameter_tree);
839 case SET_PRIMARY_ADDRESS_PARAMETER_ID:
840 dissect_set_primary_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
842 case SUCCESS_REPORT_PARAMETER_ID:
843 dissect_success_report_parameter(parameter_tvb, parameter_tree, parameter_item);
845 case ADAP_LAYER_INDICATION_PARAMETER_ID:
846 dissect_adap_indication_parameter(parameter_tvb, parameter_tree, parameter_item);
849 dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
853 if (padding_length > 0)
854 proto_tree_add_item(parameter_tree, hf_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
858 dissect_parameters(tvbuff_t *parameters_tvb, packet_info *pinfo, proto_tree *tree, proto_item *additional_item, gboolean dissecting_init_init_ack_chunk)
860 gint offset, length, total_length, remaining_length;
861 tvbuff_t *parameter_tvb;
864 while((remaining_length = tvb_length_remaining(parameters_tvb, offset))) {
865 if ((offset > 0) && additional_item)
866 proto_item_append_text(additional_item, " ");
867 length = tvb_get_ntohs(parameters_tvb, offset + PARAMETER_LENGTH_OFFSET);
868 total_length = ADD_PADDING(length);
869 if (remaining_length >= length)
870 total_length = MIN(total_length, remaining_length);
871 /* create a tvb for the parameter including the padding bytes */
872 parameter_tvb = tvb_new_subset(parameters_tvb, offset, total_length, total_length);
873 dissect_parameter(parameter_tvb, pinfo, tree, additional_item, dissecting_init_init_ack_chunk);
874 /* get rid of the handled parameter */
875 offset += total_length;
881 * Code to handle error causes for ABORT and ERROR chunks
885 #define CAUSE_CODE_LENGTH 2
886 #define CAUSE_LENGTH_LENGTH 2
887 #define CAUSE_HEADER_LENGTH (CAUSE_CODE_LENGTH + CAUSE_LENGTH_LENGTH)
889 #define CAUSE_HEADER_OFFSET 0
890 #define CAUSE_CODE_OFFSET CAUSE_HEADER_OFFSET
891 #define CAUSE_LENGTH_OFFSET (CAUSE_CODE_OFFSET + CAUSE_CODE_LENGTH)
892 #define CAUSE_INFO_OFFSET (CAUSE_LENGTH_OFFSET + CAUSE_LENGTH_LENGTH)
895 #define CAUSE_STREAM_IDENTIFIER_LENGTH 2
896 #define CAUSE_RESERVED_LENGTH 2
897 #define CAUSE_STREAM_IDENTIFIER_OFFSET CAUSE_INFO_OFFSET
898 #define CAUSE_RESERVED_OFFSET (CAUSE_STREAM_IDENTIFIER_OFFSET + CAUSE_STREAM_IDENTIFIER_LENGTH)
901 dissect_invalid_stream_identifier_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
903 proto_tree_add_item(cause_tree, hf_cause_stream_identifier, cause_tvb, CAUSE_STREAM_IDENTIFIER_OFFSET, CAUSE_STREAM_IDENTIFIER_LENGTH, NETWORK_BYTE_ORDER);
904 proto_tree_add_item(cause_tree, hf_cause_reserved, cause_tvb, CAUSE_RESERVED_OFFSET, CAUSE_RESERVED_LENGTH, NETWORK_BYTE_ORDER);
905 proto_item_append_text(cause_item, " (SID: %u)", tvb_get_ntohs(cause_tvb, CAUSE_STREAM_IDENTIFIER_OFFSET));
908 #define CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH 4
909 #define CAUSE_MISSING_PARAMETER_TYPE_LENGTH 2
911 #define CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET CAUSE_INFO_OFFSET
912 #define CAUSE_FIRST_MISSING_PARAMETER_TYPE_OFFSET (CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET + \
913 CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH )
916 dissect_missing_mandatory_parameters_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree)
918 guint32 number_of_missing_parameters, missing_parameter_number;
921 number_of_missing_parameters = tvb_get_ntohl(cause_tvb, CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET);
922 proto_tree_add_item(cause_tree, hf_cause_number_of_missing_parameters, cause_tvb, CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET, CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH, NETWORK_BYTE_ORDER);
923 offset = CAUSE_FIRST_MISSING_PARAMETER_TYPE_OFFSET;
924 for(missing_parameter_number = 1; missing_parameter_number <= number_of_missing_parameters; missing_parameter_number++) {
925 proto_tree_add_item(cause_tree, hf_cause_missing_parameter_type, cause_tvb, offset, CAUSE_MISSING_PARAMETER_TYPE_LENGTH, NETWORK_BYTE_ORDER);
926 offset += CAUSE_MISSING_PARAMETER_TYPE_LENGTH;
930 #define CAUSE_MEASURE_OF_STALENESS_LENGTH 4
931 #define CAUSE_MEASURE_OF_STALENESS_OFFSET CAUSE_INFO_OFFSET
934 dissect_stale_cookie_error_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
936 proto_tree_add_item(cause_tree, hf_cause_measure_of_staleness, cause_tvb, CAUSE_MEASURE_OF_STALENESS_OFFSET, CAUSE_MEASURE_OF_STALENESS_LENGTH, NETWORK_BYTE_ORDER);
937 proto_item_append_text(cause_item, " (Measure: %u usec)", tvb_get_ntohl(cause_tvb, CAUSE_MEASURE_OF_STALENESS_OFFSET));
941 dissect_out_of_resource_cause(tvbuff_t *cause_tvb _U_)
946 dissect_unresolvable_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
948 guint16 parameter_length;
949 tvbuff_t *parameter_tvb;
951 parameter_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
952 parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, parameter_length, parameter_length);
953 proto_item_append_text(cause_item, " (Address: ");
954 dissect_parameter(parameter_tvb, pinfo, cause_tree, cause_item, FALSE);
955 proto_item_append_text(cause_item, ")");
959 dissect_unrecognized_chunk_type_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
961 guint16 chunk_length;
962 guint8 unrecognized_type;
963 tvbuff_t *unrecognized_chunk_tvb;
965 chunk_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
966 unrecognized_chunk_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, chunk_length, chunk_length);
967 dissect_sctp_chunk(unrecognized_chunk_tvb, pinfo, cause_tree,cause_tree, FALSE);
968 unrecognized_type = tvb_get_guint8(unrecognized_chunk_tvb, CHUNK_TYPE_OFFSET);
969 proto_item_append_text(cause_item, " (Type: %u (%s))", unrecognized_type, val_to_str(unrecognized_type, chunk_type_values, "unknown"));
973 dissect_invalid_mandatory_parameter_cause(tvbuff_t *cause_tvb _U_)
978 dissect_unrecognized_parameters_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree)
980 guint16 cause_info_length;
981 tvbuff_t *unrecognized_parameters_tvb;
983 cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
985 unrecognized_parameters_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
986 dissect_parameters(unrecognized_parameters_tvb, pinfo, cause_tree, NULL, FALSE);
989 #define CAUSE_TSN_LENGTH 4
990 #define CAUSE_TSN_OFFSET CAUSE_INFO_OFFSET
993 dissect_no_user_data_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
995 proto_tree_add_item(cause_tree, hf_cause_tsn, cause_tvb, CAUSE_TSN_OFFSET, CAUSE_TSN_LENGTH, NETWORK_BYTE_ORDER);
996 proto_item_append_text(cause_item, " (TSN: %u)", tvb_get_ntohl(cause_tvb, CAUSE_TSN_OFFSET));
1000 dissect_cookie_received_while_shutting_down_cause(tvbuff_t *cause_tvb _U_)
1005 dissect_restart_with_new_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree* cause_tree, proto_item *cause_item)
1007 guint16 cause_info_length;
1008 tvbuff_t *parameter_tvb;
1010 cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1011 parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1012 proto_item_append_text(cause_item, " (New addresses: ");
1013 dissect_parameters(parameter_tvb, pinfo, cause_tree, cause_item, FALSE);
1014 proto_item_append_text(cause_item, ")");
1018 dissect_user_initiated_abort_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree)
1020 guint16 cause_info_length;
1022 cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1023 if (cause_info_length > 0)
1024 proto_tree_add_item(cause_tree, hf_cause_info, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, NETWORK_BYTE_ORDER);
1028 dissect_protocol_violation_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree)
1030 guint16 cause_info_length;
1032 cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1033 if (cause_info_length > 0)
1034 proto_tree_add_item(cause_tree, hf_cause_info, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, NETWORK_BYTE_ORDER);
1038 dissect_delete_last_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
1040 guint16 cause_info_length;
1041 tvbuff_t *parameter_tvb;
1043 cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1044 parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1045 proto_item_append_text(cause_item, " (Last address: ");
1046 dissect_parameter(parameter_tvb, pinfo, cause_tree, cause_item, FALSE);
1047 proto_item_append_text(cause_item, ")");
1051 dissect_resource_outage_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree)
1053 guint16 cause_info_length;
1054 tvbuff_t *parameter_tvb;
1056 cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1057 parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1058 dissect_parameter(parameter_tvb, pinfo, cause_tree, NULL, FALSE);
1062 dissect_delete_source_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
1064 guint16 cause_info_length;
1065 tvbuff_t *parameter_tvb;
1067 cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1068 parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1069 proto_item_append_text(cause_item, " (Deleted address: ");
1070 dissect_parameter(parameter_tvb, pinfo, cause_tree, cause_item, FALSE);
1071 proto_item_append_text(cause_item, ")");
1075 dissect_request_refused_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree)
1077 guint16 cause_info_length;
1078 tvbuff_t *parameter_tvb;
1080 cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1081 parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1082 dissect_parameter(parameter_tvb, pinfo, cause_tree, NULL, FALSE);
1086 dissect_unknown_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
1088 guint16 cause_info_length;
1090 cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1091 if (cause_info_length > 0)
1092 proto_tree_add_item(cause_tree, hf_cause_info, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, NETWORK_BYTE_ORDER);
1093 proto_item_append_text(cause_item, "Code: %u, information length: %u byte%s)", tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET), cause_info_length, plurality(cause_info_length, "", "s"));
1096 #define INVALID_STREAM_IDENTIFIER 0x01
1097 #define MISSING_MANDATORY_PARAMETERS 0x02
1098 #define STALE_COOKIE_ERROR 0x03
1099 #define OUT_OF_RESOURCE 0x04
1100 #define UNRESOLVABLE_ADDRESS 0x05
1101 #define UNRECOGNIZED_CHUNK_TYPE 0x06
1102 #define INVALID_MANDATORY_PARAMETER 0x07
1103 #define UNRECOGNIZED_PARAMETERS 0x08
1104 #define NO_USER_DATA 0x09
1105 #define COOKIE_RECEIVED_WHILE_SHUTTING_DOWN 0x0a
1106 #define RESTART_WITH_NEW_ADDRESSES 0x0b
1107 #define USER_INITIATED_ABORT 0x0c
1108 #define PROTOCOL_VIOLATION 0x0d
1109 #define REQUEST_TO_DELETE_LAST_ADDRESS 0x0100
1110 #define OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE 0X0101
1111 #define REQUEST_TO_DELETE_SOURCE_ADDRESS 0x0102
1112 #define ABORT_DUE_TO_ILLEGAL_ASCONF 0x0103
1113 #define REQUESTION_REFUSED 0x0104
1115 static const value_string cause_code_values[] = {
1116 { INVALID_STREAM_IDENTIFIER, "Invalid stream identifier" },
1117 { MISSING_MANDATORY_PARAMETERS, "Missing mandatory parameter" },
1118 { STALE_COOKIE_ERROR, "Stale cookie error" },
1119 { OUT_OF_RESOURCE, "Out of resource" },
1120 { UNRESOLVABLE_ADDRESS, "Unresolvable address" },
1121 { UNRECOGNIZED_CHUNK_TYPE, "Unrecognized chunk type" },
1122 { INVALID_MANDATORY_PARAMETER, "Invalid mandatory parameter" },
1123 { UNRECOGNIZED_PARAMETERS, "Unrecognized parameters" },
1124 { NO_USER_DATA, "No user data" },
1125 { COOKIE_RECEIVED_WHILE_SHUTTING_DOWN, "Cookie received while shutting down" },
1126 { RESTART_WITH_NEW_ADDRESSES, "Restart of an association with new addresses" },
1127 { USER_INITIATED_ABORT, "User initiated ABORT" },
1128 { PROTOCOL_VIOLATION, "Protocol violation" },
1129 { REQUEST_TO_DELETE_LAST_ADDRESS, "Request to delete last address" },
1130 { OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE, "Operation refused due to resource shortage" },
1131 { REQUEST_TO_DELETE_SOURCE_ADDRESS, "Request to delete source address" },
1132 { ABORT_DUE_TO_ILLEGAL_ASCONF, "Association Aborted due to illegal ASCONF-ACK" },
1133 { REQUESTION_REFUSED, "Request refused - no authorization" },
1138 dissect_error_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *chunk_tree)
1140 guint16 code, length, padding_length;
1141 proto_item *cause_item;
1142 proto_tree *cause_tree;
1144 code = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET);
1145 length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
1146 padding_length = tvb_length(cause_tvb) - length;
1148 cause_item = proto_tree_add_text(chunk_tree, cause_tvb, CAUSE_HEADER_OFFSET, tvb_length(cause_tvb), "%s cause", val_to_str(code, cause_code_values, "Unknown"));
1149 cause_tree = proto_item_add_subtree(cause_item, ett_sctp_chunk_cause);
1151 proto_tree_add_item(cause_tree, hf_cause_code, cause_tvb, CAUSE_CODE_OFFSET, CAUSE_CODE_LENGTH, NETWORK_BYTE_ORDER);
1152 proto_tree_add_item(cause_tree, hf_cause_length, cause_tvb, CAUSE_LENGTH_OFFSET, CAUSE_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
1155 case INVALID_STREAM_IDENTIFIER:
1156 dissect_invalid_stream_identifier_cause(cause_tvb, cause_tree, cause_item);
1158 case MISSING_MANDATORY_PARAMETERS:
1159 dissect_missing_mandatory_parameters_cause(cause_tvb, cause_tree);
1161 case STALE_COOKIE_ERROR:
1162 dissect_stale_cookie_error_cause(cause_tvb, cause_tree, cause_item);
1164 case OUT_OF_RESOURCE:
1165 dissect_out_of_resource_cause(cause_tvb);
1167 case UNRESOLVABLE_ADDRESS:
1168 dissect_unresolvable_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
1170 case UNRECOGNIZED_CHUNK_TYPE:
1171 dissect_unrecognized_chunk_type_cause(cause_tvb, pinfo, cause_tree, cause_item);
1173 case INVALID_MANDATORY_PARAMETER:
1174 dissect_invalid_mandatory_parameter_cause(cause_tvb);
1176 case UNRECOGNIZED_PARAMETERS:
1177 dissect_unrecognized_parameters_cause(cause_tvb, pinfo, cause_tree);
1180 dissect_no_user_data_cause(cause_tvb, cause_tree, cause_item);
1182 case COOKIE_RECEIVED_WHILE_SHUTTING_DOWN:
1183 dissect_cookie_received_while_shutting_down_cause(cause_tvb);
1185 case RESTART_WITH_NEW_ADDRESSES:
1186 dissect_restart_with_new_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
1188 case USER_INITIATED_ABORT:
1189 dissect_user_initiated_abort_cause(cause_tvb, cause_tree);
1191 case PROTOCOL_VIOLATION:
1192 dissect_protocol_violation_cause(cause_tvb, cause_tree);
1194 case REQUEST_TO_DELETE_LAST_ADDRESS:
1195 dissect_delete_last_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
1197 case OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE:
1198 dissect_resource_outage_cause(cause_tvb, pinfo, cause_tree);
1200 case REQUEST_TO_DELETE_SOURCE_ADDRESS:
1201 dissect_delete_source_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
1203 case REQUESTION_REFUSED:
1204 dissect_request_refused_cause(cause_tvb, pinfo, cause_tree);
1207 dissect_unknown_cause(cause_tvb, cause_tree, cause_item);
1211 if (padding_length > 0)
1212 proto_tree_add_item(cause_tree, hf_cause_padding, cause_tvb, CAUSE_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
1216 dissect_error_causes(tvbuff_t *causes_tvb, packet_info *pinfo, proto_tree *tree)
1218 gint offset, length, total_length, remaining_length;
1219 tvbuff_t *cause_tvb;
1222 while((remaining_length = tvb_length_remaining(causes_tvb, offset))) {
1223 length = tvb_get_ntohs(causes_tvb, offset + CAUSE_LENGTH_OFFSET);
1224 total_length = ADD_PADDING(length);
1225 if (remaining_length >= length)
1226 total_length = MIN(total_length, remaining_length);
1227 /* create a tvb for the parameter including the padding bytes */
1228 cause_tvb = tvb_new_subset(causes_tvb, offset, total_length, total_length);
1229 dissect_error_cause(cause_tvb, pinfo, tree);
1230 /* get rid of the handled cause */
1231 offset += total_length;
1237 * Code to actually dissect the packets
1240 static gboolean try_heuristic_first = FALSE;
1243 dissect_payload(tvbuff_t *payload_tvb, packet_info *pinfo, proto_tree *tree, guint32 ppi)
1245 guint32 low_port, high_port;
1247 if (try_heuristic_first) {
1248 /* do lookup with the heuristic subdissector table */
1249 if (dissector_try_heuristic(sctp_heur_subdissector_list, payload_tvb, pinfo, tree))
1253 /* Do lookups with the subdissector table.
1255 When trying port numbers, we try the port number with the lower value
1256 first, followed by the port number with the higher value. This means
1257 that, for packets where a dissector is registered for *both* port
1258 numbers, and where there's no match on the PPI:
1260 1) we pick the same dissector for traffic going in both directions;
1262 2) we prefer the port number that's more likely to be the right
1263 one (as that prefers well-known ports to reserved ports);
1265 although there is, of course, no guarantee that any such strategy
1266 will always pick the right port number.
1268 XXX - we ignore port numbers of 0, as some dissectors use a port
1269 number of 0 to disable the port. */
1270 if (dissector_try_port(sctp_ppi_dissector_table, ppi, payload_tvb, pinfo, tree))
1272 if (pinfo->srcport > pinfo->destport) {
1273 low_port = pinfo->destport;
1274 high_port = pinfo->srcport;
1276 low_port = pinfo->srcport;
1277 high_port = pinfo->destport;
1279 if (low_port != 0 &&
1280 dissector_try_port(sctp_port_dissector_table, low_port, payload_tvb, pinfo, tree))
1282 if (high_port != 0 &&
1283 dissector_try_port(sctp_port_dissector_table, high_port, payload_tvb, pinfo, tree))
1286 if (!try_heuristic_first) {
1287 /* do lookup with the heuristic subdissector table */
1288 if (dissector_try_heuristic(sctp_heur_subdissector_list, payload_tvb, pinfo, tree))
1292 /* Oh, well, we don't know this; dissect it as data. */
1293 call_dissector(data_handle, payload_tvb, pinfo, tree);
1297 #define DATA_CHUNK_TSN_LENGTH 4
1298 #define DATA_CHUNK_STREAM_ID_LENGTH 2
1299 #define DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH 2
1300 #define DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH 4
1302 #define DATA_CHUNK_TSN_OFFSET (CHUNK_VALUE_OFFSET + 0)
1303 #define DATA_CHUNK_STREAM_ID_OFFSET (DATA_CHUNK_TSN_OFFSET + DATA_CHUNK_TSN_LENGTH)
1304 #define DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET (DATA_CHUNK_STREAM_ID_OFFSET + \
1305 DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH)
1306 #define DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET (DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET + \
1307 DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH)
1308 #define DATA_CHUNK_PAYLOAD_OFFSET (DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET + \
1309 DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH)
1311 #define DATA_CHUNK_HEADER_LENGTH (CHUNK_HEADER_LENGTH + \
1312 DATA_CHUNK_TSN_LENGTH + \
1313 DATA_CHUNK_STREAM_ID_LENGTH + \
1314 DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH + \
1315 DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH)
1317 #define SCTP_DATA_CHUNK_E_BIT 0x01
1318 #define SCTP_DATA_CHUNK_B_BIT 0x02
1319 #define SCTP_DATA_CHUNK_U_BIT 0x04
1321 static const true_false_string sctp_data_chunk_e_bit_value = {
1323 "Not the last segment"
1326 static const true_false_string sctp_data_chunk_b_bit_value = {
1328 "Subsequent segment"
1331 static const true_false_string sctp_data_chunk_u_bit_value = {
1332 "Unordered delivery",
1337 dissect_data_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1339 guint16 payload_length;
1340 guint32 payload_proto_id;
1341 tvbuff_t *payload_tvb;
1342 proto_tree *flags_tree;
1343 guint8 e_bit, b_bit, u_bit;
1345 payload_proto_id = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET);
1348 proto_item_set_len(chunk_item, DATA_CHUNK_HEADER_LENGTH);
1349 flags_tree = proto_item_add_subtree(flags_item, ett_sctp_data_chunk_flags);
1350 proto_tree_add_item(flags_tree, hf_data_chunk_e_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
1351 proto_tree_add_item(flags_tree, hf_data_chunk_b_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
1352 proto_tree_add_item(flags_tree, hf_data_chunk_u_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
1353 proto_tree_add_item(chunk_tree, hf_data_chunk_tsn, chunk_tvb, DATA_CHUNK_TSN_OFFSET, DATA_CHUNK_TSN_LENGTH, NETWORK_BYTE_ORDER);
1354 proto_tree_add_item(chunk_tree, hf_data_chunk_stream_id, chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET, DATA_CHUNK_STREAM_ID_LENGTH, NETWORK_BYTE_ORDER);
1355 proto_tree_add_item(chunk_tree, hf_data_chunk_stream_seq_number, chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET, DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH, NETWORK_BYTE_ORDER);
1356 proto_tree_add_item(chunk_tree, hf_data_chunk_payload_proto_id, chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH, NETWORK_BYTE_ORDER);
1358 e_bit = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_DATA_CHUNK_E_BIT;
1359 b_bit = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_DATA_CHUNK_B_BIT;
1360 u_bit = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_DATA_CHUNK_U_BIT;
1362 proto_item_append_text(chunk_item, "(%s, ", (u_bit) ? "unordered" : "ordered");
1365 proto_item_append_text(chunk_item, "complete");
1367 proto_item_append_text(chunk_item, "first");
1370 proto_item_append_text(chunk_item, "last");
1372 proto_item_append_text(chunk_item, "middle");
1375 proto_item_append_text(chunk_item, " segment, TSN: %u, SID: %u, SSN: %u, PPID: %u",
1376 tvb_get_ntohl(chunk_tvb, DATA_CHUNK_TSN_OFFSET),
1377 tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET),
1378 tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET),
1381 payload_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1382 if (payload_length < DATA_CHUNK_HEADER_LENGTH) {
1384 proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
1385 payload_length, DATA_CHUNK_HEADER_LENGTH);
1389 payload_length -= DATA_CHUNK_HEADER_LENGTH;
1391 proto_item_append_text(chunk_item, ", payload length: %u byte%s)",
1392 payload_length, plurality(payload_length, "", "s"));
1394 payload_tvb = tvb_new_subset(chunk_tvb, DATA_CHUNK_PAYLOAD_OFFSET, payload_length, payload_length);
1395 return dissect_payload(payload_tvb, pinfo, tree, payload_proto_id);
1398 #define INIT_CHUNK_INITIATE_TAG_LENGTH 4
1399 #define INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH 4
1400 #define INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH 2
1401 #define INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH 2
1402 #define INIT_CHUNK_INITIAL_TSN_LENGTH 4
1403 #define INIT_CHUNK_FIXED_PARAMTERS_LENGTH (INIT_CHUNK_INITIATE_TAG_LENGTH + \
1404 INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH + \
1405 INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH + \
1406 INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH + \
1407 INIT_CHUNK_INITIAL_TSN_LENGTH)
1409 #define INIT_CHUNK_INITIATE_TAG_OFFSET CHUNK_VALUE_OFFSET
1410 #define INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET (INIT_CHUNK_INITIATE_TAG_OFFSET + \
1411 INIT_CHUNK_INITIATE_TAG_LENGTH )
1412 #define INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET (INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET + \
1413 INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH )
1414 #define INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET (INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET + \
1415 INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH )
1416 #define INIT_CHUNK_INITIAL_TSN_OFFSET (INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET + \
1417 INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH )
1418 #define INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET (INIT_CHUNK_INITIAL_TSN_OFFSET + \
1419 INIT_CHUNK_INITIAL_TSN_LENGTH )
1422 dissect_init_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
1424 gint parameters_length;
1425 tvbuff_t *parameters_tvb;
1428 /* handle fixed parameters */
1429 proto_tree_add_item(chunk_tree, hf_init_chunk_initiate_tag, chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET, INIT_CHUNK_INITIATE_TAG_LENGTH, NETWORK_BYTE_ORDER);
1430 proto_tree_add_item_hidden(chunk_tree, hf_initiate_tag, chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET, INIT_CHUNK_INITIATE_TAG_LENGTH, NETWORK_BYTE_ORDER);
1431 proto_tree_add_item(chunk_tree, hf_init_chunk_adv_rec_window_credit, chunk_tvb, INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET, INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH, NETWORK_BYTE_ORDER);
1432 proto_tree_add_item(chunk_tree, hf_init_chunk_number_of_outbound_streams, chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH, NETWORK_BYTE_ORDER);
1433 proto_tree_add_item(chunk_tree, hf_init_chunk_number_of_inbound_streams, chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH, NETWORK_BYTE_ORDER);
1434 proto_tree_add_item(chunk_tree, hf_init_chunk_initial_tsn, chunk_tvb, INIT_CHUNK_INITIAL_TSN_OFFSET, INIT_CHUNK_INITIAL_TSN_LENGTH, NETWORK_BYTE_ORDER);
1436 /* handle variable paramters */
1437 parameters_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - INIT_CHUNK_FIXED_PARAMTERS_LENGTH - CHUNK_HEADER_LENGTH;
1438 parameters_tvb = tvb_new_subset(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET, parameters_length, parameters_length);
1439 dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, TRUE);
1441 proto_item_append_text(chunk_item, " (Outbound streams: %u, inbound streams: %u)",
1442 tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET),
1443 tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET));
1448 dissect_init_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
1450 gint parameters_length;
1451 tvbuff_t *parameters_tvb;
1454 /* handle fixed parameters */
1455 proto_tree_add_item(chunk_tree, hf_initack_chunk_initiate_tag, chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET, INIT_CHUNK_INITIATE_TAG_LENGTH, NETWORK_BYTE_ORDER);
1456 proto_tree_add_item_hidden(chunk_tree, hf_initiate_tag, chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET, INIT_CHUNK_INITIATE_TAG_LENGTH, NETWORK_BYTE_ORDER);
1457 proto_tree_add_item(chunk_tree, hf_initack_chunk_adv_rec_window_credit, chunk_tvb, INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET, INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH, NETWORK_BYTE_ORDER);
1458 proto_tree_add_item(chunk_tree, hf_initack_chunk_number_of_outbound_streams, chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH, NETWORK_BYTE_ORDER);
1459 proto_tree_add_item(chunk_tree, hf_initack_chunk_number_of_inbound_streams, chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH, NETWORK_BYTE_ORDER);
1460 proto_tree_add_item(chunk_tree, hf_initack_chunk_initial_tsn, chunk_tvb, INIT_CHUNK_INITIAL_TSN_OFFSET, INIT_CHUNK_INITIAL_TSN_LENGTH, NETWORK_BYTE_ORDER);
1462 /* handle variable paramters */
1463 parameters_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - INIT_CHUNK_FIXED_PARAMTERS_LENGTH - CHUNK_HEADER_LENGTH;
1464 parameters_tvb = tvb_new_subset(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET, parameters_length, parameters_length);
1465 dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, TRUE);
1467 proto_item_append_text(chunk_item, " (Outbound streams: %u, inbound streams: %u)",
1468 tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET),
1469 tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET));
1473 #define SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH 4
1474 #define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH 4
1475 #define SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH 2
1476 #define SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH 2
1477 #define SACK_CHUNK_GAP_BLOCK_LENGTH 4
1478 #define SACK_CHUNK_GAP_BLOCK_START_LENGTH 2
1479 #define SACK_CHUNK_GAP_BLOCK_END_LENGTH 2
1480 #define SACK_CHUNK_DUP_TSN_LENGTH 4
1482 #define SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET (CHUNK_VALUE_OFFSET + 0)
1483 #define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET (SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET + \
1484 SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH)
1485 #define SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET (SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET + \
1486 SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH)
1487 #define SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET (SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET + \
1488 SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH)
1489 #define SACK_CHUNK_GAP_BLOCK_OFFSET (SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET + \
1490 SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH)
1494 dissect_sack_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
1496 guint16 number_of_gap_blocks, number_of_dup_tsns;
1497 guint16 gap_block_number, dup_tsn_number, start, end;
1498 gint gap_block_offset, dup_tsn_offset;
1499 guint32 cum_tsn_ack;
1500 proto_item *block_item;
1501 proto_tree *block_tree;
1504 proto_tree_add_item(chunk_tree, hf_sack_chunk_cumulative_tsn_ack, chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET, SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH, NETWORK_BYTE_ORDER);
1505 proto_tree_add_item(chunk_tree, hf_sack_chunk_adv_rec_window_credit, chunk_tvb, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH, NETWORK_BYTE_ORDER);
1506 proto_tree_add_item(chunk_tree, hf_sack_chunk_number_of_gap_blocks, chunk_tvb, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH, NETWORK_BYTE_ORDER);
1507 proto_tree_add_item(chunk_tree, hf_sack_chunk_number_of_dup_tsns, chunk_tvb, SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET, SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH, NETWORK_BYTE_ORDER);
1509 /* handle the gap acknowledgement blocks */
1510 number_of_gap_blocks = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET);
1511 gap_block_offset = SACK_CHUNK_GAP_BLOCK_OFFSET;
1512 cum_tsn_ack = tvb_get_ntohl(chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
1513 for(gap_block_number = 1; gap_block_number <= number_of_gap_blocks; gap_block_number++) {
1514 start = tvb_get_ntohs(chunk_tvb, gap_block_offset);
1515 end = tvb_get_ntohs(chunk_tvb, gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH);
1516 block_item = proto_tree_add_text(chunk_tree, chunk_tvb, gap_block_offset, SACK_CHUNK_GAP_BLOCK_LENGTH, "Gap Acknowledgement for TSN %u to %u", cum_tsn_ack + start, cum_tsn_ack + end);
1517 block_tree = proto_item_add_subtree(block_item, ett_sctp_sack_chunk_gap_block);
1518 proto_tree_add_item(block_tree, hf_sack_chunk_gap_block_start, chunk_tvb, gap_block_offset, SACK_CHUNK_GAP_BLOCK_START_LENGTH, NETWORK_BYTE_ORDER);
1519 proto_tree_add_item(block_tree, hf_sack_chunk_gap_block_end, chunk_tvb, gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH, SACK_CHUNK_GAP_BLOCK_END_LENGTH, NETWORK_BYTE_ORDER);
1520 gap_block_offset += SACK_CHUNK_GAP_BLOCK_LENGTH;
1523 /* handle the duplicate TSNs */
1524 number_of_dup_tsns = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET);
1525 dup_tsn_offset = SACK_CHUNK_GAP_BLOCK_OFFSET + number_of_gap_blocks * SACK_CHUNK_GAP_BLOCK_LENGTH;
1526 for(dup_tsn_number = 1; dup_tsn_number <= number_of_dup_tsns; dup_tsn_number++) {
1527 proto_tree_add_item(chunk_tree, hf_sack_chunk_duplicate_tsn, chunk_tvb, dup_tsn_offset, SACK_CHUNK_DUP_TSN_LENGTH, NETWORK_BYTE_ORDER);
1528 dup_tsn_offset += SACK_CHUNK_DUP_TSN_LENGTH;
1531 proto_item_append_text(chunk_item, " (Cumulative TSN: %u, a_rwnd: %u, gaps: %u, duplicate TSNs: %u)",
1532 tvb_get_ntohl(chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET),
1533 tvb_get_ntohl(chunk_tvb, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET),
1534 number_of_gap_blocks, number_of_dup_tsns);
1538 #define HEARTBEAT_CHUNK_INFO_OFFSET CHUNK_VALUE_OFFSET
1541 dissect_heartbeat_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
1543 tvbuff_t *parameter_tvb;
1547 info_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
1548 proto_item_append_text(chunk_item, " (Information: %u byte%s)", info_length, plurality(info_length, "", "s"));
1549 parameter_tvb = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, info_length, info_length);
1550 /* FIXME: Parameters or parameter? */
1551 dissect_parameter(parameter_tvb, pinfo, chunk_tree, NULL, FALSE);
1556 dissect_heartbeat_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
1558 tvbuff_t *parameter_tvb;
1562 info_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
1563 proto_item_append_text(chunk_item, " (Information: %u byte%s)", info_length, plurality(info_length, "", "s"));
1564 parameter_tvb = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, info_length, info_length);
1565 /* FIXME: Parameters or parameter? */
1566 dissect_parameter(parameter_tvb, pinfo, chunk_tree, NULL, FALSE);
1569 #define ABORT_CHUNK_FIRST_ERROR_CAUSE_OFFSET 4
1572 dissect_abort_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *flags_item)
1574 guint16 causes_length;
1575 tvbuff_t *causes_tvb;
1576 proto_tree *flags_tree;
1579 flags_tree = proto_item_add_subtree(flags_item, ett_sctp_abort_chunk_flags);
1580 proto_tree_add_item(flags_tree, hf_abort_chunk_t_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
1582 causes_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
1583 causes_tvb = tvb_new_subset(chunk_tvb, CHUNK_VALUE_OFFSET, causes_length, causes_length);
1584 dissect_error_causes(causes_tvb, pinfo, chunk_tree);
1588 #define SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET CHUNK_VALUE_OFFSET
1589 #define SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_LENGTH 4
1592 dissect_shutdown_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
1595 proto_tree_add_item(chunk_tree, hf_shutdown_chunk_cumulative_tsn_ack, chunk_tvb, SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET, SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_LENGTH, NETWORK_BYTE_ORDER);
1596 proto_item_append_text(chunk_item, " (Cumulative TSN ack: %u)", tvb_get_ntohl(chunk_tvb, SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET));
1601 dissect_shutdown_ack_chunk(tvbuff_t *chunk_tvb _U_)
1605 #define ERROR_CAUSE_IND_CAUSES_OFFSET CHUNK_VALUE_OFFSET
1608 dissect_error_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree)
1610 guint16 causes_length;
1611 tvbuff_t *causes_tvb;
1614 causes_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
1615 causes_tvb = tvb_new_subset(chunk_tvb, ERROR_CAUSE_IND_CAUSES_OFFSET, causes_length, causes_length);
1616 dissect_error_causes(causes_tvb, pinfo, chunk_tree);
1620 #define COOKIE_OFFSET CHUNK_VALUE_OFFSET
1623 dissect_cookie_echo_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
1625 guint cookie_length;
1628 cookie_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
1629 proto_tree_add_item(chunk_tree, hf_cookie, chunk_tvb, COOKIE_OFFSET, cookie_length, NETWORK_BYTE_ORDER);
1630 proto_item_append_text(chunk_item, " (Cookie length: %u byte%s)", cookie_length, plurality(cookie_length, "", "s"));
1635 dissect_cookie_ack_chunk(tvbuff_t *chunk_tvb _U_)
1639 #define ECNE_CHUNK_LOWEST_TSN_OFFSET CHUNK_VALUE_OFFSET
1640 #define ECNE_CHUNK_LOWEST_TSN_LENGTH 4
1643 dissect_ecne_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
1646 proto_tree_add_item(chunk_tree, hf_ecne_chunk_lowest_tsn, chunk_tvb, ECNE_CHUNK_LOWEST_TSN_OFFSET, ECNE_CHUNK_LOWEST_TSN_LENGTH, NETWORK_BYTE_ORDER);
1647 proto_item_append_text(chunk_item, " (Lowest TSN: %u)", tvb_get_ntohl(chunk_tvb, ECNE_CHUNK_LOWEST_TSN_OFFSET));
1650 #define CWR_CHUNK_LOWEST_TSN_OFFSET CHUNK_VALUE_OFFSET
1651 #define CWR_CHUNK_LOWEST_TSN_LENGTH 4
1654 dissect_cwr_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
1657 proto_tree_add_item(chunk_tree, hf_cwr_chunk_lowest_tsn, chunk_tvb, CWR_CHUNK_LOWEST_TSN_OFFSET, CWR_CHUNK_LOWEST_TSN_LENGTH, NETWORK_BYTE_ORDER);
1658 proto_item_append_text(chunk_item, " (Lowest TSN: %u)", tvb_get_ntohl(chunk_tvb, CWR_CHUNK_LOWEST_TSN_OFFSET));
1661 #define SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT 0x01
1664 static const true_false_string sctp_shutdown_complete_chunk_t_bit_value = {
1671 dissect_shutdown_complete_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *flags_item)
1673 proto_tree *flags_tree;
1676 flags_tree = proto_item_add_subtree(flags_item, ett_sctp_shutdown_complete_chunk_flags);
1677 proto_tree_add_item(flags_tree, hf_shutdown_complete_chunk_t_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
1681 #define FORWARD_TSN_CHUNK_TSN_LENGTH 4
1682 #define FORWARD_TSN_CHUNK_SID_LENGTH 2
1683 #define FORWARD_TSN_CHUNK_SSN_LENGTH 2
1684 #define FORWARD_TSN_CHUNK_TSN_OFFSET CHUNK_VALUE_OFFSET
1685 #define FORWARD_TSN_CHUNK_SID_OFFSET 0
1686 #define FORWARD_TSN_CHUNK_SSN_OFFSET (FORWARD_TSN_CHUNK_SID_OFFSET + FORWARD_TSN_CHUNK_SID_LENGTH)
1689 dissect_forward_tsn_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
1692 guint16 number_of_affected_streams, affected_stream, length;
1695 proto_tree_add_item(chunk_tree, hf_forward_tsn_chunk_tsn, chunk_tvb, FORWARD_TSN_CHUNK_TSN_OFFSET, FORWARD_TSN_CHUNK_TSN_LENGTH, NETWORK_BYTE_ORDER);
1696 length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1697 number_of_affected_streams = (length - CHUNK_HEADER_LENGTH - FORWARD_TSN_CHUNK_TSN_LENGTH) /
1698 (FORWARD_TSN_CHUNK_SID_LENGTH + FORWARD_TSN_CHUNK_SSN_LENGTH);
1699 offset = CHUNK_VALUE_OFFSET + FORWARD_TSN_CHUNK_TSN_LENGTH;
1701 for(affected_stream = 0; affected_stream < number_of_affected_streams; affected_stream++) {
1702 proto_tree_add_item(chunk_tree, hf_forward_tsn_chunk_sid, chunk_tvb, offset + FORWARD_TSN_CHUNK_SID_OFFSET, FORWARD_TSN_CHUNK_SID_LENGTH, NETWORK_BYTE_ORDER);
1703 proto_tree_add_item(chunk_tree, hf_forward_tsn_chunk_ssn, chunk_tvb, offset + FORWARD_TSN_CHUNK_SSN_OFFSET, FORWARD_TSN_CHUNK_SSN_LENGTH, NETWORK_BYTE_ORDER);
1704 offset = offset + (FORWARD_TSN_CHUNK_SID_LENGTH + FORWARD_TSN_CHUNK_SSN_LENGTH);
1706 proto_item_append_text(chunk_item, "(Cumulative TSN: %u)", tvb_get_ntohl(chunk_tvb, FORWARD_TSN_CHUNK_TSN_OFFSET));
1710 #define SERIAL_NUMBER_LENGTH 4
1711 #define SERIAL_NUMBER_OFFSET PARAMETER_VALUE_OFFSET
1712 #define ASCONF_CHUNK_PARAMETERS_OFFSET (SERIAL_NUMBER_OFFSET + SERIAL_NUMBER_LENGTH)
1715 dissect_asconf_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree)
1717 guint parameters_length;
1718 tvbuff_t *parameters_tvb;
1721 proto_tree_add_item(chunk_tree, hf_asconf_serial, chunk_tvb, SERIAL_NUMBER_OFFSET, SERIAL_NUMBER_LENGTH, NETWORK_BYTE_ORDER);
1722 parameters_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH - SERIAL_NUMBER_LENGTH;
1723 parameters_tvb = tvb_new_subset(chunk_tvb, ASCONF_CHUNK_PARAMETERS_OFFSET, parameters_length, parameters_length);
1724 dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, FALSE);
1728 #define ASCONF_ACK_CHUNK_PARAMETERS_OFFSET (SERIAL_NUMBER_OFFSET + SERIAL_NUMBER_LENGTH)
1731 dissect_asconf_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree)
1733 guint parameters_length;
1734 tvbuff_t *parameters_tvb;
1737 proto_tree_add_item(chunk_tree, hf_asconf_ack_serial, chunk_tvb, SERIAL_NUMBER_OFFSET, SERIAL_NUMBER_LENGTH, NETWORK_BYTE_ORDER);
1738 parameters_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH - SERIAL_NUMBER_LENGTH;
1739 parameters_tvb = tvb_new_subset(chunk_tvb, ASCONF_ACK_CHUNK_PARAMETERS_OFFSET, parameters_length, parameters_length);
1740 dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, FALSE);
1744 #define PKTDROP_CHUNK_BANDWIDTH_LENGTH 4
1745 #define PKTDROP_CHUNK_QUEUESIZE_LENGTH 4
1746 #define PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH 2
1747 #define PKTDROP_CHUNK_RESERVED_SIZE_LENGTH 2
1749 #define PKTDROP_CHUNK_HEADER_LENGTH (CHUNK_HEADER_LENGTH + \
1750 PKTDROP_CHUNK_BANDWIDTH_LENGTH + \
1751 PKTDROP_CHUNK_QUEUESIZE_LENGTH + \
1752 PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH + \
1753 PKTDROP_CHUNK_RESERVED_SIZE_LENGTH)
1755 #define PKTDROP_CHUNK_BANDWIDTH_OFFSET CHUNK_VALUE_OFFSET
1756 #define PKTDROP_CHUNK_QUEUESIZE_OFFSET (PKTDROP_CHUNK_BANDWIDTH_OFFSET + PKTDROP_CHUNK_BANDWIDTH_LENGTH)
1757 #define PKTDROP_CHUNK_TRUNCATED_SIZE_OFFSET (PKTDROP_CHUNK_QUEUESIZE_OFFSET + PKTDROP_CHUNK_QUEUESIZE_LENGTH)
1758 #define PKTDROP_CHUNK_RESERVED_SIZE_OFFSET (PKTDROP_CHUNK_TRUNCATED_SIZE_OFFSET + PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH)
1759 #define PKTDROP_CHUNK_DATA_FIELD_OFFSET (PKTDROP_CHUNK_RESERVED_SIZE_OFFSET + PKTDROP_CHUNK_RESERVED_SIZE_LENGTH)
1761 #define SCTP_PKTDROP_CHUNK_M_BIT 0x01
1762 #define SCTP_PKTDROP_CHUNK_B_BIT 0x02
1763 #define SCTP_PKTDROP_CHUNK_T_BIT 0x04
1765 static const true_false_string sctp_pktdropk_m_bit_value = {
1766 "Source is a middlebox",
1767 "Source is an endhost"
1771 static const true_false_string sctp_pktdropk_s_bit_value = {
1772 "This is a summary",
1773 "This is not a summary"
1777 static const true_false_string sctp_pktdropk_b_bit_value = {
1778 "SCTP checksum was incorrect",
1779 "SCTP checksum was correct"
1782 static const true_false_string sctp_pktdropk_t_bit_value = {
1783 "Packet is truncated",
1784 "Packet is not truncated"
1788 dissect_pktdrop_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *flags_item)
1790 guint16 data_field_length;
1791 tvbuff_t *data_field_tvb;
1792 proto_tree *flags_tree;
1794 data_field_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - PKTDROP_CHUNK_HEADER_LENGTH;
1795 data_field_tvb = tvb_new_subset(chunk_tvb, PKTDROP_CHUNK_DATA_FIELD_OFFSET, data_field_length, data_field_length);
1798 flags_tree = proto_item_add_subtree(flags_item, ett_sctp_pktdrop_chunk_flags);
1800 proto_tree_add_item(flags_tree, hf_pktdrop_chunk_m_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
1802 proto_tree_add_item(flags_tree, hf_pktdrop_chunk_s_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
1804 proto_tree_add_item(flags_tree, hf_pktdrop_chunk_b_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
1805 proto_tree_add_item(flags_tree, hf_pktdrop_chunk_t_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
1806 proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_bandwidth, chunk_tvb, PKTDROP_CHUNK_BANDWIDTH_OFFSET, PKTDROP_CHUNK_BANDWIDTH_LENGTH, NETWORK_BYTE_ORDER);
1807 proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_queuesize, chunk_tvb, PKTDROP_CHUNK_QUEUESIZE_OFFSET, PKTDROP_CHUNK_QUEUESIZE_LENGTH, NETWORK_BYTE_ORDER);
1808 proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_truncated_length, chunk_tvb, PKTDROP_CHUNK_TRUNCATED_SIZE_OFFSET, PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH, NETWORK_BYTE_ORDER);
1809 proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_reserved, chunk_tvb, PKTDROP_CHUNK_RESERVED_SIZE_OFFSET, PKTDROP_CHUNK_RESERVED_SIZE_LENGTH, NETWORK_BYTE_ORDER);
1810 if (tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_PKTDROP_CHUNK_T_BIT)
1811 proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_data_field, chunk_tvb, PKTDROP_CHUNK_DATA_FIELD_OFFSET, data_field_length, NETWORK_BYTE_ORDER);
1813 dissect_sctp_packet(data_field_tvb, pinfo, chunk_tree, TRUE);
1818 dissect_unknown_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
1820 guint chunk_value_length;
1823 chunk_value_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
1824 if (chunk_value_length > 0)
1825 proto_tree_add_item(chunk_tree, hf_chunk_value, chunk_tvb, CHUNK_VALUE_OFFSET, chunk_value_length, NETWORK_BYTE_ORDER);
1826 proto_item_append_text(chunk_item, " (Type: %u, value length: %u byte%s)", tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET), chunk_value_length, plurality(chunk_value_length, "", "s"));
1830 #define SCTP_CHUNK_BIT_1 0x80
1831 #define SCTP_CHUNK_BIT_2 0x40
1833 static const true_false_string sctp_chunk_bit_1_value = {
1834 "Skip chunk and continue processing of the packet",
1835 "Stop processing of the packet"
1838 static const true_false_string sctp_chunk_bit_2_value = {
1845 dissect_sctp_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *sctp_tree, gboolean useinfo)
1848 guint16 length, padding_length;
1850 proto_item *flags_item;
1851 proto_item *chunk_item;
1852 proto_tree *chunk_tree;
1853 proto_item *type_item;
1854 proto_tree *type_tree;
1858 /* first extract the chunk header */
1859 type = tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET);
1860 flags = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
1861 length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1862 padding_length = tvb_length(chunk_tvb) - length;
1864 if (useinfo && (check_col(pinfo->cinfo, COL_INFO)))
1865 col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(type, chunk_type_values, "RESERVED"));
1868 /* create proto_tree stuff */
1869 chunk_item = proto_tree_add_text(sctp_tree, chunk_tvb, CHUNK_HEADER_OFFSET, tvb_length(chunk_tvb), "%s chunk", val_to_str(type, chunk_type_values, "RESERVED"));
1870 chunk_tree = proto_item_add_subtree(chunk_item, ett_sctp_chunk);
1872 /* then insert the chunk header components into the protocol tree */
1873 type_item = proto_tree_add_item(chunk_tree, hf_chunk_type, chunk_tvb, CHUNK_TYPE_OFFSET, CHUNK_TYPE_LENGTH, NETWORK_BYTE_ORDER);
1874 type_tree = proto_item_add_subtree(type_item, ett_sctp_chunk_type);
1875 proto_tree_add_item(type_tree, hf_chunk_bit_1, chunk_tvb, CHUNK_TYPE_OFFSET, CHUNK_TYPE_LENGTH, NETWORK_BYTE_ORDER);
1876 proto_tree_add_item(type_tree, hf_chunk_bit_2, chunk_tvb, CHUNK_TYPE_OFFSET, CHUNK_TYPE_LENGTH, NETWORK_BYTE_ORDER);
1877 flags_item = proto_tree_add_item(chunk_tree, hf_chunk_flags, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
1878 proto_tree_add_item(chunk_tree, hf_chunk_length, chunk_tvb, CHUNK_LENGTH_OFFSET, CHUNK_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
1885 /* now dissect the chunk value */
1888 case SCTP_DATA_CHUNK_ID:
1889 result = dissect_data_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1891 case SCTP_INIT_CHUNK_ID:
1892 dissect_init_chunk(chunk_tvb, pinfo, chunk_tree, chunk_item);
1894 case SCTP_INIT_ACK_CHUNK_ID:
1895 dissect_init_ack_chunk(chunk_tvb, pinfo, chunk_tree, chunk_item);
1897 case SCTP_SACK_CHUNK_ID:
1898 dissect_sack_chunk(chunk_tvb, chunk_tree, chunk_item);
1900 case SCTP_HEARTBEAT_CHUNK_ID:
1901 dissect_heartbeat_chunk(chunk_tvb, pinfo, chunk_tree, chunk_item);
1903 case SCTP_HEARTBEAT_ACK_CHUNK_ID:
1904 dissect_heartbeat_ack_chunk(chunk_tvb, pinfo, chunk_tree, chunk_item);
1906 case SCTP_ABORT_CHUNK_ID:
1907 dissect_abort_chunk(chunk_tvb, pinfo, chunk_tree, flags_item);
1909 case SCTP_SHUTDOWN_CHUNK_ID:
1910 dissect_shutdown_chunk(chunk_tvb, chunk_tree, chunk_item);
1912 case SCTP_SHUTDOWN_ACK_CHUNK_ID:
1913 dissect_shutdown_ack_chunk(chunk_tvb);
1915 case SCTP_ERROR_CHUNK_ID:
1916 dissect_error_chunk(chunk_tvb, pinfo, chunk_tree);
1918 case SCTP_COOKIE_ECHO_CHUNK_ID:
1919 dissect_cookie_echo_chunk(chunk_tvb, chunk_tree, chunk_item);
1921 case SCTP_COOKIE_ACK_CHUNK_ID:
1922 dissect_cookie_ack_chunk(chunk_tvb);
1924 case SCTP_ECNE_CHUNK_ID:
1925 dissect_ecne_chunk(chunk_tvb, chunk_tree, chunk_item);
1927 case SCTP_CWR_CHUNK_ID:
1928 dissect_cwr_chunk(chunk_tvb, chunk_tree, chunk_item);
1930 case SCTP_SHUTDOWN_COMPLETE_CHUNK_ID:
1931 dissect_shutdown_complete_chunk(chunk_tvb, chunk_tree, flags_item);
1933 case SCTP_FORWARD_TSN_CHUNK_ID:
1934 dissect_forward_tsn_chunk(chunk_tvb, chunk_tree, chunk_item);
1936 case SCTP_ASCONF_ACK_CHUNK_ID:
1937 dissect_asconf_ack_chunk(chunk_tvb, pinfo, chunk_tree);
1939 case SCTP_ASCONF_CHUNK_ID:
1940 dissect_asconf_chunk(chunk_tvb, pinfo, chunk_tree);
1942 case SCTP_PKTDROP_CHUNK_ID:
1943 col_set_writable(pinfo->cinfo, FALSE);
1944 dissect_pktdrop_chunk(chunk_tvb, pinfo, chunk_tree, flags_item);
1945 col_set_writable(pinfo->cinfo, TRUE);
1948 dissect_unknown_chunk(chunk_tvb, chunk_tree, chunk_item);
1952 if (padding_length > 0)
1953 proto_tree_add_item(chunk_tree, hf_chunk_padding, chunk_tvb, CHUNK_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
1955 if (useinfo && ((type == SCTP_DATA_CHUNK_ID) || show_always_control_chunks))
1956 col_set_fence(pinfo->cinfo, COL_INFO);
1962 dissect_sctp_chunks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *sctp_item, proto_tree *sctp_tree, gboolean encapsulated)
1964 tvbuff_t *chunk_tvb;
1965 guint16 length, total_length, remaining_length;
1966 gint last_offset, offset;
1967 gboolean sctp_item_length_set;
1969 /* the common header of the datagram is already handled */
1971 offset = COMMON_HEADER_LENGTH;
1972 sctp_item_length_set = FALSE;
1974 while((remaining_length = tvb_length_remaining(tvb, offset))) {
1975 /* extract the chunk length and compute number of padding bytes */
1976 length = tvb_get_ntohs(tvb, offset + CHUNK_LENGTH_OFFSET);
1977 total_length = ADD_PADDING(length);
1978 if (remaining_length >= length)
1979 total_length = MIN(total_length, remaining_length);
1980 /* create a tvb for the chunk including the padding bytes */
1981 chunk_tvb = tvb_new_subset(tvb, offset, total_length, total_length);
1983 /* save it in the sctp_info structure */
1984 if (!encapsulated) {
1985 if (sctp_info.number_of_tvbs < MAXIMUM_NUMBER_OF_TVBS)
1986 sctp_info.tvb[sctp_info.number_of_tvbs++] = chunk_tvb;
1988 sctp_info.incomplete = TRUE;
1991 /* call dissect_sctp_chunk for the actual work */
1992 if (dissect_sctp_chunk(chunk_tvb, pinfo, tree, sctp_tree, !encapsulated) && (tree)) {
1993 proto_item_set_len(sctp_item, offset - last_offset + DATA_CHUNK_HEADER_LENGTH);
1994 sctp_item_length_set = TRUE;
1995 offset += total_length;
1996 last_offset = offset;
1997 if (tvb_reported_length_remaining(tvb, offset) > 0) {
1998 sctp_item = proto_tree_add_item(tree, proto_sctp, tvb, offset, -1, FALSE);
1999 sctp_tree = proto_item_add_subtree(sctp_item, ett_sctp);
2000 sctp_item_length_set = FALSE;
2003 /* get rid of the dissected chunk */
2004 offset += total_length;
2007 if (!sctp_item_length_set && (tree)) {
2008 proto_item_set_len(sctp_item, offset - last_offset);
2013 dissect_sctp_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean encapsulated)
2015 guint32 checksum = 0, calculated_crc32c = 0, calculated_adler32 = 0;
2017 gboolean crc32c_correct = FALSE, adler32_correct = FALSE;
2018 proto_item *sctp_item;
2019 proto_tree *sctp_tree;
2021 length = tvb_length(tvb);
2022 checksum = tvb_get_ntohl(tvb, CHECKSUM_OFFSET);
2023 switch(sctp_checksum) {
2024 case SCTP_CHECKSUM_NONE:
2026 case SCTP_CHECKSUM_ADLER32:
2027 calculated_adler32 = sctp_adler32(tvb_get_ptr(tvb, 0, length), length);
2028 adler32_correct = (checksum == calculated_adler32);
2029 sctp_info.adler32_calculated = TRUE;
2030 sctp_info.adler32_correct = adler32_correct;
2032 case SCTP_CHECKSUM_CRC32C:
2033 calculated_crc32c = sctp_crc32c(tvb_get_ptr(tvb, 0, length), length);
2034 crc32c_correct = (checksum == calculated_crc32c);
2035 sctp_info.crc32c_calculated = TRUE;
2036 sctp_info.crc32c_correct = crc32c_correct;
2038 case SCTP_CHECKSUM_AUTOMATIC:
2039 calculated_adler32 = sctp_adler32(tvb_get_ptr(tvb, 0, length), length);
2040 adler32_correct = (checksum == calculated_adler32);
2041 calculated_crc32c = sctp_crc32c(tvb_get_ptr(tvb, 0, length), length);
2042 crc32c_correct = (checksum == calculated_crc32c);
2043 sctp_info.adler32_calculated = TRUE;
2044 sctp_info.adler32_correct = adler32_correct;
2045 sctp_info.crc32c_calculated = TRUE;
2046 sctp_info.crc32c_correct = crc32c_correct;
2050 /* In the interest of speed, if "tree" is NULL, don't do any work not
2051 necessary to generate protocol tree items. */
2053 /* create the sctp protocol tree */
2054 sctp_item = proto_tree_add_item(tree, proto_sctp, tvb, 0, -1, FALSE);
2055 sctp_tree = proto_item_add_subtree(sctp_item, ett_sctp);
2057 /* add the components of the common header to the protocol tree */
2058 proto_tree_add_item(sctp_tree, hf_source_port, tvb, SOURCE_PORT_OFFSET, SOURCE_PORT_LENGTH, NETWORK_BYTE_ORDER);
2059 proto_tree_add_item(sctp_tree, hf_destination_port, tvb, DESTINATION_PORT_OFFSET, DESTINATION_PORT_LENGTH, NETWORK_BYTE_ORDER);
2060 proto_tree_add_item(sctp_tree, hf_verification_tag, tvb, VERIFICATION_TAG_OFFSET, VERIFICATION_TAG_LENGTH, NETWORK_BYTE_ORDER);
2061 proto_tree_add_item_hidden(sctp_tree, hf_port, tvb, SOURCE_PORT_OFFSET, SOURCE_PORT_LENGTH, NETWORK_BYTE_ORDER);
2062 proto_tree_add_item_hidden(sctp_tree, hf_port, tvb, DESTINATION_PORT_OFFSET, DESTINATION_PORT_LENGTH, NETWORK_BYTE_ORDER);
2064 length = tvb_length(tvb);
2065 checksum = tvb_get_ntohl(tvb, CHECKSUM_OFFSET);
2066 switch(sctp_checksum) {
2067 case SCTP_CHECKSUM_NONE:
2068 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, checksum, "Checksum: 0x%08x (not verified)", checksum);
2070 case SCTP_CHECKSUM_ADLER32:
2071 if (adler32_correct)
2072 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2073 checksum, "Checksum: 0x%08x (correct Adler32)", checksum);
2075 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2076 checksum, "Checksum: 0x%08x (incorrect Adler32, should be 0x%08x)", checksum, calculated_adler32);
2077 proto_tree_add_boolean_hidden(sctp_tree, hf_checksum_bad, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, !(adler32_correct));
2079 case SCTP_CHECKSUM_CRC32C:
2081 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2082 checksum, "Checksum: 0x%08x (correct CRC32C)", checksum);
2084 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2085 checksum, "Checksum: 0x%08x (incorrect CRC32C, should be 0x%08x)", checksum, calculated_crc32c);
2086 proto_tree_add_boolean_hidden(sctp_tree, hf_checksum_bad, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, !(crc32c_correct));
2088 case SCTP_CHECKSUM_AUTOMATIC:
2089 if ((adler32_correct) && !(crc32c_correct))
2090 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2091 checksum, "Checksum: 0x%08x (correct Adler32)", checksum);
2092 else if (!(adler32_correct) && (crc32c_correct))
2093 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2094 checksum, "Checksum: 0x%08x (correct CRC32C)", checksum);
2095 else if ((adler32_correct) && (crc32c_correct))
2096 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2097 checksum, "Checksum: 0x%08x (correct Adler32 and CRC32C)", checksum);
2099 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2100 checksum, "Checksum: 0x%08x (incorrect, should be 0x%08x (Adler32) or 0x%08x (CRC32C))",
2101 checksum, calculated_adler32, calculated_crc32c);
2102 proto_tree_add_boolean_hidden(sctp_tree, hf_checksum_bad, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, !(crc32c_correct || adler32_correct));
2109 /* add all chunks of the sctp datagram to the protocol tree */
2110 dissect_sctp_chunks(tvb, pinfo, tree, sctp_item, sctp_tree, encapsulated);
2114 dissect_sctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2116 guint16 source_port, destination_port;
2118 /* Extract the common header */
2119 source_port = tvb_get_ntohs(tvb, SOURCE_PORT_OFFSET);
2120 destination_port = tvb_get_ntohs(tvb, DESTINATION_PORT_OFFSET);
2122 /* update pi structure */
2123 pinfo->ptype = PT_SCTP;
2124 pinfo->srcport = source_port;
2125 pinfo->destport = destination_port;
2127 /* make entry in the Protocol column on summary display */
2128 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2129 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCTP");
2131 /* Clear entries in Info column on summary display */
2132 if (check_col(pinfo->cinfo, COL_INFO))
2133 col_set_str(pinfo->cinfo, COL_INFO, "");
2135 memset(&sctp_info, 0, sizeof(struct _sctp_info));
2136 sctp_info.verification_tag = tvb_get_ntohl(tvb, VERIFICATION_TAG_OFFSET);
2137 dissect_sctp_packet(tvb, pinfo, tree, FALSE);
2138 if (!pinfo->in_error_pkt)
2139 tap_queue_packet(sctp_tap, pinfo, &sctp_info);
2142 /* Register the protocol with Ethereal */
2144 proto_register_sctp(void)
2147 /* Setup list of header fields */
2148 static hf_register_info hf[] = {
2149 { &hf_source_port, { "Source port", "sctp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2150 { &hf_destination_port, { "Destination port", "sctp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2151 { &hf_port, { "Port", "sctp.port", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2152 { &hf_verification_tag, { "Verification tag", "sctp.verification_tag", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
2153 { &hf_checksum, { "Checksum", "sctp.checksum", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
2154 { &hf_checksum_bad, { "Bad checksum", "sctp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL } },
2155 { &hf_chunk_type, { "Chunk type", "sctp.chunk_type", FT_UINT8, BASE_DEC, VALS(chunk_type_values), 0x0, "", HFILL } },
2156 { &hf_chunk_flags, { "Chunk flags", "sctp.chunk_flags", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL } },
2157 { &hf_chunk_bit_1, { "Bit", "sctp.chunk_bit_1", FT_BOOLEAN, 8, TFS(&sctp_chunk_bit_1_value), SCTP_CHUNK_BIT_1, "", HFILL } },
2158 { &hf_chunk_bit_2, { "Bit", "sctp.chunk_bit_2", FT_BOOLEAN, 8, TFS(&sctp_chunk_bit_2_value), SCTP_CHUNK_BIT_2, "", HFILL } },
2159 { &hf_chunk_length, { "Chunk length", "sctp.chunk_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2160 { &hf_chunk_padding, { "Chunk padding", "sctp.chunk_padding", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
2161 { &hf_chunk_value, { "Chunk value", "sctp.chunk_value", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
2162 { &hf_cookie, { "Cookie", "sctp.cookie", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
2163 { &hf_initiate_tag, { "Initiate tag", "sctp.initiate_tag", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
2164 { &hf_init_chunk_initiate_tag, { "Initiate tag", "sctp.init_initiate_tag", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
2165 { &hf_init_chunk_adv_rec_window_credit, { "Advertised receiver window credit (a_rwnd)", "sctp.init_credit", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2166 { &hf_init_chunk_number_of_outbound_streams, { "Number of outbound streams", "sctp.init_nr_out_streams", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2167 { &hf_init_chunk_number_of_inbound_streams, { "Number of inbound streams", "sctp.init_nr_in_streams", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2168 { &hf_init_chunk_initial_tsn, { "Initial TSN", "sctp.init_initial_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2169 { &hf_initack_chunk_initiate_tag, { "Initiate tag", "sctp.initack_initiate_tag", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
2170 { &hf_initack_chunk_adv_rec_window_credit, { "Advertised receiver window credit (a_rwnd)", "sctp.initack_credit", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2171 { &hf_initack_chunk_number_of_outbound_streams, { "Number of outbound streams", "sctp.initack_nr_out_streams", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2172 { &hf_initack_chunk_number_of_inbound_streams, { "Number of inbound streams", "sctp.initack_nr_in_streams", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2173 { &hf_initack_chunk_initial_tsn, { "Initial TSN", "sctp.initack_initial_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2174 { &hf_cumulative_tsn_ack, { "Cumulative TSN Ack", "sctp.cumulative_tsn_ack", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2175 { &hf_data_chunk_tsn, { "TSN", "sctp.data_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2176 { &hf_data_chunk_stream_id, { "Stream Identifier", "sctp.data_sid", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL } },
2177 { &hf_data_chunk_stream_seq_number, { "Stream sequence number", "sctp.data_ssn", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2178 { &hf_data_chunk_payload_proto_id, { "Payload protocol identifier", "sctp.data_payload_proto_id", FT_UINT32, BASE_DEC, VALS(sctp_payload_proto_id_values), 0x0, "", HFILL } },
2179 { &hf_data_chunk_e_bit, { "E-Bit", "sctp.data_e_bit", FT_BOOLEAN, 8, TFS(&sctp_data_chunk_e_bit_value), SCTP_DATA_CHUNK_E_BIT, "", HFILL } },
2180 { &hf_data_chunk_b_bit, { "B-Bit", "sctp.data_b_bit", FT_BOOLEAN, 8, TFS(&sctp_data_chunk_b_bit_value), SCTP_DATA_CHUNK_B_BIT, "", HFILL } },
2181 { &hf_data_chunk_u_bit, { "U-Bit", "sctp.data_u_bit", FT_BOOLEAN, 8, TFS(&sctp_data_chunk_u_bit_value), SCTP_DATA_CHUNK_U_BIT, "", HFILL } },
2182 { &hf_sack_chunk_cumulative_tsn_ack, { "Cumulative TSN ACK", "sctp.sack_cumulative_tsn_ack", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2183 { &hf_sack_chunk_adv_rec_window_credit, { "Advertised receiver window credit (a_rwnd)", "sctp.sack_a_rwnd", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2184 { &hf_sack_chunk_number_of_gap_blocks, { "Number of gap acknowldgement blocks ", "sctp.sack_number_of_gap_blocks", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2185 { &hf_sack_chunk_number_of_dup_tsns, { "Number of duplicated TSNs", "sctp.sack_number_of_duplicated_tsns", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2186 { &hf_sack_chunk_gap_block_start, { "Start", "sctp.sack_gap_block_start", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2187 { &hf_sack_chunk_gap_block_end, { "End", "sctp.sack_gap_block_end", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2188 { &hf_sack_chunk_duplicate_tsn, { "Duplicate TSN", "sctp.sack_duplicate_tsn", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2189 { &hf_shutdown_chunk_cumulative_tsn_ack, { "Cumulative TSN Ack", "sctp.shutdown_cumulative_tsn_ack", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2190 { &hf_ecne_chunk_lowest_tsn, { "Lowest TSN", "sctp.ecne_lowest_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2191 { &hf_cwr_chunk_lowest_tsn, { "Lowest TSN", "sctp.cwr_lowest_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2192 { &hf_shutdown_complete_chunk_t_bit, { "T-Bit", "sctp.shutdown_complete_t_bit", FT_BOOLEAN, 8, TFS(&sctp_shutdown_complete_chunk_t_bit_value), SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT, "", HFILL } },
2193 { &hf_abort_chunk_t_bit, { "T-Bit", "sctp.abort_t_bit", FT_BOOLEAN, 8, TFS(&sctp_shutdown_complete_chunk_t_bit_value), SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT, "", HFILL } },
2194 { &hf_forward_tsn_chunk_tsn, { "New cumulative TSN", "sctp.forward_tsn_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2195 { &hf_forward_tsn_chunk_sid, { "Stream identifier", "sctp.forward_tsn_sid", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2196 { &hf_forward_tsn_chunk_ssn, { "Stream sequence number", "sctp.forward_tsn_ssn", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2197 { &hf_parameter_type, { "Parameter type", "sctp.parameter_type", FT_UINT16, BASE_HEX, VALS(parameter_identifier_values), 0x0, "", HFILL } },
2198 { &hf_parameter_length, { "Parameter length", "sctp.parameter_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2199 { &hf_parameter_value, { "Parameter value", "sctp.parameter_value", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
2200 { &hf_parameter_padding, { "Parameter padding", "sctp.parameter_padding", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
2201 { &hf_parameter_bit_1, { "Bit", "sctp.parameter_bit_1", FT_BOOLEAN, 16, TFS(&sctp_parameter_bit_1_value), SCTP_PARAMETER_BIT_1, "", HFILL } },
2202 { &hf_parameter_bit_2, { "Bit", "sctp.parameter_bit_2", FT_BOOLEAN, 16, TFS(&sctp_parameter_bit_2_value), SCTP_PARAMETER_BIT_2, "", HFILL } },
2203 { &hf_ipv4_address, { "IP Version 4 address", "sctp.parameter_ipv4_address", FT_IPv4, BASE_NONE, NULL, 0x0, "", HFILL } },
2204 { &hf_ipv6_address, { "IP Version 6 address", "sctp.parameter_ipv6_address", FT_IPv6, BASE_NONE, NULL, 0x0, "", HFILL } },
2205 { &hf_heartbeat_info, { "Heartbeat information", "sctp.parameter_heartbeat_information", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
2206 { &hf_state_cookie, { "State cookie", "sctp.parameter_state_cookie", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
2207 { &hf_cookie_preservative_increment, { "Suggested Cookie life-span increment (msec)", "sctp.parameter_cookie_preservative_incr", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2208 { &hf_hostname, { "Hostname", "sctp.parameter_hostname", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL } },
2209 { &hf_supported_address_type, { "Supported address type", "sctp.parameter_supported_addres_type", FT_UINT16, BASE_DEC, VALS(address_types_values), 0x0, "", HFILL } },
2210 { &hf_asconf_serial, { "Serial Number", "sctp.asconf_serial_number", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
2211 { &hf_asconf_ack_serial, { "Serial Number", "sctp.asconf_ack_serial_number", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
2212 { &hf_correlation_id, { "Correlation_id", "sctp.correlation_id", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
2213 { &hf_adap_indication, { "Indication", "sctp.adapation_layer_indication", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
2214 { &hf_cause_code, { "Cause code", "sctp.cause_code", FT_UINT16, BASE_HEX, VALS(cause_code_values), 0x0, "", HFILL } },
2215 { &hf_cause_length, { "Cause length", "sctp.cause_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2216 { &hf_cause_info, { "Cause information", "sctp.cause_information", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
2217 { &hf_cause_padding, { "Cause padding", "sctp.cause_padding", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
2218 { &hf_cause_stream_identifier, { "Stream identifier", "sctp.cause_stream_identifier", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2219 { &hf_cause_reserved, { "Reserved", "sctp.cause_reserved", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2220 { &hf_cause_number_of_missing_parameters, { "Number of missing parameters", "sctp.cause_nr_of_missing_parameters", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2221 { &hf_cause_missing_parameter_type, { "Missing parameter type", "sctp.cause_missing_parameter_type", FT_UINT16, BASE_HEX, VALS(parameter_identifier_values), 0x0, "", HFILL } },
2222 { &hf_cause_measure_of_staleness, { "Measure of staleness in usec", "sctp.cause_measure_of_staleness", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2223 { &hf_cause_tsn, { "TSN", "sctp.cause_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2224 { &hf_pktdrop_chunk_m_bit, { "M-Bit", "sctp.pckdrop_m_bit", FT_BOOLEAN, 8, TFS(&sctp_pktdropk_m_bit_value), SCTP_PKTDROP_CHUNK_M_BIT, "", HFILL } },
2225 { &hf_pktdrop_chunk_b_bit, { "B-Bit", "sctp.pckdrop_b_bit", FT_BOOLEAN, 8, TFS(&sctp_pktdropk_b_bit_value), SCTP_PKTDROP_CHUNK_B_BIT, "", HFILL } },
2226 { &hf_pktdrop_chunk_t_bit, { "T-Bit", "sctp.pckdrop_t_bit", FT_BOOLEAN, 8, TFS(&sctp_pktdropk_t_bit_value), SCTP_PKTDROP_CHUNK_T_BIT, "", HFILL } },
2227 { &hf_pktdrop_chunk_bandwidth, { "Bandwidth", "sctp.pktdrop_bandwidth", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2228 { &hf_pktdrop_chunk_queuesize, { "Queuesize", "sctp.pktdrop_queuesize", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2229 { &hf_pktdrop_chunk_truncated_length, { "Truncated length", "sctp.pktdrop_truncated_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2230 { &hf_pktdrop_chunk_reserved, { "Reserved", "sctp.pktdrop_reserved", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2231 { &hf_pktdrop_chunk_data_field, { "Data field", "sctp.pktdrop_datafield", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
2234 /* Setup protocol subtree array */
2235 static gint *ett[] = {
2238 &ett_sctp_chunk_parameter,
2239 &ett_sctp_chunk_cause,
2240 &ett_sctp_chunk_type,
2241 &ett_sctp_data_chunk_flags,
2242 &ett_sctp_abort_chunk_flags,
2243 &ett_sctp_shutdown_complete_chunk_flags,
2244 &ett_sctp_pktdrop_chunk_flags,
2245 &ett_sctp_parameter_type,
2246 &ett_sctp_sack_chunk_gap_block,
2247 &ett_sctp_unrecognized_parameter_parameter,
2250 static enum_val_t sctp_checksum_options[] = {
2251 { "none", "None", SCTP_CHECKSUM_NONE },
2252 { "adler-32", "Adler 32", SCTP_CHECKSUM_ADLER32 },
2253 { "crc-32c", "CRC 32c", SCTP_CHECKSUM_CRC32C },
2254 { "automatic", "Automatic", SCTP_CHECKSUM_AUTOMATIC},
2258 /* Register the protocol name and description */
2259 proto_sctp = proto_register_protocol("Stream Control Transmission Protocol", "SCTP", "sctp");
2260 sctp_module = prefs_register_protocol(proto_sctp, NULL);
2261 prefs_register_enum_preference(sctp_module, "checksum", "Checksum type",
2262 "The type of checksum used in SCTP packets",
2263 &sctp_checksum, sctp_checksum_options, FALSE);
2264 prefs_register_bool_preference(sctp_module, "show_always_control_chunks",
2265 "Show always control chunks",
2266 "Show always SCTP control chunks in the Info column",
2267 &show_always_control_chunks);
2268 prefs_register_bool_preference(sctp_module, "try_heuristic_first",
2269 "Try heuristic sub-dissectors first",
2270 "Try to decode a packet using an heuristic sub-dissector before using a sub-dissector registered to a specific port or PPI",
2271 &try_heuristic_first);
2273 /* Required function calls to register the header fields and subtrees used */
2274 proto_register_field_array(proto_sctp, hf, array_length(hf));
2275 proto_register_subtree_array(ett, array_length(ett));
2276 sctp_tap = register_tap("sctp");
2277 /* subdissector code */
2278 sctp_port_dissector_table = register_dissector_table("sctp.port", "SCTP port", FT_UINT16, BASE_DEC);
2279 sctp_ppi_dissector_table = register_dissector_table("sctp.ppi", "SCTP payload protocol identifier", FT_UINT32, BASE_HEX);
2280 register_heur_dissector_list("sctp", &sctp_heur_subdissector_list);
2284 proto_reg_handoff_sctp(void)
2286 dissector_handle_t sctp_handle;
2288 data_handle = find_dissector("data");
2289 sctp_handle = create_dissector_handle(dissect_sctp, proto_sctp);
2290 dissector_add("ip.proto", IP_PROTO_SCTP, sctp_handle);
2291 dissector_add("udp.port", UDP_TUNNELING_PORT, sctp_handle);