add details for doxygen, various code cleanups as a result of this
[obnox/wireshark/wip.git] / packet-sctp.c
1 /* packet-sctp.c
2  * Routines for Stream Control Transmission Protocol dissection
3  * It should be compilant to
4  * - RFC 2960
5  * - RFC 3309
6  * - http://www.ietf.org/internet-drafts/draft-ietf-tsvwg-sctpimpguide-09.txt
7  * - http://www.ietf.org/internet-drafts/draft-ietf-tsvwg-addip-sctp-08.txt for the add-IP extension
8  * - http://www.ietf.org/internet-drafts/draft-stewart-tsvwg-prsctp-04.txt for the 'Partial Reliability' extension
9  * - another upcoming ID on packetdrop stuff.
10  * Copyright 2000, 2001, 2002, 2003, 2004 Michael Tuexen <tuexen [AT] fh-muenster.de>
11  * Still to do (so stay tuned)
12  * - support for reassembly
13  * - error checking mode
14  *   * padding errors
15  *   * length errors
16  *   * bundling errors
17  *   * value errors
18  *
19  * $Id: packet-sctp.c,v 1.72 2004/05/24 02:25:19 guy Exp $
20  *
21  * Ethereal - Network traffic analyzer
22  * By Gerald Combs <gerald@ethereal.com>
23  * Copyright 1998 Gerald Combs
24  *
25  * Copied from README.developer
26  *
27  * This program is free software; you can redistribute it and/or
28  * modify it under the terms of the GNU General Public License
29  * as published by the Free Software Foundation; either version 2
30  * of the License, or (at your option) any later version.
31  *
32  * This program is distributed in the hope that it will be useful,
33  * but WITHOUT ANY WARRANTY; without even the implied warranty of
34  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
35  * GNU General Public License for more details.
36  *
37  * You should have received a copy of the GNU General Public License
38  * along with this program; if not, write to the Free Software
39  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
40  */
41
42 #ifdef HAVE_CONFIG_H
43 # include "config.h"
44 #endif
45
46 #include <string.h>
47 #include "prefs.h"
48 #include <epan/packet.h>
49 #include "tap.h"
50 #include "ipproto.h"
51 #include "packet-sctp.h"
52 #include "sctpppids.h"
53
54 #define NETWORK_BYTE_ORDER     FALSE
55 #define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
56 #define UDP_TUNNELING_PORT 9899
57
58 /* Initialize the protocol and registered fields */
59 static int proto_sctp = -1;
60 static int hf_port = -1;
61 static int hf_source_port      = -1;
62 static int hf_destination_port = -1;
63 static int hf_verification_tag = -1;
64 static int hf_checksum         = -1;
65 static int hf_checksum_bad     = -1;
66
67 static int hf_chunk_type       = -1;
68 static int hf_chunk_flags      = -1;
69 static int hf_chunk_bit_1      = -1;
70 static int hf_chunk_bit_2      = -1;
71 static int hf_chunk_length     = -1;
72 static int hf_chunk_padding    = -1;
73 static int hf_chunk_value    = -1;
74
75 static int hf_initiate_tag   = -1;
76 static int hf_init_chunk_initiate_tag   = -1;
77 static int hf_init_chunk_adv_rec_window_credit = -1;
78 static int hf_init_chunk_number_of_outbound_streams = -1;
79 static int hf_init_chunk_number_of_inbound_streams  = -1;
80 static int hf_init_chunk_initial_tsn    = -1;
81
82 static int hf_initack_chunk_initiate_tag   = -1;
83 static int hf_initack_chunk_adv_rec_window_credit = -1;
84 static int hf_initack_chunk_number_of_outbound_streams = -1;
85 static int hf_initack_chunk_number_of_inbound_streams  = -1;
86 static int hf_initack_chunk_initial_tsn    = -1;
87
88 static int hf_cumulative_tsn_ack = -1;
89
90 static int hf_data_chunk_tsn = -1;
91 static int hf_data_chunk_stream_id = -1;
92 static int hf_data_chunk_stream_seq_number = -1;
93 static int hf_data_chunk_payload_proto_id = -1;
94
95 static int hf_data_chunk_e_bit = -1;
96 static int hf_data_chunk_b_bit = -1;
97 static int hf_data_chunk_u_bit = -1;
98
99 static int hf_sack_chunk_cumulative_tsn_ack = -1;
100 static int hf_sack_chunk_adv_rec_window_credit = -1;
101 static int hf_sack_chunk_number_of_gap_blocks = -1;
102 static int hf_sack_chunk_number_of_dup_tsns = -1;
103 static int hf_sack_chunk_gap_block_start = -1;
104 static int hf_sack_chunk_gap_block_end = -1;
105 static int hf_sack_chunk_duplicate_tsn = -1;
106
107 static int hf_shutdown_chunk_cumulative_tsn_ack = -1;
108 static int hf_cookie = -1;
109 static int hf_cwr_chunk_lowest_tsn = -1;
110
111 static int hf_ecne_chunk_lowest_tsn = -1;
112 static int hf_abort_chunk_t_bit = -1;
113 static int hf_shutdown_complete_chunk_t_bit = -1;
114
115 static int hf_parameter_type = -1;
116 static int hf_parameter_length = -1;
117 static int hf_parameter_value = -1;
118 static int hf_parameter_padding = -1;
119 static int hf_parameter_bit_1      = -1;
120 static int hf_parameter_bit_2      = -1;
121 static int hf_ipv4_address = -1;
122 static int hf_ipv6_address = -1;
123 static int hf_heartbeat_info = -1;
124 static int hf_state_cookie = -1;
125 static int hf_cookie_preservative_increment = -1;
126 static int hf_hostname = -1;
127 static int hf_supported_address_type = -1;
128
129 static int hf_cause_code = -1;
130 static int hf_cause_length = -1;
131 static int hf_cause_padding = -1;
132 static int hf_cause_info = -1;
133
134 static int hf_cause_stream_identifier = -1;
135 static int hf_cause_reserved = -1;
136
137 static int hf_cause_number_of_missing_parameters = -1;
138 static int hf_cause_missing_parameter_type = -1;
139
140 static int hf_cause_measure_of_staleness = -1;
141
142 static int hf_cause_tsn = -1;
143
144 static int hf_forward_tsn_chunk_tsn = -1;
145 static int hf_forward_tsn_chunk_sid = -1;
146 static int hf_forward_tsn_chunk_ssn = -1;
147
148 static int hf_asconf_ack_serial = -1;
149 static int hf_asconf_serial = -1;
150 static int hf_correlation_id = -1;
151
152 static int hf_adap_indication = -1;
153
154 static int hf_pktdrop_chunk_m_bit = -1;
155 /*
156 static int hf_pktdrop_chunk_s_bit = -1;
157 */
158 static int hf_pktdrop_chunk_b_bit = -1;
159 static int hf_pktdrop_chunk_t_bit = -1;
160 static int hf_pktdrop_chunk_bandwidth = -1;
161 static int hf_pktdrop_chunk_queuesize = -1;
162 static int hf_pktdrop_chunk_truncated_length = -1;
163 static int hf_pktdrop_chunk_reserved = -1;
164 static int hf_pktdrop_chunk_data_field = -1;
165
166 static dissector_table_t sctp_port_dissector_table;
167 static dissector_table_t sctp_ppi_dissector_table;
168 static heur_dissector_list_t sctp_heur_subdissector_list;
169 static int sctp_tap = -1;
170 static module_t *sctp_module;
171
172 /* Initialize the subtree pointers */
173 static gint ett_sctp = -1;
174 static gint ett_sctp_chunk = -1;
175 static gint ett_sctp_chunk_parameter = -1;
176 static gint ett_sctp_chunk_cause = -1;
177 static gint ett_sctp_chunk_type = -1;
178 static gint ett_sctp_data_chunk_flags = -1;
179 static gint ett_sctp_abort_chunk_flags = -1;
180 static gint ett_sctp_shutdown_complete_chunk_flags = -1;
181 static gint ett_sctp_pktdrop_chunk_flags = -1;
182 static gint ett_sctp_parameter_type= -1;
183 static gint ett_sctp_sack_chunk_gap_block = -1;
184 static gint ett_sctp_unrecognized_parameter_parameter = -1;
185
186 static dissector_handle_t data_handle;
187
188 #define SCTP_DATA_CHUNK_ID               0
189 #define SCTP_INIT_CHUNK_ID               1
190 #define SCTP_INIT_ACK_CHUNK_ID           2
191 #define SCTP_SACK_CHUNK_ID               3
192 #define SCTP_HEARTBEAT_CHUNK_ID          4
193 #define SCTP_HEARTBEAT_ACK_CHUNK_ID      5
194 #define SCTP_ABORT_CHUNK_ID              6
195 #define SCTP_SHUTDOWN_CHUNK_ID           7
196 #define SCTP_SHUTDOWN_ACK_CHUNK_ID       8
197 #define SCTP_ERROR_CHUNK_ID              9
198 #define SCTP_COOKIE_ECHO_CHUNK_ID       10
199 #define SCTP_COOKIE_ACK_CHUNK_ID        11
200 #define SCTP_ECNE_CHUNK_ID              12
201 #define SCTP_CWR_CHUNK_ID               13
202 #define SCTP_SHUTDOWN_COMPLETE_CHUNK_ID 14
203 #define SCTP_FORWARD_TSN_CHUNK_ID      192
204 #define SCTP_ASCONF_ACK_CHUNK_ID      0x80
205 #define SCTP_PKTDROP_CHUNK_ID         0X81
206 #define SCTP_ASCONF_CHUNK_ID          0XC1
207 #define SCTP_IETF_EXT                  255
208
209 static const value_string chunk_type_values[] = {
210   { SCTP_DATA_CHUNK_ID,              "DATA" },
211   { SCTP_INIT_CHUNK_ID,              "INIT" },
212   { SCTP_INIT_ACK_CHUNK_ID,          "INIT_ACK" },
213   { SCTP_SACK_CHUNK_ID,              "SACK" },
214   { SCTP_HEARTBEAT_CHUNK_ID,         "HEARTBEAT" },
215   { SCTP_HEARTBEAT_ACK_CHUNK_ID,     "HEARTBEAT_ACK" },
216   { SCTP_ABORT_CHUNK_ID,             "ABORT" },
217   { SCTP_SHUTDOWN_CHUNK_ID,          "SHUTDOWN" },
218   { SCTP_SHUTDOWN_ACK_CHUNK_ID,      "SHUTDOWN_ACK" },
219   { SCTP_ERROR_CHUNK_ID,             "ERROR" },
220   { SCTP_COOKIE_ECHO_CHUNK_ID,       "COOKIE_ECHO" },
221   { SCTP_COOKIE_ACK_CHUNK_ID,        "COOKIE_ACK" },
222   { SCTP_ECNE_CHUNK_ID,              "ECNE" },
223   { SCTP_CWR_CHUNK_ID,               "CWR" },
224   { SCTP_SHUTDOWN_COMPLETE_CHUNK_ID, "SHUTDOWN_COMPLETE" },
225   { SCTP_FORWARD_TSN_CHUNK_ID,       "FORWARD TSN" },
226   { SCTP_ASCONF_ACK_CHUNK_ID,        "ASCONF_ACK" },
227   { SCTP_PKTDROP_CHUNK_ID,           "PKTDROP" },
228   { SCTP_ASCONF_CHUNK_ID,            "ASCONF" },
229   { SCTP_IETF_EXT,                   "IETF_EXTENSION" },
230   { 0,                               NULL } };
231
232 static const value_string sctp_payload_proto_id_values[] = {
233   { NOT_SPECIFIED_PROTOCOL_ID,           "not specified" },
234   { IUA_PAYLOAD_PROTOCOL_ID,             "IUA" },
235   { M2UA_PAYLOAD_PROTOCOL_ID,            "M2UA" },
236   { M3UA_PAYLOAD_PROTOCOL_ID,            "M3UA" },
237   { SUA_PAYLOAD_PROTOCOL_ID,             "SUA" },
238   { M2PA_PAYLOAD_PROTOCOL_ID,            "M2PA" },
239   { V5UA_PAYLOAD_PROTOCOL_ID,            "V5UA" },
240   { H248_PAYLOAD_PROTOCOL_ID,            "H.248/MEGACO" },
241   { BICC_PAYLOAD_PROTOCOL_ID,            "BICC/Q.2150.3" },
242   { TALI_PAYLOAD_PROTOCOL_ID,            "TALI" },
243   { DUA_PAYLOAD_PROTOCOL_ID,             "DUA" },
244   { ASAP_PAYLOAD_PROTOCOL_ID,            "ASAP" },
245   { ENRP_PAYLOAD_PROTOCOL_ID,            "ENRP" },
246   { H323_PAYLOAD_PROTOCOL_ID,            "H.323" },
247   { 0,                                   NULL } };
248
249
250 #define CHUNK_TYPE_LENGTH             1
251 #define CHUNK_FLAGS_LENGTH            1
252 #define CHUNK_LENGTH_LENGTH           2
253 #define CHUNK_HEADER_LENGTH           (CHUNK_TYPE_LENGTH + \
254                                        CHUNK_FLAGS_LENGTH + \
255                                        CHUNK_LENGTH_LENGTH)
256 #define CHUNK_HEADER_OFFSET           0
257 #define CHUNK_TYPE_OFFSET             CHUNK_HEADER_OFFSET
258 #define CHUNK_FLAGS_OFFSET            (CHUNK_TYPE_OFFSET + CHUNK_TYPE_LENGTH)
259 #define CHUNK_LENGTH_OFFSET           (CHUNK_FLAGS_OFFSET + CHUNK_FLAGS_LENGTH)
260 #define CHUNK_VALUE_OFFSET            (CHUNK_LENGTH_OFFSET + CHUNK_LENGTH_LENGTH)
261
262 #define PARAMETER_TYPE_LENGTH            2
263 #define PARAMETER_LENGTH_LENGTH          2
264 #define PARAMETER_HEADER_LENGTH          (PARAMETER_TYPE_LENGTH + PARAMETER_LENGTH_LENGTH)
265
266 #define PARAMETER_HEADER_OFFSET          0
267 #define PARAMETER_TYPE_OFFSET            PARAMETER_HEADER_OFFSET
268 #define PARAMETER_LENGTH_OFFSET          (PARAMETER_TYPE_OFFSET + PARAMETER_TYPE_LENGTH)
269 #define PARAMETER_VALUE_OFFSET           (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
270
271 #define SOURCE_PORT_LENGTH      2
272 #define DESTINATION_PORT_LENGTH 2
273 #define VERIFICATION_TAG_LENGTH 4
274 #define CHECKSUM_LENGTH         4
275 #define COMMON_HEADER_LENGTH    (SOURCE_PORT_LENGTH + \
276                                  DESTINATION_PORT_LENGTH + \
277                                  VERIFICATION_TAG_LENGTH + \
278                                  CHECKSUM_LENGTH)
279 #define SOURCE_PORT_OFFSET      0
280 #define DESTINATION_PORT_OFFSET (SOURCE_PORT_OFFSET + SOURCE_PORT_LENGTH)
281 #define VERIFICATION_TAG_OFFSET (DESTINATION_PORT_OFFSET + DESTINATION_PORT_LENGTH)
282 #define CHECKSUM_OFFSET         (VERIFICATION_TAG_OFFSET + VERIFICATION_TAG_LENGTH)
283
284 #define SCTP_CHECKSUM_NONE      0
285 #define SCTP_CHECKSUM_ADLER32   1
286 #define SCTP_CHECKSUM_CRC32C    2
287 #define SCTP_CHECKSUM_AUTOMATIC 3
288
289 static gboolean show_always_control_chunks = TRUE;
290 static gint sctp_checksum = SCTP_CHECKSUM_CRC32C;
291 static struct _sctp_info sctp_info;
292
293 /* adler32.c -- compute the Adler-32 checksum of a data stream
294  * Copyright (C) 1995-1996 Mark Adler
295  * For conditions of distribution and use, see copyright notice in zlib.h
296  * available, e.g. from  http://www.cdrom.com/pub/infozip/zlib/
297  *
298  * It was modified for the use in this dissector.
299  */
300
301 #define BASE 65521L /* largest prime smaller than 65536      */
302 #define NMAX 5540   /* NMAX is the largest n - 12 such that  */
303         /* 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
304
305 #define DO1(buf,i)  {s1 += buf[i]; s2 += s1;}
306 #define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
307 #define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
308 #define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
309 #define DO16(buf)   DO8(buf,0); DO8(buf,8);
310
311 static unsigned int
312 sctp_adler32(const unsigned char* buf, unsigned int len)
313 {
314     unsigned int s1 = 1L;
315     unsigned int s2 = 0L;
316     int k;
317
318     /* handle the first 8 bytes of the datagram */
319     DO8(buf,0);
320     buf += SOURCE_PORT_LENGTH +
321            DESTINATION_PORT_LENGTH +
322            VERIFICATION_TAG_LENGTH;
323
324     /* handle four 0 bytes as checksum */
325     s2  += CHECKSUM_LENGTH * s1;
326     buf += CHECKSUM_LENGTH;
327
328     /* now we have 12 bytes handled */
329     len -= COMMON_HEADER_LENGTH;
330
331     /* handle the rest of the datagram */
332     while (len > 0) {
333         k = len < NMAX ? len : NMAX;
334         len -= k;
335         while (k >= 16) {
336             DO16(buf);
337             buf += 16;
338             k -= 16;
339         }
340         if (k != 0) do {
341             s1 += *buf++;
342             s2 += s1;
343         } while (--k);
344         s1 %= BASE;
345         s2 %= BASE;
346     }
347     return (s2 << 16) | s1;
348 }
349
350 /* The CRC32C code is taken from draft-ietf-tsvwg-sctpcsum-01.txt.
351  * That code is copyrighted by D. Otis and has been modified.
352  *
353  * Polynomial is
354  *
355  *      x^32 + x^28 + x^27 + x^26 + x^25 + x^23 + x^22 + x^20 + x^19 +
356  *          x^18 + x^14 + x^13 + x^11 + x^10 + x^9 + x^8 + x^6 + 1
357  *
358  * Note that this is not the AUTODIN/HDLC/802.x CRC - it uses a different
359  * polynomial.
360  */
361
362 #define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
363 static guint32 crc_c[256] =
364 {
365 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
366 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
367 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
368 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
369 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
370 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
371 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
372 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
373 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
374 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
375 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
376 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
377 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
378 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
379 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
380 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
381 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
382 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
383 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
384 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
385 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
386 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
387 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
388 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
389 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
390 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
391 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
392 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
393 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
394 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
395 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
396 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
397 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
398 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
399 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
400 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
401 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
402 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
403 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
404 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
405 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
406 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
407 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
408 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
409 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
410 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
411 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
412 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
413 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
414 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
415 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
416 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
417 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
418 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
419 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
420 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
421 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
422 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
423 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
424 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
425 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
426 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
427 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
428 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L,
429 };
430
431 static guint32
432 sctp_crc32c(const unsigned char* buf, unsigned int len)
433 {
434   unsigned int i;
435   guint32 crc32 = ~0L;
436   guint32 result;
437   unsigned char byte0,byte1,byte2,byte3;
438
439   for (i = 0; i < SOURCE_PORT_LENGTH + DESTINATION_PORT_LENGTH + VERIFICATION_TAG_LENGTH; i++)
440   {
441     CRC32C(crc32, buf[i]);
442   }
443   CRC32C(crc32, 0);
444   CRC32C(crc32, 0);
445   CRC32C(crc32, 0);
446   CRC32C(crc32, 0);
447   for (i = COMMON_HEADER_LENGTH; i < len; i++)
448   {
449     CRC32C(crc32, buf[i]);
450   }
451   result = ~crc32;
452
453   byte0 = result & 0xff;
454   byte1 = (result>>8) & 0xff;
455   byte2 = (result>>16) & 0xff;
456   byte3 = (result>>24) & 0xff;
457   crc32 = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
458   return ( crc32 );
459 }
460
461 /*
462  * Routines for dissecting parameters
463  */
464
465 static void
466 dissect_parameter(tvbuff_t *, packet_info *, proto_tree *, proto_item *, gboolean);
467
468 static void
469 dissect_parameters(tvbuff_t *, packet_info *, proto_tree *, proto_item *, gboolean);
470
471 static void
472 dissect_error_cause(tvbuff_t *, packet_info *, proto_tree *);
473
474 static void
475 dissect_error_causes(tvbuff_t *, packet_info *, proto_tree *);
476
477 static gboolean
478 dissect_sctp_chunk(tvbuff_t *, packet_info *, proto_tree *, proto_tree *, gboolean);
479
480 static void
481 dissect_sctp_packet(tvbuff_t *, packet_info *, proto_tree *, gboolean);
482
483
484
485 #define HEARTBEAT_INFO_PARAMETER_INFO_OFFSET PARAMETER_VALUE_OFFSET
486
487 static void
488 dissect_heartbeat_info_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
489 {
490   guint16 heartbeat_info_length;
491   
492   heartbeat_info_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
493   if (heartbeat_info_length > 0)
494     proto_tree_add_item(parameter_tree, hf_heartbeat_info, parameter_tvb, HEARTBEAT_INFO_PARAMETER_INFO_OFFSET, heartbeat_info_length, NETWORK_BYTE_ORDER);
495   proto_item_append_text(parameter_item, " (Information: %u byte%s)", heartbeat_info_length, plurality(heartbeat_info_length, "", "s"));
496 }
497
498 #define IPV4_ADDRESS_LENGTH 4
499 #define IPV4_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
500
501 static void
502 dissect_ipv4_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item, proto_item *additional_item, gboolean dissecting_init_init_ack_chunk)
503 {
504   proto_tree_add_item(parameter_tree, hf_ipv4_address, parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH, NETWORK_BYTE_ORDER);
505   proto_item_append_text(parameter_item, " (Address: %s)", ip_to_str((const guint8 *)tvb_get_ptr(parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH)));
506   if (additional_item)
507       proto_item_append_text(additional_item, "%s", ip_to_str((const guint8 *)tvb_get_ptr(parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH)));
508   if (dissecting_init_init_ack_chunk) {
509           if (sctp_info.number_of_tvbs < MAXIMUM_NUMBER_OF_TVBS)
510         sctp_info.tvb[sctp_info.number_of_tvbs++] = parameter_tvb;
511       else
512         sctp_info.incomplete = TRUE;
513   }
514 }
515
516 #define IPV6_ADDRESS_LENGTH 16
517 #define IPV6_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
518
519 static void
520 dissect_ipv6_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item, proto_item *additional_item, gboolean dissecting_init_init_ack_chunk)
521 {
522   proto_tree_add_item(parameter_tree, hf_ipv6_address, parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH, NETWORK_BYTE_ORDER);
523   proto_item_append_text(parameter_item, " (Address: %s)", ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH)));
524   if (additional_item)
525     proto_item_append_text(additional_item, "%s", ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH)));
526   if (dissecting_init_init_ack_chunk) {
527         if (sctp_info.number_of_tvbs < MAXIMUM_NUMBER_OF_TVBS)
528       sctp_info.tvb[sctp_info.number_of_tvbs++] = parameter_tvb;
529     else
530       sctp_info.incomplete = TRUE;
531   }
532 }
533
534 #define STATE_COOKIE_PARAMETER_COOKIE_OFFSET   PARAMETER_VALUE_OFFSET
535
536 static void
537 dissect_state_cookie_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
538 {
539   guint16 state_cookie_length;
540
541   state_cookie_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
542   if (state_cookie_length > 0)
543     proto_tree_add_item(parameter_tree, hf_state_cookie, parameter_tvb, STATE_COOKIE_PARAMETER_COOKIE_OFFSET, state_cookie_length, NETWORK_BYTE_ORDER);
544   proto_item_append_text(parameter_item, " (Cookie length: %u byte%s)", state_cookie_length, plurality(state_cookie_length, "", "s"));
545 }
546
547 static void
548 dissect_unrecognized_parameters_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
549 {
550   /* FIXME: Does it contain one or more parameters? */
551   dissect_parameter(tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, -1, -1), pinfo, parameter_tree, NULL, FALSE);
552 }
553
554 #define COOKIE_PRESERVATIVE_PARAMETER_INCR_LENGTH 4
555 #define COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET PARAMETER_VALUE_OFFSET
556
557 static void
558 dissect_cookie_preservative_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
559 {
560   proto_tree_add_item(parameter_tree, hf_cookie_preservative_increment, parameter_tvb, COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET, COOKIE_PRESERVATIVE_PARAMETER_INCR_LENGTH, NETWORK_BYTE_ORDER);
561   proto_item_append_text(parameter_item, " (Increment :%u msec)", tvb_get_ntohl(parameter_tvb, COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET));
562 }
563
564 #define HOSTNAME_OFFSET PARAMETER_VALUE_OFFSET
565
566 static void
567 dissect_hostname_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
568 {
569   guint16 hostname_length;
570
571   hostname_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
572   proto_tree_add_item(parameter_tree, hf_hostname, parameter_tvb, HOSTNAME_OFFSET, hostname_length, NETWORK_BYTE_ORDER);
573   proto_item_append_text(parameter_item, " (Hostname: %.*s)", hostname_length, (const char *)tvb_get_ptr(parameter_tvb, HOSTNAME_OFFSET, hostname_length));
574
575 }
576
577 #define IPv4_ADDRESS_TYPE      5
578 #define IPv6_ADDRESS_TYPE      6
579 #define HOSTNAME_ADDRESS_TYPE 11
580
581 static const value_string address_types_values[] = {
582   {  IPv4_ADDRESS_TYPE,    "IPv4 address"     },
583   {  IPv6_ADDRESS_TYPE,    "IPv6 address"     },
584   { HOSTNAME_ADDRESS_TYPE, "Hostname address" },
585   {  0, NULL               }
586 };
587
588 #define SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH 2
589
590 static void
591 dissect_supported_address_types_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
592 {
593   guint16 address_type, number_of_address_types, address_type_number;
594   guint offset;
595
596   number_of_address_types = (tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH)
597                             / SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH;
598
599   offset = PARAMETER_VALUE_OFFSET;
600   proto_item_append_text(parameter_item, " (Supported types: ");
601   for(address_type_number = 1; address_type_number <= number_of_address_types; address_type_number++) {
602     proto_tree_add_item(parameter_tree, hf_supported_address_type, parameter_tvb, offset, SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH, NETWORK_BYTE_ORDER);
603     address_type = tvb_get_ntohs(parameter_tvb, offset);
604     switch (address_type) {
605       case IPv4_ADDRESS_TYPE:
606         proto_item_append_text(parameter_item, "IPv4");
607         break;
608       case IPv6_ADDRESS_TYPE:
609         proto_item_append_text(parameter_item, "IPv6");
610         break;
611       case HOSTNAME_ADDRESS_TYPE:
612         proto_item_append_text(parameter_item, "hostname");
613         break;
614       default:
615         proto_item_append_text(parameter_item, "%u", address_type);
616     }
617     if (address_type_number < number_of_address_types)
618       proto_item_append_text(parameter_item, ", ");
619     offset += SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH;
620   };
621   proto_item_append_text(parameter_item, ")");
622 }
623
624 static void
625 dissect_ecn_parameter(tvbuff_t *parameter_tvb _U_)
626 {
627 }
628
629 static void
630 dissect_forward_tsn_supported_parameter(tvbuff_t *parameter_tvb _U_)
631 {
632 }
633
634 #define CORRELATION_ID_LENGTH    4
635 #define CORRELATION_ID_OFFSET    PARAMETER_VALUE_OFFSET
636 #define ADDRESS_PARAMETER_OFFSET (CORRELATION_ID_OFFSET + CORRELATION_ID_LENGTH)
637
638 static void
639 dissect_add_ip_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
640 {
641   guint16 address_length;
642   tvbuff_t *address_tvb;
643
644   address_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
645   
646   proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
647   address_tvb    =  tvb_new_subset(parameter_tvb, ADDRESS_PARAMETER_OFFSET, address_length, address_length);
648   proto_item_append_text(parameter_item, " (Address: ");
649   dissect_parameter(address_tvb, pinfo, parameter_tree, parameter_item, FALSE);
650   proto_item_append_text(parameter_item, ", correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
651 }
652
653 static void
654 dissect_del_ip_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
655 {
656   guint16 address_length;
657   tvbuff_t *address_tvb;
658
659   address_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
660   
661   proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
662   address_tvb    =  tvb_new_subset(parameter_tvb, ADDRESS_PARAMETER_OFFSET, address_length, address_length);
663   proto_item_append_text(parameter_item, " (Address: ");
664   dissect_parameter(address_tvb, pinfo, parameter_tree, parameter_item, FALSE);
665   proto_item_append_text(parameter_item, ", correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
666 }
667
668 #define ERROR_CAUSE_IND_CASUES_OFFSET (CORRELATION_ID_OFFSET + CORRELATION_ID_LENGTH)
669
670 static void
671 dissect_error_cause_indication_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
672 {
673   guint16 causes_length;
674   tvbuff_t *causes_tvb;
675
676   proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
677   causes_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
678   causes_tvb    = tvb_new_subset(parameter_tvb, ERROR_CAUSE_IND_CASUES_OFFSET, causes_length, causes_length);
679   dissect_error_causes(causes_tvb, pinfo,  parameter_tree);
680 }
681
682 static void
683 dissect_set_primary_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
684 {
685   guint16 address_length;
686   tvbuff_t *address_tvb;
687
688   address_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
689   
690   proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
691   address_tvb    =  tvb_new_subset(parameter_tvb, ADDRESS_PARAMETER_OFFSET, address_length, address_length);
692   proto_item_append_text(parameter_item, " (Address: ");
693   dissect_parameter(address_tvb, pinfo, parameter_tree, parameter_item, FALSE);
694   proto_item_append_text(parameter_item, ", correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
695 }
696
697 static void
698 dissect_success_report_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
699 {
700   proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
701   proto_item_append_text(parameter_item, " (Correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
702 }
703
704 #define ADAP_INDICATION_LENGTH 4
705 #define ADAP_INDICATION_OFFSET PARAMETER_VALUE_OFFSET
706
707 static void
708 dissect_adap_indication_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
709 {
710   proto_tree_add_item(parameter_tree, hf_adap_indication, parameter_tvb, ADAP_INDICATION_OFFSET, ADAP_INDICATION_LENGTH, NETWORK_BYTE_ORDER);
711   proto_item_append_text(parameter_item, " (Indication: %u)", tvb_get_ntohl(parameter_tvb, ADAP_INDICATION_OFFSET));
712 }
713
714 static void
715 dissect_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
716 {
717   guint16 type, parameter_value_length;
718
719   type                   = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
720   parameter_value_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
721
722   if (parameter_value_length > 0)
723     proto_tree_add_item(parameter_tree, hf_parameter_value, parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length, NETWORK_BYTE_ORDER);
724
725   proto_item_append_text(parameter_item, " (Type %u, value length: %u byte%s)", type, parameter_value_length, plurality(parameter_value_length, "", "s"));
726 }
727
728 #define HEARTBEAT_INFO_PARAMETER_ID          0x0001
729 #define IPV4ADDRESS_PARAMETER_ID             0x0005
730 #define IPV6ADDRESS_PARAMETER_ID             0x0006
731 #define STATE_COOKIE_PARAMETER_ID            0x0007
732 #define UNREC_PARA_PARAMETER_ID              0x0008
733 #define COOKIE_PRESERVATIVE_PARAMETER_ID     0x0009
734 #define HOSTNAME_ADDRESS_PARAMETER_ID        0x000b
735 #define SUPPORTED_ADDRESS_TYPES_PARAMETER_ID 0x000c
736 #define ECN_PARAMETER_ID                     0x8000
737 #define FORWARD_TSN_SUPPORTED_PARAMETER_ID   0xC000
738 #define ADD_IP_ADDRESS_PARAMETER_ID          0xC001
739 #define DEL_IP_ADDRESS_PARAMETER_ID          0xC002
740 #define ERROR_CAUSE_INDICATION_PARAMETER_ID  0xC003
741 #define SET_PRIMARY_ADDRESS_PARAMETER_ID     0xC004
742 #define SUCCESS_REPORT_PARAMETER_ID          0xC005
743 #define ADAP_LAYER_INDICATION_PARAMETER_ID   0xC006
744
745 static const value_string parameter_identifier_values[] = {
746   { HEARTBEAT_INFO_PARAMETER_ID,          "Heartbeat info"              },
747   { IPV4ADDRESS_PARAMETER_ID,             "IPv4 address"                },
748   { IPV6ADDRESS_PARAMETER_ID,             "IPv6 address"                },
749   { STATE_COOKIE_PARAMETER_ID,            "State cookie"                },
750   { UNREC_PARA_PARAMETER_ID,              "Unrecognized parameter"      },
751   { COOKIE_PRESERVATIVE_PARAMETER_ID,     "Cookie preservative"         },
752   { HOSTNAME_ADDRESS_PARAMETER_ID,        "Hostname address"            },
753   { SUPPORTED_ADDRESS_TYPES_PARAMETER_ID, "Supported address types"     },
754   { ECN_PARAMETER_ID,                     "ECN"                         },
755   { FORWARD_TSN_SUPPORTED_PARAMETER_ID,   "Forward TSN supported"       },
756   { ADD_IP_ADDRESS_PARAMETER_ID,          "Add IP address"              },
757   { DEL_IP_ADDRESS_PARAMETER_ID,          "Delete IP address"           },
758   { ERROR_CAUSE_INDICATION_PARAMETER_ID,  "Error cause indication"      },
759   { SET_PRIMARY_ADDRESS_PARAMETER_ID,     "Set primary address"         },
760   { SUCCESS_REPORT_PARAMETER_ID,          "Success report"              },
761   { ADAP_LAYER_INDICATION_PARAMETER_ID,   "Adaptation Layer Indication" },
762   { 0,                                    NULL                          } };
763
764 #define SCTP_PARAMETER_BIT_1  0x8000
765 #define SCTP_PARAMETER_BIT_2 0x4000
766
767 static const true_false_string sctp_parameter_bit_1_value = {
768   "Skip parameter and continue processing of the chunk",
769   "Stop processing of chunk"
770 };
771
772 static const true_false_string sctp_parameter_bit_2_value = {
773   "Do report",
774   "Do not report"
775 };
776
777 static void
778 dissect_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *additional_item, gboolean dissecting_init_init_ack_chunk)
779 {
780   guint16 type, length, padding_length;
781   proto_item *parameter_item;
782   proto_tree *parameter_tree;
783   proto_item *type_item;
784   proto_tree *type_tree;
785
786   type           = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
787   length         = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
788   padding_length = tvb_length(parameter_tvb) - length;
789
790   parameter_item = proto_tree_add_text(chunk_tree, parameter_tvb, PARAMETER_HEADER_OFFSET, tvb_length(parameter_tvb), "%s parameter", val_to_str(type, parameter_identifier_values, "Unknown"));
791   parameter_tree = proto_item_add_subtree(parameter_item, ett_sctp_chunk_parameter);
792
793   type_item = proto_tree_add_item(parameter_tree, hf_parameter_type,   parameter_tvb, PARAMETER_TYPE_OFFSET,   PARAMETER_TYPE_LENGTH,   NETWORK_BYTE_ORDER);
794   type_tree = proto_item_add_subtree(type_item, ett_sctp_parameter_type);
795   proto_tree_add_item(type_tree, hf_parameter_bit_1,  parameter_tvb, PARAMETER_TYPE_OFFSET,  PARAMETER_TYPE_LENGTH,  NETWORK_BYTE_ORDER);
796   proto_tree_add_item(type_tree, hf_parameter_bit_2,  parameter_tvb, PARAMETER_TYPE_OFFSET,  PARAMETER_TYPE_LENGTH,  NETWORK_BYTE_ORDER);
797   proto_tree_add_item(parameter_tree, hf_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
798
799   switch(type) {
800   case HEARTBEAT_INFO_PARAMETER_ID:
801     dissect_heartbeat_info_parameter(parameter_tvb, parameter_tree, parameter_item);
802     break;
803   case IPV4ADDRESS_PARAMETER_ID:
804     dissect_ipv4_parameter(parameter_tvb, parameter_tree, parameter_item, additional_item, dissecting_init_init_ack_chunk);
805     break;
806   case IPV6ADDRESS_PARAMETER_ID:
807     dissect_ipv6_parameter(parameter_tvb, parameter_tree, parameter_item, additional_item, dissecting_init_init_ack_chunk);
808     break;
809   case STATE_COOKIE_PARAMETER_ID:
810     dissect_state_cookie_parameter(parameter_tvb, parameter_tree, parameter_item);
811     break;
812   case UNREC_PARA_PARAMETER_ID:
813     dissect_unrecognized_parameters_parameter(parameter_tvb, pinfo,  parameter_tree);
814     break;
815   case COOKIE_PRESERVATIVE_PARAMETER_ID:
816     dissect_cookie_preservative_parameter(parameter_tvb, parameter_tree, parameter_item);
817     break;
818   case HOSTNAME_ADDRESS_PARAMETER_ID:
819     dissect_hostname_parameter(parameter_tvb, parameter_tree, parameter_item);
820     break;
821   case SUPPORTED_ADDRESS_TYPES_PARAMETER_ID:
822     dissect_supported_address_types_parameter(parameter_tvb, parameter_tree, parameter_item);
823     break;
824   case ECN_PARAMETER_ID:
825     dissect_ecn_parameter(parameter_tvb);
826     break;
827   case FORWARD_TSN_SUPPORTED_PARAMETER_ID:
828     dissect_forward_tsn_supported_parameter(parameter_tvb);
829     break;
830   case ADD_IP_ADDRESS_PARAMETER_ID:
831     dissect_add_ip_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
832     break;
833   case DEL_IP_ADDRESS_PARAMETER_ID:
834     dissect_del_ip_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
835     break;
836   case ERROR_CAUSE_INDICATION_PARAMETER_ID:
837     dissect_error_cause_indication_parameter(parameter_tvb, pinfo, parameter_tree);
838     break;
839   case SET_PRIMARY_ADDRESS_PARAMETER_ID:
840     dissect_set_primary_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
841     break;
842   case SUCCESS_REPORT_PARAMETER_ID:
843     dissect_success_report_parameter(parameter_tvb, parameter_tree, parameter_item);
844     break;
845   case ADAP_LAYER_INDICATION_PARAMETER_ID:
846     dissect_adap_indication_parameter(parameter_tvb, parameter_tree, parameter_item);
847     break;
848   default:
849     dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
850     break;
851   }
852   
853   if (padding_length > 0)
854     proto_tree_add_item(parameter_tree, hf_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
855 }
856
857 static void
858 dissect_parameters(tvbuff_t *parameters_tvb, packet_info *pinfo, proto_tree *tree, proto_item *additional_item, gboolean dissecting_init_init_ack_chunk)
859 {
860   gint offset, length, total_length, remaining_length;
861   tvbuff_t *parameter_tvb;
862
863   offset = 0;
864   while((remaining_length = tvb_length_remaining(parameters_tvb, offset))) {
865     if ((offset > 0) && additional_item)
866       proto_item_append_text(additional_item, " ");
867     length       = tvb_get_ntohs(parameters_tvb, offset + PARAMETER_LENGTH_OFFSET);
868     total_length = ADD_PADDING(length);
869     if (remaining_length >= length)
870       total_length = MIN(total_length, remaining_length);
871     /* create a tvb for the parameter including the padding bytes */
872     parameter_tvb  = tvb_new_subset(parameters_tvb, offset, total_length, total_length);
873     dissect_parameter(parameter_tvb, pinfo, tree, additional_item, dissecting_init_init_ack_chunk);
874     /* get rid of the handled parameter */
875     offset += total_length;
876   }
877 }
878
879
880 /*
881  * Code to handle error causes for ABORT and ERROR chunks
882  */
883  
884  
885 #define CAUSE_CODE_LENGTH            2
886 #define CAUSE_LENGTH_LENGTH          2
887 #define CAUSE_HEADER_LENGTH          (CAUSE_CODE_LENGTH + CAUSE_LENGTH_LENGTH)
888
889 #define CAUSE_HEADER_OFFSET          0
890 #define CAUSE_CODE_OFFSET            CAUSE_HEADER_OFFSET
891 #define CAUSE_LENGTH_OFFSET          (CAUSE_CODE_OFFSET + CAUSE_CODE_LENGTH)
892 #define CAUSE_INFO_OFFSET            (CAUSE_LENGTH_OFFSET + CAUSE_LENGTH_LENGTH)
893
894
895 #define CAUSE_STREAM_IDENTIFIER_LENGTH 2
896 #define CAUSE_RESERVED_LENGTH 2
897 #define CAUSE_STREAM_IDENTIFIER_OFFSET CAUSE_INFO_OFFSET
898 #define CAUSE_RESERVED_OFFSET          (CAUSE_STREAM_IDENTIFIER_OFFSET + CAUSE_STREAM_IDENTIFIER_LENGTH)
899  
900 static void
901 dissect_invalid_stream_identifier_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
902 {
903   proto_tree_add_item(cause_tree, hf_cause_stream_identifier, cause_tvb, CAUSE_STREAM_IDENTIFIER_OFFSET, CAUSE_STREAM_IDENTIFIER_LENGTH, NETWORK_BYTE_ORDER);
904   proto_tree_add_item(cause_tree, hf_cause_reserved,          cause_tvb, CAUSE_RESERVED_OFFSET,          CAUSE_RESERVED_LENGTH,          NETWORK_BYTE_ORDER);
905   proto_item_append_text(cause_item, " (SID: %u)", tvb_get_ntohs(cause_tvb, CAUSE_STREAM_IDENTIFIER_OFFSET));
906 }
907
908 #define CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH 4
909 #define CAUSE_MISSING_PARAMETER_TYPE_LENGTH       2
910
911 #define CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET CAUSE_INFO_OFFSET
912 #define CAUSE_FIRST_MISSING_PARAMETER_TYPE_OFFSET (CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET + \
913                                                    CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH )
914
915 static void
916 dissect_missing_mandatory_parameters_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree)
917 {
918   guint32 number_of_missing_parameters, missing_parameter_number;
919   guint   offset;
920
921   number_of_missing_parameters = tvb_get_ntohl(cause_tvb, CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET);
922   proto_tree_add_item(cause_tree, hf_cause_number_of_missing_parameters, cause_tvb, CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET, CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH, NETWORK_BYTE_ORDER);
923   offset = CAUSE_FIRST_MISSING_PARAMETER_TYPE_OFFSET;
924   for(missing_parameter_number = 1; missing_parameter_number <= number_of_missing_parameters; missing_parameter_number++) {
925     proto_tree_add_item(cause_tree, hf_cause_missing_parameter_type, cause_tvb, offset, CAUSE_MISSING_PARAMETER_TYPE_LENGTH, NETWORK_BYTE_ORDER);
926     offset +=  CAUSE_MISSING_PARAMETER_TYPE_LENGTH;
927   }
928 }
929
930 #define CAUSE_MEASURE_OF_STALENESS_LENGTH 4
931 #define CAUSE_MEASURE_OF_STALENESS_OFFSET CAUSE_INFO_OFFSET
932
933 static void
934 dissect_stale_cookie_error_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
935 {
936   proto_tree_add_item(cause_tree, hf_cause_measure_of_staleness, cause_tvb, CAUSE_MEASURE_OF_STALENESS_OFFSET, CAUSE_MEASURE_OF_STALENESS_LENGTH, NETWORK_BYTE_ORDER);
937   proto_item_append_text(cause_item, " (Measure: %u usec)", tvb_get_ntohl(cause_tvb, CAUSE_MEASURE_OF_STALENESS_OFFSET));
938 }
939
940 static void
941 dissect_out_of_resource_cause(tvbuff_t *cause_tvb _U_)
942 {
943 }
944
945 static void
946 dissect_unresolvable_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
947 {
948   guint16 parameter_length;
949   tvbuff_t *parameter_tvb;
950
951   parameter_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
952   parameter_tvb    = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, parameter_length, parameter_length);
953   proto_item_append_text(cause_item, " (Address: ");
954   dissect_parameter(parameter_tvb, pinfo, cause_tree, cause_item, FALSE);
955   proto_item_append_text(cause_item, ")");
956 }
957
958 static void
959 dissect_unrecognized_chunk_type_cause(tvbuff_t *cause_tvb,  packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
960 {
961   guint16 chunk_length;
962   guint8 unrecognized_type;
963   tvbuff_t *unrecognized_chunk_tvb;
964
965   chunk_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
966   unrecognized_chunk_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, chunk_length, chunk_length);
967   dissect_sctp_chunk(unrecognized_chunk_tvb, pinfo, cause_tree,cause_tree, FALSE);
968   unrecognized_type   = tvb_get_guint8(unrecognized_chunk_tvb, CHUNK_TYPE_OFFSET);
969   proto_item_append_text(cause_item, " (Type: %u (%s))", unrecognized_type, val_to_str(unrecognized_type, chunk_type_values, "unknown"));
970 }
971
972 static void
973 dissect_invalid_mandatory_parameter_cause(tvbuff_t *cause_tvb _U_)
974 {
975 }
976
977 static void
978 dissect_unrecognized_parameters_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree)
979 {
980   guint16 cause_info_length;
981   tvbuff_t *unrecognized_parameters_tvb;
982
983   cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
984
985   unrecognized_parameters_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
986   dissect_parameters(unrecognized_parameters_tvb, pinfo, cause_tree, NULL, FALSE);
987 }
988
989 #define CAUSE_TSN_LENGTH 4
990 #define CAUSE_TSN_OFFSET CAUSE_INFO_OFFSET
991
992 static void
993 dissect_no_user_data_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
994 {
995   proto_tree_add_item(cause_tree, hf_cause_tsn, cause_tvb, CAUSE_TSN_OFFSET, CAUSE_TSN_LENGTH, NETWORK_BYTE_ORDER);
996   proto_item_append_text(cause_item, " (TSN: %u)", tvb_get_ntohl(cause_tvb, CAUSE_TSN_OFFSET));
997 }
998
999 static void
1000 dissect_cookie_received_while_shutting_down_cause(tvbuff_t *cause_tvb _U_)
1001 {
1002 }
1003
1004 static void
1005 dissect_restart_with_new_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree* cause_tree, proto_item *cause_item)
1006 {
1007   guint16 cause_info_length;
1008   tvbuff_t *parameter_tvb;
1009
1010   cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1011   parameter_tvb    = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1012   proto_item_append_text(cause_item, " (New addresses: ");
1013   dissect_parameters(parameter_tvb, pinfo, cause_tree, cause_item, FALSE);
1014   proto_item_append_text(cause_item, ")");
1015 }
1016
1017 static void
1018 dissect_user_initiated_abort_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree)
1019 {
1020   guint16 cause_info_length;
1021
1022   cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1023   if (cause_info_length > 0)
1024     proto_tree_add_item(cause_tree, hf_cause_info, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, NETWORK_BYTE_ORDER);
1025 }
1026
1027 static void
1028 dissect_protocol_violation_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree)
1029 {
1030   guint16 cause_info_length;
1031
1032   cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1033   if (cause_info_length > 0)
1034     proto_tree_add_item(cause_tree, hf_cause_info, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, NETWORK_BYTE_ORDER);
1035 }
1036
1037 static void
1038 dissect_delete_last_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
1039 {
1040   guint16 cause_info_length;
1041   tvbuff_t *parameter_tvb;
1042
1043   cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1044   parameter_tvb    = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1045   proto_item_append_text(cause_item, " (Last address: ");
1046   dissect_parameter(parameter_tvb, pinfo, cause_tree, cause_item, FALSE);
1047   proto_item_append_text(cause_item, ")");
1048 }
1049
1050 static void
1051 dissect_resource_outage_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree)
1052 {
1053   guint16 cause_info_length;
1054   tvbuff_t *parameter_tvb;
1055
1056   cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1057   parameter_tvb     = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1058   dissect_parameter(parameter_tvb, pinfo, cause_tree, NULL, FALSE);
1059 }
1060
1061 static void
1062 dissect_delete_source_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
1063 {
1064   guint16 cause_info_length;
1065   tvbuff_t *parameter_tvb;
1066
1067   cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1068   parameter_tvb    = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1069   proto_item_append_text(cause_item, " (Deleted address: ");
1070   dissect_parameter(parameter_tvb, pinfo, cause_tree, cause_item, FALSE);
1071   proto_item_append_text(cause_item, ")");
1072 }
1073
1074 static void
1075 dissect_request_refused_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree)
1076 {
1077   guint16 cause_info_length;
1078   tvbuff_t *parameter_tvb;
1079
1080   cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1081   parameter_tvb    = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1082   dissect_parameter(parameter_tvb, pinfo, cause_tree, NULL, FALSE);
1083 }
1084
1085 static void
1086 dissect_unknown_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
1087 {
1088   guint16 cause_info_length;
1089
1090   cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
1091   if (cause_info_length > 0)
1092     proto_tree_add_item(cause_tree, hf_cause_info, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, NETWORK_BYTE_ORDER);
1093   proto_item_append_text(cause_item, "Code: %u, information length: %u byte%s)", tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET), cause_info_length, plurality(cause_info_length, "", "s"));
1094 }
1095
1096 #define INVALID_STREAM_IDENTIFIER                  0x01
1097 #define MISSING_MANDATORY_PARAMETERS               0x02
1098 #define STALE_COOKIE_ERROR                         0x03
1099 #define OUT_OF_RESOURCE                            0x04
1100 #define UNRESOLVABLE_ADDRESS                       0x05
1101 #define UNRECOGNIZED_CHUNK_TYPE                    0x06
1102 #define INVALID_MANDATORY_PARAMETER                0x07
1103 #define UNRECOGNIZED_PARAMETERS                    0x08
1104 #define NO_USER_DATA                               0x09
1105 #define COOKIE_RECEIVED_WHILE_SHUTTING_DOWN        0x0a
1106 #define RESTART_WITH_NEW_ADDRESSES                 0x0b
1107 #define USER_INITIATED_ABORT                       0x0c
1108 #define PROTOCOL_VIOLATION                         0x0d
1109 #define REQUEST_TO_DELETE_LAST_ADDRESS             0x0100
1110 #define OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE 0X0101
1111 #define REQUEST_TO_DELETE_SOURCE_ADDRESS           0x0102
1112 #define ABORT_DUE_TO_ILLEGAL_ASCONF                0x0103
1113 #define REQUESTION_REFUSED                         0x0104
1114
1115 static const value_string cause_code_values[] = {
1116   { INVALID_STREAM_IDENTIFIER,                  "Invalid stream identifier" },
1117   { MISSING_MANDATORY_PARAMETERS,               "Missing mandatory parameter" },
1118   { STALE_COOKIE_ERROR,                         "Stale cookie error" },
1119   { OUT_OF_RESOURCE,                            "Out of resource" },
1120   { UNRESOLVABLE_ADDRESS,                       "Unresolvable address" },
1121   { UNRECOGNIZED_CHUNK_TYPE,                    "Unrecognized chunk type" },
1122   { INVALID_MANDATORY_PARAMETER,                "Invalid mandatory parameter" },
1123   { UNRECOGNIZED_PARAMETERS,                    "Unrecognized parameters" },
1124   { NO_USER_DATA,                               "No user data" },
1125   { COOKIE_RECEIVED_WHILE_SHUTTING_DOWN,        "Cookie received while shutting down" },
1126   { RESTART_WITH_NEW_ADDRESSES,                 "Restart of an association with new addresses" },
1127   { USER_INITIATED_ABORT,                       "User initiated ABORT" },
1128   { PROTOCOL_VIOLATION,                         "Protocol violation" },
1129   { REQUEST_TO_DELETE_LAST_ADDRESS,             "Request to delete last address" },
1130   { OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE, "Operation refused due to resource shortage" },
1131   { REQUEST_TO_DELETE_SOURCE_ADDRESS,           "Request to delete source address" },
1132   { ABORT_DUE_TO_ILLEGAL_ASCONF,                "Association Aborted due to illegal ASCONF-ACK" },
1133   { REQUESTION_REFUSED,                         "Request refused - no authorization" },
1134   { 0,                                          NULL } };
1135
1136
1137 static void
1138 dissect_error_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *chunk_tree)
1139 {
1140   guint16 code, length, padding_length;
1141   proto_item *cause_item;
1142   proto_tree *cause_tree;
1143
1144   code           = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET);
1145   length         = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
1146   padding_length = tvb_length(cause_tvb) - length;
1147
1148   cause_item = proto_tree_add_text(chunk_tree, cause_tvb, CAUSE_HEADER_OFFSET, tvb_length(cause_tvb), "%s cause", val_to_str(code, cause_code_values, "Unknown"));
1149   cause_tree = proto_item_add_subtree(cause_item, ett_sctp_chunk_cause);
1150
1151   proto_tree_add_item(cause_tree, hf_cause_code, cause_tvb,   CAUSE_CODE_OFFSET,   CAUSE_CODE_LENGTH,   NETWORK_BYTE_ORDER);
1152   proto_tree_add_item(cause_tree, hf_cause_length, cause_tvb, CAUSE_LENGTH_OFFSET, CAUSE_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
1153
1154   switch(code) {
1155   case INVALID_STREAM_IDENTIFIER:
1156     dissect_invalid_stream_identifier_cause(cause_tvb, cause_tree, cause_item);
1157     break;
1158   case MISSING_MANDATORY_PARAMETERS:
1159     dissect_missing_mandatory_parameters_cause(cause_tvb, cause_tree);
1160     break;
1161   case STALE_COOKIE_ERROR:
1162     dissect_stale_cookie_error_cause(cause_tvb, cause_tree, cause_item);
1163     break;
1164   case OUT_OF_RESOURCE:
1165     dissect_out_of_resource_cause(cause_tvb);
1166     break;
1167   case UNRESOLVABLE_ADDRESS:
1168     dissect_unresolvable_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
1169     break;
1170   case UNRECOGNIZED_CHUNK_TYPE:
1171     dissect_unrecognized_chunk_type_cause(cause_tvb, pinfo, cause_tree, cause_item);
1172     break;
1173   case INVALID_MANDATORY_PARAMETER:
1174     dissect_invalid_mandatory_parameter_cause(cause_tvb);
1175     break;
1176   case UNRECOGNIZED_PARAMETERS:
1177     dissect_unrecognized_parameters_cause(cause_tvb, pinfo, cause_tree);
1178     break;
1179   case NO_USER_DATA:
1180     dissect_no_user_data_cause(cause_tvb, cause_tree, cause_item);
1181     break;
1182   case COOKIE_RECEIVED_WHILE_SHUTTING_DOWN:
1183     dissect_cookie_received_while_shutting_down_cause(cause_tvb);
1184     break;
1185   case RESTART_WITH_NEW_ADDRESSES:
1186     dissect_restart_with_new_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
1187     break;
1188   case USER_INITIATED_ABORT:
1189     dissect_user_initiated_abort_cause(cause_tvb, cause_tree);
1190     break;
1191   case PROTOCOL_VIOLATION:
1192     dissect_protocol_violation_cause(cause_tvb, cause_tree);
1193     break;
1194   case REQUEST_TO_DELETE_LAST_ADDRESS:
1195     dissect_delete_last_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
1196     break;
1197   case OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE:
1198     dissect_resource_outage_cause(cause_tvb, pinfo, cause_tree);
1199     break;
1200   case REQUEST_TO_DELETE_SOURCE_ADDRESS:
1201     dissect_delete_source_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
1202     break;
1203   case REQUESTION_REFUSED:
1204         dissect_request_refused_cause(cause_tvb, pinfo, cause_tree);
1205         break;
1206   default:
1207     dissect_unknown_cause(cause_tvb, cause_tree, cause_item);
1208     break;
1209   }
1210   
1211   if (padding_length > 0)
1212     proto_tree_add_item(cause_tree, hf_cause_padding, cause_tvb, CAUSE_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
1213 }
1214
1215 static void
1216 dissect_error_causes(tvbuff_t *causes_tvb, packet_info *pinfo, proto_tree *tree)
1217 {
1218   gint offset, length, total_length, remaining_length;
1219   tvbuff_t *cause_tvb;
1220
1221   offset = 0;
1222   while((remaining_length = tvb_length_remaining(causes_tvb, offset))) {
1223     length       = tvb_get_ntohs(causes_tvb, offset + CAUSE_LENGTH_OFFSET);
1224     total_length = ADD_PADDING(length);
1225     if (remaining_length >= length)
1226       total_length = MIN(total_length, remaining_length);
1227     /* create a tvb for the parameter including the padding bytes */
1228     cause_tvb    = tvb_new_subset(causes_tvb, offset, total_length, total_length);
1229     dissect_error_cause(cause_tvb, pinfo, tree);
1230     /* get rid of the handled cause */
1231     offset += total_length;
1232   }
1233 }
1234
1235
1236 /*
1237  * Code to actually dissect the packets
1238 */
1239
1240 static gboolean try_heuristic_first = FALSE;
1241
1242 static gboolean
1243 dissect_payload(tvbuff_t *payload_tvb, packet_info *pinfo, proto_tree *tree, guint32 ppi)
1244 {
1245   guint32 low_port, high_port;
1246
1247   if (try_heuristic_first) {
1248     /* do lookup with the heuristic subdissector table */
1249     if (dissector_try_heuristic(sctp_heur_subdissector_list, payload_tvb, pinfo, tree))
1250        return TRUE;
1251   }
1252
1253   /* Do lookups with the subdissector table.
1254
1255      When trying port numbers, we try the port number with the lower value
1256      first, followed by the port number with the higher value.  This means
1257      that, for packets where a dissector is registered for *both* port
1258      numbers, and where there's no match on the PPI:
1259
1260   1) we pick the same dissector for traffic going in both directions;
1261
1262   2) we prefer the port number that's more likely to be the right
1263      one (as that prefers well-known ports to reserved ports);
1264
1265      although there is, of course, no guarantee that any such strategy
1266      will always pick the right port number.
1267
1268      XXX - we ignore port numbers of 0, as some dissectors use a port
1269      number of 0 to disable the port. */
1270   if (dissector_try_port(sctp_ppi_dissector_table, ppi, payload_tvb, pinfo, tree))
1271     return TRUE;
1272   if (pinfo->srcport > pinfo->destport) {
1273     low_port = pinfo->destport;
1274     high_port = pinfo->srcport;
1275   } else {
1276     low_port = pinfo->srcport;
1277     high_port = pinfo->destport;
1278   }
1279   if (low_port != 0 &&
1280       dissector_try_port(sctp_port_dissector_table, low_port, payload_tvb, pinfo, tree))
1281     return TRUE;
1282   if (high_port != 0 &&
1283       dissector_try_port(sctp_port_dissector_table, high_port, payload_tvb, pinfo, tree))
1284     return TRUE;
1285
1286   if (!try_heuristic_first) {
1287     /* do lookup with the heuristic subdissector table */
1288     if (dissector_try_heuristic(sctp_heur_subdissector_list, payload_tvb, pinfo, tree))
1289        return TRUE;
1290   }
1291
1292   /* Oh, well, we don't know this; dissect it as data. */
1293   call_dissector(data_handle, payload_tvb, pinfo, tree);
1294   return TRUE;
1295 }
1296
1297 #define DATA_CHUNK_TSN_LENGTH         4
1298 #define DATA_CHUNK_STREAM_ID_LENGTH   2
1299 #define DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH 2
1300 #define DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH 4
1301
1302 #define DATA_CHUNK_TSN_OFFSET         (CHUNK_VALUE_OFFSET + 0)
1303 #define DATA_CHUNK_STREAM_ID_OFFSET   (DATA_CHUNK_TSN_OFFSET + DATA_CHUNK_TSN_LENGTH)
1304 #define DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET (DATA_CHUNK_STREAM_ID_OFFSET + \
1305                                              DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH)
1306 #define DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET (DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET + \
1307                                                DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH)
1308 #define DATA_CHUNK_PAYLOAD_OFFSET     (DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET + \
1309                                        DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH)
1310
1311 #define DATA_CHUNK_HEADER_LENGTH      (CHUNK_HEADER_LENGTH + \
1312                                        DATA_CHUNK_TSN_LENGTH + \
1313                                        DATA_CHUNK_STREAM_ID_LENGTH + \
1314                                        DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH + \
1315                                        DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH)
1316
1317 #define SCTP_DATA_CHUNK_E_BIT 0x01
1318 #define SCTP_DATA_CHUNK_B_BIT 0x02
1319 #define SCTP_DATA_CHUNK_U_BIT 0x04
1320
1321 static const true_false_string sctp_data_chunk_e_bit_value = {
1322   "Last segment",
1323   "Not the last segment"
1324 };
1325
1326 static const true_false_string sctp_data_chunk_b_bit_value = {
1327   "First segment",
1328   "Subsequent segment"
1329 };
1330
1331 static const true_false_string sctp_data_chunk_u_bit_value = {
1332   "Unordered delivery",
1333   "Ordered deliviery"
1334 };
1335
1336 static gboolean
1337 dissect_data_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1338 {
1339   guint16 payload_length;
1340   guint32 payload_proto_id;
1341   tvbuff_t *payload_tvb;
1342   proto_tree *flags_tree;
1343   guint8 e_bit, b_bit, u_bit;
1344         
1345   payload_proto_id  = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET);
1346
1347   if (chunk_tree) {
1348     proto_item_set_len(chunk_item, DATA_CHUNK_HEADER_LENGTH);
1349     flags_tree  = proto_item_add_subtree(flags_item, ett_sctp_data_chunk_flags);
1350     proto_tree_add_item(flags_tree, hf_data_chunk_e_bit,             chunk_tvb, CHUNK_FLAGS_OFFSET,                    CHUNK_FLAGS_LENGTH,                    NETWORK_BYTE_ORDER);
1351     proto_tree_add_item(flags_tree, hf_data_chunk_b_bit,             chunk_tvb, CHUNK_FLAGS_OFFSET,                    CHUNK_FLAGS_LENGTH,                    NETWORK_BYTE_ORDER);
1352     proto_tree_add_item(flags_tree, hf_data_chunk_u_bit,             chunk_tvb, CHUNK_FLAGS_OFFSET,                    CHUNK_FLAGS_LENGTH,                    NETWORK_BYTE_ORDER);
1353     proto_tree_add_item(chunk_tree, hf_data_chunk_tsn,               chunk_tvb, DATA_CHUNK_TSN_OFFSET,                 DATA_CHUNK_TSN_LENGTH,                 NETWORK_BYTE_ORDER);
1354     proto_tree_add_item(chunk_tree, hf_data_chunk_stream_id,         chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET,           DATA_CHUNK_STREAM_ID_LENGTH,           NETWORK_BYTE_ORDER);
1355     proto_tree_add_item(chunk_tree, hf_data_chunk_stream_seq_number, chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET,   DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH,   NETWORK_BYTE_ORDER);
1356     proto_tree_add_item(chunk_tree, hf_data_chunk_payload_proto_id,  chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH, NETWORK_BYTE_ORDER);
1357
1358     e_bit = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_DATA_CHUNK_E_BIT;
1359     b_bit = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_DATA_CHUNK_B_BIT;
1360     u_bit = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_DATA_CHUNK_U_BIT;
1361
1362     proto_item_append_text(chunk_item, "(%s, ", (u_bit) ? "unordered" : "ordered");
1363     if (b_bit) {
1364       if (e_bit)
1365         proto_item_append_text(chunk_item, "complete");
1366       else
1367         proto_item_append_text(chunk_item, "first");
1368     } else {
1369       if (e_bit)
1370         proto_item_append_text(chunk_item, "last");
1371       else
1372         proto_item_append_text(chunk_item, "middle");
1373     }
1374                                 
1375     proto_item_append_text(chunk_item, " segment, TSN: %u, SID: %u, SSN: %u, PPID: %u",
1376                            tvb_get_ntohl(chunk_tvb, DATA_CHUNK_TSN_OFFSET), 
1377                            tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET),
1378                            tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET),
1379                            payload_proto_id);
1380   }
1381   payload_length    = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1382   if (payload_length < DATA_CHUNK_HEADER_LENGTH) {
1383     if (chunk_tree) {
1384       proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
1385                              payload_length, DATA_CHUNK_HEADER_LENGTH);
1386     }
1387     return TRUE;
1388   }
1389   payload_length -= DATA_CHUNK_HEADER_LENGTH;
1390   if (chunk_tree) {
1391       proto_item_append_text(chunk_item, ", payload length: %u byte%s)",
1392                              payload_length, plurality(payload_length, "", "s"));
1393   }
1394   payload_tvb       = tvb_new_subset(chunk_tvb, DATA_CHUNK_PAYLOAD_OFFSET, payload_length, payload_length);
1395   return dissect_payload(payload_tvb, pinfo, tree, payload_proto_id);
1396 }
1397
1398 #define INIT_CHUNK_INITIATE_TAG_LENGTH               4
1399 #define INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH      4
1400 #define INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH 2
1401 #define INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH  2
1402 #define INIT_CHUNK_INITIAL_TSN_LENGTH                4
1403 #define INIT_CHUNK_FIXED_PARAMTERS_LENGTH            (INIT_CHUNK_INITIATE_TAG_LENGTH + \
1404                                                       INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH + \
1405                                                       INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH + \
1406                                                       INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH + \
1407                                                       INIT_CHUNK_INITIAL_TSN_LENGTH)
1408                                                       
1409 #define INIT_CHUNK_INITIATE_TAG_OFFSET               CHUNK_VALUE_OFFSET
1410 #define INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET      (INIT_CHUNK_INITIATE_TAG_OFFSET + \
1411                                                       INIT_CHUNK_INITIATE_TAG_LENGTH )
1412 #define INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET (INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET + \
1413                                                       INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH )
1414 #define INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET  (INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET + \
1415                                                       INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH )
1416 #define INIT_CHUNK_INITIAL_TSN_OFFSET                (INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET + \
1417                                                       INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH )
1418 #define INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET  (INIT_CHUNK_INITIAL_TSN_OFFSET + \
1419                                                       INIT_CHUNK_INITIAL_TSN_LENGTH )
1420
1421 static void
1422 dissect_init_chunk(tvbuff_t *chunk_tvb,  packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
1423 {
1424   gint parameters_length;
1425   tvbuff_t *parameters_tvb;
1426
1427   if (chunk_tree) {
1428     /* handle fixed parameters */
1429     proto_tree_add_item(chunk_tree, hf_init_chunk_initiate_tag,               chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET,               INIT_CHUNK_INITIATE_TAG_LENGTH,               NETWORK_BYTE_ORDER);
1430     proto_tree_add_item_hidden(chunk_tree, hf_initiate_tag,                   chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET,               INIT_CHUNK_INITIATE_TAG_LENGTH,               NETWORK_BYTE_ORDER);
1431     proto_tree_add_item(chunk_tree, hf_init_chunk_adv_rec_window_credit,      chunk_tvb, INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET,      INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH,      NETWORK_BYTE_ORDER);
1432     proto_tree_add_item(chunk_tree, hf_init_chunk_number_of_outbound_streams, chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH, NETWORK_BYTE_ORDER);
1433     proto_tree_add_item(chunk_tree, hf_init_chunk_number_of_inbound_streams,  chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET,  INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH,  NETWORK_BYTE_ORDER);
1434     proto_tree_add_item(chunk_tree, hf_init_chunk_initial_tsn,                chunk_tvb, INIT_CHUNK_INITIAL_TSN_OFFSET,                INIT_CHUNK_INITIAL_TSN_LENGTH,                NETWORK_BYTE_ORDER);
1435
1436     /* handle variable paramters */
1437     parameters_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - INIT_CHUNK_FIXED_PARAMTERS_LENGTH - CHUNK_HEADER_LENGTH;
1438     parameters_tvb = tvb_new_subset(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET, parameters_length, parameters_length);
1439     dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, TRUE);
1440
1441     proto_item_append_text(chunk_item, " (Outbound streams: %u, inbound streams: %u)",
1442                            tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET),
1443                            tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET));
1444   }
1445 }
1446
1447 static void
1448 dissect_init_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
1449 {
1450   gint parameters_length;
1451   tvbuff_t *parameters_tvb;
1452
1453   if (chunk_tree) {
1454     /* handle fixed parameters */
1455     proto_tree_add_item(chunk_tree, hf_initack_chunk_initiate_tag,               chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET,               INIT_CHUNK_INITIATE_TAG_LENGTH,               NETWORK_BYTE_ORDER);
1456     proto_tree_add_item_hidden(chunk_tree, hf_initiate_tag,                      chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET,               INIT_CHUNK_INITIATE_TAG_LENGTH,               NETWORK_BYTE_ORDER);
1457     proto_tree_add_item(chunk_tree, hf_initack_chunk_adv_rec_window_credit,      chunk_tvb, INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET,      INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH,      NETWORK_BYTE_ORDER);
1458     proto_tree_add_item(chunk_tree, hf_initack_chunk_number_of_outbound_streams, chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH, NETWORK_BYTE_ORDER);
1459     proto_tree_add_item(chunk_tree, hf_initack_chunk_number_of_inbound_streams,  chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET,  INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH,  NETWORK_BYTE_ORDER);
1460     proto_tree_add_item(chunk_tree, hf_initack_chunk_initial_tsn,                chunk_tvb, INIT_CHUNK_INITIAL_TSN_OFFSET,                INIT_CHUNK_INITIAL_TSN_LENGTH,                NETWORK_BYTE_ORDER);
1461
1462     /* handle variable paramters */
1463     parameters_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - INIT_CHUNK_FIXED_PARAMTERS_LENGTH - CHUNK_HEADER_LENGTH;
1464     parameters_tvb = tvb_new_subset(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET, parameters_length, parameters_length);
1465     dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, TRUE);
1466
1467     proto_item_append_text(chunk_item, " (Outbound streams: %u, inbound streams: %u)",
1468                            tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET),
1469                            tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET));
1470   }
1471 }
1472
1473 #define SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH    4
1474 #define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH 4
1475 #define SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH  2
1476 #define SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH    2
1477 #define SACK_CHUNK_GAP_BLOCK_LENGTH             4
1478 #define SACK_CHUNK_GAP_BLOCK_START_LENGTH       2
1479 #define SACK_CHUNK_GAP_BLOCK_END_LENGTH         2
1480 #define SACK_CHUNK_DUP_TSN_LENGTH               4
1481
1482 #define SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET (CHUNK_VALUE_OFFSET + 0)
1483 #define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET (SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET + \
1484                                                  SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH)
1485 #define SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET (SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET + \
1486                                                 SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH)
1487 #define SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET (SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET + \
1488                                               SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH)
1489 #define SACK_CHUNK_GAP_BLOCK_OFFSET (SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET + \
1490                                      SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH)
1491
1492
1493 static void
1494 dissect_sack_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
1495 {
1496   guint16 number_of_gap_blocks, number_of_dup_tsns;
1497   guint16 gap_block_number, dup_tsn_number, start, end;
1498   gint gap_block_offset, dup_tsn_offset;
1499   guint32 cum_tsn_ack;
1500   proto_item *block_item;
1501   proto_tree *block_tree;
1502         
1503   if (chunk_tree) {
1504     proto_tree_add_item(chunk_tree, hf_sack_chunk_cumulative_tsn_ack,    chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET,    SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH,    NETWORK_BYTE_ORDER);
1505     proto_tree_add_item(chunk_tree, hf_sack_chunk_adv_rec_window_credit, chunk_tvb, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH, NETWORK_BYTE_ORDER);
1506     proto_tree_add_item(chunk_tree, hf_sack_chunk_number_of_gap_blocks,  chunk_tvb, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET,  SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH,  NETWORK_BYTE_ORDER);
1507     proto_tree_add_item(chunk_tree, hf_sack_chunk_number_of_dup_tsns,    chunk_tvb, SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET,    SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH,    NETWORK_BYTE_ORDER);
1508
1509     /* handle the gap acknowledgement blocks */
1510     number_of_gap_blocks = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET);
1511     gap_block_offset     = SACK_CHUNK_GAP_BLOCK_OFFSET;
1512     cum_tsn_ack          = tvb_get_ntohl(chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
1513     for(gap_block_number = 1; gap_block_number <= number_of_gap_blocks; gap_block_number++) {
1514       start = tvb_get_ntohs(chunk_tvb, gap_block_offset);
1515       end   = tvb_get_ntohs(chunk_tvb, gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH);
1516       block_item = proto_tree_add_text(chunk_tree, chunk_tvb, gap_block_offset, SACK_CHUNK_GAP_BLOCK_LENGTH, "Gap Acknowledgement for TSN %u to %u", cum_tsn_ack + start, cum_tsn_ack + end);
1517       block_tree = proto_item_add_subtree(block_item, ett_sctp_sack_chunk_gap_block);
1518       proto_tree_add_item(block_tree, hf_sack_chunk_gap_block_start, chunk_tvb, gap_block_offset,                                     SACK_CHUNK_GAP_BLOCK_START_LENGTH, NETWORK_BYTE_ORDER);
1519       proto_tree_add_item(block_tree, hf_sack_chunk_gap_block_end,   chunk_tvb, gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH, SACK_CHUNK_GAP_BLOCK_END_LENGTH, NETWORK_BYTE_ORDER);
1520       gap_block_offset += SACK_CHUNK_GAP_BLOCK_LENGTH;
1521     }
1522
1523     /* handle the duplicate TSNs */
1524     number_of_dup_tsns = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET);
1525     dup_tsn_offset     = SACK_CHUNK_GAP_BLOCK_OFFSET + number_of_gap_blocks * SACK_CHUNK_GAP_BLOCK_LENGTH;
1526     for(dup_tsn_number = 1; dup_tsn_number <= number_of_dup_tsns; dup_tsn_number++) {
1527       proto_tree_add_item(chunk_tree, hf_sack_chunk_duplicate_tsn, chunk_tvb, dup_tsn_offset, SACK_CHUNK_DUP_TSN_LENGTH, NETWORK_BYTE_ORDER);
1528       dup_tsn_offset += SACK_CHUNK_DUP_TSN_LENGTH;
1529     }
1530
1531     proto_item_append_text(chunk_item, " (Cumulative TSN: %u, a_rwnd: %u, gaps: %u, duplicate TSNs: %u)",
1532                      tvb_get_ntohl(chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET),
1533                      tvb_get_ntohl(chunk_tvb, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET),
1534                      number_of_gap_blocks, number_of_dup_tsns);
1535   }
1536 }
1537
1538 #define HEARTBEAT_CHUNK_INFO_OFFSET CHUNK_VALUE_OFFSET
1539
1540 static void
1541 dissect_heartbeat_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
1542 {
1543   tvbuff_t   *parameter_tvb;
1544   guint info_length;
1545
1546   if (chunk_tree) {
1547     info_length    = tvb_get_ntohs(chunk_tvb,  CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
1548     proto_item_append_text(chunk_item, " (Information: %u byte%s)", info_length, plurality(info_length, "", "s"));
1549     parameter_tvb  = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, info_length, info_length);
1550     /* FIXME: Parameters or parameter? */
1551     dissect_parameter(parameter_tvb, pinfo, chunk_tree, NULL, FALSE);
1552   }
1553 }
1554
1555 static void
1556 dissect_heartbeat_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
1557 {
1558   tvbuff_t   *parameter_tvb;
1559   guint info_length;
1560
1561   if (chunk_tree) {
1562     info_length    = tvb_get_ntohs(chunk_tvb,  CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
1563     proto_item_append_text(chunk_item, " (Information: %u byte%s)", info_length, plurality(info_length, "", "s"));
1564     parameter_tvb  = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, info_length, info_length);
1565     /* FIXME: Parameters or parameter? */
1566     dissect_parameter(parameter_tvb, pinfo, chunk_tree, NULL, FALSE);
1567   }
1568 }
1569 #define ABORT_CHUNK_FIRST_ERROR_CAUSE_OFFSET 4
1570
1571 static void
1572 dissect_abort_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *flags_item)
1573 {
1574   guint16 causes_length;
1575   tvbuff_t *causes_tvb;
1576         proto_tree *flags_tree;
1577         
1578   if (chunk_tree) {
1579     flags_tree  = proto_item_add_subtree(flags_item, ett_sctp_abort_chunk_flags);
1580     proto_tree_add_item(flags_tree, hf_abort_chunk_t_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
1581
1582     causes_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
1583     causes_tvb    = tvb_new_subset(chunk_tvb, CHUNK_VALUE_OFFSET, causes_length, causes_length);
1584     dissect_error_causes(causes_tvb, pinfo, chunk_tree);
1585   }
1586 }
1587
1588 #define SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET CHUNK_VALUE_OFFSET
1589 #define SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_LENGTH 4
1590
1591 static void
1592 dissect_shutdown_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
1593 {
1594   if (chunk_tree) {
1595     proto_tree_add_item(chunk_tree, hf_shutdown_chunk_cumulative_tsn_ack, chunk_tvb, SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET, SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_LENGTH, NETWORK_BYTE_ORDER);
1596     proto_item_append_text(chunk_item, " (Cumulative TSN ack: %u)", tvb_get_ntohl(chunk_tvb, SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET));
1597   }
1598 }
1599
1600 static void
1601 dissect_shutdown_ack_chunk(tvbuff_t *chunk_tvb _U_)
1602 {
1603 }
1604
1605 #define ERROR_CAUSE_IND_CAUSES_OFFSET CHUNK_VALUE_OFFSET
1606
1607 static void
1608 dissect_error_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree)
1609 {
1610   guint16 causes_length;
1611   tvbuff_t *causes_tvb;
1612
1613   if (chunk_tree) {
1614     causes_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
1615     causes_tvb    = tvb_new_subset(chunk_tvb, ERROR_CAUSE_IND_CAUSES_OFFSET, causes_length, causes_length);
1616     dissect_error_causes(causes_tvb, pinfo, chunk_tree);    
1617   }
1618 }
1619
1620 #define COOKIE_OFFSET CHUNK_VALUE_OFFSET
1621
1622 static void
1623 dissect_cookie_echo_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
1624 {
1625   guint cookie_length;
1626
1627   if (chunk_tree) {
1628     cookie_length  = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
1629     proto_tree_add_item(chunk_tree, hf_cookie, chunk_tvb, COOKIE_OFFSET, cookie_length, NETWORK_BYTE_ORDER);
1630     proto_item_append_text(chunk_item, " (Cookie length: %u byte%s)", cookie_length, plurality(cookie_length, "", "s"));
1631   }
1632 }
1633
1634 static void
1635 dissect_cookie_ack_chunk(tvbuff_t *chunk_tvb _U_)
1636 {
1637 }
1638
1639 #define ECNE_CHUNK_LOWEST_TSN_OFFSET CHUNK_VALUE_OFFSET
1640 #define ECNE_CHUNK_LOWEST_TSN_LENGTH 4
1641
1642 static void
1643 dissect_ecne_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
1644 {
1645   if (chunk_tree)
1646     proto_tree_add_item(chunk_tree, hf_ecne_chunk_lowest_tsn, chunk_tvb, ECNE_CHUNK_LOWEST_TSN_OFFSET, ECNE_CHUNK_LOWEST_TSN_LENGTH, NETWORK_BYTE_ORDER);
1647     proto_item_append_text(chunk_item, " (Lowest TSN: %u)", tvb_get_ntohl(chunk_tvb, ECNE_CHUNK_LOWEST_TSN_OFFSET));
1648 }
1649
1650 #define CWR_CHUNK_LOWEST_TSN_OFFSET CHUNK_VALUE_OFFSET
1651 #define CWR_CHUNK_LOWEST_TSN_LENGTH 4
1652
1653 static void
1654 dissect_cwr_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
1655 {
1656   if (chunk_tree)
1657     proto_tree_add_item(chunk_tree, hf_cwr_chunk_lowest_tsn, chunk_tvb, CWR_CHUNK_LOWEST_TSN_OFFSET, CWR_CHUNK_LOWEST_TSN_LENGTH, NETWORK_BYTE_ORDER);
1658     proto_item_append_text(chunk_item, " (Lowest TSN: %u)", tvb_get_ntohl(chunk_tvb, CWR_CHUNK_LOWEST_TSN_OFFSET));
1659 }
1660
1661 #define SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT 0x01
1662
1663
1664 static const true_false_string sctp_shutdown_complete_chunk_t_bit_value = {
1665   "No TCB destroyed",
1666   "TCB destroyed"
1667 };
1668
1669
1670 static void
1671 dissect_shutdown_complete_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *flags_item)
1672 {
1673         proto_tree *flags_tree;
1674         
1675   if (chunk_tree) {
1676     flags_tree  = proto_item_add_subtree(flags_item, ett_sctp_shutdown_complete_chunk_flags);
1677                 proto_tree_add_item(flags_tree, hf_shutdown_complete_chunk_t_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
1678   }
1679 }
1680
1681 #define FORWARD_TSN_CHUNK_TSN_LENGTH 4
1682 #define FORWARD_TSN_CHUNK_SID_LENGTH 2
1683 #define FORWARD_TSN_CHUNK_SSN_LENGTH 2
1684 #define FORWARD_TSN_CHUNK_TSN_OFFSET CHUNK_VALUE_OFFSET
1685 #define FORWARD_TSN_CHUNK_SID_OFFSET 0
1686 #define FORWARD_TSN_CHUNK_SSN_OFFSET (FORWARD_TSN_CHUNK_SID_OFFSET + FORWARD_TSN_CHUNK_SID_LENGTH)
1687
1688 static void
1689 dissect_forward_tsn_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
1690 {
1691   guint   offset;
1692   guint16 number_of_affected_streams, affected_stream, length;
1693
1694   if (chunk_tree) {
1695     proto_tree_add_item(chunk_tree, hf_forward_tsn_chunk_tsn, chunk_tvb, FORWARD_TSN_CHUNK_TSN_OFFSET, FORWARD_TSN_CHUNK_TSN_LENGTH, NETWORK_BYTE_ORDER);
1696     length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1697     number_of_affected_streams = (length - CHUNK_HEADER_LENGTH - FORWARD_TSN_CHUNK_TSN_LENGTH) /
1698                                  (FORWARD_TSN_CHUNK_SID_LENGTH + FORWARD_TSN_CHUNK_SSN_LENGTH);
1699     offset = CHUNK_VALUE_OFFSET + FORWARD_TSN_CHUNK_TSN_LENGTH;
1700
1701     for(affected_stream = 0;  affected_stream < number_of_affected_streams; affected_stream++) {
1702         proto_tree_add_item(chunk_tree, hf_forward_tsn_chunk_sid, chunk_tvb, offset + FORWARD_TSN_CHUNK_SID_OFFSET, FORWARD_TSN_CHUNK_SID_LENGTH, NETWORK_BYTE_ORDER);
1703         proto_tree_add_item(chunk_tree, hf_forward_tsn_chunk_ssn, chunk_tvb, offset + FORWARD_TSN_CHUNK_SSN_OFFSET, FORWARD_TSN_CHUNK_SSN_LENGTH, NETWORK_BYTE_ORDER);
1704         offset = offset + (FORWARD_TSN_CHUNK_SID_LENGTH + FORWARD_TSN_CHUNK_SSN_LENGTH);
1705     }
1706     proto_item_append_text(chunk_item, "(Cumulative TSN: %u)", tvb_get_ntohl(chunk_tvb, FORWARD_TSN_CHUNK_TSN_OFFSET));
1707   }
1708 }
1709
1710 #define SERIAL_NUMBER_LENGTH    4
1711 #define SERIAL_NUMBER_OFFSET    PARAMETER_VALUE_OFFSET
1712 #define ASCONF_CHUNK_PARAMETERS_OFFSET (SERIAL_NUMBER_OFFSET + SERIAL_NUMBER_LENGTH)
1713
1714 static void
1715 dissect_asconf_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree)
1716 {
1717   guint parameters_length;
1718   tvbuff_t *parameters_tvb;
1719
1720   if (chunk_tree) {
1721     proto_tree_add_item(chunk_tree, hf_asconf_serial, chunk_tvb, SERIAL_NUMBER_OFFSET, SERIAL_NUMBER_LENGTH, NETWORK_BYTE_ORDER);
1722     parameters_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH - SERIAL_NUMBER_LENGTH;
1723     parameters_tvb    = tvb_new_subset(chunk_tvb, ASCONF_CHUNK_PARAMETERS_OFFSET, parameters_length, parameters_length);
1724     dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, FALSE);
1725   }
1726 }
1727
1728 #define ASCONF_ACK_CHUNK_PARAMETERS_OFFSET (SERIAL_NUMBER_OFFSET + SERIAL_NUMBER_LENGTH)
1729
1730 static void
1731 dissect_asconf_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree)
1732 {
1733   guint parameters_length;
1734   tvbuff_t *parameters_tvb;
1735
1736   if (chunk_tree) {
1737     proto_tree_add_item(chunk_tree, hf_asconf_ack_serial, chunk_tvb, SERIAL_NUMBER_OFFSET, SERIAL_NUMBER_LENGTH, NETWORK_BYTE_ORDER);
1738     parameters_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH - SERIAL_NUMBER_LENGTH;
1739     parameters_tvb    = tvb_new_subset(chunk_tvb, ASCONF_ACK_CHUNK_PARAMETERS_OFFSET, parameters_length, parameters_length);
1740     dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, FALSE);
1741   }
1742 }
1743
1744 #define PKTDROP_CHUNK_BANDWIDTH_LENGTH      4
1745 #define PKTDROP_CHUNK_QUEUESIZE_LENGTH      4
1746 #define PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH 2
1747 #define PKTDROP_CHUNK_RESERVED_SIZE_LENGTH  2
1748
1749 #define PKTDROP_CHUNK_HEADER_LENGTH (CHUNK_HEADER_LENGTH + \
1750                    PKTDROP_CHUNK_BANDWIDTH_LENGTH + \
1751                    PKTDROP_CHUNK_QUEUESIZE_LENGTH + \
1752                    PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH + \
1753                    PKTDROP_CHUNK_RESERVED_SIZE_LENGTH)
1754                    
1755 #define PKTDROP_CHUNK_BANDWIDTH_OFFSET      CHUNK_VALUE_OFFSET
1756 #define PKTDROP_CHUNK_QUEUESIZE_OFFSET      (PKTDROP_CHUNK_BANDWIDTH_OFFSET + PKTDROP_CHUNK_BANDWIDTH_LENGTH)
1757 #define PKTDROP_CHUNK_TRUNCATED_SIZE_OFFSET (PKTDROP_CHUNK_QUEUESIZE_OFFSET + PKTDROP_CHUNK_QUEUESIZE_LENGTH)
1758 #define PKTDROP_CHUNK_RESERVED_SIZE_OFFSET  (PKTDROP_CHUNK_TRUNCATED_SIZE_OFFSET + PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH)
1759 #define PKTDROP_CHUNK_DATA_FIELD_OFFSET     (PKTDROP_CHUNK_RESERVED_SIZE_OFFSET + PKTDROP_CHUNK_RESERVED_SIZE_LENGTH)
1760
1761 #define SCTP_PKTDROP_CHUNK_M_BIT 0x01
1762 #define SCTP_PKTDROP_CHUNK_B_BIT 0x02
1763 #define SCTP_PKTDROP_CHUNK_T_BIT 0x04
1764
1765 static const true_false_string sctp_pktdropk_m_bit_value = {
1766   "Source is a middlebox",
1767   "Source is an endhost"
1768 };
1769
1770 /*
1771 static const true_false_string sctp_pktdropk_s_bit_value = {
1772   "This is a summary",
1773   "This is not a summary"
1774 };
1775 */
1776
1777 static const true_false_string sctp_pktdropk_b_bit_value = {
1778   "SCTP checksum was incorrect",
1779   "SCTP checksum was correct"
1780 };
1781
1782 static const true_false_string sctp_pktdropk_t_bit_value = {
1783   "Packet is truncated",
1784   "Packet is not truncated"
1785 };
1786
1787 static void
1788 dissect_pktdrop_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *flags_item)
1789 {
1790   guint16 data_field_length;
1791   tvbuff_t *data_field_tvb;
1792   proto_tree *flags_tree;
1793
1794   data_field_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - PKTDROP_CHUNK_HEADER_LENGTH;
1795   data_field_tvb    = tvb_new_subset(chunk_tvb, PKTDROP_CHUNK_DATA_FIELD_OFFSET, data_field_length, data_field_length);
1796
1797   if (chunk_tree) {
1798     flags_tree  = proto_item_add_subtree(flags_item, ett_sctp_pktdrop_chunk_flags);
1799
1800     proto_tree_add_item(flags_tree, hf_pktdrop_chunk_m_bit,            chunk_tvb, CHUNK_FLAGS_OFFSET,                  CHUNK_FLAGS_LENGTH,                    NETWORK_BYTE_ORDER);
1801 /*
1802     proto_tree_add_item(flags_tree, hf_pktdrop_chunk_s_bit,            chunk_tvb, CHUNK_FLAGS_OFFSET,                  CHUNK_FLAGS_LENGTH,                    NETWORK_BYTE_ORDER);
1803 */
1804     proto_tree_add_item(flags_tree, hf_pktdrop_chunk_b_bit,            chunk_tvb, CHUNK_FLAGS_OFFSET,                  CHUNK_FLAGS_LENGTH,                    NETWORK_BYTE_ORDER);
1805     proto_tree_add_item(flags_tree, hf_pktdrop_chunk_t_bit,            chunk_tvb, CHUNK_FLAGS_OFFSET,                  CHUNK_FLAGS_LENGTH,                    NETWORK_BYTE_ORDER);
1806     proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_bandwidth,        chunk_tvb, PKTDROP_CHUNK_BANDWIDTH_OFFSET,      PKTDROP_CHUNK_BANDWIDTH_LENGTH,        NETWORK_BYTE_ORDER);
1807     proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_queuesize,        chunk_tvb, PKTDROP_CHUNK_QUEUESIZE_OFFSET,      PKTDROP_CHUNK_QUEUESIZE_LENGTH,        NETWORK_BYTE_ORDER);
1808     proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_truncated_length, chunk_tvb, PKTDROP_CHUNK_TRUNCATED_SIZE_OFFSET, PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH,   NETWORK_BYTE_ORDER);
1809     proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_reserved,         chunk_tvb, PKTDROP_CHUNK_RESERVED_SIZE_OFFSET,  PKTDROP_CHUNK_RESERVED_SIZE_LENGTH,    NETWORK_BYTE_ORDER);
1810     if (tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_PKTDROP_CHUNK_T_BIT)
1811       proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_data_field,       chunk_tvb, PKTDROP_CHUNK_DATA_FIELD_OFFSET,     data_field_length,                     NETWORK_BYTE_ORDER);
1812     else
1813       dissect_sctp_packet(data_field_tvb, pinfo, chunk_tree, TRUE);
1814   }
1815 }
1816
1817 static void
1818 dissect_unknown_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
1819 {
1820   guint chunk_value_length;
1821
1822   if (chunk_tree) {
1823     chunk_value_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
1824     if (chunk_value_length > 0)
1825       proto_tree_add_item(chunk_tree, hf_chunk_value, chunk_tvb, CHUNK_VALUE_OFFSET, chunk_value_length, NETWORK_BYTE_ORDER);
1826     proto_item_append_text(chunk_item, " (Type: %u, value length: %u byte%s)", tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET), chunk_value_length, plurality(chunk_value_length, "", "s"));
1827   }
1828 }
1829
1830 #define SCTP_CHUNK_BIT_1 0x80
1831 #define SCTP_CHUNK_BIT_2 0x40
1832
1833 static const true_false_string sctp_chunk_bit_1_value = {
1834   "Skip chunk and continue processing of the packet",
1835   "Stop processing of the packet"
1836 };
1837
1838 static const true_false_string sctp_chunk_bit_2_value = {
1839   "Do report",
1840   "Do not report"
1841 };
1842
1843
1844 static gboolean
1845 dissect_sctp_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *sctp_tree, gboolean useinfo)
1846 {
1847   guint8 type, flags;
1848   guint16 length, padding_length;
1849   gboolean result;
1850   proto_item *flags_item;
1851   proto_item *chunk_item;
1852   proto_tree *chunk_tree;
1853   proto_item *type_item;
1854   proto_tree *type_tree;
1855
1856   result = FALSE;
1857
1858   /* first extract the chunk header */
1859   type           = tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET);
1860   flags          = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
1861   length         = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1862   padding_length = tvb_length(chunk_tvb) - length;
1863
1864  if (useinfo && (check_col(pinfo->cinfo, COL_INFO)))
1865     col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(type, chunk_type_values, "RESERVED"));
1866  
1867   if (tree) {
1868     /* create proto_tree stuff */
1869     chunk_item   = proto_tree_add_text(sctp_tree, chunk_tvb, CHUNK_HEADER_OFFSET, tvb_length(chunk_tvb), "%s chunk", val_to_str(type, chunk_type_values, "RESERVED"));
1870     chunk_tree   = proto_item_add_subtree(chunk_item, ett_sctp_chunk);
1871
1872     /* then insert the chunk header components into the protocol tree */
1873     type_item  = proto_tree_add_item(chunk_tree, hf_chunk_type, chunk_tvb, CHUNK_TYPE_OFFSET, CHUNK_TYPE_LENGTH, NETWORK_BYTE_ORDER);
1874     type_tree  = proto_item_add_subtree(type_item, ett_sctp_chunk_type);
1875     proto_tree_add_item(type_tree, hf_chunk_bit_1,  chunk_tvb, CHUNK_TYPE_OFFSET,  CHUNK_TYPE_LENGTH,  NETWORK_BYTE_ORDER);
1876     proto_tree_add_item(type_tree, hf_chunk_bit_2,  chunk_tvb, CHUNK_TYPE_OFFSET,  CHUNK_TYPE_LENGTH,  NETWORK_BYTE_ORDER);
1877     flags_item = proto_tree_add_item(chunk_tree, hf_chunk_flags, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
1878     proto_tree_add_item(chunk_tree, hf_chunk_length, chunk_tvb, CHUNK_LENGTH_OFFSET, CHUNK_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
1879   } else {
1880     chunk_tree = NULL;
1881     chunk_item = NULL;
1882     flags_item = NULL;
1883   };
1884
1885   /* now dissect the chunk value */
1886
1887   switch(type) {
1888   case SCTP_DATA_CHUNK_ID:
1889     result = dissect_data_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1890     break;
1891   case SCTP_INIT_CHUNK_ID:
1892     dissect_init_chunk(chunk_tvb, pinfo, chunk_tree, chunk_item);
1893     break;
1894   case SCTP_INIT_ACK_CHUNK_ID:
1895     dissect_init_ack_chunk(chunk_tvb, pinfo, chunk_tree, chunk_item);
1896     break;
1897   case SCTP_SACK_CHUNK_ID:
1898     dissect_sack_chunk(chunk_tvb, chunk_tree, chunk_item);
1899     break;
1900   case SCTP_HEARTBEAT_CHUNK_ID:
1901     dissect_heartbeat_chunk(chunk_tvb, pinfo, chunk_tree, chunk_item);
1902     break;
1903   case SCTP_HEARTBEAT_ACK_CHUNK_ID:
1904     dissect_heartbeat_ack_chunk(chunk_tvb, pinfo, chunk_tree, chunk_item);
1905     break;
1906   case SCTP_ABORT_CHUNK_ID:
1907     dissect_abort_chunk(chunk_tvb, pinfo, chunk_tree, flags_item);
1908     break;
1909   case SCTP_SHUTDOWN_CHUNK_ID:
1910     dissect_shutdown_chunk(chunk_tvb, chunk_tree, chunk_item);
1911     break;
1912   case SCTP_SHUTDOWN_ACK_CHUNK_ID:
1913     dissect_shutdown_ack_chunk(chunk_tvb);
1914     break;
1915   case SCTP_ERROR_CHUNK_ID:
1916     dissect_error_chunk(chunk_tvb, pinfo, chunk_tree);
1917     break;
1918   case SCTP_COOKIE_ECHO_CHUNK_ID:
1919     dissect_cookie_echo_chunk(chunk_tvb, chunk_tree, chunk_item);
1920     break;
1921   case SCTP_COOKIE_ACK_CHUNK_ID:
1922     dissect_cookie_ack_chunk(chunk_tvb);
1923     break;
1924   case SCTP_ECNE_CHUNK_ID:
1925     dissect_ecne_chunk(chunk_tvb, chunk_tree, chunk_item);
1926     break;
1927   case SCTP_CWR_CHUNK_ID:
1928     dissect_cwr_chunk(chunk_tvb, chunk_tree, chunk_item);
1929     break;
1930   case SCTP_SHUTDOWN_COMPLETE_CHUNK_ID:
1931     dissect_shutdown_complete_chunk(chunk_tvb, chunk_tree, flags_item);
1932     break;
1933   case SCTP_FORWARD_TSN_CHUNK_ID:
1934     dissect_forward_tsn_chunk(chunk_tvb, chunk_tree, chunk_item);
1935     break;
1936   case SCTP_ASCONF_ACK_CHUNK_ID:
1937     dissect_asconf_ack_chunk(chunk_tvb, pinfo, chunk_tree);
1938     break;
1939   case SCTP_ASCONF_CHUNK_ID:
1940     dissect_asconf_chunk(chunk_tvb, pinfo, chunk_tree);
1941     break;
1942   case SCTP_PKTDROP_CHUNK_ID:
1943     col_set_writable(pinfo->cinfo, FALSE);
1944     dissect_pktdrop_chunk(chunk_tvb, pinfo, chunk_tree, flags_item);
1945     col_set_writable(pinfo->cinfo, TRUE);
1946     break;
1947   default:
1948     dissect_unknown_chunk(chunk_tvb, chunk_tree, chunk_item);
1949     break;
1950   }
1951   
1952   if (padding_length > 0)
1953     proto_tree_add_item(chunk_tree, hf_chunk_padding, chunk_tvb, CHUNK_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
1954
1955   if (useinfo && ((type == SCTP_DATA_CHUNK_ID) || show_always_control_chunks))
1956     col_set_fence(pinfo->cinfo, COL_INFO);
1957
1958   return result;
1959 }
1960
1961 static void
1962 dissect_sctp_chunks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *sctp_item, proto_tree *sctp_tree, gboolean encapsulated)
1963 {
1964   tvbuff_t *chunk_tvb;
1965   guint16 length, total_length, remaining_length;
1966   gint last_offset, offset;
1967   gboolean sctp_item_length_set;
1968   
1969   /* the common header of the datagram is already handled */
1970   last_offset = 0;
1971   offset = COMMON_HEADER_LENGTH;
1972   sctp_item_length_set = FALSE;
1973
1974   while((remaining_length = tvb_length_remaining(tvb, offset))) {
1975     /* extract the chunk length and compute number of padding bytes */
1976     length         = tvb_get_ntohs(tvb, offset + CHUNK_LENGTH_OFFSET);
1977     total_length   = ADD_PADDING(length);
1978     if (remaining_length >= length)
1979       total_length = MIN(total_length, remaining_length);
1980     /* create a tvb for the chunk including the padding bytes */
1981     chunk_tvb    = tvb_new_subset(tvb, offset, total_length, total_length);
1982
1983     /* save it in the sctp_info structure */
1984     if (!encapsulated) {
1985       if (sctp_info.number_of_tvbs < MAXIMUM_NUMBER_OF_TVBS)
1986         sctp_info.tvb[sctp_info.number_of_tvbs++] = chunk_tvb;
1987       else
1988         sctp_info.incomplete = TRUE;
1989     }
1990
1991     /* call dissect_sctp_chunk for the actual work */
1992     if (dissect_sctp_chunk(chunk_tvb, pinfo, tree, sctp_tree, !encapsulated) && (tree)) {
1993       proto_item_set_len(sctp_item, offset - last_offset + DATA_CHUNK_HEADER_LENGTH);
1994       sctp_item_length_set = TRUE;
1995       offset += total_length;
1996       last_offset = offset;
1997       if (tvb_reported_length_remaining(tvb, offset) > 0) {
1998         sctp_item = proto_tree_add_item(tree, proto_sctp, tvb, offset, -1, FALSE);
1999         sctp_tree = proto_item_add_subtree(sctp_item, ett_sctp);
2000         sctp_item_length_set = FALSE;
2001       }
2002     } else {
2003       /* get rid of the dissected chunk */
2004       offset += total_length;
2005     }
2006   }
2007   if (!sctp_item_length_set && (tree)) {
2008     proto_item_set_len(sctp_item, offset - last_offset);
2009   }
2010 }
2011
2012 static void
2013 dissect_sctp_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean encapsulated)
2014 {
2015   guint32 checksum = 0, calculated_crc32c = 0, calculated_adler32 = 0;
2016   guint length;
2017   gboolean crc32c_correct = FALSE, adler32_correct = FALSE;
2018   proto_item *sctp_item;
2019   proto_tree *sctp_tree;
2020
2021   length    = tvb_length(tvb);
2022   checksum  = tvb_get_ntohl(tvb, CHECKSUM_OFFSET);
2023   switch(sctp_checksum) {
2024   case SCTP_CHECKSUM_NONE:
2025     break;
2026   case SCTP_CHECKSUM_ADLER32:
2027     calculated_adler32           = sctp_adler32(tvb_get_ptr(tvb, 0, length), length);
2028     adler32_correct              = (checksum == calculated_adler32);
2029     sctp_info.adler32_calculated = TRUE;
2030     sctp_info.adler32_correct    = adler32_correct;
2031     break;
2032   case SCTP_CHECKSUM_CRC32C:
2033     calculated_crc32c            = sctp_crc32c(tvb_get_ptr(tvb, 0, length), length);
2034     crc32c_correct               = (checksum == calculated_crc32c);
2035     sctp_info.crc32c_calculated  = TRUE;
2036     sctp_info.crc32c_correct     = crc32c_correct;
2037     break;
2038   case SCTP_CHECKSUM_AUTOMATIC:
2039     calculated_adler32           = sctp_adler32(tvb_get_ptr(tvb, 0, length), length);
2040     adler32_correct              = (checksum == calculated_adler32);
2041     calculated_crc32c            = sctp_crc32c(tvb_get_ptr(tvb, 0, length), length);
2042     crc32c_correct               = (checksum == calculated_crc32c);
2043     sctp_info.adler32_calculated = TRUE;
2044     sctp_info.adler32_correct    = adler32_correct;
2045     sctp_info.crc32c_calculated  = TRUE;
2046     sctp_info.crc32c_correct     = crc32c_correct;
2047     break;
2048   }
2049   
2050   /* In the interest of speed, if "tree" is NULL, don't do any work not
2051      necessary to generate protocol tree items. */
2052   if (tree) {
2053     /* create the sctp protocol tree */
2054     sctp_item = proto_tree_add_item(tree, proto_sctp, tvb, 0, -1, FALSE);
2055     sctp_tree = proto_item_add_subtree(sctp_item, ett_sctp);
2056
2057     /* add the components of the common header to the protocol tree */
2058     proto_tree_add_item(sctp_tree, hf_source_port,      tvb, SOURCE_PORT_OFFSET,      SOURCE_PORT_LENGTH,      NETWORK_BYTE_ORDER);
2059     proto_tree_add_item(sctp_tree, hf_destination_port, tvb, DESTINATION_PORT_OFFSET, DESTINATION_PORT_LENGTH, NETWORK_BYTE_ORDER);
2060     proto_tree_add_item(sctp_tree, hf_verification_tag, tvb, VERIFICATION_TAG_OFFSET, VERIFICATION_TAG_LENGTH, NETWORK_BYTE_ORDER);
2061     proto_tree_add_item_hidden(sctp_tree, hf_port, tvb, SOURCE_PORT_OFFSET,      SOURCE_PORT_LENGTH,      NETWORK_BYTE_ORDER);
2062     proto_tree_add_item_hidden(sctp_tree, hf_port, tvb, DESTINATION_PORT_OFFSET, DESTINATION_PORT_LENGTH, NETWORK_BYTE_ORDER);
2063
2064     length    = tvb_length(tvb);
2065     checksum  = tvb_get_ntohl(tvb, CHECKSUM_OFFSET);
2066     switch(sctp_checksum) {
2067     case SCTP_CHECKSUM_NONE:
2068       proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, checksum, "Checksum: 0x%08x (not verified)", checksum);
2069       break;
2070     case SCTP_CHECKSUM_ADLER32:
2071       if (adler32_correct)
2072         proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2073                                    checksum, "Checksum: 0x%08x (correct Adler32)", checksum);
2074       else
2075         proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2076                                    checksum, "Checksum: 0x%08x (incorrect Adler32, should be 0x%08x)", checksum, calculated_adler32);
2077       proto_tree_add_boolean_hidden(sctp_tree, hf_checksum_bad, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, !(adler32_correct));
2078      break;
2079     case SCTP_CHECKSUM_CRC32C:
2080       if (crc32c_correct)
2081         proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2082                                    checksum, "Checksum: 0x%08x (correct CRC32C)", checksum);
2083       else
2084         proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2085                                    checksum, "Checksum: 0x%08x (incorrect CRC32C, should be 0x%08x)", checksum, calculated_crc32c);
2086       proto_tree_add_boolean_hidden(sctp_tree, hf_checksum_bad, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, !(crc32c_correct));
2087       break;
2088     case SCTP_CHECKSUM_AUTOMATIC:
2089       if ((adler32_correct) && !(crc32c_correct))
2090         proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2091                                    checksum, "Checksum: 0x%08x (correct Adler32)", checksum);
2092       else if (!(adler32_correct) && (crc32c_correct))
2093         proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2094                                    checksum, "Checksum: 0x%08x (correct CRC32C)", checksum);
2095       else if ((adler32_correct) && (crc32c_correct))
2096         proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2097                                    checksum, "Checksum: 0x%08x (correct Adler32 and CRC32C)", checksum);
2098       else
2099         proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2100                                    checksum, "Checksum: 0x%08x (incorrect, should be 0x%08x (Adler32) or 0x%08x (CRC32C))",
2101                                    checksum, calculated_adler32, calculated_crc32c);
2102       proto_tree_add_boolean_hidden(sctp_tree, hf_checksum_bad, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, !(crc32c_correct || adler32_correct));
2103       break;
2104     }
2105   } else {
2106     sctp_tree = NULL;
2107     sctp_item = NULL;
2108   };
2109   /* add all chunks of the sctp datagram to the protocol tree */
2110   dissect_sctp_chunks(tvb, pinfo, tree, sctp_item, sctp_tree, encapsulated);
2111 }
2112
2113 static void
2114 dissect_sctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2115 {
2116   guint16 source_port, destination_port;
2117   
2118   /* Extract the common header */
2119   source_port      = tvb_get_ntohs(tvb, SOURCE_PORT_OFFSET);
2120   destination_port = tvb_get_ntohs(tvb, DESTINATION_PORT_OFFSET);
2121
2122   /* update pi structure */
2123   pinfo->ptype    = PT_SCTP;
2124   pinfo->srcport  = source_port;
2125   pinfo->destport = destination_port;
2126
2127   /* make entry in the Protocol column on summary display */
2128   if (check_col(pinfo->cinfo, COL_PROTOCOL))
2129     col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCTP");
2130
2131   /* Clear entries in Info column on summary display */
2132   if (check_col(pinfo->cinfo, COL_INFO))
2133     col_set_str(pinfo->cinfo, COL_INFO, "");
2134       
2135   memset(&sctp_info, 0, sizeof(struct _sctp_info));
2136   sctp_info.verification_tag = tvb_get_ntohl(tvb, VERIFICATION_TAG_OFFSET);
2137   dissect_sctp_packet(tvb, pinfo, tree, FALSE);
2138   if (!pinfo->in_error_pkt)
2139     tap_queue_packet(sctp_tap, pinfo, &sctp_info);
2140 }
2141
2142 /* Register the protocol with Ethereal */
2143 void
2144 proto_register_sctp(void)
2145 {
2146
2147   /* Setup list of header fields */
2148   static hf_register_info hf[] = {
2149     { &hf_source_port,                              { "Source port",                                 "sctp.srcport",                               FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2150     { &hf_destination_port,                         { "Destination port",                            "sctp.dstport",                               FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2151     { &hf_port,                                     { "Port",                                        "sctp.port",                                  FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2152     { &hf_verification_tag,                         { "Verification tag",                            "sctp.verification_tag",                      FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                "", HFILL } },
2153     { &hf_checksum,                                 { "Checksum",                                    "sctp.checksum",                              FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                "", HFILL } },
2154     { &hf_checksum_bad,                             { "Bad checksum",                                "sctp.checksum_bad",                          FT_BOOLEAN, BASE_NONE, NULL,                                           0x0,                                "", HFILL } },
2155     { &hf_chunk_type,                               { "Chunk type",                                  "sctp.chunk_type",                            FT_UINT8,   BASE_DEC,  VALS(chunk_type_values),                        0x0,                                "", HFILL } },
2156     { &hf_chunk_flags,                              { "Chunk flags",                                 "sctp.chunk_flags",                           FT_UINT8,   BASE_HEX,  NULL,                                           0x0,                                "", HFILL } },
2157     { &hf_chunk_bit_1,                              { "Bit",                                         "sctp.chunk_bit_1",                           FT_BOOLEAN, 8,         TFS(&sctp_chunk_bit_1_value),                   SCTP_CHUNK_BIT_1,                   "", HFILL } },
2158     { &hf_chunk_bit_2,                              { "Bit",                                         "sctp.chunk_bit_2",                           FT_BOOLEAN, 8,         TFS(&sctp_chunk_bit_2_value),                   SCTP_CHUNK_BIT_2,                   "", HFILL } },
2159     { &hf_chunk_length,                             { "Chunk length",                                "sctp.chunk_length",                          FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2160     { &hf_chunk_padding,                            { "Chunk padding",                               "sctp.chunk_padding",                         FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                "", HFILL } },
2161     { &hf_chunk_value,                              { "Chunk value",                                 "sctp.chunk_value",                           FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                "", HFILL } },
2162     { &hf_cookie,                                   { "Cookie",                                      "sctp.cookie",                                FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                "", HFILL } },
2163     { &hf_initiate_tag,                             { "Initiate tag",                                "sctp.initiate_tag",                          FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                "", HFILL } },
2164     { &hf_init_chunk_initiate_tag,                  { "Initiate tag",                                "sctp.init_initiate_tag",                     FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                "", HFILL } },
2165     { &hf_init_chunk_adv_rec_window_credit,         { "Advertised receiver window credit (a_rwnd)",  "sctp.init_credit",                           FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2166     { &hf_init_chunk_number_of_outbound_streams,    { "Number of outbound streams",                  "sctp.init_nr_out_streams",                   FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2167     { &hf_init_chunk_number_of_inbound_streams,     { "Number of inbound streams",                   "sctp.init_nr_in_streams",                    FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2168     { &hf_init_chunk_initial_tsn,                   { "Initial TSN",                                 "sctp.init_initial_tsn",                      FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2169     { &hf_initack_chunk_initiate_tag,               { "Initiate tag",                                "sctp.initack_initiate_tag",                  FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                "", HFILL } },
2170     { &hf_initack_chunk_adv_rec_window_credit,      { "Advertised receiver window credit (a_rwnd)",  "sctp.initack_credit",                        FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2171     { &hf_initack_chunk_number_of_outbound_streams, { "Number of outbound streams",                  "sctp.initack_nr_out_streams",                FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2172     { &hf_initack_chunk_number_of_inbound_streams,  { "Number of inbound streams",                   "sctp.initack_nr_in_streams",                 FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2173     { &hf_initack_chunk_initial_tsn,                { "Initial TSN",                                 "sctp.initack_initial_tsn",                   FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2174     { &hf_cumulative_tsn_ack,                       { "Cumulative TSN Ack",                          "sctp.cumulative_tsn_ack",                    FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2175     { &hf_data_chunk_tsn,                           { "TSN",                                         "sctp.data_tsn",                              FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2176     { &hf_data_chunk_stream_id,                     { "Stream Identifier",                           "sctp.data_sid",                              FT_UINT16,  BASE_HEX,  NULL,                                           0x0,                                "", HFILL } },
2177     { &hf_data_chunk_stream_seq_number,             { "Stream sequence number",                      "sctp.data_ssn",                              FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2178     { &hf_data_chunk_payload_proto_id,              { "Payload protocol identifier",                 "sctp.data_payload_proto_id",                 FT_UINT32,  BASE_DEC,  VALS(sctp_payload_proto_id_values),             0x0,                                "", HFILL } },
2179     { &hf_data_chunk_e_bit,                         { "E-Bit",                                       "sctp.data_e_bit",                            FT_BOOLEAN, 8,         TFS(&sctp_data_chunk_e_bit_value),              SCTP_DATA_CHUNK_E_BIT,              "", HFILL } },
2180     { &hf_data_chunk_b_bit,                         { "B-Bit",                                       "sctp.data_b_bit",                            FT_BOOLEAN, 8,         TFS(&sctp_data_chunk_b_bit_value),              SCTP_DATA_CHUNK_B_BIT,              "", HFILL } },
2181     { &hf_data_chunk_u_bit,                         { "U-Bit",                                       "sctp.data_u_bit",                            FT_BOOLEAN, 8,         TFS(&sctp_data_chunk_u_bit_value),              SCTP_DATA_CHUNK_U_BIT,              "", HFILL } },
2182     { &hf_sack_chunk_cumulative_tsn_ack,            { "Cumulative TSN ACK",                          "sctp.sack_cumulative_tsn_ack",               FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2183     { &hf_sack_chunk_adv_rec_window_credit,         { "Advertised receiver window credit (a_rwnd)",  "sctp.sack_a_rwnd",                           FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2184     { &hf_sack_chunk_number_of_gap_blocks,          { "Number of gap acknowldgement blocks ",        "sctp.sack_number_of_gap_blocks",             FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2185     { &hf_sack_chunk_number_of_dup_tsns,            { "Number of duplicated TSNs",                   "sctp.sack_number_of_duplicated_tsns",        FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2186     { &hf_sack_chunk_gap_block_start,               { "Start",                                       "sctp.sack_gap_block_start",                  FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2187     { &hf_sack_chunk_gap_block_end,                 { "End",                                         "sctp.sack_gap_block_end",                    FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2188     { &hf_sack_chunk_duplicate_tsn,                 { "Duplicate TSN",                               "sctp.sack_duplicate_tsn",                    FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2189     { &hf_shutdown_chunk_cumulative_tsn_ack,        { "Cumulative TSN Ack",                          "sctp.shutdown_cumulative_tsn_ack",           FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2190     { &hf_ecne_chunk_lowest_tsn,                    { "Lowest TSN",                                  "sctp.ecne_lowest_tsn",                       FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2191     { &hf_cwr_chunk_lowest_tsn,                     { "Lowest TSN",                                  "sctp.cwr_lowest_tsn",                        FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2192     { &hf_shutdown_complete_chunk_t_bit,            { "T-Bit",                                       "sctp.shutdown_complete_t_bit",               FT_BOOLEAN, 8,         TFS(&sctp_shutdown_complete_chunk_t_bit_value), SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT, "", HFILL } },
2193     { &hf_abort_chunk_t_bit,                        { "T-Bit",                                       "sctp.abort_t_bit",                           FT_BOOLEAN, 8,         TFS(&sctp_shutdown_complete_chunk_t_bit_value), SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT, "", HFILL } },
2194     { &hf_forward_tsn_chunk_tsn,                    { "New cumulative TSN",                          "sctp.forward_tsn_tsn",                       FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2195     { &hf_forward_tsn_chunk_sid,                    { "Stream identifier",                           "sctp.forward_tsn_sid",                       FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2196     { &hf_forward_tsn_chunk_ssn,                    { "Stream sequence number",                      "sctp.forward_tsn_ssn",                       FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2197     { &hf_parameter_type,                           { "Parameter type",                              "sctp.parameter_type",                        FT_UINT16,  BASE_HEX,  VALS(parameter_identifier_values),              0x0,                                "", HFILL } },
2198     { &hf_parameter_length,                         { "Parameter length",                            "sctp.parameter_length",                      FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2199     { &hf_parameter_value,                          { "Parameter value",                             "sctp.parameter_value",                       FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                "", HFILL } },
2200     { &hf_parameter_padding,                        { "Parameter padding",                           "sctp.parameter_padding",                     FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                "", HFILL } },
2201     { &hf_parameter_bit_1,                          { "Bit",                                         "sctp.parameter_bit_1",                       FT_BOOLEAN, 16,        TFS(&sctp_parameter_bit_1_value),               SCTP_PARAMETER_BIT_1,               "", HFILL } },
2202     { &hf_parameter_bit_2,                          { "Bit",                                         "sctp.parameter_bit_2",                       FT_BOOLEAN, 16,        TFS(&sctp_parameter_bit_2_value),               SCTP_PARAMETER_BIT_2,               "", HFILL } },
2203     { &hf_ipv4_address,                             { "IP Version 4 address",                        "sctp.parameter_ipv4_address",                FT_IPv4,    BASE_NONE, NULL,                                           0x0,                                "", HFILL } },
2204     { &hf_ipv6_address,                             { "IP Version 6 address",                        "sctp.parameter_ipv6_address",                FT_IPv6,    BASE_NONE, NULL,                                           0x0,                                "", HFILL } },
2205     { &hf_heartbeat_info,                           { "Heartbeat information",                       "sctp.parameter_heartbeat_information",       FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                "", HFILL } },
2206     { &hf_state_cookie,                             { "State cookie",                                "sctp.parameter_state_cookie",                FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                "", HFILL } },
2207     { &hf_cookie_preservative_increment,            { "Suggested Cookie life-span increment (msec)", "sctp.parameter_cookie_preservative_incr",    FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2208     { &hf_hostname,                                 { "Hostname",                                    "sctp.parameter_hostname",                    FT_STRING,  BASE_NONE, NULL,                                           0x0,                                "", HFILL } },
2209     { &hf_supported_address_type,                   { "Supported address type",                      "sctp.parameter_supported_addres_type",       FT_UINT16,  BASE_DEC,  VALS(address_types_values),                     0x0,                                "", HFILL } },
2210     { &hf_asconf_serial,                            { "Serial Number",                               "sctp.asconf_serial_number",                  FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                "", HFILL } },
2211     { &hf_asconf_ack_serial,                        { "Serial Number",                               "sctp.asconf_ack_serial_number",              FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                "", HFILL } },
2212     { &hf_correlation_id,                           { "Correlation_id",                              "sctp.correlation_id",                        FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                "", HFILL } },
2213     { &hf_adap_indication,                          { "Indication",                                  "sctp.adapation_layer_indication",            FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                "", HFILL } },
2214     { &hf_cause_code,                               { "Cause code",                                  "sctp.cause_code",                            FT_UINT16,  BASE_HEX,  VALS(cause_code_values),                        0x0,                                "", HFILL } },
2215     { &hf_cause_length,                             { "Cause length",                                "sctp.cause_length",                          FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2216     { &hf_cause_info,                               { "Cause information",                           "sctp.cause_information",                     FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                "", HFILL } },
2217     { &hf_cause_padding,                            { "Cause padding",                               "sctp.cause_padding",                         FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                "", HFILL } },
2218     { &hf_cause_stream_identifier,                  { "Stream identifier",                           "sctp.cause_stream_identifier",               FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2219     { &hf_cause_reserved,                           { "Reserved",                                    "sctp.cause_reserved",                        FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2220     { &hf_cause_number_of_missing_parameters,       { "Number of missing parameters",                "sctp.cause_nr_of_missing_parameters",        FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2221     { &hf_cause_missing_parameter_type,             { "Missing parameter type",                      "sctp.cause_missing_parameter_type",          FT_UINT16,  BASE_HEX,  VALS(parameter_identifier_values),              0x0,                                "", HFILL } },
2222     { &hf_cause_measure_of_staleness,               { "Measure of staleness in usec",                "sctp.cause_measure_of_staleness",            FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2223     { &hf_cause_tsn,                                { "TSN",                                         "sctp.cause_tsn",                             FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2224     { &hf_pktdrop_chunk_m_bit,                      { "M-Bit",                                       "sctp.pckdrop_m_bit",                         FT_BOOLEAN, 8,         TFS(&sctp_pktdropk_m_bit_value),                SCTP_PKTDROP_CHUNK_M_BIT,           "", HFILL } },
2225     { &hf_pktdrop_chunk_b_bit,                      { "B-Bit",                                       "sctp.pckdrop_b_bit",                         FT_BOOLEAN, 8,         TFS(&sctp_pktdropk_b_bit_value),                SCTP_PKTDROP_CHUNK_B_BIT,           "", HFILL } },
2226     { &hf_pktdrop_chunk_t_bit,                      { "T-Bit",                                       "sctp.pckdrop_t_bit",                         FT_BOOLEAN, 8,         TFS(&sctp_pktdropk_t_bit_value),                SCTP_PKTDROP_CHUNK_T_BIT,           "", HFILL } },
2227     { &hf_pktdrop_chunk_bandwidth,                  { "Bandwidth",                                   "sctp.pktdrop_bandwidth",                     FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2228     { &hf_pktdrop_chunk_queuesize,                  { "Queuesize",                                   "sctp.pktdrop_queuesize",                     FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2229     { &hf_pktdrop_chunk_truncated_length,           { "Truncated length",                            "sctp.pktdrop_truncated_length",              FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2230     { &hf_pktdrop_chunk_reserved,                   { "Reserved",                                    "sctp.pktdrop_reserved",                      FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                "", HFILL } },
2231     { &hf_pktdrop_chunk_data_field,                 { "Data field",                                  "sctp.pktdrop_datafield",                     FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                "", HFILL } },
2232  };
2233
2234   /* Setup protocol subtree array */
2235   static gint *ett[] = {
2236     &ett_sctp,
2237     &ett_sctp_chunk,
2238     &ett_sctp_chunk_parameter,
2239     &ett_sctp_chunk_cause,
2240     &ett_sctp_chunk_type,
2241     &ett_sctp_data_chunk_flags,
2242     &ett_sctp_abort_chunk_flags,
2243     &ett_sctp_shutdown_complete_chunk_flags,
2244     &ett_sctp_pktdrop_chunk_flags,
2245     &ett_sctp_parameter_type,
2246     &ett_sctp_sack_chunk_gap_block,
2247     &ett_sctp_unrecognized_parameter_parameter,
2248   };
2249
2250   static enum_val_t sctp_checksum_options[] = {
2251     { "none",      "None",        SCTP_CHECKSUM_NONE },
2252     { "adler-32",  "Adler 32",    SCTP_CHECKSUM_ADLER32 },
2253     { "crc-32c",   "CRC 32c",     SCTP_CHECKSUM_CRC32C },
2254     { "automatic", "Automatic",   SCTP_CHECKSUM_AUTOMATIC},
2255     { NULL, NULL, 0 }
2256   };
2257
2258   /* Register the protocol name and description */
2259   proto_sctp = proto_register_protocol("Stream Control Transmission Protocol", "SCTP", "sctp");
2260   sctp_module = prefs_register_protocol(proto_sctp, NULL);
2261   prefs_register_enum_preference(sctp_module, "checksum", "Checksum type",
2262                          "The type of checksum used in SCTP packets",
2263                          &sctp_checksum, sctp_checksum_options, FALSE);
2264   prefs_register_bool_preference(sctp_module, "show_always_control_chunks",
2265                          "Show always control chunks",
2266                          "Show always SCTP control chunks in the Info column",
2267                          &show_always_control_chunks);
2268   prefs_register_bool_preference(sctp_module, "try_heuristic_first",
2269                          "Try heuristic sub-dissectors first",
2270                          "Try to decode a packet using an heuristic sub-dissector before using a sub-dissector registered to a specific port or PPI",
2271                          &try_heuristic_first);
2272
2273   /* Required function calls to register the header fields and subtrees used */
2274   proto_register_field_array(proto_sctp, hf, array_length(hf));
2275   proto_register_subtree_array(ett, array_length(ett));
2276   sctp_tap = register_tap("sctp");
2277   /* subdissector code */
2278   sctp_port_dissector_table = register_dissector_table("sctp.port", "SCTP port", FT_UINT16, BASE_DEC);
2279   sctp_ppi_dissector_table  = register_dissector_table("sctp.ppi",  "SCTP payload protocol identifier", FT_UINT32, BASE_HEX);
2280   register_heur_dissector_list("sctp", &sctp_heur_subdissector_list);
2281 }
2282
2283 void
2284 proto_reg_handoff_sctp(void)
2285 {
2286   dissector_handle_t sctp_handle;
2287
2288   data_handle = find_dissector("data");
2289   sctp_handle = create_dissector_handle(dissect_sctp, proto_sctp);
2290   dissector_add("ip.proto", IP_PROTO_SCTP, sctp_handle);
2291   dissector_add("udp.port", UDP_TUNNELING_PORT, sctp_handle);
2292 }