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 Michael Tuexen <tuexen [AT] fh-muenster.de>
11 * Still to do (so stay tuned)
12 * - support for reassembly
13 * - error checking mode
15 * $Id: packet-sctp.c,v 1.58 2003/06/08 15:59:26 tuexen Exp $
17 * Ethereal - Network traffic analyzer
18 * By Gerald Combs <gerald@ethereal.com>
19 * Copyright 1998 Gerald Combs
21 * Copied from README.developer
23 * This program is free software; you can redistribute it and/or
24 * modify it under the terms of the GNU General Public License
25 * as published by the Free Software Foundation; either version 2
26 * of the License, or (at your option) any later version.
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
33 * You should have received a copy of the GNU General Public License
34 * along with this program; if not, write to the Free Software
35 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
43 #include <epan/packet.h>
45 #include "sctpppids.h"
47 #define NETWORK_BYTE_ORDER FALSE
48 #define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
50 /* Initialize the protocol and registered fields */
51 static int proto_sctp = -1;
52 static int hf_port = -1;
53 static int hf_source_port = -1;
54 static int hf_destination_port = -1;
55 static int hf_verification_tag = -1;
56 static int hf_checksum = -1;
57 static int hf_checksum_bad = -1;
59 static int hf_chunk_type = -1;
60 static int hf_chunk_flags = -1;
61 static int hf_chunk_bit_1 = -1;
62 static int hf_chunk_bit_2 = -1;
63 static int hf_chunk_length = -1;
64 static int hf_chunk_padding = -1;
65 static int hf_chunk_value = -1;
67 static int hf_init_chunk_initiate_tag = -1;
68 static int hf_init_chunk_adv_rec_window_credit = -1;
69 static int hf_init_chunk_number_of_outbound_streams = -1;
70 static int hf_init_chunk_number_of_inbound_streams = -1;
71 static int hf_init_chunk_initial_tsn = -1;
73 static int hf_initack_chunk_initiate_tag = -1;
74 static int hf_initack_chunk_adv_rec_window_credit = -1;
75 static int hf_initack_chunk_number_of_outbound_streams = -1;
76 static int hf_initack_chunk_number_of_inbound_streams = -1;
77 static int hf_initack_chunk_initial_tsn = -1;
79 static int hf_cumulative_tsn_ack = -1;
81 static int hf_data_chunk_tsn = -1;
82 static int hf_data_chunk_stream_id = -1;
83 static int hf_data_chunk_stream_seq_number = -1;
84 static int hf_data_chunk_payload_proto_id = -1;
86 static int hf_data_chunk_e_bit = -1;
87 static int hf_data_chunk_b_bit = -1;
88 static int hf_data_chunk_u_bit = -1;
90 static int hf_sack_chunk_cumulative_tsn_ack = -1;
91 static int hf_sack_chunk_adv_rec_window_credit = -1;
92 static int hf_sack_chunk_number_of_gap_blocks = -1;
93 static int hf_sack_chunk_number_of_dup_tsns = -1;
94 static int hf_sack_chunk_gap_block_start = -1;
95 static int hf_sack_chunk_gap_block_end = -1;
96 static int hf_sack_chunk_duplicate_tsn = -1;
98 static int hf_shutdown_chunk_cumulative_tsn_ack = -1;
99 static int hf_cookie = -1;
100 static int hf_cwr_chunk_lowest_tsn = -1;
102 static int hf_ecne_chunk_lowest_tsn = -1;
103 static int hf_abort_chunk_t_bit = -1;
104 static int hf_shutdown_complete_chunk_t_bit = -1;
106 static int hf_parameter_type = -1;
107 static int hf_parameter_length = -1;
108 static int hf_parameter_value = -1;
109 static int hf_parameter_padding = -1;
110 static int hf_parameter_bit_1 = -1;
111 static int hf_parameter_bit_2 = -1;
112 static int hf_ipv4_address = -1;
113 static int hf_ipv6_address = -1;
114 static int hf_heartbeat_info = -1;
115 static int hf_state_cookie = -1;
116 static int hf_cookie_preservative_increment = -1;
117 static int hf_hostname = -1;
118 static int hf_supported_address_type = -1;
120 static int hf_cause_code = -1;
121 static int hf_cause_length = -1;
122 static int hf_cause_padding = -1;
123 static int hf_cause_info = -1;
125 static int hf_cause_stream_identifier = -1;
126 static int hf_cause_reserved = -1;
128 static int hf_cause_number_of_missing_parameters = -1;
129 static int hf_cause_missing_parameter_type = -1;
131 static int hf_cause_measure_of_staleness = -1;
133 static int hf_cause_tsn = -1;
135 static int hf_forward_tsn_chunk_tsn = -1;
136 static int hf_forward_tsn_chunk_sid = -1;
137 static int hf_forward_tsn_chunk_ssn = -1;
139 static int hf_asconf_ack_serial = -1;
140 static int hf_asconf_serial = -1;
141 static int hf_correlation_id = -1;
143 static int hf_adap_indication = -1;
145 static int hf_pktdrop_chunk_m_bit = -1;
147 static int hf_pktdrop_chunk_s_bit = -1;
149 static int hf_pktdrop_chunk_b_bit = -1;
150 static int hf_pktdrop_chunk_t_bit = -1;
151 static int hf_pktdrop_chunk_bandwidth = -1;
152 static int hf_pktdrop_chunk_queuesize = -1;
153 static int hf_pktdrop_chunk_truncated_length = -1;
154 static int hf_pktdrop_chunk_reserved = -1;
155 static int hf_pktdrop_chunk_data_field = -1;
157 static dissector_table_t sctp_port_dissector_table;
158 static dissector_table_t sctp_ppi_dissector_table;
160 static module_t *sctp_module;
162 /* Initialize the subtree pointers */
163 static gint ett_sctp = -1;
164 static gint ett_sctp_chunk = -1;
165 static gint ett_sctp_chunk_parameter = -1;
166 static gint ett_sctp_chunk_cause = -1;
167 static gint ett_sctp_chunk_type = -1;
168 static gint ett_sctp_data_chunk_flags = -1;
169 static gint ett_sctp_abort_chunk_flags = -1;
170 static gint ett_sctp_shutdown_complete_chunk_flags = -1;
171 static gint ett_sctp_pktdrop_chunk_flags = -1;
172 static gint ett_sctp_parameter_type= -1;
173 static gint ett_sctp_sack_chunk_gap_block = -1;
174 static gint ett_sctp_unrecognized_parameter_parameter = -1;
176 static dissector_handle_t data_handle;
178 #define SCTP_DATA_CHUNK_ID 0
179 #define SCTP_INIT_CHUNK_ID 1
180 #define SCTP_INIT_ACK_CHUNK_ID 2
181 #define SCTP_SACK_CHUNK_ID 3
182 #define SCTP_HEARTBEAT_CHUNK_ID 4
183 #define SCTP_HEARTBEAT_ACK_CHUNK_ID 5
184 #define SCTP_ABORT_CHUNK_ID 6
185 #define SCTP_SHUTDOWN_CHUNK_ID 7
186 #define SCTP_SHUTDOWN_ACK_CHUNK_ID 8
187 #define SCTP_ERROR_CHUNK_ID 9
188 #define SCTP_COOKIE_ECHO_CHUNK_ID 10
189 #define SCTP_COOKIE_ACK_CHUNK_ID 11
190 #define SCTP_ECNE_CHUNK_ID 12
191 #define SCTP_CWR_CHUNK_ID 13
192 #define SCTP_SHUTDOWN_COMPLETE_CHUNK_ID 14
193 #define SCTP_FORWARD_TSN_CHUNK_ID 192
194 #define SCTP_ASCONF_ACK_CHUNK_ID 0x80
195 #define SCTP_PKTDROP_CHUNK_ID 0X81
196 #define SCTP_ASCONF_CHUNK_ID 0XC1
197 #define SCTP_IETF_EXT 255
199 static const value_string chunk_type_values[] = {
200 { SCTP_DATA_CHUNK_ID, "DATA" },
201 { SCTP_INIT_CHUNK_ID, "INIT" },
202 { SCTP_INIT_ACK_CHUNK_ID, "INIT_ACK" },
203 { SCTP_SACK_CHUNK_ID, "SACK" },
204 { SCTP_HEARTBEAT_CHUNK_ID, "HEARTBEAT" },
205 { SCTP_HEARTBEAT_ACK_CHUNK_ID, "HEARTBEAT_ACK" },
206 { SCTP_ABORT_CHUNK_ID, "ABORT" },
207 { SCTP_SHUTDOWN_CHUNK_ID, "SHUTDOWN" },
208 { SCTP_SHUTDOWN_ACK_CHUNK_ID, "SHUTDOWN_ACK" },
209 { SCTP_ERROR_CHUNK_ID, "ERROR" },
210 { SCTP_COOKIE_ECHO_CHUNK_ID, "COOKIE_ECHO" },
211 { SCTP_COOKIE_ACK_CHUNK_ID, "COOKIE_ACK" },
212 { SCTP_ECNE_CHUNK_ID, "ECNE" },
213 { SCTP_CWR_CHUNK_ID, "CWR" },
214 { SCTP_SHUTDOWN_COMPLETE_CHUNK_ID, "SHUTDOWN_COMPLETE" },
215 { SCTP_FORWARD_TSN_CHUNK_ID, "FORWARD TSN" },
216 { SCTP_ASCONF_ACK_CHUNK_ID, "ASCONF_ACK" },
217 { SCTP_PKTDROP_CHUNK_ID, "PKTDROP" },
218 { SCTP_ASCONF_CHUNK_ID, "ASCONF" },
219 { SCTP_IETF_EXT, "IETF_EXTENSION" },
222 static const value_string sctp_payload_proto_id_values[] = {
223 { NOT_SPECIFIED_PROTOCOL_ID, "not specified" },
224 { IUA_PAYLOAD_PROTOCOL_ID, "IUA" },
225 { M2UA_PAYLOAD_PROTOCOL_ID, "M2UA" },
226 { M3UA_PAYLOAD_PROTOCOL_ID, "M3UA" },
227 { SUA_PAYLOAD_PROTOCOL_ID, "SUA" },
228 { M2PA_PAYLOAD_PROTOCOL_ID, "M2PA" },
229 { V5UA_PAYLOAD_PROTOCOL_ID, "V5UA" },
230 { H248_PAYLOAD_PROTOCOL_ID, "H.248/MEGACO" },
231 { BICC_PAYLOAD_PROTOCOL_ID, "BICC/Q.2150.3" },
232 { TALI_PAYLOAD_PROTOCOL_ID, "TALI" },
233 { DUA_PAYLOAD_PROTOCOL_ID, "DUA" },
234 { ASAP_PAYLOAD_PROTOCOL_ID, "ASAP" },
235 { ENRP_PAYLOAD_PROTOCOL_ID, "ENRP" },
236 { H323_PAYLOAD_PROTOCOL_ID, "H.323" },
240 #define CHUNK_TYPE_LENGTH 1
241 #define CHUNK_FLAGS_LENGTH 1
242 #define CHUNK_LENGTH_LENGTH 2
243 #define CHUNK_HEADER_LENGTH (CHUNK_TYPE_LENGTH + \
244 CHUNK_FLAGS_LENGTH + \
246 #define CHUNK_HEADER_OFFSET 0
247 #define CHUNK_TYPE_OFFSET CHUNK_HEADER_OFFSET
248 #define CHUNK_FLAGS_OFFSET (CHUNK_TYPE_OFFSET + CHUNK_TYPE_LENGTH)
249 #define CHUNK_LENGTH_OFFSET (CHUNK_FLAGS_OFFSET + CHUNK_FLAGS_LENGTH)
250 #define CHUNK_VALUE_OFFSET (CHUNK_LENGTH_OFFSET + CHUNK_LENGTH_LENGTH)
252 #define PARAMETER_TYPE_LENGTH 2
253 #define PARAMETER_LENGTH_LENGTH 2
254 #define PARAMETER_HEADER_LENGTH (PARAMETER_TYPE_LENGTH + PARAMETER_LENGTH_LENGTH)
256 #define PARAMETER_HEADER_OFFSET 0
257 #define PARAMETER_TYPE_OFFSET PARAMETER_HEADER_OFFSET
258 #define PARAMETER_LENGTH_OFFSET (PARAMETER_TYPE_OFFSET + PARAMETER_TYPE_LENGTH)
259 #define PARAMETER_VALUE_OFFSET (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
261 #define SOURCE_PORT_LENGTH 2
262 #define DESTINATION_PORT_LENGTH 2
263 #define VERIFICATION_TAG_LENGTH 4
264 #define CHECKSUM_LENGTH 4
265 #define COMMON_HEADER_LENGTH (SOURCE_PORT_LENGTH + \
266 DESTINATION_PORT_LENGTH + \
267 VERIFICATION_TAG_LENGTH + \
269 #define SOURCE_PORT_OFFSET 0
270 #define DESTINATION_PORT_OFFSET (SOURCE_PORT_OFFSET + SOURCE_PORT_LENGTH)
271 #define VERIFICATION_TAG_OFFSET (DESTINATION_PORT_OFFSET + DESTINATION_PORT_LENGTH)
272 #define CHECKSUM_OFFSET (VERIFICATION_TAG_OFFSET + VERIFICATION_TAG_LENGTH)
274 #define SCTP_CHECKSUM_NONE 0
275 #define SCTP_CHECKSUM_ADLER32 1
276 #define SCTP_CHECKSUM_CRC32C 2
277 #define SCTP_CHECKSUM_AUTOMATIC 3
279 static gboolean show_always_control_chunks = TRUE;
280 static gint sctp_checksum = SCTP_CHECKSUM_ADLER32;
282 /* adler32.c -- compute the Adler-32 checksum of a data stream
283 * Copyright (C) 1995-1996 Mark Adler
284 * For conditions of distribution and use, see copyright notice in zlib.h
285 * available, e.g. from http://www.cdrom.com/pub/infozip/zlib/
287 * It was modified for the use in this dissector.
290 #define BASE 65521L /* largest prime smaller than 65536 */
291 #define NMAX 5540 /* NMAX is the largest n - 12 such that */
292 /* 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
294 #define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
295 #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
296 #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
297 #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
298 #define DO16(buf) DO8(buf,0); DO8(buf,8);
301 sctp_adler32(const unsigned char* buf, unsigned int len)
303 unsigned int s1 = 1L;
304 unsigned int s2 = 0L;
307 /* handle the first 8 bytes of the datagram */
309 buf += SOURCE_PORT_LENGTH +
310 DESTINATION_PORT_LENGTH +
311 VERIFICATION_TAG_LENGTH;
313 /* handle four 0 bytes as checksum */
314 s2 += CHECKSUM_LENGTH * s1;
315 buf += CHECKSUM_LENGTH;
317 /* now we have 12 bytes handled */
318 len -= COMMON_HEADER_LENGTH;
320 /* handle the rest of the datagram */
322 k = len < NMAX ? len : NMAX;
336 return (s2 << 16) | s1;
339 /* The CRC32C code is taken from draft-ietf-tsvwg-sctpcsum-01.txt.
340 * That code is copyrighted by D. Otis and has been modified.
343 #define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
344 static guint32 crc_c[256] =
346 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
347 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
348 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
349 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
350 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
351 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
352 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
353 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
354 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
355 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
356 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
357 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
358 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
359 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
360 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
361 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
362 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
363 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
364 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
365 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
366 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
367 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
368 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
369 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
370 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
371 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
372 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
373 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
374 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
375 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
376 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
377 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
378 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
379 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
380 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
381 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
382 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
383 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
384 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
385 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
386 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
387 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
388 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
389 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
390 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
391 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
392 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
393 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
394 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
395 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
396 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
397 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
398 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
399 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
400 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
401 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
402 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
403 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
404 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
405 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
406 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
407 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
408 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
409 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L,
413 sctp_crc32c(const unsigned char* buf, unsigned int len)
418 unsigned char byte0,byte1,byte2,byte3;
420 for (i = 0; i < SOURCE_PORT_LENGTH + DESTINATION_PORT_LENGTH + VERIFICATION_TAG_LENGTH; i++)
422 CRC32C(crc32, buf[i]);
428 for (i = COMMON_HEADER_LENGTH; i < len; i++)
430 CRC32C(crc32, buf[i]);
434 byte0 = result & 0xff;
435 byte1 = (result>>8) & 0xff;
436 byte2 = (result>>16) & 0xff;
437 byte3 = (result>>24) & 0xff;
438 crc32 = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
443 * Routines for dissecting parameters
447 dissect_parameter(tvbuff_t *, packet_info *, proto_tree *, proto_item *);
450 dissect_parameters(tvbuff_t *, packet_info *, proto_tree *, proto_item *);
453 dissect_error_cause(tvbuff_t *, packet_info *, proto_tree *);
456 dissect_error_causes(tvbuff_t *, packet_info *, proto_tree *);
459 dissect_sctp_chunk(tvbuff_t *, packet_info *, proto_tree *, proto_tree *, gboolean);
462 dissect_sctp_packet(tvbuff_t *, packet_info *, proto_tree *);
466 #define HEARTBEAT_INFO_PARAMETER_INFO_OFFSET PARAMETER_VALUE_OFFSET
469 dissect_heartbeat_info_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
471 guint16 heartbeat_info_length;
473 heartbeat_info_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
474 if (heartbeat_info_length > 0)
475 proto_tree_add_item(parameter_tree, hf_heartbeat_info, parameter_tvb, HEARTBEAT_INFO_PARAMETER_INFO_OFFSET, heartbeat_info_length, NETWORK_BYTE_ORDER);
476 proto_item_append_text(parameter_item, " (Information: %u byte%s)", heartbeat_info_length, plurality(heartbeat_info_length, "", "s"));
479 #define IPV4_ADDRESS_LENGTH 4
480 #define IPV4_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
483 dissect_ipv4_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item, proto_item *additional_item)
485 proto_tree_add_item(parameter_tree, hf_ipv4_address, parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH, NETWORK_BYTE_ORDER);
486 proto_item_append_text(parameter_item, " (Address: %s)", ip_to_str((const guint8 *)tvb_get_ptr(parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH)));
488 proto_item_append_text(additional_item, "%s", ip_to_str((const guint8 *)tvb_get_ptr(parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH)));
491 #define IPV6_ADDRESS_LENGTH 16
492 #define IPV6_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
495 dissect_ipv6_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item, proto_item *additional_item)
497 proto_tree_add_item(parameter_tree, hf_ipv6_address, parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH, NETWORK_BYTE_ORDER);
498 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)));
500 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)));
503 #define STATE_COOKIE_PARAMETER_COOKIE_OFFSET PARAMETER_VALUE_OFFSET
506 dissect_state_cookie_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
508 guint16 state_cookie_length;
510 state_cookie_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
511 if (state_cookie_length > 0)
512 proto_tree_add_item(parameter_tree, hf_state_cookie, parameter_tvb, STATE_COOKIE_PARAMETER_COOKIE_OFFSET, state_cookie_length, NETWORK_BYTE_ORDER);
513 proto_item_append_text(parameter_item, " (Cookie length: %u byte%s)", state_cookie_length, plurality(state_cookie_length, "", "s"));
517 dissect_unrecognized_parameters_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
519 /* FIXME: Does it contain one or more parameters? */
520 dissect_parameter(tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, -1, -1), pinfo, parameter_tree, NULL);
523 #define COOKIE_PRESERVATIVE_PARAMETER_INCR_LENGTH 4
524 #define COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET PARAMETER_VALUE_OFFSET
527 dissect_cookie_preservative_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
529 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);
530 proto_item_append_text(parameter_item, " (Increment :%u msec)", tvb_get_ntohl(parameter_tvb, COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET));
533 #define HOSTNAME_OFFSET PARAMETER_VALUE_OFFSET
536 dissect_hostname_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
538 guint16 hostname_length;
540 hostname_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
541 proto_tree_add_item(parameter_tree, hf_hostname, parameter_tvb, HOSTNAME_OFFSET, hostname_length, NETWORK_BYTE_ORDER);
542 proto_item_append_text(parameter_item, " (Hostname: %.*s)", hostname_length, (const char *)tvb_get_ptr(parameter_tvb, HOSTNAME_OFFSET, hostname_length));
546 #define IPv4_ADDRESS_TYPE 5
547 #define IPv6_ADDRESS_TYPE 6
548 #define HOSTNAME_ADDRESS_TYPE 11
550 static const value_string address_types_values[] = {
551 { IPv4_ADDRESS_TYPE, "IPv4 address" },
552 { IPv6_ADDRESS_TYPE, "IPv6 address" },
553 { HOSTNAME_ADDRESS_TYPE, "Hostname address" },
557 #define SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH 2
560 dissect_supported_address_types_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
562 guint16 address_type, number_of_address_types, address_type_number;
565 number_of_address_types = (tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH)
566 / SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH;
568 offset = PARAMETER_VALUE_OFFSET;
569 proto_item_append_text(parameter_item, " (Supported types: ");
570 for(address_type_number = 1; address_type_number <= number_of_address_types; address_type_number++) {
571 proto_tree_add_item(parameter_tree, hf_supported_address_type, parameter_tvb, offset, SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH, NETWORK_BYTE_ORDER);
572 address_type = tvb_get_ntohs(parameter_tvb, offset);
573 switch (address_type) {
574 case IPv4_ADDRESS_TYPE:
575 proto_item_append_text(parameter_item, "IPv4");
577 case IPv6_ADDRESS_TYPE:
578 proto_item_append_text(parameter_item, "IPv6");
580 case HOSTNAME_ADDRESS_TYPE:
581 proto_item_append_text(parameter_item, "hostname");
584 proto_item_append_text(parameter_item, "%u", address_type);
586 if (address_type_number < number_of_address_types)
587 proto_item_append_text(parameter_item, ", ");
588 offset += SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH;
590 proto_item_append_text(parameter_item, ")");
594 dissect_ecn_parameter(tvbuff_t *parameter_tvb _U_)
599 dissect_forward_tsn_supported_parameter(tvbuff_t *parameter_tvb _U_)
603 #define CORRELATION_ID_LENGTH 4
604 #define CORRELATION_ID_OFFSET PARAMETER_VALUE_OFFSET
605 #define ADDRESS_PARAMETER_OFFSET (CORRELATION_ID_OFFSET + CORRELATION_ID_LENGTH)
608 dissect_add_ip_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
610 guint16 address_length;
611 tvbuff_t *address_tvb;
613 address_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
615 proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
616 address_tvb = tvb_new_subset(parameter_tvb, ADDRESS_PARAMETER_OFFSET, address_length, address_length);
617 proto_item_append_text(parameter_item, " (Address: ");
618 dissect_parameter(address_tvb, pinfo, parameter_tree, parameter_item);
619 proto_item_append_text(parameter_item, ", correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
623 dissect_del_ip_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
625 guint16 address_length;
626 tvbuff_t *address_tvb;
628 address_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
630 proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
631 address_tvb = tvb_new_subset(parameter_tvb, ADDRESS_PARAMETER_OFFSET, address_length, address_length);
632 proto_item_append_text(parameter_item, " (Address: ");
633 dissect_parameter(address_tvb, pinfo, parameter_tree, parameter_item);
634 proto_item_append_text(parameter_item, ", correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
637 #define ERROR_CAUSE_IND_CASUES_OFFSET (CORRELATION_ID_OFFSET + CORRELATION_ID_LENGTH)
640 dissect_error_cause_indication_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
642 guint16 causes_length;
643 tvbuff_t *causes_tvb;
645 proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
646 causes_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
647 causes_tvb = tvb_new_subset(parameter_tvb, ERROR_CAUSE_IND_CASUES_OFFSET, causes_length, causes_length);
648 dissect_error_causes(causes_tvb, pinfo, parameter_tree);
652 dissect_set_primary_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
654 guint16 address_length;
655 tvbuff_t *address_tvb;
657 address_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
659 proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
660 address_tvb = tvb_new_subset(parameter_tvb, ADDRESS_PARAMETER_OFFSET, address_length, address_length);
661 proto_item_append_text(parameter_item, " (Address: ");
662 dissect_parameter(address_tvb, pinfo, parameter_tree, parameter_item);
663 proto_item_append_text(parameter_item, ", correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
667 dissect_success_report_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
669 proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
670 proto_item_append_text(parameter_item, " (Correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
673 #define ADAP_INDICATION_LENGTH 4
674 #define ADAP_INDICATION_OFFSET PARAMETER_VALUE_OFFSET
677 dissect_adap_indication_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
679 proto_tree_add_item(parameter_tree, hf_adap_indication, parameter_tvb, ADAP_INDICATION_OFFSET, ADAP_INDICATION_LENGTH, NETWORK_BYTE_ORDER);
680 proto_item_append_text(parameter_item, " (Indication: %u)", tvb_get_ntohl(parameter_tvb, ADAP_INDICATION_OFFSET));
684 dissect_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
686 guint16 type, parameter_value_length;
688 type = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
689 parameter_value_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
691 if (parameter_value_length > 0)
692 proto_tree_add_item(parameter_tree, hf_parameter_value, parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length, NETWORK_BYTE_ORDER);
694 proto_item_append_text(parameter_item, " (Type %u, value length: %u byte%s)", type, parameter_value_length, plurality(parameter_value_length, "", "s"));
697 #define HEARTBEAT_INFO_PARAMETER_ID 0x0001
698 #define IPV4ADDRESS_PARAMETER_ID 0x0005
699 #define IPV6ADDRESS_PARAMETER_ID 0x0006
700 #define STATE_COOKIE_PARAMETER_ID 0x0007
701 #define UNREC_PARA_PARAMETER_ID 0x0008
702 #define COOKIE_PRESERVATIVE_PARAMETER_ID 0x0009
703 #define HOSTNAME_ADDRESS_PARAMETER_ID 0x000b
704 #define SUPPORTED_ADDRESS_TYPES_PARAMETER_ID 0x000c
705 #define ECN_PARAMETER_ID 0x8000
706 #define FORWARD_TSN_SUPPORTED_PARAMETER_ID 0xC000
707 #define ADD_IP_ADDRESS_PARAMETER_ID 0xC001
708 #define DEL_IP_ADDRESS_PARAMETER_ID 0xC002
709 #define ERROR_CAUSE_INDICATION_PARAMETER_ID 0xC003
710 #define SET_PRIMARY_ADDRESS_PARAMETER_ID 0xC004
711 #define SUCCESS_REPORT_PARAMETER_ID 0xC005
712 #define ADAP_LAYER_INDICATION_PARAMETER_ID 0xC006
714 static const value_string parameter_identifier_values[] = {
715 { HEARTBEAT_INFO_PARAMETER_ID, "Heartbeat info" },
716 { IPV4ADDRESS_PARAMETER_ID, "IPv4 address" },
717 { IPV6ADDRESS_PARAMETER_ID, "IPv6 address" },
718 { STATE_COOKIE_PARAMETER_ID, "State cookie" },
719 { UNREC_PARA_PARAMETER_ID, "Unrecognized parameter" },
720 { COOKIE_PRESERVATIVE_PARAMETER_ID, "Cookie preservative" },
721 { HOSTNAME_ADDRESS_PARAMETER_ID, "Hostname address" },
722 { SUPPORTED_ADDRESS_TYPES_PARAMETER_ID, "Supported address types" },
723 { ECN_PARAMETER_ID, "ECN" },
724 { FORWARD_TSN_SUPPORTED_PARAMETER_ID, "Forward TSN supported" },
725 { ADD_IP_ADDRESS_PARAMETER_ID, "Add IP address" },
726 { DEL_IP_ADDRESS_PARAMETER_ID, "Delete IP address" },
727 { ERROR_CAUSE_INDICATION_PARAMETER_ID, "Error cause indication" },
728 { SET_PRIMARY_ADDRESS_PARAMETER_ID, "Set primary address" },
729 { SUCCESS_REPORT_PARAMETER_ID, "Success report" },
730 { ADAP_LAYER_INDICATION_PARAMETER_ID, "Adaptation Layer Indication" },
733 #define SCTP_PARAMETER_BIT_1 0x8000
734 #define SCTP_PARAMETER_BIT_2 0x4000
736 static const true_false_string sctp_parameter_bit_1_value = {
737 "Skip parameter and continue prosessing of the chunk",
738 "Stop processing of chunk"
741 static const true_false_string sctp_parameter_bit_2_value = {
747 dissect_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *additional_item)
749 guint16 type, length, padding_length;
750 proto_item *parameter_item;
751 proto_tree *parameter_tree;
752 proto_item *type_item;
753 proto_tree *type_tree;
755 type = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
756 length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
757 padding_length = tvb_length(parameter_tvb) - length;;
759 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"));
760 parameter_tree = proto_item_add_subtree(parameter_item, ett_sctp_chunk_parameter);
762 type_item = proto_tree_add_item(parameter_tree, hf_parameter_type, parameter_tvb, PARAMETER_TYPE_OFFSET, PARAMETER_TYPE_LENGTH, NETWORK_BYTE_ORDER);
763 type_tree = proto_item_add_subtree(type_item, ett_sctp_parameter_type);
764 proto_tree_add_item(type_tree, hf_parameter_bit_1, parameter_tvb, PARAMETER_TYPE_OFFSET, PARAMETER_TYPE_LENGTH, NETWORK_BYTE_ORDER);
765 proto_tree_add_item(type_tree, hf_parameter_bit_2, parameter_tvb, PARAMETER_TYPE_OFFSET, PARAMETER_TYPE_LENGTH, NETWORK_BYTE_ORDER);
766 proto_tree_add_item(parameter_tree, hf_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
769 case HEARTBEAT_INFO_PARAMETER_ID:
770 dissect_heartbeat_info_parameter(parameter_tvb, parameter_tree, parameter_item);
772 case IPV4ADDRESS_PARAMETER_ID:
773 dissect_ipv4_parameter(parameter_tvb, parameter_tree, parameter_item, additional_item);
775 case IPV6ADDRESS_PARAMETER_ID:
776 dissect_ipv6_parameter(parameter_tvb, parameter_tree, parameter_item, additional_item);
778 case STATE_COOKIE_PARAMETER_ID:
779 dissect_state_cookie_parameter(parameter_tvb, parameter_tree, parameter_item);
781 case UNREC_PARA_PARAMETER_ID:
782 dissect_unrecognized_parameters_parameter(parameter_tvb, pinfo, parameter_tree);
784 case COOKIE_PRESERVATIVE_PARAMETER_ID:
785 dissect_cookie_preservative_parameter(parameter_tvb, parameter_tree, parameter_item);
787 case HOSTNAME_ADDRESS_PARAMETER_ID:
788 dissect_hostname_parameter(parameter_tvb, parameter_tree, parameter_item);
790 case SUPPORTED_ADDRESS_TYPES_PARAMETER_ID:
791 dissect_supported_address_types_parameter(parameter_tvb, parameter_tree, parameter_item);
793 case ECN_PARAMETER_ID:
794 dissect_ecn_parameter(parameter_tvb);
796 case FORWARD_TSN_SUPPORTED_PARAMETER_ID:
797 dissect_forward_tsn_supported_parameter(parameter_tvb);
799 case ADD_IP_ADDRESS_PARAMETER_ID:
800 dissect_add_ip_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
802 case DEL_IP_ADDRESS_PARAMETER_ID:
803 dissect_del_ip_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
805 case ERROR_CAUSE_INDICATION_PARAMETER_ID:
806 dissect_error_cause_indication_parameter(parameter_tvb, pinfo, parameter_tree);
808 case SET_PRIMARY_ADDRESS_PARAMETER_ID:
809 dissect_set_primary_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
811 case SUCCESS_REPORT_PARAMETER_ID:
812 dissect_success_report_parameter(parameter_tvb, parameter_tree, parameter_item);
814 case ADAP_LAYER_INDICATION_PARAMETER_ID:
815 dissect_adap_indication_parameter(parameter_tvb, parameter_tree, parameter_item);
818 dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
822 if (padding_length > 0)
823 proto_tree_add_item(parameter_tree, hf_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
827 dissect_parameters(tvbuff_t *parameters_tvb, packet_info *pinfo, proto_tree *tree, proto_item *additional_item)
829 gint offset, length, total_length, remaining_length;
830 tvbuff_t *parameter_tvb;
833 while((remaining_length = tvb_length_remaining(parameters_tvb, offset))) {
834 if ((offset > 0) && additional_item)
835 proto_item_append_text(additional_item, " ");
836 length = tvb_get_ntohs(parameters_tvb, offset + PARAMETER_LENGTH_OFFSET);
837 total_length = ADD_PADDING(length);
838 if (remaining_length >= length)
839 total_length = MIN(total_length, remaining_length);
840 /* create a tvb for the parameter including the padding bytes */
841 parameter_tvb = tvb_new_subset(parameters_tvb, offset, total_length, total_length);
842 dissect_parameter(parameter_tvb, pinfo, tree, additional_item);
843 /* get rid of the handled parameter */
844 offset += total_length;
850 * Code to handle error causes for ABORT and ERROR chunks
854 #define CAUSE_CODE_LENGTH 2
855 #define CAUSE_LENGTH_LENGTH 2
856 #define CAUSE_HEADER_LENGTH (CAUSE_CODE_LENGTH + CAUSE_LENGTH_LENGTH)
858 #define CAUSE_HEADER_OFFSET 0
859 #define CAUSE_CODE_OFFSET CAUSE_HEADER_OFFSET
860 #define CAUSE_LENGTH_OFFSET (CAUSE_CODE_OFFSET + CAUSE_CODE_LENGTH)
861 #define CAUSE_INFO_OFFSET (CAUSE_LENGTH_OFFSET + CAUSE_LENGTH_LENGTH)
864 #define CAUSE_STREAM_IDENTIFIER_LENGTH 2
865 #define CAUSE_RESERVED_LENGTH 2
866 #define CAUSE_STREAM_IDENTIFIER_OFFSET CAUSE_INFO_OFFSET
867 #define CAUSE_RESERVED_OFFSET (CAUSE_STREAM_IDENTIFIER_OFFSET + CAUSE_STREAM_IDENTIFIER_LENGTH)
870 dissect_invalid_stream_identifier_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
872 proto_tree_add_item(cause_tree, hf_cause_stream_identifier, cause_tvb, CAUSE_STREAM_IDENTIFIER_OFFSET, CAUSE_STREAM_IDENTIFIER_LENGTH, NETWORK_BYTE_ORDER);
873 proto_tree_add_item(cause_tree, hf_cause_reserved, cause_tvb, CAUSE_RESERVED_OFFSET, CAUSE_RESERVED_LENGTH, NETWORK_BYTE_ORDER);
874 proto_item_append_text(cause_item, " (SID: %u)", tvb_get_ntohs(cause_tvb, CAUSE_STREAM_IDENTIFIER_OFFSET));
877 #define CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH 4
878 #define CAUSE_MISSING_PARAMETER_TYPE_LENGTH 2
880 #define CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET CAUSE_INFO_OFFSET
881 #define CAUSE_FIRST_MISSING_PARAMETER_TYPE_OFFSET (CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET + \
882 CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH )
885 dissect_missing_mandatory_parameters_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree)
887 guint32 number_of_missing_parameters, missing_parameter_number;
890 number_of_missing_parameters = tvb_get_ntohl(cause_tvb, CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET);
891 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);
892 offset = CAUSE_FIRST_MISSING_PARAMETER_TYPE_OFFSET;
893 for(missing_parameter_number = 1; missing_parameter_number <= number_of_missing_parameters; missing_parameter_number++) {
894 proto_tree_add_item(cause_tree, hf_cause_missing_parameter_type, cause_tvb, offset, CAUSE_MISSING_PARAMETER_TYPE_LENGTH, NETWORK_BYTE_ORDER);
895 offset += CAUSE_MISSING_PARAMETER_TYPE_LENGTH;
899 #define CAUSE_MEASURE_OF_STALENESS_LENGTH 4
900 #define CAUSE_MEASURE_OF_STALENESS_OFFSET CAUSE_INFO_OFFSET
903 dissect_stale_cookie_error_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
905 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);
906 proto_item_append_text(cause_item, " (Measure: %u usec)", tvb_get_ntohl(cause_tvb, CAUSE_MEASURE_OF_STALENESS_OFFSET));
910 dissect_out_of_resource_cause(tvbuff_t *cause_tvb _U_)
915 dissect_unresolvable_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
917 guint16 parameter_length;
918 tvbuff_t *parameter_tvb;
920 parameter_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
921 parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, parameter_length, parameter_length);
922 proto_item_append_text(cause_item, " (Address: ");
923 dissect_parameter(parameter_tvb, pinfo, cause_tree, cause_item);
924 proto_item_append_text(cause_item, ")");
928 dissect_unrecognized_chunk_type_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
930 guint16 chunk_length;
931 guint8 unrecognized_type;
932 tvbuff_t *unrecognized_chunk_tvb;
934 chunk_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
935 unrecognized_chunk_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, chunk_length, chunk_length);
936 dissect_sctp_chunk(unrecognized_chunk_tvb, pinfo, cause_tree,cause_tree, FALSE);
937 unrecognized_type = tvb_get_guint8(unrecognized_chunk_tvb, CHUNK_TYPE_OFFSET);
938 proto_item_append_text(cause_item, " (Type: %u (%s))", unrecognized_type, val_to_str(unrecognized_type, chunk_type_values, "unknown"));
942 dissect_invalid_mandatory_parameter_cause(tvbuff_t *cause_tvb _U_)
947 dissect_unrecognized_parameters_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree)
949 guint16 cause_info_length;
950 tvbuff_t *unrecognized_parameters_tvb;
952 cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
954 unrecognized_parameters_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
955 dissect_parameters(unrecognized_parameters_tvb, pinfo, cause_tree, NULL);
958 #define CAUSE_TSN_LENGTH 4
959 #define CAUSE_TSN_OFFSET CAUSE_INFO_OFFSET
962 dissect_no_user_data_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
964 proto_tree_add_item(cause_tree, hf_cause_tsn, cause_tvb, CAUSE_TSN_OFFSET, CAUSE_TSN_LENGTH, NETWORK_BYTE_ORDER);
965 proto_item_append_text(cause_item, " (TSN: %u)", tvb_get_ntohl(cause_tvb, CAUSE_TSN_OFFSET));
969 dissect_cookie_received_while_shutting_down_cause(tvbuff_t *cause_tvb _U_)
974 dissect_restart_with_new_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree* cause_tree, proto_item *cause_item)
976 guint16 cause_info_length;
977 tvbuff_t *parameter_tvb;
979 cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
980 parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
981 proto_item_append_text(cause_item, " (New addresses: ");
982 dissect_parameters(parameter_tvb, pinfo, cause_tree, cause_item);
983 proto_item_append_text(cause_item, ")");
987 dissect_user_initiated_abort_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree)
989 guint16 cause_info_length;
991 cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
992 if (cause_info_length > 0)
993 proto_tree_add_item(cause_tree, hf_cause_info, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, NETWORK_BYTE_ORDER);
997 dissect_protocol_violation_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree)
999 guint16 cause_info_length;
1001 cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1002 if (cause_info_length > 0)
1003 proto_tree_add_item(cause_tree, hf_cause_info, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, NETWORK_BYTE_ORDER);
1007 dissect_delete_last_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
1009 guint16 cause_info_length;
1010 tvbuff_t *parameter_tvb;
1012 cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1013 parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1014 proto_item_append_text(cause_item, " (Last address: ");
1015 dissect_parameter(parameter_tvb, pinfo, cause_tree, cause_item);
1016 proto_item_append_text(cause_item, ")");
1020 dissect_resource_outage_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree)
1022 guint16 cause_info_length;
1023 tvbuff_t *parameter_tvb;
1025 cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1026 parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1027 dissect_parameter(parameter_tvb, pinfo, cause_tree, NULL);
1031 dissect_delete_source_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
1033 guint16 cause_info_length;
1034 tvbuff_t *parameter_tvb;
1036 cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1037 parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1038 proto_item_append_text(cause_item, " (Deleted address: ");
1039 dissect_parameter(parameter_tvb, pinfo, cause_tree, cause_item);
1040 proto_item_append_text(cause_item, ")");
1044 dissect_request_refused_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree)
1046 guint16 cause_info_length;
1047 tvbuff_t *parameter_tvb;
1049 cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1050 parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1051 dissect_parameter(parameter_tvb, pinfo, cause_tree, NULL);
1055 dissect_unknown_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
1057 guint16 cause_info_length;
1059 cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1060 if (cause_info_length > 0)
1061 proto_tree_add_item(cause_tree, hf_cause_info, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, NETWORK_BYTE_ORDER);
1062 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"));
1065 #define INVALID_STREAM_IDENTIFIER 0x01
1066 #define MISSING_MANDATORY_PARAMETERS 0x02
1067 #define STALE_COOKIE_ERROR 0x03
1068 #define OUT_OF_RESOURCE 0x04
1069 #define UNRESOLVABLE_ADDRESS 0x05
1070 #define UNRECOGNIZED_CHUNK_TYPE 0x06
1071 #define INVALID_MANDATORY_PARAMETER 0x07
1072 #define UNRECOGNIZED_PARAMETERS 0x08
1073 #define NO_USER_DATA 0x09
1074 #define COOKIE_RECEIVED_WHILE_SHUTTING_DOWN 0x0a
1075 #define RESTART_WITH_NEW_ADDRESSES 0x0b
1076 #define USER_INITIATED_ABORT 0x0c
1077 #define PROTOCOL_VIOLATION 0x0d
1078 #define REQUEST_TO_DELETE_LAST_ADDRESS 0x0100
1079 #define OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE 0X0101
1080 #define REQUEST_TO_DELETE_SOURCE_ADDRESS 0x0102
1081 #define ABORT_DUE_TO_ILLEGAL_ASCONF 0x0103
1082 #define REQUESTION_REFUSED 0x0104
1084 static const value_string cause_code_values[] = {
1085 { INVALID_STREAM_IDENTIFIER, "Invalid stream identifier" },
1086 { MISSING_MANDATORY_PARAMETERS, "Missing mandator parameter" },
1087 { STALE_COOKIE_ERROR, "Stale cookie error" },
1088 { OUT_OF_RESOURCE, "Out of resource" },
1089 { UNRESOLVABLE_ADDRESS, "Unresolvable address" },
1090 { UNRECOGNIZED_CHUNK_TYPE, "Unrecognized chunk type" },
1091 { INVALID_MANDATORY_PARAMETER, "Invalid mandatory parameter" },
1092 { UNRECOGNIZED_PARAMETERS, "Unrecognized parameters" },
1093 { NO_USER_DATA, "No user data" },
1094 { COOKIE_RECEIVED_WHILE_SHUTTING_DOWN, "Cookie received while shutting down" },
1095 { RESTART_WITH_NEW_ADDRESSES, "Restart of an association with new addresses" },
1096 { USER_INITIATED_ABORT, "User initiated ABORT" },
1097 { PROTOCOL_VIOLATION, "Protocol violation" },
1098 { REQUEST_TO_DELETE_LAST_ADDRESS, "Request to delete last address" },
1099 { OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE, "Operation refused due to resource shortage" },
1100 { REQUEST_TO_DELETE_SOURCE_ADDRESS, "Request to delete source address" },
1101 { ABORT_DUE_TO_ILLEGAL_ASCONF, "Association Aborted due to illegal ASCONF-ACK" },
1102 { REQUESTION_REFUSED, "Request refused - no authorization" },
1107 dissect_error_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *chunk_tree)
1109 guint16 code, length, padding_length;
1110 proto_item *cause_item;
1111 proto_tree *cause_tree;
1113 code = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET);
1114 length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
1115 padding_length = tvb_length(cause_tvb) - length;;
1117 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"));
1118 cause_tree = proto_item_add_subtree(cause_item, ett_sctp_chunk_cause);
1120 proto_tree_add_item(cause_tree, hf_cause_code, cause_tvb, CAUSE_CODE_OFFSET, CAUSE_CODE_LENGTH, NETWORK_BYTE_ORDER);
1121 proto_tree_add_item(cause_tree, hf_cause_length, cause_tvb, CAUSE_LENGTH_OFFSET, CAUSE_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
1124 case INVALID_STREAM_IDENTIFIER:
1125 dissect_invalid_stream_identifier_cause(cause_tvb, cause_tree, cause_item);
1127 case MISSING_MANDATORY_PARAMETERS:
1128 dissect_missing_mandatory_parameters_cause(cause_tvb, cause_tree);
1130 case STALE_COOKIE_ERROR:
1131 dissect_stale_cookie_error_cause(cause_tvb, cause_tree, cause_item);
1133 case OUT_OF_RESOURCE:
1134 dissect_out_of_resource_cause(cause_tvb);
1136 case UNRESOLVABLE_ADDRESS:
1137 dissect_unresolvable_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
1139 case UNRECOGNIZED_CHUNK_TYPE:
1140 dissect_unrecognized_chunk_type_cause(cause_tvb, pinfo, cause_tree, cause_item);
1142 case INVALID_MANDATORY_PARAMETER:
1143 dissect_invalid_mandatory_parameter_cause(cause_tvb);
1145 case UNRECOGNIZED_PARAMETERS:
1146 dissect_unrecognized_parameters_cause(cause_tvb, pinfo, cause_tree);
1149 dissect_no_user_data_cause(cause_tvb, cause_tree, cause_item);
1151 case COOKIE_RECEIVED_WHILE_SHUTTING_DOWN:
1152 dissect_cookie_received_while_shutting_down_cause(cause_tvb);
1154 case RESTART_WITH_NEW_ADDRESSES:
1155 dissect_restart_with_new_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
1157 case USER_INITIATED_ABORT:
1158 dissect_user_initiated_abort_cause(cause_tvb, cause_tree);
1160 case PROTOCOL_VIOLATION:
1161 dissect_protocol_violation_cause(cause_tvb, cause_tree);
1163 case REQUEST_TO_DELETE_LAST_ADDRESS:
1164 dissect_delete_last_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
1166 case OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE:
1167 dissect_resource_outage_cause(cause_tvb, pinfo, cause_tree);
1169 case REQUEST_TO_DELETE_SOURCE_ADDRESS:
1170 dissect_delete_source_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
1172 case REQUESTION_REFUSED:
1173 dissect_request_refused_cause(cause_tvb, pinfo, cause_tree);
1176 dissect_unknown_cause(cause_tvb, cause_tree, cause_item);
1180 if (padding_length > 0)
1181 proto_tree_add_item(cause_tree, hf_cause_padding, cause_tvb, CAUSE_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
1185 dissect_error_causes(tvbuff_t *causes_tvb, packet_info *pinfo, proto_tree *tree)
1187 gint offset, length, total_length, remaining_length;
1188 tvbuff_t *cause_tvb;
1191 while((remaining_length = tvb_length_remaining(causes_tvb, offset))) {
1192 length = tvb_get_ntohs(causes_tvb, offset + CAUSE_LENGTH_OFFSET);
1193 total_length = ADD_PADDING(length);
1194 if (remaining_length >= length)
1195 total_length = MIN(total_length, remaining_length);
1196 /* create a tvb for the parameter including the padding bytes */
1197 cause_tvb = tvb_new_subset(causes_tvb, offset, total_length, total_length);
1198 dissect_error_cause(cause_tvb, pinfo, tree);
1199 /* get rid of the handled cause */
1200 offset += total_length;
1206 * Code to actually dissect the packets
1210 dissect_payload(tvbuff_t *payload_tvb, packet_info *pinfo, proto_tree *tree, guint32 ppi)
1212 guint32 low_port, high_port;
1214 /* Do lookups with the subdissector table.
1216 When trying port numbers, we try the port number with the lower value
1217 first, followed by the port number with the higher value. This means
1218 that, for packets where a dissector is registered for *both* port
1219 numbers, and where there's no match on the PPI:
1221 1) we pick the same dissector for traffic going in both directions;
1223 2) we prefer the port number that's more likely to be the right
1224 one (as that prefers well-known ports to reserved ports);
1226 although there is, of course, no guarantee that any such strategy
1227 will always pick the right port number.
1229 XXX - we ignore port numbers of 0, as some dissectors use a port
1230 number of 0 to disable the port. */
1231 if (dissector_try_port(sctp_ppi_dissector_table, ppi, payload_tvb, pinfo, tree))
1233 if (pinfo->srcport > pinfo->destport) {
1234 low_port = pinfo->destport;
1235 high_port = pinfo->srcport;
1237 low_port = pinfo->srcport;
1238 high_port = pinfo->destport;
1240 if (low_port != 0 &&
1241 dissector_try_port(sctp_port_dissector_table, low_port, payload_tvb, pinfo, tree))
1243 if (high_port != 0 &&
1244 dissector_try_port(sctp_port_dissector_table, high_port, payload_tvb, pinfo, tree))
1247 call_dissector(data_handle, payload_tvb, pinfo, tree);
1251 #define DATA_CHUNK_TSN_LENGTH 4
1252 #define DATA_CHUNK_STREAM_ID_LENGTH 2
1253 #define DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH 2
1254 #define DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH 4
1256 #define DATA_CHUNK_TSN_OFFSET (CHUNK_VALUE_OFFSET + 0)
1257 #define DATA_CHUNK_STREAM_ID_OFFSET (DATA_CHUNK_TSN_OFFSET + DATA_CHUNK_TSN_LENGTH)
1258 #define DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET (DATA_CHUNK_STREAM_ID_OFFSET + \
1259 DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH)
1260 #define DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET (DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET + \
1261 DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH)
1262 #define DATA_CHUNK_PAYLOAD_OFFSET (DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET + \
1263 DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH)
1265 #define DATA_CHUNK_HEADER_LENGTH (CHUNK_HEADER_LENGTH + \
1266 DATA_CHUNK_TSN_LENGTH + \
1267 DATA_CHUNK_STREAM_ID_LENGTH + \
1268 DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH + \
1269 DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH)
1271 #define SCTP_DATA_CHUNK_E_BIT 0x01
1272 #define SCTP_DATA_CHUNK_B_BIT 0x02
1273 #define SCTP_DATA_CHUNK_U_BIT 0x04
1275 static const true_false_string sctp_data_chunk_e_bit_value = {
1277 "Not the last segment"
1280 static const true_false_string sctp_data_chunk_b_bit_value = {
1282 "Subsequent segment"
1285 static const true_false_string sctp_data_chunk_u_bit_value = {
1286 "Unordered delivery",
1291 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)
1293 guint16 payload_length;
1294 guint32 payload_proto_id;
1295 tvbuff_t *payload_tvb;
1296 proto_tree *flags_tree;
1297 guint8 e_bit, b_bit, u_bit;
1299 payload_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - DATA_CHUNK_HEADER_LENGTH;
1300 payload_tvb = tvb_new_subset(chunk_tvb, DATA_CHUNK_PAYLOAD_OFFSET, payload_length, payload_length);
1301 payload_proto_id = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET);
1304 flags_tree = proto_item_add_subtree(flags_item, ett_sctp_data_chunk_flags);
1305 proto_tree_add_item(flags_tree, hf_data_chunk_e_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
1306 proto_tree_add_item(flags_tree, hf_data_chunk_b_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
1307 proto_tree_add_item(flags_tree, hf_data_chunk_u_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
1308 proto_tree_add_item(chunk_tree, hf_data_chunk_tsn, chunk_tvb, DATA_CHUNK_TSN_OFFSET, DATA_CHUNK_TSN_LENGTH, NETWORK_BYTE_ORDER);
1309 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);
1310 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);
1311 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);
1313 e_bit = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_DATA_CHUNK_E_BIT;
1314 b_bit = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_DATA_CHUNK_B_BIT;
1315 u_bit = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_DATA_CHUNK_U_BIT;
1317 proto_item_append_text(chunk_item, "(%s, ", (u_bit) ? "unordered" : "ordered");
1320 proto_item_append_text(chunk_item, "complete");
1322 proto_item_append_text(chunk_item, "first");
1325 proto_item_append_text(chunk_item, "last");
1327 proto_item_append_text(chunk_item, "middle");
1330 proto_item_append_text(chunk_item, " segment, TSN: %u, SID: %u, SSN: %u, PPID: %u, payload length: %u byte%s)",
1331 tvb_get_ntohl(chunk_tvb, DATA_CHUNK_TSN_OFFSET),
1332 tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET),
1333 tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET),
1335 payload_length, plurality(payload_length, "", "s"));
1336 proto_item_set_len(chunk_item, DATA_CHUNK_HEADER_LENGTH);
1339 return dissect_payload(payload_tvb, pinfo, tree, payload_proto_id);
1342 #define INIT_CHUNK_INITIATE_TAG_LENGTH 4
1343 #define INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH 4
1344 #define INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH 2
1345 #define INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH 2
1346 #define INIT_CHUNK_INITIAL_TSN_LENGTH 4
1347 #define INIT_CHUNK_FIXED_PARAMTERS_LENGTH (INIT_CHUNK_INITIATE_TAG_LENGTH + \
1348 INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH + \
1349 INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH + \
1350 INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH + \
1351 INIT_CHUNK_INITIAL_TSN_LENGTH)
1353 #define INIT_CHUNK_INITIATE_TAG_OFFSET CHUNK_VALUE_OFFSET
1354 #define INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET (INIT_CHUNK_INITIATE_TAG_OFFSET + \
1355 INIT_CHUNK_INITIATE_TAG_LENGTH )
1356 #define INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET (INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET + \
1357 INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH )
1358 #define INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET (INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET + \
1359 INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH )
1360 #define INIT_CHUNK_INITIAL_TSN_OFFSET (INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET + \
1361 INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH )
1362 #define INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET (INIT_CHUNK_INITIAL_TSN_OFFSET + \
1363 INIT_CHUNK_INITIAL_TSN_LENGTH )
1366 dissect_init_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
1368 gint parameters_length;
1369 tvbuff_t *parameters_tvb;
1372 /* handle fixed parameters */
1373 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);
1374 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);
1375 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);
1376 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);
1377 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);
1379 /* handle variable paramters */
1380 parameters_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - INIT_CHUNK_FIXED_PARAMTERS_LENGTH - CHUNK_HEADER_LENGTH;
1381 parameters_tvb = tvb_new_subset(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET, parameters_length, parameters_length);
1382 dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL);
1384 proto_item_append_text(chunk_item, " (Outbound streams: %u, inbound streams: %u)",
1385 tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET),
1386 tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET));
1391 dissect_init_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
1393 gint parameters_length;
1394 tvbuff_t *parameters_tvb;
1397 /* handle fixed parameters */
1398 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);
1399 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);
1400 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);
1401 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);
1402 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);
1404 /* handle variable paramters */
1405 parameters_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - INIT_CHUNK_FIXED_PARAMTERS_LENGTH - CHUNK_HEADER_LENGTH;
1406 parameters_tvb = tvb_new_subset(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET, parameters_length, parameters_length);
1407 dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL);
1409 proto_item_append_text(chunk_item, " (Outbound streams: %u, inbound streams: %u)",
1410 tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET),
1411 tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET));
1415 #define SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH 4
1416 #define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH 4
1417 #define SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH 2
1418 #define SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH 2
1419 #define SACK_CHUNK_GAP_BLOCK_LENGTH 4
1420 #define SACK_CHUNK_GAP_BLOCK_START_LENGTH 2
1421 #define SACK_CHUNK_GAP_BLOCK_END_LENGTH 2
1422 #define SACK_CHUNK_DUP_TSN_LENGTH 4
1424 #define SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET (CHUNK_VALUE_OFFSET + 0)
1425 #define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET (SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET + \
1426 SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH)
1427 #define SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET (SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET + \
1428 SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH)
1429 #define SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET (SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET + \
1430 SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH)
1431 #define SACK_CHUNK_GAP_BLOCK_OFFSET (SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET + \
1432 SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH)
1436 dissect_sack_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
1438 guint16 number_of_gap_blocks, number_of_dup_tsns;
1439 guint16 gap_block_number, dup_tsn_number, start, end;
1440 gint gap_block_offset, dup_tsn_offset;
1441 guint32 cum_tsn_ack;
1442 proto_item *block_item;
1443 proto_tree *block_tree;
1446 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);
1447 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);
1448 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);
1449 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);
1451 /* handle the gap acknowledgement blocks */
1452 number_of_gap_blocks = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET);
1453 gap_block_offset = SACK_CHUNK_GAP_BLOCK_OFFSET;
1454 cum_tsn_ack = tvb_get_ntohl(chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
1455 for(gap_block_number = 1; gap_block_number <= number_of_gap_blocks; gap_block_number++) {
1456 start = tvb_get_ntohs(chunk_tvb, gap_block_offset);
1457 end = tvb_get_ntohs(chunk_tvb, gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH);
1458 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);
1459 block_tree = proto_item_add_subtree(block_item, ett_sctp_sack_chunk_gap_block);
1460 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);
1461 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);
1462 gap_block_offset += SACK_CHUNK_GAP_BLOCK_LENGTH;
1465 /* handle the duplicate TSNs */
1466 number_of_dup_tsns = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET);
1467 dup_tsn_offset = SACK_CHUNK_GAP_BLOCK_OFFSET + number_of_gap_blocks * SACK_CHUNK_GAP_BLOCK_LENGTH;
1468 for(dup_tsn_number = 1; dup_tsn_number <= number_of_dup_tsns; dup_tsn_number++) {
1469 proto_tree_add_item(chunk_tree, hf_sack_chunk_duplicate_tsn, chunk_tvb, dup_tsn_offset, SACK_CHUNK_DUP_TSN_LENGTH, NETWORK_BYTE_ORDER);
1470 dup_tsn_offset += SACK_CHUNK_DUP_TSN_LENGTH;
1473 proto_item_append_text(chunk_item, " (Cumulative TSN: %u, a_rwnd: %u, gaps: %u, duplicate TSNs: %u)",
1474 tvb_get_ntohl(chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET),
1475 tvb_get_ntohl(chunk_tvb, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET),
1476 number_of_gap_blocks, number_of_dup_tsns);
1480 #define HEARTBEAT_CHUNK_INFO_OFFSET CHUNK_VALUE_OFFSET
1483 dissect_heartbeat_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
1485 tvbuff_t *parameter_tvb;
1489 info_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
1490 proto_item_append_text(chunk_item, " (Information: %u byte%s)", info_length, plurality(info_length, "", "s"));
1491 parameter_tvb = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, info_length, info_length);
1492 /* FIXME: Parameters or parameter? */
1493 dissect_parameter(parameter_tvb, pinfo, chunk_tree, NULL);
1498 dissect_heartbeat_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
1500 tvbuff_t *parameter_tvb;
1504 info_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
1505 proto_item_append_text(chunk_item, " (Information: %u byte%s)", info_length, plurality(info_length, "", "s"));
1506 parameter_tvb = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, info_length, info_length);
1507 /* FIXME: Parameters or parameter? */
1508 dissect_parameter(parameter_tvb, pinfo, chunk_tree, NULL);
1511 #define ABORT_CHUNK_FIRST_ERROR_CAUSE_OFFSET 4
1514 dissect_abort_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *flags_item)
1516 guint16 causes_length;
1517 tvbuff_t *causes_tvb;
1518 proto_tree *flags_tree;
1521 flags_tree = proto_item_add_subtree(flags_item, ett_sctp_abort_chunk_flags);
1522 proto_tree_add_item(flags_tree, hf_abort_chunk_t_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
1524 causes_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
1525 causes_tvb = tvb_new_subset(chunk_tvb, CHUNK_VALUE_OFFSET, causes_length, causes_length);
1526 dissect_error_causes(causes_tvb, pinfo, chunk_tree);
1530 #define SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET CHUNK_VALUE_OFFSET
1531 #define SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_LENGTH 4
1534 dissect_shutdown_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
1537 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);
1538 proto_item_append_text(chunk_item, " (Cumulative TSN ack: %u)", tvb_get_ntohl(chunk_tvb, SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET));
1543 dissect_shutdown_ack_chunk(tvbuff_t *chunk_tvb _U_)
1547 #define ERROR_CAUSE_IND_CAUSES_OFFSET CHUNK_VALUE_OFFSET
1550 dissect_error_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree)
1552 guint16 causes_length;
1553 tvbuff_t *causes_tvb;
1556 causes_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
1557 causes_tvb = tvb_new_subset(chunk_tvb, ERROR_CAUSE_IND_CAUSES_OFFSET, causes_length, causes_length);
1558 dissect_error_causes(causes_tvb, pinfo, chunk_tree);
1562 #define COOKIE_OFFSET CHUNK_VALUE_OFFSET
1565 dissect_cookie_echo_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
1567 guint cookie_length;
1570 cookie_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
1571 proto_tree_add_item(chunk_tree, hf_cookie, chunk_tvb, COOKIE_OFFSET, cookie_length, NETWORK_BYTE_ORDER);
1572 proto_item_append_text(chunk_item, " (Cookie length: %u byte%s)", cookie_length, plurality(cookie_length, "", "s"));
1577 dissect_cookie_ack_chunk(tvbuff_t *chunk_tvb _U_)
1581 #define ECNE_CHUNK_LOWEST_TSN_OFFSET CHUNK_VALUE_OFFSET
1582 #define ECNE_CHUNK_LOWEST_TSN_LENGTH 4
1585 dissect_ecne_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
1588 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);
1589 proto_item_append_text(chunk_item, " (Lowest TSN: %u)", tvb_get_ntohl(chunk_tvb, ECNE_CHUNK_LOWEST_TSN_OFFSET));
1592 #define CWR_CHUNK_LOWEST_TSN_OFFSET CHUNK_VALUE_OFFSET
1593 #define CWR_CHUNK_LOWEST_TSN_LENGTH 4
1596 dissect_cwr_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
1599 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);
1600 proto_item_append_text(chunk_item, " (Lowest TSN: %u)", tvb_get_ntohl(chunk_tvb, CWR_CHUNK_LOWEST_TSN_OFFSET));
1603 #define SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT 0x01
1606 static const true_false_string sctp_shutdown_complete_chunk_t_bit_value = {
1613 dissect_shutdown_complete_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *flags_item)
1615 proto_tree *flags_tree;
1618 flags_tree = proto_item_add_subtree(flags_item, ett_sctp_shutdown_complete_chunk_flags);
1619 proto_tree_add_item(flags_tree, hf_shutdown_complete_chunk_t_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
1623 #define FORWARD_TSN_CHUNK_TSN_LENGTH 4
1624 #define FORWARD_TSN_CHUNK_SID_LENGTH 2
1625 #define FORWARD_TSN_CHUNK_SSN_LENGTH 2
1626 #define FORWARD_TSN_CHUNK_TSN_OFFSET CHUNK_VALUE_OFFSET
1627 #define FORWARD_TSN_CHUNK_SID_OFFSET 0
1628 #define FORWARD_TSN_CHUNK_SSN_OFFSET (FORWARD_TSN_CHUNK_SID_OFFSET + FORWARD_TSN_CHUNK_SID_LENGTH)
1631 dissect_forward_tsn_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
1634 guint16 number_of_affected_streams, affected_stream, length;
1637 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);
1638 length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1639 number_of_affected_streams = (length - CHUNK_HEADER_LENGTH - FORWARD_TSN_CHUNK_TSN_LENGTH) /
1640 (FORWARD_TSN_CHUNK_SID_LENGTH + FORWARD_TSN_CHUNK_SSN_LENGTH);
1641 offset = CHUNK_VALUE_OFFSET + FORWARD_TSN_CHUNK_TSN_LENGTH;
1643 for(affected_stream = 0; affected_stream < number_of_affected_streams; affected_stream++) {
1644 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);
1645 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);
1646 offset = offset + (FORWARD_TSN_CHUNK_SID_LENGTH + FORWARD_TSN_CHUNK_SSN_LENGTH);
1648 proto_item_append_text(chunk_item, "(Cumulative TSN: %u)", tvb_get_ntohl(chunk_tvb, FORWARD_TSN_CHUNK_TSN_OFFSET));
1652 #define SERIAL_NUMBER_LENGTH 4
1653 #define SERIAL_NUMBER_OFFSET PARAMETER_VALUE_OFFSET
1654 #define ASCONF_CHUNK_PARAMETERS_OFFSET (SERIAL_NUMBER_OFFSET + SERIAL_NUMBER_LENGTH)
1657 dissect_asconf_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree)
1659 guint parameters_length;
1660 tvbuff_t *parameters_tvb;
1663 proto_tree_add_item(chunk_tree, hf_asconf_serial, chunk_tvb, SERIAL_NUMBER_OFFSET, SERIAL_NUMBER_LENGTH, NETWORK_BYTE_ORDER);
1664 parameters_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH - SERIAL_NUMBER_LENGTH;
1665 parameters_tvb = tvb_new_subset(chunk_tvb, ASCONF_CHUNK_PARAMETERS_OFFSET, parameters_length, parameters_length);
1666 dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL);
1670 #define ASCONF_ACK_CHUNK_PARAMETERS_OFFSET (SERIAL_NUMBER_OFFSET + SERIAL_NUMBER_LENGTH)
1673 dissect_asconf_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree)
1675 guint parameters_length;
1676 tvbuff_t *parameters_tvb;
1679 proto_tree_add_item(chunk_tree, hf_asconf_ack_serial, chunk_tvb, SERIAL_NUMBER_OFFSET, SERIAL_NUMBER_LENGTH, NETWORK_BYTE_ORDER);
1680 parameters_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH - SERIAL_NUMBER_LENGTH;
1681 parameters_tvb = tvb_new_subset(chunk_tvb, ASCONF_ACK_CHUNK_PARAMETERS_OFFSET, parameters_length, parameters_length);
1682 dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL);
1686 #define PKTDROP_CHUNK_BANDWIDTH_LENGTH 4
1687 #define PKTDROP_CHUNK_QUEUESIZE_LENGTH 4
1688 #define PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH 2
1689 #define PKTDROP_CHUNK_RESERVED_SIZE_LENGTH 2
1691 #define PKTDROP_CHUNK_HEADER_LENGTH (CHUNK_HEADER_LENGTH + \
1692 PKTDROP_CHUNK_BANDWIDTH_LENGTH + \
1693 PKTDROP_CHUNK_QUEUESIZE_LENGTH + \
1694 PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH + \
1695 PKTDROP_CHUNK_RESERVED_SIZE_LENGTH)
1697 #define PKTDROP_CHUNK_BANDWIDTH_OFFSET CHUNK_VALUE_OFFSET
1698 #define PKTDROP_CHUNK_QUEUESIZE_OFFSET (PKTDROP_CHUNK_BANDWIDTH_OFFSET + PKTDROP_CHUNK_BANDWIDTH_LENGTH)
1699 #define PKTDROP_CHUNK_TRUNCATED_SIZE_OFFSET (PKTDROP_CHUNK_QUEUESIZE_OFFSET + PKTDROP_CHUNK_QUEUESIZE_LENGTH)
1700 #define PKTDROP_CHUNK_RESERVED_SIZE_OFFSET (PKTDROP_CHUNK_TRUNCATED_SIZE_OFFSET + PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH)
1701 #define PKTDROP_CHUNK_DATA_FIELD_OFFSET (PKTDROP_CHUNK_RESERVED_SIZE_OFFSET + PKTDROP_CHUNK_RESERVED_SIZE_LENGTH)
1703 #define SCTP_PKTDROP_CHUNK_M_BIT 0x01
1705 #define SCTP_PKTDROP_CHUNK_S_BIT 0x02
1707 #define SCTP_PKTDROP_CHUNK_B_BIT 0x04
1708 #define SCTP_PKTDROP_CHUNK_T_BIT 0x08
1710 static const true_false_string sctp_pktdropk_m_bit_value = {
1711 "Source is a middlebox",
1712 "Source is an endhost"
1716 static const true_false_string sctp_pktdropk_s_bit_value = {
1717 "This is a summary",
1718 "This is not a summary"
1722 static const true_false_string sctp_pktdropk_b_bit_value = {
1723 "SCTP checksum was incorrect",
1724 "SCTP checksum was correct"
1727 static const true_false_string sctp_pktdropk_t_bit_value = {
1728 "Packet is truncated",
1729 "Packet is not truncated"
1733 dissect_pktdrop_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *flags_item)
1735 guint16 data_field_length;
1736 tvbuff_t *data_field_tvb;
1737 proto_tree *flags_tree;
1739 data_field_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - PKTDROP_CHUNK_HEADER_LENGTH;
1740 data_field_tvb = tvb_new_subset(chunk_tvb, PKTDROP_CHUNK_DATA_FIELD_OFFSET, data_field_length, data_field_length);
1743 flags_tree = proto_item_add_subtree(flags_item, ett_sctp_pktdrop_chunk_flags);
1745 proto_tree_add_item(flags_tree, hf_pktdrop_chunk_m_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
1747 proto_tree_add_item(flags_tree, hf_pktdrop_chunk_s_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
1749 proto_tree_add_item(flags_tree, hf_pktdrop_chunk_b_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
1750 proto_tree_add_item(flags_tree, hf_pktdrop_chunk_t_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
1751 proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_bandwidth, chunk_tvb, PKTDROP_CHUNK_BANDWIDTH_OFFSET, PKTDROP_CHUNK_BANDWIDTH_LENGTH, NETWORK_BYTE_ORDER);
1752 proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_queuesize, chunk_tvb, PKTDROP_CHUNK_QUEUESIZE_OFFSET, PKTDROP_CHUNK_QUEUESIZE_LENGTH, NETWORK_BYTE_ORDER);
1753 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);
1754 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);
1755 if (tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_PKTDROP_CHUNK_T_BIT)
1756 proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_data_field, chunk_tvb, PKTDROP_CHUNK_DATA_FIELD_OFFSET, data_field_length, NETWORK_BYTE_ORDER);
1758 dissect_sctp_packet(data_field_tvb, pinfo, chunk_tree);
1763 dissect_unknown_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
1765 guint chunk_value_length;
1768 chunk_value_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
1769 if (chunk_value_length > 0)
1770 proto_tree_add_item(chunk_tree, hf_chunk_value, chunk_tvb, CHUNK_VALUE_OFFSET, chunk_value_length, NETWORK_BYTE_ORDER);
1771 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"));
1775 #define SCTP_CHUNK_BIT_1 0x80
1776 #define SCTP_CHUNK_BIT_2 0x40
1778 static const true_false_string sctp_chunk_bit_1_value = {
1779 "Skip chunk and continue prosessing of the packet",
1780 "Stop processing of the packet"
1783 static const true_false_string sctp_chunk_bit_2_value = {
1790 dissect_sctp_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *sctp_tree, gboolean useinfo)
1793 guint16 length, padding_length;
1795 proto_item *flags_item;
1796 proto_item *chunk_item;
1797 proto_tree *chunk_tree;
1798 proto_item *type_item;
1799 proto_tree *type_tree;
1803 /* first extract the chunk header */
1804 type = tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET);
1805 flags = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
1806 length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1807 padding_length = tvb_length(chunk_tvb) - length;;
1809 if (useinfo && (check_col(pinfo->cinfo, COL_INFO)))
1810 col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(type, chunk_type_values, "RESERVED"));
1813 /* create proto_tree stuff */
1814 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"));
1815 chunk_tree = proto_item_add_subtree(chunk_item, ett_sctp_chunk);
1817 /* then insert the chunk header components into the protocol tree */
1818 type_item = proto_tree_add_item(chunk_tree, hf_chunk_type, chunk_tvb, CHUNK_TYPE_OFFSET, CHUNK_TYPE_LENGTH, NETWORK_BYTE_ORDER);
1819 type_tree = proto_item_add_subtree(type_item, ett_sctp_chunk_type);
1820 proto_tree_add_item(type_tree, hf_chunk_bit_1, chunk_tvb, CHUNK_TYPE_OFFSET, CHUNK_TYPE_LENGTH, NETWORK_BYTE_ORDER);
1821 proto_tree_add_item(type_tree, hf_chunk_bit_2, chunk_tvb, CHUNK_TYPE_OFFSET, CHUNK_TYPE_LENGTH, NETWORK_BYTE_ORDER);
1822 flags_item = proto_tree_add_item(chunk_tree, hf_chunk_flags, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
1823 proto_tree_add_item(chunk_tree, hf_chunk_length, chunk_tvb, CHUNK_LENGTH_OFFSET, CHUNK_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
1830 /* now dissect the chunk value */
1833 case SCTP_DATA_CHUNK_ID:
1834 result = dissect_data_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1836 case SCTP_INIT_CHUNK_ID:
1837 dissect_init_chunk(chunk_tvb, pinfo, chunk_tree, chunk_item);
1839 case SCTP_INIT_ACK_CHUNK_ID:
1840 dissect_init_ack_chunk(chunk_tvb, pinfo, chunk_tree, chunk_item);
1842 case SCTP_SACK_CHUNK_ID:
1843 dissect_sack_chunk(chunk_tvb, chunk_tree, chunk_item);
1845 case SCTP_HEARTBEAT_CHUNK_ID:
1846 dissect_heartbeat_chunk(chunk_tvb, pinfo, chunk_tree, chunk_item);
1848 case SCTP_HEARTBEAT_ACK_CHUNK_ID:
1849 dissect_heartbeat_ack_chunk(chunk_tvb, pinfo, chunk_tree, chunk_item);
1851 case SCTP_ABORT_CHUNK_ID:
1852 dissect_abort_chunk(chunk_tvb, pinfo, chunk_tree, flags_item);
1854 case SCTP_SHUTDOWN_CHUNK_ID:
1855 dissect_shutdown_chunk(chunk_tvb, chunk_tree, chunk_item);
1857 case SCTP_SHUTDOWN_ACK_CHUNK_ID:
1858 dissect_shutdown_ack_chunk(chunk_tvb);
1860 case SCTP_ERROR_CHUNK_ID:
1861 dissect_error_chunk(chunk_tvb, pinfo, chunk_tree);
1863 case SCTP_COOKIE_ECHO_CHUNK_ID:
1864 dissect_cookie_echo_chunk(chunk_tvb, chunk_tree, chunk_item);
1866 case SCTP_COOKIE_ACK_CHUNK_ID:
1867 dissect_cookie_ack_chunk(chunk_tvb);
1869 case SCTP_ECNE_CHUNK_ID:
1870 dissect_ecne_chunk(chunk_tvb, chunk_tree, chunk_item);
1872 case SCTP_CWR_CHUNK_ID:
1873 dissect_cwr_chunk(chunk_tvb, chunk_tree, chunk_item);
1875 case SCTP_SHUTDOWN_COMPLETE_CHUNK_ID:
1876 dissect_shutdown_complete_chunk(chunk_tvb, chunk_tree, flags_item);
1878 case SCTP_FORWARD_TSN_CHUNK_ID:
1879 dissect_forward_tsn_chunk(chunk_tvb, chunk_tree, chunk_item);
1881 case SCTP_ASCONF_ACK_CHUNK_ID:
1882 dissect_asconf_ack_chunk(chunk_tvb, pinfo, chunk_tree);
1884 case SCTP_ASCONF_CHUNK_ID:
1885 dissect_asconf_chunk(chunk_tvb, pinfo, chunk_tree);
1887 case SCTP_PKTDROP_CHUNK_ID:
1888 dissect_pktdrop_chunk(chunk_tvb, pinfo, chunk_tree, flags_item);
1891 dissect_unknown_chunk(chunk_tvb, chunk_tree, chunk_item);
1895 if (padding_length > 0)
1896 proto_tree_add_item(chunk_tree, hf_chunk_padding, chunk_tvb, CHUNK_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
1898 if (useinfo && ((type == SCTP_DATA_CHUNK_ID) || show_always_control_chunks))
1899 col_set_fence(pinfo->cinfo, COL_INFO);
1905 dissect_sctp_chunks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *sctp_item, proto_tree *sctp_tree)
1907 tvbuff_t *chunk_tvb;
1908 guint16 length, total_length, remaining_length;
1909 gint last_offset, offset;
1910 gboolean sctp_item_length_set;
1912 /* the common header of the datagram is already handled */
1914 offset = COMMON_HEADER_LENGTH;
1915 sctp_item_length_set = FALSE;
1917 while((remaining_length = tvb_length_remaining(tvb, offset))) {
1918 /* extract the chunk length and compute number of padding bytes */
1919 length = tvb_get_ntohs(tvb, offset + CHUNK_LENGTH_OFFSET);
1920 total_length = ADD_PADDING(length);
1921 if (remaining_length >= length)
1922 total_length = MIN(total_length, remaining_length);
1923 /* create a tvb for the chunk including the padding bytes */
1924 chunk_tvb = tvb_new_subset(tvb, offset, total_length, total_length);
1925 /* call dissect_sctp_chunk for a actual work */
1926 if (dissect_sctp_chunk(chunk_tvb, pinfo, tree, sctp_tree, TRUE) && (tree)) {
1927 proto_item_set_len(sctp_item, offset - last_offset + DATA_CHUNK_HEADER_LENGTH);
1928 sctp_item_length_set = TRUE;
1929 offset += total_length;
1930 last_offset = offset;
1931 if (tvb_reported_length_remaining(tvb, offset) > 0) {
1932 sctp_item = proto_tree_add_item(tree, proto_sctp, tvb, offset, -1, FALSE);
1933 sctp_tree = proto_item_add_subtree(sctp_item, ett_sctp);
1934 sctp_item_length_set = FALSE;
1937 /* get rid of the dissected chunk */
1938 offset += total_length;
1941 if (!sctp_item_length_set && (tree)) {
1942 proto_item_set_len(sctp_item, offset - last_offset);
1947 dissect_sctp_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1949 guint32 checksum, calculated_crc32c, calculated_adler32;
1951 gboolean crc32c_correct, adler32_correct;
1952 proto_item *sctp_item;
1953 proto_tree *sctp_tree;
1955 /* In the interest of speed, if "tree" is NULL, don't do any work not
1956 necessary to generate protocol tree items. */
1958 /* create the sctp protocol tree */
1959 sctp_item = proto_tree_add_item(tree, proto_sctp, tvb, 0, -1, FALSE);
1960 sctp_tree = proto_item_add_subtree(sctp_item, ett_sctp);
1962 /* add the components of the common header to the protocol tree */
1963 proto_tree_add_item(sctp_tree, hf_source_port, tvb, SOURCE_PORT_OFFSET, SOURCE_PORT_LENGTH, NETWORK_BYTE_ORDER);
1964 proto_tree_add_item(sctp_tree, hf_destination_port, tvb, DESTINATION_PORT_OFFSET, DESTINATION_PORT_LENGTH, NETWORK_BYTE_ORDER);
1965 proto_tree_add_item(sctp_tree, hf_verification_tag, tvb, VERIFICATION_TAG_OFFSET, VERIFICATION_TAG_LENGTH, NETWORK_BYTE_ORDER);
1966 proto_tree_add_item_hidden(sctp_tree, hf_port, tvb, SOURCE_PORT_OFFSET, SOURCE_PORT_LENGTH, NETWORK_BYTE_ORDER);
1967 proto_tree_add_item_hidden(sctp_tree, hf_port, tvb, DESTINATION_PORT_OFFSET, DESTINATION_PORT_LENGTH, NETWORK_BYTE_ORDER);
1969 length = tvb_length(tvb);
1970 checksum = tvb_get_ntohl(tvb, CHECKSUM_OFFSET);
1971 switch(sctp_checksum) {
1972 case SCTP_CHECKSUM_NONE:
1973 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, checksum, "Checksum: 0x%08x (not verified)", checksum);
1975 case SCTP_CHECKSUM_ADLER32:
1976 calculated_adler32 = sctp_adler32(tvb_get_ptr(tvb, 0, length), length);
1977 adler32_correct = (checksum == calculated_adler32);
1978 if (adler32_correct)
1979 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
1980 checksum, "Checksum: 0x%08x (correct Adler32)", checksum);
1982 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
1983 checksum, "Checksum: 0x%08x (incorrect Adler32, should be 0x%08x)", checksum, calculated_adler32);
1984 proto_tree_add_boolean_hidden(sctp_tree, hf_checksum_bad, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, !(adler32_correct));
1986 case SCTP_CHECKSUM_CRC32C:
1987 calculated_crc32c = sctp_crc32c(tvb_get_ptr(tvb, 0, length), length);
1988 crc32c_correct = (checksum == calculated_crc32c);
1990 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
1991 checksum, "Checksum: 0x%08x (correct CRC32C)", checksum);
1993 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
1994 checksum, "Checksum: 0x%08x (incorrect CRC32C, should be 0x%08x)", checksum, calculated_crc32c);
1995 proto_tree_add_boolean_hidden(sctp_tree, hf_checksum_bad, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, !(crc32c_correct));
1997 case SCTP_CHECKSUM_AUTOMATIC:
1998 calculated_adler32 = sctp_adler32(tvb_get_ptr(tvb, 0, length), length);
1999 adler32_correct = (checksum == calculated_adler32);
2000 calculated_crc32c = sctp_crc32c(tvb_get_ptr(tvb, 0, length), length);
2001 crc32c_correct = (checksum == calculated_crc32c);
2002 if ((adler32_correct) && !(crc32c_correct))
2003 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2004 checksum, "Checksum: 0x%08x (correct Adler32)", checksum);
2005 else if (!(adler32_correct) && (crc32c_correct))
2006 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2007 checksum, "Checksum: 0x%08x (correct CRC32C)", checksum);
2008 else if ((adler32_correct) && (crc32c_correct))
2009 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2010 checksum, "Checksum: 0x%08x (correct Adler32 and CRC32C)", checksum);
2012 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2013 checksum, "Checksum: 0x%08x (incorrect, should be 0x%08x (Adler32) or 0x%08x (CRC32C))",
2014 checksum, calculated_adler32, calculated_crc32c);
2015 proto_tree_add_boolean_hidden(sctp_tree, hf_checksum_bad, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, !(crc32c_correct || adler32_correct));
2022 /* add all chunks of the sctp datagram to the protocol tree */
2023 dissect_sctp_chunks(tvb, pinfo, tree, sctp_item, sctp_tree);
2027 dissect_sctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2029 guint16 source_port, destination_port;
2031 /* Extract the common header */
2032 source_port = tvb_get_ntohs(tvb, SOURCE_PORT_OFFSET);
2033 destination_port = tvb_get_ntohs(tvb, DESTINATION_PORT_OFFSET);
2035 /* update pi structure */
2036 pinfo->ptype = PT_SCTP;
2037 pinfo->srcport = source_port;
2038 pinfo->destport = destination_port;
2040 /* make entry in the Protocol column on summary display */
2041 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2042 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCTP");
2044 /* Clear entries in Info column on summary display */
2045 if (check_col(pinfo->cinfo, COL_INFO))
2046 col_set_str(pinfo->cinfo, COL_INFO, "");
2048 dissect_sctp_packet(tvb, pinfo, tree);
2051 /* Register the protocol with Ethereal */
2053 proto_register_sctp(void)
2056 /* Setup list of header fields */
2057 static hf_register_info hf[] = {
2058 { &hf_source_port, { "Source port", "sctp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2059 { &hf_destination_port, { "Destination port", "sctp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2060 { &hf_port, { "Port", "sctp.port", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2061 { &hf_verification_tag, { "Verification tag", "sctp.verfication_tag", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
2062 { &hf_checksum, { "Checksum", "sctp.checksum", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
2063 { &hf_checksum_bad, { "Bad checksum", "sctp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL } },
2064 { &hf_chunk_type, { "Chunk type", "sctp.chunk_type", FT_UINT8, BASE_DEC, VALS(chunk_type_values), 0x0, "", HFILL } },
2065 { &hf_chunk_flags, { "Chunk flags", "sctp.chunk_flags", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL } },
2066 { &hf_chunk_bit_1, { "Bit", "sctp.chunk_bit_1", FT_BOOLEAN, 8, TFS(&sctp_chunk_bit_1_value), SCTP_CHUNK_BIT_1, "", HFILL } },
2067 { &hf_chunk_bit_2, { "Bit", "sctp.chunk_bit_2", FT_BOOLEAN, 8, TFS(&sctp_chunk_bit_2_value), SCTP_CHUNK_BIT_2, "", HFILL } },
2068 { &hf_chunk_length, { "Chunk length", "sctp.chunk_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2069 { &hf_chunk_padding, { "Chunk padding", "sctp.chunk_padding", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
2070 { &hf_chunk_value, { "Chunk value", "sctp.chunk_value", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
2071 { &hf_cookie, { "Cookie", "sctp.cookie", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
2072 { &hf_init_chunk_initiate_tag, { "Initiate tag", "sctp.init_initiate_tag", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
2073 { &hf_init_chunk_adv_rec_window_credit, { "Advertised receiver window credit (a_rwnd)", "sctp.init_credit", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2074 { &hf_init_chunk_number_of_outbound_streams, { "Number of outbound streams", "sctp.init_nr_out_streams", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2075 { &hf_init_chunk_number_of_inbound_streams, { "Number of inbound streams", "sctp.init_nr.in.streams", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2076 { &hf_init_chunk_initial_tsn, { "Initial TSN", "sctp.init_initial_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2077 { &hf_initack_chunk_initiate_tag, { "Initiate tag", "sctp.initack_initiate_tag", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
2078 { &hf_initack_chunk_adv_rec_window_credit, { "Advertised receiver window credit (a_rwnd)", "sctp.initack_credit", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2079 { &hf_initack_chunk_number_of_outbound_streams, { "Number of outbound streams", "sctp.initack_nr_out_streams", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2080 { &hf_initack_chunk_number_of_inbound_streams, { "Number of inbound streams", "sctp.initack_nr.in.streams", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2081 { &hf_initack_chunk_initial_tsn, { "Initial TSN", "sctp.initack_initial_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2082 { &hf_cumulative_tsn_ack, { "Cumulative TSN Ack", "sctp.cumulative_tsn_ack", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2083 { &hf_data_chunk_tsn, { "TSN", "sctp.data_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2084 { &hf_data_chunk_stream_id, { "Stream Identifier", "sctp.data_sid", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL } },
2085 { &hf_data_chunk_stream_seq_number, { "Stream sequence number", "sctp.data_ssn", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2086 { &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 } },
2087 { &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 } },
2088 { &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 } },
2089 { &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 } },
2090 { &hf_sack_chunk_cumulative_tsn_ack, { "Cumulative TSN ACK", "sctp.sack_cumulative_tsn_ack", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2091 { &hf_sack_chunk_adv_rec_window_credit, { "Advertised receiver window credit (a_rwnd)", "sctp.sack_a_rwnd", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2092 { &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 } },
2093 { &hf_sack_chunk_number_of_dup_tsns, { "Number of duplicated TSNs", "sctp.sack_number_of_duplicated_tsns", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2094 { &hf_sack_chunk_gap_block_start, { "Start", "sctp.sack_gap_block_start", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2095 { &hf_sack_chunk_gap_block_end, { "End", "sctp.sack_gap_block_end", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2096 { &hf_sack_chunk_duplicate_tsn, { "Duplicate TSN", "sctp.sack_duplicate_tsn", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2097 { &hf_shutdown_chunk_cumulative_tsn_ack, { "Cumulative TSN Ack", "sctp.shutdown_cumulative_tsn_ack", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2098 { &hf_ecne_chunk_lowest_tsn, { "Lowest TSN", "sctp.ecne_lowest_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2099 { &hf_cwr_chunk_lowest_tsn, { "Lowest TSN", "sctp.cwr_lowest_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2100 { &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 } },
2101 { &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 } },
2102 { &hf_forward_tsn_chunk_tsn, { "New cumulative TSN", "sctp.forward_tsn.tsn", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2103 { &hf_forward_tsn_chunk_sid, { "Stream identifier", "sctp.forward_tsn_sid", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2104 { &hf_forward_tsn_chunk_ssn, { "Stream sequence number", "sctp.forward_tsn_ssn", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2105 { &hf_parameter_type, { "Parameter type", "sctp.parameter_type", FT_UINT16, BASE_HEX, VALS(parameter_identifier_values), 0x0, "", HFILL } },
2106 { &hf_parameter_length, { "Parameter length", "sctp.parameter_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2107 { &hf_parameter_value, { "Parameter value", "sctp.parameter_value", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
2108 { &hf_parameter_padding, { "Parameter padding", "sctp.parameter_padding", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
2109 { &hf_parameter_bit_1, { "Bit", "sctp.parameter_bit_1", FT_BOOLEAN, 16, TFS(&sctp_parameter_bit_1_value), SCTP_PARAMETER_BIT_1, "", HFILL } },
2110 { &hf_parameter_bit_2, { "Bit", "sctp.parameter_bit_2", FT_BOOLEAN, 16, TFS(&sctp_parameter_bit_2_value), SCTP_PARAMETER_BIT_2, "", HFILL } },
2111 { &hf_ipv4_address, { "IP Version 4 address", "sctp.parameter_ipv4_address", FT_IPv4, BASE_NONE, NULL, 0x0, "", HFILL } },
2112 { &hf_ipv6_address, { "IP Version 6 address", "sctp.parameter_ipv6_address", FT_IPv6, BASE_NONE, NULL, 0x0, "", HFILL } },
2113 { &hf_heartbeat_info, { "Heartbeat information", "sctp.parameter_heartbeat_information", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
2114 { &hf_state_cookie, { "State cookie", "sctp.parameter_state_cookie", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
2115 { &hf_cookie_preservative_increment, { "Suggested Cookie life-span increment (msec)", "sctp.parameter_cookie_preservative_incr", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2116 { &hf_hostname, { "Hostname", "sctp.parameter_hostname", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL } },
2117 { &hf_supported_address_type, { "Supported address type", "sctp.parameter_supported_addres_type", FT_UINT16, BASE_DEC, VALS(address_types_values), 0x0, "", HFILL } },
2118 { &hf_asconf_serial, { "Serial Number", "sctp.asconf_serial_number", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
2119 { &hf_asconf_ack_serial, { "Serial Number", "sctp.asconf_ack_serial_number", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
2120 { &hf_correlation_id, { "Correlation_id", "sctp.correlation_id", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
2121 { &hf_adap_indication, { "Indication", "sctp.adapation_layer_indication", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
2122 { &hf_cause_code, { "Cause code", "sctp.cause_code", FT_UINT16, BASE_HEX, VALS(cause_code_values), 0x0, "", HFILL } },
2123 { &hf_cause_length, { "Cause length", "sctp.cause_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2124 { &hf_cause_info, { "Cause information", "sctp.cause_information", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
2125 { &hf_cause_padding, { "Cause padding", "sctp.cause_padding", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
2126 { &hf_cause_stream_identifier, { "Stream identifier", "sctp.cause_stream_identifier", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2127 { &hf_cause_reserved, { "Reserved", "sctp.cause_reserved", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2128 { &hf_cause_number_of_missing_parameters, { "Number of missing parameters", "sctp.cause_nr_of_missing_parameters", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2129 { &hf_cause_missing_parameter_type, { "Missing parameter type", "sctp.cause_missing_parameter_type", FT_UINT16, BASE_HEX, VALS(parameter_identifier_values), 0x0, "", HFILL } },
2130 { &hf_cause_measure_of_staleness, { "Measure of staleness in usec", "sctp.cause_measure_of_staleness", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2131 { &hf_cause_tsn, { "TSN", "sctp.cause_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2132 { &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 } },
2134 { &hf_pktdrop_chunk_s_bit, { "S-Bit", "sctp.pckdrop_s_bit", FT_BOOLEAN, 8, TFS(&sctp_pktdropk_s_bit_value), SCTP_PKTDROP_CHUNK_S_BIT, "", HFILL } },
2136 { &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 } },
2137 { &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 } },
2138 { &hf_pktdrop_chunk_bandwidth, { "Bandwidth", "sctp.pktdrop_bandwidth", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2139 { &hf_pktdrop_chunk_queuesize, { "Queuesize", "sctp.pktdrop_queuesize", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
2140 { &hf_pktdrop_chunk_truncated_length, { "Truncated length", "sctp.pktdrop_truncated_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2141 { &hf_pktdrop_chunk_reserved, { "Reserved", "sctp.pktdrop_reserved", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
2142 { &hf_pktdrop_chunk_data_field, { "Data field", "sctp.pktdrop_datafield", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
2145 /* Setup protocol subtree array */
2146 static gint *ett[] = {
2149 &ett_sctp_chunk_parameter,
2150 &ett_sctp_chunk_cause,
2151 &ett_sctp_chunk_type,
2152 &ett_sctp_data_chunk_flags,
2153 &ett_sctp_abort_chunk_flags,
2154 &ett_sctp_shutdown_complete_chunk_flags,
2155 &ett_sctp_pktdrop_chunk_flags,
2156 &ett_sctp_parameter_type,
2157 &ett_sctp_sack_chunk_gap_block,
2158 &ett_sctp_unrecognized_parameter_parameter,
2161 static enum_val_t sctp_checksum_options[] = {
2162 { "None", SCTP_CHECKSUM_NONE },
2163 { "Adler 32", SCTP_CHECKSUM_ADLER32 },
2164 { "CRC 32c", SCTP_CHECKSUM_CRC32C },
2165 { "Automatic", SCTP_CHECKSUM_AUTOMATIC},
2169 /* Register the protocol name and description */
2170 proto_sctp = proto_register_protocol("Stream Control Transmission Protocol", "SCTP", "sctp");
2171 sctp_module = prefs_register_protocol(proto_sctp, NULL);
2172 prefs_register_enum_preference(sctp_module, "checksum", "Checksum type",
2173 "The type of checksum used in SCTP packets", &sctp_checksum, sctp_checksum_options, FALSE);
2174 prefs_register_bool_preference(sctp_module, "show_always_control_chunks", "Show always control chunks", "Show always SCTP control chunks in the Info column", &show_always_control_chunks);
2177 /* Required function calls to register the header fields and subtrees used */
2178 proto_register_field_array(proto_sctp, hf, array_length(hf));
2179 proto_register_subtree_array(ett, array_length(ett));
2181 /* subdissector code */
2182 sctp_port_dissector_table = register_dissector_table("sctp.port", "SCTP port", FT_UINT16, BASE_DEC);
2183 sctp_ppi_dissector_table = register_dissector_table("sctp.ppi", "SCTP payload protocol identifier", FT_UINT32, BASE_HEX);
2188 proto_reg_handoff_sctp(void)
2190 dissector_handle_t sctp_handle;
2192 data_handle = find_dissector("data");
2193 sctp_handle = create_dissector_handle(dissect_sctp, proto_sctp);
2194 dissector_add("ip.proto", IP_PROTO_SCTP, sctp_handle);