2 * Routines for Stream Control Transmission Protocol dissection
4 * It should be compliant to
9 * - http://www.ietf.org/internet-drafts/draft-ietf-tsvwg-addip-sctp-18.txt
10 * - http://www.ietf.org/internet-drafts/draft-ietf-tsvwg-sctp-auth-08.txt
11 * - http://www.ietf.org/internet-drafts/draft-stewart-sctp-pktdrprep-02.txt
12 * - http://www.ietf.org/internet-drafts/draft-stewart-sctpstrrst-01.txt
13 * - http://www.ietf.org/internet-drafts/draft-ladha-sctp-nonce-02.txt
14 * - http://www.ietf.org/internet-drafts/draft-tuexen-tsvwg-sctp-sack-immediately-00.txt
16 * Copyright 2000-2005 Michael Tuexen <tuexen [AT] fh-muenster.de>
17 * Still to do (so stay tuned)
18 * - error checking mode
25 * Reassembly added 2006 by Robin Seggelmann
26 * TSN Tracking by Luis E. G. Ontanon (Feb 2007)
27 * Copyright 2009, Varun Notibala <nbvarun [AT] gmail.com>
31 * Wireshark - Network traffic analyzer
32 * By Gerald Combs <gerald@wireshark.org>
33 * Copyright 1998 Gerald Combs
35 * This program is free software; you can redistribute it and/or
36 * modify it under the terms of the GNU General Public License
37 * as published by the Free Software Foundation; either version 2
38 * of the License, or (at your option) any later version.
40 * This program is distributed in the hope that it will be useful,
41 * but WITHOUT ANY WARRANTY; without even the implied warranty of
42 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43 * GNU General Public License for more details.
45 * You should have received a copy of the GNU General Public License
46 * along with this program; if not, write to the Free Software
47 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
55 #include <epan/prefs.h>
56 #include <epan/packet.h>
58 #include <epan/ipproto.h>
59 #include <epan/addr_resolv.h>
60 #include "packet-sctp.h"
61 #include <epan/sctpppids.h>
62 #include <epan/emem.h>
63 #include <epan/expert.h>
64 #include <packet-frame.h>
65 #include <epan/crc32.h>
67 #define LT(x, y) ((gint32)((x) - (y)) < 0)
69 #define NETWORK_BYTE_ORDER FALSE
70 #define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
71 #define UDP_TUNNELING_PORT 9899
73 /* Initialize the protocol and registered fields */
74 static int proto_sctp = -1;
75 static int hf_port = -1;
76 static int hf_source_port = -1;
77 static int hf_destination_port = -1;
78 static int hf_verification_tag = -1;
79 static int hf_checksum = -1;
80 static int hf_checksum_bad = -1;
82 static int hf_chunk_type = -1;
83 static int hf_chunk_flags = -1;
84 static int hf_chunk_bit_1 = -1;
85 static int hf_chunk_bit_2 = -1;
86 static int hf_chunk_length = -1;
87 static int hf_chunk_padding = -1;
88 static int hf_chunk_value = -1;
90 static int hf_initiate_tag = -1;
91 static int hf_init_chunk_initiate_tag = -1;
92 static int hf_init_chunk_adv_rec_window_credit = -1;
93 static int hf_init_chunk_number_of_outbound_streams = -1;
94 static int hf_init_chunk_number_of_inbound_streams = -1;
95 static int hf_init_chunk_initial_tsn = -1;
97 static int hf_initack_chunk_initiate_tag = -1;
98 static int hf_initack_chunk_adv_rec_window_credit = -1;
99 static int hf_initack_chunk_number_of_outbound_streams = -1;
100 static int hf_initack_chunk_number_of_inbound_streams = -1;
101 static int hf_initack_chunk_initial_tsn = -1;
103 static int hf_cumulative_tsn_ack = -1;
105 static int hf_data_chunk_tsn = -1;
106 static int hf_data_chunk_stream_id = -1;
107 static int hf_data_chunk_stream_seq_number = -1;
108 static int hf_data_chunk_payload_proto_id = -1;
110 static int hf_data_chunk_e_bit = -1;
111 static int hf_data_chunk_b_bit = -1;
112 static int hf_data_chunk_u_bit = -1;
113 static int hf_data_chunk_i_bit = -1;
115 static int hf_sack_chunk_ns = -1;
116 static int hf_sack_chunk_cumulative_tsn_ack = -1;
117 static int hf_sack_chunk_adv_rec_window_credit = -1;
118 static int hf_sack_chunk_number_of_gap_blocks = -1;
119 static int hf_sack_chunk_number_of_dup_tsns = -1;
120 static int hf_sack_chunk_gap_block_start = -1;
121 static int hf_sack_chunk_gap_block_end = -1;
122 static int hf_sack_chunk_gap_block_start_tsn = -1;
123 static int hf_sack_chunk_gap_block_end_tsn = -1;
124 static int hf_sack_chunk_number_tsns_gap_acked = -1;
125 static int hf_sack_chunk_duplicate_tsn = -1;
127 static int hf_nr_sack_chunk_ns = -1;
128 static int hf_nr_sack_chunk_cumulative_tsn_ack = -1;
129 static int hf_nr_sack_chunk_adv_rec_window_credit = -1;
130 static int hf_nr_sack_chunk_number_of_gap_blocks = -1;
131 static int hf_nr_sack_chunk_number_of_nr_gap_blocks = -1;
132 static int hf_nr_sack_chunk_number_of_dup_tsns = -1;
133 static int hf_nr_sack_chunk_reserved = -1;
134 static int hf_nr_sack_chunk_gap_block_start = -1;
135 static int hf_nr_sack_chunk_gap_block_end = -1;
136 static int hf_nr_sack_chunk_gap_block_start_tsn = -1;
137 static int hf_nr_sack_chunk_gap_block_end_tsn = -1;
138 static int hf_nr_sack_chunk_number_tsns_gap_acked = -1;
139 static int hf_nr_sack_chunk_nr_gap_block_start = -1;
140 static int hf_nr_sack_chunk_nr_gap_block_end = -1;
141 static int hf_nr_sack_chunk_nr_gap_block_start_tsn = -1;
142 static int hf_nr_sack_chunk_nr_gap_block_end_tsn = -1;
143 static int hf_nr_sack_chunk_number_tsns_nr_gap_acked = -1;
144 static int hf_nr_sack_chunk_duplicate_tsn = -1;
146 static int hf_shutdown_chunk_cumulative_tsn_ack = -1;
147 static int hf_cookie = -1;
148 static int hf_cwr_chunk_lowest_tsn = -1;
150 static int hf_ecne_chunk_lowest_tsn = -1;
151 static int hf_abort_chunk_t_bit = -1;
152 static int hf_shutdown_complete_chunk_t_bit = -1;
154 static int hf_parameter_type = -1;
155 static int hf_parameter_length = -1;
156 static int hf_parameter_value = -1;
157 static int hf_parameter_padding = -1;
158 static int hf_parameter_bit_1 = -1;
159 static int hf_parameter_bit_2 = -1;
160 static int hf_ipv4_address = -1;
161 static int hf_ipv6_address = -1;
162 static int hf_heartbeat_info = -1;
163 static int hf_state_cookie = -1;
164 static int hf_cookie_preservative_increment = -1;
165 static int hf_hostname = -1;
166 static int hf_supported_address_type = -1;
167 static int hf_stream_reset_req_seq_nr = -1;
168 static int hf_stream_reset_rsp_seq_nr = -1;
169 static int hf_senders_last_assigned_tsn = -1;
170 static int hf_senders_next_tsn = -1;
171 static int hf_receivers_next_tsn = -1;
172 static int hf_stream_reset_rsp_result = -1;
173 static int hf_stream_reset_sid = -1;
174 static int hf_random_number = -1;
175 static int hf_chunks_to_auth = -1;
176 static int hf_hmac_id = -1;
177 static int hf_hmac = -1;
178 static int hf_shared_key_id = -1;
179 static int hf_supported_chunk_type = -1;
181 static int hf_cause_code = -1;
182 static int hf_cause_length = -1;
183 static int hf_cause_padding = -1;
184 static int hf_cause_info = -1;
186 static int hf_cause_stream_identifier = -1;
187 static int hf_cause_reserved = -1;
189 static int hf_cause_number_of_missing_parameters = -1;
190 static int hf_cause_missing_parameter_type = -1;
192 static int hf_cause_measure_of_staleness = -1;
194 static int hf_cause_tsn = -1;
196 static int hf_forward_tsn_chunk_tsn = -1;
197 static int hf_forward_tsn_chunk_sid = -1;
198 static int hf_forward_tsn_chunk_ssn = -1;
200 static int hf_asconf_ack_serial = -1;
201 static int hf_asconf_serial = -1;
202 static int hf_correlation_id = -1;
204 static int hf_adap_indication = -1;
206 static int hf_pktdrop_chunk_m_bit = -1;
207 static int hf_pktdrop_chunk_b_bit = -1;
208 static int hf_pktdrop_chunk_t_bit = -1;
209 static int hf_pktdrop_chunk_bandwidth = -1;
210 static int hf_pktdrop_chunk_queuesize = -1;
211 static int hf_pktdrop_chunk_truncated_length = -1;
212 static int hf_pktdrop_chunk_reserved = -1;
213 static int hf_pktdrop_chunk_data_field = -1;
215 static int hf_sctp_reassembled_in = -1;
216 static int hf_sctp_duplicate = -1;
217 static int hf_sctp_fragments = -1;
218 static int hf_sctp_fragment = -1;
220 static int hf_sctp_retransmission = -1;
221 static int hf_sctp_retransmitted = -1;
222 static int hf_sctp_retransmitted_count = -1;
223 static int hf_sctp_rtt = -1;
224 static int hf_sctp_rto = -1;
225 static int hf_sctp_ack_tsn = -1;
226 static int hf_sctp_ack_frame = -1;
227 static int hf_sctp_acked = -1;
228 static int hf_sctp_retransmitted_after_ack = -1;
230 static dissector_table_t sctp_port_dissector_table;
231 static dissector_table_t sctp_ppi_dissector_table;
232 static heur_dissector_list_t sctp_heur_subdissector_list;
233 static int sctp_tap = -1;
234 static module_t *sctp_module;
236 /* Initialize the subtree pointers */
237 static gint ett_sctp = -1;
238 static gint ett_sctp_chunk = -1;
239 static gint ett_sctp_chunk_parameter = -1;
240 static gint ett_sctp_chunk_cause = -1;
241 static gint ett_sctp_chunk_type = -1;
242 static gint ett_sctp_data_chunk_flags = -1;
243 static gint ett_sctp_sack_chunk_flags = -1;
244 static gint ett_sctp_nr_sack_chunk_flags = -1;
245 static gint ett_sctp_abort_chunk_flags = -1;
246 static gint ett_sctp_shutdown_complete_chunk_flags = -1;
247 static gint ett_sctp_pktdrop_chunk_flags = -1;
248 static gint ett_sctp_parameter_type= -1;
249 static gint ett_sctp_sack_chunk_gap_block = -1;
250 static gint ett_sctp_sack_chunk_gap_block_start = -1;
251 static gint ett_sctp_sack_chunk_gap_block_end = -1;
252 static gint ett_sctp_nr_sack_chunk_gap_block = -1;
253 static gint ett_sctp_nr_sack_chunk_gap_block_start = -1;
254 static gint ett_sctp_nr_sack_chunk_gap_block_end = -1;
255 static gint ett_sctp_nr_sack_chunk_nr_gap_block = -1;
256 static gint ett_sctp_nr_sack_chunk_nr_gap_block_start = -1;
257 static gint ett_sctp_nr_sack_chunk_nr_gap_block_end = -1;
258 static gint ett_sctp_unrecognized_parameter_parameter = -1;
260 static gint ett_sctp_fragments = -1;
261 static gint ett_sctp_fragment = -1;
263 static gint ett_sctp_tsn = -1;
264 static gint ett_sctp_ack = -1;
265 static gint ett_sctp_acked = -1;
266 static gint ett_sctp_tsn_retransmission = -1;
267 static gint ett_sctp_tsn_retransmitted_count = -1;
268 static gint ett_sctp_tsn_retransmitted = -1;
269 static dissector_handle_t data_handle;
271 static gboolean enable_tsn_analysis = FALSE;
272 static gboolean enable_ulp_dissection = TRUE;
274 #define SCTP_DATA_CHUNK_ID 0
275 #define SCTP_INIT_CHUNK_ID 1
276 #define SCTP_INIT_ACK_CHUNK_ID 2
277 #define SCTP_SACK_CHUNK_ID 3
278 #define SCTP_HEARTBEAT_CHUNK_ID 4
279 #define SCTP_HEARTBEAT_ACK_CHUNK_ID 5
280 #define SCTP_ABORT_CHUNK_ID 6
281 #define SCTP_SHUTDOWN_CHUNK_ID 7
282 #define SCTP_SHUTDOWN_ACK_CHUNK_ID 8
283 #define SCTP_ERROR_CHUNK_ID 9
284 #define SCTP_COOKIE_ECHO_CHUNK_ID 10
285 #define SCTP_COOKIE_ACK_CHUNK_ID 11
286 #define SCTP_ECNE_CHUNK_ID 12
287 #define SCTP_CWR_CHUNK_ID 13
288 #define SCTP_SHUTDOWN_COMPLETE_CHUNK_ID 14
289 #define SCTP_AUTH_CHUNK_ID 15
290 #define SCTP_NR_SACK_CHUNK_ID 16
291 #define SCTP_ASCONF_ACK_CHUNK_ID 0x80
292 #define SCTP_PKTDROP_CHUNK_ID 0x81
293 #define SCTP_STREAM_RESET_CHUNK_ID 0x82
294 #define SCTP_FORWARD_TSN_CHUNK_ID 0xC0
295 #define SCTP_ASCONF_CHUNK_ID 0xC1
296 #define SCTP_IETF_EXT 0xFF
298 static const value_string chunk_type_values[] = {
299 { SCTP_DATA_CHUNK_ID, "DATA" },
300 { SCTP_INIT_CHUNK_ID, "INIT" },
301 { SCTP_INIT_ACK_CHUNK_ID, "INIT_ACK" },
302 { SCTP_SACK_CHUNK_ID, "SACK" },
303 { SCTP_HEARTBEAT_CHUNK_ID, "HEARTBEAT" },
304 { SCTP_HEARTBEAT_ACK_CHUNK_ID, "HEARTBEAT_ACK" },
305 { SCTP_ABORT_CHUNK_ID, "ABORT" },
306 { SCTP_SHUTDOWN_CHUNK_ID, "SHUTDOWN" },
307 { SCTP_SHUTDOWN_ACK_CHUNK_ID, "SHUTDOWN_ACK" },
308 { SCTP_ERROR_CHUNK_ID, "ERROR" },
309 { SCTP_COOKIE_ECHO_CHUNK_ID, "COOKIE_ECHO" },
310 { SCTP_COOKIE_ACK_CHUNK_ID, "COOKIE_ACK" },
311 { SCTP_ECNE_CHUNK_ID, "ECNE" },
312 { SCTP_CWR_CHUNK_ID, "CWR" },
313 { SCTP_SHUTDOWN_COMPLETE_CHUNK_ID, "SHUTDOWN_COMPLETE" },
314 { SCTP_STREAM_RESET_CHUNK_ID, "STREAM_RESET" },
315 { SCTP_AUTH_CHUNK_ID, "AUTH" },
316 { SCTP_NR_SACK_CHUNK_ID, "NR-SACK" },
317 { SCTP_FORWARD_TSN_CHUNK_ID, "FORWARD_TSN" },
318 { SCTP_ASCONF_ACK_CHUNK_ID, "ASCONF_ACK" },
319 { SCTP_PKTDROP_CHUNK_ID, "PKTDROP" },
320 { SCTP_ASCONF_CHUNK_ID, "ASCONF" },
321 { SCTP_IETF_EXT, "IETF_EXTENSION" },
324 static const value_string sctp_payload_proto_id_values[] = {
325 { NOT_SPECIFIED_PROTOCOL_ID, "not specified" },
326 { IUA_PAYLOAD_PROTOCOL_ID, "IUA" },
327 { M2UA_PAYLOAD_PROTOCOL_ID, "M2UA" },
328 { M3UA_PAYLOAD_PROTOCOL_ID, "M3UA" },
329 { SUA_PAYLOAD_PROTOCOL_ID, "SUA" },
330 { M2PA_PAYLOAD_PROTOCOL_ID, "M2PA" },
331 { V5UA_PAYLOAD_PROTOCOL_ID, "V5UA" },
332 { H248_PAYLOAD_PROTOCOL_ID, "H.248/MEGACO" },
333 { BICC_PAYLOAD_PROTOCOL_ID, "BICC/Q.2150.3" },
334 { TALI_PAYLOAD_PROTOCOL_ID, "TALI" },
335 { DUA_PAYLOAD_PROTOCOL_ID, "DUA" },
336 { ASAP_PAYLOAD_PROTOCOL_ID, "ASAP" },
337 { ENRP_PAYLOAD_PROTOCOL_ID, "ENRP" },
338 { H323_PAYLOAD_PROTOCOL_ID, "H.323" },
339 { QIPC_PAYLOAD_PROTOCOL_ID, "Q.IPC/Q.2150.3" },
340 { SIMCO_PAYLOAD_PROTOCOL_ID, "SIMCO" },
341 { DDP_SEG_CHUNK_PROTOCOL_ID, "DDP Segment Chunk" }, /* [RFC-ietf-rddp-sctp-07.txt] */
342 { DDP_STREAM_SES_CTRL_PROTOCOL_ID, "DDP Stream Session Control" }, /* [RFC-ietf-rddp-sctp-07.txt] */
343 { S1AP_PAYLOAD_PROTOCOL_ID, "S1 Application Protocol (S1AP)" }, /* [TS 23.401][TS 36.413][Koodli] */
347 #define CHUNK_TYPE_LENGTH 1
348 #define CHUNK_FLAGS_LENGTH 1
349 #define CHUNK_LENGTH_LENGTH 2
350 #define CHUNK_HEADER_LENGTH (CHUNK_TYPE_LENGTH + \
351 CHUNK_FLAGS_LENGTH + \
353 #define CHUNK_HEADER_OFFSET 0
354 #define CHUNK_TYPE_OFFSET CHUNK_HEADER_OFFSET
355 #define CHUNK_FLAGS_OFFSET (CHUNK_TYPE_OFFSET + CHUNK_TYPE_LENGTH)
356 #define CHUNK_LENGTH_OFFSET (CHUNK_FLAGS_OFFSET + CHUNK_FLAGS_LENGTH)
357 #define CHUNK_VALUE_OFFSET (CHUNK_LENGTH_OFFSET + CHUNK_LENGTH_LENGTH)
359 #define PARAMETER_TYPE_LENGTH 2
360 #define PARAMETER_LENGTH_LENGTH 2
361 #define PARAMETER_HEADER_LENGTH (PARAMETER_TYPE_LENGTH + PARAMETER_LENGTH_LENGTH)
363 #define PARAMETER_HEADER_OFFSET 0
364 #define PARAMETER_TYPE_OFFSET PARAMETER_HEADER_OFFSET
365 #define PARAMETER_LENGTH_OFFSET (PARAMETER_TYPE_OFFSET + PARAMETER_TYPE_LENGTH)
366 #define PARAMETER_VALUE_OFFSET (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
368 #define SOURCE_PORT_LENGTH 2
369 #define DESTINATION_PORT_LENGTH 2
370 #define VERIFICATION_TAG_LENGTH 4
371 #define CHECKSUM_LENGTH 4
372 #define COMMON_HEADER_LENGTH (SOURCE_PORT_LENGTH + \
373 DESTINATION_PORT_LENGTH + \
374 VERIFICATION_TAG_LENGTH + \
376 #define SOURCE_PORT_OFFSET 0
377 #define DESTINATION_PORT_OFFSET (SOURCE_PORT_OFFSET + SOURCE_PORT_LENGTH)
378 #define VERIFICATION_TAG_OFFSET (DESTINATION_PORT_OFFSET + DESTINATION_PORT_LENGTH)
379 #define CHECKSUM_OFFSET (VERIFICATION_TAG_OFFSET + VERIFICATION_TAG_LENGTH)
381 #define SCTP_CHECKSUM_NONE 0
382 #define SCTP_CHECKSUM_ADLER32 1
383 #define SCTP_CHECKSUM_CRC32C 2
384 #define SCTP_CHECKSUM_AUTOMATIC 3
386 /* default values for preferences */
387 static gboolean show_port_numbers = TRUE;
389 static gboolean show_chunk_types = TRUE;
391 static gboolean show_always_control_chunks = TRUE;
392 static gint sctp_checksum = SCTP_CHECKSUM_NONE;
394 static gboolean use_reassembly = FALSE;
396 static struct _sctp_info sctp_info;
398 /* adler32.c -- compute the Adler-32 checksum of a data stream
399 * Copyright (C) 1995-1996 Mark Adler
400 * For conditions of distribution and use, see copyright notice in zlib.h
401 * available, e.g. from http://www.cdrom.com/pub/infozip/zlib/
403 * It was modified for the use in this dissector.
406 #define BASE 65521L /* largest prime smaller than 65536 */
407 #define NMAX 5540 /* NMAX is the largest n - 12 such that */
408 /* 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
410 #define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
411 #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
412 #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
413 #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
414 #define DO16(buf) DO8(buf,0); DO8(buf,8);
417 sctp_adler32(const unsigned char* buf, unsigned int len)
419 unsigned int s1 = 1L;
420 unsigned int s2 = 0L;
423 /* handle the first 8 bytes of the datagram */
425 buf += SOURCE_PORT_LENGTH +
426 DESTINATION_PORT_LENGTH +
427 VERIFICATION_TAG_LENGTH;
429 /* handle four 0 bytes as checksum */
430 s2 += CHECKSUM_LENGTH * s1;
431 buf += CHECKSUM_LENGTH;
433 /* now we have 12 bytes handled */
434 len -= COMMON_HEADER_LENGTH;
436 /* handle the rest of the datagram */
438 k = len < NMAX ? len : NMAX;
452 return (s2 << 16) | s1;
457 sctp_crc32c(const unsigned char* buf, unsigned int len)
460 guint32 crc32 = CRC32C_PRELOAD;
462 unsigned char byte0,byte1,byte2,byte3;
464 for (i = 0; i < SOURCE_PORT_LENGTH + DESTINATION_PORT_LENGTH + VERIFICATION_TAG_LENGTH; i++)
466 CRC32C(crc32, buf[i]);
472 for (i = COMMON_HEADER_LENGTH; i < len; i++)
474 CRC32C(crc32, buf[i]);
478 byte0 = result & 0xff;
479 byte1 = (result>>8) & 0xff;
480 byte2 = (result>>16) & 0xff;
481 byte3 = (result>>24) & 0xff;
482 crc32 = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
487 * Routines for dissecting parameters
490 typedef struct _sctp_half_assoc_t sctp_half_assoc_t;
492 static void dissect_parameter(tvbuff_t *, packet_info *, proto_tree *, proto_item *, gboolean);
494 static void dissect_parameters(tvbuff_t *, packet_info *, proto_tree *, proto_item *, gboolean);
496 static void dissect_error_cause(tvbuff_t *, packet_info *, proto_tree *);
498 static void dissect_error_causes(tvbuff_t *, packet_info *, proto_tree *);
500 static gboolean dissect_data_chunk(tvbuff_t*, guint16, packet_info*, proto_tree*, proto_tree*, proto_item*, proto_item*, sctp_half_assoc_t*);
502 static void dissect_sctp_packet(tvbuff_t *, packet_info *, proto_tree *, gboolean);
505 /* TSN ANALYSIS CODE */
507 struct _sctp_half_assoc_t {
514 guint32 first_tsn; /* start */
515 guint32 cumm_ack; /* rel */
516 emem_tree_t *tsns; /* sctp_tsn_t* by rel_tsn */
517 emem_tree_t *tsn_acks; /* sctp_tsn_t* by ctsn_frame */
519 struct _sctp_half_assoc_t *peer;
524 typedef struct _sctp_tsn_t {
534 struct _retransmit_t {
537 struct _retransmit_t *next;
539 guint32 retransmit_count;
540 struct _sctp_tsn_t *next;
544 static emem_tree_key_t*
545 make_address_key(guint32 spt, guint32 dpt, address *addr)
547 emem_tree_key_t *k = ep_alloc(sizeof(emem_tree_key_t)*6);
549 k[0].length = 1; k[0].key = ep_memdup(&spt,sizeof(spt));
550 k[1].length = 1; k[1].key = ep_memdup(&dpt,sizeof(dpt));
551 k[2].length = 1; k[2].key = (guint32*)(void *)&(addr->type);
552 k[3].length = 1; k[3].key = (guint32*)(void *)&(addr->len);
554 k[4].length = ((addr->len/4)+1);
555 k[4].key = ep_alloc0(((addr->len/4)+1)*4);
556 if (addr->len) memcpy(k[4].key, addr->data, addr->len);
558 k[5].length = 0; k[5].key = NULL;
563 static emem_tree_key_t *
564 make_dir_key(guint32 spt, guint32 dpt, guint32 vtag)
566 emem_tree_key_t *k = ep_alloc(sizeof(emem_tree_key_t)*4);
568 k[0].length = 1; k[0].key = ep_memdup(&spt,sizeof(spt));
569 k[1].length = 1; k[1].key = ep_memdup(&dpt,sizeof(dpt));
570 k[2].length = 1; k[2].key = ep_memdup(&vtag,sizeof(vtag));
571 k[3].length = 0; k[3].key = NULL;
578 static emem_tree_t *dirs_by_ptvtag; /* sctp_half_assoc_t* */
579 static emem_tree_t *dirs_by_ptaddr; /* sctp_half_assoc_t**, it may contain a null pointer */
581 static sctp_half_assoc_t *
582 get_half_assoc(packet_info *pinfo, guint32 spt, guint32 dpt, guint32 vtag)
584 sctp_half_assoc_t *ha;
585 sctp_half_assoc_t **hb;
588 if (!enable_tsn_analysis || !vtag) return NULL;
590 /* look for the current half_assoc by spt, dpt and vtag */
592 k = make_dir_key(spt, dpt, vtag);
593 if (( ha = emem_tree_lookup32_array(dirs_by_ptvtag, k) )) {
594 /* found, if it has been already matched we're done */
595 if (ha->peer) return ha;
597 /* not found, make a new one and add it to the table */
598 ha = se_alloc0(sizeof(sctp_half_assoc_t));
602 ha->tsns = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK,"");
603 ha->tsn_acks = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK,"");
608 /* add this half to the table indexed by ports and vtag */
609 emem_tree_insert32_array(dirs_by_ptvtag, k, ha);
612 /* at this point we have an unmatched half, look for its other half using the ports and IP address */
613 k = make_address_key(dpt, spt, &(pinfo->dst));
615 if (( hb = emem_tree_lookup32_array(dirs_by_ptaddr, k) )) {
616 /*the table contains a pointer to a pointer to a half */
618 /* if there is no half pointed by this, add the current half to the table */
621 /* there's a half pointed by this, assume it's our peer and clear the table's pointer */
627 /* we found no entry in the table: add one (using reversed ports and src addresss) so that it can be matched later */
628 *(hb = se_alloc(sizeof(void*))) = ha;
629 k = make_address_key(spt, dpt, &(pinfo->src));
630 emem_tree_insert32_array(dirs_by_ptaddr, k, hb);
636 /* Limit the number of retransmissions we track (to limit memory usage--and
637 * tree size--in pathological cases, for example zero window probing forever).
639 #define MAX_RETRANS_TRACKED_PER_TSN 100
642 tsn_tree(sctp_tsn_t *t, proto_item *tsn_item, packet_info *pinfo,
643 tvbuff_t *tvb, guint32 framenum)
647 proto_tree *tsn_tree_pt = proto_item_add_subtree(tsn_item, ett_sctp_tsn);
649 if (t->first_transmit.framenum != framenum) {
652 pi = proto_tree_add_uint(tsn_tree_pt, hf_sctp_retransmission, tvb, 0, 0, t->first_transmit.framenum);
653 pt = proto_item_add_subtree(pi, ett_sctp_tsn_retransmission);
654 PROTO_ITEM_SET_GENERATED(pi);
655 expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_NOTE, "Retransmitted TSN");
657 nstime_delta( &rto, &pinfo->fd->abs_ts, &(t->first_transmit.ts) );
658 pi = proto_tree_add_time(pt, hf_sctp_rto, tvb, 0, 0, &rto);
659 PROTO_ITEM_SET_GENERATED(pi);
661 /* Detect reneged acks */
662 /* XXX what if the frames aren't sorted by time? */
663 if (t->ack.framenum && t->ack.framenum < framenum)
665 pi = proto_tree_add_uint_format(pt, hf_sctp_retransmitted_after_ack, tvb, 0, 0, t->ack.framenum,
666 "This TSN was acked (in frame %u) prior to this retransmission (reneged ack?)",
668 PROTO_ITEM_SET_GENERATED(pi);
669 expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_WARN,
670 "This TSN was acked prior to this retransmission (reneged ack?)");
672 } else if (t->retransmit) {
673 struct _retransmit_t **r;
677 if (t->retransmit_count > MAX_RETRANS_TRACKED_PER_TSN)
678 g_snprintf(ds, sizeof(ds), " (only %d displayed)", MAX_RETRANS_TRACKED_PER_TSN);
682 pi = proto_tree_add_uint_format(tsn_tree_pt,
683 hf_sctp_retransmitted_count,
684 tvb, 0, 0, t->retransmit_count,
685 "This TSN was retransmitted %u time%s%s",
687 plurality(t->retransmit_count, "", "s"),
689 PROTO_ITEM_SET_GENERATED(pi);
691 if (t->retransmit_count > 2)
692 expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_WARN,
693 "This TSN was retransmitted more than 2 times");
695 pt = proto_item_add_subtree(pi, ett_sctp_tsn_retransmitted_count);
699 nstime_delta(&rto, &((*r)->ts), &pinfo->fd->abs_ts);
700 pi = proto_tree_add_uint_format(pt,
701 hf_sctp_retransmitted,
704 "This TSN was retransmitted in frame %u (%s seconds after this frame)",
706 rel_time_to_secs_str(&rto));
707 PROTO_ITEM_SET_GENERATED(pi);
712 if (t->ack.framenum) {
715 pi = proto_tree_add_uint(tsn_tree_pt, hf_sctp_acked, tvb, 0 , 0, t->ack.framenum);
716 PROTO_ITEM_SET_GENERATED(pi);
717 pt = proto_item_add_subtree(pi, ett_sctp_ack);
719 nstime_delta( &rtt, &(t->ack.ts), &(t->first_transmit.ts) );
720 pi = proto_tree_add_time(pt, hf_sctp_rtt, tvb, 0, 0, &rtt);
721 PROTO_ITEM_SET_GENERATED(pi);
725 #define RELTSN(tsn) (((tsn) < h->first_tsn) ? (tsn + (0xffffffff - (h->first_tsn)) + 1) : (tsn - h->first_tsn))
728 sctp_tsn(packet_info *pinfo, tvbuff_t *tvb, proto_item *tsn_item,
729 sctp_half_assoc_t *h, guint32 tsn)
735 /* no half assoc? nothing to do!*/
740 framenum = pinfo->fd->num;
742 /* If we're dissecting for a read filter in the GUI [tshark assigns
743 * frame numbers before running the read filter], don't do the TSN
744 * analysis. (We can't anyway because we don't have a valid frame
747 * Without this check if you load a capture file in the
748 * GUI while using a read filter, every SCTP TSN is marked as a
749 * retransmission of that in frame 0.
754 /* we have not seen any tsn yet in this half assoc set the ground */
761 reltsn = RELTSN(tsn);
763 /* printf("%.3d REL TSN: %p->%p [%u] %u \n",framenum,h,h->peer,tsn,reltsn); */
765 /* look for this tsn in this half's tsn table */
766 if (! (t = emem_tree_lookup32(h->tsns,reltsn) )) {
767 /* no tsn found, create a new one */
768 t = se_alloc0(sizeof(sctp_tsn_t));
771 t->first_transmit.framenum = framenum;
772 t->first_transmit.ts.secs = pinfo->fd->abs_ts.secs;
773 t->first_transmit.ts.nsecs = pinfo->fd->abs_ts.nsecs;
775 emem_tree_insert32(h->tsns,reltsn,t);
778 if ( (! pinfo->fd->flags.visited ) && t->first_transmit.framenum != framenum ) {
779 struct _retransmit_t **r;
782 t->retransmit_count++;
785 while (*r && i < MAX_RETRANS_TRACKED_PER_TSN) {
790 if (i <= MAX_RETRANS_TRACKED_PER_TSN) {
791 /* TODO: we're allocating 16 bytes here. The se_
792 * allocator adds 8 bytes of canary to that at each
793 * allocation. Should these allocations be batched
794 * or does it not matter for the rare cases when there's
795 * more than 1 or 2 retransmissions of a TSN?
796 * For now, go with simplicity (of code here).
798 *r = se_alloc0(sizeof(struct _retransmit_t));
799 (*r)->framenum = framenum;
800 (*r)->ts.secs = pinfo->fd->abs_ts.secs;
801 (*r)->ts.nsecs = pinfo->fd->abs_ts.nsecs;
805 tsn_tree(t, tsn_item, pinfo, tvb, framenum);
809 ack_tree(sctp_tsn_t *t, proto_tree *acks_tree,
810 tvbuff_t *tvb, packet_info *pinfo)
815 guint framenum = pinfo->fd->num;
817 if ( t->ack.framenum == framenum ) {
818 nstime_delta( &rtt, &(t->ack.ts), &(t->first_transmit.ts) );
820 pi = proto_tree_add_uint(acks_tree, hf_sctp_ack_tsn, tvb, 0 , 0, t->tsn);
821 PROTO_ITEM_SET_GENERATED(pi);
823 pt = proto_item_add_subtree(pi, ett_sctp_acked);
825 pi = proto_tree_add_uint(pt, hf_sctp_ack_frame, tvb, 0 , 0, t->first_transmit.framenum);
826 PROTO_ITEM_SET_GENERATED(pi);
828 pi = proto_tree_add_time(pt, hf_sctp_rtt, tvb, 0, 0, &rtt);
829 PROTO_ITEM_SET_GENERATED(pi);
834 sctp_ack(packet_info *pinfo, tvbuff_t *tvb, proto_tree *acks_tree,
835 sctp_half_assoc_t *h, guint32 reltsn)
844 framenum = pinfo->fd->num;
846 /* printf("%.6d ACK: %p->%p [%u] \n",framenum,h,h->peer,reltsn); */
848 t = se_tree_lookup32(h->peer->tsns,reltsn);
851 if (! t->ack.framenum) {
854 t->ack.framenum = framenum;
855 t->ack.ts.secs = pinfo->fd->abs_ts.secs;
856 t->ack.ts.nsecs = pinfo->fd->abs_ts.nsecs;
858 if (( t2 = emem_tree_lookup32(h->peer->tsn_acks, framenum) )) {
859 for(;t2->next;t2 = t2->next)
864 emem_tree_insert32(h->peer->tsn_acks, framenum,t);
868 if ( t->ack.framenum == framenum)
869 ack_tree(t, acks_tree, tvb, pinfo);
872 proto_tree_add_text(acks_tree, tvb, 0 , 0, "Assoc: %p vs %p ?? %ld",h,h->peer,tsn);
876 #define RELTSNACK(tsn) (((tsn) < h->peer->first_tsn) ? ((tsn) + (0xffffffff - (h->peer->first_tsn)) + 1) : ((tsn) - h->peer->first_tsn))
878 sctp_ack_block(packet_info *pinfo, sctp_half_assoc_t *h, tvbuff_t *tvb,
879 proto_item *acks_tree, const guint32 *tsn_start_ptr,
888 if ( !h || !h->peer || ! h->peer->started )
891 framenum = pinfo->fd->num;
892 rel_end = RELTSNACK(tsn_end);
895 rel_start = RELTSNACK(*tsn_start_ptr);
896 /* printf("%.3d BACK: %p->%p [%u-%u]\n",framenum,h,h->peer,rel_start,rel_end); */
898 rel_start = h->peer->cumm_ack;
899 /* printf("%.3d CACK: %p->%p [%u-%u]\n",framenum,h,h->peer,rel_start,rel_end); */
903 if ((t = emem_tree_lookup32(h->peer->tsn_acks, framenum))) {
904 for(;t;t = t->next) {
905 guint32 tsn = t->tsn;
907 if ( tsn < h->peer->first_tsn ) {
908 tsn += (0xffffffff - (h->peer->first_tsn)) + 1;
910 tsn -= h->peer->first_tsn;
913 if (t->ack.framenum == framenum && ( (!tsn_start_ptr) || rel_start <= tsn) && tsn <= rel_end)
914 ack_tree(t, acks_tree, tvb, pinfo);
920 if (pinfo->fd->flags.visited || rel_end < rel_start || rel_end - rel_start > 0xffff0000 ) return;
922 if (! tsn_start_ptr )
923 h->peer->cumm_ack = rel_end + 1;
925 if (rel_start <= rel_end && rel_end - rel_start < 5000 ) {
927 for (i=0; i <= rel_end-rel_start; i++) {
928 rel_tsn = (guint32) (i+rel_start);
929 sctp_ack(pinfo, tvb, acks_tree, h, rel_tsn);
934 /* END TSN ANALYSIS CODE */
939 #define HEARTBEAT_INFO_PARAMETER_INFO_OFFSET PARAMETER_VALUE_OFFSET
942 dissect_heartbeat_info_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
944 guint16 heartbeat_info_length;
946 heartbeat_info_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
947 if (heartbeat_info_length > 0)
948 proto_tree_add_item(parameter_tree, hf_heartbeat_info, parameter_tvb, HEARTBEAT_INFO_PARAMETER_INFO_OFFSET, heartbeat_info_length, NETWORK_BYTE_ORDER);
949 proto_item_append_text(parameter_item, " (Information: %u byte%s)", heartbeat_info_length, plurality(heartbeat_info_length, "", "s"));
952 #define IPV4_ADDRESS_LENGTH 4
953 #define IPV4_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
956 dissect_ipv4_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item, proto_item *additional_item, gboolean dissecting_init_init_ack_chunk)
958 if (parameter_tree) {
959 proto_tree_add_item(parameter_tree, hf_ipv4_address, parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH, NETWORK_BYTE_ORDER);
960 proto_item_append_text(parameter_item, " (Address: %s)", ip_to_str((const guint8 *)tvb_get_ptr(parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH)));
962 proto_item_append_text(additional_item, "%s", ip_to_str((const guint8 *)tvb_get_ptr(parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH)));
964 if (dissecting_init_init_ack_chunk) {
965 if (sctp_info.number_of_tvbs < MAXIMUM_NUMBER_OF_TVBS)
966 sctp_info.tvb[sctp_info.number_of_tvbs++] = parameter_tvb;
968 sctp_info.incomplete = TRUE;
972 #define IPV6_ADDRESS_LENGTH 16
973 #define IPV6_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
976 dissect_ipv6_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item, proto_item *additional_item, gboolean dissecting_init_init_ack_chunk)
978 if (parameter_tree) {
979 proto_tree_add_item(parameter_tree, hf_ipv6_address, parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH, NETWORK_BYTE_ORDER);
980 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)));
982 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)));
984 if (dissecting_init_init_ack_chunk) {
985 if (sctp_info.number_of_tvbs < MAXIMUM_NUMBER_OF_TVBS)
986 sctp_info.tvb[sctp_info.number_of_tvbs++] = parameter_tvb;
988 sctp_info.incomplete = TRUE;
992 #define STATE_COOKIE_PARAMETER_COOKIE_OFFSET PARAMETER_VALUE_OFFSET
995 dissect_state_cookie_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
997 guint16 state_cookie_length;
999 state_cookie_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1000 if (state_cookie_length > 0)
1001 proto_tree_add_item(parameter_tree, hf_state_cookie, parameter_tvb, STATE_COOKIE_PARAMETER_COOKIE_OFFSET, state_cookie_length, NETWORK_BYTE_ORDER);
1002 proto_item_append_text(parameter_item, " (Cookie length: %u byte%s)", state_cookie_length, plurality(state_cookie_length, "", "s"));
1006 dissect_unrecognized_parameters_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
1008 /* FIXME: Does it contain one or more parameters? */
1009 dissect_parameter(tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, -1, -1), pinfo, parameter_tree, NULL, FALSE);
1012 #define COOKIE_PRESERVATIVE_PARAMETER_INCR_LENGTH 4
1013 #define COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET PARAMETER_VALUE_OFFSET
1016 dissect_cookie_preservative_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1018 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);
1019 proto_item_append_text(parameter_item, " (Increment :%u msec)", tvb_get_ntohl(parameter_tvb, COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET));
1022 #define HOSTNAME_OFFSET PARAMETER_VALUE_OFFSET
1025 dissect_hostname_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1027 guint16 hostname_length;
1029 hostname_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1030 proto_tree_add_item(parameter_tree, hf_hostname, parameter_tvb, HOSTNAME_OFFSET, hostname_length, NETWORK_BYTE_ORDER);
1031 proto_item_append_text(parameter_item, " (Hostname: %.*s)", hostname_length, (const char *)tvb_get_ptr(parameter_tvb, HOSTNAME_OFFSET, hostname_length));
1035 #define IPv4_ADDRESS_TYPE 5
1036 #define IPv6_ADDRESS_TYPE 6
1037 #define HOSTNAME_ADDRESS_TYPE 11
1039 static const value_string address_types_values[] = {
1040 { IPv4_ADDRESS_TYPE, "IPv4 address" },
1041 { IPv6_ADDRESS_TYPE, "IPv6 address" },
1042 { HOSTNAME_ADDRESS_TYPE, "Hostname address" },
1046 #define SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH 2
1049 dissect_supported_address_types_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1051 guint16 addr_type, number_of_addr_types, addr_type_number;
1054 number_of_addr_types = (tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH)
1055 / SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH;
1057 offset = PARAMETER_VALUE_OFFSET;
1058 proto_item_append_text(parameter_item, " (Supported types: ");
1059 for(addr_type_number = 1; addr_type_number <= number_of_addr_types; addr_type_number++) {
1060 proto_tree_add_item(parameter_tree, hf_supported_address_type, parameter_tvb, offset, SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH, NETWORK_BYTE_ORDER);
1061 addr_type = tvb_get_ntohs(parameter_tvb, offset);
1062 switch (addr_type) {
1063 case IPv4_ADDRESS_TYPE:
1064 proto_item_append_text(parameter_item, "IPv4");
1066 case IPv6_ADDRESS_TYPE:
1067 proto_item_append_text(parameter_item, "IPv6");
1069 case HOSTNAME_ADDRESS_TYPE:
1070 proto_item_append_text(parameter_item, "hostname");
1073 proto_item_append_text(parameter_item, "%u", addr_type);
1075 if (addr_type_number < number_of_addr_types)
1076 proto_item_append_text(parameter_item, ", ");
1077 offset += SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH;
1079 proto_item_append_text(parameter_item, ")");
1082 #define STREAM_RESET_SEQ_NR_LENGTH 4
1083 #define SENDERS_LAST_ASSIGNED_TSN_LENGTH 4
1084 #define SID_LENGTH 2
1086 #define STREAM_RESET_REQ_SEQ_NR_OFFSET PARAMETER_VALUE_OFFSET
1087 #define STREAM_RESET_REQ_RSP_SEQ_NR_OFFSET (PARAMETER_VALUE_OFFSET + STREAM_RESET_SEQ_NR_LENGTH)
1088 #define SENDERS_LAST_ASSIGNED_TSN_OFFSET (STREAM_RESET_REQ_RSP_SEQ_NR_OFFSET + STREAM_RESET_SEQ_NR_LENGTH)
1091 dissect_outgoing_ssn_reset_request_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item _U_)
1093 guint length, number_of_sids, sid_number, sid_offset;
1095 proto_tree_add_item(parameter_tree, hf_stream_reset_req_seq_nr, parameter_tvb, STREAM_RESET_REQ_SEQ_NR_OFFSET, STREAM_RESET_SEQ_NR_LENGTH, NETWORK_BYTE_ORDER);
1096 proto_tree_add_item(parameter_tree, hf_stream_reset_rsp_seq_nr, parameter_tvb, STREAM_RESET_REQ_RSP_SEQ_NR_OFFSET, STREAM_RESET_SEQ_NR_LENGTH, NETWORK_BYTE_ORDER);
1097 proto_tree_add_item(parameter_tree, hf_senders_last_assigned_tsn, parameter_tvb, SENDERS_LAST_ASSIGNED_TSN_OFFSET, SENDERS_LAST_ASSIGNED_TSN_LENGTH, NETWORK_BYTE_ORDER);
1099 length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1100 sid_offset = SENDERS_LAST_ASSIGNED_TSN_OFFSET + SENDERS_LAST_ASSIGNED_TSN_LENGTH;
1101 if (length > PARAMETER_HEADER_LENGTH + STREAM_RESET_SEQ_NR_LENGTH + STREAM_RESET_SEQ_NR_LENGTH + SENDERS_LAST_ASSIGNED_TSN_LENGTH) {
1102 number_of_sids = (length - (PARAMETER_HEADER_LENGTH + STREAM_RESET_SEQ_NR_LENGTH + STREAM_RESET_SEQ_NR_LENGTH + SENDERS_LAST_ASSIGNED_TSN_LENGTH)) / SID_LENGTH;
1103 for(sid_number = 1; sid_number <= number_of_sids; sid_number++) {
1104 proto_tree_add_item(parameter_tree, hf_stream_reset_sid, parameter_tvb, sid_offset, SID_LENGTH, NETWORK_BYTE_ORDER);
1105 sid_offset += SID_LENGTH;
1111 dissect_incoming_ssn_reset_request_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item _U_)
1113 guint length, number_of_sids, sid_number, sid_offset;
1115 proto_tree_add_item(parameter_tree, hf_stream_reset_req_seq_nr, parameter_tvb, STREAM_RESET_REQ_SEQ_NR_OFFSET, STREAM_RESET_SEQ_NR_LENGTH, NETWORK_BYTE_ORDER);
1117 length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1118 sid_offset = STREAM_RESET_REQ_SEQ_NR_OFFSET + STREAM_RESET_SEQ_NR_LENGTH;
1119 if (length > PARAMETER_HEADER_LENGTH + STREAM_RESET_SEQ_NR_LENGTH) {
1120 number_of_sids = (length - (PARAMETER_HEADER_LENGTH + STREAM_RESET_SEQ_NR_LENGTH)) / SID_LENGTH;
1121 for(sid_number = 1; sid_number <= number_of_sids; sid_number++) {
1122 proto_tree_add_item(parameter_tree, hf_stream_reset_sid, parameter_tvb, sid_offset, SID_LENGTH, NETWORK_BYTE_ORDER);
1123 sid_offset += SID_LENGTH;
1128 #define STREAM_RESET_REQ_SEQ_NR_OFFSET PARAMETER_VALUE_OFFSET
1131 dissect_ssn_tsn_reset_request_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item _U_)
1133 proto_tree_add_item(parameter_tree, hf_stream_reset_req_seq_nr, parameter_tvb, STREAM_RESET_REQ_SEQ_NR_OFFSET, STREAM_RESET_SEQ_NR_LENGTH, NETWORK_BYTE_ORDER);
1136 #define STREAM_RESET_RSP_RESULT_LENGTH 4
1137 #define SENDERS_NEXT_TSN_LENGTH 4
1138 #define RECEIVERS_NEXT_TSN_LENGTH 4
1140 #define STREAM_RESET_RSP_RSP_SEQ_NR_OFFSET PARAMETER_VALUE_OFFSET
1141 #define STREAM_RESET_RSP_RESULT_OFFSET (STREAM_RESET_RSP_RSP_SEQ_NR_OFFSET + STREAM_RESET_SEQ_NR_LENGTH)
1142 #define SENDERS_NEXT_TSN_OFFSET (STREAM_RESET_RSP_RESULT_OFFSET + STREAM_RESET_RSP_RESULT_LENGTH)
1143 #define RECEIVERS_NEXT_TSN_OFFSET (SENDERS_NEXT_TSN_OFFSET + SENDERS_NEXT_TSN_LENGTH)
1145 static const value_string stream_reset_result_values[] = {
1146 { 0, "Nothing to do" },
1149 { 3, "Error - Wrong SSN" },
1150 { 4, "Error - Request already in progress" },
1156 dissect_stream_reset_response_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item _U_)
1160 length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1162 proto_tree_add_item(parameter_tree, hf_stream_reset_rsp_seq_nr, parameter_tvb, STREAM_RESET_RSP_RSP_SEQ_NR_OFFSET, STREAM_RESET_SEQ_NR_LENGTH, NETWORK_BYTE_ORDER);
1163 proto_tree_add_item(parameter_tree, hf_stream_reset_rsp_result, parameter_tvb, STREAM_RESET_RSP_RESULT_OFFSET, STREAM_RESET_RSP_RESULT_LENGTH, NETWORK_BYTE_ORDER);
1164 if (length >= PARAMETER_HEADER_LENGTH + STREAM_RESET_SEQ_NR_LENGTH + STREAM_RESET_RSP_RESULT_LENGTH + SENDERS_NEXT_TSN_LENGTH)
1165 proto_tree_add_item(parameter_tree, hf_senders_next_tsn, parameter_tvb, SENDERS_NEXT_TSN_OFFSET, SENDERS_NEXT_TSN_LENGTH, NETWORK_BYTE_ORDER);
1166 if (length >= PARAMETER_HEADER_LENGTH + STREAM_RESET_SEQ_NR_LENGTH + STREAM_RESET_RSP_RESULT_LENGTH + SENDERS_NEXT_TSN_LENGTH + RECEIVERS_NEXT_TSN_LENGTH)
1167 proto_tree_add_item(parameter_tree, hf_receivers_next_tsn, parameter_tvb, RECEIVERS_NEXT_TSN_OFFSET, RECEIVERS_NEXT_TSN_LENGTH, NETWORK_BYTE_ORDER);
1171 dissect_ecn_parameter(tvbuff_t *parameter_tvb _U_)
1176 dissect_nonce_supported_parameter(tvbuff_t *parameter_tvb _U_)
1180 #define RANDOM_NUMBER_OFFSET PARAMETER_VALUE_OFFSET
1183 dissect_random_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
1185 gint32 number_length;
1187 number_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1188 if (number_length > 0)
1189 proto_tree_add_item(parameter_tree, hf_random_number, parameter_tvb, RANDOM_NUMBER_OFFSET, number_length, NETWORK_BYTE_ORDER);
1193 dissect_chunks_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
1195 gint32 number_of_chunks;
1196 guint16 chunk_number, offset;
1198 number_of_chunks = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1199 for(chunk_number = 1, offset = PARAMETER_VALUE_OFFSET; chunk_number <= number_of_chunks; chunk_number++, offset += CHUNK_TYPE_LENGTH)
1200 proto_tree_add_item(parameter_tree, hf_chunks_to_auth, parameter_tvb, offset, CHUNK_TYPE_LENGTH, NETWORK_BYTE_ORDER);
1203 static const value_string hmac_id_values[] = {
1204 { 0x0000, "Reserved" },
1205 { 0x0001, "SHA-1" },
1206 { 0x0002, "Reserved" },
1207 { 0x0003, "SHA-256" },
1208 { 0x8001, "SHA_224" },
1209 { 0x8002, "SHA_384" },
1210 { 0x8003, "SHA_512" },
1213 #define HMAC_ID_LENGTH 2
1216 dissect_hmac_algo_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
1218 gint32 number_of_ids;
1219 guint16 id_number, offset;
1221 number_of_ids = (tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH) / HMAC_ID_LENGTH;
1222 for(id_number = 1, offset = PARAMETER_VALUE_OFFSET; id_number <= number_of_ids; id_number++, offset += HMAC_ID_LENGTH)
1223 proto_tree_add_item(parameter_tree, hf_hmac_id, parameter_tvb, offset, HMAC_ID_LENGTH, NETWORK_BYTE_ORDER);
1227 dissect_supported_extensions_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1229 gint32 number_of_types;
1230 guint16 type_number, offset;
1232 proto_item_append_text(parameter_item, " (Supported types: ");
1233 number_of_types = (tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH) / CHUNK_TYPE_LENGTH;
1234 for(type_number = 1, offset = PARAMETER_VALUE_OFFSET; type_number <= number_of_types; type_number++, offset += CHUNK_TYPE_LENGTH) {
1235 proto_tree_add_item(parameter_tree, hf_supported_chunk_type, parameter_tvb, offset, CHUNK_TYPE_LENGTH, NETWORK_BYTE_ORDER);
1236 proto_item_append_text(parameter_item, "%s", val_to_str(tvb_get_guint8(parameter_tvb, offset), chunk_type_values, "Unknown"));
1237 if (type_number < number_of_types)
1238 proto_item_append_text(parameter_item, ", ");
1241 proto_item_append_text(parameter_item, ")");
1245 dissect_forward_tsn_supported_parameter(tvbuff_t *parameter_tvb _U_)
1249 #define CORRELATION_ID_LENGTH 4
1250 #define CORRELATION_ID_OFFSET PARAMETER_VALUE_OFFSET
1251 #define ADDRESS_PARAMETER_OFFSET (CORRELATION_ID_OFFSET + CORRELATION_ID_LENGTH)
1254 dissect_add_ip_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
1256 guint16 address_length;
1257 tvbuff_t *address_tvb;
1259 address_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
1261 proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
1262 address_tvb = tvb_new_subset(parameter_tvb, ADDRESS_PARAMETER_OFFSET, address_length, address_length);
1263 proto_item_append_text(parameter_item, " (Address: ");
1264 dissect_parameter(address_tvb, pinfo, parameter_tree, parameter_item, FALSE);
1265 proto_item_append_text(parameter_item, ", correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
1269 dissect_del_ip_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
1271 guint16 address_length;
1272 tvbuff_t *address_tvb;
1274 address_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
1276 proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
1277 address_tvb = tvb_new_subset(parameter_tvb, ADDRESS_PARAMETER_OFFSET, address_length, address_length);
1278 proto_item_append_text(parameter_item, " (Address: ");
1279 dissect_parameter(address_tvb, pinfo, parameter_tree, parameter_item, FALSE);
1280 proto_item_append_text(parameter_item, ", correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
1283 #define ERROR_CAUSE_IND_CASUES_OFFSET (CORRELATION_ID_OFFSET + CORRELATION_ID_LENGTH)
1286 dissect_error_cause_indication_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
1288 guint16 causes_length;
1289 tvbuff_t *causes_tvb;
1291 proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
1292 causes_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
1293 causes_tvb = tvb_new_subset(parameter_tvb, ERROR_CAUSE_IND_CASUES_OFFSET, causes_length, causes_length);
1294 dissect_error_causes(causes_tvb, pinfo, parameter_tree);
1298 dissect_set_primary_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
1300 guint16 address_length;
1301 tvbuff_t *address_tvb;
1303 address_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
1305 proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
1306 address_tvb = tvb_new_subset(parameter_tvb, ADDRESS_PARAMETER_OFFSET, address_length, address_length);
1307 proto_item_append_text(parameter_item, " (Address: ");
1308 dissect_parameter(address_tvb, pinfo, parameter_tree, parameter_item, FALSE);
1309 proto_item_append_text(parameter_item, ", correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
1313 dissect_success_report_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1315 proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
1316 proto_item_append_text(parameter_item, " (Correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
1319 #define ADAP_INDICATION_LENGTH 4
1320 #define ADAP_INDICATION_OFFSET PARAMETER_VALUE_OFFSET
1323 dissect_adap_indication_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1325 proto_tree_add_item(parameter_tree, hf_adap_indication, parameter_tvb, ADAP_INDICATION_OFFSET, ADAP_INDICATION_LENGTH, NETWORK_BYTE_ORDER);
1326 proto_item_append_text(parameter_item, " (Indication: %u)", tvb_get_ntohl(parameter_tvb, ADAP_INDICATION_OFFSET));
1330 dissect_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1332 guint16 type, parameter_value_length;
1334 type = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
1335 parameter_value_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1337 if (parameter_value_length > 0)
1338 proto_tree_add_item(parameter_tree, hf_parameter_value, parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length, NETWORK_BYTE_ORDER);
1340 proto_item_append_text(parameter_item, " (Type %u, value length: %u byte%s)", type, parameter_value_length, plurality(parameter_value_length, "", "s"));
1343 #define HEARTBEAT_INFO_PARAMETER_ID 0x0001
1344 #define IPV4ADDRESS_PARAMETER_ID 0x0005
1345 #define IPV6ADDRESS_PARAMETER_ID 0x0006
1346 #define STATE_COOKIE_PARAMETER_ID 0x0007
1347 #define UNREC_PARA_PARAMETER_ID 0x0008
1348 #define COOKIE_PRESERVATIVE_PARAMETER_ID 0x0009
1349 #define HOSTNAME_ADDRESS_PARAMETER_ID 0x000b
1350 #define SUPPORTED_ADDRESS_TYPES_PARAMETER_ID 0x000c
1351 #define OUTGOING_SSN_RESET_REQUEST_PARAMETER_ID 0x000d
1352 #define INCOMING_SSN_RESET_REQUEST_PARAMETER_ID 0x000e
1353 #define SSN_TSN_RESET_REQUEST_PARAMETER_ID 0x000f
1354 #define STREAM_RESET_RESPONSE_PARAMETER_ID 0x0010
1355 #define ECN_PARAMETER_ID 0x8000
1356 #define NONCE_SUPPORTED_PARAMETER_ID 0x8001
1357 #define RANDOM_PARAMETER_ID 0x8002
1358 #define CHUNKS_PARAMETER_ID 0x8003
1359 #define HMAC_ALGO_PARAMETER_ID 0x8004
1360 #define SUPPORTED_EXTENSIONS_PARAMETER_ID 0x8008
1361 #define FORWARD_TSN_SUPPORTED_PARAMETER_ID 0xC000
1362 #define ADD_IP_ADDRESS_PARAMETER_ID 0xC001
1363 #define DEL_IP_ADDRESS_PARAMETER_ID 0xC002
1364 #define ERROR_CAUSE_INDICATION_PARAMETER_ID 0xC003
1365 #define SET_PRIMARY_ADDRESS_PARAMETER_ID 0xC004
1366 #define SUCCESS_REPORT_PARAMETER_ID 0xC005
1367 #define ADAP_LAYER_INDICATION_PARAMETER_ID 0xC006
1369 static const value_string parameter_identifier_values[] = {
1370 { HEARTBEAT_INFO_PARAMETER_ID, "Heartbeat info" },
1371 { IPV4ADDRESS_PARAMETER_ID, "IPv4 address" },
1372 { IPV6ADDRESS_PARAMETER_ID, "IPv6 address" },
1373 { STATE_COOKIE_PARAMETER_ID, "State cookie" },
1374 { UNREC_PARA_PARAMETER_ID, "Unrecognized parameter" },
1375 { COOKIE_PRESERVATIVE_PARAMETER_ID, "Cookie preservative" },
1376 { HOSTNAME_ADDRESS_PARAMETER_ID, "Hostname address" },
1377 { OUTGOING_SSN_RESET_REQUEST_PARAMETER_ID, "Outgoing SSN reset request" },
1378 { INCOMING_SSN_RESET_REQUEST_PARAMETER_ID, "Incoming SSN reset request" },
1379 { SSN_TSN_RESET_REQUEST_PARAMETER_ID, "SSN/TSN reset request" },
1380 { STREAM_RESET_RESPONSE_PARAMETER_ID, "Stream reset response" },
1381 { SUPPORTED_ADDRESS_TYPES_PARAMETER_ID, "Supported address types" },
1382 { ECN_PARAMETER_ID, "ECN" },
1383 { NONCE_SUPPORTED_PARAMETER_ID, "Nonce supported" },
1384 { RANDOM_PARAMETER_ID, "Random" },
1385 { CHUNKS_PARAMETER_ID, "Authenticated Chunk list" },
1386 { HMAC_ALGO_PARAMETER_ID, "Requested HMAC Algorithm" },
1387 { SUPPORTED_EXTENSIONS_PARAMETER_ID, "Supported Extensions" },
1388 { FORWARD_TSN_SUPPORTED_PARAMETER_ID, "Forward TSN supported" },
1389 { ADD_IP_ADDRESS_PARAMETER_ID, "Add IP address" },
1390 { DEL_IP_ADDRESS_PARAMETER_ID, "Delete IP address" },
1391 { ERROR_CAUSE_INDICATION_PARAMETER_ID, "Error cause indication" },
1392 { SET_PRIMARY_ADDRESS_PARAMETER_ID, "Set primary address" },
1393 { SUCCESS_REPORT_PARAMETER_ID, "Success report" },
1394 { ADAP_LAYER_INDICATION_PARAMETER_ID, "Adaptation Layer Indication" },
1397 #define SCTP_PARAMETER_BIT_1 0x8000
1398 #define SCTP_PARAMETER_BIT_2 0x4000
1400 static const true_false_string sctp_parameter_bit_1_value = {
1401 "Skip parameter and continue processing of the chunk",
1402 "Stop processing of chunk"
1405 static const true_false_string sctp_parameter_bit_2_value = {
1411 dissect_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *additional_item, gboolean dissecting_init_init_ack_chunk)
1413 guint16 type, length, padding_length;
1414 proto_item *parameter_item;
1415 proto_tree *parameter_tree;
1416 proto_item *type_item;
1417 proto_tree *type_tree;
1419 type = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
1420 length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1421 padding_length = tvb_length(parameter_tvb) - length;
1423 if (!(chunk_tree || (dissecting_init_init_ack_chunk && (type == IPV4ADDRESS_PARAMETER_ID || type == IPV6ADDRESS_PARAMETER_ID))))
1427 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"));
1428 parameter_tree = proto_item_add_subtree(parameter_item, ett_sctp_chunk_parameter);
1430 type_item = proto_tree_add_item(parameter_tree, hf_parameter_type, parameter_tvb, PARAMETER_TYPE_OFFSET, PARAMETER_TYPE_LENGTH, NETWORK_BYTE_ORDER);
1431 type_tree = proto_item_add_subtree(type_item, ett_sctp_parameter_type);
1432 proto_tree_add_item(type_tree, hf_parameter_bit_1, parameter_tvb, PARAMETER_TYPE_OFFSET, PARAMETER_TYPE_LENGTH, NETWORK_BYTE_ORDER);
1433 proto_tree_add_item(type_tree, hf_parameter_bit_2, parameter_tvb, PARAMETER_TYPE_OFFSET, PARAMETER_TYPE_LENGTH, NETWORK_BYTE_ORDER);
1434 proto_tree_add_item(parameter_tree, hf_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
1436 parameter_item = NULL;
1437 parameter_tree = NULL;
1441 case HEARTBEAT_INFO_PARAMETER_ID:
1442 dissect_heartbeat_info_parameter(parameter_tvb, parameter_tree, parameter_item);
1444 case IPV4ADDRESS_PARAMETER_ID:
1445 dissect_ipv4_parameter(parameter_tvb, parameter_tree, parameter_item, additional_item, dissecting_init_init_ack_chunk);
1447 case IPV6ADDRESS_PARAMETER_ID:
1448 dissect_ipv6_parameter(parameter_tvb, parameter_tree, parameter_item, additional_item, dissecting_init_init_ack_chunk);
1450 case STATE_COOKIE_PARAMETER_ID:
1451 dissect_state_cookie_parameter(parameter_tvb, parameter_tree, parameter_item);
1453 case UNREC_PARA_PARAMETER_ID:
1454 dissect_unrecognized_parameters_parameter(parameter_tvb, pinfo, parameter_tree);
1456 case COOKIE_PRESERVATIVE_PARAMETER_ID:
1457 dissect_cookie_preservative_parameter(parameter_tvb, parameter_tree, parameter_item);
1459 case HOSTNAME_ADDRESS_PARAMETER_ID:
1460 dissect_hostname_parameter(parameter_tvb, parameter_tree, parameter_item);
1462 case SUPPORTED_ADDRESS_TYPES_PARAMETER_ID:
1463 dissect_supported_address_types_parameter(parameter_tvb, parameter_tree, parameter_item);
1465 case OUTGOING_SSN_RESET_REQUEST_PARAMETER_ID:
1466 dissect_outgoing_ssn_reset_request_parameter(parameter_tvb, parameter_tree, parameter_item);
1468 case INCOMING_SSN_RESET_REQUEST_PARAMETER_ID:
1469 dissect_incoming_ssn_reset_request_parameter(parameter_tvb, parameter_tree, parameter_item);
1471 case SSN_TSN_RESET_REQUEST_PARAMETER_ID:
1472 dissect_ssn_tsn_reset_request_parameter(parameter_tvb, parameter_tree, parameter_item);
1474 case STREAM_RESET_RESPONSE_PARAMETER_ID:
1475 dissect_stream_reset_response_parameter(parameter_tvb, parameter_tree, parameter_item);
1477 case ECN_PARAMETER_ID:
1478 dissect_ecn_parameter(parameter_tvb);
1480 case NONCE_SUPPORTED_PARAMETER_ID:
1481 dissect_nonce_supported_parameter(parameter_tvb);
1483 case RANDOM_PARAMETER_ID:
1484 dissect_random_parameter(parameter_tvb, parameter_tree);
1486 case CHUNKS_PARAMETER_ID:
1487 dissect_chunks_parameter(parameter_tvb, parameter_tree);
1489 case HMAC_ALGO_PARAMETER_ID:
1490 dissect_hmac_algo_parameter(parameter_tvb, parameter_tree);
1492 case SUPPORTED_EXTENSIONS_PARAMETER_ID:
1493 dissect_supported_extensions_parameter(parameter_tvb, parameter_tree, parameter_item);
1495 case FORWARD_TSN_SUPPORTED_PARAMETER_ID:
1496 dissect_forward_tsn_supported_parameter(parameter_tvb);
1498 case ADD_IP_ADDRESS_PARAMETER_ID:
1499 dissect_add_ip_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
1501 case DEL_IP_ADDRESS_PARAMETER_ID:
1502 dissect_del_ip_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
1504 case ERROR_CAUSE_INDICATION_PARAMETER_ID:
1505 dissect_error_cause_indication_parameter(parameter_tvb, pinfo, parameter_tree);
1507 case SET_PRIMARY_ADDRESS_PARAMETER_ID:
1508 dissect_set_primary_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
1510 case SUCCESS_REPORT_PARAMETER_ID:
1511 dissect_success_report_parameter(parameter_tvb, parameter_tree, parameter_item);
1513 case ADAP_LAYER_INDICATION_PARAMETER_ID:
1514 dissect_adap_indication_parameter(parameter_tvb, parameter_tree, parameter_item);
1517 dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
1521 if (padding_length > 0)
1522 proto_tree_add_item(parameter_tree, hf_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
1526 dissect_parameters(tvbuff_t *parameters_tvb, packet_info *pinfo, proto_tree *tree, proto_item *additional_item, gboolean dissecting_init_init_ack_chunk)
1528 gint offset, length, total_length, remaining_length;
1529 tvbuff_t *parameter_tvb;
1532 while((remaining_length = tvb_length_remaining(parameters_tvb, offset))) {
1533 if ((offset > 0) && additional_item)
1534 proto_item_append_text(additional_item, " ");
1535 length = tvb_get_ntohs(parameters_tvb, offset + PARAMETER_LENGTH_OFFSET);
1536 total_length = ADD_PADDING(length);
1537 if (remaining_length >= length)
1538 total_length = MIN(total_length, remaining_length);
1539 /* create a tvb for the parameter including the padding bytes */
1540 parameter_tvb = tvb_new_subset(parameters_tvb, offset, total_length, total_length);
1541 dissect_parameter(parameter_tvb, pinfo, tree, additional_item, dissecting_init_init_ack_chunk);
1542 /* get rid of the handled parameter */
1543 offset += total_length;
1549 * Code to handle error causes for ABORT and ERROR chunks
1553 #define CAUSE_CODE_LENGTH 2
1554 #define CAUSE_LENGTH_LENGTH 2
1555 #define CAUSE_HEADER_LENGTH (CAUSE_CODE_LENGTH + CAUSE_LENGTH_LENGTH)
1557 #define CAUSE_HEADER_OFFSET 0
1558 #define CAUSE_CODE_OFFSET CAUSE_HEADER_OFFSET
1559 #define CAUSE_LENGTH_OFFSET (CAUSE_CODE_OFFSET + CAUSE_CODE_LENGTH)
1560 #define CAUSE_INFO_OFFSET (CAUSE_LENGTH_OFFSET + CAUSE_LENGTH_LENGTH)
1563 #define CAUSE_STREAM_IDENTIFIER_LENGTH 2
1564 #define CAUSE_RESERVED_LENGTH 2
1565 #define CAUSE_STREAM_IDENTIFIER_OFFSET CAUSE_INFO_OFFSET
1566 #define CAUSE_RESERVED_OFFSET (CAUSE_STREAM_IDENTIFIER_OFFSET + CAUSE_STREAM_IDENTIFIER_LENGTH)
1569 dissect_invalid_stream_identifier_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
1571 proto_tree_add_item(cause_tree, hf_cause_stream_identifier, cause_tvb, CAUSE_STREAM_IDENTIFIER_OFFSET, CAUSE_STREAM_IDENTIFIER_LENGTH, NETWORK_BYTE_ORDER);
1572 proto_tree_add_item(cause_tree, hf_cause_reserved, cause_tvb, CAUSE_RESERVED_OFFSET, CAUSE_RESERVED_LENGTH, NETWORK_BYTE_ORDER);
1573 proto_item_append_text(cause_item, " (SID: %u)", tvb_get_ntohs(cause_tvb, CAUSE_STREAM_IDENTIFIER_OFFSET));
1576 #define CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH 4
1577 #define CAUSE_MISSING_PARAMETER_TYPE_LENGTH 2
1579 #define CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET CAUSE_INFO_OFFSET
1580 #define CAUSE_FIRST_MISSING_PARAMETER_TYPE_OFFSET (CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET + \
1581 CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH )
1584 dissect_missing_mandatory_parameters_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree)
1586 guint32 number_of_missing_parameters, missing_parameter_number;
1589 number_of_missing_parameters = tvb_get_ntohl(cause_tvb, CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET);
1590 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);
1591 offset = CAUSE_FIRST_MISSING_PARAMETER_TYPE_OFFSET;
1592 for(missing_parameter_number = 1; missing_parameter_number <= number_of_missing_parameters; missing_parameter_number++) {
1593 proto_tree_add_item(cause_tree, hf_cause_missing_parameter_type, cause_tvb, offset, CAUSE_MISSING_PARAMETER_TYPE_LENGTH, NETWORK_BYTE_ORDER);
1594 offset += CAUSE_MISSING_PARAMETER_TYPE_LENGTH;
1598 #define CAUSE_MEASURE_OF_STALENESS_LENGTH 4
1599 #define CAUSE_MEASURE_OF_STALENESS_OFFSET CAUSE_INFO_OFFSET
1602 dissect_stale_cookie_error_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
1604 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);
1605 proto_item_append_text(cause_item, " (Measure: %u usec)", tvb_get_ntohl(cause_tvb, CAUSE_MEASURE_OF_STALENESS_OFFSET));
1609 dissect_out_of_resource_cause(tvbuff_t *cause_tvb _U_)
1614 dissect_unresolvable_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
1616 guint16 parameter_length;
1617 tvbuff_t *parameter_tvb;
1619 parameter_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1620 parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, parameter_length, parameter_length);
1621 proto_item_append_text(cause_item, " (Address: ");
1622 dissect_parameter(parameter_tvb, pinfo, cause_tree, cause_item, FALSE);
1623 proto_item_append_text(cause_item, ")");
1627 dissect_sctp_chunk(tvbuff_t *chunk_tvb,
1630 proto_tree *sctp_tree,
1631 sctp_half_assoc_t* assoc,
1635 dissect_unrecognized_chunk_type_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
1637 guint16 chunk_length;
1638 guint8 unrecognized_type;
1639 tvbuff_t *unrecognized_chunk_tvb;
1641 chunk_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1642 unrecognized_chunk_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, chunk_length, chunk_length);
1643 dissect_sctp_chunk(unrecognized_chunk_tvb, pinfo, cause_tree,cause_tree, NULL, FALSE);
1644 unrecognized_type = tvb_get_guint8(unrecognized_chunk_tvb, CHUNK_TYPE_OFFSET);
1645 proto_item_append_text(cause_item, " (Type: %u (%s))", unrecognized_type, val_to_str(unrecognized_type, chunk_type_values, "unknown"));
1649 dissect_invalid_mandatory_parameter_cause(tvbuff_t *cause_tvb _U_)
1654 dissect_unrecognized_parameters_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree)
1656 guint16 cause_info_length;
1657 tvbuff_t *unrecognized_parameters_tvb;
1659 cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1661 unrecognized_parameters_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1662 dissect_parameters(unrecognized_parameters_tvb, pinfo, cause_tree, NULL, FALSE);
1665 #define CAUSE_TSN_LENGTH 4
1666 #define CAUSE_TSN_OFFSET CAUSE_INFO_OFFSET
1669 dissect_no_user_data_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
1671 proto_tree_add_item(cause_tree, hf_cause_tsn, cause_tvb, CAUSE_TSN_OFFSET, CAUSE_TSN_LENGTH, NETWORK_BYTE_ORDER);
1672 proto_item_append_text(cause_item, " (TSN: %u)", tvb_get_ntohl(cause_tvb, CAUSE_TSN_OFFSET));
1676 dissect_cookie_received_while_shutting_down_cause(tvbuff_t *cause_tvb _U_)
1681 dissect_restart_with_new_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree* cause_tree, proto_item *cause_item)
1683 guint16 cause_info_length;
1684 tvbuff_t *parameter_tvb;
1686 cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1687 parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1688 proto_item_append_text(cause_item, " (New addresses: ");
1689 dissect_parameters(parameter_tvb, pinfo, cause_tree, cause_item, FALSE);
1690 proto_item_append_text(cause_item, ")");
1694 dissect_user_initiated_abort_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree)
1696 guint16 cause_info_length;
1698 cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1699 if (cause_info_length > 0)
1700 proto_tree_add_item(cause_tree, hf_cause_info, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, NETWORK_BYTE_ORDER);
1704 dissect_protocol_violation_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree)
1706 guint16 cause_info_length;
1708 cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1709 if (cause_info_length > 0)
1710 proto_tree_add_item(cause_tree, hf_cause_info, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, NETWORK_BYTE_ORDER);
1714 dissect_delete_last_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
1716 guint16 cause_info_length;
1717 tvbuff_t *parameter_tvb;
1719 cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1720 parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1721 proto_item_append_text(cause_item, " (Last address: ");
1722 dissect_parameter(parameter_tvb, pinfo, cause_tree, cause_item, FALSE);
1723 proto_item_append_text(cause_item, ")");
1727 dissect_resource_outage_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree)
1729 guint16 cause_info_length;
1730 tvbuff_t *parameter_tvb;
1732 cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1733 parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1734 dissect_parameter(parameter_tvb, pinfo, cause_tree, NULL, FALSE);
1738 dissect_delete_source_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
1740 guint16 cause_info_length;
1741 tvbuff_t *parameter_tvb;
1743 cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1744 parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1745 proto_item_append_text(cause_item, " (Deleted address: ");
1746 dissect_parameter(parameter_tvb, pinfo, cause_tree, cause_item, FALSE);
1747 proto_item_append_text(cause_item, ")");
1751 dissect_request_refused_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree)
1753 guint16 cause_info_length;
1754 tvbuff_t *parameter_tvb;
1756 cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1757 parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1758 dissect_parameter(parameter_tvb, pinfo, cause_tree, NULL, FALSE);
1762 dissect_unsupported_hmac_id_cause(tvbuff_t *cause_tvb, packet_info *pinfo _U_, proto_tree *cause_tree)
1764 proto_tree_add_item(cause_tree, hf_hmac_id, cause_tvb, CAUSE_INFO_OFFSET, HMAC_ID_LENGTH, NETWORK_BYTE_ORDER);
1768 dissect_unknown_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
1770 guint16 cause_info_length;
1772 cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1773 if (cause_info_length > 0)
1774 proto_tree_add_item(cause_tree, hf_cause_info, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, NETWORK_BYTE_ORDER);
1775 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"));
1778 #define INVALID_STREAM_IDENTIFIER 0x01
1779 #define MISSING_MANDATORY_PARAMETERS 0x02
1780 #define STALE_COOKIE_ERROR 0x03
1781 #define OUT_OF_RESOURCE 0x04
1782 #define UNRESOLVABLE_ADDRESS 0x05
1783 #define UNRECOGNIZED_CHUNK_TYPE 0x06
1784 #define INVALID_MANDATORY_PARAMETER 0x07
1785 #define UNRECOGNIZED_PARAMETERS 0x08
1786 #define NO_USER_DATA 0x09
1787 #define COOKIE_RECEIVED_WHILE_SHUTTING_DOWN 0x0a
1788 #define RESTART_WITH_NEW_ADDRESSES 0x0b
1789 #define USER_INITIATED_ABORT 0x0c
1790 #define PROTOCOL_VIOLATION 0x0d
1791 #define REQUEST_TO_DELETE_LAST_ADDRESS 0x00a0
1792 #define OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE 0x00a1
1793 #define REQUEST_TO_DELETE_SOURCE_ADDRESS 0x00a2
1794 #define ABORT_DUE_TO_ILLEGAL_ASCONF 0x00a3
1795 #define REQUEST_REFUSED 0x00a4
1796 #define UNSUPPORTED_HMAC_ID 0x0105
1798 static const value_string cause_code_values[] = {
1799 { INVALID_STREAM_IDENTIFIER, "Invalid stream identifier" },
1800 { MISSING_MANDATORY_PARAMETERS, "Missing mandatory parameter" },
1801 { STALE_COOKIE_ERROR, "Stale cookie error" },
1802 { OUT_OF_RESOURCE, "Out of resource" },
1803 { UNRESOLVABLE_ADDRESS, "Unresolvable address" },
1804 { UNRECOGNIZED_CHUNK_TYPE, "Unrecognized chunk type" },
1805 { INVALID_MANDATORY_PARAMETER, "Invalid mandatory parameter" },
1806 { UNRECOGNIZED_PARAMETERS, "Unrecognized parameters" },
1807 { NO_USER_DATA, "No user data" },
1808 { COOKIE_RECEIVED_WHILE_SHUTTING_DOWN, "Cookie received while shutting down" },
1809 { RESTART_WITH_NEW_ADDRESSES, "Restart of an association with new addresses" },
1810 { USER_INITIATED_ABORT, "User initiated ABORT" },
1811 { PROTOCOL_VIOLATION, "Protocol violation" },
1812 { REQUEST_TO_DELETE_LAST_ADDRESS, "Request to delete last address" },
1813 { OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE, "Operation refused due to resource shortage" },
1814 { REQUEST_TO_DELETE_SOURCE_ADDRESS, "Request to delete source address" },
1815 { ABORT_DUE_TO_ILLEGAL_ASCONF, "Association Aborted due to illegal ASCONF-ACK" },
1816 { REQUEST_REFUSED, "Request refused - no authorization" },
1817 { UNSUPPORTED_HMAC_ID, "Unsupported HMAC identifier" },
1822 dissect_error_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *chunk_tree)
1824 guint16 code, length, padding_length;
1825 proto_item *cause_item;
1826 proto_tree *cause_tree;
1828 code = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET);
1829 length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
1830 padding_length = tvb_length(cause_tvb) - length;
1832 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"));
1833 cause_tree = proto_item_add_subtree(cause_item, ett_sctp_chunk_cause);
1835 proto_tree_add_item(cause_tree, hf_cause_code, cause_tvb, CAUSE_CODE_OFFSET, CAUSE_CODE_LENGTH, NETWORK_BYTE_ORDER);
1836 proto_tree_add_item(cause_tree, hf_cause_length, cause_tvb, CAUSE_LENGTH_OFFSET, CAUSE_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
1839 case INVALID_STREAM_IDENTIFIER:
1840 dissect_invalid_stream_identifier_cause(cause_tvb, cause_tree, cause_item);
1842 case MISSING_MANDATORY_PARAMETERS:
1843 dissect_missing_mandatory_parameters_cause(cause_tvb, cause_tree);
1845 case STALE_COOKIE_ERROR:
1846 dissect_stale_cookie_error_cause(cause_tvb, cause_tree, cause_item);
1848 case OUT_OF_RESOURCE:
1849 dissect_out_of_resource_cause(cause_tvb);
1851 case UNRESOLVABLE_ADDRESS:
1852 dissect_unresolvable_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
1854 case UNRECOGNIZED_CHUNK_TYPE:
1855 dissect_unrecognized_chunk_type_cause(cause_tvb, pinfo, cause_tree, cause_item);
1857 case INVALID_MANDATORY_PARAMETER:
1858 dissect_invalid_mandatory_parameter_cause(cause_tvb);
1860 case UNRECOGNIZED_PARAMETERS:
1861 dissect_unrecognized_parameters_cause(cause_tvb, pinfo, cause_tree);
1864 dissect_no_user_data_cause(cause_tvb, cause_tree, cause_item);
1866 case COOKIE_RECEIVED_WHILE_SHUTTING_DOWN:
1867 dissect_cookie_received_while_shutting_down_cause(cause_tvb);
1869 case RESTART_WITH_NEW_ADDRESSES:
1870 dissect_restart_with_new_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
1872 case USER_INITIATED_ABORT:
1873 dissect_user_initiated_abort_cause(cause_tvb, cause_tree);
1875 case PROTOCOL_VIOLATION:
1876 dissect_protocol_violation_cause(cause_tvb, cause_tree);
1878 case REQUEST_TO_DELETE_LAST_ADDRESS:
1879 dissect_delete_last_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
1881 case OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE:
1882 dissect_resource_outage_cause(cause_tvb, pinfo, cause_tree);
1884 case REQUEST_TO_DELETE_SOURCE_ADDRESS:
1885 dissect_delete_source_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
1887 case REQUEST_REFUSED:
1888 dissect_request_refused_cause(cause_tvb, pinfo, cause_tree);
1890 case UNSUPPORTED_HMAC_ID:
1891 dissect_unsupported_hmac_id_cause(cause_tvb, pinfo, cause_tree);
1894 dissect_unknown_cause(cause_tvb, cause_tree, cause_item);
1898 if (padding_length > 0)
1899 proto_tree_add_item(cause_tree, hf_cause_padding, cause_tvb, CAUSE_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
1903 dissect_error_causes(tvbuff_t *causes_tvb, packet_info *pinfo, proto_tree *tree)
1905 gint offset, length, total_length, remaining_length;
1906 tvbuff_t *cause_tvb;
1909 while((remaining_length = tvb_length_remaining(causes_tvb, offset))) {
1910 length = tvb_get_ntohs(causes_tvb, offset + CAUSE_LENGTH_OFFSET);
1911 total_length = ADD_PADDING(length);
1912 if (remaining_length >= length)
1913 total_length = MIN(total_length, remaining_length);
1914 /* create a tvb for the parameter including the padding bytes */
1915 cause_tvb = tvb_new_subset(causes_tvb, offset, total_length, total_length);
1916 dissect_error_cause(cause_tvb, pinfo, tree);
1917 /* get rid of the handled cause */
1918 offset += total_length;
1924 * Code to actually dissect the packets
1927 static gboolean try_heuristic_first = FALSE;
1930 dissect_payload(tvbuff_t *payload_tvb, packet_info *pinfo, proto_tree *tree, guint32 ppi)
1932 guint32 low_port, high_port;
1936 if (enable_ulp_dissection) {
1937 if (try_heuristic_first) {
1938 /* do lookup with the heuristic subdissector table */
1939 if (dissector_try_heuristic(sctp_heur_subdissector_list, payload_tvb, pinfo, tree))
1943 /* Do lookups with the subdissector table.
1945 When trying port numbers, we try the port number with the lower value
1946 first, followed by the port number with the higher value. This means
1947 that, for packets where a dissector is registered for *both* port
1948 numbers, and where there's no match on the PPI:
1950 1) we pick the same dissector for traffic going in both directions;
1952 2) we prefer the port number that's more likely to be the right
1953 one (as that prefers well-known ports to reserved ports);
1955 although there is, of course, no guarantee that any such strategy
1956 will always pick the right port number.
1958 XXX - we ignore port numbers of 0, as some dissectors use a port
1959 number of 0 to disable the port. */
1960 if (dissector_try_port(sctp_ppi_dissector_table, ppi, payload_tvb, pinfo, tree))
1962 if (pinfo->srcport > pinfo->destport) {
1963 low_port = pinfo->destport;
1964 high_port = pinfo->srcport;
1966 low_port = pinfo->srcport;
1967 high_port = pinfo->destport;
1969 if (low_port != 0 &&
1970 dissector_try_port(sctp_port_dissector_table, low_port, payload_tvb, pinfo, tree))
1972 if (high_port != 0 &&
1973 dissector_try_port(sctp_port_dissector_table, high_port, payload_tvb, pinfo, tree))
1976 if (!try_heuristic_first) {
1977 /* do lookup with the heuristic subdissector table */
1978 if (dissector_try_heuristic(sctp_heur_subdissector_list, payload_tvb, pinfo, tree))
1982 /* Oh, well, we don't know this; dissect it as data. */
1983 call_dissector(data_handle, payload_tvb, pinfo, tree);
1987 #define DATA_CHUNK_TSN_LENGTH 4
1988 #define DATA_CHUNK_STREAM_ID_LENGTH 2
1989 #define DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH 2
1990 #define DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH 4
1992 #define DATA_CHUNK_TSN_OFFSET (CHUNK_VALUE_OFFSET + 0)
1993 #define DATA_CHUNK_STREAM_ID_OFFSET (DATA_CHUNK_TSN_OFFSET + DATA_CHUNK_TSN_LENGTH)
1994 #define DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET (DATA_CHUNK_STREAM_ID_OFFSET + \
1995 DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH)
1996 #define DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET (DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET + \
1997 DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH)
1998 #define DATA_CHUNK_PAYLOAD_OFFSET (DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET + \
1999 DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH)
2001 #define DATA_CHUNK_HEADER_LENGTH (CHUNK_HEADER_LENGTH + \
2002 DATA_CHUNK_TSN_LENGTH + \
2003 DATA_CHUNK_STREAM_ID_LENGTH + \
2004 DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH + \
2005 DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH)
2007 #define SCTP_DATA_CHUNK_E_BIT 0x01
2008 #define SCTP_DATA_CHUNK_B_BIT 0x02
2009 #define SCTP_DATA_CHUNK_U_BIT 0x04
2010 #define SCTP_DATA_CHUNK_I_BIT 0x08
2012 /* table to hold fragmented SCTP messages */
2013 static GHashTable *frag_table = NULL;
2016 typedef struct _frag_key {
2019 guint32 verification_tag;
2021 guint16 stream_seq_num;
2026 frag_equal(gconstpointer k1, gconstpointer k2)
2028 const frag_key* key1 = (const frag_key*) k1;
2029 const frag_key* key2 = (const frag_key*) k2;
2031 return ( (key1->sport == key2->sport) &&
2032 (key1->dport == key1->dport) &&
2033 (key1->verification_tag == key1->verification_tag) &&
2034 (key1->stream_id == key1->stream_id) &&
2035 (key1->stream_seq_num == key1->stream_seq_num)
2041 frag_hash(gconstpointer k)
2043 const frag_key* key = (const frag_key*) k;
2045 return key->sport ^ key->dport ^ key->verification_tag ^
2046 key->stream_id ^ key->stream_seq_num;
2052 frag_free_msgs(sctp_frag_msg *msg)
2054 sctp_frag_be *beginend;
2055 sctp_fragment *fragment;
2057 /* free all begins */
2058 while (msg->begins) {
2059 beginend = msg->begins;
2060 msg->begins = msg->begins->next;
2066 beginend = msg->ends;
2067 msg->ends = msg->ends->next;
2071 /* free all fragments */
2072 while (msg->fragments) {
2073 fragment = msg->fragments;
2074 msg->fragments = msg->fragments->next;
2075 g_free(fragment->data);
2079 /* msg->messages is se_ allocated, no need to free it */
2085 free_table_entry(gpointer key, gpointer value, gpointer user_data _U_)
2087 sctp_frag_msg *msg = value;
2088 frag_key *fkey = key;
2090 frag_free_msgs(msg);
2096 frag_table_init(void)
2098 /* destroy an existing hast table and create a new one */
2100 g_hash_table_foreach_remove(frag_table, free_table_entry, NULL);
2101 g_hash_table_destroy(frag_table);
2105 frag_table = g_hash_table_new(frag_hash, frag_equal);
2109 static sctp_frag_msg*
2110 find_message(guint16 stream_id, guint16 stream_seq_num)
2114 key.sport = sctp_info.sport;
2115 key.dport = sctp_info.dport;
2116 key.verification_tag = sctp_info.verification_tag;
2117 key.stream_id = stream_id;
2118 key.stream_seq_num = stream_seq_num;
2120 return g_hash_table_lookup(frag_table, &key);
2124 static sctp_fragment*
2125 find_fragment(guint32 tsn, guint16 stream_id, guint16 stream_seq_num)
2128 sctp_fragment *next_fragment;
2130 msg = find_message(stream_id, stream_seq_num);
2133 next_fragment = msg->fragments;
2134 while (next_fragment) {
2135 if (next_fragment->tsn == tsn)
2136 return next_fragment;
2137 next_fragment = next_fragment->next;
2145 static sctp_fragment*
2146 add_fragment(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 tsn,
2147 guint16 stream_id, guint16 stream_seq_num, guint8 b_bit, guint8 e_bit)
2150 sctp_fragment *fragment, *last_fragment;
2151 sctp_frag_be *beginend, *last_beginend;
2154 /* lookup message. if not found, create it */
2155 msg = find_message(stream_id, stream_seq_num);
2158 msg = g_malloc (sizeof (sctp_frag_msg));
2161 msg->fragments = NULL;
2162 msg->messages = NULL;
2165 key = g_malloc(sizeof (frag_key));
2166 key->sport = sctp_info.sport;
2167 key->dport = sctp_info.dport;
2168 key->verification_tag = sctp_info.verification_tag;
2169 key->stream_id = stream_id;
2170 key->stream_seq_num = stream_seq_num;
2172 g_hash_table_insert(frag_table, key, msg);
2175 /* lookup segment. if not found, create it */
2176 fragment = find_fragment(tsn, stream_id, stream_seq_num);
2179 /* this fragment is already known.
2180 * compare frame number to check if it's a duplicate
2182 if (fragment->frame_num == pinfo->fd->num) {
2185 /* there already is a fragment having the same ports, v_tag,
2186 * stream id, stream_seq_num and tsn but it appeared in a different
2187 * frame, so it must be a duplicate fragment. maybe a retransmission?
2188 * Mark it as duplicate and return NULL
2190 if (check_col(pinfo->cinfo, COL_INFO))
2191 col_append_str(pinfo->cinfo, COL_INFO, " (Duplicate Message Fragment)");
2193 proto_tree_add_uint(tree, hf_sctp_duplicate, tvb, 0, 0, fragment->frame_num);
2198 /* create new fragment */
2199 fragment = g_malloc (sizeof (sctp_fragment));
2200 fragment->frame_num = pinfo->fd->num;
2201 fragment->tsn = tsn;
2202 fragment->len = tvb_length(tvb);
2203 fragment->next = NULL;
2204 if (fragment->len) {
2205 fragment->data = g_malloc (fragment->len);
2206 tvb_memcpy(tvb, fragment->data, 0, fragment->len);
2209 /* add new fragment to linked list. sort ascending by tsn */
2210 if (!msg->fragments)
2211 msg->fragments = fragment;
2213 if (msg->fragments->tsn > fragment->tsn) {
2214 fragment->next = msg->fragments;
2215 msg->fragments = fragment;
2217 last_fragment = msg->fragments;
2218 while (last_fragment->next &&
2219 last_fragment->next->tsn < fragment->tsn)
2220 last_fragment = last_fragment->next;
2222 fragment->next = last_fragment->next;
2223 last_fragment->next = fragment;
2228 /* save begin or end if neccessary */
2229 if (b_bit && !e_bit) {
2230 beginend = g_malloc (sizeof (sctp_frag_be));
2231 beginend->fragment = fragment;
2232 beginend->next = NULL;
2234 /* add begin to linked list. sort descending by tsn */
2236 msg->begins = beginend;
2238 if (msg->begins->fragment->tsn < beginend->fragment->tsn) {
2239 beginend->next = msg->begins;
2240 msg->begins = beginend;
2242 last_beginend = msg->begins;
2243 while (last_beginend->next &&
2244 last_beginend->next->fragment->tsn > beginend->fragment->tsn)
2245 last_beginend = last_beginend->next;
2247 beginend->next = last_beginend->next;
2248 last_beginend->next = beginend;
2254 if (!b_bit && e_bit) {
2255 beginend = g_malloc (sizeof (sctp_frag_be));
2256 beginend->fragment = fragment;
2257 beginend->next = NULL;
2259 /* add end to linked list. sort ascending by tsn */
2261 msg->ends = beginend;
2263 if (msg->ends->fragment->tsn > beginend->fragment->tsn) {
2264 beginend->next = msg->ends;
2265 msg->ends = beginend;
2267 last_beginend = msg->ends;
2268 while (last_beginend->next &&
2269 last_beginend->next->fragment->tsn < beginend->fragment->tsn)
2270 last_beginend = last_beginend->next;
2272 beginend->next = last_beginend->next;
2273 last_beginend->next = beginend;
2283 fragment_reassembly(tvbuff_t *tvb, sctp_fragment* fragment,
2284 packet_info *pinfo, proto_tree *tree, guint16 stream_id,
2285 guint16 stream_seq_num)
2288 sctp_complete_msg *message, *last_message;
2289 sctp_fragment *frag_i, *last_frag, *first_frag;
2290 sctp_frag_be *begin, *end, *beginend;
2291 guint32 len, offset = 0;
2292 tvbuff_t* new_tvb = NULL;
2296 msg = find_message(stream_id, stream_seq_num);
2299 /* no message, we can't do anything */
2303 /* check if fragment is part of an already reassembled message */
2304 for (message = msg->messages;
2306 !(message->begin <= fragment->tsn && message->end >= fragment->tsn) &&
2307 !(message->begin > message->end &&
2308 (message->begin <= fragment->tsn || message->end >= fragment->tsn));
2309 message = message->next);
2312 /* we found the reassembled message this fragment belongs to */
2313 if (fragment == message->reassembled_in) {
2315 /* this is the last fragment, create data source */
2316 new_tvb = tvb_new_child_real_data(tvb, message->data, message->len, message->len);
2317 add_new_data_source(pinfo, new_tvb, "Reassembled SCTP Message");
2319 /* display reassembly info */
2320 item = proto_tree_add_item(tree, hf_sctp_fragments, tvb, 0, -1, FALSE);
2321 ptree = proto_item_add_subtree(item, ett_sctp_fragments);
2322 proto_item_append_text(item, " (%u bytes, %u fragments): ",
2323 message->len, message->end - message->begin + 1);
2325 if (message->begin > message->end) {
2326 for (frag_i = find_fragment(message->begin, stream_id, stream_seq_num);
2328 frag_i = frag_i->next) {
2330 proto_tree_add_uint_format(ptree, hf_sctp_fragment, new_tvb, offset, frag_i->len,
2331 frag_i->frame_num, "Frame: %u, payload: %u-%u (%u bytes)",
2332 frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
2333 offset += frag_i->len;
2336 for (frag_i = msg->fragments;
2337 frag_i && frag_i->tsn <= message->end;
2338 frag_i = frag_i->next) {
2340 proto_tree_add_uint_format(ptree, hf_sctp_fragment, new_tvb, offset, frag_i->len,
2341 frag_i->frame_num, "Frame: %u, payload: %u-%u (%u bytes)",
2342 frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
2343 offset += frag_i->len;
2346 for (frag_i = find_fragment(message->begin, stream_id, stream_seq_num);
2347 frag_i && frag_i->tsn <= message->end;
2348 frag_i = frag_i->next) {
2350 proto_tree_add_uint_format(ptree, hf_sctp_fragment, new_tvb, offset, frag_i->len,
2351 frag_i->frame_num, "Frame: %u, payload: %u-%u (%u bytes)",
2352 frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
2353 offset += frag_i->len;
2360 /* this is not the last fragment,
2361 * so let the user know the frame where the reassembly is
2363 if (check_col(pinfo->cinfo, COL_INFO))
2364 col_append_str(pinfo->cinfo, COL_INFO, " (Message Fragment) ");
2366 proto_tree_add_uint(tree, hf_sctp_reassembled_in, tvb, 0, 0, message->reassembled_in->frame_num);
2370 /* this fragment has not been reassembled, yet
2371 * check now if we can reassemble it
2372 * at first look for the first and last tsn of the msg
2374 for (begin = msg->begins;
2375 begin && begin->fragment->tsn > fragment->tsn;
2376 begin = begin->next);
2378 /* in case begin still is null, set it to first (highest) begin
2379 * maybe the message tsn restart at 0 in between
2382 begin = msg->begins;
2384 for (end = msg->ends;
2385 end && end->fragment->tsn < fragment->tsn;
2388 /* in case end still is null, set it to first (lowest) end
2389 * maybe the message tsn restart at 0 in between
2394 if (!begin || !end || !msg->fragments ||
2395 (begin->fragment->tsn > end->fragment->tsn && msg->fragments->tsn)) {
2396 /* begin and end have not been collected, yet
2397 * or there might be a tsn restart but the first fragment hasn't a tsn of 0
2398 * just mark as fragment
2401 if (check_col(pinfo->cinfo, COL_INFO))
2402 col_append_str(pinfo->cinfo, COL_INFO, " (Message Fragment) ");
2407 /* we found possible begin and end
2408 * look for the first fragment and then try to get to the end
2410 first_frag = begin->fragment;
2412 /* while looking if all fragments are there
2413 * we can calculate the overall length that
2414 * we need in case of success
2416 len = first_frag->len;
2418 /* check if begin is past end
2419 * this can happen if there has been a tsn restart
2420 * or we just got the wrong begin and end
2423 if (begin->fragment->tsn > end->fragment->tsn) {
2424 for (last_frag = first_frag, frag_i = first_frag->next;
2425 frag_i && frag_i->tsn == (last_frag->tsn + 1);
2426 last_frag = frag_i, frag_i = frag_i->next) len += frag_i->len;
2428 /* check if we reached the last possible tsn
2429 * if yes, restart and continue
2431 if ((last_frag->tsn + 1)) {
2432 /* there are just fragments missing */
2433 if (check_col(pinfo->cinfo, COL_INFO))
2434 col_append_str(pinfo->cinfo, COL_INFO, " (Message Fragment) ");
2439 /* we got all fragments until the last possible tsn
2440 * and the first is 0 if we got here
2443 len += msg->fragments->len;
2444 for (last_frag = msg->fragments, frag_i = last_frag->next;
2445 frag_i && frag_i->tsn < end->fragment->tsn && frag_i->tsn == (last_frag->tsn + 1);
2446 last_frag = frag_i, frag_i = frag_i->next) len += frag_i->len;
2449 for (last_frag = first_frag, frag_i = first_frag->next;
2450 frag_i && frag_i->tsn < end->fragment->tsn && frag_i->tsn == (last_frag->tsn + 1);
2451 last_frag = frag_i, frag_i = frag_i->next) len += frag_i->len;
2454 if (!frag_i || frag_i != end->fragment || frag_i->tsn != (last_frag->tsn + 1)) {
2455 /* we need more fragments. just mark as fragment */
2456 if (check_col(pinfo->cinfo, COL_INFO))
2457 col_append_str(pinfo->cinfo, COL_INFO, " (Message Fragment) ");
2462 /* ok, this message is complete, we can reassemble it
2463 * but at first don't forget to add the length of the last fragment
2467 message = se_alloc (sizeof (sctp_complete_msg));
2468 message->begin = begin->fragment->tsn;
2469 message->end = end->fragment->tsn;
2470 message->reassembled_in = fragment;
2472 message->data = se_alloc(len);
2473 message->next = NULL;
2475 /* now copy all fragments */
2476 if (begin->fragment->tsn > end->fragment->tsn) {
2477 /* a tsn restart has occured */
2478 for (frag_i = first_frag;
2480 frag_i = frag_i->next) {
2482 if (frag_i->len && frag_i->data)
2483 memcpy(message->data + offset, frag_i->data, frag_i->len);
2484 offset += frag_i->len;
2486 /* release fragment data */
2487 g_free(frag_i->data);
2488 frag_i->data = NULL;
2491 for (frag_i = msg->fragments;
2492 frag_i && frag_i->tsn <= end->fragment->tsn;
2493 frag_i = frag_i->next) {
2495 if (frag_i->len && frag_i->data)
2496 memcpy(message->data + offset, frag_i->data, frag_i->len);
2497 offset += frag_i->len;
2499 /* release fragment data */
2500 g_free(frag_i->data);
2501 frag_i->data = NULL;
2505 for (frag_i = first_frag;
2506 frag_i && frag_i->tsn <= end->fragment->tsn;
2507 frag_i = frag_i->next) {
2509 if (frag_i->len && frag_i->data)
2510 memcpy(message->data + offset, frag_i->data, frag_i->len);
2511 offset += frag_i->len;
2513 /* release fragment data */
2514 g_free(frag_i->data);
2515 frag_i->data = NULL;
2520 if (!msg->messages) {
2521 msg->messages = message;
2523 for (last_message = msg->messages;
2525 last_message = last_message->next);
2527 last_message->next = message;
2530 /* remove begin and end from list */
2531 if (msg->begins == begin) {
2532 msg->begins = begin->next;
2534 for (beginend = msg->begins;
2535 beginend && beginend->next != begin;
2536 beginend = beginend->next);
2537 if (beginend && beginend->next == begin)
2538 beginend->next = begin->next;
2542 if (msg->ends == end) {
2543 msg->ends = end->next;
2545 for (beginend = msg->ends;
2546 beginend && beginend->next != end;
2547 beginend = beginend->next);
2548 if (beginend && beginend->next == end)
2549 beginend->next = end->next;
2553 /* create data source */
2554 new_tvb = tvb_new_child_real_data(tvb, message->data, len, len);
2555 add_new_data_source(pinfo, new_tvb, "Reassembled SCTP Message");
2557 /* display reassembly info */
2558 item = proto_tree_add_item(tree, hf_sctp_fragments, tvb, 0, -1, FALSE);
2559 ptree = proto_item_add_subtree(item, ett_sctp_fragments);
2560 proto_item_append_text(item, " (%u bytes, %u fragments): ",
2561 message->len, message->end - message->begin + 1);
2563 if (message->begin > message->end) {
2564 for (frag_i = find_fragment(message->begin, stream_id, stream_seq_num);
2566 frag_i = frag_i->next) {
2568 proto_tree_add_uint_format(ptree, hf_sctp_fragment, new_tvb, offset, frag_i->len,
2569 frag_i->frame_num, "Frame: %u, payload: %u-%u (%u bytes)",
2570 frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
2571 offset += frag_i->len;
2574 for (frag_i = msg->fragments;
2575 frag_i && frag_i->tsn <= message->end;
2576 frag_i = frag_i->next) {
2578 proto_tree_add_uint_format(ptree, hf_sctp_fragment, new_tvb, offset, frag_i->len,
2579 frag_i->frame_num, "Frame: %u, payload: %u-%u (%u bytes)",
2580 frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
2581 offset += frag_i->len;
2584 for (frag_i = find_fragment(message->begin, stream_id, stream_seq_num);
2585 frag_i && frag_i->tsn <= message->end;
2586 frag_i = frag_i->next) {
2588 proto_tree_add_uint_format(ptree, hf_sctp_fragment, new_tvb, offset, frag_i->len,
2589 frag_i->frame_num, "Frame: %u, payload: %u-%u (%u bytes)",
2590 frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
2591 offset += frag_i->len;
2595 /* it's not fragmented anymore */
2596 pinfo->fragmented = FALSE;
2603 dissect_fragmented_payload(tvbuff_t *payload_tvb, packet_info *pinfo, proto_tree *tree,
2604 proto_tree *chunk_tree, guint32 tsn, guint32 ppi, guint16 stream_id,
2605 guint16 stream_seq_num, guint8 b_bit, guint8 e_bit)
2607 sctp_fragment* fragment;
2608 tvbuff_t* new_tvb = NULL;
2610 /* add fragement to list of known fragments. returns NULL if segment is a duplicate */
2611 fragment = add_fragment(payload_tvb, pinfo, chunk_tree, tsn, stream_id, stream_seq_num, b_bit, e_bit);
2614 new_tvb = fragment_reassembly(payload_tvb, fragment, pinfo, chunk_tree, stream_id, stream_seq_num);
2616 /* pass reassembled data to next dissector, if possible */
2618 return dissect_payload(new_tvb, pinfo, tree, ppi);
2620 /* no reassembly done, do nothing */
2624 static const true_false_string sctp_data_chunk_e_bit_value = {
2626 "Not the last segment"
2629 static const true_false_string sctp_data_chunk_b_bit_value = {
2631 "Subsequent segment"
2634 static const true_false_string sctp_data_chunk_u_bit_value = {
2635 "Unordered delivery",
2639 static const true_false_string sctp_data_chunk_i_bit_value = {
2640 "Send SACK immediately",
2641 "Possibly delay SACK"
2645 dissect_data_chunk(tvbuff_t *chunk_tvb,
2646 guint16 chunk_length,
2649 proto_tree *chunk_tree,
2650 proto_item *chunk_item,
2651 proto_item *flags_item,
2652 sctp_half_assoc_t* ha)
2654 guint number_of_ppid;
2655 guint32 payload_proto_id;
2656 tvbuff_t *payload_tvb;
2657 proto_tree *flags_tree;
2658 guint8 e_bit, b_bit, u_bit;
2659 guint16 stream_id, stream_seq_num = 0;
2661 proto_item* tsn_item = NULL;
2663 if (chunk_length <= DATA_CHUNK_HEADER_LENGTH) {
2664 proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
2665 chunk_length, DATA_CHUNK_HEADER_LENGTH);
2668 payload_proto_id = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET);
2670 /* insert the PPID in the pinfo structure if it is non-zero, not already there and there is still room */
2671 if (payload_proto_id) {
2672 for(number_of_ppid = 0; number_of_ppid < MAX_NUMBER_OF_PPIDS; number_of_ppid++)
2673 if ((pinfo->ppids[number_of_ppid] == 0) || (pinfo->ppids[number_of_ppid] == payload_proto_id))
2675 if ((number_of_ppid < MAX_NUMBER_OF_PPIDS) && (pinfo->ppids[number_of_ppid] == 0))
2676 pinfo->ppids[number_of_ppid] = payload_proto_id;
2679 e_bit = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_DATA_CHUNK_E_BIT;
2680 b_bit = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_DATA_CHUNK_B_BIT;
2681 u_bit = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_DATA_CHUNK_U_BIT;
2682 stream_id = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET);
2683 stream_seq_num = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET);
2684 tsn = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_TSN_OFFSET);
2687 proto_item_set_len(chunk_item, DATA_CHUNK_HEADER_LENGTH);
2688 flags_tree = proto_item_add_subtree(flags_item, ett_sctp_data_chunk_flags);
2689 proto_tree_add_item(flags_tree, hf_data_chunk_e_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
2690 proto_tree_add_item(flags_tree, hf_data_chunk_b_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
2691 proto_tree_add_item(flags_tree, hf_data_chunk_u_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
2692 proto_tree_add_item(flags_tree, hf_data_chunk_i_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
2693 tsn_item = proto_tree_add_item(chunk_tree, hf_data_chunk_tsn, chunk_tvb, DATA_CHUNK_TSN_OFFSET, DATA_CHUNK_TSN_LENGTH, NETWORK_BYTE_ORDER);
2694 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);
2695 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);
2696 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);
2698 proto_item_append_text(chunk_item, "(%s, ", (u_bit) ? "unordered" : "ordered");
2701 proto_item_append_text(chunk_item, "complete");
2703 proto_item_append_text(chunk_item, "first");
2706 proto_item_append_text(chunk_item, "last");
2708 proto_item_append_text(chunk_item, "middle");
2711 proto_item_append_text(chunk_item, " segment, TSN: %u, SID: %u, SSN: %u, PPID: %u, payload length: %u byte%s)",
2712 tvb_get_ntohl(chunk_tvb, DATA_CHUNK_TSN_OFFSET),
2713 tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET),
2714 tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET),
2716 chunk_length - DATA_CHUNK_HEADER_LENGTH, plurality(chunk_length - DATA_CHUNK_HEADER_LENGTH, "", "s"));
2719 sctp_tsn(pinfo, chunk_tvb, tsn_item, ha, tsn);
2722 payload_tvb = tvb_new_subset(chunk_tvb, DATA_CHUNK_PAYLOAD_OFFSET, chunk_length - DATA_CHUNK_HEADER_LENGTH, chunk_length - DATA_CHUNK_HEADER_LENGTH);
2724 /* Is this a fragment? */
2725 if (b_bit && e_bit) {
2726 /* No - just call the subdissector. */
2727 return dissect_payload(payload_tvb, pinfo, tree, payload_proto_id);
2730 pinfo->fragmented = TRUE;
2732 /* if reassembly is off just mark as fragment for next dissector and proceed */
2733 if (!use_reassembly)
2735 /* Don't pass on non-first fragments since the next dissector will
2736 * almost certainly not understand the data.
2740 volatile gboolean retval = FALSE;
2743 * If this particular fragment happens to get a ReportedBoundsError
2744 * exception (which in fact we expect it to since it's a fragment),
2745 * don't stop dissecting chunks within this frame.
2747 * If it gets a BoundsError, we can stop, as there's nothing more to
2748 * see, so we just re-throw it.
2751 retval = dissect_payload(payload_tvb, pinfo, tree, payload_proto_id);
2753 CATCH(BoundsError) {
2756 CATCH(ReportedBoundsError) {
2757 show_reported_bounds_error(payload_tvb, pinfo, tree);
2768 /* if unordered set stream_seq_num to 0 for easier handling */
2772 /* start reassembly */
2773 return dissect_fragmented_payload(payload_tvb, pinfo, tree, chunk_tree, tsn, payload_proto_id, stream_id, stream_seq_num, b_bit, e_bit);
2777 #define INIT_CHUNK_INITIATE_TAG_LENGTH 4
2778 #define INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH 4
2779 #define INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH 2
2780 #define INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH 2
2781 #define INIT_CHUNK_INITIAL_TSN_LENGTH 4
2782 #define INIT_CHUNK_FIXED_PARAMTERS_LENGTH (CHUNK_HEADER_LENGTH + \
2783 INIT_CHUNK_INITIATE_TAG_LENGTH + \
2784 INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH + \
2785 INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH + \
2786 INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH + \
2787 INIT_CHUNK_INITIAL_TSN_LENGTH)
2789 #define INIT_CHUNK_INITIATE_TAG_OFFSET CHUNK_VALUE_OFFSET
2790 #define INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET (INIT_CHUNK_INITIATE_TAG_OFFSET + \
2791 INIT_CHUNK_INITIATE_TAG_LENGTH )
2792 #define INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET (INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET + \
2793 INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH )
2794 #define INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET (INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET + \
2795 INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH )
2796 #define INIT_CHUNK_INITIAL_TSN_OFFSET (INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET + \
2797 INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH )
2798 #define INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET (INIT_CHUNK_INITIAL_TSN_OFFSET + \
2799 INIT_CHUNK_INITIAL_TSN_LENGTH )
2802 dissect_init_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
2804 tvbuff_t *parameters_tvb;
2805 proto_item *hidden_item;
2807 if (chunk_length < INIT_CHUNK_FIXED_PARAMTERS_LENGTH) {
2808 proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
2810 INIT_CHUNK_FIXED_PARAMTERS_LENGTH);
2814 /* handle fixed parameters */
2815 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);
2816 hidden_item = proto_tree_add_item(chunk_tree, hf_initiate_tag, chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET, INIT_CHUNK_INITIATE_TAG_LENGTH, NETWORK_BYTE_ORDER);
2817 PROTO_ITEM_SET_HIDDEN(hidden_item);
2818 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);
2819 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);
2820 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);
2821 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);
2823 proto_item_append_text(chunk_item, " (Outbound streams: %u, inbound streams: %u)",
2824 tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET),
2825 tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET));
2827 /* handle variable parameters */
2828 chunk_length -= INIT_CHUNK_FIXED_PARAMTERS_LENGTH;
2829 parameters_tvb = tvb_new_subset(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET, chunk_length, chunk_length);
2830 dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, TRUE);
2834 dissect_init_ack_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
2836 tvbuff_t *parameters_tvb;
2837 proto_item *hidden_item;
2839 if (chunk_length < INIT_CHUNK_FIXED_PARAMTERS_LENGTH) {
2840 proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
2842 INIT_CHUNK_FIXED_PARAMTERS_LENGTH);
2846 /* handle fixed parameters */
2847 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);
2848 hidden_item = proto_tree_add_item(chunk_tree, hf_initiate_tag, chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET, INIT_CHUNK_INITIATE_TAG_LENGTH, NETWORK_BYTE_ORDER);
2849 PROTO_ITEM_SET_HIDDEN(hidden_item);
2850 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);
2851 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);
2852 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);
2853 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);
2855 proto_item_append_text(chunk_item, " (Outbound streams: %u, inbound streams: %u)",
2856 tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET),
2857 tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET));
2859 /* handle variable paramters */
2860 chunk_length -= INIT_CHUNK_FIXED_PARAMTERS_LENGTH;
2861 parameters_tvb = tvb_new_subset(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET, chunk_length, chunk_length);
2862 dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, TRUE);
2865 #define SCTP_SACK_CHUNK_NS_BIT 0x01
2866 #define SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH 4
2867 #define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH 4
2868 #define SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH 2
2869 #define SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH 2
2870 #define SACK_CHUNK_GAP_BLOCK_LENGTH 4
2871 #define SACK_CHUNK_GAP_BLOCK_START_LENGTH 2
2872 #define SACK_CHUNK_GAP_BLOCK_END_LENGTH 2
2873 #define SACK_CHUNK_DUP_TSN_LENGTH 4
2875 #define SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET (CHUNK_VALUE_OFFSET + 0)
2876 #define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET (SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET + \
2877 SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH)
2878 #define SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET (SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET + \
2879 SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH)
2880 #define SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET (SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET + \
2881 SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH)
2882 #define SACK_CHUNK_GAP_BLOCK_OFFSET (SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET + \
2883 SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH)
2887 dissect_sack_chunk(packet_info* pinfo, tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item, sctp_half_assoc_t* ha)
2889 guint16 number_of_gap_blocks, number_of_dup_tsns;
2890 guint16 gap_block_number, dup_tsn_number, start, end;
2891 gint gap_block_offset, dup_tsn_offset;
2892 guint32 cum_tsn_ack;
2893 proto_item *block_item;
2894 proto_tree *block_tree;
2895 proto_tree *flags_tree;
2896 proto_item *ctsa_item;
2897 proto_item *a_rwnd_item;
2898 proto_tree *acks_tree;
2899 guint32 tsns_gap_acked = 0;
2902 flags_tree = proto_item_add_subtree(flags_item, ett_sctp_sack_chunk_flags);
2903 proto_tree_add_item(flags_tree, hf_sack_chunk_ns, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
2904 ctsa_item = 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);
2905 a_rwnd_item = 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);
2906 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);
2907 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);
2909 a_rwnd = tvb_get_ntohl(chunk_tvb, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET);
2911 expert_add_info_format(pinfo, a_rwnd_item, PI_SEQUENCE, PI_NOTE, "Zero Advertised Receiver Window Credit");
2914 /* handle the gap acknowledgement blocks */
2915 number_of_gap_blocks = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET);
2916 gap_block_offset = SACK_CHUNK_GAP_BLOCK_OFFSET;
2917 cum_tsn_ack = tvb_get_ntohl(chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
2919 acks_tree = proto_item_add_subtree(ctsa_item,ett_sctp_ack);
2920 sctp_ack_block(pinfo, ha, chunk_tvb, acks_tree, NULL, cum_tsn_ack);
2922 for(gap_block_number = 1; gap_block_number <= number_of_gap_blocks; gap_block_number++) {
2927 start = tvb_get_ntohs(chunk_tvb, gap_block_offset);
2928 end = tvb_get_ntohs(chunk_tvb, gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH);
2929 tsn_start = cum_tsn_ack + start;
2931 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);
2932 block_tree = proto_item_add_subtree(block_item, ett_sctp_sack_chunk_gap_block);
2934 pi = 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);
2935 pt = proto_item_add_subtree(pi, ett_sctp_sack_chunk_gap_block_start);
2936 pi = proto_tree_add_uint(pt, hf_sack_chunk_gap_block_start_tsn,
2937 chunk_tvb, gap_block_offset,SACK_CHUNK_GAP_BLOCK_START_LENGTH, cum_tsn_ack + start);
2938 PROTO_ITEM_SET_GENERATED(pi);
2940 pi = 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);
2941 pt = proto_item_add_subtree(pi, ett_sctp_sack_chunk_gap_block_end);
2942 pi = proto_tree_add_uint(pt, hf_sack_chunk_gap_block_end_tsn, chunk_tvb,
2943 gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH, SACK_CHUNK_GAP_BLOCK_END_LENGTH, cum_tsn_ack + end);
2944 PROTO_ITEM_SET_GENERATED(pi);
2946 sctp_ack_block(pinfo, ha, chunk_tvb, block_tree, &tsn_start, cum_tsn_ack + end);
2947 gap_block_offset += SACK_CHUNK_GAP_BLOCK_LENGTH;
2949 tsns_gap_acked += (end+1 - start);
2952 if (tsns_gap_acked) {
2955 pi = proto_tree_add_uint(chunk_tree, hf_sack_chunk_number_tsns_gap_acked, chunk_tvb, 0, 0, tsns_gap_acked);
2956 PROTO_ITEM_SET_GENERATED(pi);
2958 /* If there are a huge number of GAP ACKs, warn the user. 100 is a random
2959 * number: it could be tuned.
2961 if (tsns_gap_acked > 100)
2962 expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_WARN, "More than 100 TSNs were gap-acknowledged in this SACK");
2967 /* handle the duplicate TSNs */
2968 number_of_dup_tsns = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET);
2969 dup_tsn_offset = SACK_CHUNK_GAP_BLOCK_OFFSET + number_of_gap_blocks * SACK_CHUNK_GAP_BLOCK_LENGTH;
2970 for(dup_tsn_number = 1; dup_tsn_number <= number_of_dup_tsns; dup_tsn_number++) {
2971 proto_tree_add_item(chunk_tree, hf_sack_chunk_duplicate_tsn, chunk_tvb, dup_tsn_offset, SACK_CHUNK_DUP_TSN_LENGTH, NETWORK_BYTE_ORDER);
2972 dup_tsn_offset += SACK_CHUNK_DUP_TSN_LENGTH;
2975 proto_item_append_text(chunk_item, " (Cumulative TSN: %u, a_rwnd: %u, gaps: %u, duplicate TSNs: %u)",
2976 tvb_get_ntohl(chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET),
2978 number_of_gap_blocks, number_of_dup_tsns);
2981 /* NE: Dissect nr-sack chunk */
2982 #define SCTP_NR_SACK_CHUNK_NS_BIT 0x01
2983 #define NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH 4
2984 #define NR_SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH 4
2985 #define NR_SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH 2
2986 #define NR_SACK_CHUNK_NUMBER_OF_NR_GAP_BLOCKS_LENGTH 2
2987 #define NR_SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH 2
2988 #define NR_SACK_CHUNK_RESERVED_LENGTH 2
2989 #define NR_SACK_CHUNK_GAP_BLOCK_LENGTH 4
2990 #define NR_SACK_CHUNK_GAP_BLOCK_START_LENGTH 2
2991 #define NR_SACK_CHUNK_GAP_BLOCK_END_LENGTH 2
2992 #define NR_SACK_CHUNK_NR_GAP_BLOCK_LENGTH 4
2993 #define NR_SACK_CHUNK_NR_GAP_BLOCK_START_LENGTH 2
2994 #define NR_SACK_CHUNK_NR_GAP_BLOCK_END_LENGTH 2
2995 #define NR_SACK_CHUNK_DUP_TSN_LENGTH 4
2997 #define NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET (CHUNK_VALUE_OFFSET + 0)
2998 #define NR_SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET (NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET + \
2999 NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH)
3000 #define NR_SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET (NR_SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET + \
3001 NR_SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH)
3002 #define NR_SACK_CHUNK_NUMBER_OF_NR_GAP_BLOCKS_OFFSET (NR_SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET + \
3003 NR_SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH)
3004 #define NR_SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET (NR_SACK_CHUNK_NUMBER_OF_NR_GAP_BLOCKS_OFFSET + \
3005 NR_SACK_CHUNK_NUMBER_OF_NR_GAP_BLOCKS_LENGTH)
3006 #define NR_SACK_CHUNK_RESERVED_OFFSET (NR_SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET + \
3007 NR_SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH)
3008 #define NR_SACK_CHUNK_GAP_BLOCK_OFFSET (NR_SACK_CHUNK_RESERVED_OFFSET + \
3009 NR_SACK_CHUNK_RESERVED_LENGTH)
3012 dissect_nr_sack_chunk(packet_info* pinfo, tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item, sctp_half_assoc_t* ha)
3014 guint16 number_of_gap_blocks, number_of_dup_tsns;
3015 guint16 number_of_nr_gap_blocks;
3016 guint16 gap_block_number, nr_gap_block_number, dup_tsn_number, start, end;
3017 gint gap_block_offset, nr_gap_block_offset, dup_tsn_offset;
3018 guint32 cum_tsn_ack;
3019 proto_item *block_item;
3020 proto_tree *block_tree;
3021 proto_tree *flags_tree;
3022 proto_item *ctsa_item;
3023 proto_item *num_of_gap_blocks;
3024 proto_tree *acks_tree;
3025 guint32 tsns_gap_acked = 0;
3026 guint32 tsns_nr_gap_acked = 0;
3028 flags_tree = proto_item_add_subtree(flags_item, ett_sctp_nr_sack_chunk_flags);
3029 proto_tree_add_item(flags_tree, hf_nr_sack_chunk_ns, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
3031 ctsa_item = proto_tree_add_item(chunk_tree, hf_nr_sack_chunk_cumulative_tsn_ack, chunk_tvb, NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET, NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH, NETWORK_BYTE_ORDER);
3032 proto_tree_add_item(chunk_tree, hf_nr_sack_chunk_adv_rec_window_credit, chunk_tvb, NR_SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET, NR_SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH, NETWORK_BYTE_ORDER);
3034 num_of_gap_blocks = proto_tree_add_item(chunk_tree, hf_nr_sack_chunk_number_of_gap_blocks, chunk_tvb, NR_SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET, NR_SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH, NETWORK_BYTE_ORDER);
3036 proto_tree_add_item(chunk_tree, hf_nr_sack_chunk_number_of_nr_gap_blocks, chunk_tvb, NR_SACK_CHUNK_NUMBER_OF_NR_GAP_BLOCKS_OFFSET, NR_SACK_CHUNK_NUMBER_OF_NR_GAP_BLOCKS_LENGTH, NETWORK_BYTE_ORDER);
3037 proto_tree_add_item(chunk_tree, hf_nr_sack_chunk_number_of_dup_tsns, chunk_tvb, NR_SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET, NR_SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH, NETWORK_BYTE_ORDER);
3038 proto_tree_add_item(chunk_tree, hf_nr_sack_chunk_reserved, chunk_tvb, NR_SACK_CHUNK_RESERVED_OFFSET, NR_SACK_CHUNK_RESERVED_LENGTH, NETWORK_BYTE_ORDER);
3041 number_of_gap_blocks = tvb_get_ntohs(chunk_tvb, NR_SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET);
3042 gap_block_offset = NR_SACK_CHUNK_GAP_BLOCK_OFFSET;
3043 cum_tsn_ack = tvb_get_ntohl(chunk_tvb, NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
3045 acks_tree = proto_item_add_subtree(ctsa_item,ett_sctp_ack);
3046 sctp_ack_block(pinfo, ha, chunk_tvb, acks_tree, NULL, cum_tsn_ack);
3048 for(gap_block_number = 1; gap_block_number <= number_of_gap_blocks; gap_block_number++) {
3053 start = tvb_get_ntohs(chunk_tvb, gap_block_offset);
3054 end = tvb_get_ntohs(chunk_tvb, gap_block_offset + NR_SACK_CHUNK_GAP_BLOCK_START_LENGTH);
3055 tsn_start = cum_tsn_ack + start;
3057 block_item = proto_tree_add_text(chunk_tree, chunk_tvb, gap_block_offset, NR_SACK_CHUNK_GAP_BLOCK_LENGTH, "Gap Acknowledgement for TSN %u to %u", cum_tsn_ack + start, cum_tsn_ack + end);
3058 block_tree = proto_item_add_subtree(block_item, ett_sctp_nr_sack_chunk_gap_block);
3060 pi = proto_tree_add_item(block_tree, hf_nr_sack_chunk_gap_block_start, chunk_tvb, gap_block_offset, NR_SACK_CHUNK_GAP_BLOCK_START_LENGTH, NETWORK_BYTE_ORDER);
3061 pt = proto_item_add_subtree(pi, ett_sctp_nr_sack_chunk_gap_block_start);
3062 pi = proto_tree_add_uint(pt, hf_nr_sack_chunk_gap_block_start_tsn,
3063 chunk_tvb, gap_block_offset,NR_SACK_CHUNK_GAP_BLOCK_START_LENGTH, cum_tsn_ack + start);
3064 PROTO_ITEM_SET_GENERATED(pi);
3066 pi = proto_tree_add_item(block_tree, hf_nr_sack_chunk_gap_block_end, chunk_tvb, gap_block_offset + NR_SACK_CHUNK_GAP_BLOCK_START_LENGTH, NR_SACK_CHUNK_GAP_BLOCK_END_LENGTH, NETWORK_BYTE_ORDER);
3067 pt = proto_item_add_subtree(pi, ett_sctp_nr_sack_chunk_gap_block_end);
3068 pi = proto_tree_add_uint(pt, hf_nr_sack_chunk_gap_block_end_tsn, chunk_tvb,
3069 gap_block_offset + NR_SACK_CHUNK_GAP_BLOCK_START_LENGTH, NR_SACK_CHUNK_GAP_BLOCK_END_LENGTH, cum_tsn_ack + end);
3070 PROTO_ITEM_SET_GENERATED(pi);
3072 sctp_ack_block(pinfo, ha, chunk_tvb, block_tree, &tsn_start, cum_tsn_ack + end);
3073 gap_block_offset += NR_SACK_CHUNK_GAP_BLOCK_LENGTH;
3074 tsns_gap_acked += (end - start) + 1;
3077 if (tsns_gap_acked) {
3080 pi = proto_tree_add_uint(chunk_tree, hf_nr_sack_chunk_number_tsns_gap_acked, chunk_tvb, 0, 0, tsns_gap_acked);
3081 PROTO_ITEM_SET_GENERATED(pi);
3083 /* If there are a huge number of GAP ACKs, warn the user. 100 is a random
3084 * number: it could be tuned.
3086 if (tsns_gap_acked > 100)
3087 expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_WARN, "More than 100 TSNs were gap-acknowledged in this NR-SACK");
3091 /* NE: handle the nr-sack chunk's nr-gap blocks */
3092 number_of_nr_gap_blocks = tvb_get_ntohs(chunk_tvb, NR_SACK_CHUNK_NUMBER_OF_NR_GAP_BLOCKS_OFFSET);
3093 nr_gap_block_offset = gap_block_offset;
3095 for(nr_gap_block_number = 1; nr_gap_block_number <= number_of_nr_gap_blocks; nr_gap_block_number++) {
3100 start = tvb_get_ntohs(chunk_tvb, nr_gap_block_offset);
3101 end = tvb_get_ntohs(chunk_tvb, nr_gap_block_offset + NR_SACK_CHUNK_NR_GAP_BLOCK_START_LENGTH);
3102 tsn_start = cum_tsn_ack + start;
3104 block_item = proto_tree_add_text(chunk_tree, chunk_tvb, nr_gap_block_offset, NR_SACK_CHUNK_NR_GAP_BLOCK_LENGTH, "NR-Gap Acknowledgement for TSN %u to %u", cum_tsn_ack + start, cum_tsn_ack + end);
3105 block_tree = proto_item_add_subtree(block_item, ett_sctp_nr_sack_chunk_nr_gap_block);
3107 pi = proto_tree_add_item(block_tree, hf_nr_sack_chunk_nr_gap_block_start, chunk_tvb, nr_gap_block_offset, NR_SACK_CHUNK_NR_GAP_BLOCK_START_LENGTH, NETWORK_BYTE_ORDER);
3108 pt = proto_item_add_subtree(pi, ett_sctp_nr_sack_chunk_nr_gap_block_start);
3109 pi = proto_tree_add_uint(pt, hf_nr_sack_chunk_nr_gap_block_start_tsn,
3110 chunk_tvb, nr_gap_block_offset, NR_SACK_CHUNK_NR_GAP_BLOCK_START_LENGTH, cum_tsn_ack + start);
3111 PROTO_ITEM_SET_GENERATED(pi);
3113 pi = proto_tree_add_item(block_tree, hf_nr_sack_chunk_nr_gap_block_end, chunk_tvb, nr_gap_block_offset + NR_SACK_CHUNK_NR_GAP_BLOCK_START_LENGTH, NR_SACK_CHUNK_NR_GAP_BLOCK_END_LENGTH, NETWORK_BYTE_ORDER);
3114 pt = proto_item_add_subtree(pi, ett_sctp_nr_sack_chunk_nr_gap_block_end);
3115 pi = proto_tree_add_uint(pt, hf_nr_sack_chunk_nr_gap_block_end_tsn, chunk_tvb,
3116 nr_gap_block_offset + NR_SACK_CHUNK_NR_GAP_BLOCK_START_LENGTH, NR_SACK_CHUNK_NR_GAP_BLOCK_END_LENGTH, cum_tsn_ack + end);
3117 PROTO_ITEM_SET_GENERATED(pi);
3119 /* sctp_ack_block(pinfo, ha, chunk_tvb, block_tree, &tsn_start, cum_tsn_ack + end); */
3120 nr_gap_block_offset += NR_SACK_CHUNK_NR_GAP_BLOCK_LENGTH;
3121 tsns_nr_gap_acked += (end - start) + 1;
3124 if (tsns_nr_gap_acked) {
3127 pi = proto_tree_add_uint(chunk_tree, hf_nr_sack_chunk_number_tsns_nr_gap_acked, chunk_tvb, 0, 0, tsns_nr_gap_acked);
3128 PROTO_ITEM_SET_GENERATED(pi);
3130 /* If there are a huge number of GAP ACKs, warn the user. 100 is a random
3131 * number: it could be tuned.
3133 if (tsns_nr_gap_acked > 100)
3134 expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_WARN, "More than 100 TSNs were nr-gap-acknowledged in this NR-SACK");
3137 /* handle the duplicate TSNs */
3138 number_of_dup_tsns = tvb_get_ntohs(chunk_tvb, NR_SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET);
3139 dup_tsn_offset = NR_SACK_CHUNK_GAP_BLOCK_OFFSET + number_of_gap_blocks * NR_SACK_CHUNK_GAP_BLOCK_LENGTH
3140 + number_of_nr_gap_blocks * NR_SACK_CHUNK_NR_GAP_BLOCK_LENGTH;
3143 for(dup_tsn_number = 1; dup_tsn_number <= number_of_dup_tsns; dup_tsn_number++) {
3144 proto_tree_add_item(chunk_tree, hf_sack_chunk_duplicate_tsn, chunk_tvb, dup_tsn_offset, NR_SACK_CHUNK_DUP_TSN_LENGTH, NETWORK_BYTE_ORDER);
3145 dup_tsn_offset += NR_SACK_CHUNK_DUP_TSN_LENGTH;
3148 proto_item_append_text(chunk_item, " (Cumulative TSN: %u, a_rwnd: %u, gaps: %u, nr-gaps: %u, duplicate TSNs: %u)",
3149 tvb_get_ntohl(chunk_tvb, NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET),
3150 tvb_get_ntohl(chunk_tvb, NR_SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET),
3151 number_of_gap_blocks, number_of_nr_gap_blocks, number_of_dup_tsns);
3154 #define HEARTBEAT_CHUNK_INFO_OFFSET CHUNK_VALUE_OFFSET
3157 dissect_heartbeat_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
3159 tvbuff_t *parameter_tvb;
3162 proto_item_append_text(chunk_item, " (Information: %u byte%s)", chunk_length - CHUNK_HEADER_LENGTH, plurality(chunk_length - CHUNK_HEADER_LENGTH, "", "s"));
3163 parameter_tvb = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, chunk_length - CHUNK_HEADER_LENGTH, chunk_length - CHUNK_HEADER_LENGTH);
3164 /* FIXME: Parameters or parameter? */
3165 dissect_parameter(parameter_tvb, pinfo, chunk_tree, NULL, FALSE);
3170 dissect_heartbeat_ack_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
3172 tvbuff_t *parameter_tvb;
3175 proto_item_append_text(chunk_item, " (Information: %u byte%s)", chunk_length - CHUNK_HEADER_LENGTH, plurality(chunk_length - CHUNK_HEADER_LENGTH, "", "s"));
3176 parameter_tvb = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, chunk_length - CHUNK_HEADER_LENGTH, chunk_length - CHUNK_HEADER_LENGTH);
3177 /* FIXME: Parameters or parameter? */
3178 dissect_parameter(parameter_tvb, pinfo, chunk_tree, NULL, FALSE);
3182 #define ABORT_CHUNK_FIRST_ERROR_CAUSE_OFFSET 4
3183 #define SCTP_ABORT_CHUNK_T_BIT 0x01
3186 dissect_abort_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *flags_item)
3188 tvbuff_t *causes_tvb;
3189 proto_tree *flags_tree;
3191 sctp_info.vtag_reflected =
3192 (tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_ABORT_CHUNK_T_BIT) != 0;
3195 flags_tree = proto_item_add_subtree(flags_item, ett_sctp_abort_chunk_flags);
3196 proto_tree_add_item(flags_tree, hf_abort_chunk_t_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
3197 causes_tvb = tvb_new_subset(chunk_tvb, CHUNK_VALUE_OFFSET, chunk_length - CHUNK_HEADER_LENGTH, chunk_length - CHUNK_HEADER_LENGTH);
3198 dissect_error_causes(causes_tvb, pinfo, chunk_tree);
3202 #define SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET CHUNK_VALUE_OFFSET
3203 #define SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_LENGTH 4
3206 dissect_shutdown_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
3209 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);
3210 proto_item_append_text(chunk_item, " (Cumulative TSN ack: %u)", tvb_get_ntohl(chunk_tvb, SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET));
3215 dissect_shutdown_ack_chunk(tvbuff_t *chunk_tvb _U_)
3219 #define ERROR_CAUSE_IND_CAUSES_OFFSET CHUNK_VALUE_OFFSET
3222 dissect_error_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree)
3224 tvbuff_t *causes_tvb;
3227 causes_tvb = tvb_new_subset(chunk_tvb, ERROR_CAUSE_IND_CAUSES_OFFSET, chunk_length - CHUNK_HEADER_LENGTH, chunk_length - CHUNK_HEADER_LENGTH);
3228 dissect_error_causes(causes_tvb, pinfo, chunk_tree);
3232 #define COOKIE_OFFSET CHUNK_VALUE_OFFSET
3235 dissect_cookie_echo_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, proto_tree *chunk_tree, proto_item *chunk_item)
3238 proto_tree_add_item(chunk_tree, hf_cookie, chunk_tvb, COOKIE_OFFSET, chunk_length - CHUNK_HEADER_LENGTH, NETWORK_BYTE_ORDER);
3239 proto_item_append_text(chunk_item, " (Cookie length: %u byte%s)", chunk_length - CHUNK_HEADER_LENGTH, plurality(chunk_length - CHUNK_HEADER_LENGTH, "", "s"));
3244 dissect_cookie_ack_chunk(tvbuff_t *chunk_tvb _U_)
3248 #define ECNE_CHUNK_LOWEST_TSN_OFFSET CHUNK_VALUE_OFFSET
3249 #define ECNE_CHUNK_LOWEST_TSN_LENGTH 4
3252 dissect_ecne_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
3255 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);
3256 proto_item_append_text(chunk_item, " (Lowest TSN: %u)", tvb_get_ntohl(chunk_tvb, ECNE_CHUNK_LOWEST_TSN_OFFSET));
3259 #define CWR_CHUNK_LOWEST_TSN_OFFSET CHUNK_VALUE_OFFSET
3260 #define CWR_CHUNK_LOWEST_TSN_LENGTH 4
3263 dissect_cwr_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
3266 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);
3267 proto_item_append_text(chunk_item, " (Lowest TSN: %u)", tvb_get_ntohl(chunk_tvb, CWR_CHUNK_LOWEST_TSN_OFFSET));
3270 #define SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT 0x01
3273 static const true_false_string sctp_shutdown_complete_chunk_t_bit_value = {
3280 dissect_shutdown_complete_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *flags_item)
3282 proto_tree *flags_tree;
3284 sctp_info.vtag_reflected =
3285 (tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT) != 0;
3288 flags_tree = proto_item_add_subtree(flags_item, ett_sctp_shutdown_complete_chunk_flags);
3289 proto_tree_add_item(flags_tree, hf_shutdown_complete_chunk_t_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
3293 #define FORWARD_TSN_CHUNK_TSN_LENGTH 4
3294 #define FORWARD_TSN_CHUNK_SID_LENGTH 2
3295 #define FORWARD_TSN_CHUNK_SSN_LENGTH 2
3296 #define FORWARD_TSN_CHUNK_TSN_OFFSET CHUNK_VALUE_OFFSET
3297 #define FORWARD_TSN_CHUNK_SID_OFFSET 0
3298 #define FORWARD_TSN_CHUNK_SSN_OFFSET (FORWARD_TSN_CHUNK_SID_OFFSET + FORWARD_TSN_CHUNK_SID_LENGTH)
3301 dissect_forward_tsn_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, proto_tree *chunk_tree, proto_item *chunk_item)
3304 guint16 number_of_affected_streams, affected_stream;
3307 if (chunk_length < CHUNK_HEADER_LENGTH + FORWARD_TSN_CHUNK_TSN_LENGTH) {
3308 proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
3310 CHUNK_HEADER_LENGTH + FORWARD_TSN_CHUNK_TSN_LENGTH);
3314 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);
3315 number_of_affected_streams = (chunk_length - CHUNK_HEADER_LENGTH - FORWARD_TSN_CHUNK_TSN_LENGTH) /
3316 (FORWARD_TSN_CHUNK_SID_LENGTH + FORWARD_TSN_CHUNK_SSN_LENGTH);
3317 offset = CHUNK_VALUE_OFFSET + FORWARD_TSN_CHUNK_TSN_LENGTH;
3319 for(affected_stream = 0; affected_stream < number_of_affected_streams; affected_stream++) {
3320 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);
3321 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);
3322 offset = offset + (FORWARD_TSN_CHUNK_SID_LENGTH + FORWARD_TSN_CHUNK_SSN_LENGTH);
3324 proto_item_append_text(chunk_item, "(Cumulative TSN: %u)", tvb_get_ntohl(chunk_tvb, FORWARD_TSN_CHUNK_TSN_OFFSET));
3328 #define STREAM_RESET_PARAMETERS_OFFSET CHUNK_HEADER_LENGTH
3331 dissect_stream_reset_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item _U_)
3333 tvbuff_t *parameters_tvb;
3336 parameters_tvb = tvb_new_subset(chunk_tvb, STREAM_RESET_PARAMETERS_OFFSET, chunk_length - CHUNK_HEADER_LENGTH, chunk_length - CHUNK_HEADER_LENGTH);
3337 dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, FALSE);
3341 #define SHARED_KEY_ID_LENGTH 2
3343 #define SHARED_KEY_ID_OFFSET PARAMETER_VALUE_OFFSET
3344 #define HMAC_ID_OFFSET (SHARED_KEY_ID_OFFSET + SHARED_KEY_ID_LENGTH)
3345 #define HMAC_OFFSET (HMAC_ID_OFFSET + HMAC_ID_LENGTH)
3348 dissect_auth_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, proto_tree *chunk_tree, proto_item *chunk_item _U_)
3352 hmac_length = chunk_length - CHUNK_HEADER_LENGTH - HMAC_ID_LENGTH - SHARED_KEY_ID_LENGTH;
3353 proto_tree_add_item(chunk_tree, hf_shared_key_id, chunk_tvb, SHARED_KEY_ID_OFFSET, SHARED_KEY_ID_LENGTH, NETWORK_BYTE_ORDER);
3354 proto_tree_add_item(chunk_tree, hf_hmac_id, chunk_tvb, HMAC_ID_OFFSET, HMAC_ID_LENGTH, NETWORK_BYTE_ORDER);
3355 if (hmac_length > 0)
3356 proto_tree_add_item(chunk_tree, hf_hmac, chunk_tvb, HMAC_OFFSET, hmac_length, NETWORK_BYTE_ORDER);
3359 #define SCTP_SERIAL_NUMBER_LENGTH 4
3360 #define SERIAL_NUMBER_OFFSET CHUNK_VALUE_OFFSET
3361 #define ASCONF_CHUNK_PARAMETERS_OFFSET (SERIAL_NUMBER_OFFSET + SCTP_SERIAL_NUMBER_LENGTH)
3364 dissect_asconf_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
3366 tvbuff_t *parameters_tvb;
3368 if (chunk_length < CHUNK_HEADER_LENGTH + SCTP_SERIAL_NUMBER_LENGTH) {
3369 proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
3371 CHUNK_HEADER_LENGTH + SCTP_SERIAL_NUMBER_LENGTH);
3375 proto_tree_add_item(chunk_tree, hf_asconf_serial, chunk_tvb, SERIAL_NUMBER_OFFSET, SCTP_SERIAL_NUMBER_LENGTH, NETWORK_BYTE_ORDER);
3376 chunk_length -= CHUNK_HEADER_LENGTH + SCTP_SERIAL_NUMBER_LENGTH;
3377 parameters_tvb = tvb_new_subset(chunk_tvb, ASCONF_CHUNK_PARAMETERS_OFFSET, chunk_length, chunk_length);
3378 dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, FALSE);
3382 #define ASCONF_ACK_CHUNK_PARAMETERS_OFFSET (SERIAL_NUMBER_OFFSET + SCTP_SERIAL_NUMBER_LENGTH)
3385 dissect_asconf_ack_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
3387 tvbuff_t *parameters_tvb;
3389 if (chunk_length < CHUNK_HEADER_LENGTH + SCTP_SERIAL_NUMBER_LENGTH) {
3390 proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
3391 chunk_length + CHUNK_HEADER_LENGTH,
3392 CHUNK_HEADER_LENGTH + SCTP_SERIAL_NUMBER_LENGTH);
3396 proto_tree_add_item(chunk_tree, hf_asconf_ack_serial, chunk_tvb, SERIAL_NUMBER_OFFSET, SCTP_SERIAL_NUMBER_LENGTH, NETWORK_BYTE_ORDER);
3397 chunk_length -= CHUNK_HEADER_LENGTH + SCTP_SERIAL_NUMBER_LENGTH;
3398 parameters_tvb = tvb_new_subset(chunk_tvb, ASCONF_ACK_CHUNK_PARAMETERS_OFFSET, chunk_length, chunk_length);
3399 dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, FALSE);
3403 #define PKTDROP_CHUNK_BANDWIDTH_LENGTH 4
3404 #define PKTDROP_CHUNK_QUEUESIZE_LENGTH 4
3405 #define PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH 2
3406 #define PKTDROP_CHUNK_RESERVED_SIZE_LENGTH 2
3408 #define PKTDROP_CHUNK_HEADER_LENGTH (CHUNK_HEADER_LENGTH + \
3409 PKTDROP_CHUNK_BANDWIDTH_LENGTH + \
3410 PKTDROP_CHUNK_QUEUESIZE_LENGTH + \
3411 PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH + \
3412 PKTDROP_CHUNK_RESERVED_SIZE_LENGTH)
3414 #define PKTDROP_CHUNK_BANDWIDTH_OFFSET CHUNK_VALUE_OFFSET
3415 #define PKTDROP_CHUNK_QUEUESIZE_OFFSET (PKTDROP_CHUNK_BANDWIDTH_OFFSET + PKTDROP_CHUNK_BANDWIDTH_LENGTH)
3416 #define PKTDROP_CHUNK_TRUNCATED_SIZE_OFFSET (PKTDROP_CHUNK_QUEUESIZE_OFFSET + PKTDROP_CHUNK_QUEUESIZE_LENGTH)
3417 #define PKTDROP_CHUNK_RESERVED_SIZE_OFFSET (PKTDROP_CHUNK_TRUNCATED_SIZE_OFFSET + PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH)
3418 #define PKTDROP_CHUNK_DATA_FIELD_OFFSET (PKTDROP_CHUNK_RESERVED_SIZE_OFFSET + PKTDROP_CHUNK_RESERVED_SIZE_LENGTH)
3420 #define SCTP_PKTDROP_CHUNK_M_BIT 0x01
3421 #define SCTP_PKTDROP_CHUNK_B_BIT 0x02
3422 #define SCTP_PKTDROP_CHUNK_T_BIT 0x04
3424 static const true_false_string sctp_pktdropk_m_bit_value = {
3425 "Source is a middlebox",
3426 "Source is an endhost"
3429 static const true_false_string sctp_pktdropk_b_bit_value = {
3430 "SCTP checksum was incorrect",
3431 "SCTP checksum was correct"
3434 static const true_false_string sctp_pktdropk_t_bit_value = {
3435 "Packet is truncated",
3436 "Packet is not truncated"
3440 dissect_pktdrop_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
3442 tvbuff_t *data_field_tvb;
3443 proto_tree *flags_tree;
3445 if (chunk_length < PKTDROP_CHUNK_HEADER_LENGTH) {
3446 proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
3448 PKTDROP_CHUNK_HEADER_LENGTH);
3451 chunk_length -= PKTDROP_CHUNK_HEADER_LENGTH;
3452 data_field_tvb = tvb_new_subset(chunk_tvb, PKTDROP_CHUNK_DATA_FIELD_OFFSET, chunk_length, chunk_length);
3455 flags_tree = proto_item_add_subtree(flags_item, ett_sctp_pktdrop_chunk_flags);
3457 proto_tree_add_item(flags_tree, hf_pktdrop_chunk_m_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
3458 proto_tree_add_item(flags_tree, hf_pktdrop_chunk_b_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
3459 proto_tree_add_item(flags_tree, hf_pktdrop_chunk_t_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
3460 proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_bandwidth, chunk_tvb, PKTDROP_CHUNK_BANDWIDTH_OFFSET, PKTDROP_CHUNK_BANDWIDTH_LENGTH, NETWORK_BYTE_ORDER);
3461 proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_queuesize, chunk_tvb, PKTDROP_CHUNK_QUEUESIZE_OFFSET, PKTDROP_CHUNK_QUEUESIZE_LENGTH, NETWORK_BYTE_ORDER);
3462 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);
3463 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);
3464 /* XXX - set pinfo->in_error_pkt? */
3465 if (chunk_length > 0) {
3466 if (tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_PKTDROP_CHUNK_T_BIT)
3467 proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_data_field, chunk_tvb, PKTDROP_CHUNK_DATA_FIELD_OFFSET, chunk_length, NETWORK_BYTE_ORDER);
3469 dissect_sctp_packet(data_field_tvb, pinfo, chunk_tree, TRUE);
3475 dissect_unknown_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, proto_tree *chunk_tree, proto_item *chunk_item)
3478 if (chunk_length > CHUNK_HEADER_LENGTH)
3479 proto_tree_add_item(chunk_tree, hf_chunk_value, chunk_tvb, CHUNK_VALUE_OFFSET, chunk_length - CHUNK_HEADER_LENGTH, NETWORK_BYTE_ORDER);
3480 proto_item_append_text(chunk_item, " (Type: %u, value length: %u byte%s)", chunk_length, chunk_length, plurality(chunk_length - CHUNK_HEADER_LENGTH, "", "s"));
3484 #define SCTP_CHUNK_BIT_1 0x80
3485 #define SCTP_CHUNK_BIT_2 0x40
3487 static const true_false_string sctp_chunk_bit_1_value = {
3488 "Skip chunk and continue processing of the packet",
3489 "Stop processing of the packet"
3492 static const true_false_string sctp_chunk_bit_2_value = {
3499 dissect_sctp_chunk(tvbuff_t *chunk_tvb,
3502 proto_tree *sctp_tree,
3503 sctp_half_assoc_t* ha,
3507 guint16 length, padding_length;
3509 proto_item *flags_item;
3510 proto_item *chunk_item;
3511 proto_tree *chunk_tree;
3512 proto_item *type_item;
3513 proto_tree *type_tree;
3517 /* first extract the chunk header */
3518 type = tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET);
3519 flags = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
3520 length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
3521 padding_length = tvb_length(chunk_tvb) - length;
3523 if (useinfo && (check_col(pinfo->cinfo, COL_INFO)))
3524 col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(type, chunk_type_values, "RESERVED"));
3527 /* create proto_tree stuff */
3528 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"));
3529 chunk_tree = proto_item_add_subtree(chunk_item, ett_sctp_chunk);
3531 /* then insert the chunk header components into the protocol tree */
3532 type_item = proto_tree_add_item(chunk_tree, hf_chunk_type, chunk_tvb, CHUNK_TYPE_OFFSET, CHUNK_TYPE_LENGTH, NETWORK_BYTE_ORDER);
3533 type_tree = proto_item_add_subtree(type_item, ett_sctp_chunk_type);
3534 proto_tree_add_item(type_tree, hf_chunk_bit_1, chunk_tvb, CHUNK_TYPE_OFFSET, CHUNK_TYPE_LENGTH, NETWORK_BYTE_ORDER);
3535 proto_tree_add_item(type_tree, hf_chunk_bit_2, chunk_tvb, CHUNK_TYPE_OFFSET, CHUNK_TYPE_LENGTH, NETWORK_BYTE_ORDER);
3536 flags_item = proto_tree_add_item(chunk_tree, hf_chunk_flags, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
3542 if (length < CHUNK_HEADER_LENGTH) {
3544 proto_tree_add_uint_format(chunk_tree, hf_chunk_length, chunk_tvb,
3545 CHUNK_LENGTH_OFFSET, CHUNK_LENGTH_LENGTH,
3547 "Chunk length: %u (invalid, should be >= %u)",
3548 length, CHUNK_HEADER_LENGTH);
3549 proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
3550 length, CHUNK_HEADER_LENGTH);
3552 if (type == SCTP_DATA_CHUNK_ID)
3557 proto_tree_add_uint(chunk_tree, hf_chunk_length, chunk_tvb, CHUNK_LENGTH_OFFSET, CHUNK_LENGTH_LENGTH, length);
3560 length -= CHUNK_HEADER_LENGTH;
3563 /* now dissect the chunk value */
3565 case SCTP_DATA_CHUNK_ID:
3566 result = dissect_data_chunk(chunk_tvb, length, pinfo, tree, chunk_tree, chunk_item, flags_item, ha);
3568 case SCTP_INIT_CHUNK_ID:
3569 dissect_init_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
3571 case SCTP_INIT_ACK_CHUNK_ID:
3572 dissect_init_ack_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
3574 case SCTP_SACK_CHUNK_ID:
3575 dissect_sack_chunk(pinfo, chunk_tvb, chunk_tree, chunk_item, flags_item, ha);
3577 case SCTP_HEARTBEAT_CHUNK_ID:
3578 dissect_heartbeat_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
3580 case SCTP_HEARTBEAT_ACK_CHUNK_ID:
3581 dissect_heartbeat_ack_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
3583 case SCTP_ABORT_CHUNK_ID:
3584 dissect_abort_chunk(chunk_tvb, length, pinfo, chunk_tree, flags_item);
3586 case SCTP_SHUTDOWN_CHUNK_ID:
3587 dissect_shutdown_chunk(chunk_tvb, chunk_tree, chunk_item);
3589 case SCTP_SHUTDOWN_ACK_CHUNK_ID:
3590 dissect_shutdown_ack_chunk(chunk_tvb);
3592 case SCTP_ERROR_CHUNK_ID:
3593 dissect_error_chunk(chunk_tvb, length, pinfo, chunk_tree);
3595 case SCTP_COOKIE_ECHO_CHUNK_ID:
3596 dissect_cookie_echo_chunk(chunk_tvb, length, chunk_tree, chunk_item);
3598 case SCTP_COOKIE_ACK_CHUNK_ID:
3599 dissect_cookie_ack_chunk(chunk_tvb);
3601 case SCTP_ECNE_CHUNK_ID:
3602 dissect_ecne_chunk(chunk_tvb, chunk_tree, chunk_item);
3604 case SCTP_CWR_CHUNK_ID:
3605 dissect_cwr_chunk(chunk_tvb, chunk_tree, chunk_item);
3607 case SCTP_SHUTDOWN_COMPLETE_CHUNK_ID:
3608 dissect_shutdown_complete_chunk(chunk_tvb, chunk_tree, flags_item);
3610 case SCTP_FORWARD_TSN_CHUNK_ID:
3611 dissect_forward_tsn_chunk(chunk_tvb, length, chunk_tree, chunk_item);
3613 case SCTP_STREAM_RESET_CHUNK_ID:
3614 dissect_stream_reset_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
3616 case SCTP_AUTH_CHUNK_ID:
3617 dissect_auth_chunk(chunk_tvb, length, chunk_tree, chunk_item);
3619 case SCTP_NR_SACK_CHUNK_ID:
3620 dissect_nr_sack_chunk(pinfo, chunk_tvb, chunk_tree, chunk_item, flags_item, ha);
3622 case SCTP_ASCONF_ACK_CHUNK_ID:
3623 dissect_asconf_ack_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
3625 case SCTP_ASCONF_CHUNK_ID:
3626 dissect_asconf_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
3628 case SCTP_PKTDROP_CHUNK_ID:
3629 col_set_writable(pinfo->cinfo, FALSE);
3630 dissect_pktdrop_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item, flags_item);
3631 col_set_writable(pinfo->cinfo, TRUE);
3634 dissect_unknown_chunk(chunk_tvb, length, chunk_tree, chunk_item);
3638 if (padding_length > 0)
3639 proto_tree_add_item(chunk_tree, hf_chunk_padding, chunk_tvb, CHUNK_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
3641 if (useinfo && ((type == SCTP_DATA_CHUNK_ID) || show_always_control_chunks) && check_col(pinfo->cinfo, COL_INFO))
3642 col_set_fence(pinfo->cinfo, COL_INFO);
3648 dissect_sctp_chunks(tvbuff_t *tvb,
3651 proto_item *sctp_item,
3652 proto_tree *sctp_tree,
3653 sctp_half_assoc_t* ha,
3654 gboolean encapsulated)
3656 tvbuff_t *chunk_tvb;
3657 guint16 length, total_length, remaining_length;
3658 gint last_offset, offset;
3659 gboolean sctp_item_length_set;
3661 /* the common header of the datagram is already handled */
3663 offset = COMMON_HEADER_LENGTH;
3664 sctp_item_length_set = FALSE;
3666 while((remaining_length = tvb_length_remaining(tvb, offset))) {
3667 /* extract the chunk length and compute number of padding bytes */
3668 length = tvb_get_ntohs(tvb, offset + CHUNK_LENGTH_OFFSET);
3669 total_length = ADD_PADDING(length);
3670 if (remaining_length >= length)
3671 total_length = MIN(total_length, remaining_length);
3672 /* create a tvb for the chunk including the padding bytes */
3673 chunk_tvb = tvb_new_subset(tvb, offset, total_length, total_length);
3675 /* save it in the sctp_info structure */
3676 if (!encapsulated) {
3677 if (sctp_info.number_of_tvbs < MAXIMUM_NUMBER_OF_TVBS)
3678 sctp_info.tvb[sctp_info.number_of_tvbs++] = chunk_tvb;
3680 sctp_info.incomplete = TRUE;
3683 /* call dissect_sctp_chunk for the actual work */
3684 if (dissect_sctp_chunk(chunk_tvb, pinfo, tree, sctp_tree, ha, !encapsulated) && (tree)) {
3685 proto_item_set_len(sctp_item, offset - last_offset + DATA_CHUNK_HEADER_LENGTH);
3686 sctp_item_length_set = TRUE;
3687 offset += total_length;
3688 last_offset = offset;
3689 if (tvb_reported_length_remaining(tvb, offset) > 0) {
3690 sctp_item = proto_tree_add_item(tree, proto_sctp, tvb, offset, -1, FALSE);
3691 sctp_tree = proto_item_add_subtree(sctp_item, ett_sctp);
3692 sctp_item_length_set = FALSE;
3695 /* get rid of the dissected chunk */
3696 offset += total_length;
3699 if (!sctp_item_length_set && (tree)) {
3700 proto_item_set_len(sctp_item, offset - last_offset);
3705 dissect_sctp_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean encapsulated)
3707 guint32 checksum = 0, calculated_crc32c = 0, calculated_adler32 = 0;
3708 guint16 source_port, destination_port;
3709 guint length, reported_length;
3710 gboolean crc32c_correct = FALSE, adler32_correct = FALSE;
3711 proto_item *sctp_item, *hidden_item;
3712 proto_tree *sctp_tree;
3714 sctp_half_assoc_t* ha = NULL;
3716 length = tvb_length(tvb);
3717 reported_length = tvb_reported_length(tvb);
3718 checksum = tvb_get_ntohl(tvb, CHECKSUM_OFFSET);
3719 sctp_info.checksum_zero = (checksum == 0);
3721 /* Only try to checksum the packet if we have all of it */
3722 if (tvb_bytes_exist(tvb, 0, reported_length)) {
3724 switch(sctp_checksum) {
3725 case SCTP_CHECKSUM_NONE:
3727 case SCTP_CHECKSUM_ADLER32:
3728 calculated_adler32 = sctp_adler32(tvb_get_ptr(tvb, 0, length), length);
3729 adler32_correct = (checksum == calculated_adler32);
3730 sctp_info.adler32_calculated = TRUE;
3731 sctp_info.adler32_correct = adler32_correct;
3733 case SCTP_CHECKSUM_CRC32C:
3734 calculated_crc32c = sctp_crc32c(tvb_get_ptr(tvb, 0, length), length);
3735 crc32c_correct = (checksum == calculated_crc32c);
3736 sctp_info.crc32c_calculated = TRUE;
3737 sctp_info.crc32c_correct = crc32c_correct;
3739 case SCTP_CHECKSUM_AUTOMATIC:
3740 calculated_adler32 = sctp_adler32(tvb_get_ptr(tvb, 0, length), length);
3741 adler32_correct = (checksum == calculated_adler32);
3742 calculated_crc32c = sctp_crc32c(tvb_get_ptr(tvb, 0, length), length);
3743 crc32c_correct = (checksum == calculated_crc32c);
3744 sctp_info.adler32_calculated = TRUE;
3745 sctp_info.adler32_correct = adler32_correct;
3746 sctp_info.crc32c_calculated = TRUE;
3747 sctp_info.crc32c_correct = crc32c_correct;
3752 /* In the interest of speed, if "tree" is NULL, don't do any work not
3753 necessary to generate protocol tree items. */
3754 source_port = tvb_get_ntohs(tvb, SOURCE_PORT_OFFSET);
3755 destination_port = tvb_get_ntohs(tvb, DESTINATION_PORT_OFFSET);
3756 vtag = tvb_get_ntohl(tvb,VERIFICATION_TAG_OFFSET);
3758 ha = get_half_assoc(pinfo, source_port, destination_port, vtag);
3762 /* create the sctp protocol tree */
3763 if (show_port_numbers)
3764 sctp_item = proto_tree_add_protocol_format(tree, proto_sctp, tvb, 0, -1,
3765 "Stream Control Transmission Protocol, Src Port: %s (%u), Dst Port: %s (%u)",
3766 get_sctp_port(source_port), source_port,
3767 get_sctp_port(destination_port), destination_port);
3769 sctp_item = proto_tree_add_item(tree, proto_sctp, tvb, 0, -1, FALSE);
3770 sctp_tree = proto_item_add_subtree(sctp_item, ett_sctp);
3772 /* add the components of the common header to the protocol tree */
3773 proto_tree_add_item(sctp_tree, hf_source_port, tvb, SOURCE_PORT_OFFSET, SOURCE_PORT_LENGTH, NETWORK_BYTE_ORDER);
3774 proto_tree_add_item(sctp_tree, hf_destination_port, tvb, DESTINATION_PORT_OFFSET, DESTINATION_PORT_LENGTH, NETWORK_BYTE_ORDER);
3775 proto_tree_add_item(sctp_tree, hf_verification_tag, tvb, VERIFICATION_TAG_OFFSET, VERIFICATION_TAG_LENGTH, NETWORK_BYTE_ORDER);
3776 hidden_item = proto_tree_add_item(sctp_tree, hf_port, tvb, SOURCE_PORT_OFFSET, SOURCE_PORT_LENGTH, NETWORK_BYTE_ORDER);
3777 PROTO_ITEM_SET_HIDDEN(hidden_item);
3778 hidden_item = proto_tree_add_item(sctp_tree, hf_port, tvb, DESTINATION_PORT_OFFSET, DESTINATION_PORT_LENGTH, NETWORK_BYTE_ORDER);
3779 PROTO_ITEM_SET_HIDDEN(hidden_item);
3781 if (tvb_bytes_exist(tvb, 0, reported_length)) {
3782 /* We have the whole packet */
3784 switch(sctp_checksum) {
3785 case SCTP_CHECKSUM_NONE:
3786 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, checksum, "Checksum: 0x%08x (not verified)", checksum);
3788 case SCTP_CHECKSUM_ADLER32:
3789 if (adler32_correct)
3790 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
3791 checksum, "Checksum: 0x%08x [correct Adler32]", checksum);
3793 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
3794 checksum, "Checksum: 0x%08x [incorrect Adler32, should be 0x%08x]", checksum, calculated_adler32);
3795 hidden_item = proto_tree_add_boolean(sctp_tree, hf_checksum_bad, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, !(adler32_correct));
3796 PROTO_ITEM_SET_HIDDEN(hidden_item);
3798 case SCTP_CHECKSUM_CRC32C:
3800 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
3801 checksum, "Checksum: 0x%08x [correct CRC32C]", checksum);
3803 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
3804 checksum, "Checksum: 0x%08x [incorrect CRC32C, should be 0x%08x]", checksum, calculated_crc32c);
3805 hidden_item = proto_tree_add_boolean(sctp_tree, hf_checksum_bad, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, !(crc32c_correct));
3806 PROTO_ITEM_SET_HIDDEN(hidden_item);
3808 case SCTP_CHECKSUM_AUTOMATIC:
3809 if ((adler32_correct) && !(crc32c_correct))
3810 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
3811 checksum, "Checksum: 0x%08x [correct Adler32]", checksum);
3812 else if ((!adler32_correct) && (crc32c_correct))
3813 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
3814 checksum, "Checksum: 0x%08x [correct CRC32C]", checksum);
3815 else if ((adler32_correct) && (crc32c_correct))
3816 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
3817 checksum, "Checksum: 0x%08x [correct Adler32 and CRC32C]", checksum);
3819 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
3820 checksum, "Checksum: 0x%08x [incorrect, should be 0x%08x (Adler32) or 0x%08x (CRC32C)]",
3821 checksum, calculated_adler32, calculated_crc32c);
3822 hidden_item = proto_tree_add_boolean(sctp_tree, hf_checksum_bad, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, !(crc32c_correct || adler32_correct));
3823 PROTO_ITEM_SET_HIDDEN(hidden_item);
3827 /* We don't have the whole packet so we can't verify the checksum */
3828 proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
3829 checksum, "Checksum: 0x%08x [unchecked, not all data available]", checksum);
3836 /* add all chunks of the sctp datagram to the protocol tree */
3837 dissect_sctp_chunks(tvb, pinfo, tree, sctp_item, sctp_tree, ha, encapsulated);
3841 dissect_sctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
3843 guint16 source_port, destination_port;
3845 /* Extract the common header */
3846 source_port = tvb_get_ntohs(tvb, SOURCE_PORT_OFFSET);
3847 destination_port = tvb_get_ntohs(tvb, DESTINATION_PORT_OFFSET);
3849 /* update pi structure */
3850 pinfo->ptype = PT_SCTP;
3851 pinfo->srcport = source_port;
3852 pinfo->destport = destination_port;
3854 /* make entry in the Protocol column on summary display */
3855 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCTP");
3857 /* Clear entries in Info column on summary display */
3858 if (check_col(pinfo->cinfo, COL_INFO))
3859 col_set_str(pinfo->cinfo, COL_INFO, "");
3861 memset(&pinfo->ppids, 0, sizeof(pinfo->ppids));
3863 /* The tvb array in struct _sctp_info is huge: currently 2k pointers.
3864 * We know (by the value of 'number_of_tvbs') which of these entries have
3865 * been used, so don't memset() the array. This saves us from zeroing out
3866 * 8k (4-byte pointers) or 16k (8-byte pointers) of memory every time we
3867 * dissect a packet (saving quite a bit of time!).
3869 sctp_info.incomplete = 0;
3870 sctp_info.adler32_calculated = 0;
3871 sctp_info.adler32_correct = 0;
3872 sctp_info.crc32c_calculated = 0;
3873 sctp_info.crc32c_correct = 0;
3874 sctp_info.vtag_reflected = 0;
3875 sctp_info.number_of_tvbs = 0;
3876 sctp_info.verification_tag = tvb_get_ntohl(tvb, VERIFICATION_TAG_OFFSET);
3878 sctp_info.sport = pinfo->srcport;
3879 sctp_info.dport = pinfo->destport;
3880 SET_ADDRESS(&sctp_info.ip_src, pinfo->src.type, pinfo->src.len, pinfo->src.data);
3881 SET_ADDRESS(&sctp_info.ip_dst, pinfo->dst.type, pinfo->dst.len, pinfo->dst.data);
3883 dissect_sctp_packet(tvb, pinfo, tree, FALSE);
3884 if (!pinfo->in_error_pkt)
3885 tap_queue_packet(sctp_tap, pinfo, &sctp_info);
3888 /* Register the protocol with Wireshark */
3890 proto_register_sctp(void)
3893 /* Setup list of header fields */
3894 static hf_register_info hf[] = {
3895 { &hf_source_port, { "Source port", "sctp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3896 { &hf_destination_port, { "Destination port", "sctp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3897 { &hf_port, { "Port", "sctp.port", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3898 { &hf_verification_tag, { "Verification tag", "sctp.verification_tag", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3899 { &hf_checksum, { "Checksum", "sctp.checksum", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3900 { &hf_checksum_bad, { "Bad checksum", "sctp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3901 { &hf_chunk_type, { "Chunk type", "sctp.chunk_type", FT_UINT8, BASE_DEC, VALS(chunk_type_values), 0x0, NULL, HFILL } },
3902 { &hf_chunk_flags, { "Chunk flags", "sctp.chunk_flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3903 { &hf_chunk_bit_1, { "Bit", "sctp.chunk_bit_1", FT_BOOLEAN, 8, TFS(&sctp_chunk_bit_1_value), SCTP_CHUNK_BIT_1, NULL, HFILL } },
3904 { &hf_chunk_bit_2, { "Bit", "sctp.chunk_bit_2", FT_BOOLEAN, 8, TFS(&sctp_chunk_bit_2_value), SCTP_CHUNK_BIT_2, NULL, HFILL } },
3905 { &hf_chunk_length, { "Chunk length", "sctp.chunk_length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3906 { &hf_chunk_padding, { "Chunk padding", "sctp.chunk_padding", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3907 { &hf_chunk_value, { "Chunk value", "sctp.chunk_value", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3908 { &hf_cookie, { "Cookie", "sctp.cookie", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3909 { &hf_initiate_tag, { "Initiate tag", "sctp.initiate_tag", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3910 { &hf_init_chunk_initiate_tag, { "Initiate tag", "sctp.init_initiate_tag", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3911 { &hf_init_chunk_adv_rec_window_credit, { "Advertised receiver window credit (a_rwnd)", "sctp.init_credit", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3912 { &hf_init_chunk_number_of_outbound_streams, { "Number of outbound streams", "sctp.init_nr_out_streams", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3913 { &hf_init_chunk_number_of_inbound_streams, { "Number of inbound streams", "sctp.init_nr_in_streams", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3914 { &hf_init_chunk_initial_tsn, { "Initial TSN", "sctp.init_initial_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3915 { &hf_initack_chunk_initiate_tag, { "Initiate tag", "sctp.initack_initiate_tag", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3916 { &hf_initack_chunk_adv_rec_window_credit, { "Advertised receiver window credit (a_rwnd)", "sctp.initack_credit", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3917 { &hf_initack_chunk_number_of_outbound_streams, { "Number of outbound streams", "sctp.initack_nr_out_streams", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3918 { &hf_initack_chunk_number_of_inbound_streams, { "Number of inbound streams", "sctp.initack_nr_in_streams", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3919 { &hf_initack_chunk_initial_tsn, { "Initial TSN", "sctp.initack_initial_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3920 { &hf_cumulative_tsn_ack, { "Cumulative TSN Ack", "sctp.cumulative_tsn_ack", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3921 { &hf_data_chunk_tsn, { "TSN", "sctp.data_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3922 { &hf_data_chunk_stream_id, { "Stream Identifier", "sctp.data_sid", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3923 { &hf_data_chunk_stream_seq_number, { "Stream sequence number", "sctp.data_ssn", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3924 { &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, NULL, HFILL } },
3925 { &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, NULL, HFILL } },
3926 { &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, NULL, HFILL } },
3927 { &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, NULL, HFILL } },
3928 { &hf_data_chunk_i_bit, { "I-Bit", "sctp.data_i_bit", FT_BOOLEAN, 8, TFS(&sctp_data_chunk_i_bit_value), SCTP_DATA_CHUNK_I_BIT, NULL, HFILL } },
3929 { &hf_sack_chunk_ns, { "Nounce sum", "sctp.sack_nounce_sum", FT_UINT8, BASE_DEC, NULL, SCTP_SACK_CHUNK_NS_BIT, NULL, HFILL } },
3930 { &hf_sack_chunk_cumulative_tsn_ack, { "Cumulative TSN ACK", "sctp.sack_cumulative_tsn_ack", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3931 { &hf_sack_chunk_adv_rec_window_credit, { "Advertised receiver window credit (a_rwnd)", "sctp.sack_a_rwnd", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3932 { &hf_sack_chunk_number_of_gap_blocks, { "Number of gap acknowledgement blocks", "sctp.sack_number_of_gap_blocks", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3933 { &hf_sack_chunk_number_of_dup_tsns, { "Number of duplicated TSNs", "sctp.sack_number_of_duplicated_tsns", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3934 { &hf_sack_chunk_gap_block_start, { "Start", "sctp.sack_gap_block_start", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3935 { &hf_sack_chunk_gap_block_start_tsn, { "Start TSN", "sctp.sack_gap_block_start_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3936 { &hf_sack_chunk_gap_block_end, { "End", "sctp.sack_gap_block_end", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3937 { &hf_sack_chunk_gap_block_end_tsn, { "End TSN", "sctp.sack_gap_block_end_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3938 { &hf_sack_chunk_number_tsns_gap_acked, { "Number of TSNs in gap acknowledgement blocks", "sctp.sack_number_of_tsns_gap_acked", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3939 { &hf_sack_chunk_duplicate_tsn, { "Duplicate TSN", "sctp.sack_duplicate_tsn", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3940 { &hf_nr_sack_chunk_ns, { "Nounce sum", "sctp.nr_sack_nounce_sum", FT_UINT8, BASE_DEC, NULL, SCTP_NR_SACK_CHUNK_NS_BIT, NULL, HFILL } },
3941 { &hf_nr_sack_chunk_cumulative_tsn_ack, { "Cumulative TSN ACK", "sctp.nr_sack_cumulative_tsn_ack", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3942 { &hf_nr_sack_chunk_adv_rec_window_credit, { "Advertised receiver window credit (a_rwnd)", "sctp.nr_sack_a_rwnd", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3943 { &hf_nr_sack_chunk_number_of_gap_blocks, { "Number of gap acknowledgement blocks", "sctp.nr_sack_number_of_gap_blocks", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3944 { &hf_nr_sack_chunk_number_of_nr_gap_blocks, { "Number of nr-gap acknowledgement blocks", "sctp.nr_sack_number_of_nr_gap_blocks", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3945 { &hf_nr_sack_chunk_number_of_dup_tsns, { "Number of duplicated TSNs", "sctp.nr_sack_number_of_duplicated_tsns", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3946 { &hf_nr_sack_chunk_reserved, { "Reserved", "sctp.nr_sack_reserved", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3947 { &hf_nr_sack_chunk_gap_block_start, { "Start", "sctp.nr_sack_gap_block_start", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3948 { &hf_nr_sack_chunk_gap_block_start_tsn, { "Start TSN", "sctp.nr_sack_gap_block_start_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3949 { &hf_nr_sack_chunk_gap_block_end, { "End", "sctp.nr_sack_gap_block_end", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3950 { &hf_nr_sack_chunk_gap_block_end_tsn, { "End TSN", "sctp.nr_sack_gap_block_end_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3951 { &hf_nr_sack_chunk_number_tsns_gap_acked, { "Number of TSNs in gap acknowledgement blocks", "sctp.nr_sack_number_of_tsns_gap_acked", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3952 { &hf_nr_sack_chunk_nr_gap_block_start, { "Start", "sctp.nr_sack_nr_gap_block_start", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3953 { &hf_nr_sack_chunk_nr_gap_block_start_tsn, { "Start TSN", "sctp.nr_sack_nr_gap_block_start_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3954 { &hf_nr_sack_chunk_nr_gap_block_end, { "End", "sctp.nr_sack_nr_gap_block_end", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3955 { &hf_nr_sack_chunk_nr_gap_block_end_tsn, { "End TSN", "sctp.nr_sack_nr_gap_block_end_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3956 { &hf_nr_sack_chunk_number_tsns_nr_gap_acked, { "Number of TSNs in nr-gap acknowledgement blocks","sctp.nr_sack_number_of_tsns_nr_gap_acked", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3957 { &hf_nr_sack_chunk_duplicate_tsn, { "Duplicate TSN", "sctp.nr_sack_duplicate_tsn", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3958 { &hf_shutdown_chunk_cumulative_tsn_ack, { "Cumulative TSN Ack", "sctp.shutdown_cumulative_tsn_ack", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3959 { &hf_ecne_chunk_lowest_tsn, { "Lowest TSN", "sctp.ecne_lowest_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3960 { &hf_cwr_chunk_lowest_tsn, { "Lowest TSN", "sctp.cwr_lowest_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3961 { &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, NULL, HFILL } },
3962 { &hf_abort_chunk_t_bit, { "T-Bit", "sctp.abort_t_bit", FT_BOOLEAN, 8, TFS(&sctp_shutdown_complete_chunk_t_bit_value), SCTP_ABORT_CHUNK_T_BIT, NULL, HFILL } },
3963 { &hf_forward_tsn_chunk_tsn, { "New cumulative TSN", "sctp.forward_tsn_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3964 { &hf_forward_tsn_chunk_sid, { "Stream identifier", "sctp.forward_tsn_sid", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3965 { &hf_forward_tsn_chunk_ssn, { "Stream sequence number", "sctp.forward_tsn_ssn", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3966 { &hf_parameter_type, { "Parameter type", "sctp.parameter_type", FT_UINT16, BASE_HEX, VALS(parameter_identifier_values), 0x0, NULL, HFILL } },
3967 { &hf_parameter_length, { "Parameter length", "sctp.parameter_length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3968 { &hf_parameter_value, { "Parameter value", "sctp.parameter_value", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3969 { &hf_parameter_padding, { "Parameter padding", "sctp.parameter_padding", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3970 { &hf_parameter_bit_1, { "Bit", "sctp.parameter_bit_1", FT_BOOLEAN, 16, TFS(&sctp_parameter_bit_1_value), SCTP_PARAMETER_BIT_1, NULL, HFILL } },
3971 { &hf_parameter_bit_2, { "Bit", "sctp.parameter_bit_2", FT_BOOLEAN, 16, TFS(&sctp_parameter_bit_2_value), SCTP_PARAMETER_BIT_2, NULL, HFILL } },
3972 { &hf_ipv4_address, { "IP Version 4 address", "sctp.parameter_ipv4_address", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3973 { &hf_ipv6_address, { "IP Version 6 address", "sctp.parameter_ipv6_address", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3974 { &hf_heartbeat_info, { "Heartbeat information", "sctp.parameter_heartbeat_information", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3975 { &hf_state_cookie, { "State cookie", "sctp.parameter_state_cookie", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3976 { &hf_cookie_preservative_increment, { "Suggested Cookie life-span increment (msec)", "sctp.parameter_cookie_preservative_incr", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3977 { &hf_hostname, { "Hostname", "sctp.parameter_hostname", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3978 { &hf_supported_address_type, { "Supported address type", "sctp.parameter_supported_addres_type", FT_UINT16, BASE_DEC, VALS(address_types_values), 0x0, NULL, HFILL } },
3979 { &hf_stream_reset_req_seq_nr, { "Stream reset request sequence number", "sctp.parameter_stream_reset_request_sequence_number", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3980 { &hf_stream_reset_rsp_seq_nr, { "Stream reset response sequence number", "sctp.parameter_stream_reset_response_sequence_number", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3981 { &hf_senders_last_assigned_tsn, { "Senders last assigned TSN", "sctp.parameter_senders_last_assigned_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3982 { &hf_senders_next_tsn, { "Senders next TSN", "sctp.parameter_senders_next_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3983 { &hf_receivers_next_tsn, { "Receivers next TSN", "sctp.parameter_receivers_next_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3984 { &hf_stream_reset_rsp_result, { "Result", "sctp.parameter_stream_reset_response_result", FT_UINT32, BASE_DEC, VALS(stream_reset_result_values), 0x0, NULL, HFILL } },
3985 { &hf_stream_reset_sid, { "Stream Identifier", "sctp.parameter_stream_reset_sid", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3986 { &hf_asconf_serial, { "Serial number", "sctp.asconf_serial_number", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3987 { &hf_asconf_ack_serial, { "Serial number", "sctp.asconf_ack_serial_number", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3988 { &hf_correlation_id, { "Correlation_id", "sctp.correlation_id", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3989 { &hf_adap_indication, { "Indication", "sctp.adapation_layer_indication", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3990 { &hf_random_number, { "Random number", "sctp.random_number", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3991 { &hf_chunks_to_auth, { "Chunk type", "sctp.chunk_type_to_auth", FT_UINT8, BASE_DEC, VALS(chunk_type_values), 0x0, NULL, HFILL } },
3992 { &hf_hmac_id, { "HMAC identifier", "sctp.hmac_id", FT_UINT16, BASE_DEC, VALS(hmac_id_values), 0x0, NULL, HFILL } },
3993 { &hf_hmac, { "HMAC", "sctp.hmac", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3994 { &hf_shared_key_id, { "Shared key identifier", "sctp.shared_key_id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3995 { &hf_supported_chunk_type, { "Supported chunk type", "sctp.supported_chunk_type", FT_UINT8, BASE_DEC, VALS(chunk_type_values), 0x0, NULL, HFILL } },
3996 { &hf_cause_code, { "Cause code", "sctp.cause_code", FT_UINT16, BASE_HEX, VALS(cause_code_values), 0x0, NULL, HFILL } },
3997 { &hf_cause_length, { "Cause length", "sctp.cause_length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3998 { &hf_cause_info, { "Cause information", "sctp.cause_information", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3999 { &hf_cause_padding, { "Cause padding", "sctp.cause_padding", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
4000 { &hf_cause_stream_identifier, { "Stream identifier", "sctp.cause_stream_identifier", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
4001 { &hf_cause_reserved, { "Reserved", "sctp.cause_reserved", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
4002 { &hf_cause_number_of_missing_parameters, { "Number of missing parameters", "sctp.cause_nr_of_missing_parameters", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
4003 { &hf_cause_missing_parameter_type, { "Missing parameter type", "sctp.cause_missing_parameter_type", FT_UINT16, BASE_HEX, VALS(parameter_identifier_values), 0x0, NULL, HFILL } },
4004 { &hf_cause_measure_of_staleness, { "Measure of staleness in usec", "sctp.cause_measure_of_staleness", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
4005 { &hf_cause_tsn, { "TSN", "sctp.cause_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
4006 { &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, NULL, HFILL } },
4007 { &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, NULL, HFILL } },
4008 { &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, NULL, HFILL } },
4009 { &hf_pktdrop_chunk_bandwidth, { "Bandwidth", "sctp.pktdrop_bandwidth", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
4010 { &hf_pktdrop_chunk_queuesize, { "Queuesize", "sctp.pktdrop_queuesize", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
4011 { &hf_pktdrop_chunk_truncated_length, { "Truncated length", "sctp.pktdrop_truncated_length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
4012 { &hf_pktdrop_chunk_reserved, { "Reserved", "sctp.pktdrop_reserved", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
4013 { &hf_pktdrop_chunk_data_field, { "Data field", "sctp.pktdrop_datafield", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
4015 { &hf_sctp_fragment, { "SCTP Fragment", "sctp.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
4016 { &hf_sctp_fragments, { "Reassembled SCTP Fragments", "sctp.fragments", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
4017 { &hf_sctp_reassembled_in, { "Reassembled Message in frame", "sctp.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
4018 { &hf_sctp_duplicate, { "Fragment already seen in frame", "sctp.duplicate", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
4020 { &hf_sctp_rtt, { "The RTT to ACK the chunk was", "sctp.rtt", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, NULL, HFILL } },
4021 { &hf_sctp_rto, { "Retransmitted after", "sctp.retransmission_time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, NULL, HFILL } },
4022 { &hf_sctp_retransmission, { "This TSN is a retransmission of one in frame", "sctp.retransmission", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
4023 { &hf_sctp_retransmitted, { "This TSN is retransmitted in frame", "sctp.retransmitted", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
4024 { &hf_sctp_retransmitted_count, { "TSN was retransmitted this many times", "sctp.retransmitted_count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
4025 { &hf_sctp_acked, { "This chunk is acked in frame", "sctp.acked", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
4026 { &hf_sctp_ack_tsn, { "Acknowledges TSN", "sctp.ack", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
4027 { &hf_sctp_ack_frame, { "Chunk acknowledged in frame", "sctp.ack_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
4028 { &hf_sctp_retransmitted_after_ack, { "Chunk was acked prior to retransmission", "sctp.retransmitted_after_ack", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } }
4032 /* Setup protocol subtree array */
4033 static gint *ett[] = {
4036 &ett_sctp_chunk_parameter,
4037 &ett_sctp_chunk_cause,
4038 &ett_sctp_chunk_type,
4039 &ett_sctp_data_chunk_flags,
4040 &ett_sctp_sack_chunk_flags,
4041 &ett_sctp_nr_sack_chunk_flags,
4042 &ett_sctp_abort_chunk_flags,
4043 &ett_sctp_shutdown_complete_chunk_flags,
4044 &ett_sctp_pktdrop_chunk_flags,
4045 &ett_sctp_parameter_type,
4046 &ett_sctp_sack_chunk_gap_block,
4047 &ett_sctp_sack_chunk_gap_block_start,
4048 &ett_sctp_sack_chunk_gap_block_end,
4049 &ett_sctp_nr_sack_chunk_gap_block,
4050 &ett_sctp_nr_sack_chunk_gap_block_start,
4051 &ett_sctp_nr_sack_chunk_gap_block_end,
4052 &ett_sctp_nr_sack_chunk_nr_gap_block,
4053 &ett_sctp_nr_sack_chunk_nr_gap_block_start,
4054 &ett_sctp_nr_sack_chunk_nr_gap_block_end,
4055 &ett_sctp_unrecognized_parameter_parameter,
4056 &ett_sctp_fragments,
4061 &ett_sctp_tsn_retransmission,
4062 &ett_sctp_tsn_retransmitted_count,
4063 &ett_sctp_tsn_retransmitted
4066 static enum_val_t sctp_checksum_options[] = {
4067 { "none", "None", SCTP_CHECKSUM_NONE },
4068 { "adler-32", "Adler 32", SCTP_CHECKSUM_ADLER32 },
4069 { "crc-32c", "CRC 32c", SCTP_CHECKSUM_CRC32C },
4070 { "automatic", "Automatic", SCTP_CHECKSUM_AUTOMATIC},
4074 /* Register the protocol name and description */
4075 proto_sctp = proto_register_protocol("Stream Control Transmission Protocol", "SCTP", "sctp");
4076 sctp_module = prefs_register_protocol(proto_sctp, NULL);
4077 prefs_register_bool_preference(sctp_module, "show_port_numbers_in_tree",
4078 "Show port numbers in the protocol tree",
4079 "Show source and destination port numbers in the protocol tree",
4080 &show_port_numbers);
4082 prefs_register_bool_preference(sctp_module, "show_chunk_types_in_tree",
4083 "Show chunk types in the protocol tree",
4084 "Show chunk types in the protocol tree",
4087 prefs_register_enum_preference(sctp_module, "checksum", "Checksum type",
4088 "The type of checksum used in SCTP packets",
4089 &sctp_checksum, sctp_checksum_options, FALSE);
4090 prefs_register_bool_preference(sctp_module, "show_always_control_chunks",
4091 "Show always control chunks",
4092 "Show always SCTP control chunks in the Info column",
4093 &show_always_control_chunks);
4094 prefs_register_bool_preference(sctp_module, "try_heuristic_first",
4095 "Try heuristic sub-dissectors first",
4096 "Try to decode a packet using an heuristic sub-dissector before using a sub-dissector registered to a specific port or PPI",
4097 &try_heuristic_first);
4098 prefs_register_bool_preference(sctp_module, "reassembly",
4099 "Reassemble fragmented SCTP user messages",
4100 "Whether fragmented SCTP user messages should be reassembled",
4102 prefs_register_bool_preference(sctp_module, "tsn_analysis",
4103 "Enable TSN analysis",
4104 "Match TSNs and their SACKs",
4105 &enable_tsn_analysis);
4106 prefs_register_bool_preference(sctp_module, "ulp_dissection",
4107 "Dissect upper layer protocols",
4108 "Dissect upper layer protocols",
4109 &enable_ulp_dissection);
4111 /* Required function calls to register the header fields and subtrees used */
4112 proto_register_field_array(proto_sctp, hf, array_length(hf));
4113 proto_register_subtree_array(ett, array_length(ett));
4114 sctp_tap = register_tap("sctp");
4115 /* subdissector code */
4116 sctp_port_dissector_table = register_dissector_table("sctp.port", "SCTP port", FT_UINT16, BASE_DEC);
4117 sctp_ppi_dissector_table = register_dissector_table("sctp.ppi", "SCTP payload protocol identifier", FT_UINT32, BASE_HEX);
4119 register_dissector("sctp", dissect_sctp, proto_sctp);
4120 register_heur_dissector_list("sctp", &sctp_heur_subdissector_list);
4122 register_init_routine(frag_table_init);
4124 dirs_by_ptvtag = se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "sctp_dirs_by_ptvtag");
4125 dirs_by_ptaddr = se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "sctp_dirs_by_ptaddr");
4129 proto_reg_handoff_sctp(void)
4131 dissector_handle_t sctp_handle;
4133 data_handle = find_dissector("data");
4134 sctp_handle = find_dissector("sctp");
4135 dissector_add("ip.proto", IP_PROTO_SCTP, sctp_handle);
4136 dissector_add("udp.port", UDP_TUNNELING_PORT, sctp_handle);