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