Don't guard col_set_str (COL_PROTOCOL) with col_check
[metze/wireshark/wip.git] / epan / dissectors / packet-sctp.c
1 /* packet-sctp.c
2  * Routines for Stream Control Transmission Protocol dissection
3  *
4  * It should be compliant to
5  * - RFC 2960
6  * - RFC 3309
7  * - RFC 3758
8  * - RFC 4460
9  * - http://www.ietf.org/internet-drafts/draft-ietf-tsvwg-addip-sctp-18.txt
10  * - http://www.ietf.org/internet-drafts/draft-ietf-tsvwg-sctp-auth-08.txt
11  * - http://www.ietf.org/internet-drafts/draft-stewart-sctp-pktdrprep-02.txt
12  * - http://www.ietf.org/internet-drafts/draft-stewart-sctpstrrst-01.txt
13  * - http://www.ietf.org/internet-drafts/draft-ladha-sctp-nonce-02.txt
14  * -  http://www.ietf.org/internet-drafts/draft-tuexen-tsvwg-sctp-sack-immediately-00.txt
15  *
16  * Copyright 2000-2005 Michael Tuexen <tuexen [AT] fh-muenster.de>
17  * Still to do (so stay tuned)
18  * - error checking mode
19  *   * padding errors
20  *   * length errors
21  *   * bundling errors
22  *   * value errors
23  *
24  *
25  * Reassembly added 2006 by Robin Seggelmann
26  * TSN Tracking by Luis E. G. Ontanon (Feb 2007)
27  * Copyright 2009, Varun Notibala <nbvarun [AT] gmail.com>
28  *
29  * $Id$
30  *
31  * Wireshark - Network traffic analyzer
32  * By Gerald Combs <gerald@wireshark.org>
33  * Copyright 1998 Gerald Combs
34  *
35  * This program is free software; you can redistribute it and/or
36  * modify it under the terms of the GNU General Public License
37  * as published by the Free Software Foundation; either version 2
38  * of the License, or (at your option) any later version.
39  *
40  * This program is distributed in the hope that it will be useful,
41  * but WITHOUT ANY WARRANTY; without even the implied warranty of
42  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
43  * GNU General Public License for more details.
44  *
45  * You should have received a copy of the GNU General Public License
46  * along with this program; if not, write to the Free Software
47  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
48  */
49
50 #ifdef HAVE_CONFIG_H
51 # include "config.h"
52 #endif
53
54 #include <string.h>
55 #include <epan/prefs.h>
56 #include <epan/packet.h>
57 #include <epan/tap.h>
58 #include <epan/ipproto.h>
59 #include <epan/addr_resolv.h>
60 #include "packet-sctp.h"
61 #include <epan/sctpppids.h>
62 #include <epan/emem.h>
63 #include <epan/expert.h>
64 #include <packet-frame.h>
65 #include <epan/crc32.h>
66
67 #define LT(x, y) ((gint32)((x) - (y)) < 0)
68
69 #define NETWORK_BYTE_ORDER     FALSE
70 #define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
71 #define UDP_TUNNELING_PORT 9899
72
73 /* Initialize the protocol and registered fields */
74 static int proto_sctp = -1;
75 static int hf_port = -1;
76 static int hf_source_port      = -1;
77 static int hf_destination_port = -1;
78 static int hf_verification_tag = -1;
79 static int hf_checksum         = -1;
80 static int hf_checksum_bad     = -1;
81
82 static int hf_chunk_type       = -1;
83 static int hf_chunk_flags      = -1;
84 static int hf_chunk_bit_1      = -1;
85 static int hf_chunk_bit_2      = -1;
86 static int hf_chunk_length     = -1;
87 static int hf_chunk_padding    = -1;
88 static int hf_chunk_value    = -1;
89
90 static int hf_initiate_tag   = -1;
91 static int hf_init_chunk_initiate_tag   = -1;
92 static int hf_init_chunk_adv_rec_window_credit = -1;
93 static int hf_init_chunk_number_of_outbound_streams = -1;
94 static int hf_init_chunk_number_of_inbound_streams  = -1;
95 static int hf_init_chunk_initial_tsn    = -1;
96
97 static int hf_initack_chunk_initiate_tag   = -1;
98 static int hf_initack_chunk_adv_rec_window_credit = -1;
99 static int hf_initack_chunk_number_of_outbound_streams = -1;
100 static int hf_initack_chunk_number_of_inbound_streams  = -1;
101 static int hf_initack_chunk_initial_tsn    = -1;
102
103 static int hf_cumulative_tsn_ack = -1;
104
105 static int hf_data_chunk_tsn = -1;
106 static int hf_data_chunk_stream_id = -1;
107 static int hf_data_chunk_stream_seq_number = -1;
108 static int hf_data_chunk_payload_proto_id = -1;
109
110 static int hf_data_chunk_e_bit = -1;
111 static int hf_data_chunk_b_bit = -1;
112 static int hf_data_chunk_u_bit = -1;
113 static int hf_data_chunk_i_bit = -1;
114
115 static int hf_sack_chunk_ns = -1;
116 static int hf_sack_chunk_cumulative_tsn_ack = -1;
117 static int hf_sack_chunk_adv_rec_window_credit = -1;
118 static int hf_sack_chunk_number_of_gap_blocks = -1;
119 static int hf_sack_chunk_number_of_dup_tsns = -1;
120 static int hf_sack_chunk_gap_block_start = -1;
121 static int hf_sack_chunk_gap_block_end = -1;
122 static int hf_sack_chunk_gap_block_start_tsn = -1;
123 static int hf_sack_chunk_gap_block_end_tsn = -1;
124 static int hf_sack_chunk_number_tsns_gap_acked = -1;
125 static int hf_sack_chunk_duplicate_tsn = -1;
126
127 static int hf_nr_sack_chunk_ns = -1;
128 static int hf_nr_sack_chunk_cumulative_tsn_ack = -1;
129 static int hf_nr_sack_chunk_adv_rec_window_credit = -1;
130 static int hf_nr_sack_chunk_number_of_gap_blocks = -1;
131 static int hf_nr_sack_chunk_number_of_nr_gap_blocks = -1;
132 static int hf_nr_sack_chunk_number_of_dup_tsns = -1;
133 static int hf_nr_sack_chunk_reserved = -1;
134 static int hf_nr_sack_chunk_gap_block_start = -1;
135 static int hf_nr_sack_chunk_gap_block_end = -1;
136 static int hf_nr_sack_chunk_gap_block_start_tsn = -1;
137 static int hf_nr_sack_chunk_gap_block_end_tsn = -1;
138 static int hf_nr_sack_chunk_number_tsns_gap_acked = -1;
139 static int hf_nr_sack_chunk_nr_gap_block_start = -1;
140 static int hf_nr_sack_chunk_nr_gap_block_end = -1;
141 static int hf_nr_sack_chunk_nr_gap_block_start_tsn = -1;
142 static int hf_nr_sack_chunk_nr_gap_block_end_tsn = -1;
143 static int hf_nr_sack_chunk_number_tsns_nr_gap_acked = -1;
144 static int hf_nr_sack_chunk_duplicate_tsn = -1;
145
146 static int hf_shutdown_chunk_cumulative_tsn_ack = -1;
147 static int hf_cookie = -1;
148 static int hf_cwr_chunk_lowest_tsn = -1;
149
150 static int hf_ecne_chunk_lowest_tsn = -1;
151 static int hf_abort_chunk_t_bit = -1;
152 static int hf_shutdown_complete_chunk_t_bit = -1;
153
154 static int hf_parameter_type = -1;
155 static int hf_parameter_length = -1;
156 static int hf_parameter_value = -1;
157 static int hf_parameter_padding = -1;
158 static int hf_parameter_bit_1      = -1;
159 static int hf_parameter_bit_2      = -1;
160 static int hf_ipv4_address = -1;
161 static int hf_ipv6_address = -1;
162 static int hf_heartbeat_info = -1;
163 static int hf_state_cookie = -1;
164 static int hf_cookie_preservative_increment = -1;
165 static int hf_hostname = -1;
166 static int hf_supported_address_type = -1;
167 static int hf_stream_reset_req_seq_nr = -1;
168 static int hf_stream_reset_rsp_seq_nr = -1;
169 static int hf_senders_last_assigned_tsn = -1;
170 static int hf_senders_next_tsn = -1;
171 static int hf_receivers_next_tsn = -1;
172 static int hf_stream_reset_rsp_result = -1;
173 static int hf_stream_reset_sid = -1;
174 static int hf_random_number = -1;
175 static int hf_chunks_to_auth = -1;
176 static int hf_hmac_id = -1;
177 static int hf_hmac = -1;
178 static int hf_shared_key_id = -1;
179 static int hf_supported_chunk_type = -1;
180
181 static int hf_cause_code = -1;
182 static int hf_cause_length = -1;
183 static int hf_cause_padding = -1;
184 static int hf_cause_info = -1;
185
186 static int hf_cause_stream_identifier = -1;
187 static int hf_cause_reserved = -1;
188
189 static int hf_cause_number_of_missing_parameters = -1;
190 static int hf_cause_missing_parameter_type = -1;
191
192 static int hf_cause_measure_of_staleness = -1;
193
194 static int hf_cause_tsn = -1;
195
196 static int hf_forward_tsn_chunk_tsn = -1;
197 static int hf_forward_tsn_chunk_sid = -1;
198 static int hf_forward_tsn_chunk_ssn = -1;
199
200 static int hf_asconf_ack_serial = -1;
201 static int hf_asconf_serial = -1;
202 static int hf_correlation_id = -1;
203
204 static int hf_adap_indication = -1;
205
206 static int hf_pktdrop_chunk_m_bit = -1;
207 static int hf_pktdrop_chunk_b_bit = -1;
208 static int hf_pktdrop_chunk_t_bit = -1;
209 static int hf_pktdrop_chunk_bandwidth = -1;
210 static int hf_pktdrop_chunk_queuesize = -1;
211 static int hf_pktdrop_chunk_truncated_length = -1;
212 static int hf_pktdrop_chunk_reserved = -1;
213 static int hf_pktdrop_chunk_data_field = -1;
214
215 static int hf_sctp_reassembled_in = -1;
216 static int hf_sctp_duplicate = -1;
217 static int hf_sctp_fragments = -1;
218 static int hf_sctp_fragment = -1;
219
220 static int hf_sctp_retransmission = -1;
221 static int hf_sctp_retransmitted = -1;
222 static int hf_sctp_retransmitted_count = -1;
223 static int hf_sctp_rtt = -1;
224 static int hf_sctp_rto = -1;
225 static int hf_sctp_ack_tsn = -1;
226 static int hf_sctp_ack_frame = -1;
227 static int hf_sctp_acked = -1;
228 static int hf_sctp_retransmitted_after_ack = -1;
229
230 static dissector_table_t sctp_port_dissector_table;
231 static dissector_table_t sctp_ppi_dissector_table;
232 static heur_dissector_list_t sctp_heur_subdissector_list;
233 static int sctp_tap = -1;
234 static module_t *sctp_module;
235
236 /* Initialize the subtree pointers */
237 static gint ett_sctp = -1;
238 static gint ett_sctp_chunk = -1;
239 static gint ett_sctp_chunk_parameter = -1;
240 static gint ett_sctp_chunk_cause = -1;
241 static gint ett_sctp_chunk_type = -1;
242 static gint ett_sctp_data_chunk_flags = -1;
243 static gint ett_sctp_sack_chunk_flags = -1;
244 static gint ett_sctp_nr_sack_chunk_flags = -1;
245 static gint ett_sctp_abort_chunk_flags = -1;
246 static gint ett_sctp_shutdown_complete_chunk_flags = -1;
247 static gint ett_sctp_pktdrop_chunk_flags = -1;
248 static gint ett_sctp_parameter_type= -1;
249 static gint ett_sctp_sack_chunk_gap_block = -1;
250 static gint ett_sctp_sack_chunk_gap_block_start = -1;
251 static gint ett_sctp_sack_chunk_gap_block_end = -1;
252 static gint ett_sctp_nr_sack_chunk_gap_block = -1;
253 static gint ett_sctp_nr_sack_chunk_gap_block_start = -1;
254 static gint ett_sctp_nr_sack_chunk_gap_block_end = -1;
255 static gint ett_sctp_nr_sack_chunk_nr_gap_block = -1;
256 static gint ett_sctp_nr_sack_chunk_nr_gap_block_start = -1;
257 static gint ett_sctp_nr_sack_chunk_nr_gap_block_end = -1;
258 static gint ett_sctp_unrecognized_parameter_parameter = -1;
259
260 static gint ett_sctp_fragments = -1;
261 static gint ett_sctp_fragment  = -1;
262
263 static gint ett_sctp_tsn = -1;
264 static gint ett_sctp_ack = -1;
265 static gint ett_sctp_acked = -1;
266 static gint ett_sctp_tsn_retransmission = -1;
267 static gint ett_sctp_tsn_retransmitted_count = -1;
268 static gint ett_sctp_tsn_retransmitted = -1;
269 static dissector_handle_t data_handle;
270
271 static gboolean enable_tsn_analysis = FALSE;
272 static gboolean enable_ulp_dissection = TRUE;
273
274 #define SCTP_DATA_CHUNK_ID               0
275 #define SCTP_INIT_CHUNK_ID               1
276 #define SCTP_INIT_ACK_CHUNK_ID           2
277 #define SCTP_SACK_CHUNK_ID               3
278 #define SCTP_HEARTBEAT_CHUNK_ID          4
279 #define SCTP_HEARTBEAT_ACK_CHUNK_ID      5
280 #define SCTP_ABORT_CHUNK_ID              6
281 #define SCTP_SHUTDOWN_CHUNK_ID           7
282 #define SCTP_SHUTDOWN_ACK_CHUNK_ID       8
283 #define SCTP_ERROR_CHUNK_ID              9
284 #define SCTP_COOKIE_ECHO_CHUNK_ID       10
285 #define SCTP_COOKIE_ACK_CHUNK_ID        11
286 #define SCTP_ECNE_CHUNK_ID              12
287 #define SCTP_CWR_CHUNK_ID               13
288 #define SCTP_SHUTDOWN_COMPLETE_CHUNK_ID 14
289 #define SCTP_AUTH_CHUNK_ID              15
290 #define SCTP_NR_SACK_CHUNK_ID           16
291 #define SCTP_ASCONF_ACK_CHUNK_ID      0x80
292 #define SCTP_PKTDROP_CHUNK_ID         0x81
293 #define SCTP_STREAM_RESET_CHUNK_ID    0x82
294 #define SCTP_FORWARD_TSN_CHUNK_ID     0xC0
295 #define SCTP_ASCONF_CHUNK_ID          0xC1
296 #define SCTP_IETF_EXT                 0xFF
297
298 static const value_string chunk_type_values[] = {
299   { SCTP_DATA_CHUNK_ID,              "DATA" },
300   { SCTP_INIT_CHUNK_ID,              "INIT" },
301   { SCTP_INIT_ACK_CHUNK_ID,          "INIT_ACK" },
302   { SCTP_SACK_CHUNK_ID,              "SACK" },
303   { SCTP_HEARTBEAT_CHUNK_ID,         "HEARTBEAT" },
304   { SCTP_HEARTBEAT_ACK_CHUNK_ID,     "HEARTBEAT_ACK" },
305   { SCTP_ABORT_CHUNK_ID,             "ABORT" },
306   { SCTP_SHUTDOWN_CHUNK_ID,          "SHUTDOWN" },
307   { SCTP_SHUTDOWN_ACK_CHUNK_ID,      "SHUTDOWN_ACK" },
308   { SCTP_ERROR_CHUNK_ID,             "ERROR" },
309   { SCTP_COOKIE_ECHO_CHUNK_ID,       "COOKIE_ECHO" },
310   { SCTP_COOKIE_ACK_CHUNK_ID,        "COOKIE_ACK" },
311   { SCTP_ECNE_CHUNK_ID,              "ECNE" },
312   { SCTP_CWR_CHUNK_ID,               "CWR" },
313   { SCTP_SHUTDOWN_COMPLETE_CHUNK_ID, "SHUTDOWN_COMPLETE" },
314   { SCTP_STREAM_RESET_CHUNK_ID,      "STREAM_RESET" },
315   { SCTP_AUTH_CHUNK_ID,              "AUTH" },
316   { SCTP_NR_SACK_CHUNK_ID,           "NR-SACK" },
317   { SCTP_FORWARD_TSN_CHUNK_ID,       "FORWARD_TSN" },
318   { SCTP_ASCONF_ACK_CHUNK_ID,        "ASCONF_ACK" },
319   { SCTP_PKTDROP_CHUNK_ID,           "PKTDROP" },
320   { SCTP_ASCONF_CHUNK_ID,            "ASCONF" },
321   { SCTP_IETF_EXT,                   "IETF_EXTENSION" },
322   { 0,                               NULL } };
323
324 static const value_string sctp_payload_proto_id_values[] = {
325   { NOT_SPECIFIED_PROTOCOL_ID,           "not specified" },
326   { IUA_PAYLOAD_PROTOCOL_ID,             "IUA" },
327   { M2UA_PAYLOAD_PROTOCOL_ID,            "M2UA" },
328   { M3UA_PAYLOAD_PROTOCOL_ID,            "M3UA" },
329   { SUA_PAYLOAD_PROTOCOL_ID,             "SUA" },
330   { M2PA_PAYLOAD_PROTOCOL_ID,            "M2PA" },
331   { V5UA_PAYLOAD_PROTOCOL_ID,            "V5UA" },
332   { H248_PAYLOAD_PROTOCOL_ID,            "H.248/MEGACO" },
333   { BICC_PAYLOAD_PROTOCOL_ID,            "BICC/Q.2150.3" },
334   { TALI_PAYLOAD_PROTOCOL_ID,            "TALI" },
335   { DUA_PAYLOAD_PROTOCOL_ID,             "DUA" },
336   { ASAP_PAYLOAD_PROTOCOL_ID,            "ASAP" },
337   { ENRP_PAYLOAD_PROTOCOL_ID,            "ENRP" },
338   { H323_PAYLOAD_PROTOCOL_ID,            "H.323" },
339   { QIPC_PAYLOAD_PROTOCOL_ID,            "Q.IPC/Q.2150.3" },
340   { SIMCO_PAYLOAD_PROTOCOL_ID,           "SIMCO" },
341   { DDP_SEG_CHUNK_PROTOCOL_ID,                   "DDP Segment Chunk" }, /*  [RFC-ietf-rddp-sctp-07.txt] */
342   { DDP_STREAM_SES_CTRL_PROTOCOL_ID,     "DDP Stream Session Control" }, /* [RFC-ietf-rddp-sctp-07.txt] */
343   { S1AP_PAYLOAD_PROTOCOL_ID,                    "S1 Application Protocol (S1AP)" }, /* [TS 23.401][TS 36.413][Koodli] */
344   { 0,                                   NULL } };
345
346
347 #define CHUNK_TYPE_LENGTH             1
348 #define CHUNK_FLAGS_LENGTH            1
349 #define CHUNK_LENGTH_LENGTH           2
350 #define CHUNK_HEADER_LENGTH           (CHUNK_TYPE_LENGTH + \
351                                        CHUNK_FLAGS_LENGTH + \
352                                        CHUNK_LENGTH_LENGTH)
353 #define CHUNK_HEADER_OFFSET           0
354 #define CHUNK_TYPE_OFFSET             CHUNK_HEADER_OFFSET
355 #define CHUNK_FLAGS_OFFSET            (CHUNK_TYPE_OFFSET + CHUNK_TYPE_LENGTH)
356 #define CHUNK_LENGTH_OFFSET           (CHUNK_FLAGS_OFFSET + CHUNK_FLAGS_LENGTH)
357 #define CHUNK_VALUE_OFFSET            (CHUNK_LENGTH_OFFSET + CHUNK_LENGTH_LENGTH)
358
359 #define PARAMETER_TYPE_LENGTH            2
360 #define PARAMETER_LENGTH_LENGTH          2
361 #define PARAMETER_HEADER_LENGTH          (PARAMETER_TYPE_LENGTH + PARAMETER_LENGTH_LENGTH)
362
363 #define PARAMETER_HEADER_OFFSET          0
364 #define PARAMETER_TYPE_OFFSET            PARAMETER_HEADER_OFFSET
365 #define PARAMETER_LENGTH_OFFSET          (PARAMETER_TYPE_OFFSET + PARAMETER_TYPE_LENGTH)
366 #define PARAMETER_VALUE_OFFSET           (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
367
368 #define SOURCE_PORT_LENGTH      2
369 #define DESTINATION_PORT_LENGTH 2
370 #define VERIFICATION_TAG_LENGTH 4
371 #define CHECKSUM_LENGTH         4
372 #define COMMON_HEADER_LENGTH    (SOURCE_PORT_LENGTH + \
373                                  DESTINATION_PORT_LENGTH + \
374                                  VERIFICATION_TAG_LENGTH + \
375                                  CHECKSUM_LENGTH)
376 #define SOURCE_PORT_OFFSET      0
377 #define DESTINATION_PORT_OFFSET (SOURCE_PORT_OFFSET + SOURCE_PORT_LENGTH)
378 #define VERIFICATION_TAG_OFFSET (DESTINATION_PORT_OFFSET + DESTINATION_PORT_LENGTH)
379 #define CHECKSUM_OFFSET         (VERIFICATION_TAG_OFFSET + VERIFICATION_TAG_LENGTH)
380
381 #define SCTP_CHECKSUM_NONE      0
382 #define SCTP_CHECKSUM_ADLER32   1
383 #define SCTP_CHECKSUM_CRC32C    2
384 #define SCTP_CHECKSUM_AUTOMATIC 3
385
386 /* default values for preferences */
387 static gboolean show_port_numbers          = TRUE;
388 /* FIXME
389 static gboolean show_chunk_types           = TRUE;
390 */
391 static gboolean show_always_control_chunks = TRUE;
392 static gint sctp_checksum                  = SCTP_CHECKSUM_NONE;
393
394 static gboolean use_reassembly             = FALSE;
395
396 static struct _sctp_info sctp_info;
397
398 /* adler32.c -- compute the Adler-32 checksum of a data stream
399  * Copyright (C) 1995-1996 Mark Adler
400  * For conditions of distribution and use, see copyright notice in zlib.h
401  * available, e.g. from  http://www.cdrom.com/pub/infozip/zlib/
402  *
403  * It was modified for the use in this dissector.
404  */
405
406 #define BASE 65521L /* largest prime smaller than 65536      */
407 #define NMAX 5540   /* NMAX is the largest n - 12 such that  */
408         /* 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
409
410 #define DO1(buf,i)  {s1 += buf[i]; s2 += s1;}
411 #define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
412 #define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
413 #define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
414 #define DO16(buf)   DO8(buf,0); DO8(buf,8);
415
416 static unsigned int
417 sctp_adler32(const unsigned char* buf, unsigned int len)
418 {
419     unsigned int s1 = 1L;
420     unsigned int s2 = 0L;
421     int k;
422
423     /* handle the first 8 bytes of the datagram */
424     DO8(buf,0);
425     buf += SOURCE_PORT_LENGTH +
426            DESTINATION_PORT_LENGTH +
427            VERIFICATION_TAG_LENGTH;
428
429     /* handle four 0 bytes as checksum */
430     s2  += CHECKSUM_LENGTH * s1;
431     buf += CHECKSUM_LENGTH;
432
433     /* now we have 12 bytes handled */
434     len -= COMMON_HEADER_LENGTH;
435
436     /* handle the rest of the datagram */
437     while (len > 0) {
438         k = len < NMAX ? len : NMAX;
439         len -= k;
440         while (k >= 16) {
441             DO16(buf);
442             buf += 16;
443             k -= 16;
444         }
445         if (k != 0) do {
446             s1 += *buf++;
447             s2 += s1;
448         } while (--k);
449         s1 %= BASE;
450         s2 %= BASE;
451     }
452     return (s2 << 16) | s1;
453 }
454
455
456 static guint32
457 sctp_crc32c(const unsigned char* buf, unsigned int len)
458 {
459   unsigned int i;
460   guint32 crc32 = CRC32C_PRELOAD;
461   guint32 result;
462   unsigned char byte0,byte1,byte2,byte3;
463
464   for (i = 0; i < SOURCE_PORT_LENGTH + DESTINATION_PORT_LENGTH + VERIFICATION_TAG_LENGTH; i++)
465   {
466     CRC32C(crc32, buf[i]);
467   }
468   CRC32C(crc32, 0);
469   CRC32C(crc32, 0);
470   CRC32C(crc32, 0);
471   CRC32C(crc32, 0);
472   for (i = COMMON_HEADER_LENGTH; i < len; i++)
473   {
474     CRC32C(crc32, buf[i]);
475   }
476   result = ~crc32;
477
478   byte0 = result & 0xff;
479   byte1 = (result>>8) & 0xff;
480   byte2 = (result>>16) & 0xff;
481   byte3 = (result>>24) & 0xff;
482   crc32 = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
483   return ( crc32 );
484 }
485
486 /*
487  * Routines for dissecting parameters
488  */
489
490 typedef struct _sctp_half_assoc_t sctp_half_assoc_t;
491
492 static void dissect_parameter(tvbuff_t *, packet_info *, proto_tree *, proto_item *, gboolean);
493
494 static void dissect_parameters(tvbuff_t *, packet_info *, proto_tree *, proto_item *, gboolean);
495
496 static void dissect_error_cause(tvbuff_t *, packet_info *, proto_tree *);
497
498 static void dissect_error_causes(tvbuff_t *, packet_info *, proto_tree *);
499
500 static gboolean dissect_data_chunk(tvbuff_t*, guint16, packet_info*, proto_tree*, proto_tree*, proto_item*, proto_item*, sctp_half_assoc_t*);
501
502 static void dissect_sctp_packet(tvbuff_t *, packet_info *, proto_tree *, gboolean);
503
504
505 /* TSN ANALYSIS CODE */
506
507 struct _sctp_half_assoc_t {
508         guint32 spt;
509         guint32 dpt;
510         guint32 vtag;
511
512         gboolean started;
513
514         guint32 first_tsn; /* start */
515         guint32 cumm_ack; /* rel */
516         emem_tree_t *tsns; /* sctp_tsn_t* by rel_tsn */
517         emem_tree_t *tsn_acks; /* sctp_tsn_t* by ctsn_frame */
518
519         struct _sctp_half_assoc_t *peer;
520 };
521
522
523
524 typedef struct _sctp_tsn_t {
525         guint32 tsn;
526         struct {
527                 guint32 framenum;
528                 nstime_t ts;
529         } first_transmit;
530         struct {
531                 guint32 framenum;
532                 nstime_t ts;
533         } ack;
534         struct _retransmit_t {
535                 guint32 framenum;
536                 nstime_t ts;
537                 struct _retransmit_t *next;
538         } *retransmit;
539         guint32 retransmit_count;
540         struct _sctp_tsn_t *next;
541 } sctp_tsn_t;
542
543
544 static emem_tree_key_t*
545 make_address_key(guint32 spt, guint32 dpt, address *addr)
546 {
547         emem_tree_key_t *k = ep_alloc(sizeof(emem_tree_key_t)*6);
548
549         k[0].length = 1;    k[0].key = ep_memdup(&spt,sizeof(spt));
550         k[1].length = 1;    k[1].key = ep_memdup(&dpt,sizeof(dpt));
551         k[2].length = 1;    k[2].key = (guint32*)(void *)&(addr->type);
552         k[3].length = 1;    k[3].key = (guint32*)(void *)&(addr->len);
553
554         k[4].length = ((addr->len/4)+1);
555         k[4].key = ep_alloc0(((addr->len/4)+1)*4);
556         if (addr->len) memcpy(k[4].key, addr->data, addr->len);
557
558         k[5].length = 0;    k[5].key = NULL;
559
560         return k;
561 }
562
563 static emem_tree_key_t *
564 make_dir_key(guint32 spt, guint32 dpt, guint32 vtag)
565 {
566         emem_tree_key_t *k =  ep_alloc(sizeof(emem_tree_key_t)*4);
567
568         k[0].length = 1;    k[0].key = ep_memdup(&spt,sizeof(spt));
569         k[1].length = 1;    k[1].key = ep_memdup(&dpt,sizeof(dpt));
570         k[2].length = 1;    k[2].key = ep_memdup(&vtag,sizeof(vtag));
571         k[3].length = 0;    k[3].key = NULL;
572
573         return k;
574 }
575
576
577
578 static emem_tree_t *dirs_by_ptvtag; /* sctp_half_assoc_t*  */
579 static emem_tree_t *dirs_by_ptaddr; /* sctp_half_assoc_t**, it may contain a null pointer */
580
581 static sctp_half_assoc_t *
582 get_half_assoc(packet_info *pinfo, guint32 spt, guint32 dpt, guint32 vtag)
583 {
584         sctp_half_assoc_t *ha;
585         sctp_half_assoc_t **hb;
586         emem_tree_key_t *k;
587
588         if (!enable_tsn_analysis || !vtag) return NULL;
589
590         /* look for the current half_assoc by spt, dpt and vtag */
591
592         k = make_dir_key(spt, dpt, vtag);
593         if (( ha = emem_tree_lookup32_array(dirs_by_ptvtag, k)  )) {
594                 /* found, if it has been already matched we're done */
595                 if (ha->peer) return ha;
596         } else {
597                 /* not found, make a new one and add it to the table */
598                 ha = se_alloc0(sizeof(sctp_half_assoc_t));
599                 ha->spt = spt;
600                 ha->dpt = dpt;
601                 ha->vtag = vtag;
602                 ha->tsns = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK,"");
603                 ha->tsn_acks = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK,"");
604                 ha->started = FALSE;
605                 ha->first_tsn= 0;
606                 ha->cumm_ack= 0;
607
608                 /* add this half to the table indexed by ports and vtag */
609                 emem_tree_insert32_array(dirs_by_ptvtag, k, ha);
610         }
611
612         /* at this point we have an unmatched half, look for its other half using the ports and IP address */
613         k = make_address_key(dpt, spt, &(pinfo->dst));
614
615         if (( hb = emem_tree_lookup32_array(dirs_by_ptaddr, k) )) {
616                 /*the table contains a pointer to a pointer to a half */
617                 if (! *hb) {
618                         /* if there is no half pointed by this, add the current half to the table */
619                         *hb = ha;
620                 } else {
621                         /* there's a half pointed by this, assume it's our peer and clear the table's pointer */
622                         ha->peer = *hb;
623                         (*hb)->peer = ha;
624                         *hb = NULL;
625                 }
626         } else {
627                 /* we found no entry in the table: add one (using reversed ports and src addresss) so that it can be matched later */
628                 *(hb = se_alloc(sizeof(void*))) = ha;
629                 k = make_address_key(spt, dpt, &(pinfo->src));
630                 emem_tree_insert32_array(dirs_by_ptaddr, k, hb);
631         }
632
633         return ha;
634 }
635
636 /*  Limit the number of retransmissions we track (to limit memory usage--and
637  *  tree size--in pathological cases, for example zero window probing forever).
638  */
639 #define MAX_RETRANS_TRACKED_PER_TSN 100
640
641 static void
642 tsn_tree(sctp_tsn_t *t, proto_item *tsn_item, packet_info *pinfo,
643          tvbuff_t *tvb, guint32 framenum)
644 {
645         proto_item *pi;
646         proto_tree *pt;
647         proto_tree *tsn_tree_pt = proto_item_add_subtree(tsn_item, ett_sctp_tsn);
648
649         if (t->first_transmit.framenum != framenum) {
650                 nstime_t rto;
651
652                 pi = proto_tree_add_uint(tsn_tree_pt, hf_sctp_retransmission, tvb, 0, 0, t->first_transmit.framenum);
653                 pt = proto_item_add_subtree(pi, ett_sctp_tsn_retransmission);
654                 PROTO_ITEM_SET_GENERATED(pi);
655                 expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_NOTE, "Retransmitted TSN");
656
657                 nstime_delta( &rto, &pinfo->fd->abs_ts, &(t->first_transmit.ts) );
658                 pi = proto_tree_add_time(pt, hf_sctp_rto, tvb, 0, 0, &rto);
659                 PROTO_ITEM_SET_GENERATED(pi);
660
661                 /* Detect reneged acks */
662                 /* XXX what if the frames aren't sorted by time? */
663                 if (t->ack.framenum && t->ack.framenum < framenum)
664                 {
665                         pi = proto_tree_add_uint_format(pt, hf_sctp_retransmitted_after_ack, tvb, 0, 0, t->ack.framenum,
666                                                            "This TSN was acked (in frame %u) prior to this retransmission (reneged ack?)",
667                                                            t->ack.framenum);
668                         PROTO_ITEM_SET_GENERATED(pi);
669                         expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_WARN,
670                                                "This TSN was acked prior to this retransmission (reneged ack?)");
671                 }
672         } else if (t->retransmit) {
673                 struct _retransmit_t **r;
674                 nstime_t rto;
675                 char ds[64];
676
677                 if (t->retransmit_count > MAX_RETRANS_TRACKED_PER_TSN)
678                         g_snprintf(ds, sizeof(ds), " (only %d displayed)", MAX_RETRANS_TRACKED_PER_TSN);
679                 else
680                         ds[0] = 0;
681
682                 pi = proto_tree_add_uint_format(tsn_tree_pt,
683                                                 hf_sctp_retransmitted_count,
684                                                 tvb, 0, 0, t->retransmit_count,
685                                                 "This TSN was retransmitted %u time%s%s",
686                                                 t->retransmit_count,
687                                                 plurality(t->retransmit_count, "", "s"),
688                                                 ds);
689                 PROTO_ITEM_SET_GENERATED(pi);
690
691                 if (t->retransmit_count > 2)
692                         expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_WARN,
693                                                "This TSN was retransmitted more than 2 times");
694
695                 pt = proto_item_add_subtree(pi, ett_sctp_tsn_retransmitted_count);
696
697                 r = &t->retransmit;
698                 while (*r) {
699                         nstime_delta(&rto, &((*r)->ts), &pinfo->fd->abs_ts);
700                         pi = proto_tree_add_uint_format(pt,
701                                                         hf_sctp_retransmitted,
702                                                         tvb, 0, 0,
703                                                         (*r)->framenum,
704                                                         "This TSN was retransmitted in frame %u (%s seconds after this frame)",
705                                                         (*r)->framenum,
706                                                         rel_time_to_secs_str(&rto));
707                         PROTO_ITEM_SET_GENERATED(pi);
708                         r = &(*r)->next;
709                 }
710         }
711
712         if (t->ack.framenum) {
713                 nstime_t rtt;
714
715                 pi = proto_tree_add_uint(tsn_tree_pt, hf_sctp_acked, tvb, 0 , 0, t->ack.framenum);
716                 PROTO_ITEM_SET_GENERATED(pi);
717                 pt = proto_item_add_subtree(pi, ett_sctp_ack);
718
719                 nstime_delta( &rtt, &(t->ack.ts), &(t->first_transmit.ts) );
720                 pi = proto_tree_add_time(pt, hf_sctp_rtt, tvb, 0, 0, &rtt);
721                 PROTO_ITEM_SET_GENERATED(pi);
722         }
723 }
724
725 #define RELTSN(tsn) (((tsn) < h->first_tsn) ? (tsn + (0xffffffff - (h->first_tsn)) + 1) : (tsn - h->first_tsn))
726
727 static void
728 sctp_tsn(packet_info *pinfo,  tvbuff_t *tvb, proto_item *tsn_item,
729          sctp_half_assoc_t *h, guint32 tsn)
730 {
731         sctp_tsn_t *t;
732         guint32 framenum;
733         guint32 reltsn;
734
735         /* no half assoc? nothing to do!*/
736         if (!h)
737                 return;
738
739
740         framenum = pinfo->fd->num;
741
742         /*  If we're dissecting for a read filter in the GUI [tshark assigns
743          *  frame numbers before running the read filter], don't do the TSN
744          *  analysis.  (We can't anyway because we don't have a valid frame
745          *  number...)
746          *
747          *  Without this check if you load a capture file in the
748          *  GUI while using a read filter, every SCTP TSN is marked as a
749          *  retransmission of that in frame 0.
750          */
751         if (framenum == 0)
752                 return;
753
754         /* we have not seen any tsn yet in this half assoc set the ground */
755         if (! h->started) {
756                 h->first_tsn = tsn;
757                 h->started = TRUE;
758         }
759
760
761         reltsn = RELTSN(tsn);
762
763         /* printf("%.3d REL TSN: %p->%p [%u] %u \n",framenum,h,h->peer,tsn,reltsn); */
764
765         /* look for this tsn in this half's tsn table */
766         if (! (t = emem_tree_lookup32(h->tsns,reltsn) )) {
767                 /* no tsn found, create a new one */
768                 t = se_alloc0(sizeof(sctp_tsn_t));
769                 t->tsn = tsn;
770
771                 t->first_transmit.framenum = framenum;
772                 t->first_transmit.ts.secs = pinfo->fd->abs_ts.secs;
773                 t->first_transmit.ts.nsecs = pinfo->fd->abs_ts.nsecs;
774
775                 emem_tree_insert32(h->tsns,reltsn,t);
776         }
777
778         if ( (! pinfo->fd->flags.visited ) && t->first_transmit.framenum != framenum  ) {
779                 struct _retransmit_t **r;
780                 int i;
781
782                 t->retransmit_count++;
783                 r = &t->retransmit;
784                 i = 0;
785                 while (*r && i < MAX_RETRANS_TRACKED_PER_TSN) {
786                         r = &(*r)->next;
787                         i++;
788                 }
789
790                 if (i <= MAX_RETRANS_TRACKED_PER_TSN) {
791                         /*  TODO: we're allocating 16 bytes here.  The se_
792                          *  allocator adds 8 bytes of canary to that at each
793                          *  allocation.  Should these allocations be batched
794                          *  or does it not matter for the rare cases when there's
795                          *  more than 1 or 2 retransmissions of a TSN?
796                          *  For now, go with simplicity (of code here).
797                          */
798                         *r = se_alloc0(sizeof(struct _retransmit_t));
799                         (*r)->framenum = framenum;
800                         (*r)->ts.secs = pinfo->fd->abs_ts.secs;
801                         (*r)->ts.nsecs = pinfo->fd->abs_ts.nsecs;
802                 }
803         }
804
805         tsn_tree(t, tsn_item, pinfo, tvb, framenum);
806 }
807
808 static void
809 ack_tree(sctp_tsn_t *t, proto_tree *acks_tree,
810          tvbuff_t *tvb, packet_info *pinfo)
811 {
812         proto_item *pi;
813         proto_tree *pt;
814         nstime_t rtt;
815         guint framenum =  pinfo->fd->num;
816
817         if ( t->ack.framenum == framenum ) {
818                 nstime_delta( &rtt, &(t->ack.ts), &(t->first_transmit.ts) );
819
820                 pi = proto_tree_add_uint(acks_tree, hf_sctp_ack_tsn, tvb, 0 , 0, t->tsn);
821                 PROTO_ITEM_SET_GENERATED(pi);
822
823                 pt = proto_item_add_subtree(pi, ett_sctp_acked);
824
825                 pi = proto_tree_add_uint(pt, hf_sctp_ack_frame, tvb, 0 , 0, t->first_transmit.framenum);
826                 PROTO_ITEM_SET_GENERATED(pi);
827
828                 pi = proto_tree_add_time(pt, hf_sctp_rtt, tvb, 0, 0, &rtt);
829                 PROTO_ITEM_SET_GENERATED(pi);
830         }
831 }
832
833 static void
834 sctp_ack(packet_info *pinfo, tvbuff_t *tvb,  proto_tree *acks_tree,
835          sctp_half_assoc_t *h, guint32 reltsn)
836 {
837         sctp_tsn_t *t;
838         guint32 framenum;
839
840
841         if (!h || !h->peer)
842                 return;
843
844         framenum =  pinfo->fd->num;
845
846         /* printf("%.6d ACK: %p->%p [%u] \n",framenum,h,h->peer,reltsn); */
847
848         t = se_tree_lookup32(h->peer->tsns,reltsn);
849
850         if (t) {
851                 if (! t->ack.framenum) {
852                         sctp_tsn_t *t2;
853
854                         t->ack.framenum = framenum;
855                         t->ack.ts.secs = pinfo->fd->abs_ts.secs;
856                         t->ack.ts.nsecs = pinfo->fd->abs_ts.nsecs;
857
858                         if (( t2 = emem_tree_lookup32(h->peer->tsn_acks, framenum) )) {
859                                 for(;t2->next;t2 = t2->next)
860                                         ;
861
862                                 t2->next = t;
863                         } else {
864                                 emem_tree_insert32(h->peer->tsn_acks, framenum,t);
865                         }
866                 }
867
868                 if ( t->ack.framenum == framenum)
869                         ack_tree(t, acks_tree, tvb, pinfo);
870
871         } /* else {
872                 proto_tree_add_text(acks_tree, tvb, 0 , 0, "Assoc: %p vs %p ?? %ld",h,h->peer,tsn);
873         } */
874 }
875
876 #define RELTSNACK(tsn) (((tsn) < h->peer->first_tsn) ? ((tsn) + (0xffffffff - (h->peer->first_tsn)) + 1) : ((tsn) - h->peer->first_tsn))
877 static void
878 sctp_ack_block(packet_info *pinfo, sctp_half_assoc_t *h, tvbuff_t *tvb,
879                proto_item *acks_tree, const guint32 *tsn_start_ptr,
880                guint32 tsn_end)
881 {
882         sctp_tsn_t *t;
883         guint32 framenum;
884         guint32 rel_start;
885         guint32 rel_end;
886
887
888         if ( !h || !h->peer || ! h->peer->started )
889                 return;
890
891         framenum =  pinfo->fd->num;
892         rel_end = RELTSNACK(tsn_end);
893
894         if (tsn_start_ptr) {
895                 rel_start = RELTSNACK(*tsn_start_ptr);
896                 /* printf("%.3d BACK: %p->%p [%u-%u]\n",framenum,h,h->peer,rel_start,rel_end); */
897         }  else {
898                 rel_start = h->peer->cumm_ack;
899                 /* printf("%.3d CACK: %p->%p  [%u-%u]\n",framenum,h,h->peer,rel_start,rel_end); */
900         }
901
902
903         if ((t = emem_tree_lookup32(h->peer->tsn_acks, framenum))) {
904                 for(;t;t = t->next) {
905                         guint32 tsn = t->tsn;
906
907                         if ( tsn  < h->peer->first_tsn ) {
908                                 tsn += (0xffffffff - (h->peer->first_tsn)) + 1;
909                         } else {
910                                 tsn -= h->peer->first_tsn;
911                         }
912
913                         if (t->ack.framenum == framenum && ( (!tsn_start_ptr) || rel_start <= tsn) && tsn <= rel_end)
914                                 ack_tree(t, acks_tree, tvb, pinfo);
915                 }
916
917                 return;
918         }
919
920         if (pinfo->fd->flags.visited || rel_end < rel_start || rel_end - rel_start > 0xffff0000 ) return;
921
922         if (! tsn_start_ptr )
923                 h->peer->cumm_ack = rel_end + 1;
924
925         if (rel_start <= rel_end && rel_end - rel_start < 5000 ) {
926                 guint32 rel_tsn, i;
927                 for (i=0; i <= rel_end-rel_start; i++) {
928                         rel_tsn = (guint32) (i+rel_start);
929                         sctp_ack(pinfo, tvb,  acks_tree, h, rel_tsn);
930                 }
931         }
932 }
933
934 /* END TSN ANALYSIS CODE */
935
936
937
938
939 #define HEARTBEAT_INFO_PARAMETER_INFO_OFFSET PARAMETER_VALUE_OFFSET
940
941 static void
942 dissect_heartbeat_info_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
943 {
944   guint16 heartbeat_info_length;
945
946   heartbeat_info_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
947   if (heartbeat_info_length > 0)
948     proto_tree_add_item(parameter_tree, hf_heartbeat_info, parameter_tvb, HEARTBEAT_INFO_PARAMETER_INFO_OFFSET, heartbeat_info_length, NETWORK_BYTE_ORDER);
949   proto_item_append_text(parameter_item, " (Information: %u byte%s)", heartbeat_info_length, plurality(heartbeat_info_length, "", "s"));
950 }
951
952 #define IPV4_ADDRESS_LENGTH 4
953 #define IPV4_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
954
955 static void
956 dissect_ipv4_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item, proto_item *additional_item, gboolean dissecting_init_init_ack_chunk)
957 {
958   if (parameter_tree) {
959     proto_tree_add_item(parameter_tree, hf_ipv4_address, parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH, NETWORK_BYTE_ORDER);
960     proto_item_append_text(parameter_item, " (Address: %s)", ip_to_str((const guint8 *)tvb_get_ptr(parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH)));
961     if (additional_item)
962         proto_item_append_text(additional_item, "%s", ip_to_str((const guint8 *)tvb_get_ptr(parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH)));
963   }
964   if (dissecting_init_init_ack_chunk) {
965     if (sctp_info.number_of_tvbs < MAXIMUM_NUMBER_OF_TVBS)
966       sctp_info.tvb[sctp_info.number_of_tvbs++] = parameter_tvb;
967     else
968       sctp_info.incomplete = TRUE;
969   }
970 }
971
972 #define IPV6_ADDRESS_LENGTH 16
973 #define IPV6_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
974
975 static void
976 dissect_ipv6_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item, proto_item *additional_item, gboolean dissecting_init_init_ack_chunk)
977 {
978   if (parameter_tree) {
979     proto_tree_add_item(parameter_tree, hf_ipv6_address, parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH, NETWORK_BYTE_ORDER);
980     proto_item_append_text(parameter_item, " (Address: %s)", ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH)));
981     if (additional_item)
982       proto_item_append_text(additional_item, "%s", ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH)));
983   }
984   if (dissecting_init_init_ack_chunk) {
985     if (sctp_info.number_of_tvbs < MAXIMUM_NUMBER_OF_TVBS)
986       sctp_info.tvb[sctp_info.number_of_tvbs++] = parameter_tvb;
987     else
988       sctp_info.incomplete = TRUE;
989   }
990 }
991
992 #define STATE_COOKIE_PARAMETER_COOKIE_OFFSET   PARAMETER_VALUE_OFFSET
993
994 static void
995 dissect_state_cookie_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
996 {
997   guint16 state_cookie_length;
998
999   state_cookie_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1000   if (state_cookie_length > 0)
1001     proto_tree_add_item(parameter_tree, hf_state_cookie, parameter_tvb, STATE_COOKIE_PARAMETER_COOKIE_OFFSET, state_cookie_length, NETWORK_BYTE_ORDER);
1002   proto_item_append_text(parameter_item, " (Cookie length: %u byte%s)", state_cookie_length, plurality(state_cookie_length, "", "s"));
1003 }
1004
1005 static void
1006 dissect_unrecognized_parameters_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
1007 {
1008   /* FIXME: Does it contain one or more parameters? */
1009   dissect_parameter(tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, -1, -1), pinfo, parameter_tree, NULL, FALSE);
1010 }
1011
1012 #define COOKIE_PRESERVATIVE_PARAMETER_INCR_LENGTH 4
1013 #define COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET PARAMETER_VALUE_OFFSET
1014
1015 static void
1016 dissect_cookie_preservative_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1017 {
1018   proto_tree_add_item(parameter_tree, hf_cookie_preservative_increment, parameter_tvb, COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET, COOKIE_PRESERVATIVE_PARAMETER_INCR_LENGTH, NETWORK_BYTE_ORDER);
1019   proto_item_append_text(parameter_item, " (Increment :%u msec)", tvb_get_ntohl(parameter_tvb, COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET));
1020 }
1021
1022 #define HOSTNAME_OFFSET PARAMETER_VALUE_OFFSET
1023
1024 static void
1025 dissect_hostname_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1026 {
1027   guint16 hostname_length;
1028
1029   hostname_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1030   proto_tree_add_item(parameter_tree, hf_hostname, parameter_tvb, HOSTNAME_OFFSET, hostname_length, NETWORK_BYTE_ORDER);
1031   proto_item_append_text(parameter_item, " (Hostname: %.*s)", hostname_length, (const char *)tvb_get_ptr(parameter_tvb, HOSTNAME_OFFSET, hostname_length));
1032
1033 }
1034
1035 #define IPv4_ADDRESS_TYPE      5
1036 #define IPv6_ADDRESS_TYPE      6
1037 #define HOSTNAME_ADDRESS_TYPE 11
1038
1039 static const value_string address_types_values[] = {
1040   {  IPv4_ADDRESS_TYPE,    "IPv4 address"     },
1041   {  IPv6_ADDRESS_TYPE,    "IPv6 address"     },
1042   { HOSTNAME_ADDRESS_TYPE, "Hostname address" },
1043   {  0, NULL               }
1044 };
1045
1046 #define SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH 2
1047
1048 static void
1049 dissect_supported_address_types_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1050 {
1051   guint16 addr_type, number_of_addr_types, addr_type_number;
1052   guint offset;
1053
1054   number_of_addr_types = (tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH)
1055                             / SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH;
1056
1057   offset = PARAMETER_VALUE_OFFSET;
1058   proto_item_append_text(parameter_item, " (Supported types: ");
1059   for(addr_type_number = 1; addr_type_number <= number_of_addr_types; addr_type_number++) {
1060     proto_tree_add_item(parameter_tree, hf_supported_address_type, parameter_tvb, offset, SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH, NETWORK_BYTE_ORDER);
1061     addr_type = tvb_get_ntohs(parameter_tvb, offset);
1062     switch (addr_type) {
1063       case IPv4_ADDRESS_TYPE:
1064         proto_item_append_text(parameter_item, "IPv4");
1065         break;
1066       case IPv6_ADDRESS_TYPE:
1067         proto_item_append_text(parameter_item, "IPv6");
1068         break;
1069       case HOSTNAME_ADDRESS_TYPE:
1070         proto_item_append_text(parameter_item, "hostname");
1071         break;
1072       default:
1073         proto_item_append_text(parameter_item, "%u", addr_type);
1074     }
1075     if (addr_type_number < number_of_addr_types)
1076       proto_item_append_text(parameter_item, ", ");
1077     offset += SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH;
1078   }
1079   proto_item_append_text(parameter_item, ")");
1080 }
1081
1082 #define STREAM_RESET_SEQ_NR_LENGTH       4
1083 #define SENDERS_LAST_ASSIGNED_TSN_LENGTH 4
1084 #define SID_LENGTH                       2
1085
1086 #define STREAM_RESET_REQ_SEQ_NR_OFFSET     PARAMETER_VALUE_OFFSET
1087 #define STREAM_RESET_REQ_RSP_SEQ_NR_OFFSET (PARAMETER_VALUE_OFFSET + STREAM_RESET_SEQ_NR_LENGTH)
1088 #define SENDERS_LAST_ASSIGNED_TSN_OFFSET   (STREAM_RESET_REQ_RSP_SEQ_NR_OFFSET + STREAM_RESET_SEQ_NR_LENGTH)
1089
1090 static void
1091 dissect_outgoing_ssn_reset_request_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item _U_)
1092 {
1093   guint length, number_of_sids, sid_number, sid_offset;
1094
1095   proto_tree_add_item(parameter_tree, hf_stream_reset_req_seq_nr,   parameter_tvb, STREAM_RESET_REQ_SEQ_NR_OFFSET,     STREAM_RESET_SEQ_NR_LENGTH,       NETWORK_BYTE_ORDER);
1096   proto_tree_add_item(parameter_tree, hf_stream_reset_rsp_seq_nr,   parameter_tvb, STREAM_RESET_REQ_RSP_SEQ_NR_OFFSET, STREAM_RESET_SEQ_NR_LENGTH,       NETWORK_BYTE_ORDER);
1097   proto_tree_add_item(parameter_tree, hf_senders_last_assigned_tsn, parameter_tvb, SENDERS_LAST_ASSIGNED_TSN_OFFSET,   SENDERS_LAST_ASSIGNED_TSN_LENGTH, NETWORK_BYTE_ORDER);
1098
1099   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1100   sid_offset = SENDERS_LAST_ASSIGNED_TSN_OFFSET + SENDERS_LAST_ASSIGNED_TSN_LENGTH;
1101   if (length > PARAMETER_HEADER_LENGTH + STREAM_RESET_SEQ_NR_LENGTH + STREAM_RESET_SEQ_NR_LENGTH + SENDERS_LAST_ASSIGNED_TSN_LENGTH) {
1102     number_of_sids = (length - (PARAMETER_HEADER_LENGTH + STREAM_RESET_SEQ_NR_LENGTH + STREAM_RESET_SEQ_NR_LENGTH + SENDERS_LAST_ASSIGNED_TSN_LENGTH)) / SID_LENGTH;
1103     for(sid_number = 1; sid_number <= number_of_sids; sid_number++) {
1104       proto_tree_add_item(parameter_tree, hf_stream_reset_sid, parameter_tvb, sid_offset, SID_LENGTH, NETWORK_BYTE_ORDER);
1105       sid_offset += SID_LENGTH;
1106     }
1107   }
1108 }
1109
1110 static void
1111 dissect_incoming_ssn_reset_request_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item _U_)
1112 {
1113   guint length, number_of_sids, sid_number, sid_offset;
1114
1115   proto_tree_add_item(parameter_tree, hf_stream_reset_req_seq_nr, parameter_tvb, STREAM_RESET_REQ_SEQ_NR_OFFSET, STREAM_RESET_SEQ_NR_LENGTH, NETWORK_BYTE_ORDER);
1116
1117   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1118   sid_offset = STREAM_RESET_REQ_SEQ_NR_OFFSET + STREAM_RESET_SEQ_NR_LENGTH;
1119   if (length > PARAMETER_HEADER_LENGTH + STREAM_RESET_SEQ_NR_LENGTH) {
1120     number_of_sids = (length - (PARAMETER_HEADER_LENGTH + STREAM_RESET_SEQ_NR_LENGTH)) / SID_LENGTH;
1121     for(sid_number = 1; sid_number <= number_of_sids; sid_number++) {
1122       proto_tree_add_item(parameter_tree, hf_stream_reset_sid, parameter_tvb, sid_offset, SID_LENGTH, NETWORK_BYTE_ORDER);
1123       sid_offset += SID_LENGTH;
1124     }
1125   }
1126 }
1127
1128 #define STREAM_RESET_REQ_SEQ_NR_OFFSET PARAMETER_VALUE_OFFSET
1129
1130 static void
1131 dissect_ssn_tsn_reset_request_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item _U_)
1132 {
1133   proto_tree_add_item(parameter_tree, hf_stream_reset_req_seq_nr, parameter_tvb, STREAM_RESET_REQ_SEQ_NR_OFFSET, STREAM_RESET_SEQ_NR_LENGTH, NETWORK_BYTE_ORDER);
1134 }
1135
1136 #define STREAM_RESET_RSP_RESULT_LENGTH 4
1137 #define SENDERS_NEXT_TSN_LENGTH        4
1138 #define RECEIVERS_NEXT_TSN_LENGTH      4
1139
1140 #define STREAM_RESET_RSP_RSP_SEQ_NR_OFFSET PARAMETER_VALUE_OFFSET
1141 #define STREAM_RESET_RSP_RESULT_OFFSET     (STREAM_RESET_RSP_RSP_SEQ_NR_OFFSET + STREAM_RESET_SEQ_NR_LENGTH)
1142 #define SENDERS_NEXT_TSN_OFFSET            (STREAM_RESET_RSP_RESULT_OFFSET + STREAM_RESET_RSP_RESULT_LENGTH)
1143 #define RECEIVERS_NEXT_TSN_OFFSET          (SENDERS_NEXT_TSN_OFFSET + SENDERS_NEXT_TSN_LENGTH)
1144
1145 static const value_string stream_reset_result_values[] = {
1146   { 0, "Nothing to do"                       },
1147   { 1, "Performed"                           },
1148   { 2, "Denied"                              },
1149   { 3, "Error - Wrong SSN"                   },
1150   { 4, "Error - Request already in progress" },
1151   { 0, NULL                                  }
1152 };
1153
1154
1155 static void
1156 dissect_stream_reset_response_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item _U_)
1157 {
1158   guint length;
1159
1160   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1161
1162   proto_tree_add_item(parameter_tree, hf_stream_reset_rsp_seq_nr, parameter_tvb, STREAM_RESET_RSP_RSP_SEQ_NR_OFFSET, STREAM_RESET_SEQ_NR_LENGTH,     NETWORK_BYTE_ORDER);
1163   proto_tree_add_item(parameter_tree, hf_stream_reset_rsp_result, parameter_tvb, STREAM_RESET_RSP_RESULT_OFFSET,     STREAM_RESET_RSP_RESULT_LENGTH, NETWORK_BYTE_ORDER);
1164   if (length >= PARAMETER_HEADER_LENGTH + STREAM_RESET_SEQ_NR_LENGTH + STREAM_RESET_RSP_RESULT_LENGTH + SENDERS_NEXT_TSN_LENGTH)
1165     proto_tree_add_item(parameter_tree, hf_senders_next_tsn,   parameter_tvb, SENDERS_NEXT_TSN_OFFSET,   SENDERS_NEXT_TSN_LENGTH,   NETWORK_BYTE_ORDER);
1166   if (length >= PARAMETER_HEADER_LENGTH + STREAM_RESET_SEQ_NR_LENGTH + STREAM_RESET_RSP_RESULT_LENGTH + SENDERS_NEXT_TSN_LENGTH + RECEIVERS_NEXT_TSN_LENGTH)
1167     proto_tree_add_item(parameter_tree, hf_receivers_next_tsn, parameter_tvb, RECEIVERS_NEXT_TSN_OFFSET, RECEIVERS_NEXT_TSN_LENGTH, NETWORK_BYTE_ORDER);
1168 }
1169
1170 static void
1171 dissect_ecn_parameter(tvbuff_t *parameter_tvb _U_)
1172 {
1173 }
1174
1175 static void
1176 dissect_nonce_supported_parameter(tvbuff_t *parameter_tvb _U_)
1177 {
1178 }
1179
1180 #define RANDOM_NUMBER_OFFSET PARAMETER_VALUE_OFFSET
1181
1182 static void
1183 dissect_random_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
1184 {
1185   gint32 number_length;
1186
1187   number_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1188   if (number_length > 0)
1189     proto_tree_add_item(parameter_tree, hf_random_number, parameter_tvb, RANDOM_NUMBER_OFFSET, number_length, NETWORK_BYTE_ORDER);
1190 }
1191
1192 static void
1193 dissect_chunks_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
1194 {
1195   gint32 number_of_chunks;
1196   guint16 chunk_number, offset;
1197
1198   number_of_chunks = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1199   for(chunk_number = 1, offset = PARAMETER_VALUE_OFFSET; chunk_number <= number_of_chunks; chunk_number++, offset +=  CHUNK_TYPE_LENGTH)
1200     proto_tree_add_item(parameter_tree, hf_chunks_to_auth, parameter_tvb, offset, CHUNK_TYPE_LENGTH, NETWORK_BYTE_ORDER);
1201 }
1202
1203 static const value_string hmac_id_values[] = {
1204   { 0x0000,         "Reserved" },
1205   { 0x0001,         "SHA-1"    },
1206   { 0x0002,         "Reserved" },
1207   { 0x0003,         "SHA-256"  },
1208   { 0x8001,         "SHA_224"  },
1209   { 0x8002,         "SHA_384"  },
1210   { 0x8003,         "SHA_512"  },
1211   { 0,              NULL       } };
1212
1213 #define HMAC_ID_LENGTH 2
1214
1215 static void
1216 dissect_hmac_algo_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
1217 {
1218   gint32 number_of_ids;
1219   guint16 id_number, offset;
1220
1221   number_of_ids = (tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH) / HMAC_ID_LENGTH;
1222   for(id_number = 1, offset = PARAMETER_VALUE_OFFSET; id_number <= number_of_ids; id_number++, offset +=  HMAC_ID_LENGTH)
1223     proto_tree_add_item(parameter_tree, hf_hmac_id, parameter_tvb, offset, HMAC_ID_LENGTH, NETWORK_BYTE_ORDER);
1224 }
1225
1226 static void
1227 dissect_supported_extensions_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1228 {
1229   gint32 number_of_types;
1230   guint16 type_number, offset;
1231
1232   proto_item_append_text(parameter_item, " (Supported types: ");
1233   number_of_types = (tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH) / CHUNK_TYPE_LENGTH;
1234   for(type_number = 1, offset = PARAMETER_VALUE_OFFSET; type_number <= number_of_types; type_number++, offset +=  CHUNK_TYPE_LENGTH) {
1235     proto_tree_add_item(parameter_tree, hf_supported_chunk_type, parameter_tvb, offset, CHUNK_TYPE_LENGTH, NETWORK_BYTE_ORDER);
1236     proto_item_append_text(parameter_item, "%s", val_to_str(tvb_get_guint8(parameter_tvb, offset), chunk_type_values, "Unknown"));
1237     if (type_number < number_of_types)
1238       proto_item_append_text(parameter_item, ", ");
1239
1240   }
1241   proto_item_append_text(parameter_item, ")");
1242 }
1243
1244 static void
1245 dissect_forward_tsn_supported_parameter(tvbuff_t *parameter_tvb _U_)
1246 {
1247 }
1248
1249 #define CORRELATION_ID_LENGTH    4
1250 #define CORRELATION_ID_OFFSET    PARAMETER_VALUE_OFFSET
1251 #define ADDRESS_PARAMETER_OFFSET (CORRELATION_ID_OFFSET + CORRELATION_ID_LENGTH)
1252
1253 static void
1254 dissect_add_ip_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
1255 {
1256   guint16 address_length;
1257   tvbuff_t *address_tvb;
1258
1259   address_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
1260
1261   proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
1262   address_tvb    =  tvb_new_subset(parameter_tvb, ADDRESS_PARAMETER_OFFSET, address_length, address_length);
1263   proto_item_append_text(parameter_item, " (Address: ");
1264   dissect_parameter(address_tvb, pinfo, parameter_tree, parameter_item, FALSE);
1265   proto_item_append_text(parameter_item, ", correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
1266 }
1267
1268 static void
1269 dissect_del_ip_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
1270 {
1271   guint16 address_length;
1272   tvbuff_t *address_tvb;
1273
1274   address_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
1275
1276   proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
1277   address_tvb    =  tvb_new_subset(parameter_tvb, ADDRESS_PARAMETER_OFFSET, address_length, address_length);
1278   proto_item_append_text(parameter_item, " (Address: ");
1279   dissect_parameter(address_tvb, pinfo, parameter_tree, parameter_item, FALSE);
1280   proto_item_append_text(parameter_item, ", correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
1281 }
1282
1283 #define ERROR_CAUSE_IND_CASUES_OFFSET (CORRELATION_ID_OFFSET + CORRELATION_ID_LENGTH)
1284
1285 static void
1286 dissect_error_cause_indication_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
1287 {
1288   guint16 causes_length;
1289   tvbuff_t *causes_tvb;
1290
1291   proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
1292   causes_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
1293   causes_tvb    = tvb_new_subset(parameter_tvb, ERROR_CAUSE_IND_CASUES_OFFSET, causes_length, causes_length);
1294   dissect_error_causes(causes_tvb, pinfo,  parameter_tree);
1295 }
1296
1297 static void
1298 dissect_set_primary_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
1299 {
1300   guint16 address_length;
1301   tvbuff_t *address_tvb;
1302
1303   address_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
1304
1305   proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
1306   address_tvb    =  tvb_new_subset(parameter_tvb, ADDRESS_PARAMETER_OFFSET, address_length, address_length);
1307   proto_item_append_text(parameter_item, " (Address: ");
1308   dissect_parameter(address_tvb, pinfo, parameter_tree, parameter_item, FALSE);
1309   proto_item_append_text(parameter_item, ", correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
1310 }
1311
1312 static void
1313 dissect_success_report_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1314 {
1315   proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
1316   proto_item_append_text(parameter_item, " (Correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
1317 }
1318
1319 #define ADAP_INDICATION_LENGTH 4
1320 #define ADAP_INDICATION_OFFSET PARAMETER_VALUE_OFFSET
1321
1322 static void
1323 dissect_adap_indication_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1324 {
1325   proto_tree_add_item(parameter_tree, hf_adap_indication, parameter_tvb, ADAP_INDICATION_OFFSET, ADAP_INDICATION_LENGTH, NETWORK_BYTE_ORDER);
1326   proto_item_append_text(parameter_item, " (Indication: %u)", tvb_get_ntohl(parameter_tvb, ADAP_INDICATION_OFFSET));
1327 }
1328
1329 static void
1330 dissect_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1331 {
1332   guint16 type, parameter_value_length;
1333
1334   type                   = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
1335   parameter_value_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1336
1337   if (parameter_value_length > 0)
1338     proto_tree_add_item(parameter_tree, hf_parameter_value, parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length, NETWORK_BYTE_ORDER);
1339
1340   proto_item_append_text(parameter_item, " (Type %u, value length: %u byte%s)", type, parameter_value_length, plurality(parameter_value_length, "", "s"));
1341 }
1342
1343 #define HEARTBEAT_INFO_PARAMETER_ID             0x0001
1344 #define IPV4ADDRESS_PARAMETER_ID                0x0005
1345 #define IPV6ADDRESS_PARAMETER_ID                0x0006
1346 #define STATE_COOKIE_PARAMETER_ID               0x0007
1347 #define UNREC_PARA_PARAMETER_ID                 0x0008
1348 #define COOKIE_PRESERVATIVE_PARAMETER_ID        0x0009
1349 #define HOSTNAME_ADDRESS_PARAMETER_ID           0x000b
1350 #define SUPPORTED_ADDRESS_TYPES_PARAMETER_ID    0x000c
1351 #define OUTGOING_SSN_RESET_REQUEST_PARAMETER_ID 0x000d
1352 #define INCOMING_SSN_RESET_REQUEST_PARAMETER_ID 0x000e
1353 #define SSN_TSN_RESET_REQUEST_PARAMETER_ID      0x000f
1354 #define STREAM_RESET_RESPONSE_PARAMETER_ID      0x0010
1355 #define ECN_PARAMETER_ID                        0x8000
1356 #define NONCE_SUPPORTED_PARAMETER_ID            0x8001
1357 #define RANDOM_PARAMETER_ID                     0x8002
1358 #define CHUNKS_PARAMETER_ID                     0x8003
1359 #define HMAC_ALGO_PARAMETER_ID                  0x8004
1360 #define SUPPORTED_EXTENSIONS_PARAMETER_ID       0x8008
1361 #define FORWARD_TSN_SUPPORTED_PARAMETER_ID      0xC000
1362 #define ADD_IP_ADDRESS_PARAMETER_ID             0xC001
1363 #define DEL_IP_ADDRESS_PARAMETER_ID             0xC002
1364 #define ERROR_CAUSE_INDICATION_PARAMETER_ID     0xC003
1365 #define SET_PRIMARY_ADDRESS_PARAMETER_ID        0xC004
1366 #define SUCCESS_REPORT_PARAMETER_ID             0xC005
1367 #define ADAP_LAYER_INDICATION_PARAMETER_ID      0xC006
1368
1369 static const value_string parameter_identifier_values[] = {
1370   { HEARTBEAT_INFO_PARAMETER_ID,             "Heartbeat info"              },
1371   { IPV4ADDRESS_PARAMETER_ID,                "IPv4 address"                },
1372   { IPV6ADDRESS_PARAMETER_ID,                "IPv6 address"                },
1373   { STATE_COOKIE_PARAMETER_ID,               "State cookie"                },
1374   { UNREC_PARA_PARAMETER_ID,                 "Unrecognized parameter"      },
1375   { COOKIE_PRESERVATIVE_PARAMETER_ID,        "Cookie preservative"         },
1376   { HOSTNAME_ADDRESS_PARAMETER_ID,           "Hostname address"            },
1377   { OUTGOING_SSN_RESET_REQUEST_PARAMETER_ID, "Outgoing SSN reset request"  },
1378   { INCOMING_SSN_RESET_REQUEST_PARAMETER_ID, "Incoming SSN reset request"  },
1379   { SSN_TSN_RESET_REQUEST_PARAMETER_ID,      "SSN/TSN reset request"       },
1380   { STREAM_RESET_RESPONSE_PARAMETER_ID,      "Stream reset response"       },
1381   { SUPPORTED_ADDRESS_TYPES_PARAMETER_ID,    "Supported address types"     },
1382   { ECN_PARAMETER_ID,                        "ECN"                         },
1383   { NONCE_SUPPORTED_PARAMETER_ID,            "Nonce supported"             },
1384   { RANDOM_PARAMETER_ID,                     "Random"                      },
1385   { CHUNKS_PARAMETER_ID,                     "Authenticated Chunk list"    },
1386   { HMAC_ALGO_PARAMETER_ID,                  "Requested HMAC Algorithm"    },
1387   { SUPPORTED_EXTENSIONS_PARAMETER_ID,       "Supported Extensions"        },
1388   { FORWARD_TSN_SUPPORTED_PARAMETER_ID,      "Forward TSN supported"       },
1389   { ADD_IP_ADDRESS_PARAMETER_ID,             "Add IP address"              },
1390   { DEL_IP_ADDRESS_PARAMETER_ID,             "Delete IP address"           },
1391   { ERROR_CAUSE_INDICATION_PARAMETER_ID,     "Error cause indication"      },
1392   { SET_PRIMARY_ADDRESS_PARAMETER_ID,        "Set primary address"         },
1393   { SUCCESS_REPORT_PARAMETER_ID,             "Success report"              },
1394   { ADAP_LAYER_INDICATION_PARAMETER_ID,      "Adaptation Layer Indication" },
1395   { 0,                                       NULL                          } };
1396
1397 #define SCTP_PARAMETER_BIT_1  0x8000
1398 #define SCTP_PARAMETER_BIT_2 0x4000
1399
1400 static const true_false_string sctp_parameter_bit_1_value = {
1401   "Skip parameter and continue processing of the chunk",
1402   "Stop processing of chunk"
1403 };
1404
1405 static const true_false_string sctp_parameter_bit_2_value = {
1406   "Do report",
1407   "Do not report"
1408 };
1409
1410 static void
1411 dissect_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *additional_item, gboolean dissecting_init_init_ack_chunk)
1412 {
1413   guint16 type, length, padding_length;
1414   proto_item *parameter_item;
1415   proto_tree *parameter_tree;
1416   proto_item *type_item;
1417   proto_tree *type_tree;
1418
1419   type           = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
1420   length         = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1421   padding_length = tvb_length(parameter_tvb) - length;
1422
1423   if (!(chunk_tree || (dissecting_init_init_ack_chunk && (type == IPV4ADDRESS_PARAMETER_ID || type == IPV6ADDRESS_PARAMETER_ID))))
1424     return;
1425
1426   if (chunk_tree) {
1427     parameter_item = proto_tree_add_text(chunk_tree, parameter_tvb, PARAMETER_HEADER_OFFSET, tvb_length(parameter_tvb), "%s parameter", val_to_str(type, parameter_identifier_values, "Unknown"));
1428     parameter_tree = proto_item_add_subtree(parameter_item, ett_sctp_chunk_parameter);
1429
1430     type_item = proto_tree_add_item(parameter_tree, hf_parameter_type,   parameter_tvb, PARAMETER_TYPE_OFFSET,   PARAMETER_TYPE_LENGTH,   NETWORK_BYTE_ORDER);
1431     type_tree = proto_item_add_subtree(type_item, ett_sctp_parameter_type);
1432     proto_tree_add_item(type_tree, hf_parameter_bit_1,  parameter_tvb, PARAMETER_TYPE_OFFSET,  PARAMETER_TYPE_LENGTH,  NETWORK_BYTE_ORDER);
1433     proto_tree_add_item(type_tree, hf_parameter_bit_2,  parameter_tvb, PARAMETER_TYPE_OFFSET,  PARAMETER_TYPE_LENGTH,  NETWORK_BYTE_ORDER);
1434     proto_tree_add_item(parameter_tree, hf_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
1435   } else {
1436     parameter_item = NULL;
1437     parameter_tree = NULL;
1438   }
1439
1440   switch(type) {
1441   case HEARTBEAT_INFO_PARAMETER_ID:
1442     dissect_heartbeat_info_parameter(parameter_tvb, parameter_tree, parameter_item);
1443     break;
1444   case IPV4ADDRESS_PARAMETER_ID:
1445     dissect_ipv4_parameter(parameter_tvb, parameter_tree, parameter_item, additional_item, dissecting_init_init_ack_chunk);
1446     break;
1447   case IPV6ADDRESS_PARAMETER_ID:
1448     dissect_ipv6_parameter(parameter_tvb, parameter_tree, parameter_item, additional_item, dissecting_init_init_ack_chunk);
1449     break;
1450   case STATE_COOKIE_PARAMETER_ID:
1451     dissect_state_cookie_parameter(parameter_tvb, parameter_tree, parameter_item);
1452     break;
1453   case UNREC_PARA_PARAMETER_ID:
1454     dissect_unrecognized_parameters_parameter(parameter_tvb, pinfo,  parameter_tree);
1455     break;
1456   case COOKIE_PRESERVATIVE_PARAMETER_ID:
1457     dissect_cookie_preservative_parameter(parameter_tvb, parameter_tree, parameter_item);
1458     break;
1459   case HOSTNAME_ADDRESS_PARAMETER_ID:
1460     dissect_hostname_parameter(parameter_tvb, parameter_tree, parameter_item);
1461     break;
1462   case SUPPORTED_ADDRESS_TYPES_PARAMETER_ID:
1463     dissect_supported_address_types_parameter(parameter_tvb, parameter_tree, parameter_item);
1464     break;
1465   case OUTGOING_SSN_RESET_REQUEST_PARAMETER_ID:
1466     dissect_outgoing_ssn_reset_request_parameter(parameter_tvb, parameter_tree, parameter_item);
1467     break;
1468   case INCOMING_SSN_RESET_REQUEST_PARAMETER_ID:
1469     dissect_incoming_ssn_reset_request_parameter(parameter_tvb, parameter_tree, parameter_item);
1470     break;
1471   case SSN_TSN_RESET_REQUEST_PARAMETER_ID:
1472     dissect_ssn_tsn_reset_request_parameter(parameter_tvb, parameter_tree, parameter_item);
1473     break;
1474   case STREAM_RESET_RESPONSE_PARAMETER_ID:
1475     dissect_stream_reset_response_parameter(parameter_tvb, parameter_tree, parameter_item);
1476     break;
1477   case ECN_PARAMETER_ID:
1478     dissect_ecn_parameter(parameter_tvb);
1479     break;
1480   case NONCE_SUPPORTED_PARAMETER_ID:
1481     dissect_nonce_supported_parameter(parameter_tvb);
1482     break;
1483   case RANDOM_PARAMETER_ID:
1484     dissect_random_parameter(parameter_tvb, parameter_tree);
1485     break;
1486   case CHUNKS_PARAMETER_ID:
1487     dissect_chunks_parameter(parameter_tvb, parameter_tree);
1488     break;
1489   case HMAC_ALGO_PARAMETER_ID:
1490     dissect_hmac_algo_parameter(parameter_tvb, parameter_tree);
1491     break;
1492   case SUPPORTED_EXTENSIONS_PARAMETER_ID:
1493     dissect_supported_extensions_parameter(parameter_tvb, parameter_tree, parameter_item);
1494     break;
1495   case FORWARD_TSN_SUPPORTED_PARAMETER_ID:
1496     dissect_forward_tsn_supported_parameter(parameter_tvb);
1497     break;
1498   case ADD_IP_ADDRESS_PARAMETER_ID:
1499     dissect_add_ip_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
1500     break;
1501   case DEL_IP_ADDRESS_PARAMETER_ID:
1502     dissect_del_ip_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
1503     break;
1504   case ERROR_CAUSE_INDICATION_PARAMETER_ID:
1505     dissect_error_cause_indication_parameter(parameter_tvb, pinfo, parameter_tree);
1506     break;
1507   case SET_PRIMARY_ADDRESS_PARAMETER_ID:
1508     dissect_set_primary_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
1509     break;
1510   case SUCCESS_REPORT_PARAMETER_ID:
1511     dissect_success_report_parameter(parameter_tvb, parameter_tree, parameter_item);
1512     break;
1513   case ADAP_LAYER_INDICATION_PARAMETER_ID:
1514     dissect_adap_indication_parameter(parameter_tvb, parameter_tree, parameter_item);
1515     break;
1516   default:
1517     dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
1518     break;
1519   }
1520
1521   if (padding_length > 0)
1522     proto_tree_add_item(parameter_tree, hf_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
1523 }
1524
1525 static void
1526 dissect_parameters(tvbuff_t *parameters_tvb, packet_info *pinfo, proto_tree *tree, proto_item *additional_item, gboolean dissecting_init_init_ack_chunk)
1527 {
1528   gint offset, length, total_length, remaining_length;
1529   tvbuff_t *parameter_tvb;
1530
1531   offset = 0;
1532   while((remaining_length = tvb_length_remaining(parameters_tvb, offset))) {
1533     if ((offset > 0) && additional_item)
1534       proto_item_append_text(additional_item, " ");
1535     length       = tvb_get_ntohs(parameters_tvb, offset + PARAMETER_LENGTH_OFFSET);
1536     total_length = ADD_PADDING(length);
1537     if (remaining_length >= length)
1538       total_length = MIN(total_length, remaining_length);
1539     /* create a tvb for the parameter including the padding bytes */
1540     parameter_tvb  = tvb_new_subset(parameters_tvb, offset, total_length, total_length);
1541     dissect_parameter(parameter_tvb, pinfo, tree, additional_item, dissecting_init_init_ack_chunk);
1542     /* get rid of the handled parameter */
1543     offset += total_length;
1544   }
1545 }
1546
1547
1548 /*
1549  * Code to handle error causes for ABORT and ERROR chunks
1550  */
1551
1552
1553 #define CAUSE_CODE_LENGTH            2
1554 #define CAUSE_LENGTH_LENGTH          2
1555 #define CAUSE_HEADER_LENGTH          (CAUSE_CODE_LENGTH + CAUSE_LENGTH_LENGTH)
1556
1557 #define CAUSE_HEADER_OFFSET          0
1558 #define CAUSE_CODE_OFFSET            CAUSE_HEADER_OFFSET
1559 #define CAUSE_LENGTH_OFFSET          (CAUSE_CODE_OFFSET + CAUSE_CODE_LENGTH)
1560 #define CAUSE_INFO_OFFSET            (CAUSE_LENGTH_OFFSET + CAUSE_LENGTH_LENGTH)
1561
1562
1563 #define CAUSE_STREAM_IDENTIFIER_LENGTH 2
1564 #define CAUSE_RESERVED_LENGTH 2
1565 #define CAUSE_STREAM_IDENTIFIER_OFFSET CAUSE_INFO_OFFSET
1566 #define CAUSE_RESERVED_OFFSET          (CAUSE_STREAM_IDENTIFIER_OFFSET + CAUSE_STREAM_IDENTIFIER_LENGTH)
1567
1568 static void
1569 dissect_invalid_stream_identifier_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
1570 {
1571   proto_tree_add_item(cause_tree, hf_cause_stream_identifier, cause_tvb, CAUSE_STREAM_IDENTIFIER_OFFSET, CAUSE_STREAM_IDENTIFIER_LENGTH, NETWORK_BYTE_ORDER);
1572   proto_tree_add_item(cause_tree, hf_cause_reserved,          cause_tvb, CAUSE_RESERVED_OFFSET,          CAUSE_RESERVED_LENGTH,          NETWORK_BYTE_ORDER);
1573   proto_item_append_text(cause_item, " (SID: %u)", tvb_get_ntohs(cause_tvb, CAUSE_STREAM_IDENTIFIER_OFFSET));
1574 }
1575
1576 #define CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH 4
1577 #define CAUSE_MISSING_PARAMETER_TYPE_LENGTH       2
1578
1579 #define CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET CAUSE_INFO_OFFSET
1580 #define CAUSE_FIRST_MISSING_PARAMETER_TYPE_OFFSET (CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET + \
1581                                                    CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH )
1582
1583 static void
1584 dissect_missing_mandatory_parameters_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree)
1585 {
1586   guint32 number_of_missing_parameters, missing_parameter_number;
1587   guint   offset;
1588
1589   number_of_missing_parameters = tvb_get_ntohl(cause_tvb, CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET);
1590   proto_tree_add_item(cause_tree, hf_cause_number_of_missing_parameters, cause_tvb, CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET, CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH, NETWORK_BYTE_ORDER);
1591   offset = CAUSE_FIRST_MISSING_PARAMETER_TYPE_OFFSET;
1592   for(missing_parameter_number = 1; missing_parameter_number <= number_of_missing_parameters; missing_parameter_number++) {
1593     proto_tree_add_item(cause_tree, hf_cause_missing_parameter_type, cause_tvb, offset, CAUSE_MISSING_PARAMETER_TYPE_LENGTH, NETWORK_BYTE_ORDER);
1594     offset +=  CAUSE_MISSING_PARAMETER_TYPE_LENGTH;
1595   }
1596 }
1597
1598 #define CAUSE_MEASURE_OF_STALENESS_LENGTH 4
1599 #define CAUSE_MEASURE_OF_STALENESS_OFFSET CAUSE_INFO_OFFSET
1600
1601 static void
1602 dissect_stale_cookie_error_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
1603 {
1604   proto_tree_add_item(cause_tree, hf_cause_measure_of_staleness, cause_tvb, CAUSE_MEASURE_OF_STALENESS_OFFSET, CAUSE_MEASURE_OF_STALENESS_LENGTH, NETWORK_BYTE_ORDER);
1605   proto_item_append_text(cause_item, " (Measure: %u usec)", tvb_get_ntohl(cause_tvb, CAUSE_MEASURE_OF_STALENESS_OFFSET));
1606 }
1607
1608 static void
1609 dissect_out_of_resource_cause(tvbuff_t *cause_tvb _U_)
1610 {
1611 }
1612
1613 static void
1614 dissect_unresolvable_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
1615 {
1616   guint16 parameter_length;
1617   tvbuff_t *parameter_tvb;
1618
1619   parameter_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1620   parameter_tvb    = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, parameter_length, parameter_length);
1621   proto_item_append_text(cause_item, " (Address: ");
1622   dissect_parameter(parameter_tvb, pinfo, cause_tree, cause_item, FALSE);
1623   proto_item_append_text(cause_item, ")");
1624 }
1625
1626 static gboolean
1627 dissect_sctp_chunk(tvbuff_t *chunk_tvb,
1628                                    packet_info *pinfo,
1629                                    proto_tree *tree,
1630                                    proto_tree *sctp_tree,
1631                                    sctp_half_assoc_t* assoc,
1632                                    gboolean useinfo);
1633
1634 static void
1635 dissect_unrecognized_chunk_type_cause(tvbuff_t *cause_tvb,  packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
1636 {
1637   guint16 chunk_length;
1638   guint8 unrecognized_type;
1639   tvbuff_t *unrecognized_chunk_tvb;
1640
1641   chunk_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1642   unrecognized_chunk_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, chunk_length, chunk_length);
1643   dissect_sctp_chunk(unrecognized_chunk_tvb, pinfo, cause_tree,cause_tree, NULL, FALSE);
1644   unrecognized_type   = tvb_get_guint8(unrecognized_chunk_tvb, CHUNK_TYPE_OFFSET);
1645   proto_item_append_text(cause_item, " (Type: %u (%s))", unrecognized_type, val_to_str(unrecognized_type, chunk_type_values, "unknown"));
1646 }
1647
1648 static void
1649 dissect_invalid_mandatory_parameter_cause(tvbuff_t *cause_tvb _U_)
1650 {
1651 }
1652
1653 static void
1654 dissect_unrecognized_parameters_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree)
1655 {
1656   guint16 cause_info_length;
1657   tvbuff_t *unrecognized_parameters_tvb;
1658
1659   cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1660
1661   unrecognized_parameters_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1662   dissect_parameters(unrecognized_parameters_tvb, pinfo, cause_tree, NULL, FALSE);
1663 }
1664
1665 #define CAUSE_TSN_LENGTH 4
1666 #define CAUSE_TSN_OFFSET CAUSE_INFO_OFFSET
1667
1668 static void
1669 dissect_no_user_data_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
1670 {
1671   proto_tree_add_item(cause_tree, hf_cause_tsn, cause_tvb, CAUSE_TSN_OFFSET, CAUSE_TSN_LENGTH, NETWORK_BYTE_ORDER);
1672   proto_item_append_text(cause_item, " (TSN: %u)", tvb_get_ntohl(cause_tvb, CAUSE_TSN_OFFSET));
1673 }
1674
1675 static void
1676 dissect_cookie_received_while_shutting_down_cause(tvbuff_t *cause_tvb _U_)
1677 {
1678 }
1679
1680 static void
1681 dissect_restart_with_new_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree* cause_tree, proto_item *cause_item)
1682 {
1683   guint16 cause_info_length;
1684   tvbuff_t *parameter_tvb;
1685
1686   cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1687   parameter_tvb    = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1688   proto_item_append_text(cause_item, " (New addresses: ");
1689   dissect_parameters(parameter_tvb, pinfo, cause_tree, cause_item, FALSE);
1690   proto_item_append_text(cause_item, ")");
1691 }
1692
1693 static void
1694 dissect_user_initiated_abort_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree)
1695 {
1696   guint16 cause_info_length;
1697
1698   cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1699   if (cause_info_length > 0)
1700     proto_tree_add_item(cause_tree, hf_cause_info, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, NETWORK_BYTE_ORDER);
1701 }
1702
1703 static void
1704 dissect_protocol_violation_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree)
1705 {
1706   guint16 cause_info_length;
1707
1708   cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1709   if (cause_info_length > 0)
1710     proto_tree_add_item(cause_tree, hf_cause_info, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, NETWORK_BYTE_ORDER);
1711 }
1712
1713 static void
1714 dissect_delete_last_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
1715 {
1716   guint16 cause_info_length;
1717   tvbuff_t *parameter_tvb;
1718
1719   cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1720   parameter_tvb    = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1721   proto_item_append_text(cause_item, " (Last address: ");
1722   dissect_parameter(parameter_tvb, pinfo, cause_tree, cause_item, FALSE);
1723   proto_item_append_text(cause_item, ")");
1724 }
1725
1726 static void
1727 dissect_resource_outage_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree)
1728 {
1729   guint16 cause_info_length;
1730   tvbuff_t *parameter_tvb;
1731
1732   cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1733   parameter_tvb     = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1734   dissect_parameter(parameter_tvb, pinfo, cause_tree, NULL, FALSE);
1735 }
1736
1737 static void
1738 dissect_delete_source_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
1739 {
1740   guint16 cause_info_length;
1741   tvbuff_t *parameter_tvb;
1742
1743   cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1744   parameter_tvb    = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1745   proto_item_append_text(cause_item, " (Deleted address: ");
1746   dissect_parameter(parameter_tvb, pinfo, cause_tree, cause_item, FALSE);
1747   proto_item_append_text(cause_item, ")");
1748 }
1749
1750 static void
1751 dissect_request_refused_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree)
1752 {
1753   guint16 cause_info_length;
1754   tvbuff_t *parameter_tvb;
1755
1756   cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1757   parameter_tvb    = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1758   dissect_parameter(parameter_tvb, pinfo, cause_tree, NULL, FALSE);
1759 }
1760
1761 static void
1762 dissect_unsupported_hmac_id_cause(tvbuff_t *cause_tvb, packet_info *pinfo _U_, proto_tree *cause_tree)
1763 {
1764   proto_tree_add_item(cause_tree, hf_hmac_id, cause_tvb, CAUSE_INFO_OFFSET, HMAC_ID_LENGTH, NETWORK_BYTE_ORDER);
1765 }
1766
1767 static void
1768 dissect_unknown_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
1769 {
1770   guint16 cause_info_length;
1771
1772   cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1773   if (cause_info_length > 0)
1774     proto_tree_add_item(cause_tree, hf_cause_info, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, NETWORK_BYTE_ORDER);
1775   proto_item_append_text(cause_item, " (Code: %u, information length: %u byte%s)", tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET), cause_info_length, plurality(cause_info_length, "", "s"));
1776 }
1777
1778 #define INVALID_STREAM_IDENTIFIER                  0x01
1779 #define MISSING_MANDATORY_PARAMETERS               0x02
1780 #define STALE_COOKIE_ERROR                         0x03
1781 #define OUT_OF_RESOURCE                            0x04
1782 #define UNRESOLVABLE_ADDRESS                       0x05
1783 #define UNRECOGNIZED_CHUNK_TYPE                    0x06
1784 #define INVALID_MANDATORY_PARAMETER                0x07
1785 #define UNRECOGNIZED_PARAMETERS                    0x08
1786 #define NO_USER_DATA                               0x09
1787 #define COOKIE_RECEIVED_WHILE_SHUTTING_DOWN        0x0a
1788 #define RESTART_WITH_NEW_ADDRESSES                 0x0b
1789 #define USER_INITIATED_ABORT                       0x0c
1790 #define PROTOCOL_VIOLATION                         0x0d
1791 #define REQUEST_TO_DELETE_LAST_ADDRESS             0x00a0
1792 #define OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE 0x00a1
1793 #define REQUEST_TO_DELETE_SOURCE_ADDRESS           0x00a2
1794 #define ABORT_DUE_TO_ILLEGAL_ASCONF                0x00a3
1795 #define REQUEST_REFUSED                            0x00a4
1796 #define UNSUPPORTED_HMAC_ID                        0x0105
1797
1798 static const value_string cause_code_values[] = {
1799   { INVALID_STREAM_IDENTIFIER,                  "Invalid stream identifier" },
1800   { MISSING_MANDATORY_PARAMETERS,               "Missing mandatory parameter" },
1801   { STALE_COOKIE_ERROR,                         "Stale cookie error" },
1802   { OUT_OF_RESOURCE,                            "Out of resource" },
1803   { UNRESOLVABLE_ADDRESS,                       "Unresolvable address" },
1804   { UNRECOGNIZED_CHUNK_TYPE,                    "Unrecognized chunk type" },
1805   { INVALID_MANDATORY_PARAMETER,                "Invalid mandatory parameter" },
1806   { UNRECOGNIZED_PARAMETERS,                    "Unrecognized parameters" },
1807   { NO_USER_DATA,                               "No user data" },
1808   { COOKIE_RECEIVED_WHILE_SHUTTING_DOWN,        "Cookie received while shutting down" },
1809   { RESTART_WITH_NEW_ADDRESSES,                 "Restart of an association with new addresses" },
1810   { USER_INITIATED_ABORT,                       "User initiated ABORT" },
1811   { PROTOCOL_VIOLATION,                         "Protocol violation" },
1812   { REQUEST_TO_DELETE_LAST_ADDRESS,             "Request to delete last address" },
1813   { OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE, "Operation refused due to resource shortage" },
1814   { REQUEST_TO_DELETE_SOURCE_ADDRESS,           "Request to delete source address" },
1815   { ABORT_DUE_TO_ILLEGAL_ASCONF,                "Association Aborted due to illegal ASCONF-ACK" },
1816   { REQUEST_REFUSED,                            "Request refused - no authorization" },
1817   { UNSUPPORTED_HMAC_ID,                        "Unsupported HMAC identifier" },
1818   { 0,                                          NULL } };
1819
1820
1821 static void
1822 dissect_error_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *chunk_tree)
1823 {
1824   guint16 code, length, padding_length;
1825   proto_item *cause_item;
1826   proto_tree *cause_tree;
1827
1828   code           = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET);
1829   length         = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
1830   padding_length = tvb_length(cause_tvb) - length;
1831
1832   cause_item = proto_tree_add_text(chunk_tree, cause_tvb, CAUSE_HEADER_OFFSET, tvb_length(cause_tvb), "%s cause", val_to_str(code, cause_code_values, "Unknown"));
1833   cause_tree = proto_item_add_subtree(cause_item, ett_sctp_chunk_cause);
1834
1835   proto_tree_add_item(cause_tree, hf_cause_code, cause_tvb,   CAUSE_CODE_OFFSET,   CAUSE_CODE_LENGTH,   NETWORK_BYTE_ORDER);
1836   proto_tree_add_item(cause_tree, hf_cause_length, cause_tvb, CAUSE_LENGTH_OFFSET, CAUSE_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
1837
1838   switch(code) {
1839   case INVALID_STREAM_IDENTIFIER:
1840     dissect_invalid_stream_identifier_cause(cause_tvb, cause_tree, cause_item);
1841     break;
1842   case MISSING_MANDATORY_PARAMETERS:
1843     dissect_missing_mandatory_parameters_cause(cause_tvb, cause_tree);
1844     break;
1845   case STALE_COOKIE_ERROR:
1846     dissect_stale_cookie_error_cause(cause_tvb, cause_tree, cause_item);
1847     break;
1848   case OUT_OF_RESOURCE:
1849     dissect_out_of_resource_cause(cause_tvb);
1850     break;
1851   case UNRESOLVABLE_ADDRESS:
1852     dissect_unresolvable_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
1853     break;
1854   case UNRECOGNIZED_CHUNK_TYPE:
1855     dissect_unrecognized_chunk_type_cause(cause_tvb, pinfo, cause_tree, cause_item);
1856     break;
1857   case INVALID_MANDATORY_PARAMETER:
1858     dissect_invalid_mandatory_parameter_cause(cause_tvb);
1859     break;
1860   case UNRECOGNIZED_PARAMETERS:
1861     dissect_unrecognized_parameters_cause(cause_tvb, pinfo, cause_tree);
1862     break;
1863   case NO_USER_DATA:
1864     dissect_no_user_data_cause(cause_tvb, cause_tree, cause_item);
1865     break;
1866   case COOKIE_RECEIVED_WHILE_SHUTTING_DOWN:
1867     dissect_cookie_received_while_shutting_down_cause(cause_tvb);
1868     break;
1869   case RESTART_WITH_NEW_ADDRESSES:
1870     dissect_restart_with_new_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
1871     break;
1872   case USER_INITIATED_ABORT:
1873     dissect_user_initiated_abort_cause(cause_tvb, cause_tree);
1874     break;
1875   case PROTOCOL_VIOLATION:
1876     dissect_protocol_violation_cause(cause_tvb, cause_tree);
1877     break;
1878   case REQUEST_TO_DELETE_LAST_ADDRESS:
1879     dissect_delete_last_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
1880     break;
1881   case OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE:
1882     dissect_resource_outage_cause(cause_tvb, pinfo, cause_tree);
1883     break;
1884   case REQUEST_TO_DELETE_SOURCE_ADDRESS:
1885     dissect_delete_source_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
1886     break;
1887   case REQUEST_REFUSED:
1888     dissect_request_refused_cause(cause_tvb, pinfo, cause_tree);
1889     break;
1890   case UNSUPPORTED_HMAC_ID:
1891     dissect_unsupported_hmac_id_cause(cause_tvb, pinfo, cause_tree);
1892     break;
1893   default:
1894     dissect_unknown_cause(cause_tvb, cause_tree, cause_item);
1895     break;
1896   }
1897
1898   if (padding_length > 0)
1899     proto_tree_add_item(cause_tree, hf_cause_padding, cause_tvb, CAUSE_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
1900 }
1901
1902 static void
1903 dissect_error_causes(tvbuff_t *causes_tvb, packet_info *pinfo, proto_tree *tree)
1904 {
1905   gint offset, length, total_length, remaining_length;
1906   tvbuff_t *cause_tvb;
1907
1908   offset = 0;
1909   while((remaining_length = tvb_length_remaining(causes_tvb, offset))) {
1910     length       = tvb_get_ntohs(causes_tvb, offset + CAUSE_LENGTH_OFFSET);
1911     total_length = ADD_PADDING(length);
1912     if (remaining_length >= length)
1913       total_length = MIN(total_length, remaining_length);
1914     /* create a tvb for the parameter including the padding bytes */
1915     cause_tvb    = tvb_new_subset(causes_tvb, offset, total_length, total_length);
1916     dissect_error_cause(cause_tvb, pinfo, tree);
1917     /* get rid of the handled cause */
1918     offset += total_length;
1919   }
1920 }
1921
1922
1923 /*
1924  * Code to actually dissect the packets
1925 */
1926
1927 static gboolean try_heuristic_first = FALSE;
1928
1929 static gboolean
1930 dissect_payload(tvbuff_t *payload_tvb, packet_info *pinfo, proto_tree *tree, guint32 ppi)
1931 {
1932   guint32 low_port, high_port;
1933
1934   pinfo->ppid = ppi;
1935
1936   if (enable_ulp_dissection) {
1937     if (try_heuristic_first) {
1938       /* do lookup with the heuristic subdissector table */
1939       if (dissector_try_heuristic(sctp_heur_subdissector_list, payload_tvb, pinfo, tree))
1940          return TRUE;
1941     }
1942
1943     /* Do lookups with the subdissector table.
1944
1945        When trying port numbers, we try the port number with the lower value
1946        first, followed by the port number with the higher value.  This means
1947        that, for packets where a dissector is registered for *both* port
1948        numbers, and where there's no match on the PPI:
1949
1950     1) we pick the same dissector for traffic going in both directions;
1951
1952     2) we prefer the port number that's more likely to be the right
1953        one (as that prefers well-known ports to reserved ports);
1954
1955        although there is, of course, no guarantee that any such strategy
1956        will always pick the right port number.
1957
1958        XXX - we ignore port numbers of 0, as some dissectors use a port
1959        number of 0 to disable the port. */
1960     if (dissector_try_port(sctp_ppi_dissector_table, ppi, payload_tvb, pinfo, tree))
1961       return TRUE;
1962     if (pinfo->srcport > pinfo->destport) {
1963       low_port = pinfo->destport;
1964       high_port = pinfo->srcport;
1965     } else {
1966       low_port = pinfo->srcport;
1967       high_port = pinfo->destport;
1968     }
1969     if (low_port != 0 &&
1970         dissector_try_port(sctp_port_dissector_table, low_port, payload_tvb, pinfo, tree))
1971       return TRUE;
1972     if (high_port != 0 &&
1973         dissector_try_port(sctp_port_dissector_table, high_port, payload_tvb, pinfo, tree))
1974       return TRUE;
1975
1976     if (!try_heuristic_first) {
1977       /* do lookup with the heuristic subdissector table */
1978       if (dissector_try_heuristic(sctp_heur_subdissector_list, payload_tvb, pinfo, tree))
1979          return TRUE;
1980     }
1981   }
1982   /* Oh, well, we don't know this; dissect it as data. */
1983   call_dissector(data_handle, payload_tvb, pinfo, tree);
1984   return TRUE;
1985 }
1986
1987 #define DATA_CHUNK_TSN_LENGTH         4
1988 #define DATA_CHUNK_STREAM_ID_LENGTH   2
1989 #define DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH 2
1990 #define DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH 4
1991
1992 #define DATA_CHUNK_TSN_OFFSET         (CHUNK_VALUE_OFFSET + 0)
1993 #define DATA_CHUNK_STREAM_ID_OFFSET   (DATA_CHUNK_TSN_OFFSET + DATA_CHUNK_TSN_LENGTH)
1994 #define DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET (DATA_CHUNK_STREAM_ID_OFFSET + \
1995                                              DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH)
1996 #define DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET (DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET + \
1997                                                DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH)
1998 #define DATA_CHUNK_PAYLOAD_OFFSET     (DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET + \
1999                                        DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH)
2000
2001 #define DATA_CHUNK_HEADER_LENGTH      (CHUNK_HEADER_LENGTH + \
2002                                        DATA_CHUNK_TSN_LENGTH + \
2003                                        DATA_CHUNK_STREAM_ID_LENGTH + \
2004                                        DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH + \
2005                                        DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH)
2006
2007 #define SCTP_DATA_CHUNK_E_BIT 0x01
2008 #define SCTP_DATA_CHUNK_B_BIT 0x02
2009 #define SCTP_DATA_CHUNK_U_BIT 0x04
2010 #define SCTP_DATA_CHUNK_I_BIT 0x08
2011
2012 /* table to hold fragmented SCTP messages */
2013 static GHashTable *frag_table = NULL;
2014
2015
2016 typedef struct _frag_key {
2017   guint16 sport;
2018   guint16 dport;
2019   guint32 verification_tag;
2020   guint16 stream_id;
2021   guint16 stream_seq_num;
2022 } frag_key;
2023
2024
2025 static gint
2026 frag_equal(gconstpointer k1, gconstpointer k2)
2027 {
2028   const frag_key* key1 = (const frag_key*) k1;
2029   const frag_key* key2 = (const frag_key*) k2;
2030
2031   return ( (key1->sport == key2->sport) &&
2032            (key1->dport == key1->dport) &&
2033            (key1->verification_tag == key1->verification_tag) &&
2034            (key1->stream_id == key1->stream_id) &&
2035            (key1->stream_seq_num == key1->stream_seq_num)
2036            ? TRUE : FALSE);
2037 }
2038
2039
2040 static guint
2041 frag_hash(gconstpointer k)
2042 {
2043   const frag_key* key = (const frag_key*) k;
2044
2045   return key->sport ^ key->dport ^ key->verification_tag ^
2046          key->stream_id ^ key->stream_seq_num;
2047 }
2048
2049
2050
2051 static void
2052 frag_free_msgs(sctp_frag_msg *msg)
2053 {
2054   sctp_frag_be *beginend;
2055   sctp_fragment *fragment;
2056
2057   /* free all begins */
2058   while (msg->begins) {
2059     beginend = msg->begins;
2060     msg->begins = msg->begins->next;
2061     g_free(beginend);
2062   }
2063
2064   /* free all ends */
2065   while (msg->ends) {
2066     beginend = msg->ends;
2067     msg->ends = msg->ends->next;
2068     g_free(beginend);
2069   }
2070
2071   /* free all fragments */
2072   while (msg->fragments) {
2073     fragment = msg->fragments;
2074     msg->fragments = msg->fragments->next;
2075     g_free(fragment->data);
2076     g_free(fragment);
2077   }
2078
2079   /* msg->messages is se_ allocated, no need to free it */
2080
2081   g_free(msg);
2082 }
2083
2084 static gboolean
2085 free_table_entry(gpointer key, gpointer value, gpointer user_data _U_)
2086 {
2087   sctp_frag_msg *msg = value;
2088   frag_key *fkey = key;
2089
2090   frag_free_msgs(msg);
2091   g_free(fkey);
2092   return TRUE;
2093 }
2094
2095 static void
2096 frag_table_init(void)
2097 {
2098   /* destroy an existing hast table and create a new one */
2099   if (frag_table) {
2100     g_hash_table_foreach_remove(frag_table, free_table_entry, NULL);
2101     g_hash_table_destroy(frag_table);
2102     frag_table=NULL;
2103   }
2104
2105   frag_table = g_hash_table_new(frag_hash, frag_equal);
2106 }
2107
2108
2109 static sctp_frag_msg*
2110 find_message(guint16 stream_id, guint16 stream_seq_num)
2111 {
2112   frag_key key;
2113
2114   key.sport = sctp_info.sport;
2115   key.dport = sctp_info.dport;
2116   key.verification_tag = sctp_info.verification_tag;
2117   key.stream_id = stream_id;
2118   key.stream_seq_num = stream_seq_num;
2119
2120   return g_hash_table_lookup(frag_table, &key);
2121 }
2122
2123
2124 static sctp_fragment*
2125 find_fragment(guint32 tsn, guint16 stream_id, guint16 stream_seq_num)
2126 {
2127   sctp_frag_msg *msg;
2128   sctp_fragment *next_fragment;
2129
2130   msg = find_message(stream_id, stream_seq_num);
2131
2132   if (msg) {
2133     next_fragment = msg->fragments;
2134     while (next_fragment) {
2135       if (next_fragment->tsn == tsn)
2136         return next_fragment;
2137       next_fragment = next_fragment->next;
2138     }
2139   }
2140
2141   return NULL;
2142 }
2143
2144
2145 static sctp_fragment*
2146 add_fragment(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 tsn,
2147              guint16 stream_id, guint16 stream_seq_num, guint8 b_bit, guint8 e_bit)
2148 {
2149   sctp_frag_msg *msg;
2150   sctp_fragment *fragment, *last_fragment;
2151   sctp_frag_be *beginend, *last_beginend;
2152   frag_key *key;
2153
2154   /* lookup message. if not found, create it */
2155   msg = find_message(stream_id, stream_seq_num);
2156
2157   if (!msg) {
2158     msg = g_malloc (sizeof (sctp_frag_msg));
2159     msg->begins = NULL;
2160     msg->ends = NULL;
2161     msg->fragments = NULL;
2162     msg->messages = NULL;
2163     msg->next = NULL;
2164
2165     key = g_malloc(sizeof (frag_key));
2166     key->sport = sctp_info.sport;
2167     key->dport = sctp_info.dport;
2168     key->verification_tag = sctp_info.verification_tag;
2169     key->stream_id = stream_id;
2170     key->stream_seq_num = stream_seq_num;
2171
2172     g_hash_table_insert(frag_table, key, msg);
2173   }
2174
2175   /* lookup segment. if not found, create it */
2176   fragment = find_fragment(tsn, stream_id, stream_seq_num);
2177
2178   if (fragment) {
2179     /* this fragment is already known.
2180      * compare frame number to check if it's a duplicate
2181      */
2182     if (fragment->frame_num == pinfo->fd->num) {
2183       return fragment;
2184     } else {
2185       /* there already is a fragment having the same ports, v_tag,
2186        * stream id, stream_seq_num and tsn but it appeared in a different
2187        * frame, so it must be a duplicate fragment. maybe a retransmission?
2188        * Mark it as duplicate and return NULL
2189        */
2190       if (check_col(pinfo->cinfo, COL_INFO))
2191         col_append_str(pinfo->cinfo, COL_INFO, " (Duplicate Message Fragment)");
2192
2193       proto_tree_add_uint(tree, hf_sctp_duplicate, tvb, 0, 0, fragment->frame_num);
2194       return NULL;
2195     }
2196   }
2197
2198   /* create new fragment */
2199   fragment = g_malloc (sizeof (sctp_fragment));
2200   fragment->frame_num = pinfo->fd->num;
2201   fragment->tsn = tsn;
2202   fragment->len = tvb_length(tvb);
2203   fragment->next = NULL;
2204   if (fragment->len) {
2205     fragment->data = g_malloc (fragment->len);
2206     tvb_memcpy(tvb, fragment->data, 0, fragment->len);
2207   }
2208
2209   /* add new fragment to linked list. sort ascending by tsn */
2210   if (!msg->fragments)
2211     msg->fragments = fragment;
2212   else {
2213     if (msg->fragments->tsn > fragment->tsn) {
2214       fragment->next = msg->fragments;
2215       msg->fragments = fragment;
2216     } else {
2217         last_fragment = msg->fragments;
2218         while (last_fragment->next &&
2219                last_fragment->next->tsn < fragment->tsn)
2220           last_fragment = last_fragment->next;
2221
2222         fragment->next = last_fragment->next;
2223         last_fragment->next = fragment;
2224     }
2225   }
2226
2227
2228   /* save begin or end if neccessary */
2229   if (b_bit && !e_bit) {
2230     beginend = g_malloc (sizeof (sctp_frag_be));
2231     beginend->fragment = fragment;
2232     beginend->next = NULL;
2233
2234     /* add begin to linked list. sort descending by tsn */
2235     if (!msg->begins)
2236       msg->begins = beginend;
2237     else {
2238       if (msg->begins->fragment->tsn < beginend->fragment->tsn) {
2239         beginend->next = msg->begins;
2240         msg->begins = beginend;
2241       } else {
2242         last_beginend = msg->begins;
2243         while (last_beginend->next &&
2244                last_beginend->next->fragment->tsn > beginend->fragment->tsn)
2245           last_beginend = last_beginend->next;
2246
2247         beginend->next = last_beginend->next;
2248        last_beginend->next = beginend;
2249       }
2250     }
2251
2252   }
2253
2254   if (!b_bit && e_bit) {
2255     beginend = g_malloc (sizeof (sctp_frag_be));
2256     beginend->fragment = fragment;
2257     beginend->next = NULL;
2258
2259     /* add end to linked list. sort ascending by tsn */
2260     if (!msg->ends)
2261       msg->ends = beginend;
2262     else {
2263       if (msg->ends->fragment->tsn > beginend->fragment->tsn) {
2264         beginend->next = msg->ends;
2265         msg->ends = beginend;
2266       } else {
2267         last_beginend = msg->ends;
2268         while (last_beginend->next &&
2269                last_beginend->next->fragment->tsn < beginend->fragment->tsn)
2270           last_beginend = last_beginend->next;
2271
2272         beginend->next = last_beginend->next;
2273         last_beginend->next = beginend;
2274       }
2275     }
2276
2277   }
2278
2279   return fragment;
2280 }
2281
2282 static tvbuff_t*
2283 fragment_reassembly(tvbuff_t *tvb, sctp_fragment* fragment,
2284                     packet_info *pinfo, proto_tree *tree, guint16 stream_id,
2285                     guint16 stream_seq_num)
2286 {
2287   sctp_frag_msg *msg;
2288   sctp_complete_msg *message, *last_message;
2289   sctp_fragment *frag_i, *last_frag, *first_frag;
2290   sctp_frag_be *begin, *end, *beginend;
2291   guint32 len, offset = 0;
2292   tvbuff_t* new_tvb = NULL;
2293   proto_item *item;
2294   proto_tree *ptree;
2295
2296   msg = find_message(stream_id, stream_seq_num);
2297
2298   if (!msg) {
2299     /* no message, we can't do anything */
2300     return NULL;
2301   }
2302
2303   /* check if fragment is part of an already reassembled message */
2304   for (message = msg->messages;
2305        message &&
2306        !(message->begin <= fragment->tsn && message->end >= fragment->tsn) &&
2307        !(message->begin > message->end &&
2308        (message->begin <= fragment->tsn || message->end >= fragment->tsn));
2309          message = message->next);
2310
2311   if (message) {
2312     /* we found the reassembled message this fragment belongs to */
2313     if (fragment == message->reassembled_in) {
2314
2315       /* this is the last fragment, create data source */
2316       new_tvb = tvb_new_child_real_data(tvb, message->data, message->len, message->len);
2317       add_new_data_source(pinfo, new_tvb, "Reassembled SCTP Message");
2318
2319       /* display reassembly info */
2320       item = proto_tree_add_item(tree, hf_sctp_fragments, tvb, 0, -1, FALSE);
2321       ptree = proto_item_add_subtree(item, ett_sctp_fragments);
2322       proto_item_append_text(item, " (%u bytes, %u fragments): ",
2323                              message->len, message->end - message->begin + 1);
2324
2325       if (message->begin > message->end) {
2326         for (frag_i = find_fragment(message->begin, stream_id, stream_seq_num);
2327              frag_i;
2328              frag_i = frag_i->next) {
2329
2330           proto_tree_add_uint_format(ptree, hf_sctp_fragment, new_tvb, offset, frag_i->len,
2331                                      frag_i->frame_num, "Frame: %u, payload: %u-%u (%u bytes)",
2332                                      frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
2333           offset += frag_i->len;
2334         }
2335
2336         for (frag_i = msg->fragments;
2337              frag_i && frag_i->tsn <= message->end;
2338              frag_i = frag_i->next) {
2339
2340           proto_tree_add_uint_format(ptree, hf_sctp_fragment, new_tvb, offset, frag_i->len,
2341                                      frag_i->frame_num, "Frame: %u, payload: %u-%u (%u bytes)",
2342                                      frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
2343           offset += frag_i->len;
2344         }
2345       } else {
2346         for (frag_i = find_fragment(message->begin, stream_id, stream_seq_num);
2347              frag_i && frag_i->tsn <= message->end;
2348              frag_i = frag_i->next) {
2349
2350           proto_tree_add_uint_format(ptree, hf_sctp_fragment, new_tvb, offset, frag_i->len,
2351                                      frag_i->frame_num, "Frame: %u, payload: %u-%u (%u bytes)",
2352                                      frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
2353           offset += frag_i->len;
2354         }
2355       }
2356
2357       return new_tvb;
2358     }
2359
2360     /* this is not the last fragment,
2361      * so let the user know the frame where the reassembly is
2362      */
2363     if (check_col(pinfo->cinfo, COL_INFO))
2364       col_append_str(pinfo->cinfo, COL_INFO, " (Message Fragment) ");
2365
2366     proto_tree_add_uint(tree, hf_sctp_reassembled_in, tvb, 0, 0, message->reassembled_in->frame_num);
2367     return NULL;
2368   }
2369
2370   /* this fragment has not been reassembled, yet
2371    * check now if we can reassemble it
2372    * at first look for the first and last tsn of the msg
2373    */
2374   for (begin = msg->begins;
2375        begin && begin->fragment->tsn > fragment->tsn;
2376        begin = begin->next);
2377
2378   /* in case begin still is null, set it to first (highest) begin
2379    * maybe the message tsn restart at 0 in between
2380    */
2381   if (!begin)
2382     begin = msg->begins;
2383
2384   for (end = msg->ends;
2385        end && end->fragment->tsn < fragment->tsn;
2386        end = end->next);
2387
2388   /* in case end still is null, set it to first (lowest) end
2389    * maybe the message tsn restart at 0 in between
2390    */
2391   if (!end)
2392     end = msg->ends;
2393
2394   if (!begin || !end || !msg->fragments ||
2395       (begin->fragment->tsn > end->fragment->tsn && msg->fragments->tsn)) {
2396     /* begin and end have not been collected, yet
2397      * or there might be a tsn restart but the first fragment hasn't a tsn of 0
2398      * just mark as fragment
2399      */
2400
2401     if (check_col(pinfo->cinfo, COL_INFO))
2402       col_append_str(pinfo->cinfo, COL_INFO, " (Message Fragment) ");
2403
2404     return NULL;
2405   }
2406
2407   /* we found possible begin and end
2408    * look for the first fragment and then try to get to the end
2409    */
2410   first_frag = begin->fragment;
2411
2412   /* while looking if all fragments are there
2413    * we can calculate the overall length that
2414    * we need in case of success
2415    */
2416   len = first_frag->len;
2417
2418   /* check if begin is past end
2419    * this can happen if there has been a tsn restart
2420    * or we just got the wrong begin and end
2421    * so give it a try
2422   */
2423   if (begin->fragment->tsn > end->fragment->tsn) {
2424     for (last_frag = first_frag, frag_i = first_frag->next;
2425          frag_i && frag_i->tsn == (last_frag->tsn + 1);
2426          last_frag = frag_i, frag_i = frag_i->next) len += frag_i->len;
2427
2428     /* check if we reached the last possible tsn
2429      * if yes, restart and continue
2430      */
2431     if ((last_frag->tsn + 1)) {
2432       /* there are just fragments missing */
2433       if (check_col(pinfo->cinfo, COL_INFO))
2434         col_append_str(pinfo->cinfo, COL_INFO, " (Message Fragment) ");
2435
2436       return NULL;
2437     }
2438
2439     /* we got all fragments until the last possible tsn
2440      * and the first is 0 if we got here
2441      */
2442
2443     len += msg->fragments->len;
2444     for (last_frag = msg->fragments, frag_i = last_frag->next;
2445          frag_i && frag_i->tsn < end->fragment->tsn && frag_i->tsn == (last_frag->tsn + 1);
2446          last_frag = frag_i, frag_i = frag_i->next) len += frag_i->len;
2447
2448   } else {
2449     for (last_frag = first_frag, frag_i = first_frag->next;
2450          frag_i && frag_i->tsn < end->fragment->tsn && frag_i->tsn == (last_frag->tsn + 1);
2451          last_frag = frag_i, frag_i = frag_i->next) len += frag_i->len;
2452   }
2453
2454   if (!frag_i || frag_i != end->fragment || frag_i->tsn != (last_frag->tsn + 1)) {
2455     /* we need more fragments. just mark as fragment */
2456     if (check_col(pinfo->cinfo, COL_INFO))
2457       col_append_str(pinfo->cinfo, COL_INFO, " (Message Fragment) ");
2458
2459     return NULL;
2460   }
2461
2462   /* ok, this message is complete, we can reassemble it
2463    * but at first don't forget to add the length of the last fragment
2464    */
2465   len += frag_i->len;
2466
2467   message = se_alloc (sizeof (sctp_complete_msg));
2468   message->begin = begin->fragment->tsn;
2469   message->end = end->fragment->tsn;
2470   message->reassembled_in = fragment;
2471   message->len = len;
2472   message->data = se_alloc(len);
2473   message->next = NULL;
2474
2475   /* now copy all fragments */
2476   if (begin->fragment->tsn > end->fragment->tsn) {
2477     /* a tsn restart has occured */
2478     for (frag_i = first_frag;
2479          frag_i;
2480          frag_i = frag_i->next) {
2481
2482       if (frag_i->len && frag_i->data)
2483         memcpy(message->data + offset, frag_i->data, frag_i->len);
2484       offset += frag_i->len;
2485
2486       /* release fragment data */
2487       g_free(frag_i->data);
2488       frag_i->data = NULL;
2489     }
2490
2491     for (frag_i = msg->fragments;
2492          frag_i && frag_i->tsn <= end->fragment->tsn;
2493          frag_i = frag_i->next) {
2494
2495       if (frag_i->len && frag_i->data)
2496         memcpy(message->data + offset, frag_i->data, frag_i->len);
2497       offset += frag_i->len;
2498
2499       /* release fragment data */
2500       g_free(frag_i->data);
2501       frag_i->data = NULL;
2502     }
2503
2504   } else {
2505     for (frag_i = first_frag;
2506          frag_i && frag_i->tsn <= end->fragment->tsn;
2507          frag_i = frag_i->next) {
2508
2509       if (frag_i->len && frag_i->data)
2510         memcpy(message->data + offset, frag_i->data, frag_i->len);
2511       offset += frag_i->len;
2512
2513       /* release fragment data */
2514       g_free(frag_i->data);
2515       frag_i->data = NULL;
2516     }
2517   }
2518
2519   /* save message */
2520   if (!msg->messages) {
2521     msg->messages = message;
2522   } else {
2523     for (last_message = msg->messages;
2524          last_message->next;
2525          last_message = last_message->next);
2526
2527          last_message->next = message;
2528   }
2529
2530   /* remove begin and end from list */
2531   if (msg->begins == begin) {
2532     msg->begins = begin->next;
2533   } else {
2534     for (beginend = msg->begins;
2535          beginend && beginend->next != begin;
2536          beginend = beginend->next);
2537     if (beginend && beginend->next == begin)
2538       beginend->next = begin->next;
2539   }
2540   g_free(begin);
2541
2542   if (msg->ends == end) {
2543     msg->ends = end->next;
2544   } else {
2545     for (beginend = msg->ends;
2546          beginend && beginend->next != end;
2547          beginend = beginend->next);
2548     if (beginend && beginend->next == end)
2549       beginend->next = end->next;
2550   }
2551    g_free(end);
2552
2553   /* create data source */
2554   new_tvb = tvb_new_child_real_data(tvb, message->data, len, len);
2555   add_new_data_source(pinfo, new_tvb, "Reassembled SCTP Message");
2556
2557   /* display reassembly info */
2558   item = proto_tree_add_item(tree, hf_sctp_fragments, tvb, 0, -1, FALSE);
2559   ptree = proto_item_add_subtree(item, ett_sctp_fragments);
2560   proto_item_append_text(item, " (%u bytes, %u fragments): ",
2561                          message->len, message->end - message->begin + 1);
2562
2563   if (message->begin > message->end) {
2564     for (frag_i = find_fragment(message->begin, stream_id, stream_seq_num);
2565          frag_i;
2566          frag_i = frag_i->next) {
2567
2568       proto_tree_add_uint_format(ptree, hf_sctp_fragment, new_tvb, offset, frag_i->len,
2569                                  frag_i->frame_num, "Frame: %u, payload: %u-%u (%u bytes)",
2570                                  frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
2571       offset += frag_i->len;
2572     }
2573
2574     for (frag_i = msg->fragments;
2575          frag_i && frag_i->tsn <= message->end;
2576          frag_i = frag_i->next) {
2577
2578       proto_tree_add_uint_format(ptree, hf_sctp_fragment, new_tvb, offset, frag_i->len,
2579                                  frag_i->frame_num, "Frame: %u, payload: %u-%u (%u bytes)",
2580                                  frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
2581       offset += frag_i->len;
2582     }
2583   } else {
2584     for (frag_i = find_fragment(message->begin, stream_id, stream_seq_num);
2585          frag_i && frag_i->tsn <= message->end;
2586          frag_i = frag_i->next) {
2587
2588       proto_tree_add_uint_format(ptree, hf_sctp_fragment, new_tvb, offset, frag_i->len,
2589                                  frag_i->frame_num, "Frame: %u, payload: %u-%u (%u bytes)",
2590                                  frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
2591       offset += frag_i->len;
2592     }
2593   }
2594
2595   /* it's not fragmented anymore */
2596   pinfo->fragmented = FALSE;
2597
2598   return new_tvb;
2599 }
2600
2601
2602 static gboolean
2603 dissect_fragmented_payload(tvbuff_t *payload_tvb, packet_info *pinfo, proto_tree *tree,
2604                            proto_tree *chunk_tree, guint32 tsn, guint32 ppi, guint16 stream_id,
2605                            guint16 stream_seq_num, guint8 b_bit, guint8 e_bit)
2606 {
2607   sctp_fragment* fragment;
2608   tvbuff_t* new_tvb = NULL;
2609
2610   /* add fragement to list of known fragments. returns NULL if segment is a duplicate */
2611   fragment = add_fragment(payload_tvb, pinfo, chunk_tree, tsn, stream_id, stream_seq_num, b_bit, e_bit);
2612
2613   if (fragment)
2614     new_tvb = fragment_reassembly(payload_tvb, fragment, pinfo, chunk_tree, stream_id, stream_seq_num);
2615
2616   /* pass reassembled data to next dissector, if possible */
2617   if (new_tvb)
2618     return dissect_payload(new_tvb, pinfo, tree, ppi);
2619
2620   /* no reassembly done, do nothing */
2621   return TRUE;
2622 }
2623
2624 static const true_false_string sctp_data_chunk_e_bit_value = {
2625   "Last segment",
2626   "Not the last segment"
2627 };
2628
2629 static const true_false_string sctp_data_chunk_b_bit_value = {
2630   "First segment",
2631   "Subsequent segment"
2632 };
2633
2634 static const true_false_string sctp_data_chunk_u_bit_value = {
2635   "Unordered delivery",
2636   "Ordered delivery"
2637 };
2638
2639 static const true_false_string sctp_data_chunk_i_bit_value = {
2640   "Send SACK immediately",
2641   "Possibly delay SACK"
2642 };
2643
2644 static gboolean
2645 dissect_data_chunk(tvbuff_t *chunk_tvb,
2646                                    guint16 chunk_length,
2647                                    packet_info *pinfo,
2648                                    proto_tree *tree,
2649                                    proto_tree *chunk_tree,
2650                                    proto_item *chunk_item,
2651                                    proto_item *flags_item,
2652                                    sctp_half_assoc_t* ha)
2653 {
2654   guint number_of_ppid;
2655   guint32 payload_proto_id;
2656   tvbuff_t *payload_tvb;
2657   proto_tree *flags_tree;
2658   guint8 e_bit, b_bit, u_bit;
2659   guint16 stream_id, stream_seq_num = 0;
2660   guint32 tsn;
2661   proto_item* tsn_item = NULL;
2662
2663   if (chunk_length <= DATA_CHUNK_HEADER_LENGTH) {
2664     proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
2665                            chunk_length, DATA_CHUNK_HEADER_LENGTH);
2666     return TRUE;
2667   }
2668   payload_proto_id  = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET);
2669
2670   /* insert the PPID in the pinfo structure if it is non-zero, not already there and there is still room */
2671   if (payload_proto_id) {
2672     for(number_of_ppid = 0; number_of_ppid < MAX_NUMBER_OF_PPIDS; number_of_ppid++)
2673       if ((pinfo->ppids[number_of_ppid] == 0) || (pinfo->ppids[number_of_ppid] == payload_proto_id))
2674         break;
2675     if ((number_of_ppid < MAX_NUMBER_OF_PPIDS) && (pinfo->ppids[number_of_ppid] == 0))
2676       pinfo->ppids[number_of_ppid] = payload_proto_id;
2677   }
2678
2679   e_bit = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_DATA_CHUNK_E_BIT;
2680   b_bit = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_DATA_CHUNK_B_BIT;
2681   u_bit = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_DATA_CHUNK_U_BIT;
2682   stream_id = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET);
2683   stream_seq_num = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET);
2684   tsn = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_TSN_OFFSET);
2685
2686   if (chunk_tree) {
2687     proto_item_set_len(chunk_item, DATA_CHUNK_HEADER_LENGTH);
2688     flags_tree  = proto_item_add_subtree(flags_item, ett_sctp_data_chunk_flags);
2689     proto_tree_add_item(flags_tree, hf_data_chunk_e_bit,             chunk_tvb, CHUNK_FLAGS_OFFSET,                    CHUNK_FLAGS_LENGTH,                    NETWORK_BYTE_ORDER);
2690     proto_tree_add_item(flags_tree, hf_data_chunk_b_bit,             chunk_tvb, CHUNK_FLAGS_OFFSET,                    CHUNK_FLAGS_LENGTH,                    NETWORK_BYTE_ORDER);
2691     proto_tree_add_item(flags_tree, hf_data_chunk_u_bit,             chunk_tvb, CHUNK_FLAGS_OFFSET,                    CHUNK_FLAGS_LENGTH,                    NETWORK_BYTE_ORDER);
2692     proto_tree_add_item(flags_tree, hf_data_chunk_i_bit,             chunk_tvb, CHUNK_FLAGS_OFFSET,                    CHUNK_FLAGS_LENGTH,                    NETWORK_BYTE_ORDER);
2693     tsn_item = proto_tree_add_item(chunk_tree, hf_data_chunk_tsn,    chunk_tvb, DATA_CHUNK_TSN_OFFSET,                 DATA_CHUNK_TSN_LENGTH,                 NETWORK_BYTE_ORDER);
2694     proto_tree_add_item(chunk_tree, hf_data_chunk_stream_id,         chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET,           DATA_CHUNK_STREAM_ID_LENGTH,           NETWORK_BYTE_ORDER);
2695     proto_tree_add_item(chunk_tree, hf_data_chunk_stream_seq_number, chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET,   DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH,   NETWORK_BYTE_ORDER);
2696     proto_tree_add_item(chunk_tree, hf_data_chunk_payload_proto_id,  chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH, NETWORK_BYTE_ORDER);
2697
2698     proto_item_append_text(chunk_item, "(%s, ", (u_bit) ? "unordered" : "ordered");
2699     if (b_bit) {
2700       if (e_bit)
2701         proto_item_append_text(chunk_item, "complete");
2702       else
2703         proto_item_append_text(chunk_item, "first");
2704     } else {
2705       if (e_bit)
2706         proto_item_append_text(chunk_item, "last");
2707       else
2708         proto_item_append_text(chunk_item, "middle");
2709     }
2710
2711     proto_item_append_text(chunk_item, " segment, TSN: %u, SID: %u, SSN: %u, PPID: %u, payload length: %u byte%s)",
2712                            tvb_get_ntohl(chunk_tvb, DATA_CHUNK_TSN_OFFSET),
2713                            tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET),
2714                            tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET),
2715                            payload_proto_id,
2716                            chunk_length - DATA_CHUNK_HEADER_LENGTH, plurality(chunk_length - DATA_CHUNK_HEADER_LENGTH, "", "s"));
2717   }
2718
2719   sctp_tsn(pinfo,  chunk_tvb, tsn_item, ha, tsn);
2720
2721
2722   payload_tvb = tvb_new_subset(chunk_tvb, DATA_CHUNK_PAYLOAD_OFFSET, chunk_length - DATA_CHUNK_HEADER_LENGTH, chunk_length - DATA_CHUNK_HEADER_LENGTH);
2723
2724   /* Is this a fragment? */
2725   if (b_bit && e_bit) {
2726     /* No - just call the subdissector. */
2727     return dissect_payload(payload_tvb, pinfo, tree, payload_proto_id);
2728   } else {
2729     /* Yes. */
2730     pinfo->fragmented = TRUE;
2731
2732     /* if reassembly is off just mark as fragment for next dissector and proceed */
2733     if (!use_reassembly)
2734     {
2735       /*  Don't pass on non-first fragments since the next dissector will
2736        *  almost certainly not understand the data.
2737        */
2738       if (b_bit)
2739       {
2740         volatile gboolean retval = FALSE;
2741
2742         /*
2743          * If this particular fragment happens to get a ReportedBoundsError
2744          * exception (which in fact we expect it to since it's a fragment),
2745          * don't stop dissecting chunks within this frame.
2746          *
2747          * If it gets a BoundsError, we can stop, as there's nothing more to
2748          * see, so we just re-throw it.
2749          */
2750         TRY {
2751           retval = dissect_payload(payload_tvb, pinfo, tree, payload_proto_id);
2752         }
2753         CATCH(BoundsError) {
2754           RETHROW;
2755         }
2756         CATCH(ReportedBoundsError) {
2757           show_reported_bounds_error(payload_tvb, pinfo, tree);
2758         }
2759         ENDTRY;
2760
2761         return retval;
2762       }
2763
2764       /* else */
2765       return FALSE;
2766     }
2767
2768     /* if unordered set stream_seq_num to 0 for easier handling */
2769     if (u_bit)
2770       stream_seq_num = 0;
2771
2772     /* start reassembly */
2773     return dissect_fragmented_payload(payload_tvb, pinfo, tree, chunk_tree, tsn, payload_proto_id, stream_id, stream_seq_num, b_bit, e_bit);
2774   }
2775 }
2776
2777 #define INIT_CHUNK_INITIATE_TAG_LENGTH               4
2778 #define INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH      4
2779 #define INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH 2
2780 #define INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH  2
2781 #define INIT_CHUNK_INITIAL_TSN_LENGTH                4
2782 #define INIT_CHUNK_FIXED_PARAMTERS_LENGTH            (CHUNK_HEADER_LENGTH + \
2783                                                       INIT_CHUNK_INITIATE_TAG_LENGTH + \
2784                                                       INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH + \
2785                                                       INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH + \
2786                                                       INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH + \
2787                                                       INIT_CHUNK_INITIAL_TSN_LENGTH)
2788
2789 #define INIT_CHUNK_INITIATE_TAG_OFFSET               CHUNK_VALUE_OFFSET
2790 #define INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET      (INIT_CHUNK_INITIATE_TAG_OFFSET + \
2791                                                       INIT_CHUNK_INITIATE_TAG_LENGTH )
2792 #define INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET (INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET + \
2793                                                       INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH )
2794 #define INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET  (INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET + \
2795                                                       INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH )
2796 #define INIT_CHUNK_INITIAL_TSN_OFFSET                (INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET + \
2797                                                       INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH )
2798 #define INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET  (INIT_CHUNK_INITIAL_TSN_OFFSET + \
2799                                                       INIT_CHUNK_INITIAL_TSN_LENGTH )
2800
2801 static void
2802 dissect_init_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
2803 {
2804   tvbuff_t *parameters_tvb;
2805   proto_item *hidden_item;
2806
2807   if (chunk_length < INIT_CHUNK_FIXED_PARAMTERS_LENGTH) {
2808     proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
2809                            chunk_length,
2810                            INIT_CHUNK_FIXED_PARAMTERS_LENGTH);
2811     return;
2812   }
2813   if (chunk_tree) {
2814     /* handle fixed parameters */
2815     proto_tree_add_item(chunk_tree, hf_init_chunk_initiate_tag,               chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET,               INIT_CHUNK_INITIATE_TAG_LENGTH,               NETWORK_BYTE_ORDER);
2816     hidden_item = proto_tree_add_item(chunk_tree, hf_initiate_tag,                   chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET,               INIT_CHUNK_INITIATE_TAG_LENGTH,               NETWORK_BYTE_ORDER);
2817         PROTO_ITEM_SET_HIDDEN(hidden_item);
2818     proto_tree_add_item(chunk_tree, hf_init_chunk_adv_rec_window_credit,      chunk_tvb, INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET,      INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH,      NETWORK_BYTE_ORDER);
2819     proto_tree_add_item(chunk_tree, hf_init_chunk_number_of_outbound_streams, chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH, NETWORK_BYTE_ORDER);
2820     proto_tree_add_item(chunk_tree, hf_init_chunk_number_of_inbound_streams,  chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET,  INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH,  NETWORK_BYTE_ORDER);
2821     proto_tree_add_item(chunk_tree, hf_init_chunk_initial_tsn,                chunk_tvb, INIT_CHUNK_INITIAL_TSN_OFFSET,                INIT_CHUNK_INITIAL_TSN_LENGTH,                NETWORK_BYTE_ORDER);
2822
2823     proto_item_append_text(chunk_item, " (Outbound streams: %u, inbound streams: %u)",
2824                            tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET),
2825                            tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET));
2826   }
2827   /* handle variable parameters */
2828   chunk_length -= INIT_CHUNK_FIXED_PARAMTERS_LENGTH;
2829   parameters_tvb = tvb_new_subset(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET, chunk_length, chunk_length);
2830   dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, TRUE);
2831 }
2832
2833 static void
2834 dissect_init_ack_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
2835 {
2836   tvbuff_t *parameters_tvb;
2837   proto_item *hidden_item;
2838
2839   if (chunk_length < INIT_CHUNK_FIXED_PARAMTERS_LENGTH) {
2840     proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
2841                            chunk_length,
2842                            INIT_CHUNK_FIXED_PARAMTERS_LENGTH);
2843     return;
2844   }
2845   if (chunk_tree) {
2846     /* handle fixed parameters */
2847     proto_tree_add_item(chunk_tree, hf_initack_chunk_initiate_tag,               chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET,               INIT_CHUNK_INITIATE_TAG_LENGTH,               NETWORK_BYTE_ORDER);
2848     hidden_item = proto_tree_add_item(chunk_tree, hf_initiate_tag,                      chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET,               INIT_CHUNK_INITIATE_TAG_LENGTH,               NETWORK_BYTE_ORDER);
2849         PROTO_ITEM_SET_HIDDEN(hidden_item);
2850     proto_tree_add_item(chunk_tree, hf_initack_chunk_adv_rec_window_credit,      chunk_tvb, INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET,      INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH,      NETWORK_BYTE_ORDER);
2851     proto_tree_add_item(chunk_tree, hf_initack_chunk_number_of_outbound_streams, chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH, NETWORK_BYTE_ORDER);
2852     proto_tree_add_item(chunk_tree, hf_initack_chunk_number_of_inbound_streams,  chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET,  INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH,  NETWORK_BYTE_ORDER);
2853     proto_tree_add_item(chunk_tree, hf_initack_chunk_initial_tsn,                chunk_tvb, INIT_CHUNK_INITIAL_TSN_OFFSET,                INIT_CHUNK_INITIAL_TSN_LENGTH,                NETWORK_BYTE_ORDER);
2854
2855     proto_item_append_text(chunk_item, " (Outbound streams: %u, inbound streams: %u)",
2856                            tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET),
2857                            tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET));
2858   }
2859   /* handle variable paramters */
2860   chunk_length -= INIT_CHUNK_FIXED_PARAMTERS_LENGTH;
2861   parameters_tvb = tvb_new_subset(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET, chunk_length, chunk_length);
2862   dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, TRUE);
2863 }
2864
2865 #define SCTP_SACK_CHUNK_NS_BIT                  0x01
2866 #define SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH    4
2867 #define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH 4
2868 #define SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH  2
2869 #define SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH    2
2870 #define SACK_CHUNK_GAP_BLOCK_LENGTH             4
2871 #define SACK_CHUNK_GAP_BLOCK_START_LENGTH       2
2872 #define SACK_CHUNK_GAP_BLOCK_END_LENGTH         2
2873 #define SACK_CHUNK_DUP_TSN_LENGTH               4
2874
2875 #define SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET (CHUNK_VALUE_OFFSET + 0)
2876 #define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET (SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET + \
2877                                                  SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH)
2878 #define SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET (SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET + \
2879                                                 SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH)
2880 #define SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET (SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET + \
2881                                               SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH)
2882 #define SACK_CHUNK_GAP_BLOCK_OFFSET (SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET + \
2883                                      SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH)
2884
2885
2886 static void
2887 dissect_sack_chunk(packet_info* pinfo, tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item, sctp_half_assoc_t* ha)
2888 {
2889   guint16 number_of_gap_blocks, number_of_dup_tsns;
2890   guint16 gap_block_number, dup_tsn_number, start, end;
2891   gint gap_block_offset, dup_tsn_offset;
2892   guint32 cum_tsn_ack;
2893   proto_item *block_item;
2894   proto_tree *block_tree;
2895   proto_tree *flags_tree;
2896   proto_item *ctsa_item;
2897   proto_item *a_rwnd_item;
2898   proto_tree *acks_tree;
2899   guint32 tsns_gap_acked = 0;
2900   guint32 a_rwnd;
2901
2902   flags_tree  = proto_item_add_subtree(flags_item, ett_sctp_sack_chunk_flags);
2903   proto_tree_add_item(flags_tree, hf_sack_chunk_ns,                    chunk_tvb, CHUNK_FLAGS_OFFSET,                      CHUNK_FLAGS_LENGTH,                      NETWORK_BYTE_ORDER);
2904   ctsa_item = proto_tree_add_item(chunk_tree, hf_sack_chunk_cumulative_tsn_ack,    chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET,    SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH,    NETWORK_BYTE_ORDER);
2905   a_rwnd_item = proto_tree_add_item(chunk_tree, hf_sack_chunk_adv_rec_window_credit, chunk_tvb, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH, NETWORK_BYTE_ORDER);
2906   proto_tree_add_item(chunk_tree, hf_sack_chunk_number_of_gap_blocks,  chunk_tvb, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET,  SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH,  NETWORK_BYTE_ORDER);
2907   proto_tree_add_item(chunk_tree, hf_sack_chunk_number_of_dup_tsns,    chunk_tvb, SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET,    SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH,    NETWORK_BYTE_ORDER);
2908
2909   a_rwnd = tvb_get_ntohl(chunk_tvb, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET);
2910   if (a_rwnd == 0)
2911       expert_add_info_format(pinfo, a_rwnd_item, PI_SEQUENCE, PI_NOTE, "Zero Advertised Receiver Window Credit");
2912
2913
2914   /* handle the gap acknowledgement blocks */
2915   number_of_gap_blocks = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET);
2916   gap_block_offset     = SACK_CHUNK_GAP_BLOCK_OFFSET;
2917   cum_tsn_ack          = tvb_get_ntohl(chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
2918
2919   acks_tree = proto_item_add_subtree(ctsa_item,ett_sctp_ack);
2920   sctp_ack_block(pinfo, ha, chunk_tvb, acks_tree, NULL, cum_tsn_ack);
2921
2922   for(gap_block_number = 1; gap_block_number <= number_of_gap_blocks; gap_block_number++) {
2923     proto_item *pi;
2924     proto_tree *pt;
2925     guint32 tsn_start;
2926
2927     start = tvb_get_ntohs(chunk_tvb, gap_block_offset);
2928     end   = tvb_get_ntohs(chunk_tvb, gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH);
2929     tsn_start = cum_tsn_ack + start;
2930
2931     block_item = proto_tree_add_text(chunk_tree, chunk_tvb, gap_block_offset, SACK_CHUNK_GAP_BLOCK_LENGTH, "Gap Acknowledgement for TSN %u to %u", cum_tsn_ack + start, cum_tsn_ack + end);
2932     block_tree = proto_item_add_subtree(block_item, ett_sctp_sack_chunk_gap_block);
2933
2934     pi = proto_tree_add_item(block_tree, hf_sack_chunk_gap_block_start, chunk_tvb, gap_block_offset, SACK_CHUNK_GAP_BLOCK_START_LENGTH, NETWORK_BYTE_ORDER);
2935     pt = proto_item_add_subtree(pi, ett_sctp_sack_chunk_gap_block_start);
2936     pi = proto_tree_add_uint(pt, hf_sack_chunk_gap_block_start_tsn,
2937                              chunk_tvb, gap_block_offset,SACK_CHUNK_GAP_BLOCK_START_LENGTH, cum_tsn_ack + start);
2938     PROTO_ITEM_SET_GENERATED(pi);
2939
2940     pi = proto_tree_add_item(block_tree, hf_sack_chunk_gap_block_end, chunk_tvb, gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH, SACK_CHUNK_GAP_BLOCK_END_LENGTH,   NETWORK_BYTE_ORDER);
2941     pt = proto_item_add_subtree(pi, ett_sctp_sack_chunk_gap_block_end);
2942     pi = proto_tree_add_uint(pt, hf_sack_chunk_gap_block_end_tsn, chunk_tvb,
2943                              gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH, SACK_CHUNK_GAP_BLOCK_END_LENGTH, cum_tsn_ack + end);
2944     PROTO_ITEM_SET_GENERATED(pi);
2945
2946     sctp_ack_block(pinfo, ha, chunk_tvb, block_tree, &tsn_start, cum_tsn_ack + end);
2947     gap_block_offset += SACK_CHUNK_GAP_BLOCK_LENGTH;
2948
2949     tsns_gap_acked += (end+1 - start);
2950   }
2951
2952   if (tsns_gap_acked) {
2953     proto_item *pi;
2954
2955     pi = proto_tree_add_uint(chunk_tree, hf_sack_chunk_number_tsns_gap_acked, chunk_tvb, 0, 0, tsns_gap_acked);
2956     PROTO_ITEM_SET_GENERATED(pi);
2957
2958     /*  If there are a huge number of GAP ACKs, warn the user.  100 is a random
2959      *  number: it could be tuned.
2960      */
2961     if (tsns_gap_acked > 100)
2962       expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_WARN, "More than 100 TSNs were gap-acknowledged in this SACK");
2963
2964   }
2965
2966
2967   /* handle the duplicate TSNs */
2968   number_of_dup_tsns = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET);
2969   dup_tsn_offset     = SACK_CHUNK_GAP_BLOCK_OFFSET + number_of_gap_blocks * SACK_CHUNK_GAP_BLOCK_LENGTH;
2970   for(dup_tsn_number = 1; dup_tsn_number <= number_of_dup_tsns; dup_tsn_number++) {
2971     proto_tree_add_item(chunk_tree, hf_sack_chunk_duplicate_tsn, chunk_tvb, dup_tsn_offset, SACK_CHUNK_DUP_TSN_LENGTH, NETWORK_BYTE_ORDER);
2972     dup_tsn_offset += SACK_CHUNK_DUP_TSN_LENGTH;
2973   }
2974
2975   proto_item_append_text(chunk_item, " (Cumulative TSN: %u, a_rwnd: %u, gaps: %u, duplicate TSNs: %u)",
2976                          tvb_get_ntohl(chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET),
2977                          a_rwnd,
2978                          number_of_gap_blocks, number_of_dup_tsns);
2979 }
2980
2981 /* NE: Dissect nr-sack chunk */
2982 #define SCTP_NR_SACK_CHUNK_NS_BIT                  0x01
2983 #define NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH       4
2984 #define NR_SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH    4
2985 #define NR_SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH     2
2986 #define NR_SACK_CHUNK_NUMBER_OF_NR_GAP_BLOCKS_LENGTH  2
2987 #define NR_SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH       2
2988 #define NR_SACK_CHUNK_RESERVED_LENGTH                 2
2989 #define NR_SACK_CHUNK_GAP_BLOCK_LENGTH                4
2990 #define NR_SACK_CHUNK_GAP_BLOCK_START_LENGTH          2
2991 #define NR_SACK_CHUNK_GAP_BLOCK_END_LENGTH            2
2992 #define NR_SACK_CHUNK_NR_GAP_BLOCK_LENGTH             4
2993 #define NR_SACK_CHUNK_NR_GAP_BLOCK_START_LENGTH       2
2994 #define NR_SACK_CHUNK_NR_GAP_BLOCK_END_LENGTH         2
2995 #define NR_SACK_CHUNK_DUP_TSN_LENGTH                  4
2996
2997 #define NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET        (CHUNK_VALUE_OFFSET + 0)
2998 #define NR_SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET     (NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET + \
2999                                                         NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH)
3000 #define NR_SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET      (NR_SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET + \
3001                                                         NR_SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH)
3002 #define NR_SACK_CHUNK_NUMBER_OF_NR_GAP_BLOCKS_OFFSET   (NR_SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET + \
3003                                                         NR_SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH)
3004 #define NR_SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET        (NR_SACK_CHUNK_NUMBER_OF_NR_GAP_BLOCKS_OFFSET + \
3005                                                         NR_SACK_CHUNK_NUMBER_OF_NR_GAP_BLOCKS_LENGTH)
3006 #define NR_SACK_CHUNK_RESERVED_OFFSET                  (NR_SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET + \
3007                                                         NR_SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH)  
3008 #define NR_SACK_CHUNK_GAP_BLOCK_OFFSET                 (NR_SACK_CHUNK_RESERVED_OFFSET + \
3009                                                         NR_SACK_CHUNK_RESERVED_LENGTH)
3010
3011 static void
3012 dissect_nr_sack_chunk(packet_info* pinfo, tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item, sctp_half_assoc_t* ha)
3013 {
3014   guint16 number_of_gap_blocks, number_of_dup_tsns;
3015   guint16 number_of_nr_gap_blocks;
3016   guint16 gap_block_number, nr_gap_block_number, dup_tsn_number, start, end;
3017   gint gap_block_offset, nr_gap_block_offset, dup_tsn_offset;
3018   guint32 cum_tsn_ack;
3019   proto_item *block_item;
3020   proto_tree *block_tree;
3021   proto_tree *flags_tree;
3022   proto_item *ctsa_item;
3023   proto_item *num_of_gap_blocks;
3024   proto_tree *acks_tree;
3025   guint32 tsns_gap_acked = 0;
3026   guint32 tsns_nr_gap_acked = 0;
3027
3028   flags_tree  = proto_item_add_subtree(flags_item, ett_sctp_nr_sack_chunk_flags);
3029   proto_tree_add_item(flags_tree, hf_nr_sack_chunk_ns, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
3030
3031   ctsa_item = proto_tree_add_item(chunk_tree, hf_nr_sack_chunk_cumulative_tsn_ack, chunk_tvb, NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET, NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH, NETWORK_BYTE_ORDER);
3032   proto_tree_add_item(chunk_tree, hf_nr_sack_chunk_adv_rec_window_credit, chunk_tvb, NR_SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET, NR_SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH, NETWORK_BYTE_ORDER);
3033   
3034   num_of_gap_blocks = proto_tree_add_item(chunk_tree, hf_nr_sack_chunk_number_of_gap_blocks, chunk_tvb, NR_SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET,  NR_SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH, NETWORK_BYTE_ORDER);
3035   
3036   proto_tree_add_item(chunk_tree, hf_nr_sack_chunk_number_of_nr_gap_blocks,  chunk_tvb, NR_SACK_CHUNK_NUMBER_OF_NR_GAP_BLOCKS_OFFSET, NR_SACK_CHUNK_NUMBER_OF_NR_GAP_BLOCKS_LENGTH, NETWORK_BYTE_ORDER);
3037   proto_tree_add_item(chunk_tree, hf_nr_sack_chunk_number_of_dup_tsns, chunk_tvb, NR_SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET, NR_SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH, NETWORK_BYTE_ORDER);
3038   proto_tree_add_item(chunk_tree, hf_nr_sack_chunk_reserved, chunk_tvb, NR_SACK_CHUNK_RESERVED_OFFSET, NR_SACK_CHUNK_RESERVED_LENGTH, NETWORK_BYTE_ORDER);
3039
3040
3041   number_of_gap_blocks = tvb_get_ntohs(chunk_tvb, NR_SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET);
3042   gap_block_offset     = NR_SACK_CHUNK_GAP_BLOCK_OFFSET;
3043   cum_tsn_ack          = tvb_get_ntohl(chunk_tvb, NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
3044
3045   acks_tree = proto_item_add_subtree(ctsa_item,ett_sctp_ack);
3046   sctp_ack_block(pinfo, ha, chunk_tvb, acks_tree, NULL, cum_tsn_ack);
3047   
3048   for(gap_block_number = 1; gap_block_number <= number_of_gap_blocks; gap_block_number++) {
3049     proto_item *pi;
3050     proto_tree *pt;
3051     guint32 tsn_start;
3052     
3053     start = tvb_get_ntohs(chunk_tvb, gap_block_offset);
3054     end   = tvb_get_ntohs(chunk_tvb, gap_block_offset + NR_SACK_CHUNK_GAP_BLOCK_START_LENGTH);
3055     tsn_start = cum_tsn_ack + start;
3056     
3057     block_item = proto_tree_add_text(chunk_tree, chunk_tvb, gap_block_offset, NR_SACK_CHUNK_GAP_BLOCK_LENGTH, "Gap Acknowledgement for TSN %u to %u", cum_tsn_ack + start, cum_tsn_ack + end);
3058     block_tree = proto_item_add_subtree(block_item, ett_sctp_nr_sack_chunk_gap_block);
3059       
3060     pi = proto_tree_add_item(block_tree, hf_nr_sack_chunk_gap_block_start, chunk_tvb, gap_block_offset, NR_SACK_CHUNK_GAP_BLOCK_START_LENGTH, NETWORK_BYTE_ORDER);
3061     pt = proto_item_add_subtree(pi, ett_sctp_nr_sack_chunk_gap_block_start);
3062     pi = proto_tree_add_uint(pt, hf_nr_sack_chunk_gap_block_start_tsn,
3063                              chunk_tvb, gap_block_offset,NR_SACK_CHUNK_GAP_BLOCK_START_LENGTH, cum_tsn_ack + start);
3064     PROTO_ITEM_SET_GENERATED(pi);
3065
3066     pi = proto_tree_add_item(block_tree, hf_nr_sack_chunk_gap_block_end, chunk_tvb, gap_block_offset + NR_SACK_CHUNK_GAP_BLOCK_START_LENGTH, NR_SACK_CHUNK_GAP_BLOCK_END_LENGTH,   NETWORK_BYTE_ORDER);
3067     pt = proto_item_add_subtree(pi, ett_sctp_nr_sack_chunk_gap_block_end);
3068     pi = proto_tree_add_uint(pt, hf_nr_sack_chunk_gap_block_end_tsn, chunk_tvb,
3069                                gap_block_offset + NR_SACK_CHUNK_GAP_BLOCK_START_LENGTH, NR_SACK_CHUNK_GAP_BLOCK_END_LENGTH, cum_tsn_ack + end);
3070     PROTO_ITEM_SET_GENERATED(pi);
3071       
3072     sctp_ack_block(pinfo, ha, chunk_tvb, block_tree, &tsn_start, cum_tsn_ack + end);
3073     gap_block_offset += NR_SACK_CHUNK_GAP_BLOCK_LENGTH;
3074     tsns_gap_acked += (end - start) + 1;
3075   }
3076
3077   if (tsns_gap_acked) {
3078     proto_item *pi;
3079       
3080     pi = proto_tree_add_uint(chunk_tree, hf_nr_sack_chunk_number_tsns_gap_acked, chunk_tvb, 0, 0, tsns_gap_acked);
3081     PROTO_ITEM_SET_GENERATED(pi);
3082
3083     /*  If there are a huge number of GAP ACKs, warn the user.  100 is a random
3084      *  number: it could be tuned.
3085      */
3086     if (tsns_gap_acked > 100)
3087       expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_WARN, "More than 100 TSNs were gap-acknowledged in this NR-SACK");
3088     
3089   }
3090
3091   /* NE: handle the nr-sack chunk's nr-gap blocks */
3092   number_of_nr_gap_blocks = tvb_get_ntohs(chunk_tvb, NR_SACK_CHUNK_NUMBER_OF_NR_GAP_BLOCKS_OFFSET);
3093   nr_gap_block_offset     = gap_block_offset;
3094
3095   for(nr_gap_block_number = 1; nr_gap_block_number <= number_of_nr_gap_blocks; nr_gap_block_number++) {
3096     proto_item *pi;
3097     proto_tree *pt;
3098     guint32 tsn_start;
3099
3100     start = tvb_get_ntohs(chunk_tvb, nr_gap_block_offset);
3101     end   = tvb_get_ntohs(chunk_tvb, nr_gap_block_offset + NR_SACK_CHUNK_NR_GAP_BLOCK_START_LENGTH);
3102     tsn_start = cum_tsn_ack + start;
3103
3104     block_item = proto_tree_add_text(chunk_tree, chunk_tvb, nr_gap_block_offset, NR_SACK_CHUNK_NR_GAP_BLOCK_LENGTH, "NR-Gap Acknowledgement for TSN %u to %u", cum_tsn_ack + start, cum_tsn_ack + end);
3105     block_tree = proto_item_add_subtree(block_item, ett_sctp_nr_sack_chunk_nr_gap_block);
3106
3107     pi = proto_tree_add_item(block_tree, hf_nr_sack_chunk_nr_gap_block_start, chunk_tvb, nr_gap_block_offset, NR_SACK_CHUNK_NR_GAP_BLOCK_START_LENGTH, NETWORK_BYTE_ORDER);
3108     pt = proto_item_add_subtree(pi, ett_sctp_nr_sack_chunk_nr_gap_block_start);
3109     pi = proto_tree_add_uint(pt, hf_nr_sack_chunk_nr_gap_block_start_tsn,
3110                              chunk_tvb, nr_gap_block_offset, NR_SACK_CHUNK_NR_GAP_BLOCK_START_LENGTH, cum_tsn_ack + start);
3111     PROTO_ITEM_SET_GENERATED(pi);
3112
3113     pi = proto_tree_add_item(block_tree, hf_nr_sack_chunk_nr_gap_block_end, chunk_tvb, nr_gap_block_offset + NR_SACK_CHUNK_NR_GAP_BLOCK_START_LENGTH, NR_SACK_CHUNK_NR_GAP_BLOCK_END_LENGTH,   NETWORK_BYTE_ORDER);
3114     pt = proto_item_add_subtree(pi, ett_sctp_nr_sack_chunk_nr_gap_block_end);
3115     pi = proto_tree_add_uint(pt, hf_nr_sack_chunk_nr_gap_block_end_tsn, chunk_tvb,
3116                              nr_gap_block_offset + NR_SACK_CHUNK_NR_GAP_BLOCK_START_LENGTH, NR_SACK_CHUNK_NR_GAP_BLOCK_END_LENGTH, cum_tsn_ack + end);
3117     PROTO_ITEM_SET_GENERATED(pi);
3118
3119     /* sctp_ack_block(pinfo, ha, chunk_tvb, block_tree, &tsn_start, cum_tsn_ack + end); */
3120     nr_gap_block_offset += NR_SACK_CHUNK_NR_GAP_BLOCK_LENGTH;
3121     tsns_nr_gap_acked += (end - start) + 1; 
3122   }
3123
3124   if (tsns_nr_gap_acked) {
3125     proto_item *pi;
3126
3127     pi = proto_tree_add_uint(chunk_tree, hf_nr_sack_chunk_number_tsns_nr_gap_acked, chunk_tvb, 0, 0, tsns_nr_gap_acked);
3128     PROTO_ITEM_SET_GENERATED(pi);
3129
3130     /*  If there are a huge number of GAP ACKs, warn the user.  100 is a random
3131      *  number: it could be tuned.
3132      */
3133     if (tsns_nr_gap_acked > 100)
3134       expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_WARN, "More than 100 TSNs were nr-gap-acknowledged in this NR-SACK");
3135   }
3136
3137   /* handle the duplicate TSNs */
3138   number_of_dup_tsns = tvb_get_ntohs(chunk_tvb, NR_SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET);
3139   dup_tsn_offset     = NR_SACK_CHUNK_GAP_BLOCK_OFFSET + number_of_gap_blocks * NR_SACK_CHUNK_GAP_BLOCK_LENGTH 
3140     + number_of_nr_gap_blocks * NR_SACK_CHUNK_NR_GAP_BLOCK_LENGTH;
3141
3142   
3143   for(dup_tsn_number = 1; dup_tsn_number <= number_of_dup_tsns; dup_tsn_number++) {
3144     proto_tree_add_item(chunk_tree, hf_sack_chunk_duplicate_tsn, chunk_tvb, dup_tsn_offset, NR_SACK_CHUNK_DUP_TSN_LENGTH, NETWORK_BYTE_ORDER);
3145     dup_tsn_offset += NR_SACK_CHUNK_DUP_TSN_LENGTH;
3146   }
3147   
3148   proto_item_append_text(chunk_item, " (Cumulative TSN: %u, a_rwnd: %u, gaps: %u, nr-gaps: %u, duplicate TSNs: %u)",
3149                            tvb_get_ntohl(chunk_tvb, NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET),
3150                            tvb_get_ntohl(chunk_tvb, NR_SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET),
3151                            number_of_gap_blocks, number_of_nr_gap_blocks, number_of_dup_tsns);
3152 }
3153
3154 #define HEARTBEAT_CHUNK_INFO_OFFSET CHUNK_VALUE_OFFSET
3155
3156 static void
3157 dissect_heartbeat_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
3158 {
3159   tvbuff_t   *parameter_tvb;
3160
3161   if (chunk_tree) {
3162     proto_item_append_text(chunk_item, " (Information: %u byte%s)", chunk_length - CHUNK_HEADER_LENGTH, plurality(chunk_length - CHUNK_HEADER_LENGTH, "", "s"));
3163     parameter_tvb  = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, chunk_length - CHUNK_HEADER_LENGTH, chunk_length - CHUNK_HEADER_LENGTH);
3164     /* FIXME: Parameters or parameter? */
3165     dissect_parameter(parameter_tvb, pinfo, chunk_tree, NULL, FALSE);
3166   }
3167 }
3168
3169 static void
3170 dissect_heartbeat_ack_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
3171 {
3172   tvbuff_t   *parameter_tvb;
3173
3174   if (chunk_tree) {
3175     proto_item_append_text(chunk_item, " (Information: %u byte%s)", chunk_length - CHUNK_HEADER_LENGTH, plurality(chunk_length - CHUNK_HEADER_LENGTH, "", "s"));
3176     parameter_tvb  = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, chunk_length - CHUNK_HEADER_LENGTH, chunk_length - CHUNK_HEADER_LENGTH);
3177     /* FIXME: Parameters or parameter? */
3178     dissect_parameter(parameter_tvb, pinfo, chunk_tree, NULL, FALSE);
3179   }
3180 }
3181
3182 #define ABORT_CHUNK_FIRST_ERROR_CAUSE_OFFSET 4
3183 #define SCTP_ABORT_CHUNK_T_BIT               0x01
3184
3185 static void
3186 dissect_abort_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *flags_item)
3187 {
3188   tvbuff_t *causes_tvb;
3189   proto_tree *flags_tree;
3190
3191   sctp_info.vtag_reflected =
3192       (tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_ABORT_CHUNK_T_BIT) != 0;
3193
3194   if (chunk_tree) {
3195     flags_tree  = proto_item_add_subtree(flags_item, ett_sctp_abort_chunk_flags);
3196     proto_tree_add_item(flags_tree, hf_abort_chunk_t_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
3197     causes_tvb    = tvb_new_subset(chunk_tvb, CHUNK_VALUE_OFFSET, chunk_length - CHUNK_HEADER_LENGTH, chunk_length - CHUNK_HEADER_LENGTH);
3198     dissect_error_causes(causes_tvb, pinfo, chunk_tree);
3199   }
3200 }
3201
3202 #define SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET CHUNK_VALUE_OFFSET
3203 #define SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_LENGTH 4
3204
3205 static void
3206 dissect_shutdown_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
3207 {
3208   if (chunk_tree) {
3209     proto_tree_add_item(chunk_tree, hf_shutdown_chunk_cumulative_tsn_ack, chunk_tvb, SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET, SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_LENGTH, NETWORK_BYTE_ORDER);
3210     proto_item_append_text(chunk_item, " (Cumulative TSN ack: %u)", tvb_get_ntohl(chunk_tvb, SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET));
3211   }
3212 }
3213
3214 static void
3215 dissect_shutdown_ack_chunk(tvbuff_t *chunk_tvb _U_)
3216 {
3217 }
3218
3219 #define ERROR_CAUSE_IND_CAUSES_OFFSET CHUNK_VALUE_OFFSET
3220
3221 static void
3222 dissect_error_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree)
3223 {
3224   tvbuff_t *causes_tvb;
3225
3226   if (chunk_tree) {
3227     causes_tvb    = tvb_new_subset(chunk_tvb, ERROR_CAUSE_IND_CAUSES_OFFSET, chunk_length - CHUNK_HEADER_LENGTH, chunk_length - CHUNK_HEADER_LENGTH);
3228     dissect_error_causes(causes_tvb, pinfo, chunk_tree);
3229   }
3230 }
3231
3232 #define COOKIE_OFFSET CHUNK_VALUE_OFFSET
3233
3234 static void
3235 dissect_cookie_echo_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, proto_tree *chunk_tree, proto_item *chunk_item)
3236 {
3237   if (chunk_tree) {
3238     proto_tree_add_item(chunk_tree, hf_cookie, chunk_tvb, COOKIE_OFFSET, chunk_length - CHUNK_HEADER_LENGTH, NETWORK_BYTE_ORDER);
3239     proto_item_append_text(chunk_item, " (Cookie length: %u byte%s)", chunk_length - CHUNK_HEADER_LENGTH, plurality(chunk_length - CHUNK_HEADER_LENGTH, "", "s"));
3240   }
3241 }
3242
3243 static void
3244 dissect_cookie_ack_chunk(tvbuff_t *chunk_tvb _U_)
3245 {
3246 }
3247
3248 #define ECNE_CHUNK_LOWEST_TSN_OFFSET CHUNK_VALUE_OFFSET
3249 #define ECNE_CHUNK_LOWEST_TSN_LENGTH 4
3250
3251 static void
3252 dissect_ecne_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
3253 {
3254   if (chunk_tree)
3255     proto_tree_add_item(chunk_tree, hf_ecne_chunk_lowest_tsn, chunk_tvb, ECNE_CHUNK_LOWEST_TSN_OFFSET, ECNE_CHUNK_LOWEST_TSN_LENGTH, NETWORK_BYTE_ORDER);
3256     proto_item_append_text(chunk_item, " (Lowest TSN: %u)", tvb_get_ntohl(chunk_tvb, ECNE_CHUNK_LOWEST_TSN_OFFSET));
3257 }
3258
3259 #define CWR_CHUNK_LOWEST_TSN_OFFSET CHUNK_VALUE_OFFSET
3260 #define CWR_CHUNK_LOWEST_TSN_LENGTH 4
3261
3262 static void
3263 dissect_cwr_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
3264 {
3265   if (chunk_tree)
3266     proto_tree_add_item(chunk_tree, hf_cwr_chunk_lowest_tsn, chunk_tvb, CWR_CHUNK_LOWEST_TSN_OFFSET, CWR_CHUNK_LOWEST_TSN_LENGTH, NETWORK_BYTE_ORDER);
3267     proto_item_append_text(chunk_item, " (Lowest TSN: %u)", tvb_get_ntohl(chunk_tvb, CWR_CHUNK_LOWEST_TSN_OFFSET));
3268 }
3269
3270 #define SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT 0x01
3271
3272
3273 static const true_false_string sctp_shutdown_complete_chunk_t_bit_value = {
3274   "Tag reflected",
3275   "Tag not reflected"
3276 };
3277
3278
3279 static void
3280 dissect_shutdown_complete_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *flags_item)
3281 {
3282   proto_tree *flags_tree;
3283
3284   sctp_info.vtag_reflected =
3285       (tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT) != 0;
3286
3287   if (chunk_tree) {
3288     flags_tree  = proto_item_add_subtree(flags_item, ett_sctp_shutdown_complete_chunk_flags);
3289     proto_tree_add_item(flags_tree, hf_shutdown_complete_chunk_t_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
3290   }
3291 }
3292
3293 #define FORWARD_TSN_CHUNK_TSN_LENGTH 4
3294 #define FORWARD_TSN_CHUNK_SID_LENGTH 2
3295 #define FORWARD_TSN_CHUNK_SSN_LENGTH 2
3296 #define FORWARD_TSN_CHUNK_TSN_OFFSET CHUNK_VALUE_OFFSET
3297 #define FORWARD_TSN_CHUNK_SID_OFFSET 0
3298 #define FORWARD_TSN_CHUNK_SSN_OFFSET (FORWARD_TSN_CHUNK_SID_OFFSET + FORWARD_TSN_CHUNK_SID_LENGTH)
3299
3300 static void
3301 dissect_forward_tsn_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, proto_tree *chunk_tree, proto_item *chunk_item)
3302 {
3303   guint   offset;
3304   guint16 number_of_affected_streams, affected_stream;
3305
3306   /* FIXME */
3307   if (chunk_length < CHUNK_HEADER_LENGTH + FORWARD_TSN_CHUNK_TSN_LENGTH) {
3308     proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
3309                            chunk_length,
3310                            CHUNK_HEADER_LENGTH + FORWARD_TSN_CHUNK_TSN_LENGTH);
3311     return;
3312   }
3313   if (chunk_tree) {
3314     proto_tree_add_item(chunk_tree, hf_forward_tsn_chunk_tsn, chunk_tvb, FORWARD_TSN_CHUNK_TSN_OFFSET, FORWARD_TSN_CHUNK_TSN_LENGTH, NETWORK_BYTE_ORDER);
3315     number_of_affected_streams = (chunk_length - CHUNK_HEADER_LENGTH - FORWARD_TSN_CHUNK_TSN_LENGTH) /
3316                                  (FORWARD_TSN_CHUNK_SID_LENGTH + FORWARD_TSN_CHUNK_SSN_LENGTH);
3317     offset = CHUNK_VALUE_OFFSET + FORWARD_TSN_CHUNK_TSN_LENGTH;
3318
3319     for(affected_stream = 0;  affected_stream < number_of_affected_streams; affected_stream++) {
3320         proto_tree_add_item(chunk_tree, hf_forward_tsn_chunk_sid, chunk_tvb, offset + FORWARD_TSN_CHUNK_SID_OFFSET, FORWARD_TSN_CHUNK_SID_LENGTH, NETWORK_BYTE_ORDER);
3321         proto_tree_add_item(chunk_tree, hf_forward_tsn_chunk_ssn, chunk_tvb, offset + FORWARD_TSN_CHUNK_SSN_OFFSET, FORWARD_TSN_CHUNK_SSN_LENGTH, NETWORK_BYTE_ORDER);
3322         offset = offset + (FORWARD_TSN_CHUNK_SID_LENGTH + FORWARD_TSN_CHUNK_SSN_LENGTH);
3323     }
3324     proto_item_append_text(chunk_item, "(Cumulative TSN: %u)", tvb_get_ntohl(chunk_tvb, FORWARD_TSN_CHUNK_TSN_OFFSET));
3325   }
3326 }
3327
3328 #define STREAM_RESET_PARAMETERS_OFFSET CHUNK_HEADER_LENGTH
3329
3330 static void
3331 dissect_stream_reset_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item _U_)
3332 {
3333   tvbuff_t *parameters_tvb;
3334
3335   if (chunk_tree) {
3336     parameters_tvb = tvb_new_subset(chunk_tvb, STREAM_RESET_PARAMETERS_OFFSET, chunk_length - CHUNK_HEADER_LENGTH, chunk_length - CHUNK_HEADER_LENGTH);
3337     dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, FALSE);
3338   }
3339 }
3340
3341 #define SHARED_KEY_ID_LENGTH 2
3342
3343 #define SHARED_KEY_ID_OFFSET PARAMETER_VALUE_OFFSET
3344 #define HMAC_ID_OFFSET       (SHARED_KEY_ID_OFFSET + SHARED_KEY_ID_LENGTH)
3345 #define HMAC_OFFSET          (HMAC_ID_OFFSET + HMAC_ID_LENGTH)
3346
3347 static void
3348 dissect_auth_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, proto_tree *chunk_tree, proto_item *chunk_item _U_)
3349 {
3350   guint hmac_length;
3351
3352   hmac_length = chunk_length - CHUNK_HEADER_LENGTH - HMAC_ID_LENGTH - SHARED_KEY_ID_LENGTH;
3353   proto_tree_add_item(chunk_tree, hf_shared_key_id, chunk_tvb, SHARED_KEY_ID_OFFSET, SHARED_KEY_ID_LENGTH, NETWORK_BYTE_ORDER);
3354   proto_tree_add_item(chunk_tree, hf_hmac_id,       chunk_tvb, HMAC_ID_OFFSET,       HMAC_ID_LENGTH,       NETWORK_BYTE_ORDER);
3355   if (hmac_length > 0)
3356     proto_tree_add_item(chunk_tree, hf_hmac,    chunk_tvb, HMAC_OFFSET,    hmac_length,    NETWORK_BYTE_ORDER);
3357 }
3358
3359 #define SCTP_SERIAL_NUMBER_LENGTH    4
3360 #define SERIAL_NUMBER_OFFSET    CHUNK_VALUE_OFFSET
3361 #define ASCONF_CHUNK_PARAMETERS_OFFSET (SERIAL_NUMBER_OFFSET + SCTP_SERIAL_NUMBER_LENGTH)
3362
3363 static void
3364 dissect_asconf_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
3365 {
3366   tvbuff_t *parameters_tvb;
3367
3368   if (chunk_length < CHUNK_HEADER_LENGTH + SCTP_SERIAL_NUMBER_LENGTH) {
3369     proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
3370                            chunk_length,
3371                            CHUNK_HEADER_LENGTH + SCTP_SERIAL_NUMBER_LENGTH);
3372     return;
3373   }
3374   if (chunk_tree) {
3375     proto_tree_add_item(chunk_tree, hf_asconf_serial, chunk_tvb, SERIAL_NUMBER_OFFSET, SCTP_SERIAL_NUMBER_LENGTH, NETWORK_BYTE_ORDER);
3376     chunk_length -= CHUNK_HEADER_LENGTH + SCTP_SERIAL_NUMBER_LENGTH;
3377     parameters_tvb    = tvb_new_subset(chunk_tvb, ASCONF_CHUNK_PARAMETERS_OFFSET, chunk_length, chunk_length);
3378     dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, FALSE);
3379   }
3380 }
3381
3382 #define ASCONF_ACK_CHUNK_PARAMETERS_OFFSET (SERIAL_NUMBER_OFFSET + SCTP_SERIAL_NUMBER_LENGTH)
3383
3384 static void
3385 dissect_asconf_ack_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
3386 {
3387   tvbuff_t *parameters_tvb;
3388
3389   if (chunk_length < CHUNK_HEADER_LENGTH + SCTP_SERIAL_NUMBER_LENGTH) {
3390     proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
3391                            chunk_length + CHUNK_HEADER_LENGTH,
3392                            CHUNK_HEADER_LENGTH + SCTP_SERIAL_NUMBER_LENGTH);
3393     return;
3394   }
3395   if (chunk_tree) {
3396     proto_tree_add_item(chunk_tree, hf_asconf_ack_serial, chunk_tvb, SERIAL_NUMBER_OFFSET, SCTP_SERIAL_NUMBER_LENGTH, NETWORK_BYTE_ORDER);
3397     chunk_length -= CHUNK_HEADER_LENGTH + SCTP_SERIAL_NUMBER_LENGTH;
3398     parameters_tvb    = tvb_new_subset(chunk_tvb, ASCONF_ACK_CHUNK_PARAMETERS_OFFSET, chunk_length, chunk_length);
3399     dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, FALSE);
3400   }
3401 }
3402
3403 #define PKTDROP_CHUNK_BANDWIDTH_LENGTH      4
3404 #define PKTDROP_CHUNK_QUEUESIZE_LENGTH      4
3405 #define PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH 2
3406 #define PKTDROP_CHUNK_RESERVED_SIZE_LENGTH  2
3407
3408 #define PKTDROP_CHUNK_HEADER_LENGTH (CHUNK_HEADER_LENGTH + \
3409                    PKTDROP_CHUNK_BANDWIDTH_LENGTH + \
3410                    PKTDROP_CHUNK_QUEUESIZE_LENGTH + \
3411                    PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH + \
3412                    PKTDROP_CHUNK_RESERVED_SIZE_LENGTH)
3413
3414 #define PKTDROP_CHUNK_BANDWIDTH_OFFSET      CHUNK_VALUE_OFFSET
3415 #define PKTDROP_CHUNK_QUEUESIZE_OFFSET      (PKTDROP_CHUNK_BANDWIDTH_OFFSET + PKTDROP_CHUNK_BANDWIDTH_LENGTH)
3416 #define PKTDROP_CHUNK_TRUNCATED_SIZE_OFFSET (PKTDROP_CHUNK_QUEUESIZE_OFFSET + PKTDROP_CHUNK_QUEUESIZE_LENGTH)
3417 #define PKTDROP_CHUNK_RESERVED_SIZE_OFFSET  (PKTDROP_CHUNK_TRUNCATED_SIZE_OFFSET + PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH)
3418 #define PKTDROP_CHUNK_DATA_FIELD_OFFSET     (PKTDROP_CHUNK_RESERVED_SIZE_OFFSET + PKTDROP_CHUNK_RESERVED_SIZE_LENGTH)
3419
3420 #define SCTP_PKTDROP_CHUNK_M_BIT 0x01
3421 #define SCTP_PKTDROP_CHUNK_B_BIT 0x02
3422 #define SCTP_PKTDROP_CHUNK_T_BIT 0x04
3423
3424 static const true_false_string sctp_pktdropk_m_bit_value = {
3425   "Source is a middlebox",
3426   "Source is an endhost"
3427 };
3428
3429 static const true_false_string sctp_pktdropk_b_bit_value = {
3430   "SCTP checksum was incorrect",
3431   "SCTP checksum was correct"
3432 };
3433
3434 static const true_false_string sctp_pktdropk_t_bit_value = {
3435   "Packet is truncated",
3436   "Packet is not truncated"
3437 };
3438
3439 static void
3440 dissect_pktdrop_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
3441 {
3442   tvbuff_t *data_field_tvb;
3443   proto_tree *flags_tree;
3444
3445   if (chunk_length < PKTDROP_CHUNK_HEADER_LENGTH) {
3446     proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
3447                            chunk_length,
3448                            PKTDROP_CHUNK_HEADER_LENGTH);
3449     return;
3450   }
3451   chunk_length -= PKTDROP_CHUNK_HEADER_LENGTH;
3452   data_field_tvb = tvb_new_subset(chunk_tvb, PKTDROP_CHUNK_DATA_FIELD_OFFSET, chunk_length, chunk_length);
3453
3454   if (chunk_tree) {
3455     flags_tree  = proto_item_add_subtree(flags_item, ett_sctp_pktdrop_chunk_flags);
3456
3457     proto_tree_add_item(flags_tree, hf_pktdrop_chunk_m_bit,            chunk_tvb, CHUNK_FLAGS_OFFSET,                  CHUNK_FLAGS_LENGTH,                  NETWORK_BYTE_ORDER);
3458     proto_tree_add_item(flags_tree, hf_pktdrop_chunk_b_bit,            chunk_tvb, CHUNK_FLAGS_OFFSET,                  CHUNK_FLAGS_LENGTH,                  NETWORK_BYTE_ORDER);
3459     proto_tree_add_item(flags_tree, hf_pktdrop_chunk_t_bit,            chunk_tvb, CHUNK_FLAGS_OFFSET,                  CHUNK_FLAGS_LENGTH,                  NETWORK_BYTE_ORDER);
3460     proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_bandwidth,        chunk_tvb, PKTDROP_CHUNK_BANDWIDTH_OFFSET,      PKTDROP_CHUNK_BANDWIDTH_LENGTH,      NETWORK_BYTE_ORDER);
3461     proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_queuesize,        chunk_tvb, PKTDROP_CHUNK_QUEUESIZE_OFFSET,      PKTDROP_CHUNK_QUEUESIZE_LENGTH,      NETWORK_BYTE_ORDER);
3462     proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_truncated_length, chunk_tvb, PKTDROP_CHUNK_TRUNCATED_SIZE_OFFSET, PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH, NETWORK_BYTE_ORDER);
3463     proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_reserved,         chunk_tvb, PKTDROP_CHUNK_RESERVED_SIZE_OFFSET,  PKTDROP_CHUNK_RESERVED_SIZE_LENGTH,  NETWORK_BYTE_ORDER);
3464     /* XXX - set pinfo->in_error_pkt? */
3465     if (chunk_length > 0) {
3466       if (tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_PKTDROP_CHUNK_T_BIT)
3467         proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_data_field,   chunk_tvb, PKTDROP_CHUNK_DATA_FIELD_OFFSET,     chunk_length,                   NETWORK_BYTE_ORDER);
3468       else
3469         dissect_sctp_packet(data_field_tvb, pinfo, chunk_tree, TRUE);
3470     }
3471   }
3472 }
3473
3474 static void
3475 dissect_unknown_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, proto_tree *chunk_tree, proto_item *chunk_item)
3476 {
3477   if (chunk_tree) {
3478     if (chunk_length > CHUNK_HEADER_LENGTH)
3479       proto_tree_add_item(chunk_tree, hf_chunk_value, chunk_tvb, CHUNK_VALUE_OFFSET, chunk_length - CHUNK_HEADER_LENGTH, NETWORK_BYTE_ORDER);
3480     proto_item_append_text(chunk_item, " (Type: %u, value length: %u byte%s)", chunk_length, chunk_length, plurality(chunk_length - CHUNK_HEADER_LENGTH, "", "s"));
3481   }
3482 }
3483
3484 #define SCTP_CHUNK_BIT_1 0x80
3485 #define SCTP_CHUNK_BIT_2 0x40
3486
3487 static const true_false_string sctp_chunk_bit_1_value = {
3488   "Skip chunk and continue processing of the packet",
3489   "Stop processing of the packet"
3490 };
3491
3492 static const true_false_string sctp_chunk_bit_2_value = {
3493   "Do report",
3494   "Do not report"
3495 };
3496
3497
3498 static gboolean
3499 dissect_sctp_chunk(tvbuff_t *chunk_tvb,
3500                                    packet_info *pinfo,
3501                                    proto_tree *tree,
3502                                    proto_tree *sctp_tree,
3503                                    sctp_half_assoc_t* ha,
3504                                    gboolean useinfo)
3505 {
3506   guint8 type, flags;
3507   guint16 length, padding_length;
3508   gboolean result;
3509   proto_item *flags_item;
3510   proto_item *chunk_item;
3511   proto_tree *chunk_tree;
3512   proto_item *type_item;
3513   proto_tree *type_tree;
3514
3515   result = FALSE;
3516
3517   /* first extract the chunk header */
3518   type           = tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET);
3519   flags          = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
3520   length         = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
3521   padding_length = tvb_length(chunk_tvb) - length;
3522
3523  if (useinfo && (check_col(pinfo->cinfo, COL_INFO)))
3524     col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(type, chunk_type_values, "RESERVED"));
3525
3526   if (tree) {
3527     /* create proto_tree stuff */
3528     chunk_item   = proto_tree_add_text(sctp_tree, chunk_tvb, CHUNK_HEADER_OFFSET, tvb_length(chunk_tvb), "%s chunk", val_to_str(type, chunk_type_values, "RESERVED"));
3529     chunk_tree   = proto_item_add_subtree(chunk_item, ett_sctp_chunk);
3530
3531     /* then insert the chunk header components into the protocol tree */
3532     type_item  = proto_tree_add_item(chunk_tree, hf_chunk_type, chunk_tvb, CHUNK_TYPE_OFFSET, CHUNK_TYPE_LENGTH, NETWORK_BYTE_ORDER);
3533     type_tree  = proto_item_add_subtree(type_item, ett_sctp_chunk_type);
3534     proto_tree_add_item(type_tree, hf_chunk_bit_1,  chunk_tvb, CHUNK_TYPE_OFFSET,  CHUNK_TYPE_LENGTH,  NETWORK_BYTE_ORDER);
3535     proto_tree_add_item(type_tree, hf_chunk_bit_2,  chunk_tvb, CHUNK_TYPE_OFFSET,  CHUNK_TYPE_LENGTH,  NETWORK_BYTE_ORDER);
3536     flags_item = proto_tree_add_item(chunk_tree, hf_chunk_flags, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
3537   } else {
3538     chunk_tree = NULL;
3539     chunk_item = NULL;
3540     flags_item = NULL;
3541   }
3542   if (length < CHUNK_HEADER_LENGTH) {
3543     if (tree) {
3544       proto_tree_add_uint_format(chunk_tree, hf_chunk_length, chunk_tvb,
3545                                  CHUNK_LENGTH_OFFSET, CHUNK_LENGTH_LENGTH,
3546                                  length,
3547                                  "Chunk length: %u (invalid, should be >= %u)",
3548                                  length, CHUNK_HEADER_LENGTH);
3549       proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
3550                              length, CHUNK_HEADER_LENGTH);
3551     }
3552     if (type == SCTP_DATA_CHUNK_ID)
3553       result = TRUE;
3554     return result;
3555   }
3556   if (tree) {
3557     proto_tree_add_uint(chunk_tree, hf_chunk_length, chunk_tvb, CHUNK_LENGTH_OFFSET, CHUNK_LENGTH_LENGTH, length);
3558   }
3559   /*
3560   length -= CHUNK_HEADER_LENGTH;
3561   */
3562
3563   /* now dissect the chunk value */
3564   switch(type) {
3565   case SCTP_DATA_CHUNK_ID:
3566     result = dissect_data_chunk(chunk_tvb, length, pinfo, tree, chunk_tree, chunk_item, flags_item, ha);
3567     break;
3568   case SCTP_INIT_CHUNK_ID:
3569     dissect_init_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
3570     break;
3571   case SCTP_INIT_ACK_CHUNK_ID:
3572     dissect_init_ack_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
3573     break;
3574   case SCTP_SACK_CHUNK_ID:
3575     dissect_sack_chunk(pinfo, chunk_tvb, chunk_tree, chunk_item, flags_item, ha);
3576     break;
3577   case SCTP_HEARTBEAT_CHUNK_ID:
3578     dissect_heartbeat_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
3579     break;
3580   case SCTP_HEARTBEAT_ACK_CHUNK_ID:
3581     dissect_heartbeat_ack_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
3582     break;
3583   case SCTP_ABORT_CHUNK_ID:
3584     dissect_abort_chunk(chunk_tvb, length, pinfo, chunk_tree, flags_item);
3585     break;
3586   case SCTP_SHUTDOWN_CHUNK_ID:
3587     dissect_shutdown_chunk(chunk_tvb, chunk_tree, chunk_item);
3588     break;
3589   case SCTP_SHUTDOWN_ACK_CHUNK_ID:
3590     dissect_shutdown_ack_chunk(chunk_tvb);
3591     break;
3592   case SCTP_ERROR_CHUNK_ID:
3593     dissect_error_chunk(chunk_tvb, length, pinfo, chunk_tree);
3594     break;
3595   case SCTP_COOKIE_ECHO_CHUNK_ID:
3596     dissect_cookie_echo_chunk(chunk_tvb, length, chunk_tree, chunk_item);
3597     break;
3598   case SCTP_COOKIE_ACK_CHUNK_ID:
3599     dissect_cookie_ack_chunk(chunk_tvb);
3600     break;
3601   case SCTP_ECNE_CHUNK_ID:
3602     dissect_ecne_chunk(chunk_tvb, chunk_tree, chunk_item);
3603     break;
3604   case SCTP_CWR_CHUNK_ID:
3605     dissect_cwr_chunk(chunk_tvb, chunk_tree, chunk_item);
3606     break;
3607   case SCTP_SHUTDOWN_COMPLETE_CHUNK_ID:
3608     dissect_shutdown_complete_chunk(chunk_tvb, chunk_tree, flags_item);
3609     break;
3610   case SCTP_FORWARD_TSN_CHUNK_ID:
3611     dissect_forward_tsn_chunk(chunk_tvb, length, chunk_tree, chunk_item);
3612     break;
3613   case SCTP_STREAM_RESET_CHUNK_ID:
3614     dissect_stream_reset_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
3615     break;
3616   case SCTP_AUTH_CHUNK_ID:
3617     dissect_auth_chunk(chunk_tvb, length, chunk_tree, chunk_item);
3618     break;
3619   case SCTP_NR_SACK_CHUNK_ID:
3620     dissect_nr_sack_chunk(pinfo, chunk_tvb, chunk_tree, chunk_item, flags_item, ha);
3621     break;
3622   case SCTP_ASCONF_ACK_CHUNK_ID:
3623     dissect_asconf_ack_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
3624     break;
3625   case SCTP_ASCONF_CHUNK_ID:
3626     dissect_asconf_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
3627     break;
3628   case SCTP_PKTDROP_CHUNK_ID:
3629     col_set_writable(pinfo->cinfo, FALSE);
3630     dissect_pktdrop_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item, flags_item);
3631     col_set_writable(pinfo->cinfo, TRUE);
3632     break;
3633   default:
3634     dissect_unknown_chunk(chunk_tvb, length, chunk_tree, chunk_item);
3635     break;
3636   }
3637
3638   if (padding_length > 0)
3639     proto_tree_add_item(chunk_tree, hf_chunk_padding, chunk_tvb, CHUNK_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
3640
3641   if (useinfo && ((type == SCTP_DATA_CHUNK_ID) || show_always_control_chunks) && check_col(pinfo->cinfo, COL_INFO))
3642     col_set_fence(pinfo->cinfo, COL_INFO);
3643
3644   return result;
3645 }
3646
3647 static void
3648 dissect_sctp_chunks(tvbuff_t *tvb,
3649                                         packet_info *pinfo,
3650                                         proto_tree *tree,
3651                                         proto_item *sctp_item,
3652                                         proto_tree *sctp_tree,
3653                                         sctp_half_assoc_t* ha,
3654                                         gboolean encapsulated)
3655 {
3656   tvbuff_t *chunk_tvb;
3657   guint16 length, total_length, remaining_length;
3658   gint last_offset, offset;
3659   gboolean sctp_item_length_set;
3660
3661   /* the common header of the datagram is already handled */
3662   last_offset = 0;
3663   offset = COMMON_HEADER_LENGTH;
3664   sctp_item_length_set = FALSE;
3665
3666   while((remaining_length = tvb_length_remaining(tvb, offset))) {
3667     /* extract the chunk length and compute number of padding bytes */
3668     length         = tvb_get_ntohs(tvb, offset + CHUNK_LENGTH_OFFSET);
3669     total_length   = ADD_PADDING(length);
3670     if (remaining_length >= length)
3671       total_length = MIN(total_length, remaining_length);
3672     /* create a tvb for the chunk including the padding bytes */
3673     chunk_tvb    = tvb_new_subset(tvb, offset, total_length, total_length);
3674
3675     /* save it in the sctp_info structure */
3676     if (!encapsulated) {
3677       if (sctp_info.number_of_tvbs < MAXIMUM_NUMBER_OF_TVBS)
3678         sctp_info.tvb[sctp_info.number_of_tvbs++] = chunk_tvb;
3679       else
3680         sctp_info.incomplete = TRUE;
3681     }
3682
3683     /* call dissect_sctp_chunk for the actual work */
3684     if (dissect_sctp_chunk(chunk_tvb, pinfo, tree, sctp_tree, ha, !encapsulated) && (tree)) {
3685       proto_item_set_len(sctp_item, offset - last_offset + DATA_CHUNK_HEADER_LENGTH);
3686       sctp_item_length_set = TRUE;
3687       offset += total_length;
3688       last_offset = offset;
3689       if (tvb_reported_length_remaining(tvb, offset) > 0) {
3690         sctp_item = proto_tree_add_item(tree, proto_sctp, tvb, offset, -1, FALSE);
3691         sctp_tree = proto_item_add_subtree(sctp_item, ett_sctp);
3692         sctp_item_length_set = FALSE;
3693       }
3694     } else {
3695       /* get rid of the dissected chunk */
3696       offset += total_length;
3697     }
3698   }
3699   if (!sctp_item_length_set && (tree)) {
3700     proto_item_set_len(sctp_item, offset - last_offset);
3701   }
3702 }
3703
3704 static void
3705 dissect_sctp_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean encapsulated)
3706 {
3707   guint32 checksum = 0, calculated_crc32c = 0, calculated_adler32 = 0;
3708   guint16 source_port, destination_port;
3709   guint length, reported_length;
3710   gboolean crc32c_correct = FALSE, adler32_correct = FALSE;
3711   proto_item *sctp_item, *hidden_item;
3712   proto_tree *sctp_tree;
3713   guint32 vtag;
3714   sctp_half_assoc_t* ha = NULL;
3715
3716   length          = tvb_length(tvb);
3717   reported_length = tvb_reported_length(tvb);
3718   checksum        = tvb_get_ntohl(tvb, CHECKSUM_OFFSET);
3719   sctp_info.checksum_zero = (checksum == 0);
3720
3721   /* Only try to checksum the packet if we have all of it */
3722   if (tvb_bytes_exist(tvb, 0, reported_length)) {
3723
3724     switch(sctp_checksum) {
3725     case SCTP_CHECKSUM_NONE:
3726       break;
3727     case SCTP_CHECKSUM_ADLER32:
3728       calculated_adler32           = sctp_adler32(tvb_get_ptr(tvb, 0, length), length);
3729       adler32_correct              = (checksum == calculated_adler32);
3730       sctp_info.adler32_calculated = TRUE;
3731       sctp_info.adler32_correct    = adler32_correct;
3732       break;
3733     case SCTP_CHECKSUM_CRC32C:
3734       calculated_crc32c            = sctp_crc32c(tvb_get_ptr(tvb, 0, length), length);
3735       crc32c_correct               = (checksum == calculated_crc32c);
3736       sctp_info.crc32c_calculated  = TRUE;
3737       sctp_info.crc32c_correct     = crc32c_correct;
3738       break;
3739     case SCTP_CHECKSUM_AUTOMATIC:
3740       calculated_adler32           = sctp_adler32(tvb_get_ptr(tvb, 0, length), length);
3741       adler32_correct              = (checksum == calculated_adler32);
3742       calculated_crc32c            = sctp_crc32c(tvb_get_ptr(tvb, 0, length), length);
3743       crc32c_correct               = (checksum == calculated_crc32c);
3744       sctp_info.adler32_calculated = TRUE;
3745       sctp_info.adler32_correct    = adler32_correct;
3746       sctp_info.crc32c_calculated  = TRUE;
3747       sctp_info.crc32c_correct     = crc32c_correct;
3748       break;
3749     }
3750   }
3751
3752   /* In the interest of speed, if "tree" is NULL, don't do any work not
3753      necessary to generate protocol tree items. */
3754   source_port      = tvb_get_ntohs(tvb, SOURCE_PORT_OFFSET);
3755   destination_port = tvb_get_ntohs(tvb, DESTINATION_PORT_OFFSET);
3756   vtag             = tvb_get_ntohl(tvb,VERIFICATION_TAG_OFFSET);
3757
3758   ha = get_half_assoc(pinfo, source_port, destination_port, vtag);
3759
3760   if (tree) {
3761
3762     /* create the sctp protocol tree */
3763     if (show_port_numbers)
3764       sctp_item = proto_tree_add_protocol_format(tree, proto_sctp, tvb, 0, -1,
3765                                                  "Stream Control Transmission Protocol, Src Port: %s (%u), Dst Port: %s (%u)",
3766                                                  get_sctp_port(source_port), source_port,
3767                                                  get_sctp_port(destination_port), destination_port);
3768     else
3769       sctp_item = proto_tree_add_item(tree, proto_sctp, tvb, 0, -1, FALSE);
3770     sctp_tree = proto_item_add_subtree(sctp_item, ett_sctp);
3771
3772     /* add the components of the common header to the protocol tree */
3773     proto_tree_add_item(sctp_tree, hf_source_port,      tvb, SOURCE_PORT_OFFSET,      SOURCE_PORT_LENGTH,      NETWORK_BYTE_ORDER);
3774     proto_tree_add_item(sctp_tree, hf_destination_port, tvb, DESTINATION_PORT_OFFSET, DESTINATION_PORT_LENGTH, NETWORK_BYTE_ORDER);
3775     proto_tree_add_item(sctp_tree, hf_verification_tag, tvb, VERIFICATION_TAG_OFFSET, VERIFICATION_TAG_LENGTH, NETWORK_BYTE_ORDER);
3776     hidden_item = proto_tree_add_item(sctp_tree, hf_port, tvb, SOURCE_PORT_OFFSET,      SOURCE_PORT_LENGTH,      NETWORK_BYTE_ORDER);
3777         PROTO_ITEM_SET_HIDDEN(hidden_item);
3778     hidden_item = proto_tree_add_item(sctp_tree, hf_port, tvb, DESTINATION_PORT_OFFSET, DESTINATION_PORT_LENGTH, NETWORK_BYTE_ORDER);
3779         PROTO_ITEM_SET_HIDDEN(hidden_item);
3780
3781     if (tvb_bytes_exist(tvb, 0, reported_length)) {
3782       /* We have the whole packet */
3783
3784       switch(sctp_checksum) {
3785       case SCTP_CHECKSUM_NONE:
3786         proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, checksum, "Checksum: 0x%08x (not verified)", checksum);
3787         break;
3788       case SCTP_CHECKSUM_ADLER32:
3789         if (adler32_correct)
3790           proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
3791                                      checksum, "Checksum: 0x%08x [correct Adler32]", checksum);
3792         else
3793           proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
3794                                      checksum, "Checksum: 0x%08x [incorrect Adler32, should be 0x%08x]", checksum, calculated_adler32);
3795         hidden_item = proto_tree_add_boolean(sctp_tree, hf_checksum_bad, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, !(adler32_correct));
3796         PROTO_ITEM_SET_HIDDEN(hidden_item);
3797        break;
3798       case SCTP_CHECKSUM_CRC32C:
3799         if (crc32c_correct)
3800           proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
3801                                      checksum, "Checksum: 0x%08x [correct CRC32C]", checksum);
3802         else
3803           proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
3804                                      checksum, "Checksum: 0x%08x [incorrect CRC32C, should be 0x%08x]", checksum, calculated_crc32c);
3805         hidden_item = proto_tree_add_boolean(sctp_tree, hf_checksum_bad, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, !(crc32c_correct));
3806         PROTO_ITEM_SET_HIDDEN(hidden_item);
3807         break;
3808       case SCTP_CHECKSUM_AUTOMATIC:
3809         if ((adler32_correct) && !(crc32c_correct))
3810           proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
3811                                      checksum, "Checksum: 0x%08x [correct Adler32]", checksum);
3812         else if ((!adler32_correct) && (crc32c_correct))
3813           proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
3814                                      checksum, "Checksum: 0x%08x [correct CRC32C]", checksum);
3815         else if ((adler32_correct) && (crc32c_correct))
3816           proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
3817                                      checksum, "Checksum: 0x%08x [correct Adler32 and CRC32C]", checksum);
3818         else
3819           proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
3820                                      checksum, "Checksum: 0x%08x [incorrect, should be 0x%08x (Adler32) or 0x%08x (CRC32C)]",
3821                                      checksum, calculated_adler32, calculated_crc32c);
3822         hidden_item = proto_tree_add_boolean(sctp_tree, hf_checksum_bad, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, !(crc32c_correct || adler32_correct));
3823         PROTO_ITEM_SET_HIDDEN(hidden_item);
3824         break;
3825       }
3826     } else {
3827       /* We don't have the whole packet so we can't verify the checksum */
3828       proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
3829                                  checksum, "Checksum: 0x%08x [unchecked, not all data available]", checksum);
3830     }
3831   } else {
3832     sctp_tree = NULL;
3833     sctp_item = NULL;
3834   }
3835
3836   /* add all chunks of the sctp datagram to the protocol tree */
3837   dissect_sctp_chunks(tvb, pinfo, tree, sctp_item, sctp_tree, ha, encapsulated);
3838 }
3839
3840 static void
3841 dissect_sctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
3842 {
3843   guint16 source_port, destination_port;
3844
3845   /* Extract the common header */
3846   source_port      = tvb_get_ntohs(tvb, SOURCE_PORT_OFFSET);
3847   destination_port = tvb_get_ntohs(tvb, DESTINATION_PORT_OFFSET);
3848
3849   /* update pi structure */
3850   pinfo->ptype    = PT_SCTP;
3851   pinfo->srcport  = source_port;
3852   pinfo->destport = destination_port;
3853
3854   /* make entry in the Protocol column on summary display */
3855   col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCTP");
3856
3857   /* Clear entries in Info column on summary display */
3858   if (check_col(pinfo->cinfo, COL_INFO))
3859     col_set_str(pinfo->cinfo, COL_INFO, "");
3860
3861   memset(&pinfo->ppids, 0, sizeof(pinfo->ppids));
3862
3863   /*  The tvb array in struct _sctp_info is huge: currently 2k pointers.
3864    *  We know (by the value of 'number_of_tvbs') which of these entries have
3865    *  been used, so don't memset() the array.  This saves us from zeroing out
3866    *  8k (4-byte pointers) or 16k (8-byte pointers) of memory every time we
3867    *  dissect a packet (saving quite a bit of time!).
3868    */
3869   sctp_info.incomplete = 0;
3870   sctp_info.adler32_calculated = 0;
3871   sctp_info.adler32_correct = 0;
3872   sctp_info.crc32c_calculated = 0;
3873   sctp_info.crc32c_correct = 0;
3874   sctp_info.vtag_reflected = 0;
3875   sctp_info.number_of_tvbs = 0;
3876   sctp_info.verification_tag = tvb_get_ntohl(tvb, VERIFICATION_TAG_OFFSET);
3877
3878   sctp_info.sport = pinfo->srcport;
3879   sctp_info.dport = pinfo->destport;
3880   SET_ADDRESS(&sctp_info.ip_src, pinfo->src.type, pinfo->src.len, pinfo->src.data);
3881   SET_ADDRESS(&sctp_info.ip_dst, pinfo->dst.type, pinfo->dst.len, pinfo->dst.data);
3882
3883   dissect_sctp_packet(tvb, pinfo, tree, FALSE);
3884   if (!pinfo->in_error_pkt)
3885     tap_queue_packet(sctp_tap, pinfo, &sctp_info);
3886 }
3887
3888 /* Register the protocol with Wireshark */
3889 void
3890 proto_register_sctp(void)
3891 {
3892
3893   /* Setup list of header fields */
3894   static hf_register_info hf[] = {
3895     { &hf_source_port,                              { "Source port",                                    "sctp.srcport",                                         FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3896     { &hf_destination_port,                         { "Destination port",                               "sctp.dstport",                                         FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3897     { &hf_port,                                     { "Port",                                           "sctp.port",                                            FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3898     { &hf_verification_tag,                         { "Verification tag",                               "sctp.verification_tag",                                FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
3899     { &hf_checksum,                                 { "Checksum",                                       "sctp.checksum",                                        FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
3900     { &hf_checksum_bad,                             { "Bad checksum",                                   "sctp.checksum_bad",                                    FT_BOOLEAN, BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
3901     { &hf_chunk_type,                               { "Chunk type",                                     "sctp.chunk_type",                                      FT_UINT8,   BASE_DEC,  VALS(chunk_type_values),                        0x0,                                NULL, HFILL } },
3902     { &hf_chunk_flags,                              { "Chunk flags",                                    "sctp.chunk_flags",                                     FT_UINT8,   BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
3903     { &hf_chunk_bit_1,                              { "Bit",                                            "sctp.chunk_bit_1",                                     FT_BOOLEAN, 8,         TFS(&sctp_chunk_bit_1_value),                   SCTP_CHUNK_BIT_1,                   NULL, HFILL } },
3904     { &hf_chunk_bit_2,                              { "Bit",                                            "sctp.chunk_bit_2",                                     FT_BOOLEAN, 8,         TFS(&sctp_chunk_bit_2_value),                   SCTP_CHUNK_BIT_2,                   NULL, HFILL } },
3905     { &hf_chunk_length,                             { "Chunk length",                                   "sctp.chunk_length",                                    FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3906     { &hf_chunk_padding,                            { "Chunk padding",                                  "sctp.chunk_padding",                                   FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
3907     { &hf_chunk_value,                              { "Chunk value",                                    "sctp.chunk_value",                                     FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
3908     { &hf_cookie,                                   { "Cookie",                                         "sctp.cookie",                                          FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
3909     { &hf_initiate_tag,                             { "Initiate tag",                                   "sctp.initiate_tag",                                    FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
3910     { &hf_init_chunk_initiate_tag,                  { "Initiate tag",                                   "sctp.init_initiate_tag",                               FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
3911     { &hf_init_chunk_adv_rec_window_credit,         { "Advertised receiver window credit (a_rwnd)",     "sctp.init_credit",                                     FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3912     { &hf_init_chunk_number_of_outbound_streams,    { "Number of outbound streams",                     "sctp.init_nr_out_streams",                             FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3913     { &hf_init_chunk_number_of_inbound_streams,     { "Number of inbound streams",                      "sctp.init_nr_in_streams",                              FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3914     { &hf_init_chunk_initial_tsn,                   { "Initial TSN",                                    "sctp.init_initial_tsn",                                FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3915     { &hf_initack_chunk_initiate_tag,               { "Initiate tag",                                   "sctp.initack_initiate_tag",                            FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
3916     { &hf_initack_chunk_adv_rec_window_credit,      { "Advertised receiver window credit (a_rwnd)",     "sctp.initack_credit",                                  FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3917     { &hf_initack_chunk_number_of_outbound_streams, { "Number of outbound streams",                     "sctp.initack_nr_out_streams",                          FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3918     { &hf_initack_chunk_number_of_inbound_streams,  { "Number of inbound streams",                      "sctp.initack_nr_in_streams",                           FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3919     { &hf_initack_chunk_initial_tsn,                { "Initial TSN",                                    "sctp.initack_initial_tsn",                             FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3920     { &hf_cumulative_tsn_ack,                       { "Cumulative TSN Ack",                             "sctp.cumulative_tsn_ack",                              FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3921     { &hf_data_chunk_tsn,                           { "TSN",                                            "sctp.data_tsn",                                        FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3922     { &hf_data_chunk_stream_id,                     { "Stream Identifier",                              "sctp.data_sid",                                        FT_UINT16,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
3923     { &hf_data_chunk_stream_seq_number,             { "Stream sequence number",                         "sctp.data_ssn",                                        FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3924     { &hf_data_chunk_payload_proto_id,              { "Payload protocol identifier",                    "sctp.data_payload_proto_id",                           FT_UINT32,  BASE_DEC,  VALS(sctp_payload_proto_id_values),             0x0,                                NULL, HFILL } },
3925     { &hf_data_chunk_e_bit,                         { "E-Bit",                                          "sctp.data_e_bit",                                      FT_BOOLEAN, 8,         TFS(&sctp_data_chunk_e_bit_value),              SCTP_DATA_CHUNK_E_BIT,              NULL, HFILL } },
3926     { &hf_data_chunk_b_bit,                         { "B-Bit",                                          "sctp.data_b_bit",                                      FT_BOOLEAN, 8,         TFS(&sctp_data_chunk_b_bit_value),              SCTP_DATA_CHUNK_B_BIT,              NULL, HFILL } },
3927     { &hf_data_chunk_u_bit,                         { "U-Bit",                                          "sctp.data_u_bit",                                      FT_BOOLEAN, 8,         TFS(&sctp_data_chunk_u_bit_value),              SCTP_DATA_CHUNK_U_BIT,              NULL, HFILL } },
3928     { &hf_data_chunk_i_bit,                         { "I-Bit",                                          "sctp.data_i_bit",                                      FT_BOOLEAN, 8,         TFS(&sctp_data_chunk_i_bit_value),              SCTP_DATA_CHUNK_I_BIT,              NULL, HFILL } },
3929     { &hf_sack_chunk_ns,                            { "Nounce sum",                                     "sctp.sack_nounce_sum",                                 FT_UINT8,   BASE_DEC,  NULL,                                           SCTP_SACK_CHUNK_NS_BIT,             NULL, HFILL } },
3930     { &hf_sack_chunk_cumulative_tsn_ack,            { "Cumulative TSN ACK",                             "sctp.sack_cumulative_tsn_ack",                         FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3931     { &hf_sack_chunk_adv_rec_window_credit,         { "Advertised receiver window credit (a_rwnd)",     "sctp.sack_a_rwnd",                                     FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3932     { &hf_sack_chunk_number_of_gap_blocks,          { "Number of gap acknowledgement blocks",           "sctp.sack_number_of_gap_blocks",                       FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3933     { &hf_sack_chunk_number_of_dup_tsns,            { "Number of duplicated TSNs",                      "sctp.sack_number_of_duplicated_tsns",                  FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3934     { &hf_sack_chunk_gap_block_start,               { "Start",                                          "sctp.sack_gap_block_start",                            FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3935     { &hf_sack_chunk_gap_block_start_tsn,           { "Start TSN",                                      "sctp.sack_gap_block_start_tsn",                        FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3936     { &hf_sack_chunk_gap_block_end,                 { "End",                                            "sctp.sack_gap_block_end",                              FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3937     { &hf_sack_chunk_gap_block_end_tsn,             { "End TSN",                                        "sctp.sack_gap_block_end_tsn",                          FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3938     { &hf_sack_chunk_number_tsns_gap_acked,         { "Number of TSNs in gap acknowledgement blocks",   "sctp.sack_number_of_tsns_gap_acked",                   FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3939     { &hf_sack_chunk_duplicate_tsn,                 { "Duplicate TSN",                                  "sctp.sack_duplicate_tsn",                              FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3940     { &hf_nr_sack_chunk_ns,                         { "Nounce sum",                                     "sctp.nr_sack_nounce_sum",                              FT_UINT8,   BASE_DEC,  NULL,                                           SCTP_NR_SACK_CHUNK_NS_BIT,             NULL, HFILL } },
3941     { &hf_nr_sack_chunk_cumulative_tsn_ack,         { "Cumulative TSN ACK",                             "sctp.nr_sack_cumulative_tsn_ack",                      FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3942     { &hf_nr_sack_chunk_adv_rec_window_credit,      { "Advertised receiver window credit (a_rwnd)",     "sctp.nr_sack_a_rwnd",                                  FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3943     { &hf_nr_sack_chunk_number_of_gap_blocks,       { "Number of gap acknowledgement blocks",           "sctp.nr_sack_number_of_gap_blocks",                    FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3944     { &hf_nr_sack_chunk_number_of_nr_gap_blocks,    { "Number of nr-gap acknowledgement blocks",        "sctp.nr_sack_number_of_nr_gap_blocks",                 FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3945     { &hf_nr_sack_chunk_number_of_dup_tsns,         { "Number of duplicated TSNs",                      "sctp.nr_sack_number_of_duplicated_tsns",               FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3946     { &hf_nr_sack_chunk_reserved,                   { "Reserved",                                       "sctp.nr_sack_reserved",                                FT_UINT16,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
3947     { &hf_nr_sack_chunk_gap_block_start,            { "Start",                                          "sctp.nr_sack_gap_block_start",                         FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3948     { &hf_nr_sack_chunk_gap_block_start_tsn,        { "Start TSN",                                      "sctp.nr_sack_gap_block_start_tsn",                     FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3949     { &hf_nr_sack_chunk_gap_block_end,              { "End",                                            "sctp.nr_sack_gap_block_end",                           FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3950     { &hf_nr_sack_chunk_gap_block_end_tsn,          { "End TSN",                                        "sctp.nr_sack_gap_block_end_tsn",                       FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3951     { &hf_nr_sack_chunk_number_tsns_gap_acked,      { "Number of TSNs in gap acknowledgement blocks",   "sctp.nr_sack_number_of_tsns_gap_acked",                FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3952     { &hf_nr_sack_chunk_nr_gap_block_start,         { "Start",                                          "sctp.nr_sack_nr_gap_block_start",                      FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3953     { &hf_nr_sack_chunk_nr_gap_block_start_tsn,     { "Start TSN",                                      "sctp.nr_sack_nr_gap_block_start_tsn",                  FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3954     { &hf_nr_sack_chunk_nr_gap_block_end,           { "End",                                            "sctp.nr_sack_nr_gap_block_end",                        FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3955     { &hf_nr_sack_chunk_nr_gap_block_end_tsn,       { "End TSN",                                        "sctp.nr_sack_nr_gap_block_end_tsn",                    FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3956     { &hf_nr_sack_chunk_number_tsns_nr_gap_acked,   { "Number of TSNs in nr-gap acknowledgement blocks","sctp.nr_sack_number_of_tsns_nr_gap_acked",             FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3957     { &hf_nr_sack_chunk_duplicate_tsn,              { "Duplicate TSN",                                  "sctp.nr_sack_duplicate_tsn",                           FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3958     { &hf_shutdown_chunk_cumulative_tsn_ack,        { "Cumulative TSN Ack",                             "sctp.shutdown_cumulative_tsn_ack",                     FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3959     { &hf_ecne_chunk_lowest_tsn,                    { "Lowest TSN",                                     "sctp.ecne_lowest_tsn",                                 FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3960     { &hf_cwr_chunk_lowest_tsn,                     { "Lowest TSN",                                     "sctp.cwr_lowest_tsn",                                  FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3961     { &hf_shutdown_complete_chunk_t_bit,            { "T-Bit",                                          "sctp.shutdown_complete_t_bit",                         FT_BOOLEAN, 8,         TFS(&sctp_shutdown_complete_chunk_t_bit_value), SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT, NULL, HFILL } },
3962     { &hf_abort_chunk_t_bit,                        { "T-Bit",                                          "sctp.abort_t_bit",                                     FT_BOOLEAN, 8,         TFS(&sctp_shutdown_complete_chunk_t_bit_value), SCTP_ABORT_CHUNK_T_BIT,             NULL, HFILL } },
3963     { &hf_forward_tsn_chunk_tsn,                    { "New cumulative TSN",                             "sctp.forward_tsn_tsn",                                 FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3964     { &hf_forward_tsn_chunk_sid,                    { "Stream identifier",                              "sctp.forward_tsn_sid",                                 FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3965     { &hf_forward_tsn_chunk_ssn,                    { "Stream sequence number",                         "sctp.forward_tsn_ssn",                                 FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3966     { &hf_parameter_type,                           { "Parameter type",                                 "sctp.parameter_type",                                  FT_UINT16,  BASE_HEX,  VALS(parameter_identifier_values),              0x0,                                NULL, HFILL } },
3967     { &hf_parameter_length,                         { "Parameter length",                               "sctp.parameter_length",                                FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3968     { &hf_parameter_value,                          { "Parameter value",                                "sctp.parameter_value",                                 FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
3969     { &hf_parameter_padding,                        { "Parameter padding",                              "sctp.parameter_padding",                               FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
3970     { &hf_parameter_bit_1,                          { "Bit",                                            "sctp.parameter_bit_1",                                 FT_BOOLEAN, 16,        TFS(&sctp_parameter_bit_1_value),               SCTP_PARAMETER_BIT_1,               NULL, HFILL } },
3971     { &hf_parameter_bit_2,                          { "Bit",                                            "sctp.parameter_bit_2",                                 FT_BOOLEAN, 16,        TFS(&sctp_parameter_bit_2_value),               SCTP_PARAMETER_BIT_2,               NULL, HFILL } },
3972     { &hf_ipv4_address,                             { "IP Version 4 address",                           "sctp.parameter_ipv4_address",                          FT_IPv4,    BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
3973     { &hf_ipv6_address,                             { "IP Version 6 address",                           "sctp.parameter_ipv6_address",                          FT_IPv6,    BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
3974     { &hf_heartbeat_info,                           { "Heartbeat information",                          "sctp.parameter_heartbeat_information",                 FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
3975     { &hf_state_cookie,                             { "State cookie",                                   "sctp.parameter_state_cookie",                          FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
3976     { &hf_cookie_preservative_increment,            { "Suggested Cookie life-span increment (msec)",    "sctp.parameter_cookie_preservative_incr",              FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3977     { &hf_hostname,                                 { "Hostname",                                       "sctp.parameter_hostname",                              FT_STRING,  BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
3978     { &hf_supported_address_type,                   { "Supported address type",                         "sctp.parameter_supported_addres_type",                 FT_UINT16,  BASE_DEC,  VALS(address_types_values),                     0x0,                                NULL, HFILL } },
3979     { &hf_stream_reset_req_seq_nr,                  { "Stream reset request sequence number",           "sctp.parameter_stream_reset_request_sequence_number",  FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3980     { &hf_stream_reset_rsp_seq_nr,                  { "Stream reset response sequence number",          "sctp.parameter_stream_reset_response_sequence_number", FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3981     { &hf_senders_last_assigned_tsn,                { "Senders last assigned TSN",                      "sctp.parameter_senders_last_assigned_tsn",             FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3982     { &hf_senders_next_tsn,                         { "Senders next TSN",                               "sctp.parameter_senders_next_tsn",                      FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3983     { &hf_receivers_next_tsn,                       { "Receivers next TSN",                             "sctp.parameter_receivers_next_tsn",                    FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3984     { &hf_stream_reset_rsp_result,                  { "Result",                                         "sctp.parameter_stream_reset_response_result",          FT_UINT32,  BASE_DEC,  VALS(stream_reset_result_values),               0x0,                                NULL, HFILL } },
3985     { &hf_stream_reset_sid,                         { "Stream Identifier",                              "sctp.parameter_stream_reset_sid",                      FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3986     { &hf_asconf_serial,                            { "Serial number",                                  "sctp.asconf_serial_number",                            FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
3987     { &hf_asconf_ack_serial,                        { "Serial number",                                  "sctp.asconf_ack_serial_number",                        FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
3988     { &hf_correlation_id,                           { "Correlation_id",                                 "sctp.correlation_id",                                  FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
3989     { &hf_adap_indication,                          { "Indication",                                     "sctp.adapation_layer_indication",                      FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
3990     { &hf_random_number,                            { "Random number",                                  "sctp.random_number",                                   FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
3991     { &hf_chunks_to_auth,                           { "Chunk type",                                     "sctp.chunk_type_to_auth",                              FT_UINT8,   BASE_DEC,  VALS(chunk_type_values),                        0x0,                                NULL, HFILL } },
3992     { &hf_hmac_id,                                  { "HMAC identifier",                                "sctp.hmac_id",                                         FT_UINT16,  BASE_DEC,  VALS(hmac_id_values),                           0x0,                                NULL, HFILL } },
3993     { &hf_hmac,                                     { "HMAC",                                           "sctp.hmac",                                            FT_BYTES,   BASE_NONE,  NULL,                                           0x0,                                NULL, HFILL } },
3994     { &hf_shared_key_id,                            { "Shared key identifier",                          "sctp.shared_key_id",                                   FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3995     { &hf_supported_chunk_type,                     { "Supported chunk type",                           "sctp.supported_chunk_type",                            FT_UINT8,   BASE_DEC,  VALS(chunk_type_values),                        0x0,                                NULL, HFILL } },
3996     { &hf_cause_code,                               { "Cause code",                                     "sctp.cause_code",                                      FT_UINT16,  BASE_HEX,  VALS(cause_code_values),                        0x0,                                NULL, HFILL } },
3997     { &hf_cause_length,                             { "Cause length",                                   "sctp.cause_length",                                    FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
3998     { &hf_cause_info,                               { "Cause information",                              "sctp.cause_information",                               FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
3999     { &hf_cause_padding,                            { "Cause padding",                                  "sctp.cause_padding",                                   FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
4000     { &hf_cause_stream_identifier,                  { "Stream identifier",                              "sctp.cause_stream_identifier",                         FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4001     { &hf_cause_reserved,                           { "Reserved",                                       "sctp.cause_reserved",                                  FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4002     { &hf_cause_number_of_missing_parameters,       { "Number of missing parameters",                   "sctp.cause_nr_of_missing_parameters",                  FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4003     { &hf_cause_missing_parameter_type,             { "Missing parameter type",                         "sctp.cause_missing_parameter_type",                    FT_UINT16,  BASE_HEX,  VALS(parameter_identifier_values),              0x0,                                NULL, HFILL } },
4004     { &hf_cause_measure_of_staleness,               { "Measure of staleness in usec",                   "sctp.cause_measure_of_staleness",                      FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4005     { &hf_cause_tsn,                                { "TSN",                                            "sctp.cause_tsn",                                       FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4006     { &hf_pktdrop_chunk_m_bit,                      { "M-Bit",                                          "sctp.pckdrop_m_bit",                                   FT_BOOLEAN, 8,         TFS(&sctp_pktdropk_m_bit_value),                SCTP_PKTDROP_CHUNK_M_BIT,           NULL, HFILL } },
4007     { &hf_pktdrop_chunk_b_bit,                      { "B-Bit",                                          "sctp.pckdrop_b_bit",                                   FT_BOOLEAN, 8,         TFS(&sctp_pktdropk_b_bit_value),                SCTP_PKTDROP_CHUNK_B_BIT,           NULL, HFILL } },
4008     { &hf_pktdrop_chunk_t_bit,                      { "T-Bit",                                          "sctp.pckdrop_t_bit",                                   FT_BOOLEAN, 8,         TFS(&sctp_pktdropk_t_bit_value),                SCTP_PKTDROP_CHUNK_T_BIT,           NULL, HFILL } },
4009     { &hf_pktdrop_chunk_bandwidth,                  { "Bandwidth",                                      "sctp.pktdrop_bandwidth",                               FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4010     { &hf_pktdrop_chunk_queuesize,                  { "Queuesize",                                      "sctp.pktdrop_queuesize",                               FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4011     { &hf_pktdrop_chunk_truncated_length,           { "Truncated length",                               "sctp.pktdrop_truncated_length",                        FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4012     { &hf_pktdrop_chunk_reserved,                   { "Reserved",                                       "sctp.pktdrop_reserved",                                FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
4013     { &hf_pktdrop_chunk_data_field,                 { "Data field",                                     "sctp.pktdrop_datafield",                               FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
4014
4015     { &hf_sctp_fragment,                            { "SCTP Fragment",                                  "sctp.fragment",                                        FT_FRAMENUM, BASE_NONE, NULL,                                          0x0,                                NULL, HFILL } },
4016     { &hf_sctp_fragments,                           { "Reassembled SCTP Fragments",                     "sctp.fragments",                                       FT_NONE,    BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
4017     { &hf_sctp_reassembled_in,                      { "Reassembled Message in frame",                   "sctp.reassembled_in",                                  FT_FRAMENUM, BASE_NONE, NULL,                                          0x0,                                NULL, HFILL } },
4018     { &hf_sctp_duplicate,                           { "Fragment already seen in frame",                 "sctp.duplicate",                                       FT_FRAMENUM, BASE_NONE, NULL,                                          0x0,                                NULL, HFILL } },
4019
4020     { &hf_sctp_rtt,                                 { "The RTT to ACK the chunk was",                   "sctp.rtt",                                             FT_RELATIVE_TIME, BASE_NONE, NULL,                                      0x0,                                NULL, HFILL } },
4021     { &hf_sctp_rto,                                 { "Retransmitted after",                            "sctp.retransmission_time",                             FT_RELATIVE_TIME, BASE_NONE, NULL,                                      0x0,                                NULL, HFILL } },
4022     { &hf_sctp_retransmission,                      { "This TSN is a retransmission of one in frame",   "sctp.retransmission",                                  FT_FRAMENUM, BASE_NONE, NULL,                                          0x0,                                NULL, HFILL } },
4023     { &hf_sctp_retransmitted,                       { "This TSN is retransmitted in frame",             "sctp.retransmitted",                                   FT_FRAMENUM, BASE_NONE, NULL,                                          0x0,                                NULL, HFILL } },
4024     { &hf_sctp_retransmitted_count,                 { "TSN was retransmitted this many times",          "sctp.retransmitted_count",                             FT_UINT32, BASE_DEC, NULL,                                             0x0,                                NULL, HFILL } },
4025     { &hf_sctp_acked,                               { "This chunk is acked in frame",                   "sctp.acked",                                           FT_FRAMENUM, BASE_NONE, NULL,                                          0x0,                                NULL, HFILL } },
4026     { &hf_sctp_ack_tsn,                             { "Acknowledges TSN",                               "sctp.ack",                                             FT_UINT32, BASE_DEC, NULL,                                             0x0,                                NULL, HFILL } },
4027     { &hf_sctp_ack_frame,                           { "Chunk acknowledged in frame",                    "sctp.ack_frame",                                       FT_FRAMENUM, BASE_NONE, NULL,                                          0x0,                                NULL, HFILL } },
4028     { &hf_sctp_retransmitted_after_ack,             { "Chunk was acked prior to retransmission",        "sctp.retransmitted_after_ack",                         FT_FRAMENUM, BASE_NONE, NULL,                                          0x0,                                NULL, HFILL } }
4029
4030  };
4031
4032   /* Setup protocol subtree array */
4033   static gint *ett[] = {
4034     &ett_sctp,
4035     &ett_sctp_chunk,
4036     &ett_sctp_chunk_parameter,
4037     &ett_sctp_chunk_cause,
4038     &ett_sctp_chunk_type,
4039     &ett_sctp_data_chunk_flags,
4040     &ett_sctp_sack_chunk_flags,
4041     &ett_sctp_nr_sack_chunk_flags,
4042     &ett_sctp_abort_chunk_flags,
4043     &ett_sctp_shutdown_complete_chunk_flags,
4044     &ett_sctp_pktdrop_chunk_flags,
4045     &ett_sctp_parameter_type,
4046     &ett_sctp_sack_chunk_gap_block,
4047     &ett_sctp_sack_chunk_gap_block_start,
4048     &ett_sctp_sack_chunk_gap_block_end,
4049     &ett_sctp_nr_sack_chunk_gap_block,
4050     &ett_sctp_nr_sack_chunk_gap_block_start,
4051     &ett_sctp_nr_sack_chunk_gap_block_end,
4052     &ett_sctp_nr_sack_chunk_nr_gap_block,    
4053     &ett_sctp_nr_sack_chunk_nr_gap_block_start,
4054     &ett_sctp_nr_sack_chunk_nr_gap_block_end,
4055     &ett_sctp_unrecognized_parameter_parameter,
4056     &ett_sctp_fragments,
4057     &ett_sctp_fragment,
4058     &ett_sctp_ack,
4059     &ett_sctp_acked,
4060     &ett_sctp_tsn,
4061     &ett_sctp_tsn_retransmission,
4062     &ett_sctp_tsn_retransmitted_count,
4063     &ett_sctp_tsn_retransmitted
4064   };
4065
4066   static enum_val_t sctp_checksum_options[] = {
4067     { "none",      "None",        SCTP_CHECKSUM_NONE },
4068     { "adler-32",  "Adler 32",    SCTP_CHECKSUM_ADLER32 },
4069     { "crc-32c",   "CRC 32c",     SCTP_CHECKSUM_CRC32C },
4070     { "automatic", "Automatic",   SCTP_CHECKSUM_AUTOMATIC},
4071     { NULL, NULL, 0 }
4072   };
4073
4074   /* Register the protocol name and description */
4075   proto_sctp = proto_register_protocol("Stream Control Transmission Protocol", "SCTP", "sctp");
4076   sctp_module = prefs_register_protocol(proto_sctp, NULL);
4077   prefs_register_bool_preference(sctp_module, "show_port_numbers_in_tree",
4078                          "Show port numbers in the protocol tree",
4079                          "Show source and destination port numbers in the protocol tree",
4080                          &show_port_numbers);
4081   /* FIXME
4082   prefs_register_bool_preference(sctp_module, "show_chunk_types_in_tree",
4083                          "Show chunk types in the protocol tree",
4084                          "Show chunk types in the protocol tree",
4085                          &show_chunk_types);
4086   */
4087   prefs_register_enum_preference(sctp_module, "checksum", "Checksum type",
4088                          "The type of checksum used in SCTP packets",
4089                          &sctp_checksum, sctp_checksum_options, FALSE);
4090   prefs_register_bool_preference(sctp_module, "show_always_control_chunks",
4091                          "Show always control chunks",
4092                          "Show always SCTP control chunks in the Info column",
4093                          &show_always_control_chunks);
4094   prefs_register_bool_preference(sctp_module, "try_heuristic_first",
4095                          "Try heuristic sub-dissectors first",
4096                          "Try to decode a packet using an heuristic sub-dissector before using a sub-dissector registered to a specific port or PPI",
4097                          &try_heuristic_first);
4098   prefs_register_bool_preference(sctp_module, "reassembly",
4099                          "Reassemble fragmented SCTP user messages",
4100                          "Whether fragmented SCTP user messages should be reassembled",
4101                          &use_reassembly);
4102   prefs_register_bool_preference(sctp_module, "tsn_analysis",
4103                          "Enable TSN analysis",
4104                          "Match TSNs and their SACKs",
4105                          &enable_tsn_analysis);
4106   prefs_register_bool_preference(sctp_module, "ulp_dissection",
4107                          "Dissect upper layer protocols",
4108                          "Dissect upper layer protocols",
4109                          &enable_ulp_dissection);
4110
4111   /* Required function calls to register the header fields and subtrees used */
4112   proto_register_field_array(proto_sctp, hf, array_length(hf));
4113   proto_register_subtree_array(ett, array_length(ett));
4114   sctp_tap = register_tap("sctp");
4115   /* subdissector code */
4116   sctp_port_dissector_table = register_dissector_table("sctp.port", "SCTP port", FT_UINT16, BASE_DEC);
4117   sctp_ppi_dissector_table  = register_dissector_table("sctp.ppi",  "SCTP payload protocol identifier", FT_UINT32, BASE_HEX);
4118
4119   register_dissector("sctp", dissect_sctp, proto_sctp);
4120   register_heur_dissector_list("sctp", &sctp_heur_subdissector_list);
4121
4122   register_init_routine(frag_table_init);
4123
4124   dirs_by_ptvtag = se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "sctp_dirs_by_ptvtag");
4125   dirs_by_ptaddr = se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "sctp_dirs_by_ptaddr");
4126 }
4127
4128 void
4129 proto_reg_handoff_sctp(void)
4130 {
4131   dissector_handle_t sctp_handle;
4132
4133   data_handle = find_dissector("data");
4134   sctp_handle = find_dissector("sctp");
4135   dissector_add("ip.proto", IP_PROTO_SCTP, sctp_handle);
4136   dissector_add("udp.port", UDP_TUNNELING_PORT, sctp_handle);
4137 }