1 /* packet-sctp.c
2  * Routines for Stream Control Transmission Protocol dissection
3  * Copyright 2000-2012 Michael Tuexen <tuexen [AT] fh-muenster.de>
4  * Copyright 2011-2021 Thomas Dreibholz <dreibh [AT] iem.uni-due.de>
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * SPDX-License-Identifier: GPL-2.0-or-later
11  */
12 /*
13  * It should be compliant to
14  * - RFC 2960
15  * - RFC 3309
16  * - RFC 3758
17  * - RFC 4460
18  * - RFC 4895
19  * - RFC 4960
20  * - RFC 5061
21  * - RFC 6525
22  * - RFC 7053
23  * - https://tools.ietf.org/html/draft-stewart-sctp-pktdrprep-02
24  * - https://tools.ietf.org/html/draft-ladha-sctp-nonce-02
25  *
26  * Still to do (so stay tuned)
27  * - error checking mode
28  *   * padding errors
29  *   * length errors
30  *   * bundling errors
31  *   * value errors
32  *
33  * Reassembly added 2006 by Robin Seggelmann
34  * TSN Tracking by Luis E. G. Ontanon (Feb 2007)
35  * Copyright 2009, Varun Notibala <nbvarun [AT] gmail.com>
36  *
37  * PPID types updated by Thomas Dreibholz (Feb 2011)
38  */
39 
40 #include "config.h"
41 
42 #include "ws_symbol_export.h"
43 
44 #include <epan/packet.h>
45 #include <epan/capture_dissectors.h>
46 #include <epan/prefs.h>
47 #include <epan/exceptions.h>
48 #include <epan/exported_pdu.h>
49 #include <epan/ipproto.h>
50 #include <epan/addr_resolv.h>
51 #include <epan/sctpppids.h>
52 #include <epan/uat.h>
53 #include <epan/expert.h>
54 #include <epan/conversation_table.h>
55 #include <epan/show_exception.h>
56 #include <epan/decode_as.h>
57 #include <epan/proto_data.h>
58 
59 #include <wsutil/crc32.h>
60 #include <wsutil/adler32.h>
61 #include <wsutil/utf8_entities.h>
62 #include <wsutil/str_util.h>
63 
64 #include "packet-sctp.h"
65 
66 #define LT(x, y) ((gint32)((x) - (y)) < 0)
67 
68 #define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
69 #define UDP_TUNNELING_PORT 9899
70 
71 #define MAX_NUMBER_OF_PPIDS     2
72 /** This is a valid PPID, but we use it to mark the end of the list */
73 #define LAST_PPID 0xffffffff
74 
75 void proto_register_sctp(void);
76 void proto_reg_handoff_sctp(void);
77 
78 /* Initialize the protocol and registered fields */
79 static int proto_sctp = -1;
80 static int hf_port = -1;
81 static int hf_source_port      = -1;
82 static int hf_destination_port = -1;
83 static int hf_verification_tag = -1;
84 static int hf_checksum         = -1;
85 static int hf_checksum_adler   = -1;
86 static int hf_checksum_crc32c  = -1;
87 static int hf_checksum_status  = -1;
88 
89 static int hf_chunk_type       = -1;
90 static int hf_chunk_flags      = -1;
91 static int hf_chunk_bit_1      = -1;
92 static int hf_chunk_bit_2      = -1;
93 static int hf_chunk_length     = -1;
94 static int hf_chunk_padding    = -1;
95 static int hf_chunk_value    = -1;
96 
97 static int hf_initiate_tag   = -1;
98 static int hf_init_chunk_initiate_tag   = -1;
99 static int hf_init_chunk_adv_rec_window_credit = -1;
100 static int hf_init_chunk_number_of_outbound_streams = -1;
101 static int hf_init_chunk_number_of_inbound_streams  = -1;
102 static int hf_init_chunk_initial_tsn    = -1;
103 
104 static int hf_initack_chunk_initiate_tag   = -1;
105 static int hf_initack_chunk_adv_rec_window_credit = -1;
106 static int hf_initack_chunk_number_of_outbound_streams = -1;
107 static int hf_initack_chunk_number_of_inbound_streams  = -1;
108 static int hf_initack_chunk_initial_tsn    = -1;
109 
110 static int hf_data_chunk_tsn = -1;
111 static int hf_data_chunk_tsn_raw = -1;
112 static int hf_data_chunk_stream_id = -1;
113 static int hf_data_chunk_stream_seq_number = -1;
114 static int hf_data_chunk_payload_proto_id = -1;
115 static int hf_idata_chunk_reserved = -1;
116 static int hf_idata_chunk_mid = -1;
117 static int hf_idata_chunk_fsn = -1;
118 
119 static int hf_data_chunk_e_bit = -1;
120 static int hf_data_chunk_b_bit = -1;
121 static int hf_data_chunk_u_bit = -1;
122 static int hf_data_chunk_i_bit = -1;
123 
124 static int hf_sack_chunk_ns = -1;
125 static int hf_sack_chunk_cumulative_tsn_ack = -1;
126 static int hf_sack_chunk_cumulative_tsn_ack_raw = -1;
127 static int hf_sack_chunk_adv_rec_window_credit = -1;
128 static int hf_sack_chunk_number_of_gap_blocks = -1;
129 static int hf_sack_chunk_number_of_dup_tsns = -1;
130 static int hf_sack_chunk_gap_block_start = -1;
131 static int hf_sack_chunk_gap_block_end = -1;
132 static int hf_sack_chunk_gap_block_start_tsn = -1;
133 static int hf_sack_chunk_gap_block_end_tsn = -1;
134 static int hf_sack_chunk_number_tsns_gap_acked = -1;
135 static int hf_sack_chunk_duplicate_tsn = -1;
136 
137 static int hf_nr_sack_chunk_ns = -1;
138 static int hf_nr_sack_chunk_cumulative_tsn_ack = -1;
139 static int hf_nr_sack_chunk_adv_rec_window_credit = -1;
140 static int hf_nr_sack_chunk_number_of_gap_blocks = -1;
141 static int hf_nr_sack_chunk_number_of_nr_gap_blocks = -1;
142 static int hf_nr_sack_chunk_number_of_dup_tsns = -1;
143 static int hf_nr_sack_chunk_reserved = -1;
144 static int hf_nr_sack_chunk_gap_block_start = -1;
145 static int hf_nr_sack_chunk_gap_block_end = -1;
146 static int hf_nr_sack_chunk_gap_block_start_tsn = -1;
147 static int hf_nr_sack_chunk_gap_block_end_tsn = -1;
148 static int hf_nr_sack_chunk_number_tsns_gap_acked = -1;
149 static int hf_nr_sack_chunk_nr_gap_block_start = -1;
150 static int hf_nr_sack_chunk_nr_gap_block_end = -1;
151 static int hf_nr_sack_chunk_nr_gap_block_start_tsn = -1;
152 static int hf_nr_sack_chunk_nr_gap_block_end_tsn = -1;
153 static int hf_nr_sack_chunk_number_tsns_nr_gap_acked = -1;
154 static int hf_nr_sack_chunk_duplicate_tsn = -1;
155 
156 static int hf_shutdown_chunk_cumulative_tsn_ack = -1;
157 static int hf_cookie = -1;
158 static int hf_cwr_chunk_lowest_tsn = -1;
159 
160 static int hf_ecne_chunk_lowest_tsn = -1;
161 static int hf_abort_chunk_t_bit = -1;
162 static int hf_shutdown_complete_chunk_t_bit = -1;
163 
164 static int hf_parameter_type = -1;
165 static int hf_parameter_length = -1;
166 static int hf_parameter_value = -1;
167 static int hf_parameter_padding = -1;
168 static int hf_parameter_bit_1      = -1;
169 static int hf_parameter_bit_2      = -1;
170 static int hf_ipv4_address = -1;
171 static int hf_ipv6_address = -1;
172 static int hf_heartbeat_info = -1;
173 static int hf_state_cookie = -1;
174 static int hf_cookie_preservative_increment = -1;
175 static int hf_hostname = -1;
176 static int hf_supported_address_type = -1;
177 static int hf_stream_reset_req_seq_nr = -1;
178 static int hf_stream_reset_rsp_seq_nr = -1;
179 static int hf_senders_last_assigned_tsn = -1;
180 static int hf_senders_next_tsn = -1;
181 static int hf_receivers_next_tsn = -1;
182 static int hf_stream_reset_rsp_result = -1;
183 static int hf_stream_reset_sid = -1;
184 static int hf_add_outgoing_streams_number_streams = -1;
185 static int hf_add_outgoing_streams_reserved = -1;
186 static int hf_add_incoming_streams_number_streams = -1;
187 static int hf_add_incoming_streams_reserved = -1;
188 
189 static int hf_random_number = -1;
190 static int hf_chunks_to_auth = -1;
191 static int hf_hmac_id = -1;
192 static int hf_hmac = -1;
193 static int hf_shared_key_id = -1;
194 static int hf_supported_chunk_type = -1;
195 
196 static int hf_cause_code = -1;
197 static int hf_cause_length = -1;
198 static int hf_cause_padding = -1;
199 static int hf_cause_info = -1;
200 
201 static int hf_cause_stream_identifier = -1;
202 static int hf_cause_reserved = -1;
203 
204 static int hf_cause_number_of_missing_parameters = -1;
205 static int hf_cause_missing_parameter_type = -1;
206 
207 static int hf_cause_measure_of_staleness = -1;
208 
209 static int hf_cause_tsn = -1;
210 
211 static int hf_forward_tsn_chunk_tsn = -1;
212 static int hf_forward_tsn_chunk_sid = -1;
213 static int hf_forward_tsn_chunk_ssn = -1;
214 
215 static int hf_i_forward_tsn_chunk_tsn = -1;
216 static int hf_i_forward_tsn_chunk_sid = -1;
217 static int hf_i_forward_tsn_chunk_flags = -1;
218 static int hf_i_forward_tsn_chunk_res = -1;
219 static int hf_i_forward_tsn_chunk_u_bit = -1;
220 static int hf_i_forward_tsn_chunk_mid = -1;
221 
222 static int hf_asconf_ack_seq_nr = -1;
223 static int hf_asconf_seq_nr = -1;
224 static int hf_correlation_id = -1;
225 
226 static int hf_adap_indication = -1;
227 
228 static int hf_pktdrop_chunk_m_bit = -1;
229 static int hf_pktdrop_chunk_b_bit = -1;
230 static int hf_pktdrop_chunk_t_bit = -1;
231 static int hf_pktdrop_chunk_bandwidth = -1;
232 static int hf_pktdrop_chunk_queuesize = -1;
233 static int hf_pktdrop_chunk_truncated_length = -1;
234 static int hf_pktdrop_chunk_reserved = -1;
235 static int hf_pktdrop_chunk_data_field = -1;
236 
237 static int hf_pad_chunk_padding_data = -1;
238 
239 static int hf_sctp_reassembled_in = -1;
240 static int hf_sctp_duplicate = -1;
241 static int hf_sctp_fragments = -1;
242 static int hf_sctp_fragment = -1;
243 
244 static int hf_sctp_retransmission = -1;
245 static int hf_sctp_retransmitted = -1;
246 static int hf_sctp_retransmitted_count = -1;
247 static int hf_sctp_data_rtt = -1;
248 static int hf_sctp_sack_rtt = -1;
249 static int hf_sctp_rto = -1;
250 static int hf_sctp_ack_tsn = -1;
251 static int hf_sctp_ack_frame = -1;
252 static int hf_sctp_acked = -1;
253 static int hf_sctp_retransmitted_after_ack = -1;
254 
255 static int hf_sctp_assoc_index = -1;
256 
257 static dissector_table_t sctp_port_dissector_table;
258 static dissector_table_t sctp_ppi_dissector_table;
259 static heur_dissector_list_t sctp_heur_subdissector_list;
260 static int sctp_tap = -1;
261 static int exported_pdu_tap = -1;
262 
263 /* Initialize the subtree pointers */
264 static gint ett_sctp = -1;
265 static gint ett_sctp_chunk = -1;
266 static gint ett_sctp_chunk_parameter = -1;
267 static gint ett_sctp_chunk_cause = -1;
268 static gint ett_sctp_chunk_type = -1;
269 static gint ett_sctp_data_chunk_flags = -1;
270 static gint ett_sctp_sack_chunk_flags = -1;
271 static gint ett_sctp_nr_sack_chunk_flags = -1;
272 static gint ett_sctp_abort_chunk_flags = -1;
273 static gint ett_sctp_shutdown_complete_chunk_flags = -1;
274 static gint ett_sctp_pktdrop_chunk_flags = -1;
275 static gint ett_sctp_parameter_type= -1;
276 static gint ett_sctp_sack_chunk_gap_block = -1;
277 static gint ett_sctp_sack_chunk_gap_block_start = -1;
278 static gint ett_sctp_sack_chunk_gap_block_end = -1;
279 static gint ett_sctp_nr_sack_chunk_gap_block = -1;
280 static gint ett_sctp_nr_sack_chunk_gap_block_start = -1;
281 static gint ett_sctp_nr_sack_chunk_gap_block_end = -1;
282 static gint ett_sctp_nr_sack_chunk_nr_gap_block = -1;
283 static gint ett_sctp_nr_sack_chunk_nr_gap_block_start = -1;
284 static gint ett_sctp_nr_sack_chunk_nr_gap_block_end = -1;
285 static gint ett_sctp_unrecognized_parameter_parameter = -1;
286 static gint ett_sctp_i_forward_tsn_chunk_flags = -1;
287 
288 static gint ett_sctp_fragments = -1;
289 static gint ett_sctp_fragment  = -1;
290 
291 static gint ett_sctp_tsn = -1;
292 static gint ett_sctp_ack = -1;
293 static gint ett_sctp_acked = -1;
294 static gint ett_sctp_tsn_retransmission = -1;
295 static gint ett_sctp_tsn_retransmitted_count = -1;
296 static gint ett_sctp_tsn_retransmitted = -1;
297 
298 static expert_field ei_sctp_sack_chunk_adv_rec_window_credit = EI_INIT;
299 static expert_field ei_sctp_nr_sack_chunk_number_tsns_gap_acked_100 = EI_INIT;
300 static expert_field ei_sctp_parameter_length = EI_INIT;
301 static expert_field ei_sctp_bad_sctp_checksum = EI_INIT;
302 static expert_field ei_sctp_tsn_retransmitted_more_than_twice = EI_INIT;
303 static expert_field ei_sctp_parameter_padding = EI_INIT;
304 static expert_field ei_sctp_retransmitted_after_ack = EI_INIT;
305 static expert_field ei_sctp_nr_sack_chunk_number_tsns_nr_gap_acked_100 = EI_INIT;
306 static expert_field ei_sctp_sack_chunk_gap_block_out_of_order = EI_INIT;
307 static expert_field ei_sctp_chunk_length_bad = EI_INIT;
308 static expert_field ei_sctp_tsn_retransmitted = EI_INIT;
309 static expert_field ei_sctp_sack_chunk_gap_block_malformed = EI_INIT;
310 static expert_field ei_sctp_sack_chunk_number_tsns_gap_acked_100 = EI_INIT;
311 
312 WS_DLL_PUBLIC_DEF const value_string chunk_type_values[] = {
313   { SCTP_DATA_CHUNK_ID,              "DATA" },
314   { SCTP_INIT_CHUNK_ID,              "INIT" },
315   { SCTP_INIT_ACK_CHUNK_ID,          "INIT_ACK" },
316   { SCTP_SACK_CHUNK_ID,              "SACK" },
317   { SCTP_HEARTBEAT_CHUNK_ID,         "HEARTBEAT" },
318   { SCTP_HEARTBEAT_ACK_CHUNK_ID,     "HEARTBEAT_ACK" },
319   { SCTP_ABORT_CHUNK_ID,             "ABORT" },
320   { SCTP_SHUTDOWN_CHUNK_ID,          "SHUTDOWN" },
321   { SCTP_SHUTDOWN_ACK_CHUNK_ID,      "SHUTDOWN_ACK" },
322   { SCTP_ERROR_CHUNK_ID,             "ERROR" },
323   { SCTP_COOKIE_ECHO_CHUNK_ID,       "COOKIE_ECHO" },
324   { SCTP_COOKIE_ACK_CHUNK_ID,        "COOKIE_ACK" },
325   { SCTP_ECNE_CHUNK_ID,              "ECNE" },
326   { SCTP_CWR_CHUNK_ID,               "CWR" },
327   { SCTP_SHUTDOWN_COMPLETE_CHUNK_ID, "SHUTDOWN_COMPLETE" },
328   { SCTP_AUTH_CHUNK_ID,              "AUTH" },
329   { SCTP_NR_SACK_CHUNK_ID,           "NR_SACK" },
330   { SCTP_I_DATA_CHUNK_ID,            "I_DATA" },
331   { SCTP_ASCONF_ACK_CHUNK_ID,        "ASCONF_ACK" },
332   { SCTP_PKTDROP_CHUNK_ID,           "PKTDROP" },
333   { SCTP_RE_CONFIG_CHUNK_ID,         "RE_CONFIG" },
334   { SCTP_PAD_CHUNK_ID,               "PAD" },
335   { SCTP_FORWARD_TSN_CHUNK_ID,       "FORWARD_TSN" },
336   { SCTP_ASCONF_CHUNK_ID,            "ASCONF" },
337   { SCTP_I_FORWARD_TSN_CHUNK_ID,     "I_FORWARD_TSN" },
338   { SCTP_IETF_EXT,                   "IETF_EXTENSION" },
339   { 0,                               NULL } };
340 
341 
342 #define CHUNK_TYPE_LENGTH             1
343 #define CHUNK_FLAGS_LENGTH            1
344 #define CHUNK_LENGTH_LENGTH           2
345 #define CHUNK_HEADER_LENGTH           (CHUNK_TYPE_LENGTH + \
346                                        CHUNK_FLAGS_LENGTH + \
347                                        CHUNK_LENGTH_LENGTH)
348 #define CHUNK_HEADER_OFFSET           0
349 #define CHUNK_TYPE_OFFSET             CHUNK_HEADER_OFFSET
350 #define CHUNK_FLAGS_OFFSET            (CHUNK_TYPE_OFFSET + CHUNK_TYPE_LENGTH)
351 #define CHUNK_LENGTH_OFFSET           (CHUNK_FLAGS_OFFSET + CHUNK_FLAGS_LENGTH)
352 #define CHUNK_VALUE_OFFSET            (CHUNK_LENGTH_OFFSET + CHUNK_LENGTH_LENGTH)
353 
354 #define PARAMETER_TYPE_LENGTH            2
355 #define PARAMETER_LENGTH_LENGTH          2
356 #define PARAMETER_HEADER_LENGTH          (PARAMETER_TYPE_LENGTH + PARAMETER_LENGTH_LENGTH)
357 
358 #define PARAMETER_HEADER_OFFSET          0
359 #define PARAMETER_TYPE_OFFSET            PARAMETER_HEADER_OFFSET
360 #define PARAMETER_LENGTH_OFFSET          (PARAMETER_TYPE_OFFSET + PARAMETER_TYPE_LENGTH)
361 #define PARAMETER_VALUE_OFFSET           (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
362 
363 #define SOURCE_PORT_LENGTH      2
364 #define DESTINATION_PORT_LENGTH 2
365 #define VERIFICATION_TAG_LENGTH 4
366 #define CHECKSUM_LENGTH         4
367 #define COMMON_HEADER_LENGTH    (SOURCE_PORT_LENGTH + \
368                                  DESTINATION_PORT_LENGTH + \
369                                  VERIFICATION_TAG_LENGTH + \
370                                  CHECKSUM_LENGTH)
371 #define SOURCE_PORT_OFFSET      0
372 #define DESTINATION_PORT_OFFSET (SOURCE_PORT_OFFSET + SOURCE_PORT_LENGTH)
373 #define VERIFICATION_TAG_OFFSET (DESTINATION_PORT_OFFSET + DESTINATION_PORT_LENGTH)
374 #define CHECKSUM_OFFSET         (VERIFICATION_TAG_OFFSET + VERIFICATION_TAG_LENGTH)
375 
376 #define SCTP_CHECKSUM_NONE      0
377 #define SCTP_CHECKSUM_ADLER32   1
378 #define SCTP_CHECKSUM_CRC32C    2
379 #define SCTP_CHECKSUM_AUTOMATIC 3
380 
381 #define FORWARD_STREAM                     0
382 #define BACKWARD_STREAM                    1
383 #define FORWARD_ADD_FORWARD_VTAG           2
384 #define BACKWARD_ADD_FORWARD_VTAG          3
385 #define BACKWARD_ADD_BACKWARD_VTAG         4
386 #define ASSOC_NOT_FOUND                    5
387 
388 /* Default values for preferences */
389 static gboolean show_port_numbers           = TRUE;
390 static gint sctp_checksum                   = SCTP_CHECKSUM_NONE;
391 static gboolean enable_tsn_analysis         = TRUE;
392 static gboolean enable_association_indexing = FALSE;
393 static gboolean enable_ulp_dissection       = TRUE;
394 static gboolean use_reassembly              = TRUE;
395 static gboolean show_always_control_chunks  = TRUE;
396 static gboolean show_relative_tsns          = TRUE;
397 
398 /* Data types and functions for generation/handling of chunk types for chunk statistics */
399 
400 static const value_string chunk_enabled[] = {
401   {0,"Show"},
402   {1,"Hide"},
403   {0, NULL}
404 };
405 typedef struct _type_field_t {
406   guint type_id;
407   gchar* type_name;
408   guint type_enable;
409 } type_field_t;
410 
411 static type_field_t* type_fields = NULL;
412 static guint num_type_fields = 0;
413 
414 typedef struct _assoc_info_t {
415   guint16 assoc_index;
416   guint16 direction;
417   gboolean vtag_reflected;
418   guint16 sport;
419   guint16 dport;
420   guint32 verification_tag1;
421   guint32 verification_tag2;
422   guint32 initiate_tag;
423 } assoc_info_t;
424 
425 typedef struct _infodata_t {
426   guint16 assoc_index;
427   guint16 direction;
428 } infodata_t;
429 
430 static wmem_list_t *assoc_info_list = NULL;
431 static guint num_assocs = 0;
432 
UAT_CSTRING_CB_DEF(type_fields,type_name,type_field_t)433 UAT_CSTRING_CB_DEF(type_fields, type_name, type_field_t)
434 UAT_VS_DEF(type_fields, type_enable, type_field_t, guint, 0, "Show")
435 UAT_DEC_CB_DEF(type_fields, type_id, type_field_t)
436 
437 static void *sctp_chunk_type_copy_cb(void* n, const void* o, size_t siz _U_)
438 {
439   type_field_t* new_rec = (type_field_t*)n;
440   const type_field_t* old_rec = (const type_field_t*)o;
441   new_rec->type_name = g_strdup(old_rec->type_name);
442 
443   return new_rec;
444 }
445 
446 static void
sctp_chunk_type_free_cb(void * r)447 sctp_chunk_type_free_cb(void* r)
448 {
449   type_field_t* rec = (type_field_t*)r;
450   g_free(rec->type_name);
451 }
452 
453 static gboolean
sctp_chunk_type_update_cb(void * r,char ** err)454 sctp_chunk_type_update_cb(void *r, char **err)
455 {
456   type_field_t *rec = (type_field_t *)r;
457   char c;
458   if (rec->type_name == NULL) {
459     *err = g_strdup("Header name can't be empty");
460     return FALSE;
461   }
462 
463   g_strstrip(rec->type_name);
464   if (rec->type_name[0] == 0) {
465     *err = g_strdup("Header name can't be empty");
466     return FALSE;
467   }
468 
469   /* Check for invalid characters (to avoid asserting out when
470   * registering the field).
471   */
472   c = proto_check_field_name(rec->type_name);
473   if (c) {
474     *err = g_strdup_printf("Header name can't contain '%c'", c);
475     return FALSE;
476   }
477 
478   *err = NULL;
479   return TRUE;
480 }
481 
482 static dissector_handle_t sctp_handle;
483 
484 static struct _sctp_info sctp_info;
485 
486 #define RETURN_DIRECTION(direction) \
487   do { \
488     /*ws_warning("Returning %d at %d: a-itag=0x%x, a-vtag1=0x%x, a-vtag2=0x%x, b-itag=0x%x, b-vtag1=0x%x, b-vtag2=0x%x", \
489               direction, __LINE__, a->initiate_tag, a->verification_tag1, a->verification_tag2, b->initiate_tag, b->verification_tag1, b->verification_tag2);*/ \
490     return direction; \
491   } while (0)
sctp_assoc_vtag_cmp(const assoc_info_t * a,const assoc_info_t * b)492 static gint sctp_assoc_vtag_cmp(const assoc_info_t *a, const assoc_info_t *b)
493 {
494   if (a == NULL || b == NULL)
495     RETURN_DIRECTION(ASSOC_NOT_FOUND);
496 
497   if ((a->sport == b->sport) &&
498       (a->dport == b->dport) &&
499       (b->verification_tag2 != 0) &&
500       (a->initiate_tag == b->verification_tag2) &&
501       (a->initiate_tag == b->initiate_tag))
502     RETURN_DIRECTION(FORWARD_STREAM);
503 
504   if ((a->sport == b->sport) &&
505       (a->dport == b->dport) &&
506       (a->verification_tag1 == b->verification_tag1) &&
507       (a->initiate_tag ==  b->initiate_tag))
508     RETURN_DIRECTION(FORWARD_STREAM);
509 
510   if ((a->sport == b->sport) &&
511       (a->dport == b->dport) &&
512       (a->verification_tag1 == b->verification_tag1) &&
513       (a->verification_tag1 == 0 && a->initiate_tag != 0) &&
514       (a->initiate_tag != b->initiate_tag ))
515     RETURN_DIRECTION(ASSOC_NOT_FOUND);   /* two INITs that belong to different assocs */
516 
517   /* assoc known*/
518   if ((a->sport == b->sport) &&
519       (a->dport == b->dport) &&
520       (a->verification_tag1 == b->verification_tag1) &&
521       ((a->verification_tag1 != 0 ||
522        (b->verification_tag2 != 0))))
523     RETURN_DIRECTION(FORWARD_STREAM);
524 
525   /* ABORT, vtag reflected */
526   if ((a->sport == b->sport) &&
527       (a->dport == b->dport) &&
528       (a->verification_tag2 == b->verification_tag2) &&
529       (a->verification_tag1 == 0 && b->verification_tag1 != 0))
530     RETURN_DIRECTION(FORWARD_STREAM);
531 
532   if ((a->sport == b->dport) &&
533       (a->dport == b->sport) &&
534       (a->verification_tag1 == b->verification_tag2) &&
535       (a->verification_tag1 != 0))
536     RETURN_DIRECTION(BACKWARD_STREAM);
537 
538   if ((a->sport == b->dport) &&
539       (a->dport == b->sport) &&
540       (a->verification_tag2 == b->verification_tag1) &&
541       (a->verification_tag2 != 0))
542     RETURN_DIRECTION(BACKWARD_STREAM);
543 
544   if ((a->sport == b->dport) &&
545       (a->dport == b->sport) &&
546       (a->verification_tag1 == b->initiate_tag) &&
547       (a->verification_tag2 == 0))
548     RETURN_DIRECTION(BACKWARD_ADD_BACKWARD_VTAG);
549 
550   /* ABORT, vtag reflected */
551   if ((a->sport == b->dport) &&
552       (a->dport == b->sport) &&
553       (a->verification_tag2 == b->verification_tag1) &&
554       (a->verification_tag1 == 0 && b->verification_tag2 != 0))
555     RETURN_DIRECTION(BACKWARD_STREAM);
556 
557   /*forward stream verification tag can be added*/
558   if ((a->sport == b->sport) &&
559       (a->dport == b->dport) &&
560       (a->verification_tag1 != 0) &&
561       (b->verification_tag1 == 0) &&
562       (b->verification_tag2 !=0))
563     RETURN_DIRECTION(FORWARD_ADD_FORWARD_VTAG);
564 
565   if ((a->sport == b->dport) &&
566       (a->dport == b->sport) &&
567       (a->verification_tag1 == b->verification_tag2) &&
568       (b->verification_tag1 == 0))
569     RETURN_DIRECTION(BACKWARD_ADD_FORWARD_VTAG);
570 
571   /*backward stream verification tag can be added */
572   if ((a->sport == b->dport) &&
573       (a->dport == b->sport) &&
574       (a->verification_tag1 != 0) &&
575       (b->verification_tag1 != 0) &&
576       (b->verification_tag2 == 0))
577     RETURN_DIRECTION(BACKWARD_ADD_BACKWARD_VTAG);
578 
579   RETURN_DIRECTION(ASSOC_NOT_FOUND);
580 }
581 #undef RETURN_DIRECTION
582 
583 static infodata_t
find_assoc_index(assoc_info_t * tmpinfo,gboolean visited)584 find_assoc_index(assoc_info_t* tmpinfo, gboolean visited)
585 {
586   assoc_info_t *info = NULL;
587   wmem_list_frame_t *elem;
588   gboolean cmp = FALSE;
589   infodata_t inf;
590   inf.assoc_index = -1;
591   inf.direction = 1;
592 
593   if (assoc_info_list == NULL) {
594     assoc_info_list = wmem_list_new(wmem_file_scope());
595   }
596 
597   for (elem = wmem_list_head(assoc_info_list); elem; elem = wmem_list_frame_next(elem))
598   {
599     info = (assoc_info_t*) wmem_list_frame_data(elem);
600 
601     if (!visited) {
602       cmp = sctp_assoc_vtag_cmp(tmpinfo, info);
603       if (cmp < ASSOC_NOT_FOUND) {
604         switch (cmp)
605         {
606           case FORWARD_ADD_FORWARD_VTAG:
607           case BACKWARD_ADD_FORWARD_VTAG:
608             info->verification_tag1 = tmpinfo->verification_tag1;
609             break;
610           case BACKWARD_ADD_BACKWARD_VTAG:
611             info->verification_tag2 = tmpinfo->verification_tag1;
612             info->direction = 1;
613             inf.assoc_index = info->assoc_index;
614             inf.direction = 2;
615             return inf;
616           case BACKWARD_STREAM:
617             inf.assoc_index = info->assoc_index;
618             inf.direction = 2;
619             return inf;
620         }
621         if (cmp == FORWARD_STREAM || cmp == FORWARD_ADD_FORWARD_VTAG) {
622           info->direction = 1;
623         } else {
624           info->direction = 2;
625         }
626         inf.assoc_index = info->assoc_index;
627         inf.direction = info->direction;
628         return inf;
629       }
630     } else {
631       if ((tmpinfo->initiate_tag != 0 && tmpinfo->initiate_tag == info->initiate_tag) ||
632           (tmpinfo->verification_tag1 != 0 && tmpinfo->verification_tag1 == info->verification_tag1) ||
633           (tmpinfo->verification_tag2 != 0 && tmpinfo->verification_tag2 == info->verification_tag2)) {
634         inf.assoc_index = info->assoc_index;
635         inf.direction = info->direction;
636         return inf;
637       } else if ((tmpinfo->verification_tag1 != 0 && tmpinfo->verification_tag1 == info->verification_tag2) ||
638                  (tmpinfo->verification_tag2 != 0 && tmpinfo->verification_tag2 == info->verification_tag1) ||
639                  (tmpinfo->verification_tag1 == 0 && tmpinfo->initiate_tag != 0 &&
640                  tmpinfo->initiate_tag == info->verification_tag1)) {
641         inf.assoc_index = info->assoc_index;
642         if (info->direction == 1)
643           inf.direction = 2;
644         else
645           inf.direction = 1;
646         return inf;
647       }
648     }
649   }
650 
651   if (!elem && !visited) {
652     info = wmem_new0(wmem_file_scope(), assoc_info_t);
653     info->assoc_index = num_assocs;
654     info->sport = tmpinfo->sport;
655     info->dport = tmpinfo->dport;
656     info->verification_tag1 = tmpinfo->verification_tag1;
657     info->verification_tag2 = tmpinfo->verification_tag2;
658     info->initiate_tag = tmpinfo->initiate_tag;
659     num_assocs++;
660     wmem_list_prepend(assoc_info_list, info);
661     inf.assoc_index = info->assoc_index;
662     inf.direction = 1;
663   }
664 
665   return inf;
666 }
667 
668 static void
sctp_src_prompt(packet_info * pinfo,gchar * result)669 sctp_src_prompt(packet_info *pinfo, gchar *result)
670 {
671     guint32 port = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_source_port, pinfo->curr_layer_num));
672 
673     g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "source (%s%u)", UTF8_RIGHTWARDS_ARROW, port);
674 }
675 
676 static gpointer
sctp_src_value(packet_info * pinfo)677 sctp_src_value(packet_info *pinfo)
678 {
679     return p_get_proto_data(pinfo->pool, pinfo, hf_source_port, pinfo->curr_layer_num);
680 }
681 
682 static void
sctp_dst_prompt(packet_info * pinfo,gchar * result)683 sctp_dst_prompt(packet_info *pinfo, gchar *result)
684 {
685     guint32 port = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_destination_port, pinfo->curr_layer_num));
686 
687     g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "destination (%s%u)", UTF8_RIGHTWARDS_ARROW, port);
688 }
689 
690 static gpointer
sctp_dst_value(packet_info * pinfo)691 sctp_dst_value(packet_info *pinfo)
692 {
693     return p_get_proto_data(pinfo->pool, pinfo, hf_destination_port, pinfo->curr_layer_num);
694 }
695 
696 static void
sctp_both_prompt(packet_info * pinfo,gchar * result)697 sctp_both_prompt(packet_info *pinfo, gchar *result)
698 {
699     guint32 srcport = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_source_port, pinfo->curr_layer_num)),
700             destport = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_destination_port, pinfo->curr_layer_num));
701 
702     g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "both (%u%s%u)", srcport, UTF8_LEFT_RIGHT_ARROW, destport);
703 }
704 
705 static void
sctp_ppi_prompt1(packet_info * pinfo _U_,gchar * result)706 sctp_ppi_prompt1(packet_info *pinfo _U_, gchar* result)
707 {
708     guint32 ppid = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_sctp, 0));
709 
710     if (ppid == LAST_PPID) {
711         g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "PPID (none)");
712     } else {
713         g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "PPID (%d)", ppid);
714     }
715 }
716 
717 static void
sctp_ppi_prompt2(packet_info * pinfo _U_,gchar * result)718 sctp_ppi_prompt2(packet_info *pinfo _U_, gchar* result)
719 {
720     guint32 ppid = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_sctp, 1));
721 
722     if (ppid == LAST_PPID) {
723         g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "PPID (none)");
724     } else {
725         g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "PPID (%d)", ppid);
726     }
727 }
728 
729 static gpointer
sctp_ppi_value1(packet_info * pinfo)730 sctp_ppi_value1(packet_info *pinfo)
731 {
732     return p_get_proto_data(pinfo->pool, pinfo, proto_sctp, 0);
733 }
734 
735 static gpointer
sctp_ppi_value2(packet_info * pinfo)736 sctp_ppi_value2(packet_info *pinfo)
737 {
738     return p_get_proto_data(pinfo->pool, pinfo, proto_sctp, 1);
739 }
740 
sctp_conv_get_filter_type(conv_item_t * conv,conv_filter_type_e filter)741 static const char* sctp_conv_get_filter_type(conv_item_t* conv, conv_filter_type_e filter)
742 {
743     if (filter == CONV_FT_SRC_PORT)
744         return "sctp.srcport";
745 
746     if (filter == CONV_FT_DST_PORT)
747         return "sctp.dstport";
748 
749     if (filter == CONV_FT_ANY_PORT)
750         return "sctp.port";
751 
752     if(!conv) {
753         return CONV_FILTER_INVALID;
754     }
755 
756     if (filter == CONV_FT_SRC_ADDRESS) {
757         if (conv->src_address.type == AT_IPv4)
758             return "ip.src";
759         if (conv->src_address.type == AT_IPv6)
760             return "ipv6.src";
761     }
762 
763     if (filter == CONV_FT_DST_ADDRESS) {
764         if (conv->dst_address.type == AT_IPv4)
765             return "ip.dst";
766         if (conv->dst_address.type == AT_IPv6)
767             return "ipv6.dst";
768     }
769 
770     if (filter == CONV_FT_ANY_ADDRESS) {
771         if (conv->src_address.type == AT_IPv4)
772             return "ip.addr";
773         if (conv->src_address.type == AT_IPv6)
774             return "ipv6.addr";
775     }
776 
777     return CONV_FILTER_INVALID;
778 }
779 
780 static ct_dissector_info_t sctp_ct_dissector_info = {&sctp_conv_get_filter_type};
781 
782 static tap_packet_status
sctp_conversation_packet(void * pct,packet_info * pinfo,epan_dissect_t * edt _U_,const void * vip)783 sctp_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip)
784 {
785   conv_hash_t *hash = (conv_hash_t*) pct;
786   const struct _sctp_info *sctphdr=(const struct _sctp_info *)vip;
787 
788   add_conversation_table_data(hash, &sctphdr->ip_src, &sctphdr->ip_dst,
789         sctphdr->sport, sctphdr->dport, 1, pinfo->fd->pkt_len, &pinfo->rel_ts, &pinfo->abs_ts, &sctp_ct_dissector_info, ENDPOINT_SCTP);
790 
791 
792   return TAP_PACKET_REDRAW;
793 }
794 
sctp_host_get_filter_type(hostlist_talker_t * host,conv_filter_type_e filter)795 static const char* sctp_host_get_filter_type(hostlist_talker_t* host, conv_filter_type_e filter)
796 {
797     if (filter == CONV_FT_SRC_PORT)
798         return "sctp.srcport";
799 
800     if (filter == CONV_FT_DST_PORT)
801         return "sctp.dstport";
802 
803     if (filter == CONV_FT_ANY_PORT)
804         return "sctp.port";
805 
806     if(!host) {
807         return CONV_FILTER_INVALID;
808     }
809 
810     if (filter == CONV_FT_SRC_ADDRESS) {
811         if (host->myaddress.type == AT_IPv4)
812             return "ip.src";
813         if (host->myaddress.type == AT_IPv6)
814             return "ipv6.src";
815     }
816 
817     if (filter == CONV_FT_DST_ADDRESS) {
818         if (host->myaddress.type == AT_IPv4)
819             return "ip.dst";
820         if (host->myaddress.type == AT_IPv6)
821             return "ipv6.dst";
822     }
823 
824     if (filter == CONV_FT_ANY_ADDRESS) {
825         if (host->myaddress.type == AT_IPv4)
826             return "ip.addr";
827         if (host->myaddress.type == AT_IPv6)
828             return "ipv6.addr";
829     }
830 
831     return CONV_FILTER_INVALID;
832 }
833 
834 static hostlist_dissector_info_t sctp_host_dissector_info = {&sctp_host_get_filter_type};
835 
836 static tap_packet_status
sctp_hostlist_packet(void * pit,packet_info * pinfo,epan_dissect_t * edt _U_,const void * vip)837 sctp_hostlist_packet(void *pit, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip)
838 {
839   conv_hash_t *hash = (conv_hash_t*) pit;
840   const struct _sctp_info *sctphdr=(const struct _sctp_info *)vip;
841 
842   /* Take two "add" passes per packet, adding for each direction, ensures that all
843   packets are counted properly (even if address is sending to itself)
844   XXX - this could probably be done more efficiently inside hostlist_table */
845   add_hostlist_table_data(hash, &sctphdr->ip_src, sctphdr->sport, TRUE, 1, pinfo->fd->pkt_len, &sctp_host_dissector_info, ENDPOINT_SCTP);
846   add_hostlist_table_data(hash, &sctphdr->ip_dst, sctphdr->dport, FALSE, 1, pinfo->fd->pkt_len, &sctp_host_dissector_info, ENDPOINT_SCTP);
847 
848   return TAP_PACKET_REDRAW;
849 }
850 
851 static unsigned int
sctp_adler32(tvbuff_t * tvb,unsigned int len)852 sctp_adler32(tvbuff_t *tvb, unsigned int len)
853 {
854   const guint8 *buf = tvb_get_ptr(tvb, 0, len);
855   guint32 result = 1;
856 
857   result = update_adler32(result, buf, SOURCE_PORT_LENGTH + DESTINATION_PORT_LENGTH + VERIFICATION_TAG_LENGTH);
858   /* handle four 0 bytes as checksum */
859   result = update_adler32(result, "\0\0\0\0", 4);
860   result = update_adler32(result, buf+COMMON_HEADER_LENGTH, len-COMMON_HEADER_LENGTH);
861 
862   return result;
863 }
864 
865 static guint32
sctp_crc32c(tvbuff_t * tvb,unsigned int len)866 sctp_crc32c(tvbuff_t *tvb, unsigned int len)
867 {
868   const guint8 *buf = tvb_get_ptr(tvb, 0, len);
869   guint32 crc32,
870           zero = 0;
871   guint32 result;
872 
873   /* CRC for header */
874   crc32 = crc32c_calculate_no_swap(buf, SOURCE_PORT_LENGTH + DESTINATION_PORT_LENGTH + VERIFICATION_TAG_LENGTH, CRC32C_PRELOAD);
875 
876   /* handle four 0 bytes as checksum */
877   crc32 = crc32c_calculate_no_swap(&zero, 4, crc32);
878 
879   /* CRC for the rest of the packet */
880   crc32 = crc32c_calculate_no_swap(&buf[COMMON_HEADER_LENGTH], len-COMMON_HEADER_LENGTH, crc32);
881 
882   result = CRC32C_SWAP(crc32);
883 
884   return ( ~result );
885 }
886 
887 /*
888  * Routines for dissecting parameters
889  */
890 
891 typedef struct _sctp_half_assoc_t sctp_half_assoc_t;
892 
893 static void dissect_parameter(tvbuff_t *, packet_info *, proto_tree *, proto_item *, gboolean, gboolean);
894 
895 static void dissect_parameters(tvbuff_t *, packet_info *, proto_tree *, proto_item *, gboolean);
896 
897 static void dissect_error_cause(tvbuff_t *, packet_info *, proto_tree *);
898 
899 static void dissect_error_causes(tvbuff_t *, packet_info *, proto_tree *);
900 
901 static gboolean dissect_data_chunk(tvbuff_t*, guint16, packet_info*, proto_tree*, proto_tree*, proto_item*, proto_item*, sctp_half_assoc_t*, gboolean);
902 
903 static void dissect_sctp_packet(tvbuff_t *, packet_info *, proto_tree *, gboolean);
904 
905 
906 /* TSN ANALYSIS CODE */
907 
908 struct _sctp_half_assoc_t {
909   guint32 spt;
910   guint32 dpt;
911   guint32 vtag;
912 
913   gboolean started;
914 
915   guint32 first_tsn; /* start */
916   guint32 cumm_ack; /* rel */
917   wmem_tree_t *tsns; /* sctp_tsn_t* by rel_tsn */
918   wmem_tree_t *tsn_acks; /* sctp_tsn_t* by ctsn_frame */
919 
920   struct _sctp_half_assoc_t *peer;
921 };
922 
923 
924 typedef struct _retransmit_t {
925   guint32 framenum;
926   nstime_t ts;
927   struct _retransmit_t *next;
928 } retransmit_t;
929 
930 typedef struct _sctp_tsn_t {
931   guint32 tsn;
932   struct {
933     guint32 framenum;
934     nstime_t ts;
935   } first_transmit;
936   struct {
937     guint32 framenum;
938     nstime_t ts;
939   } ack;
940   retransmit_t *retransmit;
941   guint32 retransmit_count;
942   struct _sctp_tsn_t *next;
943 } sctp_tsn_t;
944 
945 
946 static wmem_tree_key_t*
make_address_key(wmem_allocator_t * pool,guint32 spt,guint32 dpt,address * addr)947 make_address_key(wmem_allocator_t *pool, guint32 spt, guint32 dpt, address *addr)
948 {
949   wmem_tree_key_t *k = (wmem_tree_key_t *)wmem_alloc(pool, sizeof(wmem_tree_key_t)*6);
950 
951   k[0].length = 1;    k[0].key = (guint32*)wmem_memdup(pool, &spt,sizeof(spt));
952   k[1].length = 1;    k[1].key = (guint32*)wmem_memdup(pool, &dpt,sizeof(dpt));
953   k[2].length = 1;    k[2].key = (guint32*)(void *)&(addr->type);
954   k[3].length = 1;    k[3].key = (guint32*)(void *)&(addr->len);
955 
956   k[4].length = ((addr->len/4)+1);
957   k[4].key = (guint32*)wmem_alloc0(pool, ((addr->len/4)+1)*4);
958   if (addr->len) memcpy(k[4].key, addr->data, addr->len);
959 
960   k[5].length = 0;    k[5].key = NULL;
961 
962   return k;
963 }
964 
965 static wmem_tree_key_t *
make_dir_key(wmem_allocator_t * pool,guint32 spt,guint32 dpt,guint32 vtag)966 make_dir_key(wmem_allocator_t *pool, guint32 spt, guint32 dpt, guint32 vtag)
967 {
968   wmem_tree_key_t *k =  (wmem_tree_key_t *)wmem_alloc(pool, sizeof(wmem_tree_key_t)*4);
969 
970   k[0].length = 1;    k[0].key = (guint32*)wmem_memdup(pool, &spt,sizeof(spt));
971   k[1].length = 1;    k[1].key = (guint32*)wmem_memdup(pool, &dpt,sizeof(dpt));
972   k[2].length = 1;    k[2].key = (guint32*)wmem_memdup(pool, &vtag,sizeof(vtag));
973   k[3].length = 0;    k[3].key = NULL;
974 
975   return k;
976 }
977 
978 
979 
980 static wmem_tree_t *dirs_by_ptvtag; /* sctp_half_assoc_t*  */
981 static wmem_tree_t *dirs_by_ptaddr; /* sctp_half_assoc_t**, it may contain a null pointer */
982 
983 static sctp_half_assoc_t *
get_half_assoc(packet_info * pinfo,guint32 spt,guint32 dpt,guint32 vtag)984 get_half_assoc(packet_info *pinfo, guint32 spt, guint32 dpt, guint32 vtag)
985 {
986   sctp_half_assoc_t *ha;
987   sctp_half_assoc_t **hb;
988   wmem_tree_key_t *k;
989 
990   if (!enable_tsn_analysis || !vtag || pinfo->flags.in_error_pkt)
991     return NULL;
992 
993   /* look for the current half_assoc by spt, dpt and vtag */
994 
995   k = make_dir_key(pinfo->pool, spt, dpt, vtag);
996   if (( ha = (sctp_half_assoc_t *)wmem_tree_lookup32_array(dirs_by_ptvtag, k)  )) {
997     /* found, if it has been already matched we're done */
998     if (ha->peer) return ha;
999   } else {
1000     /* not found, make a new one and add it to the table */
1001     ha = wmem_new0(wmem_file_scope(), sctp_half_assoc_t);
1002     ha->spt = spt;
1003     ha->dpt = dpt;
1004     ha->vtag = vtag;
1005     ha->tsns = wmem_tree_new(wmem_file_scope());
1006     ha->tsn_acks = wmem_tree_new(wmem_file_scope());
1007     ha->started = FALSE;
1008     ha->first_tsn= 0;
1009     ha->cumm_ack= 0;
1010 
1011     /* add this half to the table indexed by ports and vtag */
1012     wmem_tree_insert32_array(dirs_by_ptvtag, k, ha);
1013   }
1014 
1015   /* at this point we have an unmatched half, look for its other half using the ports and IP address */
1016   k = make_address_key(pinfo->pool, dpt, spt, &(pinfo->dst));
1017 
1018   if (( hb = (sctp_half_assoc_t **)wmem_tree_lookup32_array(dirs_by_ptaddr, k) )) {
1019     /*the table contains a pointer to a pointer to a half */
1020     if (! *hb) {
1021       /* if there is no half pointed by this, add the current half to the table */
1022       *hb = ha;
1023     } else {
1024       /* there's a half pointed by this, assume it's our peer and clear the table's pointer */
1025       ha->peer = *hb;
1026       (*hb)->peer = ha;
1027       *hb = NULL;
1028     }
1029   } else {
1030     /* we found no entry in the table: add one (using reversed ports and src addresss) so that it can be matched later */
1031     *(hb = (sctp_half_assoc_t **)wmem_alloc(wmem_file_scope(), sizeof(void*))) = ha;
1032     k = make_address_key(pinfo->pool, spt, dpt, &(pinfo->src));
1033     wmem_tree_insert32_array(dirs_by_ptaddr, k, hb);
1034   }
1035 
1036   return ha;
1037 }
1038 
1039 /*  Limit the number of retransmissions we track (to limit memory usage--and
1040  *  tree size--in pathological cases, for example zero window probing forever).
1041  */
1042 #define MAX_RETRANS_TRACKED_PER_TSN 100
1043 
1044 static void
tsn_tree(sctp_tsn_t * t,proto_item * tsn_item,packet_info * pinfo,tvbuff_t * tvb,guint32 framenum)1045 tsn_tree(sctp_tsn_t *t, proto_item *tsn_item, packet_info *pinfo,
1046          tvbuff_t *tvb, guint32 framenum)
1047 {
1048   proto_item *pi;
1049   proto_tree *pt;
1050   proto_tree *tsn_tree_pt = proto_item_add_subtree(tsn_item, ett_sctp_tsn);
1051 
1052   if (t->first_transmit.framenum != framenum) {
1053     nstime_t rto;
1054 
1055     pi = proto_tree_add_uint(tsn_tree_pt, hf_sctp_retransmission, tvb, 0, 0, t->first_transmit.framenum);
1056     pt = proto_item_add_subtree(pi, ett_sctp_tsn_retransmission);
1057     proto_item_set_generated(pi);
1058     expert_add_info(pinfo, pi, &ei_sctp_tsn_retransmitted);
1059 
1060     nstime_delta( &rto, &pinfo->abs_ts, &(t->first_transmit.ts) );
1061     pi = proto_tree_add_time(pt, hf_sctp_rto, tvb, 0, 0, &rto);
1062     proto_item_set_generated(pi);
1063 
1064     /* Detect reneged acks */
1065     /* XXX what if the frames aren't sorted by time? */
1066     if (t->ack.framenum && t->ack.framenum < framenum)
1067     {
1068       pi = proto_tree_add_uint_format(pt, hf_sctp_retransmitted_after_ack, tvb, 0, 0, t->ack.framenum,
1069                                       "This TSN was acked (in frame %u) prior to this retransmission (reneged ack?)",
1070                                       t->ack.framenum);
1071       proto_item_set_generated(pi);
1072       expert_add_info(pinfo, pi, &ei_sctp_retransmitted_after_ack);
1073     }
1074   } else if (t->retransmit) {
1075     retransmit_t **r;
1076     nstime_t rto;
1077     char ds[64];
1078 
1079     if (t->retransmit_count > MAX_RETRANS_TRACKED_PER_TSN)
1080       g_snprintf(ds, sizeof(ds), " (only %d displayed)", MAX_RETRANS_TRACKED_PER_TSN);
1081     else
1082       ds[0] = 0;
1083 
1084     pi = proto_tree_add_uint_format(tsn_tree_pt,
1085                                     hf_sctp_retransmitted_count,
1086                                     tvb, 0, 0, t->retransmit_count,
1087                                     "This TSN was retransmitted %u time%s%s",
1088                                     t->retransmit_count,
1089                                     plurality(t->retransmit_count, "", "s"),
1090                                     ds);
1091     proto_item_set_generated(pi);
1092 
1093     if (t->retransmit_count > 2)
1094       expert_add_info(pinfo, pi, &ei_sctp_tsn_retransmitted_more_than_twice);
1095 
1096     pt = proto_item_add_subtree(pi, ett_sctp_tsn_retransmitted_count);
1097 
1098     r = &t->retransmit;
1099     while (*r) {
1100       nstime_delta(&rto, &((*r)->ts), &pinfo->abs_ts);
1101       pi = proto_tree_add_uint_format(pt,
1102                                       hf_sctp_retransmitted,
1103                                       tvb, 0, 0,
1104                                       (*r)->framenum,
1105                                       "This TSN was retransmitted in frame %u (%s seconds after this frame)",
1106                                       (*r)->framenum,
1107                                       rel_time_to_secs_str(pinfo->pool, &rto));
1108       proto_item_set_generated(pi);
1109       r = &(*r)->next;
1110     }
1111   }
1112 
1113   if (t->ack.framenum) {
1114     nstime_t rtt;
1115 
1116     pi = proto_tree_add_uint(tsn_tree_pt, hf_sctp_acked, tvb, 0 , 0, t->ack.framenum);
1117     proto_item_set_generated(pi);
1118     pt = proto_item_add_subtree(pi, ett_sctp_ack);
1119 
1120     nstime_delta( &rtt, &(t->ack.ts), &(t->first_transmit.ts) );
1121     pi = proto_tree_add_time(pt, hf_sctp_data_rtt, tvb, 0, 0, &rtt);
1122     proto_item_set_generated(pi);
1123   }
1124 }
1125 
1126 #define RELTSN(tsn) (((tsn) < h->first_tsn) ? (tsn + (0xffffffff - (h->first_tsn)) + 1) : (tsn - h->first_tsn))
1127 
1128 /* Returns TRUE if the tsn is a retransmission (we've seen it before), FALSE
1129  * otherwise.
1130  */
1131 static gboolean
sctp_tsn(packet_info * pinfo,tvbuff_t * tvb,proto_item * tsn_item,sctp_half_assoc_t * h,guint32 tsn)1132 sctp_tsn(packet_info *pinfo,  tvbuff_t *tvb, proto_item *tsn_item,
1133          sctp_half_assoc_t *h, guint32 tsn)
1134 {
1135   sctp_tsn_t *t;
1136   guint32 framenum;
1137   guint32 reltsn;
1138   gboolean is_retransmission = FALSE;
1139 
1140   /* no half assoc? nothing to do!*/
1141   if (!h)
1142     return(is_retransmission);
1143 
1144 
1145   framenum = pinfo->num;
1146 
1147   /*  If we're dissecting for a read filter in the GUI [tshark assigns
1148    *  frame numbers before running the read filter], don't do the TSN
1149    *  analysis.  (We can't anyway because we don't have a valid frame
1150    *  number...)
1151    *
1152    *  Without this check if you load a capture file in the
1153    *  GUI while using a read filter, every SCTP TSN is marked as a
1154    *  retransmission of that in frame 0.
1155    */
1156   if (framenum == 0)
1157     return(is_retransmission);
1158 
1159   /* we have not seen any tsn yet in this half assoc set the ground */
1160   if (! h->started) {
1161     h->first_tsn = tsn;
1162     h->started = TRUE;
1163   }
1164 
1165 
1166   reltsn = RELTSN(tsn);
1167 
1168   /* printf("%.3d REL TSN: %p->%p [%u] %u \n",framenum,h,h->peer,tsn,reltsn); */
1169 
1170   /* look for this tsn in this half's tsn table */
1171   if (! (t = (sctp_tsn_t *)wmem_tree_lookup32(h->tsns,reltsn) )) {
1172     /* no tsn found, create a new one */
1173     t = wmem_new0(wmem_file_scope(), sctp_tsn_t);
1174     t->tsn = tsn;
1175 
1176     t->first_transmit.framenum = framenum;
1177     t->first_transmit.ts = pinfo->abs_ts;
1178 
1179     wmem_tree_insert32(h->tsns,reltsn,t);
1180   }
1181 
1182   is_retransmission = (t->first_transmit.framenum != framenum);
1183 
1184   if ( (! pinfo->fd->visited ) && is_retransmission ) {
1185     retransmit_t **r;
1186     int i;
1187 
1188     t->retransmit_count++;
1189     r = &t->retransmit;
1190     i = 0;
1191     while (*r && i < MAX_RETRANS_TRACKED_PER_TSN) {
1192       r = &(*r)->next;
1193       i++;
1194     }
1195 
1196     if (i <= MAX_RETRANS_TRACKED_PER_TSN) {
1197       *r = wmem_new0(wmem_file_scope(), retransmit_t);
1198       (*r)->framenum = framenum;
1199       (*r)->ts = pinfo->abs_ts;
1200     }
1201   }
1202 
1203   tsn_tree(t, tsn_item, pinfo, tvb, framenum);
1204 
1205   return(is_retransmission);
1206 }
1207 
1208 static void
ack_tree(sctp_tsn_t * t,proto_tree * acks_tree,tvbuff_t * tvb,packet_info * pinfo)1209 ack_tree(sctp_tsn_t *t, proto_tree *acks_tree,
1210          tvbuff_t *tvb, packet_info *pinfo)
1211 {
1212   proto_item *pi;
1213   proto_tree *pt;
1214   nstime_t rtt;
1215   guint framenum =  pinfo->num;
1216 
1217   if ( t->ack.framenum == framenum ) {
1218     nstime_delta( &rtt, &(t->ack.ts), &(t->first_transmit.ts) );
1219 
1220     pi = proto_tree_add_uint(acks_tree, hf_sctp_ack_tsn, tvb, 0 , 0, t->tsn);
1221     proto_item_set_generated(pi);
1222 
1223     pt = proto_item_add_subtree(pi, ett_sctp_acked);
1224 
1225     pi = proto_tree_add_uint(pt, hf_sctp_ack_frame, tvb, 0 , 0, t->first_transmit.framenum);
1226     proto_item_set_generated(pi);
1227 
1228     pi = proto_tree_add_time(pt, hf_sctp_sack_rtt, tvb, 0, 0, &rtt);
1229     proto_item_set_generated(pi);
1230   }
1231 }
1232 
1233 static void
sctp_ack(packet_info * pinfo,tvbuff_t * tvb,proto_tree * acks_tree,sctp_half_assoc_t * h,guint32 reltsn)1234 sctp_ack(packet_info *pinfo, tvbuff_t *tvb,  proto_tree *acks_tree,
1235          sctp_half_assoc_t *h, guint32 reltsn)
1236 {
1237   sctp_tsn_t *t;
1238   guint32 framenum;
1239 
1240 
1241   if (!h || !h->peer)
1242     return;
1243 
1244   framenum = pinfo->num;
1245 
1246   /* printf("%.6d ACK: %p->%p [%u] \n",framenum,h,h->peer,reltsn); */
1247 
1248   t = (sctp_tsn_t *)wmem_tree_lookup32(h->peer->tsns,reltsn);
1249 
1250   if (t) {
1251     if (! t->ack.framenum) {
1252       sctp_tsn_t *t2;
1253 
1254       t->ack.framenum = framenum;
1255       t->ack.ts = pinfo->abs_ts;
1256 
1257       if (( t2 = (sctp_tsn_t *)wmem_tree_lookup32(h->peer->tsn_acks, framenum) )) {
1258         for(;t2->next;t2 = t2->next)
1259           ;
1260 
1261         t2->next = t;
1262       } else {
1263         wmem_tree_insert32(h->peer->tsn_acks, framenum,t);
1264       }
1265     }
1266 
1267     if ( t->ack.framenum == framenum)
1268       ack_tree(t, acks_tree, tvb, pinfo);
1269 
1270   } /* else {
1271        proto_tree_add_debug_text(acks_tree, tvb, 0 , 0, "Assoc: %p vs %p ?? %ld",h,h->peer,tsn);
1272        } */
1273 }
1274 
1275 #define RELTSNACK(tsn) (((tsn) < h->peer->first_tsn) ? ((tsn) + (0xffffffff - (h->peer->first_tsn)) + 1) : ((tsn) - h->peer->first_tsn))
1276 static void
sctp_ack_block(packet_info * pinfo,sctp_half_assoc_t * h,tvbuff_t * tvb,proto_item * acks_tree,const guint32 * tsn_start_ptr,guint32 tsn_end)1277 sctp_ack_block(packet_info *pinfo, sctp_half_assoc_t *h, tvbuff_t *tvb,
1278                proto_item *acks_tree, const guint32 *tsn_start_ptr,
1279                guint32 tsn_end)
1280 {
1281   sctp_tsn_t *t;
1282   guint32 framenum;
1283   guint32 rel_start;
1284   guint32 rel_end;
1285 
1286 
1287   if ( !h || !h->peer || ! h->peer->started )
1288     return;
1289 
1290   framenum =  pinfo->num;
1291   rel_end = RELTSNACK(tsn_end);
1292 
1293   if (tsn_start_ptr) {
1294     rel_start = RELTSNACK(*tsn_start_ptr);
1295     /* printf("%.3d BACK: %p->%p [%u-%u]\n",framenum,h,h->peer,rel_start,rel_end); */
1296   }  else {
1297     rel_start = h->peer->cumm_ack;
1298     /* printf("%.3d CACK: %p->%p  [%u-%u]\n",framenum,h,h->peer,rel_start,rel_end); */
1299   }
1300 
1301 
1302   if ((t = (sctp_tsn_t *)wmem_tree_lookup32(h->peer->tsn_acks, framenum))) {
1303     for(;t;t = t->next) {
1304       guint32 tsn = t->tsn;
1305 
1306       tsn -= h->peer->first_tsn;
1307 
1308       if (t->ack.framenum == framenum && ( (!tsn_start_ptr) || rel_start <= tsn) && tsn <= rel_end)
1309         ack_tree(t, acks_tree, tvb, pinfo);
1310     }
1311 
1312     return;
1313   }
1314 
1315   if (PINFO_FD_VISITED(pinfo) || rel_end < rel_start || rel_end - rel_start > 0xffff0000 ) return;
1316 
1317   if (! tsn_start_ptr )
1318     h->peer->cumm_ack = rel_end + 1;
1319 
1320   if (rel_start <= rel_end && rel_end - rel_start < 5000 ) {
1321     guint32 rel_tsn, i;
1322     for (i=0; i <= rel_end-rel_start; i++) {
1323       rel_tsn = (guint32) (i+rel_start);
1324       sctp_ack(pinfo, tvb,  acks_tree, h, rel_tsn);
1325     }
1326   }
1327 }
1328 
1329 /* END TSN ANALYSIS CODE */
1330 
1331 
1332 
1333 
1334 #define HEARTBEAT_INFO_PARAMETER_INFO_OFFSET PARAMETER_VALUE_OFFSET
1335 
1336 static void
dissect_heartbeat_info_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)1337 dissect_heartbeat_info_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1338 {
1339   guint16 heartbeat_info_length;
1340 
1341   heartbeat_info_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1342   if (heartbeat_info_length > 0)
1343     proto_tree_add_item(parameter_tree, hf_heartbeat_info, parameter_tvb, HEARTBEAT_INFO_PARAMETER_INFO_OFFSET, heartbeat_info_length, ENC_NA);
1344   proto_item_append_text(parameter_item, " (Information: %u byte%s)", heartbeat_info_length, plurality(heartbeat_info_length, "", "s"));
1345 }
1346 
1347 #define IPV4_ADDRESS_LENGTH 4
1348 #define IPV4_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
1349 
1350 static void
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)1351 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)
1352 {
1353   if (parameter_tree) {
1354     proto_tree_add_item(parameter_tree, hf_ipv4_address, parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH, ENC_BIG_ENDIAN);
1355     proto_item_append_text(parameter_item, " (Address: %s)", tvb_ip_to_str(wmem_packet_scope(), parameter_tvb, IPV4_ADDRESS_OFFSET));
1356     if (additional_item)
1357         proto_item_append_text(additional_item, "%s", tvb_ip_to_str(wmem_packet_scope(), parameter_tvb, IPV4_ADDRESS_OFFSET));
1358   }
1359   if (dissecting_init_init_ack_chunk) {
1360     if (sctp_info.number_of_tvbs < MAXIMUM_NUMBER_OF_TVBS)
1361       sctp_info.tvb[sctp_info.number_of_tvbs++] = parameter_tvb;
1362     else
1363       sctp_info.incomplete = TRUE;
1364   }
1365 }
1366 
1367 #define IPV6_ADDRESS_LENGTH 16
1368 #define IPV6_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
1369 
1370 static void
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)1371 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)
1372 {
1373   if (parameter_tree) {
1374     proto_tree_add_item(parameter_tree, hf_ipv6_address, parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH, ENC_NA);
1375     proto_item_append_text(parameter_item, " (Address: %s)", tvb_ip6_to_str(wmem_packet_scope(), parameter_tvb, IPV6_ADDRESS_OFFSET));
1376     if (additional_item)
1377       proto_item_append_text(additional_item, "%s", tvb_ip6_to_str(wmem_packet_scope(), parameter_tvb, IPV6_ADDRESS_OFFSET));
1378   }
1379   if (dissecting_init_init_ack_chunk) {
1380     if (sctp_info.number_of_tvbs < MAXIMUM_NUMBER_OF_TVBS)
1381       sctp_info.tvb[sctp_info.number_of_tvbs++] = parameter_tvb;
1382     else
1383       sctp_info.incomplete = TRUE;
1384   }
1385 }
1386 
1387 #define STATE_COOKIE_PARAMETER_COOKIE_OFFSET   PARAMETER_VALUE_OFFSET
1388 
1389 static void
dissect_state_cookie_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)1390 dissect_state_cookie_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1391 {
1392   guint16 state_cookie_length;
1393 
1394   state_cookie_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1395   if (state_cookie_length > 0)
1396     proto_tree_add_item(parameter_tree, hf_state_cookie, parameter_tvb, STATE_COOKIE_PARAMETER_COOKIE_OFFSET, state_cookie_length, ENC_NA);
1397   proto_item_append_text(parameter_item, " (Cookie length: %u byte%s)", state_cookie_length, plurality(state_cookie_length, "", "s"));
1398 }
1399 
1400 static void
dissect_unrecognized_parameters_parameter(tvbuff_t * parameter_tvb,packet_info * pinfo,proto_tree * parameter_tree)1401 dissect_unrecognized_parameters_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
1402 {
1403   /* FIXME: Does it contain one or more parameters? */
1404   dissect_parameter(tvb_new_subset_remaining(parameter_tvb, PARAMETER_VALUE_OFFSET), pinfo, parameter_tree, NULL, FALSE, FALSE);
1405 }
1406 
1407 #define COOKIE_PRESERVATIVE_PARAMETER_INCR_LENGTH 4
1408 #define COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET PARAMETER_VALUE_OFFSET
1409 
1410 static void
dissect_cookie_preservative_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)1411 dissect_cookie_preservative_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1412 {
1413   proto_tree_add_item(parameter_tree, hf_cookie_preservative_increment, parameter_tvb, COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET, COOKIE_PRESERVATIVE_PARAMETER_INCR_LENGTH, ENC_BIG_ENDIAN);
1414   proto_item_append_text(parameter_item, " (Increment :%u msec)", tvb_get_ntohl(parameter_tvb, COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET));
1415 }
1416 
1417 #define HOSTNAME_OFFSET PARAMETER_VALUE_OFFSET
1418 
1419 static void
dissect_hostname_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)1420 dissect_hostname_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1421 {
1422   guint16 hostname_length;
1423 
1424   hostname_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1425   proto_tree_add_item(parameter_tree, hf_hostname, parameter_tvb, HOSTNAME_OFFSET, hostname_length, ENC_ASCII|ENC_NA);
1426   proto_item_append_text(parameter_item, " (Hostname: %.*s)", hostname_length, tvb_format_text(wmem_packet_scope(), parameter_tvb, HOSTNAME_OFFSET, hostname_length));
1427 
1428 }
1429 
1430 #define IPv4_ADDRESS_TYPE      5
1431 #define IPv6_ADDRESS_TYPE      6
1432 #define HOSTNAME_ADDRESS_TYPE 11
1433 
1434 static const value_string address_types_values[] = {
1435   {  IPv4_ADDRESS_TYPE,    "IPv4 address"     },
1436   {  IPv6_ADDRESS_TYPE,    "IPv6 address"     },
1437   { HOSTNAME_ADDRESS_TYPE, "Hostname address" },
1438   {  0, NULL               }
1439 };
1440 
1441 #define SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH 2
1442 
1443 static void
dissect_supported_address_types_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)1444 dissect_supported_address_types_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1445 {
1446   guint16 addr_type, number_of_addr_types, addr_type_number;
1447   guint offset;
1448 
1449   number_of_addr_types = (tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH)
1450                             / SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH;
1451 
1452   offset = PARAMETER_VALUE_OFFSET;
1453   proto_item_append_text(parameter_item, " (Supported types: ");
1454   for(addr_type_number = 0; addr_type_number < number_of_addr_types; addr_type_number++) {
1455     proto_tree_add_item(parameter_tree, hf_supported_address_type, parameter_tvb, offset, SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH, ENC_BIG_ENDIAN);
1456     addr_type = tvb_get_ntohs(parameter_tvb, offset);
1457     switch (addr_type) {
1458     case IPv4_ADDRESS_TYPE:
1459       proto_item_append_text(parameter_item, "IPv4");
1460       break;
1461     case IPv6_ADDRESS_TYPE:
1462       proto_item_append_text(parameter_item, "IPv6");
1463       break;
1464     case HOSTNAME_ADDRESS_TYPE:
1465       proto_item_append_text(parameter_item, "hostname");
1466       break;
1467     default:
1468       proto_item_append_text(parameter_item, "%u", addr_type);
1469     }
1470     if (addr_type_number < (number_of_addr_types-1))
1471       proto_item_append_text(parameter_item, ", ");
1472     offset += SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH;
1473   }
1474   proto_item_append_text(parameter_item, ")");
1475 }
1476 
1477 #define STREAM_RESET_SEQ_NR_LENGTH       4
1478 #define SENDERS_LAST_ASSIGNED_TSN_LENGTH 4
1479 #define SID_LENGTH                       2
1480 
1481 #define STREAM_RESET_REQ_SEQ_NR_OFFSET     PARAMETER_VALUE_OFFSET
1482 #define STREAM_RESET_REQ_RSP_SEQ_NR_OFFSET (PARAMETER_VALUE_OFFSET + STREAM_RESET_SEQ_NR_LENGTH)
1483 #define SENDERS_LAST_ASSIGNED_TSN_OFFSET   (STREAM_RESET_REQ_RSP_SEQ_NR_OFFSET + STREAM_RESET_SEQ_NR_LENGTH)
1484 
1485 static void
dissect_outgoing_ssn_reset_request_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item _U_)1486 dissect_outgoing_ssn_reset_request_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item _U_)
1487 {
1488   guint length, number_of_sids, sid_number, sid_offset;
1489 
1490   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,       ENC_BIG_ENDIAN);
1491   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,       ENC_BIG_ENDIAN);
1492   proto_tree_add_item(parameter_tree, hf_senders_last_assigned_tsn, parameter_tvb, SENDERS_LAST_ASSIGNED_TSN_OFFSET,   SENDERS_LAST_ASSIGNED_TSN_LENGTH, ENC_BIG_ENDIAN);
1493 
1494   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1495   sid_offset = SENDERS_LAST_ASSIGNED_TSN_OFFSET + SENDERS_LAST_ASSIGNED_TSN_LENGTH;
1496   if (length > PARAMETER_HEADER_LENGTH + STREAM_RESET_SEQ_NR_LENGTH + STREAM_RESET_SEQ_NR_LENGTH + SENDERS_LAST_ASSIGNED_TSN_LENGTH) {
1497     number_of_sids = (length - (PARAMETER_HEADER_LENGTH + STREAM_RESET_SEQ_NR_LENGTH + STREAM_RESET_SEQ_NR_LENGTH + SENDERS_LAST_ASSIGNED_TSN_LENGTH)) / SID_LENGTH;
1498     for(sid_number = 0; sid_number < number_of_sids; sid_number++) {
1499       proto_tree_add_item(parameter_tree, hf_stream_reset_sid, parameter_tvb, sid_offset, SID_LENGTH, ENC_BIG_ENDIAN);
1500       sid_offset += SID_LENGTH;
1501     }
1502   }
1503 }
1504 
1505 static void
dissect_incoming_ssn_reset_request_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item _U_)1506 dissect_incoming_ssn_reset_request_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item _U_)
1507 {
1508   guint length, number_of_sids, sid_number, sid_offset;
1509 
1510   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, ENC_BIG_ENDIAN);
1511 
1512   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1513   sid_offset = STREAM_RESET_REQ_SEQ_NR_OFFSET + STREAM_RESET_SEQ_NR_LENGTH;
1514   if (length > PARAMETER_HEADER_LENGTH + STREAM_RESET_SEQ_NR_LENGTH) {
1515     number_of_sids = (length - (PARAMETER_HEADER_LENGTH + STREAM_RESET_SEQ_NR_LENGTH)) / SID_LENGTH;
1516     for(sid_number = 0; sid_number < number_of_sids; sid_number++) {
1517       proto_tree_add_item(parameter_tree, hf_stream_reset_sid, parameter_tvb, sid_offset, SID_LENGTH, ENC_BIG_ENDIAN);
1518       sid_offset += SID_LENGTH;
1519     }
1520   }
1521 }
1522 
1523 #define STREAM_RESET_REQ_SEQ_NR_OFFSET PARAMETER_VALUE_OFFSET
1524 
1525 static void
dissect_ssn_tsn_reset_request_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item _U_)1526 dissect_ssn_tsn_reset_request_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item _U_)
1527 {
1528   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, ENC_BIG_ENDIAN);
1529 }
1530 
1531 #define STREAM_RESET_RSP_RESULT_LENGTH 4
1532 #define SENDERS_NEXT_TSN_LENGTH        4
1533 #define RECEIVERS_NEXT_TSN_LENGTH      4
1534 
1535 #define STREAM_RESET_RSP_RSP_SEQ_NR_OFFSET PARAMETER_VALUE_OFFSET
1536 #define STREAM_RESET_RSP_RESULT_OFFSET     (STREAM_RESET_RSP_RSP_SEQ_NR_OFFSET + STREAM_RESET_SEQ_NR_LENGTH)
1537 #define SENDERS_NEXT_TSN_OFFSET            (STREAM_RESET_RSP_RESULT_OFFSET + STREAM_RESET_RSP_RESULT_LENGTH)
1538 #define RECEIVERS_NEXT_TSN_OFFSET          (SENDERS_NEXT_TSN_OFFSET + SENDERS_NEXT_TSN_LENGTH)
1539 
1540 static const value_string stream_reset_result_values[] = {
1541   { 0, "Nothing to do"                       },
1542   { 1, "Performed"                           },
1543   { 2, "Denied"                              },
1544   { 3, "Error - Wrong SSN"                   },
1545   { 4, "Error - Request already in progress" },
1546   { 5, "Error - Bad sequence number"         },
1547   { 6, "In progress"                         },
1548   { 0, NULL                                  }
1549 };
1550 
1551 
1552 static void
dissect_re_configuration_response_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item _U_)1553 dissect_re_configuration_response_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item _U_)
1554 {
1555   guint length;
1556 
1557   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1558 
1559   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,     ENC_BIG_ENDIAN);
1560   proto_tree_add_item(parameter_tree, hf_stream_reset_rsp_result, parameter_tvb, STREAM_RESET_RSP_RESULT_OFFSET,     STREAM_RESET_RSP_RESULT_LENGTH, ENC_BIG_ENDIAN);
1561   if (length >= PARAMETER_HEADER_LENGTH + STREAM_RESET_SEQ_NR_LENGTH + STREAM_RESET_RSP_RESULT_LENGTH + SENDERS_NEXT_TSN_LENGTH)
1562     proto_tree_add_item(parameter_tree, hf_senders_next_tsn,   parameter_tvb, SENDERS_NEXT_TSN_OFFSET,   SENDERS_NEXT_TSN_LENGTH,   ENC_BIG_ENDIAN);
1563   if (length >= PARAMETER_HEADER_LENGTH + STREAM_RESET_SEQ_NR_LENGTH + STREAM_RESET_RSP_RESULT_LENGTH + SENDERS_NEXT_TSN_LENGTH + RECEIVERS_NEXT_TSN_LENGTH)
1564     proto_tree_add_item(parameter_tree, hf_receivers_next_tsn, parameter_tvb, RECEIVERS_NEXT_TSN_OFFSET, RECEIVERS_NEXT_TSN_LENGTH, ENC_BIG_ENDIAN);
1565 }
1566 
1567 #define ADD_OUTGOING_STREAM_REQ_SEQ_NR_LENGTH      4
1568 #define ADD_OUTGOING_STREAM_REQ_NUM_STREAMS_LENGTH 2
1569 #define ADD_OUTGOING_STREAM_REQ_RESERVED_LENGTH    2
1570 
1571 #define ADD_OUTGOING_STREAM_REQ_SEQ_NR_OFFSET      PARAMETER_VALUE_OFFSET
1572 #define ADD_OUTGOING_STREAM_REQ_NUM_STREAMS_OFFSET (ADD_OUTGOING_STREAM_REQ_SEQ_NR_OFFSET + ADD_OUTGOING_STREAM_REQ_SEQ_NR_LENGTH)
1573 #define ADD_OUTGOING_STREAM_REQ_RESERVED_OFFSET    (ADD_OUTGOING_STREAM_REQ_NUM_STREAMS_OFFSET + ADD_OUTGOING_STREAM_REQ_NUM_STREAMS_LENGTH)
1574 
1575 static void
dissect_add_outgoing_streams_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item _U_)1576 dissect_add_outgoing_streams_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item _U_)
1577 {
1578   /* guint length; */
1579 
1580   /* length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET); */
1581 
1582   proto_tree_add_item(parameter_tree, hf_stream_reset_req_seq_nr,             parameter_tvb, ADD_OUTGOING_STREAM_REQ_SEQ_NR_OFFSET,      ADD_OUTGOING_STREAM_REQ_SEQ_NR_LENGTH,      ENC_BIG_ENDIAN);
1583   proto_tree_add_item(parameter_tree, hf_add_outgoing_streams_number_streams, parameter_tvb, ADD_OUTGOING_STREAM_REQ_NUM_STREAMS_OFFSET, ADD_OUTGOING_STREAM_REQ_NUM_STREAMS_LENGTH, ENC_BIG_ENDIAN);
1584   proto_tree_add_item(parameter_tree, hf_add_outgoing_streams_reserved,       parameter_tvb, ADD_OUTGOING_STREAM_REQ_RESERVED_OFFSET,    ADD_OUTGOING_STREAM_REQ_RESERVED_LENGTH,    ENC_BIG_ENDIAN);
1585 }
1586 
1587 #define ADD_INCOMING_STREAM_REQ_SEQ_NR_LENGTH      4
1588 #define ADD_INCOMING_STREAM_REQ_NUM_STREAMS_LENGTH 2
1589 #define ADD_INCOMING_STREAM_REQ_RESERVED_LENGTH    2
1590 
1591 #define ADD_INCOMING_STREAM_REQ_SEQ_NR_OFFSET      PARAMETER_VALUE_OFFSET
1592 #define ADD_INCOMING_STREAM_REQ_NUM_STREAMS_OFFSET (ADD_INCOMING_STREAM_REQ_SEQ_NR_OFFSET + ADD_OUTGOING_STREAM_REQ_SEQ_NR_LENGTH)
1593 #define ADD_INCOMING_STREAM_REQ_RESERVED_OFFSET    (ADD_INCOMING_STREAM_REQ_NUM_STREAMS_OFFSET + ADD_OUTGOING_STREAM_REQ_NUM_STREAMS_LENGTH)
1594 
1595 static void
dissect_add_incoming_streams_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item _U_)1596 dissect_add_incoming_streams_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item _U_)
1597 {
1598   /* guint length; */
1599 
1600   /* length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET); */
1601 
1602   proto_tree_add_item(parameter_tree, hf_stream_reset_req_seq_nr,             parameter_tvb, ADD_INCOMING_STREAM_REQ_SEQ_NR_OFFSET,      ADD_OUTGOING_STREAM_REQ_SEQ_NR_LENGTH,    ENC_BIG_ENDIAN);
1603   proto_tree_add_item(parameter_tree, hf_add_incoming_streams_number_streams, parameter_tvb, ADD_INCOMING_STREAM_REQ_NUM_STREAMS_OFFSET, ADD_INCOMING_STREAM_REQ_NUM_STREAMS_LENGTH, ENC_BIG_ENDIAN);
1604   proto_tree_add_item(parameter_tree, hf_add_incoming_streams_reserved,       parameter_tvb, ADD_INCOMING_STREAM_REQ_RESERVED_OFFSET,    ADD_INCOMING_STREAM_REQ_RESERVED_LENGTH,    ENC_BIG_ENDIAN);
1605 }
1606 
1607 static void
dissect_ecn_parameter(tvbuff_t * parameter_tvb _U_)1608 dissect_ecn_parameter(tvbuff_t *parameter_tvb _U_)
1609 {
1610 }
1611 
1612 static void
dissect_nonce_supported_parameter(tvbuff_t * parameter_tvb _U_)1613 dissect_nonce_supported_parameter(tvbuff_t *parameter_tvb _U_)
1614 {
1615 }
1616 
1617 #define RANDOM_NUMBER_OFFSET PARAMETER_VALUE_OFFSET
1618 
1619 static void
dissect_random_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree)1620 dissect_random_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
1621 {
1622   gint32 number_length;
1623 
1624   number_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1625   if (number_length > 0)
1626     proto_tree_add_item(parameter_tree, hf_random_number, parameter_tvb, RANDOM_NUMBER_OFFSET, number_length, ENC_NA);
1627 }
1628 
1629 static void
dissect_chunks_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)1630 dissect_chunks_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1631 {
1632   guint16 number_of_chunks;
1633   guint16 chunk_number, offset;
1634 
1635   proto_item_append_text(parameter_item, " (Chunk types to be authenticated: ");
1636   number_of_chunks = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1637   for(chunk_number = 0, offset = PARAMETER_VALUE_OFFSET; chunk_number < number_of_chunks; chunk_number++, offset +=  CHUNK_TYPE_LENGTH) {
1638     proto_tree_add_item(parameter_tree, hf_chunks_to_auth, parameter_tvb, offset, CHUNK_TYPE_LENGTH, ENC_BIG_ENDIAN);
1639     proto_item_append_text(parameter_item, "%s", val_to_str_const(tvb_get_guint8(parameter_tvb, offset), chunk_type_values, "Unknown"));
1640     if (chunk_number < (number_of_chunks - 1))
1641       proto_item_append_text(parameter_item, ", ");
1642   }
1643   proto_item_append_text(parameter_item, ")");
1644 }
1645 
1646 static const value_string hmac_id_values[] = {
1647   { 0x0000,         "Reserved" },
1648   { 0x0001,         "SHA-1"    },
1649   { 0x0002,         "Reserved" },
1650   { 0x0003,         "SHA-256"  },
1651   { 0,              NULL       } };
1652 
1653 #define HMAC_ID_LENGTH 2
1654 
1655 static void
dissect_hmac_algo_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)1656 dissect_hmac_algo_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1657 {
1658   guint16 number_of_ids;
1659   guint16 id_number, offset;
1660 
1661   proto_item_append_text(parameter_item, " (Supported HMACs: ");
1662   number_of_ids = (tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH) / HMAC_ID_LENGTH;
1663   for(id_number = 0, offset = PARAMETER_VALUE_OFFSET; id_number < number_of_ids; id_number++, offset +=  HMAC_ID_LENGTH) {
1664     proto_tree_add_item(parameter_tree, hf_hmac_id, parameter_tvb, offset, HMAC_ID_LENGTH, ENC_BIG_ENDIAN);
1665     proto_item_append_text(parameter_item, "%s", val_to_str_const(tvb_get_ntohs(parameter_tvb, offset), hmac_id_values, "Unknown"));
1666     if (id_number < (number_of_ids - 1))
1667       proto_item_append_text(parameter_item, ", ");
1668   }
1669   proto_item_append_text(parameter_item, ")");
1670 }
1671 
1672 static void
dissect_supported_extensions_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)1673 dissect_supported_extensions_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1674 {
1675   guint16 number_of_types;
1676   guint16 type_number, offset;
1677 
1678   proto_item_append_text(parameter_item, " (Supported types: ");
1679   number_of_types = (tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH) / CHUNK_TYPE_LENGTH;
1680   for(type_number = 0, offset = PARAMETER_VALUE_OFFSET; type_number < number_of_types; type_number++, offset +=  CHUNK_TYPE_LENGTH) {
1681     proto_tree_add_item(parameter_tree, hf_supported_chunk_type, parameter_tvb, offset, CHUNK_TYPE_LENGTH, ENC_BIG_ENDIAN);
1682     proto_item_append_text(parameter_item, "%s", val_to_str_const(tvb_get_guint8(parameter_tvb, offset), chunk_type_values, "Unknown"));
1683     if (type_number < (number_of_types - 1))
1684       proto_item_append_text(parameter_item, ", ");
1685   }
1686   proto_item_append_text(parameter_item, ")");
1687 }
1688 
1689 static void
dissect_forward_tsn_supported_parameter(tvbuff_t * parameter_tvb _U_)1690 dissect_forward_tsn_supported_parameter(tvbuff_t *parameter_tvb _U_)
1691 {
1692 }
1693 
1694 #define CORRELATION_ID_LENGTH    4
1695 #define CORRELATION_ID_OFFSET    PARAMETER_VALUE_OFFSET
1696 #define ADDRESS_PARAMETER_OFFSET (CORRELATION_ID_OFFSET + CORRELATION_ID_LENGTH)
1697 
1698 static void
dissect_add_ip_address_parameter(tvbuff_t * parameter_tvb,packet_info * pinfo,proto_tree * parameter_tree,proto_item * parameter_item)1699 dissect_add_ip_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
1700 {
1701   guint16 address_length;
1702   tvbuff_t *address_tvb;
1703 
1704   address_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
1705 
1706   proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, ENC_BIG_ENDIAN);
1707   address_tvb =  tvb_new_subset_length_caplen(parameter_tvb, ADDRESS_PARAMETER_OFFSET,
1708                                 MIN(address_length, tvb_captured_length_remaining(parameter_tvb, ADDRESS_PARAMETER_OFFSET)),
1709                                 MIN(address_length, tvb_reported_length_remaining(parameter_tvb, ADDRESS_PARAMETER_OFFSET)));
1710   proto_item_append_text(parameter_item, " (Address: ");
1711   dissect_parameter(address_tvb, pinfo, parameter_tree, parameter_item, FALSE, FALSE);
1712   proto_item_append_text(parameter_item, ", correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
1713 }
1714 
1715 static void
dissect_del_ip_address_parameter(tvbuff_t * parameter_tvb,packet_info * pinfo,proto_tree * parameter_tree,proto_item * parameter_item)1716 dissect_del_ip_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
1717 {
1718   guint16 address_length;
1719   tvbuff_t *address_tvb;
1720 
1721   address_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
1722 
1723   proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, ENC_BIG_ENDIAN);
1724   address_tvb =  tvb_new_subset_length_caplen(parameter_tvb, ADDRESS_PARAMETER_OFFSET,
1725                                 MIN(address_length, tvb_captured_length_remaining(parameter_tvb, ADDRESS_PARAMETER_OFFSET)),
1726                                 MIN(address_length, tvb_reported_length_remaining(parameter_tvb, ADDRESS_PARAMETER_OFFSET)));
1727   proto_item_append_text(parameter_item, " (Address: ");
1728   dissect_parameter(address_tvb, pinfo, parameter_tree, parameter_item, FALSE, FALSE);
1729   proto_item_append_text(parameter_item, ", correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
1730 }
1731 
1732 #define ERROR_CAUSE_IND_CASUES_OFFSET (CORRELATION_ID_OFFSET + CORRELATION_ID_LENGTH)
1733 
1734 static void
dissect_error_cause_indication_parameter(tvbuff_t * parameter_tvb,packet_info * pinfo,proto_tree * parameter_tree)1735 dissect_error_cause_indication_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
1736 {
1737   guint16 causes_length;
1738   tvbuff_t *causes_tvb;
1739 
1740   proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, ENC_BIG_ENDIAN);
1741   causes_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
1742   causes_tvb    = tvb_new_subset_length_caplen(parameter_tvb, ERROR_CAUSE_IND_CASUES_OFFSET,
1743                                  MIN(causes_length, tvb_captured_length_remaining(parameter_tvb, ERROR_CAUSE_IND_CASUES_OFFSET)),
1744                                  MIN(causes_length, tvb_reported_length_remaining(parameter_tvb, ERROR_CAUSE_IND_CASUES_OFFSET)));
1745   dissect_error_causes(causes_tvb, pinfo,  parameter_tree);
1746 }
1747 
1748 static void
dissect_set_primary_address_parameter(tvbuff_t * parameter_tvb,packet_info * pinfo,proto_tree * parameter_tree,proto_item * parameter_item)1749 dissect_set_primary_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
1750 {
1751   guint16 address_length;
1752   tvbuff_t *address_tvb;
1753 
1754   address_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
1755 
1756   proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, ENC_BIG_ENDIAN);
1757   address_tvb    =  tvb_new_subset_length_caplen(parameter_tvb, ADDRESS_PARAMETER_OFFSET,
1758                                    MIN(address_length, tvb_captured_length_remaining(parameter_tvb, ADDRESS_PARAMETER_OFFSET)),
1759                                    MIN(address_length, tvb_reported_length_remaining(parameter_tvb, ADDRESS_PARAMETER_OFFSET)));
1760   proto_item_append_text(parameter_item, " (Address: ");
1761   dissect_parameter(address_tvb, pinfo, parameter_tree, parameter_item, FALSE, FALSE);
1762   proto_item_append_text(parameter_item, ", correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
1763 }
1764 
1765 static void
dissect_success_report_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)1766 dissect_success_report_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1767 {
1768   proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, ENC_BIG_ENDIAN);
1769   proto_item_append_text(parameter_item, " (Correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
1770 }
1771 
1772 #define ADAP_INDICATION_LENGTH 4
1773 #define ADAP_INDICATION_OFFSET PARAMETER_VALUE_OFFSET
1774 
1775 static void
dissect_adap_indication_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)1776 dissect_adap_indication_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1777 {
1778   proto_tree_add_item(parameter_tree, hf_adap_indication, parameter_tvb, ADAP_INDICATION_OFFSET, ADAP_INDICATION_LENGTH, ENC_BIG_ENDIAN);
1779   proto_item_append_text(parameter_item, " (Indication: %u)", tvb_get_ntohl(parameter_tvb, ADAP_INDICATION_OFFSET));
1780 }
1781 
1782 static void
dissect_unknown_parameter(tvbuff_t * parameter_tvb,proto_tree * parameter_tree,proto_item * parameter_item)1783 dissect_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1784 {
1785   guint16 type, parameter_value_length;
1786 
1787   type                   = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
1788   parameter_value_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1789 
1790   if (parameter_value_length > 0)
1791     proto_tree_add_item(parameter_tree, hf_parameter_value, parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length, ENC_NA);
1792 
1793   proto_item_append_text(parameter_item, " (Type %u, value length: %u byte%s)", type, parameter_value_length, plurality(parameter_value_length, "", "s"));
1794 }
1795 
1796 #define HEARTBEAT_INFO_PARAMETER_ID               0x0001
1797 #define IPV4ADDRESS_PARAMETER_ID                  0x0005
1798 #define IPV6ADDRESS_PARAMETER_ID                  0x0006
1799 #define STATE_COOKIE_PARAMETER_ID                 0x0007
1800 #define UNREC_PARA_PARAMETER_ID                   0x0008
1801 #define COOKIE_PRESERVATIVE_PARAMETER_ID          0x0009
1802 #define HOSTNAME_ADDRESS_PARAMETER_ID             0x000b
1803 #define SUPPORTED_ADDRESS_TYPES_PARAMETER_ID      0x000c
1804 #define OUTGOING_SSN_RESET_REQUEST_PARAMETER_ID   0x000d
1805 #define INCOMING_SSN_RESET_REQUEST_PARAMETER_ID   0x000e
1806 #define SSN_TSN_RESET_REQUEST_PARAMETER_ID        0x000f
1807 #define RE_CONFIGURATION_RESPONSE_PARAMETER_ID    0x0010
1808 #define ADD_OUTGOING_STREAMS_REQUEST_PARAMETER_ID 0x0011
1809 #define ADD_INCOMING_STREAMS_REQUEST_PARAMETER_ID 0x0012
1810 #define ECN_PARAMETER_ID                          0x8000
1811 #define NONCE_SUPPORTED_PARAMETER_ID              0x8001
1812 #define RANDOM_PARAMETER_ID                       0x8002
1813 #define CHUNKS_PARAMETER_ID                       0x8003
1814 #define HMAC_ALGO_PARAMETER_ID                    0x8004
1815 #define SUPPORTED_EXTENSIONS_PARAMETER_ID         0x8008
1816 #define FORWARD_TSN_SUPPORTED_PARAMETER_ID        0xC000
1817 #define ADD_IP_ADDRESS_PARAMETER_ID               0xC001
1818 #define DEL_IP_ADDRESS_PARAMETER_ID               0xC002
1819 #define ERROR_CAUSE_INDICATION_PARAMETER_ID       0xC003
1820 #define SET_PRIMARY_ADDRESS_PARAMETER_ID          0xC004
1821 #define SUCCESS_REPORT_PARAMETER_ID               0xC005
1822 #define ADAP_LAYER_INDICATION_PARAMETER_ID        0xC006
1823 
1824 static const value_string parameter_identifier_values[] = {
1825   { HEARTBEAT_INFO_PARAMETER_ID,               "Heartbeat info"               },
1826   { IPV4ADDRESS_PARAMETER_ID,                  "IPv4 address"                 },
1827   { IPV6ADDRESS_PARAMETER_ID,                  "IPv6 address"                 },
1828   { STATE_COOKIE_PARAMETER_ID,                 "State cookie"                 },
1829   { UNREC_PARA_PARAMETER_ID,                   "Unrecognized parameter"       },
1830   { COOKIE_PRESERVATIVE_PARAMETER_ID,          "Cookie preservative"          },
1831   { HOSTNAME_ADDRESS_PARAMETER_ID,             "Hostname address"             },
1832   { OUTGOING_SSN_RESET_REQUEST_PARAMETER_ID,   "Outgoing SSN reset request"   },
1833   { INCOMING_SSN_RESET_REQUEST_PARAMETER_ID,   "Incoming SSN reset request"   },
1834   { SSN_TSN_RESET_REQUEST_PARAMETER_ID,        "SSN/TSN reset request"        },
1835   { RE_CONFIGURATION_RESPONSE_PARAMETER_ID,    "Re-configuration response"    },
1836   { ADD_OUTGOING_STREAMS_REQUEST_PARAMETER_ID, "Add outgoing streams request" },
1837   { ADD_INCOMING_STREAMS_REQUEST_PARAMETER_ID, "Add incoming streams request" },
1838   { SUPPORTED_ADDRESS_TYPES_PARAMETER_ID,      "Supported address types"      },
1839   { ECN_PARAMETER_ID,                          "ECN"                          },
1840   { NONCE_SUPPORTED_PARAMETER_ID,              "Nonce supported"              },
1841   { RANDOM_PARAMETER_ID,                       "Random"                       },
1842   { CHUNKS_PARAMETER_ID,                       "Authenticated Chunk list"     },
1843   { HMAC_ALGO_PARAMETER_ID,                    "Requested HMAC Algorithm"     },
1844   { SUPPORTED_EXTENSIONS_PARAMETER_ID,         "Supported Extensions"         },
1845   { FORWARD_TSN_SUPPORTED_PARAMETER_ID,        "Forward TSN supported"        },
1846   { ADD_IP_ADDRESS_PARAMETER_ID,               "Add IP address"               },
1847   { DEL_IP_ADDRESS_PARAMETER_ID,               "Delete IP address"            },
1848   { ERROR_CAUSE_INDICATION_PARAMETER_ID,       "Error cause indication"       },
1849   { SET_PRIMARY_ADDRESS_PARAMETER_ID,          "Set primary address"          },
1850   { SUCCESS_REPORT_PARAMETER_ID,               "Success report"               },
1851   { ADAP_LAYER_INDICATION_PARAMETER_ID,        "Adaptation Layer Indication"  },
1852   { 0,                                         NULL                           } };
1853 
1854 #define SCTP_PARAMETER_BIT_1  0x8000
1855 #define SCTP_PARAMETER_BIT_2 0x4000
1856 
1857 static const true_false_string sctp_parameter_bit_1_value = {
1858   "Skip parameter and continue processing of the chunk",
1859   "Stop processing of chunk"
1860 };
1861 
1862 static const true_false_string sctp_parameter_bit_2_value = {
1863   "Do report",
1864   "Do not report"
1865 };
1866 
1867 static void
dissect_parameter(tvbuff_t * parameter_tvb,packet_info * pinfo,proto_tree * chunk_tree,proto_item * additional_item,gboolean dissecting_init_init_ack_chunk,gboolean final_parameter)1868 dissect_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo,
1869                   proto_tree *chunk_tree, proto_item *additional_item,
1870                   gboolean dissecting_init_init_ack_chunk,
1871                   gboolean final_parameter)
1872 {
1873   guint16 type, length, padding_length, reported_length;
1874   proto_item *parameter_item, *type_item;
1875   proto_tree *parameter_tree, *type_tree;
1876 
1877   type            = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
1878   length          = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1879   reported_length = tvb_reported_length(parameter_tvb);
1880   padding_length  = reported_length - length;
1881 
1882   parameter_tree = proto_tree_add_subtree_format(chunk_tree, parameter_tvb, PARAMETER_HEADER_OFFSET, -1,
1883             ett_sctp_chunk_parameter, &parameter_item, "%s parameter",
1884             val_to_str_const(type, parameter_identifier_values, "Unknown"));
1885   if (final_parameter) {
1886     if (padding_length > 0) {
1887       expert_add_info(pinfo, parameter_item, &ei_sctp_parameter_padding);
1888     }
1889   } else {
1890     if (reported_length % 4) {
1891       expert_add_info_format(pinfo, parameter_item, &ei_sctp_parameter_length, "Parameter length is not padded to a multiple of 4 bytes (length=%d)", reported_length);
1892     }
1893   }
1894 
1895   if (!(chunk_tree || (dissecting_init_init_ack_chunk && (type == IPV4ADDRESS_PARAMETER_ID || type == IPV6ADDRESS_PARAMETER_ID))))
1896     return;
1897 
1898   if (chunk_tree) {
1899     type_item = proto_tree_add_item(parameter_tree, hf_parameter_type,   parameter_tvb, PARAMETER_TYPE_OFFSET,   PARAMETER_TYPE_LENGTH,   ENC_BIG_ENDIAN);
1900     type_tree = proto_item_add_subtree(type_item, ett_sctp_parameter_type);
1901     proto_tree_add_item(type_tree, hf_parameter_bit_1,  parameter_tvb, PARAMETER_TYPE_OFFSET,  PARAMETER_TYPE_LENGTH,  ENC_BIG_ENDIAN);
1902     proto_tree_add_item(type_tree, hf_parameter_bit_2,  parameter_tvb, PARAMETER_TYPE_OFFSET,  PARAMETER_TYPE_LENGTH,  ENC_BIG_ENDIAN);
1903     proto_tree_add_item(parameter_tree, hf_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, ENC_BIG_ENDIAN);
1904     /* XXX - add expert info if length is bogus? */
1905   } else {
1906     parameter_item = NULL;
1907     parameter_tree = NULL;
1908   }
1909 
1910   switch(type) {
1911   case HEARTBEAT_INFO_PARAMETER_ID:
1912     dissect_heartbeat_info_parameter(parameter_tvb, parameter_tree, parameter_item);
1913     break;
1914   case IPV4ADDRESS_PARAMETER_ID:
1915     dissect_ipv4_parameter(parameter_tvb, parameter_tree, parameter_item, additional_item, dissecting_init_init_ack_chunk);
1916     break;
1917   case IPV6ADDRESS_PARAMETER_ID:
1918     dissect_ipv6_parameter(parameter_tvb, parameter_tree, parameter_item, additional_item, dissecting_init_init_ack_chunk);
1919     break;
1920   case STATE_COOKIE_PARAMETER_ID:
1921     dissect_state_cookie_parameter(parameter_tvb, parameter_tree, parameter_item);
1922     break;
1923   case UNREC_PARA_PARAMETER_ID:
1924     dissect_unrecognized_parameters_parameter(parameter_tvb, pinfo,  parameter_tree);
1925     break;
1926   case COOKIE_PRESERVATIVE_PARAMETER_ID:
1927     dissect_cookie_preservative_parameter(parameter_tvb, parameter_tree, parameter_item);
1928     break;
1929   case HOSTNAME_ADDRESS_PARAMETER_ID:
1930     dissect_hostname_parameter(parameter_tvb, parameter_tree, parameter_item);
1931     break;
1932   case SUPPORTED_ADDRESS_TYPES_PARAMETER_ID:
1933     dissect_supported_address_types_parameter(parameter_tvb, parameter_tree, parameter_item);
1934     break;
1935   case OUTGOING_SSN_RESET_REQUEST_PARAMETER_ID:
1936     dissect_outgoing_ssn_reset_request_parameter(parameter_tvb, parameter_tree, parameter_item);
1937     break;
1938   case INCOMING_SSN_RESET_REQUEST_PARAMETER_ID:
1939     dissect_incoming_ssn_reset_request_parameter(parameter_tvb, parameter_tree, parameter_item);
1940     break;
1941   case SSN_TSN_RESET_REQUEST_PARAMETER_ID:
1942     dissect_ssn_tsn_reset_request_parameter(parameter_tvb, parameter_tree, parameter_item);
1943     break;
1944   case RE_CONFIGURATION_RESPONSE_PARAMETER_ID:
1945     dissect_re_configuration_response_parameter(parameter_tvb, parameter_tree, parameter_item);
1946     break;
1947   case ADD_OUTGOING_STREAMS_REQUEST_PARAMETER_ID:
1948     dissect_add_outgoing_streams_parameter(parameter_tvb, parameter_tree, parameter_item);
1949     break;
1950   case ADD_INCOMING_STREAMS_REQUEST_PARAMETER_ID:
1951     dissect_add_incoming_streams_parameter(parameter_tvb, parameter_tree, parameter_item);
1952     break;
1953   case ECN_PARAMETER_ID:
1954     dissect_ecn_parameter(parameter_tvb);
1955     break;
1956   case NONCE_SUPPORTED_PARAMETER_ID:
1957     dissect_nonce_supported_parameter(parameter_tvb);
1958     break;
1959   case RANDOM_PARAMETER_ID:
1960     dissect_random_parameter(parameter_tvb, parameter_tree);
1961     break;
1962   case CHUNKS_PARAMETER_ID:
1963     dissect_chunks_parameter(parameter_tvb, parameter_tree, parameter_item);
1964     break;
1965   case HMAC_ALGO_PARAMETER_ID:
1966     dissect_hmac_algo_parameter(parameter_tvb, parameter_tree, parameter_item);
1967     break;
1968   case SUPPORTED_EXTENSIONS_PARAMETER_ID:
1969     dissect_supported_extensions_parameter(parameter_tvb, parameter_tree, parameter_item);
1970     break;
1971   case FORWARD_TSN_SUPPORTED_PARAMETER_ID:
1972     dissect_forward_tsn_supported_parameter(parameter_tvb);
1973     break;
1974   case ADD_IP_ADDRESS_PARAMETER_ID:
1975     dissect_add_ip_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
1976     break;
1977   case DEL_IP_ADDRESS_PARAMETER_ID:
1978     dissect_del_ip_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
1979     break;
1980   case ERROR_CAUSE_INDICATION_PARAMETER_ID:
1981     dissect_error_cause_indication_parameter(parameter_tvb, pinfo, parameter_tree);
1982     break;
1983   case SET_PRIMARY_ADDRESS_PARAMETER_ID:
1984     dissect_set_primary_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
1985     break;
1986   case SUCCESS_REPORT_PARAMETER_ID:
1987     dissect_success_report_parameter(parameter_tvb, parameter_tree, parameter_item);
1988     break;
1989   case ADAP_LAYER_INDICATION_PARAMETER_ID:
1990     dissect_adap_indication_parameter(parameter_tvb, parameter_tree, parameter_item);
1991     break;
1992   default:
1993     dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
1994     break;
1995   }
1996 
1997   if (padding_length > 0) {
1998     proto_tree_add_item(parameter_tree, hf_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, ENC_NA);
1999   }
2000 }
2001 
2002 static void
dissect_parameters(tvbuff_t * parameters_tvb,packet_info * pinfo,proto_tree * tree,proto_item * additional_item,gboolean dissecting_init_init_ack_chunk)2003 dissect_parameters(tvbuff_t *parameters_tvb, packet_info *pinfo, proto_tree *tree, proto_item *additional_item, gboolean dissecting_init_init_ack_chunk)
2004 {
2005   gint offset, length, total_length, remaining_length;
2006   tvbuff_t *parameter_tvb;
2007   gboolean final_parameter;
2008 
2009   offset = 0;
2010   remaining_length = tvb_reported_length_remaining(parameters_tvb, offset);
2011   while (remaining_length > 0) {
2012     if ((offset > 0) && additional_item)
2013       proto_item_append_text(additional_item, " ");
2014 
2015     length       = tvb_get_ntohs(parameters_tvb, offset + PARAMETER_LENGTH_OFFSET);
2016     total_length = ADD_PADDING(length);
2017 
2018     /*  If we have less bytes than we need, throw an exception while dissecting
2019      *  the parameter--not when generating the parameter_tvb below.
2020      */
2021     total_length = MIN(total_length, remaining_length);
2022 
2023     /* create a tvb for the parameter including the padding bytes */
2024     parameter_tvb  = tvb_new_subset_length_caplen(parameters_tvb, offset, MIN(total_length, tvb_captured_length_remaining(parameters_tvb, offset)), total_length);
2025     /* get rid of the handled parameter */
2026     offset += total_length;
2027     remaining_length = tvb_reported_length_remaining(parameters_tvb, offset);
2028     if (remaining_length > 0) {
2029       final_parameter = FALSE;
2030     } else {
2031       final_parameter = TRUE;
2032     }
2033     dissect_parameter(parameter_tvb, pinfo, tree, additional_item, dissecting_init_init_ack_chunk, final_parameter);
2034   }
2035 }
2036 
2037 
2038 /*
2039  * Code to handle error causes for ABORT and ERROR chunks
2040  */
2041 
2042 
2043 #define CAUSE_CODE_LENGTH            2
2044 #define CAUSE_LENGTH_LENGTH          2
2045 #define CAUSE_HEADER_LENGTH          (CAUSE_CODE_LENGTH + CAUSE_LENGTH_LENGTH)
2046 
2047 #define CAUSE_HEADER_OFFSET          0
2048 #define CAUSE_CODE_OFFSET            CAUSE_HEADER_OFFSET
2049 #define CAUSE_LENGTH_OFFSET          (CAUSE_CODE_OFFSET + CAUSE_CODE_LENGTH)
2050 #define CAUSE_INFO_OFFSET            (CAUSE_LENGTH_OFFSET + CAUSE_LENGTH_LENGTH)
2051 
2052 
2053 #define CAUSE_STREAM_IDENTIFIER_LENGTH 2
2054 #define CAUSE_RESERVED_LENGTH 2
2055 #define CAUSE_STREAM_IDENTIFIER_OFFSET CAUSE_INFO_OFFSET
2056 #define CAUSE_RESERVED_OFFSET          (CAUSE_STREAM_IDENTIFIER_OFFSET + CAUSE_STREAM_IDENTIFIER_LENGTH)
2057 
2058 static void
dissect_invalid_stream_identifier_cause(tvbuff_t * cause_tvb,proto_tree * cause_tree,proto_item * cause_item)2059 dissect_invalid_stream_identifier_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
2060 {
2061   proto_tree_add_item(cause_tree, hf_cause_stream_identifier, cause_tvb, CAUSE_STREAM_IDENTIFIER_OFFSET, CAUSE_STREAM_IDENTIFIER_LENGTH, ENC_BIG_ENDIAN);
2062   proto_tree_add_item(cause_tree, hf_cause_reserved,          cause_tvb, CAUSE_RESERVED_OFFSET,          CAUSE_RESERVED_LENGTH,          ENC_BIG_ENDIAN);
2063   proto_item_append_text(cause_item, " (SID: %u)", tvb_get_ntohs(cause_tvb, CAUSE_STREAM_IDENTIFIER_OFFSET));
2064 }
2065 
2066 #define CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH 4
2067 #define CAUSE_MISSING_PARAMETER_TYPE_LENGTH       2
2068 
2069 #define CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET CAUSE_INFO_OFFSET
2070 #define CAUSE_FIRST_MISSING_PARAMETER_TYPE_OFFSET (CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET + \
2071                                                    CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH )
2072 
2073 static void
dissect_missing_mandatory_parameters_cause(tvbuff_t * cause_tvb,proto_tree * cause_tree)2074 dissect_missing_mandatory_parameters_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree)
2075 {
2076   guint32 number_of_missing_parameters, missing_parameter_number;
2077   guint   offset;
2078 
2079   number_of_missing_parameters = tvb_get_ntohl(cause_tvb, CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET);
2080   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, ENC_BIG_ENDIAN);
2081   offset = CAUSE_FIRST_MISSING_PARAMETER_TYPE_OFFSET;
2082   for(missing_parameter_number = 0; missing_parameter_number < number_of_missing_parameters; missing_parameter_number++) {
2083     proto_tree_add_item(cause_tree, hf_cause_missing_parameter_type, cause_tvb, offset, CAUSE_MISSING_PARAMETER_TYPE_LENGTH, ENC_BIG_ENDIAN);
2084     offset +=  CAUSE_MISSING_PARAMETER_TYPE_LENGTH;
2085   }
2086 }
2087 
2088 #define CAUSE_MEASURE_OF_STALENESS_LENGTH 4
2089 #define CAUSE_MEASURE_OF_STALENESS_OFFSET CAUSE_INFO_OFFSET
2090 
2091 static void
dissect_stale_cookie_error_cause(tvbuff_t * cause_tvb,proto_tree * cause_tree,proto_item * cause_item)2092 dissect_stale_cookie_error_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
2093 {
2094   proto_tree_add_item(cause_tree, hf_cause_measure_of_staleness, cause_tvb, CAUSE_MEASURE_OF_STALENESS_OFFSET, CAUSE_MEASURE_OF_STALENESS_LENGTH, ENC_BIG_ENDIAN);
2095   proto_item_append_text(cause_item, " (Measure: %u usec)", tvb_get_ntohl(cause_tvb, CAUSE_MEASURE_OF_STALENESS_OFFSET));
2096 }
2097 
2098 static void
dissect_out_of_resource_cause(tvbuff_t * cause_tvb _U_)2099 dissect_out_of_resource_cause(tvbuff_t *cause_tvb _U_)
2100 {
2101 }
2102 
2103 static void
dissect_unresolvable_address_cause(tvbuff_t * cause_tvb,packet_info * pinfo,proto_tree * cause_tree,proto_item * cause_item)2104 dissect_unresolvable_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
2105 {
2106   guint16 parameter_length;
2107   tvbuff_t *parameter_tvb;
2108 
2109   parameter_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
2110   parameter_tvb    = tvb_new_subset_length_caplen(cause_tvb, CAUSE_INFO_OFFSET,
2111                                     MIN(parameter_length, tvb_captured_length_remaining(cause_tvb, CAUSE_INFO_OFFSET)),
2112                                     MIN(parameter_length, tvb_reported_length_remaining(cause_tvb, CAUSE_INFO_OFFSET)));
2113   proto_item_append_text(cause_item, " (Address: ");
2114   dissect_parameter(parameter_tvb, pinfo, cause_tree, cause_item, FALSE, FALSE);
2115   proto_item_append_text(cause_item, ")");
2116 }
2117 
2118 static gboolean
2119 dissect_sctp_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *sctp_tree, sctp_half_assoc_t *assoc, gboolean useinfo);
2120 
2121 static void
dissect_unrecognized_chunk_type_cause(tvbuff_t * cause_tvb,packet_info * pinfo,proto_tree * cause_tree,proto_item * cause_item)2122 dissect_unrecognized_chunk_type_cause(tvbuff_t *cause_tvb,  packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
2123 {
2124   guint16 chunk_length;
2125   guint8 unrecognized_type;
2126   tvbuff_t *unrecognized_chunk_tvb;
2127 
2128   chunk_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
2129   unrecognized_chunk_tvb = tvb_new_subset_length_caplen(cause_tvb, CAUSE_INFO_OFFSET,
2130                                           MIN(chunk_length, tvb_captured_length_remaining(cause_tvb, CAUSE_INFO_OFFSET)),
2131                                           MIN(chunk_length, tvb_reported_length_remaining(cause_tvb, CAUSE_INFO_OFFSET)));
2132   dissect_sctp_chunk(unrecognized_chunk_tvb, pinfo, cause_tree,cause_tree, NULL, FALSE);
2133   unrecognized_type   = tvb_get_guint8(unrecognized_chunk_tvb, CHUNK_TYPE_OFFSET);
2134   proto_item_append_text(cause_item, " (Type: %u (%s))", unrecognized_type, val_to_str_const(unrecognized_type, chunk_type_values, "unknown"));
2135 }
2136 
2137 static void
dissect_invalid_mandatory_parameter_cause(tvbuff_t * cause_tvb _U_)2138 dissect_invalid_mandatory_parameter_cause(tvbuff_t *cause_tvb _U_)
2139 {
2140 }
2141 
2142 static void
dissect_unrecognized_parameters_cause(tvbuff_t * cause_tvb,packet_info * pinfo,proto_tree * cause_tree)2143 dissect_unrecognized_parameters_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree)
2144 {
2145   guint16 cause_info_length;
2146   tvbuff_t *unrecognized_parameters_tvb;
2147 
2148   cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
2149 
2150   unrecognized_parameters_tvb = tvb_new_subset_length_caplen(cause_tvb, CAUSE_INFO_OFFSET,
2151                                                MIN(cause_info_length, tvb_captured_length_remaining(cause_tvb, CAUSE_INFO_OFFSET)),
2152                                                MIN(cause_info_length, tvb_reported_length_remaining(cause_tvb, CAUSE_INFO_OFFSET)));
2153   dissect_parameters(unrecognized_parameters_tvb, pinfo, cause_tree, NULL, FALSE);
2154 }
2155 
2156 #define CAUSE_TSN_LENGTH 4
2157 #define CAUSE_TSN_OFFSET CAUSE_INFO_OFFSET
2158 
2159 static void
dissect_no_user_data_cause(tvbuff_t * cause_tvb,proto_tree * cause_tree,proto_item * cause_item)2160 dissect_no_user_data_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
2161 {
2162   proto_tree_add_item(cause_tree, hf_cause_tsn, cause_tvb, CAUSE_TSN_OFFSET, CAUSE_TSN_LENGTH, ENC_BIG_ENDIAN);
2163   proto_item_append_text(cause_item, " (TSN: %u)", tvb_get_ntohl(cause_tvb, CAUSE_TSN_OFFSET));
2164 }
2165 
2166 static void
dissect_cookie_received_while_shutting_down_cause(tvbuff_t * cause_tvb _U_)2167 dissect_cookie_received_while_shutting_down_cause(tvbuff_t *cause_tvb _U_)
2168 {
2169 }
2170 
2171 static void
dissect_restart_with_new_address_cause(tvbuff_t * cause_tvb,packet_info * pinfo,proto_tree * cause_tree,proto_item * cause_item)2172 dissect_restart_with_new_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
2173 {
2174   guint16 cause_info_length;
2175   tvbuff_t *parameter_tvb;
2176 
2177   cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
2178   parameter_tvb     = tvb_new_subset_length_caplen(cause_tvb, CAUSE_INFO_OFFSET,
2179                                      MIN(cause_info_length, tvb_captured_length_remaining(cause_tvb, CAUSE_INFO_OFFSET)),
2180                                      MIN(cause_info_length, tvb_reported_length_remaining(cause_tvb, CAUSE_INFO_OFFSET)));
2181   proto_item_append_text(cause_item, " (New addresses: ");
2182   dissect_parameters(parameter_tvb, pinfo, cause_tree, cause_item, FALSE);
2183   proto_item_append_text(cause_item, ")");
2184 }
2185 
2186 static void
dissect_user_initiated_abort_cause(tvbuff_t * cause_tvb,proto_tree * cause_tree)2187 dissect_user_initiated_abort_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree)
2188 {
2189   guint16 cause_info_length;
2190 
2191   cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
2192   if (cause_info_length > 0)
2193     proto_tree_add_item(cause_tree, hf_cause_info, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, ENC_NA);
2194 }
2195 
2196 static void
dissect_protocol_violation_cause(tvbuff_t * cause_tvb,proto_tree * cause_tree)2197 dissect_protocol_violation_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree)
2198 {
2199   guint16 cause_info_length;
2200 
2201   cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
2202   if (cause_info_length > 0)
2203     proto_tree_add_item(cause_tree, hf_cause_info, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, ENC_NA);
2204 }
2205 
2206 static void
dissect_delete_last_address_cause(tvbuff_t * cause_tvb,packet_info * pinfo,proto_tree * cause_tree,proto_item * cause_item)2207 dissect_delete_last_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
2208 {
2209   guint16 cause_info_length;
2210   tvbuff_t *parameter_tvb;
2211 
2212   cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
2213   parameter_tvb     = tvb_new_subset_length_caplen(cause_tvb, CAUSE_INFO_OFFSET,
2214                                      MIN(cause_info_length, tvb_captured_length_remaining(cause_tvb, CAUSE_INFO_OFFSET)),
2215                                      MIN(cause_info_length, tvb_reported_length_remaining(cause_tvb, CAUSE_INFO_OFFSET)));
2216   proto_item_append_text(cause_item, " (Last address: ");
2217   dissect_parameter(parameter_tvb, pinfo, cause_tree, cause_item, FALSE, FALSE);
2218   proto_item_append_text(cause_item, ")");
2219 }
2220 
2221 static void
dissect_resource_outage_cause(tvbuff_t * cause_tvb,packet_info * pinfo,proto_tree * cause_tree)2222 dissect_resource_outage_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree)
2223 {
2224   guint16 cause_info_length;
2225   tvbuff_t *parameter_tvb;
2226 
2227   cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
2228   parameter_tvb     = tvb_new_subset_length_caplen(cause_tvb, CAUSE_INFO_OFFSET,
2229                                      MIN(cause_info_length, tvb_captured_length_remaining(cause_tvb, CAUSE_INFO_OFFSET)),
2230                                      MIN(cause_info_length, tvb_reported_length_remaining(cause_tvb, CAUSE_INFO_OFFSET)));
2231   dissect_parameter(parameter_tvb, pinfo, cause_tree, NULL, FALSE, FALSE);
2232 }
2233 
2234 static void
dissect_delete_source_address_cause(tvbuff_t * cause_tvb,packet_info * pinfo,proto_tree * cause_tree,proto_item * cause_item)2235 dissect_delete_source_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
2236 {
2237   guint16 cause_info_length;
2238   tvbuff_t *parameter_tvb;
2239 
2240   cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
2241   parameter_tvb     = tvb_new_subset_length_caplen(cause_tvb, CAUSE_INFO_OFFSET,
2242                                      MIN(cause_info_length, tvb_captured_length_remaining(cause_tvb, CAUSE_INFO_OFFSET)),
2243                                      MIN(cause_info_length, tvb_reported_length_remaining(cause_tvb, CAUSE_INFO_OFFSET)));
2244   proto_item_append_text(cause_item, " (Deleted address: ");
2245   dissect_parameter(parameter_tvb, pinfo, cause_tree, cause_item, FALSE, FALSE);
2246   proto_item_append_text(cause_item, ")");
2247 }
2248 
2249 static void
dissect_request_refused_cause(tvbuff_t * cause_tvb,packet_info * pinfo,proto_tree * cause_tree)2250 dissect_request_refused_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree)
2251 {
2252   guint16 cause_info_length;
2253   tvbuff_t *parameter_tvb;
2254 
2255   cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
2256   parameter_tvb     = tvb_new_subset_length_caplen(cause_tvb, CAUSE_INFO_OFFSET,
2257                                      MIN(cause_info_length, tvb_captured_length_remaining(cause_tvb, CAUSE_INFO_OFFSET)),
2258                                      MIN(cause_info_length, tvb_reported_length_remaining(cause_tvb, CAUSE_INFO_OFFSET)));
2259   dissect_parameter(parameter_tvb, pinfo, cause_tree, NULL, FALSE, FALSE);
2260 }
2261 
2262 static void
dissect_unsupported_hmac_id_cause(tvbuff_t * cause_tvb,packet_info * pinfo _U_,proto_tree * cause_tree)2263 dissect_unsupported_hmac_id_cause(tvbuff_t *cause_tvb, packet_info *pinfo _U_, proto_tree *cause_tree)
2264 {
2265   proto_tree_add_item(cause_tree, hf_hmac_id, cause_tvb, CAUSE_INFO_OFFSET, HMAC_ID_LENGTH, ENC_BIG_ENDIAN);
2266 }
2267 
2268 static void
dissect_unknown_cause(tvbuff_t * cause_tvb,proto_tree * cause_tree,proto_item * cause_item)2269 dissect_unknown_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
2270 {
2271   guint16 cause_info_length;
2272 
2273   cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
2274   if (cause_info_length > 0)
2275     proto_tree_add_item(cause_tree, hf_cause_info, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, ENC_NA);
2276   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"));
2277 }
2278 
2279 #define INVALID_STREAM_IDENTIFIER                  0x01
2280 #define MISSING_MANDATORY_PARAMETERS               0x02
2281 #define STALE_COOKIE_ERROR                         0x03
2282 #define OUT_OF_RESOURCE                            0x04
2283 #define UNRESOLVABLE_ADDRESS                       0x05
2284 #define UNRECOGNIZED_CHUNK_TYPE                    0x06
2285 #define INVALID_MANDATORY_PARAMETER                0x07
2286 #define UNRECOGNIZED_PARAMETERS                    0x08
2287 #define NO_USER_DATA                               0x09
2288 #define COOKIE_RECEIVED_WHILE_SHUTTING_DOWN        0x0a
2289 #define RESTART_WITH_NEW_ADDRESSES                 0x0b
2290 #define USER_INITIATED_ABORT                       0x0c
2291 #define PROTOCOL_VIOLATION                         0x0d
2292 #define REQUEST_TO_DELETE_LAST_ADDRESS             0x00a0
2293 #define OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE 0x00a1
2294 #define REQUEST_TO_DELETE_SOURCE_ADDRESS           0x00a2
2295 #define ABORT_DUE_TO_ILLEGAL_ASCONF                0x00a3
2296 #define REQUEST_REFUSED                            0x00a4
2297 #define UNSUPPORTED_HMAC_ID                        0x0105
2298 
2299 static const value_string cause_code_values[] = {
2300   { INVALID_STREAM_IDENTIFIER,                  "Invalid stream identifier" },
2301   { MISSING_MANDATORY_PARAMETERS,               "Missing mandatory parameter" },
2302   { STALE_COOKIE_ERROR,                         "Stale cookie error" },
2303   { OUT_OF_RESOURCE,                            "Out of resource" },
2304   { UNRESOLVABLE_ADDRESS,                       "Unresolvable address" },
2305   { UNRECOGNIZED_CHUNK_TYPE,                    "Unrecognized chunk type" },
2306   { INVALID_MANDATORY_PARAMETER,                "Invalid mandatory parameter" },
2307   { UNRECOGNIZED_PARAMETERS,                    "Unrecognized parameters" },
2308   { NO_USER_DATA,                               "No user data" },
2309   { COOKIE_RECEIVED_WHILE_SHUTTING_DOWN,        "Cookie received while shutting down" },
2310   { RESTART_WITH_NEW_ADDRESSES,                 "Restart of an association with new addresses" },
2311   { USER_INITIATED_ABORT,                       "User initiated ABORT" },
2312   { PROTOCOL_VIOLATION,                         "Protocol violation" },
2313   { REQUEST_TO_DELETE_LAST_ADDRESS,             "Request to delete last address" },
2314   { OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE, "Operation refused due to resource shortage" },
2315   { REQUEST_TO_DELETE_SOURCE_ADDRESS,           "Request to delete source address" },
2316   { ABORT_DUE_TO_ILLEGAL_ASCONF,                "Association Aborted due to illegal ASCONF-ACK" },
2317   { REQUEST_REFUSED,                            "Request refused - no authorization" },
2318   { UNSUPPORTED_HMAC_ID,                        "Unsupported HMAC identifier" },
2319   { 0,                                          NULL } };
2320 
2321 
2322 static void
dissect_error_cause(tvbuff_t * cause_tvb,packet_info * pinfo,proto_tree * chunk_tree)2323 dissect_error_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *chunk_tree)
2324 {
2325   guint16 code, length, padding_length;
2326   proto_item *cause_item;
2327   proto_tree *cause_tree;
2328 
2329   code           = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET);
2330   length         = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
2331   padding_length = tvb_reported_length(cause_tvb) - length;
2332 
2333   cause_tree = proto_tree_add_subtree_format(chunk_tree, cause_tvb, CAUSE_HEADER_OFFSET, -1,
2334             ett_sctp_chunk_cause, &cause_item, "%s cause", val_to_str_const(code, cause_code_values, "Unknown"));
2335 
2336   proto_tree_add_item(cause_tree, hf_cause_code, cause_tvb,   CAUSE_CODE_OFFSET,   CAUSE_CODE_LENGTH,   ENC_BIG_ENDIAN);
2337   proto_tree_add_item(cause_tree, hf_cause_length, cause_tvb, CAUSE_LENGTH_OFFSET, CAUSE_LENGTH_LENGTH, ENC_BIG_ENDIAN);
2338   /* XXX - add expert info if length is bogus? */
2339 
2340   switch(code) {
2341   case INVALID_STREAM_IDENTIFIER:
2342     dissect_invalid_stream_identifier_cause(cause_tvb, cause_tree, cause_item);
2343     break;
2344   case MISSING_MANDATORY_PARAMETERS:
2345     dissect_missing_mandatory_parameters_cause(cause_tvb, cause_tree);
2346     break;
2347   case STALE_COOKIE_ERROR:
2348     dissect_stale_cookie_error_cause(cause_tvb, cause_tree, cause_item);
2349     break;
2350   case OUT_OF_RESOURCE:
2351     dissect_out_of_resource_cause(cause_tvb);
2352     break;
2353   case UNRESOLVABLE_ADDRESS:
2354     dissect_unresolvable_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
2355     break;
2356   case UNRECOGNIZED_CHUNK_TYPE:
2357     dissect_unrecognized_chunk_type_cause(cause_tvb, pinfo, cause_tree, cause_item);
2358     break;
2359   case INVALID_MANDATORY_PARAMETER:
2360     dissect_invalid_mandatory_parameter_cause(cause_tvb);
2361     break;
2362   case UNRECOGNIZED_PARAMETERS:
2363     dissect_unrecognized_parameters_cause(cause_tvb, pinfo, cause_tree);
2364     break;
2365   case NO_USER_DATA:
2366     dissect_no_user_data_cause(cause_tvb, cause_tree, cause_item);
2367     break;
2368   case COOKIE_RECEIVED_WHILE_SHUTTING_DOWN:
2369     dissect_cookie_received_while_shutting_down_cause(cause_tvb);
2370     break;
2371   case RESTART_WITH_NEW_ADDRESSES:
2372     dissect_restart_with_new_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
2373     break;
2374   case USER_INITIATED_ABORT:
2375     dissect_user_initiated_abort_cause(cause_tvb, cause_tree);
2376     break;
2377   case PROTOCOL_VIOLATION:
2378     dissect_protocol_violation_cause(cause_tvb, cause_tree);
2379     break;
2380   case REQUEST_TO_DELETE_LAST_ADDRESS:
2381     dissect_delete_last_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
2382     break;
2383   case OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE:
2384     dissect_resource_outage_cause(cause_tvb, pinfo, cause_tree);
2385     break;
2386   case REQUEST_TO_DELETE_SOURCE_ADDRESS:
2387     dissect_delete_source_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
2388     break;
2389   case REQUEST_REFUSED:
2390     dissect_request_refused_cause(cause_tvb, pinfo, cause_tree);
2391     break;
2392   case UNSUPPORTED_HMAC_ID:
2393     dissect_unsupported_hmac_id_cause(cause_tvb, pinfo, cause_tree);
2394     break;
2395   default:
2396     dissect_unknown_cause(cause_tvb, cause_tree, cause_item);
2397     break;
2398   }
2399 
2400   if (padding_length > 0)
2401     proto_tree_add_item(cause_tree, hf_cause_padding, cause_tvb, CAUSE_HEADER_OFFSET + length, padding_length, ENC_NA);
2402 }
2403 
2404 static void
dissect_error_causes(tvbuff_t * causes_tvb,packet_info * pinfo,proto_tree * tree)2405 dissect_error_causes(tvbuff_t *causes_tvb, packet_info *pinfo, proto_tree *tree)
2406 {
2407   gint offset, length, total_length, remaining_length;
2408   tvbuff_t *cause_tvb;
2409 
2410   offset = 0;
2411   while((remaining_length = tvb_reported_length_remaining(causes_tvb, offset))) {
2412     length       = tvb_get_ntohs(causes_tvb, offset + CAUSE_LENGTH_OFFSET);
2413     total_length = ADD_PADDING(length);
2414 
2415     /*  If we have less bytes than we need, throw an exception while dissecting
2416      *  the cause--not when generating the causes_tvb below.
2417      */
2418     total_length = MIN(total_length, remaining_length);
2419 
2420     /* create a tvb for the parameter including the padding bytes */
2421     cause_tvb    = tvb_new_subset_length_caplen(causes_tvb, offset, MIN(total_length, tvb_captured_length_remaining(causes_tvb, offset)), total_length);
2422 
2423     dissect_error_cause(cause_tvb, pinfo, tree);
2424 
2425     /* get rid of the handled cause */
2426     offset += total_length;
2427   }
2428 }
2429 
2430 
2431 /*
2432  * Code to actually dissect the packets
2433 */
2434 
2435 static gboolean try_heuristic_first = FALSE;
2436 
2437 static gboolean
dissect_payload(tvbuff_t * payload_tvb,packet_info * pinfo,proto_tree * tree,guint32 ppi)2438 dissect_payload(tvbuff_t *payload_tvb, packet_info *pinfo, proto_tree *tree, guint32 ppi)
2439 {
2440   guint32 low_port, high_port;
2441   heur_dtbl_entry_t *hdtbl_entry;
2442 
2443   if (enable_ulp_dissection) {
2444     if (try_heuristic_first) {
2445       /* do lookup with the heuristic subdissector table */
2446       if (dissector_try_heuristic(sctp_heur_subdissector_list, payload_tvb, pinfo, tree, &hdtbl_entry, GUINT_TO_POINTER(ppi)))
2447          return TRUE;
2448     }
2449 
2450     /* Do lookups with the subdissector table.
2451 
2452        When trying port numbers, we try the port number with the lower value
2453        first, followed by the port number with the higher value.  This means
2454        that, for packets where a dissector is registered for *both* port
2455        numbers, and where there's no match on the PPI:
2456 
2457     1) we pick the same dissector for traffic going in both directions;
2458 
2459     2) we prefer the port number that's more likely to be the right
2460        one (as that prefers well-known ports to reserved ports);
2461 
2462        although there is, of course, no guarantee that any such strategy
2463        will always pick the right port number.
2464 
2465        XXX - we ignore port numbers of 0, as some dissectors use a port
2466        number of 0 to disable the port. */
2467     if (dissector_try_uint_new(sctp_ppi_dissector_table, ppi, payload_tvb, pinfo, tree, TRUE, GUINT_TO_POINTER(ppi)))
2468       return TRUE;
2469     if (pinfo->srcport > pinfo->destport) {
2470       low_port = pinfo->destport;
2471       high_port = pinfo->srcport;
2472     } else {
2473       low_port = pinfo->srcport;
2474       high_port = pinfo->destport;
2475     }
2476     if (low_port != 0 &&
2477         dissector_try_uint_new(sctp_port_dissector_table, low_port, payload_tvb, pinfo, tree, TRUE, GUINT_TO_POINTER(ppi)))
2478       return TRUE;
2479     if (high_port != 0 &&
2480         dissector_try_uint_new(sctp_port_dissector_table, high_port, payload_tvb, pinfo, tree, TRUE, GUINT_TO_POINTER(ppi)))
2481       return TRUE;
2482 
2483     if (!try_heuristic_first) {
2484       /* do lookup with the heuristic subdissector table */
2485       if (dissector_try_heuristic(sctp_heur_subdissector_list, payload_tvb, pinfo, tree, &hdtbl_entry, GUINT_TO_POINTER(ppi)))
2486          return TRUE;
2487     }
2488   }
2489   /* Oh, well, we don't know this; dissect it as data. */
2490   call_data_dissector(payload_tvb, pinfo, tree);
2491   return TRUE;
2492 }
2493 
2494 #define DATA_CHUNK_TSN_LENGTH         4
2495 #define DATA_CHUNK_STREAM_ID_LENGTH   2
2496 #define DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH 2
2497 #define DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH 4
2498 #define I_DATA_CHUNK_RESERVED_LENGTH 2
2499 #define I_DATA_CHUNK_MID_LENGTH 4
2500 #define I_DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH 4
2501 #define I_DATA_CHUNK_FSN_LENGTH 4
2502 
2503 #define DATA_CHUNK_TSN_OFFSET         (CHUNK_VALUE_OFFSET + 0)
2504 #define DATA_CHUNK_STREAM_ID_OFFSET   (DATA_CHUNK_TSN_OFFSET + DATA_CHUNK_TSN_LENGTH)
2505 #define DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET (DATA_CHUNK_STREAM_ID_OFFSET + \
2506                                              DATA_CHUNK_STREAM_ID_LENGTH)
2507 #define DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET (DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET + \
2508                                                DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH)
2509 #define DATA_CHUNK_PAYLOAD_OFFSET     (DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET + \
2510                                        DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH)
2511 #define I_DATA_CHUNK_RESERVED_OFFSET  (DATA_CHUNK_STREAM_ID_OFFSET + \
2512                                        DATA_CHUNK_STREAM_ID_LENGTH)
2513 #define I_DATA_CHUNK_MID_OFFSET       (I_DATA_CHUNK_RESERVED_OFFSET + \
2514                                        I_DATA_CHUNK_RESERVED_LENGTH)
2515 #define I_DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET (I_DATA_CHUNK_MID_OFFSET + \
2516                                                  I_DATA_CHUNK_MID_LENGTH)
2517 #define I_DATA_CHUNK_FSN_OFFSET       (I_DATA_CHUNK_MID_OFFSET + \
2518                                        I_DATA_CHUNK_MID_LENGTH)
2519 #define I_DATA_CHUNK_PAYLOAD_OFFSET   (I_DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET + \
2520                                        I_DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH)
2521 
2522 #define DATA_CHUNK_HEADER_LENGTH      (CHUNK_HEADER_LENGTH + \
2523                                        DATA_CHUNK_TSN_LENGTH + \
2524                                        DATA_CHUNK_STREAM_ID_LENGTH + \
2525                                        DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH + \
2526                                        DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH)
2527 #define I_DATA_CHUNK_HEADER_LENGTH    (CHUNK_HEADER_LENGTH + \
2528                                        DATA_CHUNK_TSN_LENGTH + \
2529                                        DATA_CHUNK_STREAM_ID_LENGTH + \
2530                                        I_DATA_CHUNK_RESERVED_LENGTH + \
2531                                        I_DATA_CHUNK_MID_LENGTH +\
2532                                        I_DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH)
2533 
2534 #define SCTP_DATA_CHUNK_E_BIT 0x01
2535 #define SCTP_DATA_CHUNK_B_BIT 0x02
2536 #define SCTP_DATA_CHUNK_U_BIT 0x04
2537 #define SCTP_DATA_CHUNK_I_BIT 0x08
2538 
2539 /* table to hold fragmented SCTP messages */
2540 static GHashTable *frag_table = NULL;
2541 
2542 
2543 typedef struct _frag_key {
2544   guint16 sport;
2545   guint16 dport;
2546   guint32 verification_tag;
2547   guint16 stream_id;
2548   guint32 stream_seq_num;
2549   guint8 u_bit;
2550 } frag_key;
2551 
2552 
2553 static gint
frag_equal(gconstpointer k1,gconstpointer k2)2554 frag_equal(gconstpointer k1, gconstpointer k2)
2555 {
2556   const frag_key *key1 = (const frag_key *) k1;
2557   const frag_key *key2 = (const frag_key *) k2;
2558 
2559   return ( (key1->sport == key2->sport) &&
2560            (key1->dport == key2->dport) &&
2561            (key1->verification_tag == key2->verification_tag) &&
2562            (key1->stream_id == key2->stream_id) &&
2563            (key1->stream_seq_num == key2->stream_seq_num) &&
2564            (key1->u_bit == key2->u_bit)
2565            ? TRUE : FALSE);
2566 }
2567 
2568 
2569 static guint
frag_hash(gconstpointer k)2570 frag_hash(gconstpointer k)
2571 {
2572   const frag_key *key = (const frag_key *) k;
2573 
2574   return key->sport ^ key->dport ^ key->verification_tag ^
2575          key->stream_id ^ key->stream_seq_num ^ key->u_bit;
2576 }
2577 
2578 
2579 
2580 static void
frag_free_msgs(sctp_frag_msg * msg)2581 frag_free_msgs(sctp_frag_msg *msg)
2582 {
2583   sctp_frag_be *beginend;
2584   sctp_fragment *fragment;
2585 
2586   /* free all begins */
2587   while (msg->begins) {
2588     beginend = msg->begins;
2589     msg->begins = msg->begins->next;
2590     g_free(beginend);
2591   }
2592 
2593   /* free all ends */
2594   while (msg->ends) {
2595     beginend = msg->ends;
2596     msg->ends = msg->ends->next;
2597     g_free(beginend);
2598   }
2599 
2600   /* free all fragments */
2601   while (msg->fragments) {
2602     fragment = msg->fragments;
2603     msg->fragments = msg->fragments->next;
2604     g_free(fragment->data);
2605     g_free(fragment);
2606   }
2607 
2608   /* msg->messages is wmem_ allocated, no need to free it */
2609 
2610   g_free(msg);
2611 }
2612 
2613 static void
sctp_init(void)2614 sctp_init(void)
2615 {
2616   frag_table = g_hash_table_new_full(frag_hash, frag_equal,
2617       (GDestroyNotify)g_free, (GDestroyNotify)frag_free_msgs);
2618   num_assocs = 0;
2619   assoc_info_list = NULL;
2620 }
2621 
2622 static void
sctp_cleanup(void)2623 sctp_cleanup(void)
2624 {
2625   g_hash_table_destroy(frag_table);
2626 }
2627 
2628 
2629 static sctp_frag_msg*
find_message(guint16 stream_id,guint32 stream_seq_num,guint8 u_bit)2630 find_message(guint16 stream_id, guint32 stream_seq_num, guint8 u_bit)
2631 {
2632   frag_key key;
2633 
2634   key.sport = sctp_info.sport;
2635   key.dport = sctp_info.dport;
2636   key.verification_tag = sctp_info.verification_tag;
2637   key.stream_id = stream_id;
2638   key.stream_seq_num = stream_seq_num;
2639   key.u_bit = u_bit;
2640 
2641   return (sctp_frag_msg *)g_hash_table_lookup(frag_table, &key);
2642 }
2643 
2644 
2645 static sctp_fragment*
find_fragment(guint32 tsn,guint16 stream_id,guint32 stream_seq_num,guint8 u_bit)2646 find_fragment(guint32 tsn, guint16 stream_id, guint32 stream_seq_num, guint8 u_bit)
2647 {
2648   sctp_frag_msg *msg;
2649   sctp_fragment *next_fragment;
2650 
2651   msg = find_message(stream_id, stream_seq_num, u_bit);
2652 
2653   if (msg) {
2654     next_fragment = msg->fragments;
2655     while (next_fragment) {
2656       if (next_fragment->tsn == tsn)
2657         return next_fragment;
2658       next_fragment = next_fragment->next;
2659     }
2660   }
2661 
2662   return NULL;
2663 }
2664 
2665 
2666 static sctp_fragment *
add_fragment(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint32 tsn,guint16 stream_id,guint32 stream_seq_num,guint8 b_bit,guint8 e_bit,guint8 u_bit,guint32 ppi,gboolean is_idata)2667 add_fragment(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 tsn,
2668              guint16 stream_id, guint32 stream_seq_num, guint8 b_bit, guint8 e_bit,
2669              guint8 u_bit, guint32 ppi, gboolean is_idata)
2670 {
2671   sctp_frag_msg *msg;
2672   sctp_fragment *fragment, *last_fragment;
2673   sctp_frag_be *beginend, *last_beginend;
2674   frag_key *key;
2675 
2676   /* Don't try to do reassembly on error packets */
2677   if (pinfo->flags.in_error_pkt)
2678     return NULL;
2679 
2680   /* lookup message. if not found, create it */
2681   msg = find_message(stream_id, stream_seq_num, u_bit);
2682 
2683   if (!msg) {
2684     msg = g_new(sctp_frag_msg, 1);
2685     msg->begins = NULL;
2686     msg->ends = NULL;
2687     msg->fragments = NULL;
2688     msg->messages = NULL;
2689     msg->next = NULL;
2690     if (is_idata)
2691       if (b_bit)
2692         msg->ppi = ppi;
2693       else
2694         msg->ppi = 0;
2695     else
2696       msg->ppi = ppi;
2697 
2698     key = g_new(frag_key, 1);
2699     key->sport = sctp_info.sport;
2700     key->dport = sctp_info.dport;
2701     key->verification_tag = sctp_info.verification_tag;
2702     key->stream_id = stream_id;
2703     key->stream_seq_num = stream_seq_num;
2704     key->u_bit = u_bit;
2705 
2706     g_hash_table_insert(frag_table, key, msg);
2707   } else {
2708       if (b_bit)
2709         msg->ppi = ppi;
2710   }
2711 
2712   /* lookup segment. if not found, create it */
2713   fragment = find_fragment(tsn, stream_id, stream_seq_num, u_bit);
2714 
2715   if (fragment) {
2716     /* this fragment is already known.
2717      * compare frame number to check if it's a duplicate
2718      */
2719     if (fragment->frame_num == pinfo->num) {
2720       return fragment;
2721     } else {
2722       /* There already is a fragment having the same ports, v_tag,
2723        * stream id, stream_seq_num and tsn but it appeared in a different
2724        * frame, so it must be a duplicate fragment. Maybe a retransmission?
2725        * Mark it as duplicate and return NULL.
2726        *
2727        * Note: This won't happen if TSN analysis is on: the caller will have
2728        * detected the retransmission and not pass it to the reassembly code.
2729        */
2730       col_append_str(pinfo->cinfo, COL_INFO, "(Duplicate Message Fragment) ");
2731 
2732       proto_tree_add_uint(tree, hf_sctp_duplicate, tvb, 0, 0, fragment->frame_num);
2733       return NULL;
2734     }
2735   }
2736 
2737   /* There is no point in storing a fragment with no data in it */
2738   if (tvb_captured_length(tvb) == 0)
2739     return NULL;
2740 
2741   /* create new fragment */
2742   fragment = g_new(sctp_fragment, 1);
2743   fragment->frame_num = pinfo->num;
2744   fragment->tsn = tsn;
2745   fragment->len = tvb_captured_length(tvb);
2746   fragment->ppi = msg->ppi;
2747   fragment->next = NULL;
2748   fragment->data = (unsigned char *)g_malloc (fragment->len);
2749   tvb_memcpy(tvb, fragment->data, 0, fragment->len);
2750 
2751   /* add new fragment to linked list. sort ascending by tsn */
2752   if (!msg->fragments)
2753     msg->fragments = fragment;
2754   else {
2755     if (msg->fragments->tsn > fragment->tsn) {
2756       fragment->next = msg->fragments;
2757       msg->fragments = fragment;
2758     } else {
2759         last_fragment = msg->fragments;
2760         while (last_fragment->next &&
2761                last_fragment->next->tsn < fragment->tsn)
2762           last_fragment = last_fragment->next;
2763 
2764         fragment->next = last_fragment->next;
2765         last_fragment->next = fragment;
2766     }
2767   }
2768 
2769 
2770   /* save begin or end if necessary */
2771   if (b_bit && !e_bit) {
2772     beginend = g_new(sctp_frag_be, 1);
2773     beginend->fragment = fragment;
2774     beginend->next = NULL;
2775 
2776     /* add begin to linked list. sort descending by tsn */
2777     if (!msg->begins)
2778       msg->begins = beginend;
2779     else {
2780       if (msg->begins->fragment->tsn < beginend->fragment->tsn) {
2781         beginend->next = msg->begins;
2782         msg->begins = beginend;
2783       } else {
2784         last_beginend = msg->begins;
2785         while (last_beginend->next &&
2786                last_beginend->next->fragment->tsn > beginend->fragment->tsn)
2787           last_beginend = last_beginend->next;
2788 
2789         beginend->next = last_beginend->next;
2790        last_beginend->next = beginend;
2791       }
2792     }
2793 
2794   }
2795 
2796   if (!b_bit && e_bit) {
2797     beginend = g_new(sctp_frag_be, 1);
2798     beginend->fragment = fragment;
2799     beginend->next = NULL;
2800 
2801     /* add end to linked list. sort ascending by tsn */
2802     if (!msg->ends)
2803       msg->ends = beginend;
2804     else {
2805       if (msg->ends->fragment->tsn > beginend->fragment->tsn) {
2806         beginend->next = msg->ends;
2807         msg->ends = beginend;
2808       } else {
2809         last_beginend = msg->ends;
2810         while (last_beginend->next &&
2811                last_beginend->next->fragment->tsn < beginend->fragment->tsn)
2812           last_beginend = last_beginend->next;
2813 
2814         beginend->next = last_beginend->next;
2815         last_beginend->next = beginend;
2816       }
2817     }
2818 
2819   }
2820 
2821   return fragment;
2822 }
2823 
2824 static tvbuff_t*
fragment_reassembly(tvbuff_t * tvb,sctp_fragment * fragment,packet_info * pinfo,proto_tree * tree,guint16 stream_id,guint32 stream_seq_num,guint8 u_bit)2825 fragment_reassembly(tvbuff_t *tvb, sctp_fragment *fragment,
2826                     packet_info *pinfo, proto_tree *tree, guint16 stream_id,
2827                     guint32 stream_seq_num, guint8 u_bit)
2828 {
2829   sctp_frag_msg *msg;
2830   sctp_complete_msg *message, *last_message;
2831   sctp_fragment *frag_i, *last_frag, *first_frag;
2832   sctp_frag_be *begin, *end, *beginend;
2833   guint32 len, offset = 0;
2834   tvbuff_t *new_tvb = NULL;
2835   proto_item *item;
2836   proto_tree *ptree;
2837 
2838   msg = find_message(stream_id, stream_seq_num, u_bit);
2839 
2840   if (!msg) {
2841     /* no message, we can't do anything */
2842     return NULL;
2843   }
2844 
2845   /* check if fragment is part of an already reassembled message */
2846   for (message = msg->messages;
2847        message &&
2848        !(message->begin <= fragment->tsn && message->end >= fragment->tsn) &&
2849        !(message->begin > message->end &&
2850        (message->begin <= fragment->tsn || message->end >= fragment->tsn));
2851          message = message->next);
2852 
2853   if (message) {
2854     /* we found the reassembled message this fragment belongs to */
2855     if (fragment == message->reassembled_in) {
2856 
2857       /* this is the last fragment, create data source */
2858       new_tvb = tvb_new_child_real_data(tvb, message->data, message->len, message->len);
2859       add_new_data_source(pinfo, new_tvb, "Reassembled SCTP Message");
2860 
2861       /* display reassembly info */
2862       item = proto_tree_add_item(tree, hf_sctp_fragments, tvb, 0, -1, ENC_NA);
2863       ptree = proto_item_add_subtree(item, ett_sctp_fragments);
2864       proto_item_append_text(item, " (%u bytes, %u fragments): ",
2865                              message->len, message->end - message->begin + 1);
2866 
2867       if (message->begin > message->end) {
2868         for (frag_i = find_fragment(message->begin, stream_id, stream_seq_num, u_bit);
2869              frag_i;
2870              frag_i = frag_i->next) {
2871 
2872           proto_tree_add_uint_format(ptree, hf_sctp_fragment, new_tvb, offset, frag_i->len,
2873                                      frag_i->frame_num, "Frame: %u, payload: %u-%u (%u bytes)",
2874                                      frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
2875           offset += frag_i->len;
2876 
2877           mark_frame_as_depended_upon(pinfo, frag_i->frame_num);
2878         }
2879 
2880         for (frag_i = msg->fragments;
2881              frag_i && frag_i->tsn <= message->end;
2882              frag_i = frag_i->next) {
2883 
2884           proto_tree_add_uint_format(ptree, hf_sctp_fragment, new_tvb, offset, frag_i->len,
2885                                      frag_i->frame_num, "Frame: %u, payload: %u-%u (%u bytes)",
2886                                      frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
2887           offset += frag_i->len;
2888 
2889           mark_frame_as_depended_upon(pinfo, frag_i->frame_num);
2890         }
2891       } else {
2892         for (frag_i = find_fragment(message->begin, stream_id, stream_seq_num, u_bit);
2893              frag_i && frag_i->tsn <= message->end;
2894              frag_i = frag_i->next) {
2895 
2896           proto_tree_add_uint_format(ptree, hf_sctp_fragment, new_tvb, offset, frag_i->len,
2897                                      frag_i->frame_num, "Frame: %u, payload: %u-%u (%u bytes)",
2898                                      frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
2899           offset += frag_i->len;
2900 
2901           mark_frame_as_depended_upon(pinfo, frag_i->frame_num);
2902         }
2903       }
2904 
2905       return new_tvb;
2906     }
2907 
2908     /* this is not the last fragment,
2909      * so let the user know the frame where the reassembly is
2910      */
2911     col_append_str(pinfo->cinfo, COL_INFO, "(Message Fragment) ");
2912 
2913     proto_tree_add_uint(tree, hf_sctp_reassembled_in, tvb, 0, 0, message->reassembled_in->frame_num);
2914     return NULL;
2915   }
2916 
2917   /* this fragment has not been reassembled, yet
2918    * check now if we can reassemble it
2919    * at first look for the first and last tsn of the msg
2920    */
2921   for (begin = msg->begins;
2922        begin && begin->fragment->tsn > fragment->tsn;
2923        begin = begin->next);
2924 
2925   /* in case begin still is null, set it to first (highest) begin
2926    * maybe the message tsn restart at 0 in between
2927    */
2928   if (!begin)
2929     begin = msg->begins;
2930 
2931   for (end = msg->ends;
2932        end && end->fragment->tsn < fragment->tsn;
2933        end = end->next);
2934 
2935   /* in case end still is null, set it to first (lowest) end
2936    * maybe the message tsn restart at 0 in between
2937    */
2938   if (!end)
2939     end = msg->ends;
2940 
2941   if (!begin || !end || !msg->fragments ||
2942       (begin->fragment->tsn > end->fragment->tsn && msg->fragments->tsn)) {
2943     /* begin and end have not been collected, yet
2944      * or there might be a tsn restart but the first fragment hasn't a tsn of 0
2945      * just mark as fragment
2946      */
2947 
2948     col_append_str(pinfo->cinfo, COL_INFO, "(Message Fragment) ");
2949 
2950     return NULL;
2951   }
2952 
2953   /* we found possible begin and end
2954    * look for the first fragment and then try to get to the end
2955    */
2956   first_frag = begin->fragment;
2957 
2958   /* while looking if all fragments are there
2959    * we can calculate the overall length that
2960    * we need in case of success
2961    */
2962   len = first_frag->len;
2963 
2964   /* check if begin is past end
2965    * this can happen if there has been a tsn restart
2966    * or we just got the wrong begin and end
2967    * so give it a try
2968   */
2969   if (begin->fragment->tsn > end->fragment->tsn) {
2970     for (last_frag = first_frag, frag_i = first_frag->next;
2971          frag_i && frag_i->tsn == (last_frag->tsn + 1);
2972          last_frag = frag_i, frag_i = frag_i->next) len += frag_i->len;
2973 
2974     /* check if we reached the last possible tsn
2975      * if yes, restart and continue
2976      */
2977     if ((last_frag->tsn + 1)) {
2978       /* there are just fragments missing */
2979       col_append_str(pinfo->cinfo, COL_INFO, "(Message Fragment) ");
2980 
2981       return NULL;
2982     }
2983 
2984     /* we got all fragments until the last possible tsn
2985      * and the first is 0 if we got here
2986      */
2987 
2988     len += msg->fragments->len;
2989     for (last_frag = msg->fragments, frag_i = last_frag->next;
2990          frag_i && frag_i->tsn < end->fragment->tsn && frag_i->tsn == (last_frag->tsn + 1);
2991          last_frag = frag_i, frag_i = frag_i->next) len += frag_i->len;
2992 
2993   } else {
2994     for (last_frag = first_frag, frag_i = first_frag->next;
2995          frag_i && frag_i->tsn < end->fragment->tsn && frag_i->tsn == (last_frag->tsn + 1);
2996          last_frag = frag_i, frag_i = frag_i->next) len += frag_i->len;
2997   }
2998 
2999   if (!frag_i || frag_i != end->fragment || frag_i->tsn != (last_frag->tsn + 1)) {
3000     /* we need more fragments. just mark as fragment */
3001     col_append_str(pinfo->cinfo, COL_INFO, "(Message Fragment) ");
3002 
3003     return NULL;
3004   }
3005 
3006   /* ok, this message is complete, we can reassemble it
3007    * but at first don't forget to add the length of the last fragment
3008    */
3009   len += frag_i->len;
3010 
3011   message = wmem_new(wmem_file_scope(), sctp_complete_msg);
3012   message->begin = begin->fragment->tsn;
3013   message->end = end->fragment->tsn;
3014   message->reassembled_in = fragment;
3015   message->len = len;
3016   message->data = (unsigned char *)wmem_alloc(wmem_file_scope(), len);
3017   message->next = NULL;
3018 
3019   /* now copy all fragments */
3020   if (begin->fragment->tsn > end->fragment->tsn) {
3021     /* a tsn restart has occurred */
3022     for (frag_i = first_frag;
3023          frag_i;
3024          frag_i = frag_i->next) {
3025 
3026       if (frag_i->len && frag_i->data)
3027         memcpy(message->data + offset, frag_i->data, frag_i->len);
3028       offset += frag_i->len;
3029 
3030       /* release fragment data */
3031       g_free(frag_i->data);
3032       frag_i->data = NULL;
3033     }
3034 
3035     for (frag_i = msg->fragments;
3036          frag_i && frag_i->tsn <= end->fragment->tsn;
3037          frag_i = frag_i->next) {
3038 
3039       if (frag_i->len && frag_i->data)
3040         memcpy(message->data + offset, frag_i->data, frag_i->len);
3041       offset += frag_i->len;
3042 
3043       /* release fragment data */
3044       g_free(frag_i->data);
3045       frag_i->data = NULL;
3046     }
3047 
3048   } else {
3049     for (frag_i = first_frag;
3050          frag_i && frag_i->tsn <= end->fragment->tsn;
3051          frag_i = frag_i->next) {
3052 
3053       if (frag_i->len && frag_i->data)
3054         memcpy(message->data + offset, frag_i->data, frag_i->len);
3055       offset += frag_i->len;
3056 
3057       /* release fragment data */
3058       g_free(frag_i->data);
3059       frag_i->data = NULL;
3060     }
3061   }
3062 
3063   /* save message */
3064   if (!msg->messages) {
3065     msg->messages = message;
3066   } else {
3067     for (last_message = msg->messages;
3068          last_message->next;
3069          last_message = last_message->next);
3070     last_message->next = message;
3071   }
3072 
3073   /* remove begin and end from list */
3074   if (msg->begins == begin) {
3075     msg->begins = begin->next;
3076   } else {
3077     for (beginend = msg->begins;
3078          beginend && beginend->next != begin;
3079          beginend = beginend->next);
3080     if (beginend && beginend->next == begin)
3081       beginend->next = begin->next;
3082   }
3083   g_free(begin);
3084 
3085   if (msg->ends == end) {
3086     msg->ends = end->next;
3087   } else {
3088     for (beginend = msg->ends;
3089          beginend && beginend->next != end;
3090          beginend = beginend->next);
3091     if (beginend && beginend->next == end)
3092       beginend->next = end->next;
3093   }
3094    g_free(end);
3095 
3096   /* create data source */
3097   new_tvb = tvb_new_child_real_data(tvb, message->data, len, len);
3098   add_new_data_source(pinfo, new_tvb, "Reassembled SCTP Message");
3099 
3100   /* display reassembly info */
3101   item = proto_tree_add_item(tree, hf_sctp_fragments, tvb, 0, -1, ENC_NA);
3102   ptree = proto_item_add_subtree(item, ett_sctp_fragments);
3103   proto_item_append_text(item, " (%u bytes, %u fragments): ",
3104                          message->len, message->end - message->begin + 1);
3105 
3106   if (message->begin > message->end) {
3107     for (frag_i = find_fragment(message->begin, stream_id, stream_seq_num, u_bit);
3108          frag_i;
3109          frag_i = frag_i->next) {
3110 
3111       proto_tree_add_uint_format(ptree, hf_sctp_fragment, new_tvb, offset, frag_i->len,
3112                                  frag_i->frame_num, "Frame: %u, payload: %u-%u (%u bytes)",
3113                                  frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
3114       offset += frag_i->len;
3115 
3116       mark_frame_as_depended_upon(pinfo, frag_i->frame_num);
3117     }
3118 
3119     for (frag_i = msg->fragments;
3120          frag_i && frag_i->tsn <= message->end;
3121          frag_i = frag_i->next) {
3122 
3123       proto_tree_add_uint_format(ptree, hf_sctp_fragment, new_tvb, offset, frag_i->len,
3124                                  frag_i->frame_num, "Frame: %u, payload: %u-%u (%u bytes)",
3125                                  frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
3126       offset += frag_i->len;
3127 
3128       mark_frame_as_depended_upon(pinfo, frag_i->frame_num);
3129     }
3130   } else {
3131     for (frag_i = find_fragment(message->begin, stream_id, stream_seq_num, u_bit);
3132          frag_i && frag_i->tsn <= message->end;
3133          frag_i = frag_i->next) {
3134 
3135       proto_tree_add_uint_format(ptree, hf_sctp_fragment, new_tvb, offset, frag_i->len,
3136                                  frag_i->frame_num, "Frame: %u, payload: %u-%u (%u bytes)",
3137                                  frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
3138       offset += frag_i->len;
3139 
3140       mark_frame_as_depended_upon(pinfo, frag_i->frame_num);
3141     }
3142   }
3143 
3144   /* it's not fragmented anymore */
3145   pinfo->fragmented = FALSE;
3146 
3147   return new_tvb;
3148 }
3149 
3150 static exp_pdu_data_t*
create_exp_pdu_table(packet_info * pinfo,tvbuff_t * tvb,const char * table_name,guint32 table_value)3151 create_exp_pdu_table(packet_info *pinfo, tvbuff_t *tvb, const char *table_name, guint32 table_value)
3152 {
3153   exp_pdu_data_item_t exp_pdu_data_table_value = {
3154     exp_pdu_data_dissector_table_num_value_size,
3155     exp_pdu_data_dissector_table_num_value_populate_data,
3156     GUINT_TO_POINTER(table_value)
3157   };
3158 
3159   const exp_pdu_data_item_t *sctp_exp_pdu_items[] = {
3160     &exp_pdu_data_src_ip,
3161     &exp_pdu_data_dst_ip,
3162     &exp_pdu_data_port_type,
3163     &exp_pdu_data_src_port,
3164     &exp_pdu_data_dst_port,
3165     &exp_pdu_data_orig_frame_num,
3166     &exp_pdu_data_table_value,
3167     NULL
3168   };
3169 
3170   exp_pdu_data_t *exp_pdu_data = export_pdu_create_tags(pinfo, table_name, EXP_PDU_TAG_DISSECTOR_TABLE_NAME, sctp_exp_pdu_items);
3171 
3172   exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb);
3173   exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb);
3174   exp_pdu_data->pdu_tvb = tvb;
3175 
3176   return exp_pdu_data;
3177 }
3178 
3179 static exp_pdu_data_t*
create_exp_pdu_proto_name(packet_info * pinfo,tvbuff_t * tvb,const gchar * proto_name)3180 create_exp_pdu_proto_name(packet_info *pinfo, tvbuff_t *tvb, const gchar *proto_name)
3181 {
3182   exp_pdu_data_t *exp_pdu_data = export_pdu_create_common_tags(pinfo, proto_name, EXP_PDU_TAG_PROTO_NAME);
3183 
3184   exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb);
3185   exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb);
3186   exp_pdu_data->pdu_tvb = tvb;
3187 
3188   return exp_pdu_data;
3189 }
3190 
3191 static void
export_sctp_data_chunk(packet_info * pinfo,tvbuff_t * tvb,guint32 payload_proto_id,const wmem_list_frame_t * frame)3192 export_sctp_data_chunk(packet_info *pinfo, tvbuff_t *tvb, guint32 payload_proto_id,
3193                        const wmem_list_frame_t *frame)
3194 {
3195   const gchar *proto_name = NULL;
3196   exp_pdu_data_t *exp_pdu_data = NULL;
3197 
3198   if (!have_tap_listener(exported_pdu_tap)) {
3199     /* Do nothing when there is no export pdu tap listener */
3200     return;
3201   }
3202 
3203   if (enable_ulp_dissection && frame) {
3204     /* get the proto_name of the next frame */
3205     proto_name = proto_get_protocol_filter_name(GPOINTER_TO_UINT(wmem_list_frame_data(frame)));
3206   }
3207 
3208   if (proto_name && (strcmp(proto_name, "data") != 0)) {
3209     /* when we have proto_name and it is not "data" export using the proto_name */
3210     exp_pdu_data = create_exp_pdu_proto_name(pinfo, tvb, proto_name);
3211   } else if (payload_proto_id != 0) {
3212     exp_pdu_data = create_exp_pdu_table(pinfo, tvb, "sctp.ppi", payload_proto_id);
3213   } else if (pinfo->destport != 0) {
3214     exp_pdu_data = create_exp_pdu_table(pinfo, tvb, "sctp.port", pinfo->destport);
3215   } else if (pinfo->srcport != 0) {
3216     exp_pdu_data = create_exp_pdu_table(pinfo, tvb, "sctp.port", pinfo->srcport);
3217   } else {
3218     /* do not export anything when none of the above fileds are available */
3219     return;
3220   }
3221 
3222   tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data);
3223 }
3224 
3225 static gboolean
dissect_fragmented_payload(tvbuff_t * payload_tvb,packet_info * pinfo,proto_tree * tree,proto_tree * chunk_tree,guint32 tsn,guint32 ppi,guint16 stream_id,guint32 stream_seq_num,guint8 b_bit,guint8 e_bit,guint8 u_bit,gboolean is_idata)3226 dissect_fragmented_payload(tvbuff_t *payload_tvb, packet_info *pinfo, proto_tree *tree,
3227                            proto_tree *chunk_tree, guint32 tsn, guint32 ppi, guint16 stream_id,
3228                            guint32 stream_seq_num, guint8 b_bit, guint8 e_bit, guint8 u_bit, gboolean is_idata)
3229 {
3230   sctp_fragment *fragment;
3231   tvbuff_t *new_tvb = NULL;
3232 
3233   /*
3234    * If this is a short frame, then we can't, and don't, do
3235    * reassembly on it.  We just give up.
3236    */
3237   if (tvb_reported_length(payload_tvb) > tvb_captured_length(payload_tvb))
3238     return TRUE;
3239 
3240   /* add fragment to list of known fragments. returns NULL if segment is a duplicate */
3241   fragment = add_fragment(payload_tvb, pinfo, chunk_tree, tsn, stream_id, stream_seq_num, b_bit, e_bit, u_bit, ppi, is_idata);
3242 
3243   if (fragment)
3244     new_tvb = fragment_reassembly(payload_tvb, fragment, pinfo, chunk_tree, stream_id, stream_seq_num, u_bit);
3245 
3246   /* pass reassembled data to next dissector, if possible */
3247   if (new_tvb){
3248     gboolean retval;
3249     wmem_list_frame_t *cur = wmem_list_tail(pinfo->layers);
3250 
3251     retval = dissect_payload(new_tvb, pinfo, tree, ppi);
3252     export_sctp_data_chunk(pinfo, new_tvb, ppi, wmem_list_frame_next(cur));
3253     return retval;
3254   }
3255 
3256   /* no reassembly done, do nothing */
3257   return TRUE;
3258 }
3259 
3260 static const true_false_string sctp_data_chunk_e_bit_value = {
3261   "Last segment",
3262   "Not the last segment"
3263 };
3264 
3265 static const true_false_string sctp_data_chunk_b_bit_value = {
3266   "First segment",
3267   "Subsequent segment"
3268 };
3269 
3270 static const true_false_string sctp_data_chunk_u_bit_value = {
3271   "Unordered delivery",
3272   "Ordered delivery"
3273 };
3274 
3275 static const true_false_string sctp_data_chunk_i_bit_value = {
3276   "Send SACK immediately",
3277   "Possibly delay SACK"
3278 };
3279 
3280 static gboolean
dissect_data_chunk(tvbuff_t * chunk_tvb,guint16 chunk_length,packet_info * pinfo,proto_tree * tree,proto_tree * chunk_tree,proto_item * chunk_item,proto_item * flags_item,sctp_half_assoc_t * ha,gboolean is_idata)3281 dissect_data_chunk(tvbuff_t *chunk_tvb,
3282                    guint16 chunk_length,
3283                    packet_info *pinfo,
3284                    proto_tree *tree,
3285                    proto_tree *chunk_tree,
3286                    proto_item *chunk_item,
3287                    proto_item *flags_item,
3288                    sctp_half_assoc_t *ha,
3289                    gboolean is_idata)
3290 {
3291   guint number_of_ppid;
3292   volatile guint32 payload_proto_id;
3293   tvbuff_t *payload_tvb;
3294   proto_tree *flags_tree;
3295   guint8 oct, e_bit, b_bit, u_bit;
3296   guint16 stream_id;
3297   guint32 tsn, ppid, stream_seq_num = 0;
3298   proto_item *tsn_item = NULL;
3299   gboolean call_subdissector = FALSE;
3300   gboolean is_retransmission;
3301   guint16 header_length;
3302   guint16 payload_offset;
3303 
3304   static int* const chunk_flags[] = {
3305     &hf_data_chunk_i_bit,
3306     &hf_data_chunk_u_bit,
3307     &hf_data_chunk_b_bit,
3308     &hf_data_chunk_e_bit,
3309     NULL
3310   };
3311 
3312   if (is_idata) {
3313     if (chunk_length < I_DATA_CHUNK_HEADER_LENGTH) {
3314       proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)", chunk_length, I_DATA_CHUNK_HEADER_LENGTH);
3315       return TRUE;
3316     }
3317     payload_proto_id = tvb_get_ntohl(chunk_tvb, I_DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET);
3318   } else {
3319     if (chunk_length < DATA_CHUNK_HEADER_LENGTH) {
3320       proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)", chunk_length, DATA_CHUNK_HEADER_LENGTH);
3321       return TRUE;
3322     }
3323     payload_proto_id = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET);
3324   }
3325 
3326   /* insert the PPID in the pinfo structure if it is not already there and there is still room */
3327   for(number_of_ppid = 0; number_of_ppid < MAX_NUMBER_OF_PPIDS; number_of_ppid++) {
3328     void *tmp = p_get_proto_data(pinfo->pool, pinfo, proto_sctp, number_of_ppid);
3329     ppid = GPOINTER_TO_UINT(tmp);
3330     if ((ppid == LAST_PPID) || (ppid == payload_proto_id))
3331       break;
3332   }
3333   if ((number_of_ppid < MAX_NUMBER_OF_PPIDS) && (ppid == LAST_PPID))
3334     p_add_proto_data(pinfo->pool, pinfo, proto_sctp, number_of_ppid, GUINT_TO_POINTER(payload_proto_id));
3335 
3336   oct = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
3337   e_bit = oct & SCTP_DATA_CHUNK_E_BIT;
3338   b_bit = oct & SCTP_DATA_CHUNK_B_BIT;
3339   u_bit = oct & SCTP_DATA_CHUNK_U_BIT;
3340 
3341   tsn = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_TSN_OFFSET);
3342   if((show_relative_tsns) && (ha)) {
3343      tsn -= ha->first_tsn;
3344   }
3345 
3346   col_append_fstr(pinfo->cinfo, COL_INFO, "(TSN=%" G_GUINT32_FORMAT ") ", tsn);
3347 
3348   if (chunk_tree) {
3349     if (is_idata)
3350       proto_item_set_len(chunk_item, I_DATA_CHUNK_HEADER_LENGTH);
3351     else
3352       proto_item_set_len(chunk_item, DATA_CHUNK_HEADER_LENGTH);
3353 
3354     flags_tree  = proto_item_add_subtree(flags_item, ett_sctp_data_chunk_flags);
3355     proto_tree_add_bitmask_list(flags_tree, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, chunk_flags, ENC_NA);
3356     if((show_relative_tsns) && (ha)) {
3357        tsn_item = proto_tree_add_uint(chunk_tree, hf_data_chunk_tsn, chunk_tvb, DATA_CHUNK_TSN_OFFSET, DATA_CHUNK_TSN_LENGTH, tsn);
3358        proto_tree_add_item(chunk_tree, hf_data_chunk_tsn_raw, chunk_tvb, DATA_CHUNK_TSN_OFFSET, DATA_CHUNK_TSN_LENGTH, ENC_BIG_ENDIAN);
3359     }
3360     else {
3361        tsn_item = proto_tree_add_item(chunk_tree, hf_data_chunk_tsn_raw, chunk_tvb, DATA_CHUNK_TSN_OFFSET, DATA_CHUNK_TSN_LENGTH, ENC_BIG_ENDIAN);
3362     }
3363     proto_tree_add_item(chunk_tree, hf_data_chunk_stream_id,          chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET, DATA_CHUNK_STREAM_ID_LENGTH, ENC_BIG_ENDIAN);
3364     if (is_idata) {
3365       proto_tree_add_item(chunk_tree, hf_idata_chunk_reserved, chunk_tvb, I_DATA_CHUNK_RESERVED_OFFSET, I_DATA_CHUNK_RESERVED_LENGTH, ENC_BIG_ENDIAN);
3366       proto_tree_add_item(chunk_tree, hf_idata_chunk_mid, chunk_tvb, I_DATA_CHUNK_MID_OFFSET, I_DATA_CHUNK_MID_LENGTH, ENC_BIG_ENDIAN);
3367       if (b_bit)
3368         proto_tree_add_item(chunk_tree, hf_data_chunk_payload_proto_id, chunk_tvb, I_DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET, I_DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH, ENC_BIG_ENDIAN);
3369       else
3370         proto_tree_add_item(chunk_tree, hf_idata_chunk_fsn, chunk_tvb, I_DATA_CHUNK_FSN_OFFSET, I_DATA_CHUNK_FSN_LENGTH, ENC_BIG_ENDIAN);
3371     } else {
3372       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,   ENC_BIG_ENDIAN);
3373       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, ENC_BIG_ENDIAN);
3374     }
3375     proto_item_append_text(chunk_item, " (%s, ", (u_bit) ? "unordered" : "ordered");
3376     if (b_bit) {
3377       if (e_bit)
3378         proto_item_append_text(chunk_item, "complete");
3379       else
3380         proto_item_append_text(chunk_item, "first");
3381     } else {
3382       if (e_bit)
3383         proto_item_append_text(chunk_item, "last");
3384       else
3385         proto_item_append_text(chunk_item, "middle");
3386     }
3387 
3388     if (is_idata) {
3389       if (b_bit)
3390         proto_item_append_text(chunk_item, " segment, TSN: %u, SID: %u, MID: %u, payload length: %u byte%s)",
3391                                tsn,
3392                                tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET),
3393                                tvb_get_ntohl(chunk_tvb, I_DATA_CHUNK_MID_OFFSET),
3394                                chunk_length - I_DATA_CHUNK_HEADER_LENGTH, plurality(chunk_length - I_DATA_CHUNK_HEADER_LENGTH, "", "s"));
3395       else
3396         proto_item_append_text(chunk_item, " segment, TSN: %u, SID: %u, MID: %u, FSN: %u, payload length: %u byte%s)",
3397                                tsn,
3398                                tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET),
3399                                tvb_get_ntohl(chunk_tvb, I_DATA_CHUNK_MID_OFFSET),
3400                                tvb_get_ntohl(chunk_tvb, I_DATA_CHUNK_FSN_OFFSET),
3401                                chunk_length - I_DATA_CHUNK_HEADER_LENGTH, plurality(chunk_length - I_DATA_CHUNK_HEADER_LENGTH, "", "s"));
3402     } else
3403       proto_item_append_text(chunk_item, " segment, TSN: %u, SID: %u, SSN: %u, PPID: %u, payload length: %u byte%s)",
3404                              tsn,
3405                              tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET),
3406                              tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET),
3407                              payload_proto_id,
3408                              chunk_length - DATA_CHUNK_HEADER_LENGTH, plurality(chunk_length - DATA_CHUNK_HEADER_LENGTH, "", "s"));
3409   }
3410 
3411   is_retransmission = sctp_tsn(pinfo, chunk_tvb, tsn_item, ha, tsn);
3412 
3413   if (is_idata) {
3414     header_length = I_DATA_CHUNK_HEADER_LENGTH;
3415     payload_offset = I_DATA_CHUNK_PAYLOAD_OFFSET;
3416   } else {
3417     header_length = DATA_CHUNK_HEADER_LENGTH;
3418     payload_offset = DATA_CHUNK_PAYLOAD_OFFSET;
3419   }
3420   payload_tvb = tvb_new_subset_length_caplen(chunk_tvb, payload_offset,
3421                                  MIN(chunk_length - header_length, tvb_captured_length_remaining(chunk_tvb, payload_offset)),
3422                                  MIN(chunk_length - header_length, tvb_reported_length_remaining(chunk_tvb, payload_offset)));
3423 
3424   /* Is this a fragment? */
3425   if (b_bit && e_bit) {
3426     /* No - just call the subdissector. */
3427     if (!is_retransmission)
3428       call_subdissector = TRUE;
3429   } else {
3430     /* Yes. */
3431     pinfo->fragmented = TRUE;
3432 
3433     /* if reassembly is off just mark as fragment for next dissector and proceed */
3434     if (!use_reassembly)
3435     {
3436       /*  Don't pass on non-first fragments since the next dissector will
3437        *  almost certainly not understand the data.
3438        */
3439       if (b_bit) {
3440         if (!is_retransmission)
3441           call_subdissector = TRUE;
3442       } else
3443         return FALSE;
3444     }
3445 
3446   }
3447 
3448   if (call_subdissector) {
3449     /* This isn't a fragment or reassembly is off and it's the first fragment */
3450 
3451     volatile gboolean retval = FALSE;
3452     wmem_list_frame_t *cur = wmem_list_tail(pinfo->layers);
3453 
3454     TRY {
3455       retval = dissect_payload(payload_tvb, pinfo, tree, payload_proto_id);
3456     }
3457     CATCH_NONFATAL_ERRORS {
3458       /*
3459        * Somebody threw an exception that means that there was a problem
3460        * dissecting the payload; that means that a dissector was found,
3461        * so we don't need to dissect the payload as data or update the
3462        * protocol or info columns.
3463        *
3464        * Just show the exception and then continue dissecting chunks.
3465        */
3466       show_exception(payload_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
3467     }
3468     ENDTRY;
3469 
3470     export_sctp_data_chunk(pinfo, payload_tvb, payload_proto_id, wmem_list_frame_next(cur));
3471     return retval;
3472 
3473   } else if (is_retransmission) {
3474     col_append_str(pinfo->cinfo, COL_INFO, "(retransmission) ");
3475     return FALSE;
3476   } else {
3477 
3478     /* The logic above should ensure this... */
3479     DISSECTOR_ASSERT(use_reassembly);
3480 
3481     stream_id = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET);
3482     if (is_idata) {
3483       /* The stream_seq_num variable is used to hold the MID, the tsn variable holds the FSN*/
3484       stream_seq_num = tvb_get_ntohl(chunk_tvb, I_DATA_CHUNK_MID_OFFSET);
3485       if (b_bit) {
3486         tsn = 0;
3487       } else {
3488         tsn = tvb_get_ntohl(chunk_tvb, I_DATA_CHUNK_FSN_OFFSET);
3489         payload_proto_id = 0;
3490       }
3491     } else {
3492       /* if unordered set stream_seq_num to 0 for easier handling */
3493       if (u_bit)
3494         stream_seq_num = 0;
3495       else
3496         stream_seq_num = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET);
3497     }
3498     /* start reassembly */
3499     return dissect_fragmented_payload(payload_tvb, pinfo, tree, chunk_tree, tsn, payload_proto_id, stream_id, stream_seq_num, b_bit, e_bit, u_bit, is_idata);
3500   }
3501 
3502 }
3503 
3504 #define INIT_CHUNK_INITIATE_TAG_LENGTH               4
3505 #define INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH      4
3506 #define INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH 2
3507 #define INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH  2
3508 #define INIT_CHUNK_INITIAL_TSN_LENGTH                4
3509 #define INIT_CHUNK_FIXED_PARAMTERS_LENGTH            (CHUNK_HEADER_LENGTH + \
3510                                                       INIT_CHUNK_INITIATE_TAG_LENGTH + \
3511                                                       INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH + \
3512                                                       INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH + \
3513                                                       INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH + \
3514                                                       INIT_CHUNK_INITIAL_TSN_LENGTH)
3515 
3516 #define INIT_CHUNK_INITIATE_TAG_OFFSET               CHUNK_VALUE_OFFSET
3517 #define INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET      (INIT_CHUNK_INITIATE_TAG_OFFSET + \
3518                                                       INIT_CHUNK_INITIATE_TAG_LENGTH )
3519 #define INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET (INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET + \
3520                                                       INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH )
3521 #define INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET  (INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET + \
3522                                                       INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH )
3523 #define INIT_CHUNK_INITIAL_TSN_OFFSET                (INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET + \
3524                                                       INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH )
3525 #define INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET  (INIT_CHUNK_INITIAL_TSN_OFFSET + \
3526                                                       INIT_CHUNK_INITIAL_TSN_LENGTH )
3527 
3528 static void
dissect_init_chunk(tvbuff_t * chunk_tvb,guint16 chunk_length,packet_info * pinfo,proto_tree * chunk_tree,proto_item * chunk_item)3529 dissect_init_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
3530 {
3531   tvbuff_t *parameters_tvb;
3532   proto_item *hidden_item;
3533 
3534   if (chunk_length < INIT_CHUNK_FIXED_PARAMTERS_LENGTH) {
3535     proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)", chunk_length, INIT_CHUNK_FIXED_PARAMTERS_LENGTH);
3536     return;
3537   }
3538 
3539   if (chunk_tree) {
3540     /* handle fixed parameters */
3541     proto_tree_add_item(chunk_tree, hf_init_chunk_initiate_tag,               chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET,               INIT_CHUNK_INITIATE_TAG_LENGTH,               ENC_BIG_ENDIAN);
3542     hidden_item = proto_tree_add_item(chunk_tree, hf_initiate_tag,            chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET,               INIT_CHUNK_INITIATE_TAG_LENGTH,               ENC_BIG_ENDIAN);
3543     proto_item_set_hidden(hidden_item);
3544     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,      ENC_BIG_ENDIAN);
3545     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, ENC_BIG_ENDIAN);
3546     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,  ENC_BIG_ENDIAN);
3547     proto_tree_add_item(chunk_tree, hf_init_chunk_initial_tsn,                chunk_tvb, INIT_CHUNK_INITIAL_TSN_OFFSET,                INIT_CHUNK_INITIAL_TSN_LENGTH,                ENC_BIG_ENDIAN);
3548 
3549     proto_item_append_text(chunk_item, " (Outbound streams: %u, inbound streams: %u)",
3550                            tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET),
3551                            tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET));
3552   }
3553 
3554   /* handle variable parameters */
3555   chunk_length -= INIT_CHUNK_FIXED_PARAMTERS_LENGTH;
3556   parameters_tvb = tvb_new_subset_length_caplen(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET,
3557                                   MIN(chunk_length, tvb_captured_length_remaining(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET)),
3558                                   MIN(chunk_length, tvb_reported_length_remaining(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET)));
3559   dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, TRUE);
3560 }
3561 
3562 static void
dissect_init_ack_chunk(tvbuff_t * chunk_tvb,guint16 chunk_length,packet_info * pinfo,proto_tree * chunk_tree,proto_item * chunk_item)3563 dissect_init_ack_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
3564 {
3565   tvbuff_t *parameters_tvb;
3566   proto_item *hidden_item;
3567 
3568   if (chunk_length < INIT_CHUNK_FIXED_PARAMTERS_LENGTH) {
3569     proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
3570                            chunk_length,
3571                            INIT_CHUNK_FIXED_PARAMTERS_LENGTH);
3572     return;
3573   }
3574   if (chunk_tree) {
3575     /* handle fixed parameters */
3576     proto_tree_add_item(chunk_tree, hf_initack_chunk_initiate_tag,               chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET,               INIT_CHUNK_INITIATE_TAG_LENGTH,               ENC_BIG_ENDIAN);
3577     hidden_item = proto_tree_add_item(chunk_tree, hf_initiate_tag,                      chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET,               INIT_CHUNK_INITIATE_TAG_LENGTH,               ENC_BIG_ENDIAN);
3578     proto_item_set_hidden(hidden_item);
3579     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,      ENC_BIG_ENDIAN);
3580     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, ENC_BIG_ENDIAN);
3581     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,  ENC_BIG_ENDIAN);
3582     proto_tree_add_item(chunk_tree, hf_initack_chunk_initial_tsn,                chunk_tvb, INIT_CHUNK_INITIAL_TSN_OFFSET,                INIT_CHUNK_INITIAL_TSN_LENGTH,                ENC_BIG_ENDIAN);
3583 
3584     proto_item_append_text(chunk_item, " (Outbound streams: %u, inbound streams: %u)",
3585                            tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET),
3586                            tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET));
3587   }
3588   /* handle variable paramters */
3589   chunk_length -= INIT_CHUNK_FIXED_PARAMTERS_LENGTH;
3590   parameters_tvb = tvb_new_subset_length_caplen(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET,
3591                                   MIN(chunk_length, tvb_captured_length_remaining(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET)),
3592                                   MIN(chunk_length, tvb_reported_length_remaining(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET)));
3593   dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, TRUE);
3594 }
3595 
3596 #define SCTP_SACK_CHUNK_NS_BIT                  0x01
3597 #define SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH    4
3598 #define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH 4
3599 #define SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH  2
3600 #define SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH    2
3601 #define SACK_CHUNK_GAP_BLOCK_LENGTH             4
3602 #define SACK_CHUNK_GAP_BLOCK_START_LENGTH       2
3603 #define SACK_CHUNK_GAP_BLOCK_END_LENGTH         2
3604 #define SACK_CHUNK_DUP_TSN_LENGTH               4
3605 
3606 #define SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET (CHUNK_VALUE_OFFSET + 0)
3607 #define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET (SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET + \
3608                                                  SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH)
3609 #define SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET (SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET + \
3610                                                 SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH)
3611 #define SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET (SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET + \
3612                                               SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH)
3613 #define SACK_CHUNK_GAP_BLOCK_OFFSET (SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET + \
3614                                      SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH)
3615 
3616 
3617 static void
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)3618 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)
3619 {
3620   guint16 number_of_gap_blocks, number_of_dup_tsns;
3621   guint16 gap_block_number, dup_tsn_number, start, end;
3622   gint gap_block_offset, dup_tsn_offset;
3623   guint32 cum_tsn_ack;
3624   proto_tree *block_tree;
3625   proto_tree *flags_tree;
3626   proto_item *ctsa_item;
3627   proto_item *a_rwnd_item;
3628   proto_tree *acks_tree;
3629   guint32 tsns_gap_acked = 0;
3630   guint32 a_rwnd;
3631   guint16 last_end;
3632 
3633   cum_tsn_ack = tvb_get_ntohl(chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
3634   if((show_relative_tsns) && (ha) && (ha->peer)) {
3635     cum_tsn_ack -= ha->peer->first_tsn;
3636   }
3637 
3638   flags_tree  = proto_item_add_subtree(flags_item, ett_sctp_sack_chunk_flags);
3639   proto_tree_add_item(flags_tree, hf_sack_chunk_ns, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, ENC_BIG_ENDIAN);
3640   if((show_relative_tsns) && (ha) && (ha->peer)) {
3641      ctsa_item = proto_tree_add_uint(chunk_tree, hf_sack_chunk_cumulative_tsn_ack, chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET, SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH, cum_tsn_ack);
3642      proto_tree_add_item(chunk_tree, hf_sack_chunk_cumulative_tsn_ack_raw, chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET, SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH, ENC_BIG_ENDIAN);
3643   }
3644   else {
3645      ctsa_item = proto_tree_add_item(chunk_tree, hf_sack_chunk_cumulative_tsn_ack_raw, chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET, SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH, ENC_BIG_ENDIAN);
3646   }
3647   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, ENC_BIG_ENDIAN);
3648   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, ENC_BIG_ENDIAN);
3649   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,   ENC_BIG_ENDIAN);
3650 
3651   a_rwnd = tvb_get_ntohl(chunk_tvb, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET);
3652   if (a_rwnd == 0)
3653       expert_add_info(pinfo, a_rwnd_item, &ei_sctp_sack_chunk_adv_rec_window_credit);
3654 
3655 
3656   /* handle the gap acknowledgement blocks */
3657   number_of_gap_blocks = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET);
3658   gap_block_offset     = SACK_CHUNK_GAP_BLOCK_OFFSET;
3659 
3660   acks_tree = proto_item_add_subtree(ctsa_item,ett_sctp_ack);
3661   sctp_ack_block(pinfo, ha, chunk_tvb, acks_tree, NULL, cum_tsn_ack);
3662 
3663   last_end = 0;
3664   for(gap_block_number = 0; gap_block_number < number_of_gap_blocks; gap_block_number++) {
3665     proto_item *pi;
3666     proto_tree *pt;
3667     guint32 tsn_start;
3668 
3669     start = tvb_get_ntohs(chunk_tvb, gap_block_offset);
3670     end   = tvb_get_ntohs(chunk_tvb, gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH);
3671     tsn_start = cum_tsn_ack + start;
3672 
3673     block_tree = proto_tree_add_subtree_format(chunk_tree, chunk_tvb, gap_block_offset, SACK_CHUNK_GAP_BLOCK_LENGTH,
3674                         ett_sctp_sack_chunk_gap_block, NULL, "Gap Acknowledgement for TSN %u to %u", cum_tsn_ack + start, cum_tsn_ack + end);
3675 
3676     pi = proto_tree_add_item(block_tree, hf_sack_chunk_gap_block_start, chunk_tvb, gap_block_offset, SACK_CHUNK_GAP_BLOCK_START_LENGTH, ENC_BIG_ENDIAN);
3677     pt = proto_item_add_subtree(pi, ett_sctp_sack_chunk_gap_block_start);
3678     pi = proto_tree_add_uint(pt, hf_sack_chunk_gap_block_start_tsn,
3679                              chunk_tvb, gap_block_offset,SACK_CHUNK_GAP_BLOCK_START_LENGTH, cum_tsn_ack + start);
3680     proto_item_set_generated(pi);
3681 
3682     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,   ENC_BIG_ENDIAN);
3683     pt = proto_item_add_subtree(pi, ett_sctp_sack_chunk_gap_block_end);
3684     pi = proto_tree_add_uint(pt, hf_sack_chunk_gap_block_end_tsn, chunk_tvb,
3685                              gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH, SACK_CHUNK_GAP_BLOCK_END_LENGTH, cum_tsn_ack + end);
3686     proto_item_set_generated(pi);
3687 
3688     sctp_ack_block(pinfo, ha, chunk_tvb, block_tree, &tsn_start, cum_tsn_ack + end);
3689     gap_block_offset += SACK_CHUNK_GAP_BLOCK_LENGTH;
3690 
3691     tsns_gap_acked += (end+1 - start);
3692 
3693     /* Check validity */
3694     if (start > end) {
3695        expert_add_info(pinfo, pi, &ei_sctp_sack_chunk_gap_block_malformed);
3696     }
3697     if (last_end > start) {
3698        expert_add_info(pinfo, pi, &ei_sctp_sack_chunk_gap_block_out_of_order);
3699     }
3700     last_end = end;
3701   }
3702 
3703   if(last_end == 0) {
3704     /* No GapAck -> only show CumAck */
3705     col_append_fstr(pinfo->cinfo, COL_INFO,
3706                     "(Ack=%" G_GUINT32_FORMAT ", Arwnd=%" G_GUINT32_FORMAT ") ",
3707                     cum_tsn_ack, a_rwnd);
3708   }
3709   else {
3710     /* Show CumAck + highest GapAck */
3711     col_append_fstr(pinfo->cinfo, COL_INFO,
3712                     "(Ack=%" G_GUINT32_FORMAT "+%" G_GUINT32_FORMAT ", Arwnd=%" G_GUINT32_FORMAT ") ",
3713                     cum_tsn_ack, last_end, a_rwnd);
3714   }
3715 
3716   if (tsns_gap_acked) {
3717     proto_item *pi;
3718 
3719     pi = proto_tree_add_uint(chunk_tree, hf_sack_chunk_number_tsns_gap_acked, chunk_tvb, 0, 0, tsns_gap_acked);
3720     proto_item_set_generated(pi);
3721 
3722     /*  If there are a huge number of GAP ACKs, warn the user.  100 is a random
3723      *  number: it could be tuned.
3724      */
3725     if (tsns_gap_acked > 100)
3726       expert_add_info(pinfo, pi, &ei_sctp_sack_chunk_number_tsns_gap_acked_100);
3727 
3728   }
3729 
3730 
3731   /* handle the duplicate TSNs */
3732   number_of_dup_tsns = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET);
3733   dup_tsn_offset     = SACK_CHUNK_GAP_BLOCK_OFFSET + number_of_gap_blocks * SACK_CHUNK_GAP_BLOCK_LENGTH;
3734   for(dup_tsn_number = 0; dup_tsn_number < number_of_dup_tsns; dup_tsn_number++) {
3735     proto_tree_add_item(chunk_tree, hf_sack_chunk_duplicate_tsn, chunk_tvb, dup_tsn_offset, SACK_CHUNK_DUP_TSN_LENGTH, ENC_BIG_ENDIAN);
3736     dup_tsn_offset += SACK_CHUNK_DUP_TSN_LENGTH;
3737   }
3738 
3739   proto_item_append_text(chunk_item, " (Cumulative TSN: %u, a_rwnd: %u, gaps: %u, duplicate TSNs: %u)",
3740                          tvb_get_ntohl(chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET),
3741                          a_rwnd,
3742                          number_of_gap_blocks, number_of_dup_tsns);
3743 }
3744 
3745 /* NE: Dissect nr-sack chunk */
3746 #define SCTP_NR_SACK_CHUNK_NS_BIT                  0x01
3747 #define NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH       4
3748 #define NR_SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH    4
3749 #define NR_SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH     2
3750 #define NR_SACK_CHUNK_NUMBER_OF_NR_GAP_BLOCKS_LENGTH  2
3751 #define NR_SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH       2
3752 #define NR_SACK_CHUNK_RESERVED_LENGTH                 2
3753 #define NR_SACK_CHUNK_GAP_BLOCK_LENGTH                4
3754 #define NR_SACK_CHUNK_GAP_BLOCK_START_LENGTH          2
3755 #define NR_SACK_CHUNK_GAP_BLOCK_END_LENGTH            2
3756 #define NR_SACK_CHUNK_NR_GAP_BLOCK_LENGTH             4
3757 #define NR_SACK_CHUNK_NR_GAP_BLOCK_START_LENGTH       2
3758 #define NR_SACK_CHUNK_NR_GAP_BLOCK_END_LENGTH         2
3759 #define NR_SACK_CHUNK_DUP_TSN_LENGTH                  4
3760 
3761 #define NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET        (CHUNK_VALUE_OFFSET + 0)
3762 #define NR_SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET     (NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET + \
3763                                                         NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH)
3764 #define NR_SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET      (NR_SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET + \
3765                                                         NR_SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH)
3766 #define NR_SACK_CHUNK_NUMBER_OF_NR_GAP_BLOCKS_OFFSET   (NR_SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET + \
3767                                                         NR_SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH)
3768 #define NR_SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET        (NR_SACK_CHUNK_NUMBER_OF_NR_GAP_BLOCKS_OFFSET + \
3769                                                         NR_SACK_CHUNK_NUMBER_OF_NR_GAP_BLOCKS_LENGTH)
3770 #define NR_SACK_CHUNK_RESERVED_OFFSET                  (NR_SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET + \
3771                                                         NR_SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH)
3772 #define NR_SACK_CHUNK_GAP_BLOCK_OFFSET                 (NR_SACK_CHUNK_RESERVED_OFFSET + \
3773                                                         NR_SACK_CHUNK_RESERVED_LENGTH)
3774 
3775 static void
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)3776 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)
3777 {
3778   guint16 number_of_gap_blocks, number_of_dup_tsns;
3779   guint16 number_of_nr_gap_blocks;
3780   guint16 gap_block_number, nr_gap_block_number, dup_tsn_number, start, end;
3781   gint gap_block_offset, nr_gap_block_offset, dup_tsn_offset;
3782   guint32 cum_tsn_ack;
3783   proto_tree *block_tree;
3784   proto_tree *flags_tree;
3785   proto_item *ctsa_item;
3786   proto_tree *acks_tree;
3787   guint32 tsns_gap_acked = 0;
3788   guint32 tsns_nr_gap_acked = 0;
3789   guint16 last_end;
3790 
3791   flags_tree  = proto_item_add_subtree(flags_item, ett_sctp_nr_sack_chunk_flags);
3792   proto_tree_add_item(flags_tree, hf_nr_sack_chunk_ns, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, ENC_BIG_ENDIAN);
3793 
3794   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, ENC_BIG_ENDIAN);
3795   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, ENC_BIG_ENDIAN);
3796 
3797   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, ENC_BIG_ENDIAN);
3798 
3799   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, ENC_BIG_ENDIAN);
3800   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, ENC_BIG_ENDIAN);
3801   proto_tree_add_item(chunk_tree, hf_nr_sack_chunk_reserved, chunk_tvb, NR_SACK_CHUNK_RESERVED_OFFSET, NR_SACK_CHUNK_RESERVED_LENGTH, ENC_BIG_ENDIAN);
3802 
3803 
3804   number_of_gap_blocks = tvb_get_ntohs(chunk_tvb, NR_SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET);
3805   gap_block_offset     = NR_SACK_CHUNK_GAP_BLOCK_OFFSET;
3806   cum_tsn_ack          = tvb_get_ntohl(chunk_tvb, NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
3807 
3808   acks_tree = proto_item_add_subtree(ctsa_item,ett_sctp_ack);
3809   sctp_ack_block(pinfo, ha, chunk_tvb, acks_tree, NULL, cum_tsn_ack);
3810 
3811   last_end = 0;
3812   for(gap_block_number = 0; gap_block_number < number_of_gap_blocks; gap_block_number++) {
3813     proto_item *pi;
3814     proto_tree *pt;
3815     guint32 tsn_start;
3816 
3817     start = tvb_get_ntohs(chunk_tvb, gap_block_offset);
3818     end   = tvb_get_ntohs(chunk_tvb, gap_block_offset + NR_SACK_CHUNK_GAP_BLOCK_START_LENGTH);
3819     tsn_start = cum_tsn_ack + start;
3820 
3821     block_tree = proto_tree_add_subtree_format(chunk_tree, chunk_tvb, gap_block_offset, NR_SACK_CHUNK_GAP_BLOCK_LENGTH,
3822                         ett_sctp_nr_sack_chunk_gap_block, NULL, "Gap Acknowledgement for TSN %u to %u", cum_tsn_ack + start, cum_tsn_ack + end);
3823 
3824     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, ENC_BIG_ENDIAN);
3825     pt = proto_item_add_subtree(pi, ett_sctp_nr_sack_chunk_gap_block_start);
3826     pi = proto_tree_add_uint(pt, hf_nr_sack_chunk_gap_block_start_tsn,
3827                              chunk_tvb, gap_block_offset,NR_SACK_CHUNK_GAP_BLOCK_START_LENGTH, cum_tsn_ack + start);
3828     proto_item_set_generated(pi);
3829 
3830     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,   ENC_BIG_ENDIAN);
3831     pt = proto_item_add_subtree(pi, ett_sctp_nr_sack_chunk_gap_block_end);
3832     pi = proto_tree_add_uint(pt, hf_nr_sack_chunk_gap_block_end_tsn, chunk_tvb,
3833                                gap_block_offset + NR_SACK_CHUNK_GAP_BLOCK_START_LENGTH, NR_SACK_CHUNK_GAP_BLOCK_END_LENGTH, cum_tsn_ack + end);
3834     proto_item_set_generated(pi);
3835 
3836     sctp_ack_block(pinfo, ha, chunk_tvb, block_tree, &tsn_start, cum_tsn_ack + end);
3837     gap_block_offset += NR_SACK_CHUNK_GAP_BLOCK_LENGTH;
3838     tsns_gap_acked += (end - start) + 1;
3839 
3840     /* Check validity */
3841     if (start > end) {
3842        expert_add_info(pinfo, pi, &ei_sctp_sack_chunk_gap_block_malformed);
3843     }
3844     if (last_end > start) {
3845        expert_add_info(pinfo, pi, &ei_sctp_sack_chunk_gap_block_out_of_order);
3846     }
3847     last_end = end;
3848   }
3849 
3850   if (tsns_gap_acked) {
3851     proto_item *pi;
3852 
3853     pi = proto_tree_add_uint(chunk_tree, hf_nr_sack_chunk_number_tsns_gap_acked, chunk_tvb, 0, 0, tsns_gap_acked);
3854     proto_item_set_generated(pi);
3855 
3856     /*  If there are a huge number of GAP ACKs, warn the user.  100 is a random
3857      *  number: it could be tuned.
3858      */
3859     if (tsns_gap_acked > 100)
3860       expert_add_info(pinfo, pi, &ei_sctp_nr_sack_chunk_number_tsns_gap_acked_100);
3861 
3862   }
3863 
3864   /* NE: handle the nr-sack chunk's nr-gap blocks */
3865   number_of_nr_gap_blocks = tvb_get_ntohs(chunk_tvb, NR_SACK_CHUNK_NUMBER_OF_NR_GAP_BLOCKS_OFFSET);
3866   nr_gap_block_offset     = gap_block_offset;
3867 
3868   last_end = 0;
3869   for(nr_gap_block_number = 0; nr_gap_block_number < number_of_nr_gap_blocks; nr_gap_block_number++) {
3870     proto_item *pi;
3871     proto_tree *pt;
3872     /*guint32 tsn_start;*/
3873 
3874     start = tvb_get_ntohs(chunk_tvb, nr_gap_block_offset);
3875     end   = tvb_get_ntohs(chunk_tvb, nr_gap_block_offset + NR_SACK_CHUNK_NR_GAP_BLOCK_START_LENGTH);
3876     /*tsn_start = cum_tsn_ack + start;*/
3877 
3878     block_tree = proto_tree_add_subtree_format(chunk_tree, chunk_tvb, nr_gap_block_offset, NR_SACK_CHUNK_NR_GAP_BLOCK_LENGTH,
3879             ett_sctp_nr_sack_chunk_nr_gap_block, NULL, "NR-Gap Acknowledgement for TSN %u to %u", cum_tsn_ack + start, cum_tsn_ack + end);
3880 
3881     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, ENC_BIG_ENDIAN);
3882     pt = proto_item_add_subtree(pi, ett_sctp_nr_sack_chunk_nr_gap_block_start);
3883     pi = proto_tree_add_uint(pt, hf_nr_sack_chunk_nr_gap_block_start_tsn,
3884                              chunk_tvb, nr_gap_block_offset, NR_SACK_CHUNK_NR_GAP_BLOCK_START_LENGTH, cum_tsn_ack + start);
3885     proto_item_set_generated(pi);
3886 
3887     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,   ENC_BIG_ENDIAN);
3888     pt = proto_item_add_subtree(pi, ett_sctp_nr_sack_chunk_nr_gap_block_end);
3889     pi = proto_tree_add_uint(pt, hf_nr_sack_chunk_nr_gap_block_end_tsn, chunk_tvb,
3890                              nr_gap_block_offset + NR_SACK_CHUNK_NR_GAP_BLOCK_START_LENGTH, NR_SACK_CHUNK_NR_GAP_BLOCK_END_LENGTH, cum_tsn_ack + end);
3891     proto_item_set_generated(pi);
3892 
3893     /* sctp_ack_block(pinfo, ha, chunk_tvb, block_tree, &tsn_start, cum_tsn_ack + end); */
3894     nr_gap_block_offset += NR_SACK_CHUNK_NR_GAP_BLOCK_LENGTH;
3895     tsns_nr_gap_acked += (end - start) + 1;
3896 
3897     /* Check validity */
3898     if (start > end) {
3899        expert_add_info(pinfo, pi, &ei_sctp_sack_chunk_gap_block_malformed);
3900     }
3901     if (last_end > start) {
3902        expert_add_info(pinfo, pi, &ei_sctp_sack_chunk_gap_block_out_of_order);
3903     }
3904     last_end = end;
3905   }
3906 
3907   if (tsns_nr_gap_acked) {
3908     proto_item *pi;
3909 
3910     pi = proto_tree_add_uint(chunk_tree, hf_nr_sack_chunk_number_tsns_nr_gap_acked, chunk_tvb, 0, 0, tsns_nr_gap_acked);
3911     proto_item_set_generated(pi);
3912 
3913     /*  If there are a huge number of GAP ACKs, warn the user.  100 is a random
3914      *  number: it could be tuned.
3915      */
3916     if (tsns_nr_gap_acked > 100)
3917       expert_add_info(pinfo, pi, &ei_sctp_nr_sack_chunk_number_tsns_nr_gap_acked_100);
3918   }
3919 
3920   /* handle the duplicate TSNs */
3921   number_of_dup_tsns = tvb_get_ntohs(chunk_tvb, NR_SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET);
3922   dup_tsn_offset     = NR_SACK_CHUNK_GAP_BLOCK_OFFSET + number_of_gap_blocks * NR_SACK_CHUNK_GAP_BLOCK_LENGTH
3923     + number_of_nr_gap_blocks * NR_SACK_CHUNK_NR_GAP_BLOCK_LENGTH;
3924 
3925 
3926   for(dup_tsn_number = 0; dup_tsn_number < number_of_dup_tsns; dup_tsn_number++) {
3927     proto_tree_add_item(chunk_tree, hf_nr_sack_chunk_duplicate_tsn, chunk_tvb, dup_tsn_offset, NR_SACK_CHUNK_DUP_TSN_LENGTH, ENC_BIG_ENDIAN);
3928     dup_tsn_offset += NR_SACK_CHUNK_DUP_TSN_LENGTH;
3929   }
3930 
3931   proto_item_append_text(chunk_item, " (Cumulative TSN: %u, a_rwnd: %u, gaps: %u, nr-gaps: %u, duplicate TSNs: %u)",
3932                          tvb_get_ntohl(chunk_tvb, NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET),
3933                          tvb_get_ntohl(chunk_tvb, NR_SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET),
3934                          number_of_gap_blocks, number_of_nr_gap_blocks, number_of_dup_tsns);
3935 }
3936 
3937 #define HEARTBEAT_CHUNK_INFO_OFFSET CHUNK_VALUE_OFFSET
3938 
3939 static void
dissect_heartbeat_chunk(tvbuff_t * chunk_tvb,guint16 chunk_length,packet_info * pinfo,proto_tree * chunk_tree,proto_item * chunk_item)3940 dissect_heartbeat_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
3941 {
3942   tvbuff_t   *parameter_tvb;
3943 
3944   if (chunk_tree) {
3945     proto_item_append_text(chunk_item, " (Information: %u byte%s)", chunk_length - CHUNK_HEADER_LENGTH, plurality(chunk_length - CHUNK_HEADER_LENGTH, "", "s"));
3946     parameter_tvb  = tvb_new_subset_length_caplen(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET,
3947                                     MIN(chunk_length - CHUNK_HEADER_LENGTH, tvb_captured_length_remaining(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET)),
3948                                     MIN(chunk_length - CHUNK_HEADER_LENGTH, tvb_reported_length_remaining(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET)));
3949     /* FIXME: Parameters or parameter? */
3950     dissect_parameter(parameter_tvb, pinfo, chunk_tree, NULL, FALSE, TRUE);
3951   }
3952 }
3953 
3954 #define HEARTBEAT_ACK_CHUNK_INFO_OFFSET CHUNK_VALUE_OFFSET
3955 
3956 static void
dissect_heartbeat_ack_chunk(tvbuff_t * chunk_tvb,guint16 chunk_length,packet_info * pinfo,proto_tree * chunk_tree,proto_item * chunk_item)3957 dissect_heartbeat_ack_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
3958 {
3959   tvbuff_t   *parameter_tvb;
3960 
3961   if (chunk_tree) {
3962     proto_item_append_text(chunk_item, " (Information: %u byte%s)", chunk_length - CHUNK_HEADER_LENGTH, plurality(chunk_length - CHUNK_HEADER_LENGTH, "", "s"));
3963     parameter_tvb  = tvb_new_subset_length_caplen(chunk_tvb, HEARTBEAT_ACK_CHUNK_INFO_OFFSET,
3964                                     MIN(chunk_length - CHUNK_HEADER_LENGTH, tvb_captured_length_remaining(chunk_tvb, HEARTBEAT_ACK_CHUNK_INFO_OFFSET)),
3965                                     MIN(chunk_length - CHUNK_HEADER_LENGTH, tvb_reported_length_remaining(chunk_tvb, HEARTBEAT_ACK_CHUNK_INFO_OFFSET)));
3966     /* FIXME: Parameters or parameter? */
3967     dissect_parameter(parameter_tvb, pinfo, chunk_tree, NULL, FALSE, TRUE);
3968   }
3969 }
3970 
3971 #define ABORT_CHUNK_FIRST_ERROR_CAUSE_OFFSET 4
3972 #define SCTP_ABORT_CHUNK_T_BIT               0x01
3973 
3974 static void
dissect_abort_chunk(tvbuff_t * chunk_tvb,guint16 chunk_length,packet_info * pinfo,proto_tree * chunk_tree,proto_item * flags_item)3975 dissect_abort_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *flags_item)
3976 {
3977   tvbuff_t *causes_tvb;
3978   proto_tree *flags_tree;
3979 
3980   sctp_info.vtag_reflected =
3981       (tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_ABORT_CHUNK_T_BIT) != 0;
3982 
3983   if (chunk_tree) {
3984     flags_tree  = proto_item_add_subtree(flags_item, ett_sctp_abort_chunk_flags);
3985     proto_tree_add_item(flags_tree, hf_abort_chunk_t_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, ENC_BIG_ENDIAN);
3986     causes_tvb  = tvb_new_subset_length_caplen(chunk_tvb, CHUNK_VALUE_OFFSET,
3987                                  MIN(chunk_length - CHUNK_HEADER_LENGTH, tvb_captured_length_remaining(chunk_tvb, CHUNK_VALUE_OFFSET)),
3988                                  MIN(chunk_length - CHUNK_HEADER_LENGTH, tvb_reported_length_remaining(chunk_tvb, CHUNK_VALUE_OFFSET)));
3989     dissect_error_causes(causes_tvb, pinfo, chunk_tree);
3990   }
3991 }
3992 
3993 #define SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET CHUNK_VALUE_OFFSET
3994 #define SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_LENGTH 4
3995 
3996 static void
dissect_shutdown_chunk(tvbuff_t * chunk_tvb,proto_tree * chunk_tree,proto_item * chunk_item)3997 dissect_shutdown_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
3998 {
3999   if (chunk_tree) {
4000     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, ENC_BIG_ENDIAN);
4001     proto_item_append_text(chunk_item, " (Cumulative TSN ack: %u)", tvb_get_ntohl(chunk_tvb, SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET));
4002   }
4003 }
4004 
4005 static void
dissect_shutdown_ack_chunk(tvbuff_t * chunk_tvb _U_)4006 dissect_shutdown_ack_chunk(tvbuff_t *chunk_tvb _U_)
4007 {
4008 }
4009 
4010 #define ERROR_CAUSE_IND_CAUSES_OFFSET CHUNK_VALUE_OFFSET
4011 
4012 static void
dissect_error_chunk(tvbuff_t * chunk_tvb,guint16 chunk_length,packet_info * pinfo,proto_tree * chunk_tree)4013 dissect_error_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree)
4014 {
4015   tvbuff_t *causes_tvb;
4016 
4017   if (chunk_tree) {
4018     causes_tvb = tvb_new_subset_length_caplen(chunk_tvb, ERROR_CAUSE_IND_CAUSES_OFFSET,
4019                                 MIN(chunk_length - CHUNK_HEADER_LENGTH, tvb_captured_length_remaining(chunk_tvb, ERROR_CAUSE_IND_CAUSES_OFFSET)),
4020                                 MIN(chunk_length - CHUNK_HEADER_LENGTH, tvb_reported_length_remaining(chunk_tvb, ERROR_CAUSE_IND_CAUSES_OFFSET)));
4021     dissect_error_causes(causes_tvb, pinfo, chunk_tree);
4022   }
4023 }
4024 
4025 #define COOKIE_OFFSET CHUNK_VALUE_OFFSET
4026 
4027 static void
dissect_cookie_echo_chunk(tvbuff_t * chunk_tvb,guint16 chunk_length,proto_tree * chunk_tree,proto_item * chunk_item)4028 dissect_cookie_echo_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, proto_tree *chunk_tree, proto_item *chunk_item)
4029 {
4030   if (chunk_tree) {
4031     proto_tree_add_item(chunk_tree, hf_cookie, chunk_tvb, COOKIE_OFFSET, chunk_length - CHUNK_HEADER_LENGTH, ENC_NA);
4032     proto_item_append_text(chunk_item, " (Cookie length: %u byte%s)", chunk_length - CHUNK_HEADER_LENGTH, plurality(chunk_length - CHUNK_HEADER_LENGTH, "", "s"));
4033   }
4034 }
4035 
4036 static void
dissect_cookie_ack_chunk(tvbuff_t * chunk_tvb _U_)4037 dissect_cookie_ack_chunk(tvbuff_t *chunk_tvb _U_)
4038 {
4039 }
4040 
4041 #define ECNE_CHUNK_LOWEST_TSN_OFFSET CHUNK_VALUE_OFFSET
4042 #define ECNE_CHUNK_LOWEST_TSN_LENGTH 4
4043 
4044 static void
dissect_ecne_chunk(tvbuff_t * chunk_tvb,proto_tree * chunk_tree,proto_item * chunk_item)4045 dissect_ecne_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
4046 {
4047     proto_tree_add_item(chunk_tree, hf_ecne_chunk_lowest_tsn, chunk_tvb, ECNE_CHUNK_LOWEST_TSN_OFFSET, ECNE_CHUNK_LOWEST_TSN_LENGTH, ENC_BIG_ENDIAN);
4048     proto_item_append_text(chunk_item, " (Lowest TSN: %u)", tvb_get_ntohl(chunk_tvb, ECNE_CHUNK_LOWEST_TSN_OFFSET));
4049 }
4050 
4051 #define CWR_CHUNK_LOWEST_TSN_OFFSET CHUNK_VALUE_OFFSET
4052 #define CWR_CHUNK_LOWEST_TSN_LENGTH 4
4053 
4054 static void
dissect_cwr_chunk(tvbuff_t * chunk_tvb,proto_tree * chunk_tree,proto_item * chunk_item)4055 dissect_cwr_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
4056 {
4057     proto_tree_add_item(chunk_tree, hf_cwr_chunk_lowest_tsn, chunk_tvb, CWR_CHUNK_LOWEST_TSN_OFFSET, CWR_CHUNK_LOWEST_TSN_LENGTH, ENC_BIG_ENDIAN);
4058     proto_item_append_text(chunk_item, " (Lowest TSN: %u)", tvb_get_ntohl(chunk_tvb, CWR_CHUNK_LOWEST_TSN_OFFSET));
4059 }
4060 
4061 #define SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT 0x01
4062 
4063 
4064 static const true_false_string sctp_shutdown_complete_chunk_t_bit_value = {
4065   "Tag reflected",
4066   "Tag not reflected"
4067 };
4068 
4069 
4070 static void
dissect_shutdown_complete_chunk(tvbuff_t * chunk_tvb,proto_tree * chunk_tree,proto_item * flags_item)4071 dissect_shutdown_complete_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *flags_item)
4072 {
4073   proto_tree *flags_tree;
4074 
4075   sctp_info.vtag_reflected =
4076       (tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT) != 0;
4077 
4078   if (chunk_tree) {
4079     flags_tree  = proto_item_add_subtree(flags_item, ett_sctp_shutdown_complete_chunk_flags);
4080     proto_tree_add_item(flags_tree, hf_shutdown_complete_chunk_t_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, ENC_BIG_ENDIAN);
4081   }
4082 }
4083 
4084 #define FORWARD_TSN_CHUNK_TSN_LENGTH 4
4085 #define FORWARD_TSN_CHUNK_SID_LENGTH 2
4086 #define FORWARD_TSN_CHUNK_SSN_LENGTH 2
4087 #define FORWARD_TSN_CHUNK_TSN_OFFSET CHUNK_VALUE_OFFSET
4088 #define FORWARD_TSN_CHUNK_SID_OFFSET 0
4089 #define FORWARD_TSN_CHUNK_SSN_OFFSET (FORWARD_TSN_CHUNK_SID_OFFSET + FORWARD_TSN_CHUNK_SID_LENGTH)
4090 
4091 static void
dissect_forward_tsn_chunk(tvbuff_t * chunk_tvb,guint16 chunk_length,proto_tree * chunk_tree,proto_item * chunk_item)4092 dissect_forward_tsn_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, proto_tree *chunk_tree, proto_item *chunk_item)
4093 {
4094   guint   offset;
4095   guint16 number_of_affected_streams, affected_stream;
4096 
4097   /* FIXME */
4098   if (chunk_length < CHUNK_HEADER_LENGTH + FORWARD_TSN_CHUNK_TSN_LENGTH) {
4099     proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
4100                            chunk_length,
4101                            CHUNK_HEADER_LENGTH + FORWARD_TSN_CHUNK_TSN_LENGTH);
4102     return;
4103   }
4104   if (chunk_tree) {
4105     proto_tree_add_item(chunk_tree, hf_forward_tsn_chunk_tsn, chunk_tvb, FORWARD_TSN_CHUNK_TSN_OFFSET, FORWARD_TSN_CHUNK_TSN_LENGTH, ENC_BIG_ENDIAN);
4106     number_of_affected_streams = (chunk_length - CHUNK_HEADER_LENGTH - FORWARD_TSN_CHUNK_TSN_LENGTH) /
4107                                  (FORWARD_TSN_CHUNK_SID_LENGTH + FORWARD_TSN_CHUNK_SSN_LENGTH);
4108     offset = CHUNK_VALUE_OFFSET + FORWARD_TSN_CHUNK_TSN_LENGTH;
4109 
4110     for(affected_stream = 0;  affected_stream < number_of_affected_streams; affected_stream++) {
4111         proto_tree_add_item(chunk_tree, hf_forward_tsn_chunk_sid, chunk_tvb, offset + FORWARD_TSN_CHUNK_SID_OFFSET, FORWARD_TSN_CHUNK_SID_LENGTH, ENC_BIG_ENDIAN);
4112         proto_tree_add_item(chunk_tree, hf_forward_tsn_chunk_ssn, chunk_tvb, offset + FORWARD_TSN_CHUNK_SSN_OFFSET, FORWARD_TSN_CHUNK_SSN_LENGTH, ENC_BIG_ENDIAN);
4113         offset = offset + (FORWARD_TSN_CHUNK_SID_LENGTH + FORWARD_TSN_CHUNK_SSN_LENGTH);
4114     }
4115     proto_item_append_text(chunk_item, "(Cumulative TSN: %u)", tvb_get_ntohl(chunk_tvb, FORWARD_TSN_CHUNK_TSN_OFFSET));
4116   }
4117 }
4118 
4119 #define I_FORWARD_TSN_CHUNK_TSN_LENGTH   4
4120 #define I_FORWARD_TSN_CHUNK_SID_LENGTH   2
4121 #define I_FORWARD_TSN_CHUNK_FLAGS_LENGTH 2
4122 #define I_FORWARD_TSN_CHUNK_MID_LENGTH   4
4123 #define I_FORWARD_TSN_CHUNK_TSN_OFFSET   CHUNK_VALUE_OFFSET
4124 #define I_FORWARD_TSN_CHUNK_SID_OFFSET   0
4125 #define I_FORWARD_TSN_CHUNK_FLAGS_OFFSET (I_FORWARD_TSN_CHUNK_SID_OFFSET + I_FORWARD_TSN_CHUNK_SID_LENGTH)
4126 #define I_FORWARD_TSN_CHUNK_MID_OFFSET   (I_FORWARD_TSN_CHUNK_FLAGS_OFFSET + I_FORWARD_TSN_CHUNK_FLAGS_LENGTH)
4127 
4128 #define SCTP_I_FORWARD_TSN_CHUNK_U_BIT    0x0001
4129 #define SCTP_I_FORWARD_TSN_CHUNK_RES_MASK 0xfffe
4130 
4131 static const true_false_string sctp_i_forward_tsn_chunk_u_bit_value = {
4132   "Unordered messages",
4133   "Ordered messages"
4134 };
4135 
4136 static void
dissect_i_forward_tsn_chunk(tvbuff_t * chunk_tvb,guint16 chunk_length,proto_tree * chunk_tree,proto_item * chunk_item)4137 dissect_i_forward_tsn_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, proto_tree *chunk_tree, proto_item *chunk_item)
4138 {
4139   guint   offset;
4140   guint16 number_of_affected_streams, affected_stream;
4141   proto_tree *flags_tree;
4142   proto_item *flags_item = NULL;
4143 
4144   /* FIXME */
4145   if (chunk_length < CHUNK_HEADER_LENGTH + I_FORWARD_TSN_CHUNK_TSN_LENGTH) {
4146     proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
4147                            chunk_length,
4148                            CHUNK_HEADER_LENGTH + I_FORWARD_TSN_CHUNK_TSN_LENGTH);
4149     return;
4150   }
4151   if (chunk_tree) {
4152     proto_tree_add_item(chunk_tree, hf_i_forward_tsn_chunk_tsn, chunk_tvb, I_FORWARD_TSN_CHUNK_TSN_OFFSET, I_FORWARD_TSN_CHUNK_TSN_LENGTH, ENC_BIG_ENDIAN);
4153     number_of_affected_streams = (chunk_length - CHUNK_HEADER_LENGTH - I_FORWARD_TSN_CHUNK_TSN_LENGTH) /
4154                                  (I_FORWARD_TSN_CHUNK_SID_LENGTH + I_FORWARD_TSN_CHUNK_FLAGS_LENGTH + I_FORWARD_TSN_CHUNK_MID_LENGTH);
4155     offset = CHUNK_VALUE_OFFSET + I_FORWARD_TSN_CHUNK_TSN_LENGTH;
4156 
4157     for(affected_stream = 0;  affected_stream < number_of_affected_streams; affected_stream++) {
4158         proto_tree_add_item(chunk_tree, hf_i_forward_tsn_chunk_sid, chunk_tvb, offset + I_FORWARD_TSN_CHUNK_SID_OFFSET, I_FORWARD_TSN_CHUNK_SID_LENGTH, ENC_BIG_ENDIAN);
4159         flags_item = proto_tree_add_item(chunk_tree, hf_i_forward_tsn_chunk_flags, chunk_tvb, offset + I_FORWARD_TSN_CHUNK_FLAGS_OFFSET, I_FORWARD_TSN_CHUNK_FLAGS_LENGTH, ENC_BIG_ENDIAN);
4160         flags_tree  = proto_item_add_subtree(flags_item, ett_sctp_i_forward_tsn_chunk_flags);
4161         proto_tree_add_item(flags_tree, hf_i_forward_tsn_chunk_res, chunk_tvb, offset + I_FORWARD_TSN_CHUNK_FLAGS_OFFSET, I_FORWARD_TSN_CHUNK_FLAGS_LENGTH, ENC_BIG_ENDIAN);
4162         proto_tree_add_item(flags_tree, hf_i_forward_tsn_chunk_u_bit, chunk_tvb, offset + I_FORWARD_TSN_CHUNK_FLAGS_OFFSET, I_FORWARD_TSN_CHUNK_FLAGS_LENGTH, ENC_BIG_ENDIAN);
4163         proto_tree_add_item(chunk_tree, hf_i_forward_tsn_chunk_mid, chunk_tvb, offset + I_FORWARD_TSN_CHUNK_MID_OFFSET, I_FORWARD_TSN_CHUNK_MID_LENGTH, ENC_BIG_ENDIAN);
4164         offset += (I_FORWARD_TSN_CHUNK_SID_LENGTH + I_FORWARD_TSN_CHUNK_FLAGS_LENGTH + I_FORWARD_TSN_CHUNK_MID_LENGTH);
4165     }
4166     proto_item_append_text(chunk_item, "(Cumulative TSN: %u)", tvb_get_ntohl(chunk_tvb, I_FORWARD_TSN_CHUNK_TSN_OFFSET));
4167   }
4168 }
4169 
4170 #define RE_CONFIG_PARAMETERS_OFFSET CHUNK_HEADER_LENGTH
4171 
4172 static void
dissect_re_config_chunk(tvbuff_t * chunk_tvb,guint16 chunk_length,packet_info * pinfo,proto_tree * chunk_tree,proto_item * chunk_item _U_)4173 dissect_re_config_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item _U_)
4174 {
4175   tvbuff_t *parameters_tvb;
4176 
4177   parameters_tvb = tvb_new_subset_length_caplen(chunk_tvb, RE_CONFIG_PARAMETERS_OFFSET,
4178                                   MIN(chunk_length - CHUNK_HEADER_LENGTH, tvb_captured_length_remaining(chunk_tvb, RE_CONFIG_PARAMETERS_OFFSET)),
4179                                   MIN(chunk_length - CHUNK_HEADER_LENGTH, tvb_reported_length_remaining(chunk_tvb, RE_CONFIG_PARAMETERS_OFFSET)));
4180   dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, FALSE);
4181 }
4182 
4183 #define SHARED_KEY_ID_LENGTH 2
4184 
4185 #define SHARED_KEY_ID_OFFSET PARAMETER_VALUE_OFFSET
4186 #define HMAC_ID_OFFSET       (SHARED_KEY_ID_OFFSET + SHARED_KEY_ID_LENGTH)
4187 #define HMAC_OFFSET          (HMAC_ID_OFFSET + HMAC_ID_LENGTH)
4188 
4189 static void
dissect_auth_chunk(tvbuff_t * chunk_tvb,guint16 chunk_length,proto_tree * chunk_tree,proto_item * chunk_item _U_)4190 dissect_auth_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, proto_tree *chunk_tree, proto_item *chunk_item _U_)
4191 {
4192   guint hmac_length;
4193 
4194   hmac_length = chunk_length - CHUNK_HEADER_LENGTH - HMAC_ID_LENGTH - SHARED_KEY_ID_LENGTH;
4195   proto_tree_add_item(chunk_tree, hf_shared_key_id, chunk_tvb, SHARED_KEY_ID_OFFSET, SHARED_KEY_ID_LENGTH, ENC_BIG_ENDIAN);
4196   proto_tree_add_item(chunk_tree, hf_hmac_id,       chunk_tvb, HMAC_ID_OFFSET,       HMAC_ID_LENGTH,       ENC_BIG_ENDIAN);
4197   if (hmac_length > 0)
4198     proto_tree_add_item(chunk_tree, hf_hmac,    chunk_tvb, HMAC_OFFSET,    hmac_length,    ENC_NA);
4199 }
4200 
4201 #define SCTP_SEQUENCE_NUMBER_LENGTH    4
4202 #define SEQUENCE_NUMBER_OFFSET    CHUNK_VALUE_OFFSET
4203 #define ASCONF_CHUNK_PARAMETERS_OFFSET (SEQUENCE_NUMBER_OFFSET + SCTP_SEQUENCE_NUMBER_LENGTH)
4204 
4205 static void
dissect_asconf_chunk(tvbuff_t * chunk_tvb,guint16 chunk_length,packet_info * pinfo,proto_tree * chunk_tree,proto_item * chunk_item)4206 dissect_asconf_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
4207 {
4208   tvbuff_t *parameters_tvb;
4209 
4210   if (chunk_length < CHUNK_HEADER_LENGTH + SCTP_SEQUENCE_NUMBER_LENGTH) {
4211     proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
4212                            chunk_length,
4213                            CHUNK_HEADER_LENGTH + SCTP_SEQUENCE_NUMBER_LENGTH);
4214     return;
4215   }
4216   if (chunk_tree) {
4217     proto_tree_add_item(chunk_tree, hf_asconf_seq_nr, chunk_tvb, SEQUENCE_NUMBER_OFFSET, SCTP_SEQUENCE_NUMBER_LENGTH, ENC_BIG_ENDIAN);
4218   }
4219   chunk_length -= CHUNK_HEADER_LENGTH + SCTP_SEQUENCE_NUMBER_LENGTH;
4220   parameters_tvb = tvb_new_subset_length_caplen(chunk_tvb, ASCONF_CHUNK_PARAMETERS_OFFSET,
4221                                   MIN(chunk_length, tvb_captured_length_remaining(chunk_tvb, ASCONF_CHUNK_PARAMETERS_OFFSET)),
4222                                   MIN(chunk_length, tvb_reported_length_remaining(chunk_tvb, ASCONF_CHUNK_PARAMETERS_OFFSET)));
4223   dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, FALSE);
4224 }
4225 
4226 #define ASCONF_ACK_CHUNK_PARAMETERS_OFFSET (SEQUENCE_NUMBER_OFFSET + SCTP_SEQUENCE_NUMBER_LENGTH)
4227 
4228 static void
dissect_asconf_ack_chunk(tvbuff_t * chunk_tvb,guint16 chunk_length,packet_info * pinfo,proto_tree * chunk_tree,proto_item * chunk_item)4229 dissect_asconf_ack_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
4230 {
4231   tvbuff_t *parameters_tvb;
4232 
4233   if (chunk_length < CHUNK_HEADER_LENGTH + SCTP_SEQUENCE_NUMBER_LENGTH) {
4234     proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
4235                            chunk_length + CHUNK_HEADER_LENGTH,
4236                            CHUNK_HEADER_LENGTH + SCTP_SEQUENCE_NUMBER_LENGTH);
4237     return;
4238   }
4239   if (chunk_tree) {
4240     proto_tree_add_item(chunk_tree, hf_asconf_ack_seq_nr, chunk_tvb, SEQUENCE_NUMBER_OFFSET, SCTP_SEQUENCE_NUMBER_LENGTH, ENC_BIG_ENDIAN);
4241   }
4242   chunk_length -= CHUNK_HEADER_LENGTH + SCTP_SEQUENCE_NUMBER_LENGTH;
4243   parameters_tvb = tvb_new_subset_length_caplen(chunk_tvb, ASCONF_ACK_CHUNK_PARAMETERS_OFFSET,
4244                                   MIN(chunk_length, tvb_captured_length_remaining(chunk_tvb, ASCONF_ACK_CHUNK_PARAMETERS_OFFSET)),
4245                                   MIN(chunk_length, tvb_reported_length_remaining(chunk_tvb, ASCONF_ACK_CHUNK_PARAMETERS_OFFSET)));
4246   dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, FALSE);
4247 }
4248 
4249 #define PKTDROP_CHUNK_BANDWIDTH_LENGTH      4
4250 #define PKTDROP_CHUNK_QUEUESIZE_LENGTH      4
4251 #define PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH 2
4252 #define PKTDROP_CHUNK_RESERVED_SIZE_LENGTH  2
4253 
4254 #define PKTDROP_CHUNK_HEADER_LENGTH (CHUNK_HEADER_LENGTH + \
4255                    PKTDROP_CHUNK_BANDWIDTH_LENGTH + \
4256                    PKTDROP_CHUNK_QUEUESIZE_LENGTH + \
4257                    PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH + \
4258                    PKTDROP_CHUNK_RESERVED_SIZE_LENGTH)
4259 
4260 #define PKTDROP_CHUNK_BANDWIDTH_OFFSET      CHUNK_VALUE_OFFSET
4261 #define PKTDROP_CHUNK_QUEUESIZE_OFFSET      (PKTDROP_CHUNK_BANDWIDTH_OFFSET + PKTDROP_CHUNK_BANDWIDTH_LENGTH)
4262 #define PKTDROP_CHUNK_TRUNCATED_SIZE_OFFSET (PKTDROP_CHUNK_QUEUESIZE_OFFSET + PKTDROP_CHUNK_QUEUESIZE_LENGTH)
4263 #define PKTDROP_CHUNK_RESERVED_SIZE_OFFSET  (PKTDROP_CHUNK_TRUNCATED_SIZE_OFFSET + PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH)
4264 #define PKTDROP_CHUNK_DATA_FIELD_OFFSET     (PKTDROP_CHUNK_RESERVED_SIZE_OFFSET + PKTDROP_CHUNK_RESERVED_SIZE_LENGTH)
4265 
4266 #define SCTP_PKTDROP_CHUNK_M_BIT 0x01
4267 #define SCTP_PKTDROP_CHUNK_B_BIT 0x02
4268 #define SCTP_PKTDROP_CHUNK_T_BIT 0x04
4269 
4270 static const true_false_string sctp_pktdropk_m_bit_value = {
4271   "Source is a middlebox",
4272   "Source is an endhost"
4273 };
4274 
4275 static const true_false_string sctp_pktdropk_b_bit_value = {
4276   "SCTP checksum was incorrect",
4277   "SCTP checksum was correct"
4278 };
4279 
4280 static const true_false_string sctp_pktdropk_t_bit_value = {
4281   "Packet is truncated",
4282   "Packet is not truncated"
4283 };
4284 
4285 static void
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)4286 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)
4287 {
4288   tvbuff_t *data_field_tvb;
4289   proto_tree *flags_tree;
4290 
4291   if (chunk_length < PKTDROP_CHUNK_HEADER_LENGTH) {
4292     proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
4293                            chunk_length,
4294                            PKTDROP_CHUNK_HEADER_LENGTH);
4295     return;
4296   }
4297   chunk_length -= PKTDROP_CHUNK_HEADER_LENGTH;
4298   data_field_tvb = tvb_new_subset_length_caplen(chunk_tvb, PKTDROP_CHUNK_DATA_FIELD_OFFSET,
4299                                   MIN(chunk_length, tvb_captured_length_remaining(chunk_tvb, PKTDROP_CHUNK_DATA_FIELD_OFFSET)),
4300                                   MIN(chunk_length, tvb_reported_length_remaining(chunk_tvb, PKTDROP_CHUNK_DATA_FIELD_OFFSET)));
4301 
4302   if (chunk_tree) {
4303     flags_tree  = proto_item_add_subtree(flags_item, ett_sctp_pktdrop_chunk_flags);
4304 
4305     proto_tree_add_item(flags_tree, hf_pktdrop_chunk_m_bit,            chunk_tvb, CHUNK_FLAGS_OFFSET,                  CHUNK_FLAGS_LENGTH,                  ENC_BIG_ENDIAN);
4306     proto_tree_add_item(flags_tree, hf_pktdrop_chunk_b_bit,            chunk_tvb, CHUNK_FLAGS_OFFSET,                  CHUNK_FLAGS_LENGTH,                  ENC_BIG_ENDIAN);
4307     proto_tree_add_item(flags_tree, hf_pktdrop_chunk_t_bit,            chunk_tvb, CHUNK_FLAGS_OFFSET,                  CHUNK_FLAGS_LENGTH,                  ENC_BIG_ENDIAN);
4308     proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_bandwidth,        chunk_tvb, PKTDROP_CHUNK_BANDWIDTH_OFFSET,      PKTDROP_CHUNK_BANDWIDTH_LENGTH,      ENC_BIG_ENDIAN);
4309     proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_queuesize,        chunk_tvb, PKTDROP_CHUNK_QUEUESIZE_OFFSET,      PKTDROP_CHUNK_QUEUESIZE_LENGTH,      ENC_BIG_ENDIAN);
4310     proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_truncated_length, chunk_tvb, PKTDROP_CHUNK_TRUNCATED_SIZE_OFFSET, PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH, ENC_BIG_ENDIAN);
4311     proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_reserved,         chunk_tvb, PKTDROP_CHUNK_RESERVED_SIZE_OFFSET,  PKTDROP_CHUNK_RESERVED_SIZE_LENGTH,  ENC_BIG_ENDIAN);
4312 
4313     if (chunk_length > 0) {
4314       /* XXX - We should dissect what we can and catch the BoundsError when we run out of bytes */
4315       if (tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_PKTDROP_CHUNK_T_BIT)
4316         proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_data_field,   chunk_tvb, PKTDROP_CHUNK_DATA_FIELD_OFFSET,     chunk_length,                   ENC_NA);
4317       else {
4318         gboolean save_in_error_pkt = pinfo->flags.in_error_pkt;
4319         pinfo->flags.in_error_pkt = TRUE;
4320 
4321         dissect_sctp_packet(data_field_tvb, pinfo, chunk_tree, TRUE);
4322 
4323         pinfo->flags.in_error_pkt = save_in_error_pkt;
4324       }
4325     }
4326   }
4327 }
4328 
4329 static void
dissect_pad_chunk(tvbuff_t * chunk_tvb,guint16 chunk_length,proto_tree * chunk_tree,proto_item * chunk_item)4330 dissect_pad_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, proto_tree *chunk_tree, proto_item *chunk_item)
4331 {
4332   guint16 value_length;
4333 
4334   if (chunk_tree) {
4335     value_length = chunk_length - CHUNK_HEADER_LENGTH;
4336     proto_tree_add_item(chunk_tree, hf_pad_chunk_padding_data, chunk_tvb, CHUNK_VALUE_OFFSET, value_length, ENC_NA);
4337     proto_item_append_text(chunk_item, " (Padding data length: %u byte%s)", value_length, plurality(value_length, "", "s"));
4338   }
4339 }
4340 
4341 static void
dissect_unknown_chunk(tvbuff_t * chunk_tvb,guint16 chunk_length,guint8 chunk_type,proto_tree * chunk_tree,proto_item * chunk_item)4342 dissect_unknown_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, guint8 chunk_type, proto_tree *chunk_tree, proto_item *chunk_item)
4343 {
4344   guint16 value_length;
4345 
4346   if (chunk_tree) {
4347     value_length = chunk_length - CHUNK_HEADER_LENGTH;
4348     if (value_length > 0)
4349       proto_tree_add_item(chunk_tree, hf_chunk_value, chunk_tvb, CHUNK_VALUE_OFFSET, value_length, ENC_NA);
4350     proto_item_append_text(chunk_item, " (Type: %u, value length: %u byte%s)", chunk_type, value_length, plurality(value_length, "", "s"));
4351   }
4352 }
4353 
4354 #define SCTP_CHUNK_BIT_1 0x80
4355 #define SCTP_CHUNK_BIT_2 0x40
4356 
4357 static const true_false_string sctp_chunk_bit_1_value = {
4358   "Skip chunk and continue processing of the packet",
4359   "Stop processing of the packet"
4360 };
4361 
4362 static const true_false_string sctp_chunk_bit_2_value = {
4363   "Do report",
4364   "Do not report"
4365 };
4366 
4367 
4368 static gboolean
dissect_sctp_chunk(tvbuff_t * chunk_tvb,packet_info * pinfo,proto_tree * tree,proto_tree * sctp_tree,sctp_half_assoc_t * ha,gboolean useinfo)4369 dissect_sctp_chunk(tvbuff_t *chunk_tvb,
4370                    packet_info *pinfo,
4371                    proto_tree *tree,
4372                    proto_tree *sctp_tree,
4373                    sctp_half_assoc_t *ha,
4374                    gboolean useinfo)
4375 {
4376   guint8 type;
4377   guint16 length, padding_length, reported_length;
4378   gboolean result;
4379   proto_item *flags_item, *chunk_item, *type_item, *length_item;
4380   proto_tree *chunk_tree, *type_tree;
4381 
4382   result = FALSE;
4383 
4384   /* first extract the chunk header */
4385   type            = tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET);
4386   length          = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
4387   reported_length = tvb_reported_length(chunk_tvb);
4388   padding_length  = reported_length - length;
4389 
4390   if (useinfo)
4391     col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str_const(type, chunk_type_values, "RESERVED"));
4392 
4393   /* create proto_tree stuff */
4394   chunk_tree   = proto_tree_add_subtree_format(sctp_tree, chunk_tvb, CHUNK_HEADER_OFFSET, reported_length,
4395                     ett_sctp_chunk, &chunk_item, "%s chunk",
4396                     val_to_str_const(type, chunk_type_values, "RESERVED"));
4397 
4398   if (tree) {
4399     /* then insert the chunk header components into the protocol tree */
4400     type_item  = proto_tree_add_item(chunk_tree, hf_chunk_type, chunk_tvb, CHUNK_TYPE_OFFSET, CHUNK_TYPE_LENGTH, ENC_BIG_ENDIAN);
4401     type_tree  = proto_item_add_subtree(type_item, ett_sctp_chunk_type);
4402     proto_tree_add_item(type_tree, hf_chunk_bit_1,  chunk_tvb, CHUNK_TYPE_OFFSET,  CHUNK_TYPE_LENGTH,  ENC_BIG_ENDIAN);
4403     proto_tree_add_item(type_tree, hf_chunk_bit_2,  chunk_tvb, CHUNK_TYPE_OFFSET,  CHUNK_TYPE_LENGTH,  ENC_BIG_ENDIAN);
4404     flags_item = proto_tree_add_item(chunk_tree, hf_chunk_flags, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, ENC_BIG_ENDIAN);
4405   } else {
4406     chunk_tree = NULL;
4407     chunk_item = NULL;
4408     flags_item = NULL;
4409   }
4410 
4411   if (length < CHUNK_HEADER_LENGTH) {
4412     if (tree) {
4413       proto_tree_add_uint_format_value(chunk_tree, hf_chunk_length, chunk_tvb, CHUNK_LENGTH_OFFSET, CHUNK_LENGTH_LENGTH, length,
4414                                  "%u (invalid, should be >= %u)", length, CHUNK_HEADER_LENGTH);
4415       proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)", length, CHUNK_HEADER_LENGTH);
4416     }
4417 
4418     if (type == SCTP_DATA_CHUNK_ID)
4419       result = TRUE;
4420     return result;
4421   }
4422 
4423   length_item = proto_tree_add_uint(chunk_tree, hf_chunk_length, chunk_tvb, CHUNK_LENGTH_OFFSET, CHUNK_LENGTH_LENGTH, length);
4424   if (length > reported_length && !pinfo->flags.in_error_pkt) {
4425     expert_add_info_format(pinfo, length_item, &ei_sctp_chunk_length_bad, "Chunk length (%d) is longer than remaining data (%d) in the packet.", length, reported_length);
4426     /* We'll almost certainly throw an exception shortly... */
4427   }
4428 
4429   /*
4430   length -= CHUNK_HEADER_LENGTH;
4431   */
4432 
4433   /* now dissect the chunk value */
4434   switch(type) {
4435   case SCTP_DATA_CHUNK_ID:
4436     result = dissect_data_chunk(chunk_tvb, length, pinfo, tree, chunk_tree, chunk_item, flags_item, ha, FALSE);
4437     break;
4438   case SCTP_I_DATA_CHUNK_ID:
4439     result = dissect_data_chunk(chunk_tvb, length, pinfo, tree, chunk_tree, chunk_item, flags_item, ha, TRUE);
4440     break;
4441   case SCTP_INIT_CHUNK_ID:
4442     dissect_init_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
4443     break;
4444   case SCTP_INIT_ACK_CHUNK_ID:
4445     dissect_init_ack_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
4446     break;
4447   case SCTP_SACK_CHUNK_ID:
4448     dissect_sack_chunk(pinfo, chunk_tvb, chunk_tree, chunk_item, flags_item, ha);
4449     break;
4450   case SCTP_HEARTBEAT_CHUNK_ID:
4451     dissect_heartbeat_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
4452     break;
4453   case SCTP_HEARTBEAT_ACK_CHUNK_ID:
4454     dissect_heartbeat_ack_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
4455     break;
4456   case SCTP_ABORT_CHUNK_ID:
4457     dissect_abort_chunk(chunk_tvb, length, pinfo, chunk_tree, flags_item);
4458     break;
4459   case SCTP_SHUTDOWN_CHUNK_ID:
4460     dissect_shutdown_chunk(chunk_tvb, chunk_tree, chunk_item);
4461     break;
4462   case SCTP_SHUTDOWN_ACK_CHUNK_ID:
4463     dissect_shutdown_ack_chunk(chunk_tvb);
4464     break;
4465   case SCTP_ERROR_CHUNK_ID:
4466     dissect_error_chunk(chunk_tvb, length, pinfo, chunk_tree);
4467     break;
4468   case SCTP_COOKIE_ECHO_CHUNK_ID:
4469     dissect_cookie_echo_chunk(chunk_tvb, length, chunk_tree, chunk_item);
4470     break;
4471   case SCTP_COOKIE_ACK_CHUNK_ID:
4472     dissect_cookie_ack_chunk(chunk_tvb);
4473     break;
4474   case SCTP_ECNE_CHUNK_ID:
4475     dissect_ecne_chunk(chunk_tvb, chunk_tree, chunk_item);
4476     break;
4477   case SCTP_CWR_CHUNK_ID:
4478     dissect_cwr_chunk(chunk_tvb, chunk_tree, chunk_item);
4479     break;
4480   case SCTP_SHUTDOWN_COMPLETE_CHUNK_ID:
4481     dissect_shutdown_complete_chunk(chunk_tvb, chunk_tree, flags_item);
4482     break;
4483   case SCTP_FORWARD_TSN_CHUNK_ID:
4484     dissect_forward_tsn_chunk(chunk_tvb, length, chunk_tree, chunk_item);
4485     break;
4486   case SCTP_RE_CONFIG_CHUNK_ID:
4487     dissect_re_config_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
4488     break;
4489   case SCTP_AUTH_CHUNK_ID:
4490     dissect_auth_chunk(chunk_tvb, length, chunk_tree, chunk_item);
4491     break;
4492   case SCTP_NR_SACK_CHUNK_ID:
4493     dissect_nr_sack_chunk(pinfo, chunk_tvb, chunk_tree, chunk_item, flags_item, ha);
4494     break;
4495   case SCTP_ASCONF_ACK_CHUNK_ID:
4496     dissect_asconf_ack_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
4497     break;
4498   case SCTP_ASCONF_CHUNK_ID:
4499     dissect_asconf_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
4500     break;
4501   case SCTP_I_FORWARD_TSN_CHUNK_ID:
4502     dissect_i_forward_tsn_chunk(chunk_tvb, length, chunk_tree, chunk_item);
4503     break;
4504   case SCTP_PKTDROP_CHUNK_ID:
4505     col_set_writable(pinfo->cinfo, -1, FALSE);
4506     dissect_pktdrop_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item, flags_item);
4507     col_set_writable(pinfo->cinfo, -1, TRUE);
4508     break;
4509   case SCTP_PAD_CHUNK_ID:
4510     dissect_pad_chunk(chunk_tvb, length, chunk_tree, chunk_item);
4511     break;
4512   default:
4513     dissect_unknown_chunk(chunk_tvb, length, type, chunk_tree, chunk_item);
4514     break;
4515   }
4516 
4517   if (padding_length > 0)
4518     proto_tree_add_item(chunk_tree, hf_chunk_padding, chunk_tvb, CHUNK_HEADER_OFFSET + length, padding_length, ENC_NA);
4519 
4520   if (useinfo && ((type == SCTP_DATA_CHUNK_ID) || show_always_control_chunks))
4521     col_set_fence(pinfo->cinfo, COL_INFO);
4522 
4523   return result;
4524 }
4525 
4526 static void
dissect_sctp_chunks(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,proto_item * sctp_item,proto_tree * sctp_tree,sctp_half_assoc_t * ha,gboolean encapsulated)4527 dissect_sctp_chunks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *sctp_item, proto_tree *sctp_tree, sctp_half_assoc_t *ha, gboolean encapsulated)
4528 {
4529   tvbuff_t *chunk_tvb;
4530   guint16 length, total_length, remaining_length;
4531   gint last_offset, offset;
4532   gboolean sctp_item_length_set;
4533   assoc_info_t tmpinfo;
4534   infodata_t id_dir;
4535 
4536   /* the common header of the datagram is already handled */
4537   last_offset = 0;
4538   offset = COMMON_HEADER_LENGTH;
4539   sctp_item_length_set = FALSE;
4540 
4541   while((remaining_length = tvb_reported_length_remaining(tvb, offset))) {
4542     /* extract the chunk length and compute number of padding bytes */
4543     length         = tvb_get_ntohs(tvb, offset + CHUNK_LENGTH_OFFSET);
4544     total_length   = ADD_PADDING(length);
4545 
4546     /*  If we have less bytes than we need, throw an exception while dissecting
4547      *  the chunk--not when generating the chunk_tvb below.
4548      */
4549     total_length = MIN(total_length, remaining_length);
4550 
4551     /* create a tvb for the chunk including the padding bytes */
4552     chunk_tvb = tvb_new_subset_length_caplen(tvb, offset, MIN(total_length, tvb_captured_length_remaining(tvb, offset)), total_length);
4553 
4554     /* save it in the sctp_info structure */
4555     if (!encapsulated) {
4556       if (sctp_info.number_of_tvbs < MAXIMUM_NUMBER_OF_TVBS)
4557         sctp_info.tvb[sctp_info.number_of_tvbs++] = chunk_tvb;
4558       else
4559         sctp_info.incomplete = TRUE;
4560     }
4561     if (enable_association_indexing) {
4562       tmpinfo.assoc_index = -1;
4563       tmpinfo.sport = sctp_info.sport;
4564       tmpinfo.dport = sctp_info.dport;
4565       tmpinfo.vtag_reflected = FALSE;
4566       if (tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET) == SCTP_ABORT_CHUNK_ID) {
4567         if ((tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_ABORT_CHUNK_T_BIT) != 0) {
4568           tmpinfo.vtag_reflected = TRUE;
4569         }
4570       }
4571       if (tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET) == SCTP_SHUTDOWN_COMPLETE_CHUNK_ID) {
4572         if ((tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT) != 0) {
4573           tmpinfo.vtag_reflected = TRUE;
4574         }
4575       }
4576       if (tmpinfo.vtag_reflected) {
4577         tmpinfo.verification_tag2 = sctp_info.verification_tag;
4578         tmpinfo.verification_tag1 = 0;
4579       }
4580       else {
4581         tmpinfo.verification_tag1 = sctp_info.verification_tag;
4582         tmpinfo.verification_tag2 = 0;
4583       }
4584       if (tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET) == SCTP_INIT_CHUNK_ID) {
4585         tmpinfo.initiate_tag = tvb_get_ntohl(sctp_info.tvb[0], 4);
4586       }
4587       else {
4588         tmpinfo.initiate_tag = 0;
4589       }
4590 
4591       id_dir = find_assoc_index(&tmpinfo, PINFO_FD_VISITED(pinfo));
4592       sctp_info.assoc_index = id_dir.assoc_index;
4593       sctp_info.direction = id_dir.direction;
4594     } else {
4595       sctp_info.assoc_index = -1;
4596       sctp_info.direction = ASSOC_NOT_FOUND;
4597     }
4598 
4599     /* call dissect_sctp_chunk for the actual work */
4600     if (dissect_sctp_chunk(chunk_tvb, pinfo, tree, sctp_tree, ha, !encapsulated) && (tree)) {
4601       proto_item_set_len(sctp_item, offset - last_offset + DATA_CHUNK_HEADER_LENGTH);
4602       sctp_item_length_set = TRUE;
4603       offset += total_length;
4604       last_offset = offset;
4605       if (tvb_reported_length_remaining(tvb, offset) > 0) {
4606         sctp_item = proto_tree_add_item(tree, proto_sctp, tvb, offset, -1, ENC_NA);
4607         sctp_tree = proto_item_add_subtree(sctp_item, ett_sctp);
4608         sctp_item_length_set = FALSE;
4609       }
4610     } else {
4611       /* get rid of the dissected chunk */
4612       offset += total_length;
4613     }
4614   }
4615   if (!sctp_item_length_set && (tree)) {
4616     proto_item_set_len(sctp_item, offset - last_offset);
4617   }
4618 }
4619 
4620 static void
dissect_sctp_packet(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,gboolean encapsulated)4621 dissect_sctp_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean encapsulated)
4622 {
4623   guint32 checksum = 0, calculated_crc32c = 0, calculated_adler32 = 0;
4624   guint16 source_port, destination_port;
4625   guint captured_length, reported_length;
4626   gboolean crc32c_correct = FALSE, adler32_correct = FALSE;
4627   proto_item *sctp_item, *hidden_item;
4628   proto_tree *sctp_tree;
4629   guint32 vtag;
4630   sctp_half_assoc_t *ha = NULL;
4631   proto_item *pi, *vt = NULL;
4632 
4633   captured_length = tvb_captured_length(tvb);
4634   reported_length = tvb_reported_length(tvb);
4635   checksum        = tvb_get_ntohl(tvb, CHECKSUM_OFFSET);
4636   sctp_info.checksum_zero = (checksum == 0);
4637 
4638   /* Only try to checksum the packet if we have all of it */
4639   if ((captured_length == reported_length) &&
4640      (captured_length >= COMMON_HEADER_LENGTH)) {
4641 
4642     switch(sctp_checksum) {
4643     case SCTP_CHECKSUM_NONE:
4644       break;
4645     case SCTP_CHECKSUM_ADLER32:
4646       calculated_adler32           = sctp_adler32(tvb, captured_length);
4647       adler32_correct              = (checksum == calculated_adler32);
4648       sctp_info.adler32_calculated = TRUE;
4649       sctp_info.adler32_correct    = adler32_correct;
4650       break;
4651     case SCTP_CHECKSUM_CRC32C:
4652       calculated_crc32c            = sctp_crc32c(tvb, captured_length);
4653       crc32c_correct               = (checksum == calculated_crc32c);
4654       sctp_info.crc32c_calculated  = TRUE;
4655       sctp_info.crc32c_correct     = crc32c_correct;
4656       break;
4657     case SCTP_CHECKSUM_AUTOMATIC:
4658       calculated_adler32           = sctp_adler32(tvb, captured_length);
4659       adler32_correct              = (checksum == calculated_adler32);
4660       calculated_crc32c            = sctp_crc32c(tvb, captured_length);
4661       crc32c_correct               = (checksum == calculated_crc32c);
4662       sctp_info.adler32_calculated = TRUE;
4663       sctp_info.adler32_correct    = adler32_correct;
4664       sctp_info.crc32c_calculated  = TRUE;
4665       sctp_info.crc32c_correct     = crc32c_correct;
4666       break;
4667     }
4668   }
4669 
4670   source_port      = tvb_get_ntohs(tvb, SOURCE_PORT_OFFSET);
4671   destination_port = tvb_get_ntohs(tvb, DESTINATION_PORT_OFFSET);
4672   vtag             = tvb_get_ntohl(tvb,VERIFICATION_TAG_OFFSET);
4673 
4674   ha = get_half_assoc(pinfo, source_port, destination_port, vtag);
4675 
4676   /* In the interest of speed, if "tree" is NULL, don't do any work not
4677      necessary to generate protocol tree items. */
4678   if (tree) {
4679 
4680     /* create the sctp protocol tree */
4681     if (show_port_numbers)
4682       sctp_item = proto_tree_add_protocol_format(tree, proto_sctp, tvb, 0, -1,
4683                                                  "Stream Control Transmission Protocol, Src Port: %s (%u), Dst Port: %s (%u)",
4684                                                  sctp_port_to_display(pinfo->pool, source_port), source_port,
4685                                                  sctp_port_to_display(pinfo->pool, destination_port), destination_port);
4686     else
4687       sctp_item = proto_tree_add_item(tree, proto_sctp, tvb, 0, -1, ENC_NA);
4688 
4689     sctp_tree = proto_item_add_subtree(sctp_item, ett_sctp);
4690 
4691     /* add the components of the common header to the protocol tree */
4692     proto_tree_add_item(sctp_tree, hf_source_port,      tvb, SOURCE_PORT_OFFSET,      SOURCE_PORT_LENGTH,      ENC_BIG_ENDIAN);
4693     proto_tree_add_item(sctp_tree, hf_destination_port, tvb, DESTINATION_PORT_OFFSET, DESTINATION_PORT_LENGTH, ENC_BIG_ENDIAN);
4694     vt = proto_tree_add_item(sctp_tree, hf_verification_tag, tvb, VERIFICATION_TAG_OFFSET, VERIFICATION_TAG_LENGTH, ENC_BIG_ENDIAN);
4695     hidden_item = proto_tree_add_item(sctp_tree, hf_port, tvb, SOURCE_PORT_OFFSET,      SOURCE_PORT_LENGTH,      ENC_BIG_ENDIAN);
4696     proto_item_set_hidden(hidden_item);
4697     hidden_item = proto_tree_add_item(sctp_tree, hf_port, tvb, DESTINATION_PORT_OFFSET, DESTINATION_PORT_LENGTH, ENC_BIG_ENDIAN);
4698     proto_item_set_hidden(hidden_item);
4699   } else {
4700     sctp_tree = NULL;
4701     sctp_item = NULL;
4702   }
4703 
4704   if (captured_length == reported_length) {
4705     /* We have the whole packet */
4706 
4707     switch(sctp_checksum) {
4708     case SCTP_CHECKSUM_NONE:
4709       proto_tree_add_checksum(sctp_tree, tvb, CHECKSUM_OFFSET, hf_checksum, hf_checksum_status, &ei_sctp_bad_sctp_checksum, pinfo, 0,
4710                               ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
4711       break;
4712     case SCTP_CHECKSUM_ADLER32:
4713       proto_tree_add_checksum(sctp_tree, tvb, CHECKSUM_OFFSET, hf_checksum_adler, hf_checksum_status, &ei_sctp_bad_sctp_checksum, pinfo, calculated_adler32,
4714                               ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
4715       break;
4716     case SCTP_CHECKSUM_CRC32C:
4717       proto_tree_add_checksum(sctp_tree, tvb, CHECKSUM_OFFSET, hf_checksum_crc32c, hf_checksum_status, &ei_sctp_bad_sctp_checksum, pinfo, calculated_crc32c,
4718                               ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
4719       break;
4720     case SCTP_CHECKSUM_AUTOMATIC:
4721       if ((adler32_correct) && !(crc32c_correct))
4722         proto_tree_add_checksum(sctp_tree, tvb, CHECKSUM_OFFSET, hf_checksum_adler, hf_checksum_status, &ei_sctp_bad_sctp_checksum, pinfo, calculated_adler32,
4723                               ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
4724       else if ((!adler32_correct) && (crc32c_correct))
4725         proto_tree_add_checksum(sctp_tree, tvb, CHECKSUM_OFFSET, hf_checksum_crc32c, hf_checksum_status, &ei_sctp_bad_sctp_checksum, pinfo, calculated_crc32c,
4726                               ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
4727       else {
4728         proto_tree_add_checksum(sctp_tree, tvb, CHECKSUM_OFFSET, hf_checksum_adler, hf_checksum_status, &ei_sctp_bad_sctp_checksum, pinfo, calculated_adler32,
4729                               ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
4730         proto_tree_add_checksum(sctp_tree, tvb, CHECKSUM_OFFSET, hf_checksum_crc32c, hf_checksum_status, &ei_sctp_bad_sctp_checksum, pinfo, calculated_crc32c,
4731                               ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
4732       }
4733       break;
4734     }
4735   } else {
4736     /* We don't have the whole packet so we can't verify the checksum */
4737       proto_tree_add_checksum(sctp_tree, tvb, CHECKSUM_OFFSET, hf_checksum, hf_checksum_status, &ei_sctp_bad_sctp_checksum, pinfo, 0,
4738                               ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
4739   }
4740 
4741   /* add all chunks of the sctp datagram to the protocol tree */
4742   dissect_sctp_chunks(tvb, pinfo, tree, sctp_item, sctp_tree, ha, encapsulated);
4743 
4744   /* add assoc_index and move it behind the verification tag */
4745   if (enable_association_indexing) {
4746      pi = proto_tree_add_uint(sctp_tree, hf_sctp_assoc_index, tvb, 0 , 0, sctp_info.assoc_index);
4747   }
4748   else {
4749      pi = proto_tree_add_uint_format_value(sctp_tree, hf_sctp_assoc_index, tvb, 0 , 0, sctp_info.assoc_index, "disabled (enable in preferences)");
4750   }
4751   proto_item_set_generated(pi);
4752   proto_tree_move_item(sctp_tree, vt, pi);
4753 }
4754 
4755 static gboolean
capture_sctp(const guchar * pd _U_,int offset _U_,int len _U_,capture_packet_info_t * cpinfo,const union wtap_pseudo_header * pseudo_header _U_)4756 capture_sctp(const guchar *pd _U_, int offset _U_, int len _U_, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header _U_)
4757 {
4758   capture_dissector_increment_count(cpinfo, proto_sctp);
4759   return TRUE;
4760 }
4761 
4762 static int
dissect_sctp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)4763 dissect_sctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
4764 {
4765   guint16 source_port, destination_port;
4766   guint      number_of_ppid;
4767 
4768   /* Extract the common header */
4769   source_port      = tvb_get_ntohs(tvb, SOURCE_PORT_OFFSET);
4770   destination_port = tvb_get_ntohs(tvb, DESTINATION_PORT_OFFSET);
4771 
4772   /* update pi structure */
4773   pinfo->ptype    = PT_SCTP;
4774   pinfo->srcport  = source_port;
4775   pinfo->destport = destination_port;
4776 
4777   /* make entry in the Protocol column on summary display */
4778   col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCTP");
4779 
4780   /* Clear entries in Info column on summary display */
4781   col_set_str(pinfo->cinfo, COL_INFO, "");
4782 
4783 
4784   for(number_of_ppid = 0; number_of_ppid < MAX_NUMBER_OF_PPIDS; number_of_ppid++) {
4785     p_add_proto_data(pinfo->pool, pinfo, proto_sctp, number_of_ppid, GUINT_TO_POINTER(LAST_PPID));
4786   }
4787 
4788   /*  The tvb array in struct _sctp_info is huge: currently 2k pointers.
4789    *  We know (by the value of 'number_of_tvbs') which of these entries have
4790    *  been used, so don't memset() the array.  This saves us from zeroing out
4791    *  8k (4-byte pointers) or 16k (8-byte pointers) of memory every time we
4792    *  dissect a packet (saving quite a bit of time!).
4793    */
4794   sctp_info.incomplete = 0;
4795   sctp_info.adler32_calculated = 0;
4796   sctp_info.adler32_correct = 0;
4797   sctp_info.crc32c_calculated = 0;
4798   sctp_info.crc32c_correct = 0;
4799   sctp_info.vtag_reflected = 0;
4800   sctp_info.number_of_tvbs = 0;
4801   sctp_info.verification_tag = tvb_get_ntohl(tvb, VERIFICATION_TAG_OFFSET);
4802 
4803   sctp_info.sport = pinfo->srcport;
4804   sctp_info.dport = pinfo->destport;
4805   set_address(&sctp_info.ip_src, pinfo->src.type, pinfo->src.len, pinfo->src.data);
4806   set_address(&sctp_info.ip_dst, pinfo->dst.type, pinfo->dst.len, pinfo->dst.data);
4807 
4808   p_add_proto_data(pinfo->pool, pinfo, hf_source_port, pinfo->curr_layer_num, GUINT_TO_POINTER(pinfo->srcport));
4809   p_add_proto_data(pinfo->pool, pinfo, hf_destination_port, pinfo->curr_layer_num, GUINT_TO_POINTER(pinfo->destport));
4810 
4811   dissect_sctp_packet(tvb, pinfo, tree, FALSE);
4812   if (!pinfo->flags.in_error_pkt && sctp_info.number_of_tvbs > 0)
4813     tap_queue_packet(sctp_tap, pinfo, &sctp_info);
4814 
4815   return tvb_captured_length(tvb);
4816 }
4817 
4818 /* Register the protocol with Wireshark */
4819 void
proto_register_sctp(void)4820 proto_register_sctp(void)
4821 {
4822 
4823   /* Setup list of header fields */
4824   static hf_register_info hf[] = {
4825     { &hf_source_port,                              { "Source port",                                    "sctp.srcport",                                         FT_UINT16,  BASE_PT_SCTP, NULL,                                        0x0,                                NULL, HFILL } },
4826     { &hf_destination_port,                         { "Destination port",                               "sctp.dstport",                                         FT_UINT16,  BASE_PT_SCTP, NULL,                                        0x0,                                NULL, HFILL } },
4827     { &hf_port,                                     { "Port",                                           "sctp.port",                                            FT_UINT16,  BASE_PT_SCTP, NULL,                                        0x0,                                NULL, HFILL } },
4828     { &hf_verification_tag,                         { "Verification tag",                               "sctp.verification_tag",                                FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
4829     { &hf_checksum,                                 { "Checksum",                                       "sctp.checksum",                                        FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
4830     { &hf_checksum_adler,                           { "Checksum (Adler)",                               "sctp.checksum",                                        FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
4831     { &hf_checksum_crc32c,                          { "Checksum (CRC32C)",                              "sctp.checksum",                                        FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
4832     { &hf_checksum_status,                          { "Checksum Status",                                "sctp.checksum.status",                                 FT_UINT8,   BASE_NONE, VALS(proto_checksum_vals),                      0x0,                                NULL, HFILL } },
4833     { &hf_chunk_type,                               { "Chunk type",                                     "sctp.chunk_type",                                      FT_UINT8,   BASE_DEC,  VALS(chunk_type_values),                        0x0,                                NULL, HFILL } },
4834     { &hf_chunk_flags,                              { "Chunk flags",                                    "sctp.chunk_flags",                                     FT_UINT8,   BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
4835     { &hf_chunk_bit_1,                              { "Bit",                                            "sctp.chunk_bit_1",                                     FT_BOOLEAN, 8,         TFS(&sctp_chunk_bit_1_value),                   SCTP_CHUNK_BIT_1,                   NULL, HFILL } },
4836     { &hf_chunk_bit_2,                              { "Bit",                                            "sctp.chunk_bit_2",                                     FT_BOOLEAN, 8,         TFS(&sctp_chunk_bit_2_value),                   SCTP_CHUNK_BIT_2,                   NULL, HFILL } },
4837     { &hf_chunk_length,                             { "Chunk length",                                   "sctp.chunk_length",                                    FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4838     { &hf_chunk_padding,                            { "Chunk padding",                                  "sctp.chunk_padding",                                   FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
4839     { &hf_chunk_value,                              { "Chunk value",                                    "sctp.chunk_value",                                     FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
4840     { &hf_cookie,                                   { "Cookie",                                         "sctp.cookie",                                          FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
4841     { &hf_initiate_tag,                             { "Initiate tag",                                   "sctp.initiate_tag",                                    FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
4842     { &hf_init_chunk_initiate_tag,                  { "Initiate tag",                                   "sctp.init_initiate_tag",                               FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
4843     { &hf_init_chunk_adv_rec_window_credit,         { "Advertised receiver window credit (a_rwnd)",     "sctp.init_credit",                                     FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4844     { &hf_init_chunk_number_of_outbound_streams,    { "Number of outbound streams",                     "sctp.init_nr_out_streams",                             FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4845     { &hf_init_chunk_number_of_inbound_streams,     { "Number of inbound streams",                      "sctp.init_nr_in_streams",                              FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4846     { &hf_init_chunk_initial_tsn,                   { "Initial TSN",                                    "sctp.init_initial_tsn",                                FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4847     { &hf_initack_chunk_initiate_tag,               { "Initiate tag",                                   "sctp.initack_initiate_tag",                            FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
4848     { &hf_initack_chunk_adv_rec_window_credit,      { "Advertised receiver window credit (a_rwnd)",     "sctp.initack_credit",                                  FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4849     { &hf_initack_chunk_number_of_outbound_streams, { "Number of outbound streams",                     "sctp.initack_nr_out_streams",                          FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4850     { &hf_initack_chunk_number_of_inbound_streams,  { "Number of inbound streams",                      "sctp.initack_nr_in_streams",                           FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4851     { &hf_initack_chunk_initial_tsn,                { "Initial TSN",                                    "sctp.initack_initial_tsn",                             FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4852     { &hf_data_chunk_tsn,                           { "Transmission sequence number (relative)",        "sctp.data_tsn",                                        FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4853     { &hf_data_chunk_tsn_raw,                       { "Transmission sequence number (absolute)",        "sctp.data_tsn_raw",                                    FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4854     { &hf_data_chunk_stream_id,                     { "Stream identifier",                              "sctp.data_sid",                                        FT_UINT16,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
4855     { &hf_data_chunk_stream_seq_number,             { "Stream sequence number",                         "sctp.data_ssn",                                        FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4856     { &hf_data_chunk_payload_proto_id,              { "Payload protocol identifier",                    "sctp.data_payload_proto_id",                           FT_UINT32,  BASE_DEC|BASE_EXT_STRING, &sctpppid_val_ext,               0x0,                                NULL, HFILL } },
4857     { &hf_idata_chunk_reserved,                     { "Reserved",                                       "sctp.data_reserved",                                   FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4858     { &hf_idata_chunk_mid,                          { "Message identifier",                             "sctp.data_mid",                                        FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4859     { &hf_idata_chunk_fsn,                          { "Fragment sequence number",                       "sctp.data_fsn",                                        FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4860     { &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 } },
4861     { &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 } },
4862     { &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 } },
4863     { &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 } },
4864     { &hf_sack_chunk_ns,                            { "Nounce sum",                                     "sctp.sack_nounce_sum",                                 FT_UINT8,   BASE_DEC,  NULL,                                           SCTP_SACK_CHUNK_NS_BIT,             NULL, HFILL } },
4865     { &hf_sack_chunk_cumulative_tsn_ack,            { "Cumulative TSN ACK (relative)",                  "sctp.sack_cumulative_tsn_ack",                         FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4866     { &hf_sack_chunk_cumulative_tsn_ack_raw,        { "Cumulative TSN ACK (absolute)",                  "sctp.sack_cumulative_tsn_ack_raw",                     FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4867     { &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 } },
4868     { &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 } },
4869     { &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 } },
4870     { &hf_sack_chunk_gap_block_start,               { "Start",                                          "sctp.sack_gap_block_start",                            FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4871     { &hf_sack_chunk_gap_block_start_tsn,           { "Start TSN",                                      "sctp.sack_gap_block_start_tsn",                        FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4872     { &hf_sack_chunk_gap_block_end,                 { "End",                                            "sctp.sack_gap_block_end",                              FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4873     { &hf_sack_chunk_gap_block_end_tsn,             { "End TSN",                                        "sctp.sack_gap_block_end_tsn",                          FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4874     { &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 } },
4875     { &hf_sack_chunk_duplicate_tsn,                 { "Duplicate TSN",                                  "sctp.sack_duplicate_tsn",                              FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4876     { &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 } },
4877     { &hf_nr_sack_chunk_cumulative_tsn_ack,         { "Cumulative TSN ACK",                             "sctp.nr_sack_cumulative_tsn_ack",                      FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4878     { &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 } },
4879     { &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 } },
4880     { &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 } },
4881     { &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 } },
4882     { &hf_nr_sack_chunk_reserved,                   { "Reserved",                                       "sctp.nr_sack_reserved",                                FT_UINT16,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
4883     { &hf_nr_sack_chunk_gap_block_start,            { "Start",                                          "sctp.nr_sack_gap_block_start",                         FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4884     { &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 } },
4885     { &hf_nr_sack_chunk_gap_block_end,              { "End",                                            "sctp.nr_sack_gap_block_end",                           FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4886     { &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 } },
4887     { &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 } },
4888     { &hf_nr_sack_chunk_nr_gap_block_start,         { "Start",                                          "sctp.nr_sack_nr_gap_block_start",                      FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4889     { &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 } },
4890     { &hf_nr_sack_chunk_nr_gap_block_end,           { "End",                                            "sctp.nr_sack_nr_gap_block_end",                        FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4891     { &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 } },
4892     { &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 } },
4893     { &hf_nr_sack_chunk_duplicate_tsn,              { "Duplicate TSN",                                  "sctp.nr_sack_duplicate_tsn",                           FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4894     { &hf_shutdown_chunk_cumulative_tsn_ack,        { "Cumulative TSN Ack",                             "sctp.shutdown_cumulative_tsn_ack",                     FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4895     { &hf_ecne_chunk_lowest_tsn,                    { "Lowest TSN",                                     "sctp.ecne_lowest_tsn",                                 FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4896     { &hf_cwr_chunk_lowest_tsn,                     { "Lowest TSN",                                     "sctp.cwr_lowest_tsn",                                  FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4897     { &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 } },
4898     { &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 } },
4899     { &hf_forward_tsn_chunk_tsn,                    { "New cumulative TSN",                             "sctp.forward_tsn_tsn",                                 FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4900     { &hf_forward_tsn_chunk_sid,                    { "Stream identifier",                              "sctp.forward_tsn_sid",                                 FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4901     { &hf_forward_tsn_chunk_ssn,                    { "Stream sequence number",                         "sctp.forward_tsn_ssn",                                 FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4902     { &hf_i_forward_tsn_chunk_tsn,                  { "New cumulative TSN",                             "sctp.i_forward_tsn_tsn",                               FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4903     { &hf_i_forward_tsn_chunk_sid,                  { "Stream identifier",                              "sctp.i_forward_tsn_sid",                               FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4904     { &hf_i_forward_tsn_chunk_flags,                { "Flags",                                          "sctp.i_forward_tsn_flags",                             FT_UINT16,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
4905     { &hf_i_forward_tsn_chunk_res,                  { "Reserved",                                       "sctp.i_forward_tsn_res",                               FT_UINT16,  BASE_DEC,  NULL,                                           SCTP_I_FORWARD_TSN_CHUNK_RES_MASK,  NULL, HFILL } },
4906     { &hf_i_forward_tsn_chunk_u_bit,                { "U-Bit",                                          "sctp.i_forward_tsn_u_bit",                             FT_BOOLEAN, 16,        TFS(&sctp_i_forward_tsn_chunk_u_bit_value),     SCTP_I_FORWARD_TSN_CHUNK_U_BIT,     NULL, HFILL } },
4907     { &hf_i_forward_tsn_chunk_mid,                  { "Message identifier",                             "sctp.forward_tsn_mid",                                 FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4908     { &hf_parameter_type,                           { "Parameter type",                                 "sctp.parameter_type",                                  FT_UINT16,  BASE_HEX,  VALS(parameter_identifier_values),              0x0,                                NULL, HFILL } },
4909     { &hf_parameter_length,                         { "Parameter length",                               "sctp.parameter_length",                                FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4910     { &hf_parameter_value,                          { "Parameter value",                                "sctp.parameter_value",                                 FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
4911     { &hf_parameter_padding,                        { "Parameter padding",                              "sctp.parameter_padding",                               FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
4912     { &hf_parameter_bit_1,                          { "Bit",                                            "sctp.parameter_bit_1",                                 FT_BOOLEAN, 16,        TFS(&sctp_parameter_bit_1_value),               SCTP_PARAMETER_BIT_1,               NULL, HFILL } },
4913     { &hf_parameter_bit_2,                          { "Bit",                                            "sctp.parameter_bit_2",                                 FT_BOOLEAN, 16,        TFS(&sctp_parameter_bit_2_value),               SCTP_PARAMETER_BIT_2,               NULL, HFILL } },
4914     { &hf_ipv4_address,                             { "IP Version 4 address",                           "sctp.parameter_ipv4_address",                          FT_IPv4,    BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
4915     { &hf_ipv6_address,                             { "IP Version 6 address",                           "sctp.parameter_ipv6_address",                          FT_IPv6,    BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
4916     { &hf_heartbeat_info,                           { "Heartbeat information",                          "sctp.parameter_heartbeat_information",                 FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
4917     { &hf_state_cookie,                             { "State cookie",                                   "sctp.parameter_state_cookie",                          FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
4918     { &hf_cookie_preservative_increment,            { "Suggested Cookie life-span increment (msec)",    "sctp.parameter_cookie_preservative_incr",              FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4919     { &hf_hostname,                                 { "Hostname",                                       "sctp.parameter_hostname",                              FT_STRING,  BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
4920     { &hf_supported_address_type,                   { "Supported address type",                         "sctp.parameter_supported_address_type",                FT_UINT16,  BASE_DEC,  VALS(address_types_values),                     0x0,                                NULL, HFILL } },
4921     { &hf_stream_reset_req_seq_nr,                  { "Re-configuration request sequence number",       "sctp.parameter_reconfig_request_sequence_number",      FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4922     { &hf_stream_reset_rsp_seq_nr,                  { "Re-configuration response sequence number",      "sctp.parameter_reconfig_response_sequence_number",     FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4923     { &hf_senders_last_assigned_tsn,                { "Senders last assigned TSN",                      "sctp.parameter_senders_last_assigned_tsn",             FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4924     { &hf_senders_next_tsn,                         { "Senders next TSN",                               "sctp.parameter_senders_next_tsn",                      FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4925     { &hf_receivers_next_tsn,                       { "Receivers next TSN",                             "sctp.parameter_receivers_next_tsn",                    FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4926     { &hf_stream_reset_rsp_result,                  { "Result",                                         "sctp.parameter_reconfig_response_result",              FT_UINT32,  BASE_DEC,  VALS(stream_reset_result_values),               0x0,                                NULL, HFILL } },
4927     { &hf_stream_reset_sid,                         { "Stream Identifier",                              "sctp.parameter_reconfig_sid",                          FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4928     { &hf_add_outgoing_streams_number_streams,      { "Number of streams",                              "sctp.parameter_add_outgoing_streams_number",           FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4929     { &hf_add_outgoing_streams_reserved,            { "Reserved",                                       "sctp.parameter_add_outgoing_streams_reserved",         FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4930     { &hf_add_incoming_streams_number_streams,      { "Number of streams",                              "sctp.parameter_add_incoming_streams_number",           FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4931     { &hf_add_incoming_streams_reserved,            { "Reserved",                                       "sctp.parameter_add_incoming_streams_reserved",         FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4932     { &hf_asconf_seq_nr,                            { "Sequence number",                                "sctp.asconf_seq_nr_number",                            FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
4933     { &hf_asconf_ack_seq_nr,                        { "Sequence number",                                "sctp.asconf_ack_seq_nr_number",                        FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
4934     { &hf_correlation_id,                           { "Correlation_id",                                 "sctp.correlation_id",                                  FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
4935     { &hf_adap_indication,                          { "Indication",                                     "sctp.adaptation_layer_indication",                     FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
4936     { &hf_random_number,                            { "Random number",                                  "sctp.random_number",                                   FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
4937     { &hf_chunks_to_auth,                           { "Chunk type",                                     "sctp.chunk_type_to_auth",                              FT_UINT8,   BASE_DEC,  VALS(chunk_type_values),                        0x0,                                NULL, HFILL } },
4938     { &hf_hmac_id,                                  { "HMAC identifier",                                "sctp.hmac_id",                                         FT_UINT16,  BASE_DEC,  VALS(hmac_id_values),                           0x0,                                NULL, HFILL } },
4939     { &hf_hmac,                                     { "HMAC",                                           "sctp.hmac",                                            FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
4940     { &hf_shared_key_id,                            { "Shared key identifier",                          "sctp.shared_key_id",                                   FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4941     { &hf_supported_chunk_type,                     { "Supported chunk type",                           "sctp.supported_chunk_type",                            FT_UINT8,   BASE_DEC,  VALS(chunk_type_values),                        0x0,                                NULL, HFILL } },
4942     { &hf_cause_code,                               { "Cause code",                                     "sctp.cause_code",                                      FT_UINT16,  BASE_HEX,  VALS(cause_code_values),                        0x0,                                NULL, HFILL } },
4943     { &hf_cause_length,                             { "Cause length",                                   "sctp.cause_length",                                    FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4944     { &hf_cause_info,                               { "Cause information",                              "sctp.cause_information",                               FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
4945     { &hf_cause_padding,                            { "Cause padding",                                  "sctp.cause_padding",                                   FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
4946     { &hf_cause_stream_identifier,                  { "Stream identifier",                              "sctp.cause_stream_identifier",                         FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4947     { &hf_cause_reserved,                           { "Reserved",                                       "sctp.cause_reserved",                                  FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4948     { &hf_cause_number_of_missing_parameters,       { "Number of missing parameters",                   "sctp.cause_nr_of_missing_parameters",                  FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4949     { &hf_cause_missing_parameter_type,             { "Missing parameter type",                         "sctp.cause_missing_parameter_type",                    FT_UINT16,  BASE_HEX,  VALS(parameter_identifier_values),              0x0,                                NULL, HFILL } },
4950     { &hf_cause_measure_of_staleness,               { "Measure of staleness in usec",                   "sctp.cause_measure_of_staleness",                      FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4951     { &hf_cause_tsn,                                { "TSN",                                            "sctp.cause_tsn",                                       FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4952     { &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 } },
4953     { &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 } },
4954     { &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 } },
4955     { &hf_pktdrop_chunk_bandwidth,                  { "Bandwidth",                                      "sctp.pktdrop_bandwidth",                               FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4956     { &hf_pktdrop_chunk_queuesize,                  { "Queuesize",                                      "sctp.pktdrop_queuesize",                               FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4957     { &hf_pktdrop_chunk_truncated_length,           { "Truncated length",                               "sctp.pktdrop_truncated_length",                        FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4958     { &hf_pktdrop_chunk_reserved,                   { "Reserved",                                       "sctp.pktdrop_reserved",                                FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4959     { &hf_pktdrop_chunk_data_field,                 { "Data field",                                     "sctp.pktdrop_datafield",                               FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
4960     { &hf_pad_chunk_padding_data,                   { "Padding data",                                   "sctp.padding_data",                                    FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
4961 
4962     { &hf_sctp_fragment,                            { "SCTP Fragment",                                  "sctp.fragment",                                        FT_FRAMENUM, BASE_NONE, NULL,                                          0x0,                                NULL, HFILL } },
4963     { &hf_sctp_fragments,                           { "Reassembled SCTP Fragments",                     "sctp.fragments",                                       FT_NONE,    BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
4964     { &hf_sctp_reassembled_in,                      { "Reassembled Message in frame",                   "sctp.reassembled_in",                                  FT_FRAMENUM, BASE_NONE, NULL,                                          0x0,                                NULL, HFILL } },
4965     { &hf_sctp_duplicate,                           { "Fragment already seen in frame",                 "sctp.duplicate",                                       FT_FRAMENUM, BASE_NONE, NULL,                                          0x0,                                NULL, HFILL } },
4966 
4967     { &hf_sctp_data_rtt,                            { "The RTT to SACK was",                            "sctp.data_rtt",                                        FT_RELATIVE_TIME, BASE_NONE, NULL,                                     0x0,                                NULL, HFILL } },
4968     { &hf_sctp_sack_rtt,                            { "The RTT since DATA was",                         "sctp.sack_rtt",                                        FT_RELATIVE_TIME, BASE_NONE, NULL,                                     0x0,                                NULL, HFILL } },
4969     { &hf_sctp_rto,                                 { "Retransmitted after",                            "sctp.retransmission_time",                             FT_RELATIVE_TIME, BASE_NONE, NULL,                                     0x0,                                NULL, HFILL } },
4970     { &hf_sctp_retransmission,                      { "This TSN is a retransmission of one in frame",   "sctp.retransmission",                                  FT_FRAMENUM, BASE_NONE, NULL,                                          0x0,                                NULL, HFILL } },
4971     { &hf_sctp_retransmitted,                       { "This TSN is retransmitted in frame",             "sctp.retransmitted",                                   FT_FRAMENUM, BASE_NONE, NULL,                                          0x0,                                NULL, HFILL } },
4972     { &hf_sctp_retransmitted_count,                 { "TSN was retransmitted this many times",          "sctp.retransmitted_count",                             FT_UINT32, BASE_DEC, NULL,                                             0x0,                                NULL, HFILL } },
4973     { &hf_sctp_acked,                               { "This chunk is acked in frame",                   "sctp.acked",                                           FT_FRAMENUM, BASE_NONE, NULL,                                          0x0,                                NULL, HFILL } },
4974     { &hf_sctp_ack_tsn,                             { "Acknowledges TSN",                               "sctp.ack",                                             FT_UINT32, BASE_DEC, NULL,                                             0x0,                                NULL, HFILL } },
4975     { &hf_sctp_ack_frame,                           { "Acknowledges TSN in frame",                      "sctp.ack_frame",                                       FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_ACK),                0x0,                                NULL, HFILL } },
4976     { &hf_sctp_retransmitted_after_ack,             { "Chunk was acked prior to retransmission",        "sctp.retransmitted_after_ack",                         FT_FRAMENUM, BASE_NONE, NULL,                                          0x0,                                NULL, HFILL } },
4977     { &hf_sctp_assoc_index,                         { "Association index",                              "sctp.assoc_index",                                     FT_UINT16, BASE_DEC, NULL,                                             0x0,                                NULL, HFILL } }
4978 
4979  };
4980 
4981   /* Setup protocol subtree array */
4982   static gint *ett[] = {
4983     &ett_sctp,
4984     &ett_sctp_chunk,
4985     &ett_sctp_chunk_parameter,
4986     &ett_sctp_chunk_cause,
4987     &ett_sctp_chunk_type,
4988     &ett_sctp_data_chunk_flags,
4989     &ett_sctp_sack_chunk_flags,
4990     &ett_sctp_nr_sack_chunk_flags,
4991     &ett_sctp_abort_chunk_flags,
4992     &ett_sctp_shutdown_complete_chunk_flags,
4993     &ett_sctp_pktdrop_chunk_flags,
4994     &ett_sctp_parameter_type,
4995     &ett_sctp_sack_chunk_gap_block,
4996     &ett_sctp_sack_chunk_gap_block_start,
4997     &ett_sctp_sack_chunk_gap_block_end,
4998     &ett_sctp_nr_sack_chunk_gap_block,
4999     &ett_sctp_nr_sack_chunk_gap_block_start,
5000     &ett_sctp_nr_sack_chunk_gap_block_end,
5001     &ett_sctp_nr_sack_chunk_nr_gap_block,
5002     &ett_sctp_nr_sack_chunk_nr_gap_block_start,
5003     &ett_sctp_nr_sack_chunk_nr_gap_block_end,
5004     &ett_sctp_unrecognized_parameter_parameter,
5005     &ett_sctp_i_forward_tsn_chunk_flags,
5006     &ett_sctp_fragments,
5007     &ett_sctp_fragment,
5008     &ett_sctp_ack,
5009     &ett_sctp_acked,
5010     &ett_sctp_tsn,
5011     &ett_sctp_tsn_retransmission,
5012     &ett_sctp_tsn_retransmitted_count,
5013     &ett_sctp_tsn_retransmitted
5014   };
5015 
5016   static ei_register_info ei[] = {
5017       { &ei_sctp_tsn_retransmitted, { "sctp.retransmission.expert", PI_SEQUENCE, PI_NOTE, "Retransmitted TSN", EXPFILL }},
5018       { &ei_sctp_retransmitted_after_ack, { "sctp.retransmitted_after_ack.expert", PI_SEQUENCE, PI_WARN, "This TSN was acked prior to this retransmission (reneged ack?).", EXPFILL }},
5019       { &ei_sctp_tsn_retransmitted_more_than_twice, { "sctp.retransmission.more_than_twice", PI_SEQUENCE, PI_WARN, "This TSN was retransmitted more than 2 times.", EXPFILL }},
5020       { &ei_sctp_parameter_padding, { "sctp.parameter_padding.expert", PI_MALFORMED, PI_NOTE, "The padding of this final parameter should be the padding of the chunk.", EXPFILL }},
5021       { &ei_sctp_parameter_length, { "sctp.parameter_length.bad", PI_MALFORMED, PI_ERROR, "Parameter length bad", EXPFILL }},
5022       { &ei_sctp_sack_chunk_adv_rec_window_credit, { "sctp.sack_a_rwnd.expert", PI_SEQUENCE, PI_NOTE, "Zero Advertised Receiver Window Credit", EXPFILL }},
5023       { &ei_sctp_sack_chunk_gap_block_malformed, { "sctp.sack_gap_block_malformed", PI_PROTOCOL, PI_ERROR, "Malformed gap block.", EXPFILL }},
5024       { &ei_sctp_sack_chunk_gap_block_out_of_order, { "sctp.sack_gap_block_out_of_order", PI_PROTOCOL, PI_WARN, "Gap blocks not in strict order.", EXPFILL }},
5025       { &ei_sctp_sack_chunk_number_tsns_gap_acked_100, { "sctp.sack_number_of_tsns_gap_acked.100", PI_SEQUENCE, PI_WARN, "More than 100 TSNs were gap-acknowledged in this SACK.", EXPFILL }},
5026       { &ei_sctp_nr_sack_chunk_number_tsns_gap_acked_100, { "sctp.nr_sack_number_of_tsns_gap_acked.100", PI_SEQUENCE, PI_WARN, "More than 100 TSNs were gap-acknowledged in this NR-SACK.", EXPFILL }},
5027       { &ei_sctp_nr_sack_chunk_number_tsns_nr_gap_acked_100, { "sctp.nr_sack_number_of_tsns_nr_gap_acked.100", PI_SEQUENCE, PI_WARN, "More than 100 TSNs were nr-gap-acknowledged in this NR-SACK.", EXPFILL }},
5028       { &ei_sctp_chunk_length_bad, { "sctp.chunk_length.bad", PI_MALFORMED, PI_ERROR, "Chunk length bad", EXPFILL }},
5029       { &ei_sctp_bad_sctp_checksum, { "sctp.checksum_bad.expert", PI_CHECKSUM, PI_ERROR, "Bad SCTP checksum.", EXPFILL }},
5030   };
5031 
5032   static const enum_val_t sctp_checksum_options[] = {
5033     { "none",      "None",        SCTP_CHECKSUM_NONE },
5034     { "adler-32",  "Adler 32",    SCTP_CHECKSUM_ADLER32 },
5035     { "crc-32c",   "CRC 32c",     SCTP_CHECKSUM_CRC32C },
5036     { "automatic", "Automatic",   SCTP_CHECKSUM_AUTOMATIC},
5037     { NULL, NULL, 0 }
5038   };
5039 
5040   /* Decode As handling */
5041   static build_valid_func sctp_da_src_values[1] = {sctp_src_value};
5042   static build_valid_func sctp_da_dst_values[1] = {sctp_dst_value};
5043   static build_valid_func sctp_da_both_values[2] = {sctp_src_value, sctp_dst_value};
5044   static decode_as_value_t sctp_da_port_values[3] = {{sctp_src_prompt, 1, sctp_da_src_values}, {sctp_dst_prompt, 1, sctp_da_dst_values}, {sctp_both_prompt, 2, sctp_da_both_values}};
5045   static decode_as_t sctp_da_port = {"sctp", "sctp.port", 3, 2, sctp_da_port_values, "SCTP", "port(s) as",
5046                                      decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL};
5047 
5048   static build_valid_func sctp_da_ppi_build_value1[1] = {sctp_ppi_value1};
5049   static build_valid_func sctp_da_ppi_build_value2[1] = {sctp_ppi_value2};
5050   static decode_as_value_t sctp_da_ppi_values[2] = {{sctp_ppi_prompt1, 1, sctp_da_ppi_build_value1}, {sctp_ppi_prompt2, 1, sctp_da_ppi_build_value2}};
5051   static decode_as_t sctp_da_ppi = {"sctp", "sctp.ppi", 2, 0, sctp_da_ppi_values, "SCTP", NULL,
5052                                     decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL};
5053 
5054   /* UAT for header fields */
5055   static uat_field_t custom_types_uat_fields[] = {
5056     UAT_FLD_NONE(type_fields, type_id, "Chunk ID", "IANA chunk type ID"),
5057     UAT_FLD_CSTRING(type_fields, type_name, "Type name", "Chunk Type name"),
5058     UAT_FLD_VS(type_fields, type_enable, "Visibility", chunk_enabled, "Hide or show the type in the chunk statistics"),
5059     UAT_END_FIELDS
5060   };
5061 
5062   module_t *sctp_module;
5063   expert_module_t* expert_sctp;
5064   uat_t* chunk_types_uat;
5065 
5066   chunk_types_uat = uat_new("Chunk types for the statistics dialog",
5067                             sizeof(type_field_t),
5068                             "statistics_chunk_types",
5069                             TRUE,
5070                             &type_fields,
5071                             &num_type_fields,
5072                             0,
5073                             NULL,
5074                             sctp_chunk_type_copy_cb,
5075                             sctp_chunk_type_update_cb,
5076                             sctp_chunk_type_free_cb,
5077                             NULL,
5078                             NULL,
5079                             custom_types_uat_fields
5080 );
5081 
5082   /* Register the protocol name and description */
5083   proto_sctp = proto_register_protocol("Stream Control Transmission Protocol", "SCTP", "sctp");
5084   sctp_module = prefs_register_protocol(proto_sctp, NULL);
5085   prefs_register_bool_preference(sctp_module, "show_port_numbers_in_tree",
5086                          "Show port numbers in the protocol tree",
5087                          "Show source and destination port numbers in the protocol tree",
5088                          &show_port_numbers);
5089   prefs_register_bool_preference(sctp_module, "relative_tsns", "Relative TSNs",
5090                          "Use relative TSNs instead of absolute ones",
5091                          &show_relative_tsns);
5092   prefs_register_enum_preference(sctp_module, "checksum", "Checksum type",
5093                          "The type of checksum used in SCTP packets",
5094                          &sctp_checksum, sctp_checksum_options, FALSE);
5095   prefs_register_bool_preference(sctp_module, "show_always_control_chunks",
5096                          "Show always control chunks",
5097                          "Show always SCTP control chunks in the Info column",
5098                          &show_always_control_chunks);
5099   prefs_register_bool_preference(sctp_module, "try_heuristic_first",
5100                          "Try heuristic sub-dissectors first",
5101                          "Try to decode a packet using an heuristic sub-dissector before using a sub-dissector registered to a specific port or PPI",
5102                          &try_heuristic_first);
5103   prefs_register_bool_preference(sctp_module, "reassembly",
5104                          "Reassemble fragmented SCTP user messages",
5105                          "Whether fragmented SCTP user messages should be reassembled",
5106                          &use_reassembly);
5107   prefs_register_bool_preference(sctp_module, "tsn_analysis",
5108                          "Enable TSN analysis",
5109                          "Match TSNs and their SACKs",
5110                          &enable_tsn_analysis);
5111   prefs_register_bool_preference(sctp_module, "association_index",
5112                          "Enable Association indexing (Can be CPU intense)",
5113                          "Match verification tags (CPU intense)",
5114                          &enable_association_indexing);
5115   prefs_register_bool_preference(sctp_module, "ulp_dissection",
5116                          "Dissect upper layer protocols",
5117                          "Dissect upper layer protocols",
5118                          &enable_ulp_dissection);
5119   prefs_register_uat_preference_qt(sctp_module, "statistics_chunk_types",
5120                          "Select the chunk types for the statistics dialog",
5121                          "Select the chunk types for the statistics dialog",
5122                          chunk_types_uat);
5123 
5124   /* Required function calls to register the header fields and subtrees used */
5125   proto_register_field_array(proto_sctp, hf, array_length(hf));
5126   proto_register_subtree_array(ett, array_length(ett));
5127   expert_sctp = expert_register_protocol(proto_sctp);
5128   expert_register_field_array(expert_sctp, ei, array_length(ei));
5129 
5130   sctp_tap = register_tap("sctp");
5131   exported_pdu_tap = find_tap_id(EXPORT_PDU_TAP_NAME_LAYER_3);
5132   /* subdissector code */
5133   sctp_port_dissector_table = register_dissector_table("sctp.port", "SCTP port", proto_sctp, FT_UINT16, BASE_DEC);
5134   sctp_ppi_dissector_table  = register_dissector_table("sctp.ppi",  "SCTP payload protocol identifier", proto_sctp, FT_UINT32, BASE_HEX);
5135 
5136   sctp_handle = register_dissector("sctp", dissect_sctp, proto_sctp);
5137   sctp_heur_subdissector_list = register_heur_dissector_list("sctp", proto_sctp);
5138 
5139   register_init_routine(sctp_init);
5140   register_cleanup_routine(sctp_cleanup);
5141 
5142   dirs_by_ptvtag = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
5143   dirs_by_ptaddr = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
5144 
5145   register_decode_as(&sctp_da_port);
5146   register_decode_as(&sctp_da_ppi);
5147 
5148   register_conversation_table(proto_sctp, FALSE, sctp_conversation_packet, sctp_hostlist_packet);
5149 }
5150 
5151 void
proto_reg_handoff_sctp(void)5152 proto_reg_handoff_sctp(void)
5153 {
5154   capture_dissector_handle_t sctp_cap_handle;
5155 
5156   dissector_add_uint("wtap_encap", WTAP_ENCAP_SCTP, sctp_handle);
5157   dissector_add_uint("ip.proto", IP_PROTO_SCTP, sctp_handle);
5158   dissector_add_uint_with_preference("udp.port", UDP_TUNNELING_PORT, sctp_handle);
5159   sctp_cap_handle = create_capture_dissector_handle(capture_sctp, proto_sctp);
5160   capture_dissector_add_uint("ip.proto", IP_PROTO_SCTP, sctp_cap_handle);
5161 }
5162 
5163 /*
5164  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
5165  *
5166  * Local variables:
5167  * c-basic-offset: 2
5168  * tab-width: 8
5169  * indent-tabs-mode: nil
5170  * End:
5171  *
5172  * vi: set shiftwidth=2 tabstop=8 expandtab:
5173  * :indentSize=2:tabSize=8:noTabs=true:
5174  */
5175