Rename function and variables for dissecting an NT service Account Control
[obnox/wireshark/wip.git] / packet-sctp.c
1 /* packet-sctp.c
2  * Routines for Stream Control Transmission Protocol dissection
3  * It should be compilant to
4  * - RFC 2960, for basic SCTP support
5  * - http://www.ietf.org/internet-drafts/draft-ietf-tsvwg-addip-sctp-03.txt for the add-IP extension
6  * - http://www.sctp.org/draft-ietf-tsvwg-usctp-01.txt for the 'Limited Retransmission' extension
7  * - http://www.ietf.org/internet-drafts/draft-ietf-tsvwg-sctpcsum-03.txt
8  * Copyright 2000, 2001, 2002, Michael Tuexen <Michael.Tuexen@icn.siemens.de>
9  * Still to do (so stay tuned)
10  * - support for reassembly
11  * - code cleanup
12  *
13  * $Id: packet-sctp.c,v 1.33 2002/03/03 22:42:08 guy Exp $
14  *
15  * Ethereal - Network traffic analyzer
16  * By Gerald Combs <gerald@ethereal.com>
17  * Copyright 1998 Gerald Combs
18  *
19  * Copied from README.developer
20  * 
21  * This program is free software; you can redistribute it and/or
22  * modify it under the terms of the GNU General Public License
23  * as published by the Free Software Foundation; either version 2
24  * of the License, or (at your option) any later version.
25  * 
26  * This program is distributed in the hope that it will be useful,
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
29  * GNU General Public License for more details.
30  * 
31  * You should have received a copy of the GNU General Public License
32  * along with this program; if not, write to the Free Software
33  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34  */
35
36 #ifdef HAVE_CONFIG_H
37 # include "config.h"
38 #endif
39
40 #include <stdio.h>
41 #include <stdlib.h>
42
43
44 #ifdef HAVE_SYS_TYPES_H
45 # include <sys/types.h>
46 #endif
47
48 #ifdef HAVE_NETINET_IN_H
49 # include <netinet/in.h>
50 #endif
51
52 #include <string.h>
53 #include <glib.h>
54
55 #ifdef NEED_SNPRINTF_H
56 # include "snprintf.h"
57 #endif
58
59 #include "prefs.h"
60 #include <epan/packet.h>
61 #include "ipproto.h"
62
63 /* Initialize the protocol and registered fields */
64 static int proto_sctp = -1;
65 static int hf_sctp_port = -1;
66 static int hf_sctp_source_port      = -1;
67 static int hf_sctp_destination_port = -1;
68 static int hf_sctp_verification_tag = -1;
69 static int hf_sctp_checksum         = -1;
70 static int hf_sctp_checksum_bad     = -1;
71
72 static int hf_sctp_chunk_type       = -1;
73 static int hf_sctp_chunk_flags      = -1;
74 static int hf_sctp_chunk_length     = -1;
75
76 static int hf_sctp_init_chunk_initiate_tag   = -1;
77 static int hf_sctp_init_chunk_adv_rec_window_credit = -1;
78 static int hf_sctp_init_chunk_number_of_outbound_streams = -1;
79 static int hf_sctp_init_chunk_number_of_inbound_streams  = -1;
80 static int hf_sctp_init_chunk_initial_tsn    = -1;
81
82 static int hf_sctp_cumulative_tsn_ack = -1;
83
84 static int hf_sctp_data_chunk_tsn = -1;
85 static int hf_sctp_data_chunk_stream_id = -1;
86 static int hf_sctp_data_chunk_stream_seq_number = -1;
87 static int hf_sctp_data_chunk_payload_proto_id = -1;
88
89 static int hf_sctp_data_chunk_e_bit = -1;
90 static int hf_sctp_data_chunk_b_bit = -1;
91 static int hf_sctp_data_chunk_u_bit = -1;
92
93 static int hf_sctp_sack_chunk_cumulative_tsn_ack = -1;
94 static int hf_sctp_sack_chunk_adv_rec_window_credit = -1;
95 static int hf_sctp_sack_chunk_number_of_gap_blocks = -1;
96 static int hf_sctp_sack_chunk_number_of_dup_tsns = -1;
97 static int hf_sctp_sack_chunk_gap_block_start = -1;
98 static int hf_sctp_sack_chunk_gap_block_end = -1;
99 static int hf_sctp_sack_chunk_duplicate_tsn = -1;
100
101 static int hf_sctp_shutdown_chunk_cumulative_tsn_ack = -1;
102
103 static int hf_sctp_cwr_chunk_lowest_tsn = -1;
104
105 static int hf_sctp_ecne_chunk_lowest_tsn = -1;
106
107 static int hf_sctp_shutdown_complete_chunk_t_bit = -1;
108
109 static int hf_sctp_chunk_parameter_type = -1;
110 static int hf_sctp_chunk_parameter_length = -1;
111 static int hf_sctp_parameter_ipv4_address = -1;
112 static int hf_sctp_parameter_ipv6_address = -1;
113 static int hf_sctp_parameter_cookie_preservative_increment = -1;
114 static int hf_sctp_parameter_hostname_hostname = -1;
115 static int hf_sctp_supported_address_types_parameter = -1;
116
117 static int hf_sctp_cause_code = -1;
118 static int hf_sctp_cause_length = -1;
119 static int hf_sctp_cause_stream_identifier = -1;
120
121 static int hf_sctp_cause_number_of_missing_parameters = -1;
122 static int hf_sctp_cause_missing_parameter_type = -1;
123
124 static int hf_sctp_cause_measure_of_staleness = -1;
125
126 static int hf_sctp_cause_tsn = -1;
127
128 static int hf_sctp_forward_tsn_chunk_tsn = -1;
129
130 static int hf_sctp_ustreams_start = -1;
131 static int hf_sctp_ustreams_end   = -1;
132
133 static int hf_sctp_asconf_ack_serial = -1;
134 static int hf_sctp_asconf_ack_correlation_id = -1;
135
136 static int hf_sctp_asconf_serial = -1;
137 static int hf_sctp_asconf_correlation_id = -1;
138 static int hf_sctp_asconf_reserved = -1;
139 static int hf_sctp_asconf_addr_type = -1;
140 static int hf_sctp_asconf_addr = -1;
141 static int hf_sctp_asconf_ipv4_address = -1;
142 static int hf_sctp_asconf_ipv6_address = -1;
143 static int hf_sctp_adap_indication = -1;
144
145 static dissector_table_t sctp_port_dissector_table;
146 static dissector_table_t sctp_ppi_dissector_table;
147
148 static module_t *sctp_module;
149
150 /* Initialize the subtree pointers */
151 static gint ett_sctp = -1;
152 static gint ett_sctp_chunk = -1;
153 static gint ett_sctp_chunk_parameter = -1;
154 static gint ett_sctp_chunk_cause = -1;
155 static gint ett_sctp_data_chunk_flags = -1;
156 static gint ett_sctp_sack_chunk_gap_block = -1;
157 static gint ett_sctp_supported_address_types_parameter = -1;
158 static gint ett_sctp_unrecognized_parameter_parameter = -1;
159 static gint ett_sctp_unreliable_streams_interval = -1;
160
161 #define SCTP_DATA_CHUNK_ID               0
162 #define SCTP_INIT_CHUNK_ID               1
163 #define SCTP_INIT_ACK_CHUNK_ID           2
164 #define SCTP_SACK_CHUNK_ID               3
165 #define SCTP_HEARTBEAT_CHUNK_ID          4
166 #define SCTP_HEARTBEAT_ACK_CHUNK_ID      5
167 #define SCTP_ABORT_CHUNK_ID              6
168 #define SCTP_SHUTDOWN_CHUNK_ID           7
169 #define SCTP_SHUTDOWN_ACK_CHUNK_ID       8
170 #define SCTP_ERROR_CHUNK_ID              9
171 #define SCTP_COOKIE_ECHO_CHUNK_ID       10
172 #define SCTP_COOKIE_ACK_CHUNK_ID        11
173 #define SCTP_ECNE_CHUNK_ID              12
174 #define SCTP_CWR_CHUNK_ID               13
175 #define SCTP_SHUTDOWN_COMPLETE_CHUNK_ID 14
176 #define SCTP_FORWARD_TSN_CHUNK_ID      192 
177 #define SCTP_ASCONF_ACK_CHUNK_ID      0x80
178 #define SCTP_ASCONF_CHUNK_ID          0XC1
179
180 #define SCTP_IETF_EXT                  255
181
182 static const value_string sctp_chunk_type_values[] = {
183   { SCTP_DATA_CHUNK_ID,              "DATA" },
184   { SCTP_INIT_CHUNK_ID,              "INIT" },
185   { SCTP_INIT_ACK_CHUNK_ID,          "INIT_ACK" },
186   { SCTP_SACK_CHUNK_ID,              "SACK" },
187   { SCTP_HEARTBEAT_CHUNK_ID,         "HEARTBEAT" },
188   { SCTP_HEARTBEAT_ACK_CHUNK_ID,     "HEARTBEAT_ACK" },
189   { SCTP_ABORT_CHUNK_ID,             "ABORT" },
190   { SCTP_SHUTDOWN_CHUNK_ID,          "SHUTDOWN" },
191   { SCTP_SHUTDOWN_ACK_CHUNK_ID,      "SHUTDOWN_ACK" },
192   { SCTP_ERROR_CHUNK_ID,             "ERROR" },
193   { SCTP_COOKIE_ECHO_CHUNK_ID,       "COOKIE_ECHO" },
194   { SCTP_COOKIE_ACK_CHUNK_ID,        "COOKIE_ACK" },
195   { SCTP_ECNE_CHUNK_ID,              "ECNE" },
196   { SCTP_CWR_CHUNK_ID,               "CWR" },
197   { SCTP_SHUTDOWN_COMPLETE_CHUNK_ID, "SHUTDOWN_COMPLETE" },
198   { SCTP_FORWARD_TSN_CHUNK_ID,       "FORWARD TSN" },
199   { SCTP_ASCONF_ACK_CHUNK_ID,        "ASCONF_ACK" },
200   { SCTP_ASCONF_CHUNK_ID,            "ASCONF" },
201   { SCTP_IETF_EXT,                   "IETF_EXTENSION" },
202   { 0,                               NULL } };
203
204 #define HEARTBEAT_INFO_PARAMETER_ID          0x0001
205 #define IPV4ADDRESS_PARAMETER_ID             0x0005
206 #define IPV6ADDRESS_PARAMETER_ID             0x0006
207 #define STATE_COOKIE_PARAMETER_ID            0x0007
208 #define UNREC_PARA_PARAMETER_ID              0x0008
209 #define COOKIE_PRESERVATIVE_PARAMETER_ID     0x0009
210 #define HOSTNAME_ADDRESS_PARAMETER_ID        0x000b
211 #define SUPPORTED_ADDRESS_TYPES_PARAMETER_ID 0x000c
212 #define ECN_PARAMETER_ID                     0x8000
213 #define UNRELIABLE_STREAMS_PARAMETER_ID      0xC000
214 #define ADD_IP_ADDRESS_PARAMETER_ID          0xC001
215 #define DEL_IP_ADDRESS_PARAMETER_ID          0xC002
216 #define ERROR_CAUSE_INDICATION_PARAMETER_ID  0xC003
217 #define SET_PRIMARY_ADDRESS_PARAMETER_ID     0xC004
218 #define SUCCESS_REPORT_PARAMETER_ID          0xC005
219 #define ADAP_LAYER_INDICATION_PARAMETER_ID   0xC006
220
221 static const value_string sctp_parameter_identifier_values[] = {
222   { HEARTBEAT_INFO_PARAMETER_ID,          "Heartbeat info" },
223   { IPV4ADDRESS_PARAMETER_ID,             "IPv4 address" },
224   { IPV6ADDRESS_PARAMETER_ID,             "IPv6 address" },
225   { STATE_COOKIE_PARAMETER_ID,            "State cookie" },
226   { UNREC_PARA_PARAMETER_ID,              "Unrecognized parameters" },
227   { COOKIE_PRESERVATIVE_PARAMETER_ID,     "Cookie preservative" },
228   { HOSTNAME_ADDRESS_PARAMETER_ID,        "Hostname address" },
229   { SUPPORTED_ADDRESS_TYPES_PARAMETER_ID, "Supported address types" },
230   { ECN_PARAMETER_ID,                     "ECN" },
231   { UNRELIABLE_STREAMS_PARAMETER_ID,      "Unreliable streams" },
232   { ADD_IP_ADDRESS_PARAMETER_ID,          "Add IP address" },
233   { DEL_IP_ADDRESS_PARAMETER_ID,          "Delete IP address" },
234   { ERROR_CAUSE_INDICATION_PARAMETER_ID,  "Error cause indication" },
235   { SET_PRIMARY_ADDRESS_PARAMETER_ID,     "Set primary address" },
236   { SUCCESS_REPORT_PARAMETER_ID,          "Success report" },
237   { ADAP_LAYER_INDICATION_PARAMETER_ID,   "Adaptation Layer Indication" },
238   { 0,                                    NULL } };
239
240 #define PARAMETER_TYPE_LENGTH            2
241 #define PARAMETER_LENGTH_LENGTH          2
242 #define PARAMETER_HEADER_LENGTH          (PARAMETER_TYPE_LENGTH + PARAMETER_LENGTH_LENGTH)
243
244 #define PARAMETER_HEADER_OFFSET          0
245 #define PARAMETER_TYPE_OFFSET            PARAMETER_HEADER_OFFSET
246 #define PARAMETER_LENGTH_OFFSET          (PARAMETER_TYPE_OFFSET + PARAMETER_TYPE_LENGTH)
247 #define PARAMETER_VALUE_OFFSET           (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
248
249 #define HEARTBEAT_INFO_PARAMETER_INFO_OFFSET PARAMETER_VALUE_OFFSET
250 #define HEARTBEAT_INFO_PARAMETER_HEADER_LENGTH PARAMETER_HEADER_LENGTH
251
252 #define IPV4_ADDRESS_LENGTH              4
253 #define IPV6_ADDRESS_LENGTH              16
254
255 #define STATE_COOKIE_PARAMETER_HEADER_LENGTH   PARAMETER_HEADER_LENGTH
256 #define STATE_COOKIE_PARAMETER_COOKIE_OFFSET   PARAMETER_VALUE_OFFSET
257
258 #define COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET PARAMETER_VALUE_OFFSET
259 #define COOKIE_PRESERVATIVE_PARAMETER_INCR_LENGTH 4
260 #define SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH 2
261
262 #define CAUSE_CODE_LENGTH            2
263 #define CAUSE_LENGTH_LENGTH          2
264 #define CAUSE_HEADER_LENGTH          (CAUSE_CODE_LENGTH + CAUSE_LENGTH_LENGTH)
265
266 #define CAUSE_HEADER_OFFSET          0
267 #define CAUSE_CODE_OFFSET            CAUSE_HEADER_OFFSET
268 #define CAUSE_LENGTH_OFFSET          (CAUSE_CODE_OFFSET + CAUSE_CODE_LENGTH)
269 #define CAUSE_INFO_OFFSET            (CAUSE_LENGTH_OFFSET + CAUSE_LENGTH_LENGTH)
270
271 #define CAUSE_STREAM_IDENTIFIER_LENGTH 2
272 #define CAUSE_RESERVED_LENGTH 2
273 #define CAUSE_STREAM_IDENTIFIER_OFFSET CAUSE_INFO_OFFSET
274 #define CAUSE_RESERVED_OFFSET          (CAUSE_STREAM_IDENTIFIER_OFFSET + CAUSE_STREAM_IDENTIFIER_LENGTH)
275
276 #define CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH 4
277 #define CAUSE_MISSING_PARAMETER_TYPE_LENGTH       2
278
279 #define CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET CAUSE_INFO_OFFSET
280 #define CAUSE_FIRST_MISSING_PARAMETER_TYPE_OFFSET (CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET + \
281                                                    CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH )
282
283 #define CAUSE_MEASURE_OF_STALENESS_LENGTH 4
284 #define CAUSE_MEASURE_OF_STALENESS_OFFSET CAUSE_INFO_OFFSET
285
286 #define CAUSE_TSN_LENGTH 4
287 #define CAUSE_TSN_OFFSET CAUSE_INFO_OFFSET
288
289 #define INVALID_STREAM_IDENTIFIER                  0x01
290 #define MISSING_MANDATORY_PARAMETERS               0x02
291 #define STALE_COOKIE_ERROR                         0x03
292 #define OUT_OF_RESOURCE                            0x04
293 #define UNRESOLVABLE_ADDRESS                       0x05
294 #define UNRECOGNIZED_CHUNK_TYPE                    0x06
295 #define INVALID_MANDATORY_PARAMETER                0x07
296 #define UNRECOGNIZED_PARAMETERS                    0x08
297 #define NO_USER_DATA                               0x09
298 #define COOKIE_RECEIVED_WHILE_SHUTTING_DOWN        0x0a
299 #define REQUEST_TO_DELETE_LAST_ADDRESS             0x0c
300 #define OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE 0X0d
301 #define REQUEST_TO_DELETE_SOURCE_ADDRESS           0x0e
302
303 static const value_string sctp_cause_code_values[] = {
304   { INVALID_STREAM_IDENTIFIER,                  "Invalid stream identifier" },
305   { MISSING_MANDATORY_PARAMETERS,               "Missing mandator parameter" },
306   { STALE_COOKIE_ERROR,                         "Stale cookie error" },
307   { OUT_OF_RESOURCE,                            "Out of resource" },
308   { UNRESOLVABLE_ADDRESS,                       "Unresolvable address" },
309   { UNRECOGNIZED_CHUNK_TYPE,                    "Unrecognized chunk type " },
310   { INVALID_MANDATORY_PARAMETER,                "Invalid mandatory parameter" },
311   { UNRECOGNIZED_PARAMETERS,                    "Unrecognized parameters" },
312   { NO_USER_DATA,                               "No user data" },
313   { COOKIE_RECEIVED_WHILE_SHUTTING_DOWN,        "Cookie received while shutting down" },
314   { REQUEST_TO_DELETE_LAST_ADDRESS,             "Request to delete last address" },
315   { OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE, "Operation refused due to resource shortage" },
316   { REQUEST_TO_DELETE_SOURCE_ADDRESS,           "Request to delete source address" },
317   { 0,                                          NULL } };
318
319 #define NOT_SPECIFIED_PROTOCOL_ID  0
320 #define IUA_PAYLOAD_PROTOCOL_ID    1
321 #define M2UA_PAYLOAD_PROTOCOL_ID   2
322 #define M3UA_PAYLOAD_PROTOCOL_ID   3
323 #define SUA_PAYLOAD_PROTOCOL_ID    4
324 #define M2PA_PAYLOAD_PROTOCOL_ID   5
325 #define V5UA_PAYLOAD_PROTOCOL_ID   6
326
327 static const value_string sctp_payload_proto_id_values[] = {
328   { NOT_SPECIFIED_PROTOCOL_ID,           "not specified" },
329   { IUA_PAYLOAD_PROTOCOL_ID,             "IUA" },
330   { M2UA_PAYLOAD_PROTOCOL_ID,            "M2UA" },
331   { M3UA_PAYLOAD_PROTOCOL_ID,            "M3UA" },
332   { SUA_PAYLOAD_PROTOCOL_ID,             "SUA" },
333   { M2PA_PAYLOAD_PROTOCOL_ID,            "M2PA" },
334   { V5UA_PAYLOAD_PROTOCOL_ID,            "V5UA" },
335   { 0,                                   NULL } };
336
337 /* The structure of the common header is described by the following constants */
338 #define SOURCE_PORT_LENGTH      2
339 #define DESTINATION_PORT_LENGTH 2
340 #define VERIFICATION_TAG_LENGTH 4
341 #define CHECKSUM_LENGTH         4
342 #define COMMON_HEADER_LENGTH    (SOURCE_PORT_LENGTH + \
343                                  DESTINATION_PORT_LENGTH + \
344                                  VERIFICATION_TAG_LENGTH + \
345                                  CHECKSUM_LENGTH)
346 #define SOURCE_PORT_OFFSET      0
347 #define DESTINATION_PORT_OFFSET (SOURCE_PORT_OFFSET + SOURCE_PORT_LENGTH)
348 #define VERIFICATION_TAG_OFFSET (DESTINATION_PORT_OFFSET + DESTINATION_PORT_LENGTH)
349 #define CHECKSUM_OFFSET         (VERIFICATION_TAG_OFFSET + VERIFICATION_TAG_LENGTH)
350
351 /* The structure of the chunk header is described by the following constants */
352 #define CHUNK_TYPE_LENGTH             1
353 #define CHUNK_FLAGS_LENGTH            1
354 #define CHUNK_LENGTH_LENGTH           2
355 #define CHUNK_HEADER_LENGTH           (CHUNK_TYPE_LENGTH + \
356                                        CHUNK_FLAGS_LENGTH + \
357                                        CHUNK_LENGTH_LENGTH)
358 #define CHUNK_HEADER_OFFSET           0
359 #define CHUNK_TYPE_OFFSET             CHUNK_HEADER_OFFSET
360 #define CHUNK_FLAGS_OFFSET            (CHUNK_TYPE_OFFSET + CHUNK_TYPE_LENGTH)
361 #define CHUNK_LENGTH_OFFSET           (CHUNK_FLAGS_OFFSET + CHUNK_FLAGS_LENGTH)
362 #define CHUNK_VALUE_OFFSET            (CHUNK_LENGTH_OFFSET + CHUNK_LENGTH_LENGTH)
363
364 /* The following constants describe the structure of DATA chunks */
365 #define DATA_CHUNK_TSN_LENGTH         4
366 #define DATA_CHUNK_STREAM_ID_LENGTH   2
367 #define DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH 2
368 #define DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH 4
369
370 #define DATA_CHUNK_TSN_OFFSET         (CHUNK_VALUE_OFFSET + 0)
371 #define DATA_CHUNK_STREAM_ID_OFFSET   (DATA_CHUNK_TSN_OFFSET + DATA_CHUNK_TSN_LENGTH)
372 #define DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET (DATA_CHUNK_STREAM_ID_OFFSET + \
373                                              DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH)
374 #define DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET (DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET + \
375                                                DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH)
376 #define DATA_CHUNK_PAYLOAD_OFFSET     (DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET + \
377                                        DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH)
378
379 #define DATA_CHUNK_HEADER_LENGTH      (CHUNK_HEADER_LENGTH + \
380                                        DATA_CHUNK_TSN_LENGTH + \
381                                        DATA_CHUNK_STREAM_ID_LENGTH + \
382                                        DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH + \
383                                        DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH)
384
385 #define SCTP_DATA_CHUNK_E_BIT 0x01
386 #define SCTP_DATA_CHUNK_B_BIT 0x02
387 #define SCTP_DATA_CHUNK_U_BIT 0x04
388
389 #define INIT_CHUNK_INITIATE_TAG_LENGTH               4
390 #define INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH      4
391 #define INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH 2
392 #define INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH  2
393 #define INIT_CHUNK_INITIAL_TSN_LENGTH                4
394
395 #define INIT_CHUNK_INITIATE_TAG_OFFSET               CHUNK_VALUE_OFFSET
396 #define INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET      (INIT_CHUNK_INITIATE_TAG_OFFSET + \
397                                                       INIT_CHUNK_INITIATE_TAG_LENGTH )
398 #define INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET (INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET + \
399                                                       INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH )
400 #define INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET  (INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET + \
401                                                       INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH )
402 #define INIT_CHUNK_INITIAL_TSN_OFFSET                (INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET + \
403                                                       INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH )
404 #define INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET  (INIT_CHUNK_INITIAL_TSN_OFFSET + \
405                                                       INIT_CHUNK_INITIAL_TSN_LENGTH )
406
407
408 #define SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH    4
409 #define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH 4
410 #define SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH  2
411 #define SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH    2
412 #define SACK_CHUNK_GAP_BLOCK_LENGTH             4
413 #define SACK_CHUNK_GAP_BLOCK_START_LENGTH       2
414 #define SACK_CHUNK_GAP_BLOCK_END_LENGTH         2
415 #define SACK_CHUNK_DUP_TSN_LENGTH               4
416
417 #define SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET (CHUNK_VALUE_OFFSET + 0)
418 #define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET (SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET + \
419                                                  SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH)
420 #define SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET (SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET + \
421                                                 SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH)
422 #define SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET (SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET + \
423                                               SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH)
424 #define SACK_CHUNK_GAP_BLOCK_OFFSET (SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET + \
425                                      SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH)
426
427 #define HEARTBEAT_CHUNK_INFO_OFFSET CHUNK_VALUE_OFFSET
428
429 #define SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET CHUNK_VALUE_OFFSET
430 #define SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_LENGTH 4
431                 
432 #define ABORT_CHUNK_FIRST_ERROR_CAUSE_OFFSET 4     
433 #define ERROR_CHUNK_FIRST_ERROR_CAUSE_OFFSET 4     
434
435 #define COOKIE_ECHO_CHUNK_COOKIE_OFFSET CHUNK_VALUE_OFFSET
436
437 #define ECNE_CHUNK_LOWEST_TSN_OFFSET CHUNK_VALUE_OFFSET
438 #define ECNE_CHUNK_LOWEST_TSN_LENGTH 4
439
440 #define CWR_CHUNK_LOWEST_TSN_OFFSET CHUNK_VALUE_OFFSET
441 #define CWR_CHUNK_LOWEST_TSN_LENGTH 4
442                      
443 #define SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT 0x01
444
445 static const true_false_string sctp_data_chunk_e_bit_value = {
446   "Last segment",
447   "Not the last segment"
448 };
449
450 static const true_false_string sctp_data_chunk_b_bit_value = {
451   "First segment",
452   "Subsequent segment"
453 };
454
455 static const true_false_string sctp_data_chunk_u_bit_value = {
456   "Unordered delivery",
457   "Ordered deliviery"
458 };
459
460 static const true_false_string sctp_shutdown_complete_chunk_t_bit_value = {
461   "No TCB destroyed",
462   "TCB destroyed"
463 };
464
465 #define SCTP_CHECKSUM_NONE      0
466 #define SCTP_CHECKSUM_ADLER32   1
467 #define SCTP_CHECKSUM_CRC32C    2
468 #define SCTP_CHECKSUM_AUTOMATIC 3
469
470 static gint sctp_checksum = SCTP_CHECKSUM_ADLER32;
471
472 /* adler32.c -- compute the Adler-32 checksum of a data stream
473  * Copyright (C) 1995-1996 Mark Adler
474  * For conditions of distribution and use, see copyright notice in zlib.h
475  * available, e.g. from  http://www.cdrom.com/pub/infozip/zlib/
476  *
477  * It was modified for the use in this dissector.
478  */
479
480 #define BASE 65521L /* largest prime smaller than 65536      */
481 #define NMAX 5540   /* NMAX is the largest n - 12 such that  */
482                     /* 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
483
484 #define DO1(buf,i)  {s1 += buf[i]; s2 += s1;}
485 #define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
486 #define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
487 #define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
488 #define DO16(buf)   DO8(buf,0); DO8(buf,8);
489
490 static unsigned int
491 sctp_adler32(const unsigned char* buf, unsigned int len)
492 {
493     unsigned int s1 = 1L;
494     unsigned int s2 = 0L;
495     int k;
496     
497     /* handle the first 8 bytes of the datagram */
498     DO8(buf,0);
499     buf += SOURCE_PORT_LENGTH + 
500            DESTINATION_PORT_LENGTH + 
501            VERIFICATION_TAG_LENGTH;
502     
503     /* handle four 0 bytes as checksum */
504     s2  += CHECKSUM_LENGTH * s1;
505     buf += CHECKSUM_LENGTH;
506
507     /* now we have 12 bytes handled */
508     len -= COMMON_HEADER_LENGTH;
509
510     /* handle the rest of the datagram */
511     while (len > 0) {
512         k = len < NMAX ? len : NMAX;
513         len -= k;
514         while (k >= 16) {
515             DO16(buf);
516             buf += 16;
517             k -= 16;
518         }
519         if (k != 0) do {
520             s1 += *buf++;
521             s2 += s1;
522         } while (--k);
523         s1 %= BASE;
524         s2 %= BASE;
525     }
526     return (s2 << 16) | s1;
527 }
528
529 /* The CRC32C code is taken from draft-ietf-tsvwg-sctpcsum-01.txt.
530  * That code is copyrighted by D. Otis and has been modified.
531  */
532   
533 #define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF]) 
534 static unsigned long crc_c[256] = 
535
536 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,  
537 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,  
538 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,  
539 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,  
540 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,  
541 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,  
542 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,  
543 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,  
544 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,  
545 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,  
546 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,  
547 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,  
548 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,  
549 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,  
550 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,  
551 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,  
552 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,  
553 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,  
554 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,  
555 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,  
556 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,  
557 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,  
558 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,  
559 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,  
560 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,  
561 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,  
562 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,  
563 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,  
564 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,  
565 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,  
566 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,  
567 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,  
568 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,  
569 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,  
570 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,  
571 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,  
572 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,  
573 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,  
574 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,  
575 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,  
576 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,  
577 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,  
578 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,  
579 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,  
580 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,  
581 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,  
582 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,  
583 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,  
584 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,  
585 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,  
586 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,  
587 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,  
588 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,  
589 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,  
590 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,  
591 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,  
592 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,  
593 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,  
594 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,  
595 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,  
596 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,  
597 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,  
598 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,  
599 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L,  
600 }; 
601      
602 static unsigned int
603 sctp_crc32c(const unsigned char* buf, unsigned int len)
604 {
605   unsigned int i; 
606   unsigned long crc32 = ~0L; 
607   unsigned long result;
608   unsigned char byte0,byte1,byte2,byte3;
609
610   for (i = 0; i < SOURCE_PORT_LENGTH + DESTINATION_PORT_LENGTH + VERIFICATION_TAG_LENGTH; i++) 
611   { 
612     CRC32C(crc32, buf[i]); 
613   }
614   CRC32C(crc32, 0);
615   CRC32C(crc32, 0);
616   CRC32C(crc32, 0);
617   CRC32C(crc32, 0);
618   for (i = COMMON_HEADER_LENGTH; i < len; i++) 
619   { 
620     CRC32C(crc32, buf[i]); 
621   }  
622   result = ~crc32;
623   
624   byte0 = result & 0xff;
625   byte1 = (result>>8) & 0xff;
626   byte2 = (result>>16) & 0xff;
627   byte3 = (result>>24) & 0xff;
628   crc32 = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
629   return ( crc32 );
630 }
631
632 static guint 
633 nr_of_padding_bytes (guint length)
634 {
635   guint remainder;
636
637   remainder = length % 4;
638
639   if (remainder == 0)
640     return 0;
641   else
642     return 4 - remainder;
643 }
644
645 /* 
646  * TLV parameter stuff for INIT and INIT-ACK chunks
647  */
648
649 static void
650 dissect_parameter(tvbuff_t *, packet_info *, proto_tree *);
651
652 static void
653 dissect_error_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *chunk_tree);
654
655 static gboolean
656 dissect_sctp_chunk(tvbuff_t *, packet_info *, proto_tree *, proto_tree *);
657
658 static void 
659 dissect_tlv_parameter_list(tvbuff_t *parameter_list_tvb, packet_info *pinfo, proto_tree *tree)
660 {
661   guint offset, length, padding_length, total_length;
662   tvbuff_t *parameter_tvb;
663
664   offset = 0;
665   while(tvb_reported_length_remaining(parameter_list_tvb, offset)) {
666     length         = tvb_get_ntohs(parameter_list_tvb, offset + PARAMETER_LENGTH_OFFSET);
667     padding_length = nr_of_padding_bytes(length);
668     total_length   = length + padding_length;
669     /* create a tvb for the chunk including the padding bytes */
670     parameter_tvb    = tvb_new_subset(parameter_list_tvb, offset, total_length, total_length);
671     dissect_parameter(parameter_tvb, pinfo, tree); 
672     /* get rid of the handled parameter */
673     offset += total_length;
674   }
675 }
676
677 static void
678 dissect_heartbeat_info_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
679 {
680   guint16 length, heartbeat_info_length;
681   
682   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
683   
684   heartbeat_info_length = length - HEARTBEAT_INFO_PARAMETER_HEADER_LENGTH;
685
686   proto_tree_add_text(parameter_tree, parameter_tvb, HEARTBEAT_INFO_PARAMETER_INFO_OFFSET, heartbeat_info_length,
687                       "Heartbeat info (%u byte%s)",
688                       heartbeat_info_length, plurality(heartbeat_info_length, "", "s"));
689
690   proto_item_set_text(parameter_item, "Heartbeat info parameter with %u byte%s of info",
691                       heartbeat_info_length, plurality(heartbeat_info_length, "", "s"));
692 }
693
694 static void
695 dissect_ipv4_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
696 {
697   guint32 ipv4_address;
698
699   tvb_memcpy(parameter_tvb, (guint8 *)&ipv4_address, PARAMETER_VALUE_OFFSET, IPV4_ADDRESS_LENGTH); 
700   proto_tree_add_ipv4(parameter_tree, hf_sctp_parameter_ipv4_address,
701                       parameter_tvb, PARAMETER_VALUE_OFFSET, IPV4_ADDRESS_LENGTH,
702                       ipv4_address);  
703   proto_item_set_text(parameter_item, "IPV4 address parameter");
704 }
705
706 static void
707 dissect_ipv6_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
708 {
709   proto_tree_add_ipv6(parameter_tree, hf_sctp_parameter_ipv6_address,
710                       parameter_tvb, PARAMETER_VALUE_OFFSET, IPV6_ADDRESS_LENGTH,
711                       tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, IPV6_ADDRESS_LENGTH));
712   
713   proto_item_set_text(parameter_item, "IPV6 address parameter");
714 }
715
716 static void
717 dissect_state_cookie_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
718 {
719   guint16 length, state_cookie_length;
720   
721   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
722   
723   state_cookie_length = length - STATE_COOKIE_PARAMETER_HEADER_LENGTH;
724
725   proto_tree_add_text(parameter_tree, parameter_tvb, STATE_COOKIE_PARAMETER_COOKIE_OFFSET, state_cookie_length,
726                       "State cookie (%u byte%s)",
727                       state_cookie_length, plurality(state_cookie_length, "", "s"));
728
729   proto_item_set_text(parameter_item, "State Cookie Parameter with %u byte%s cookie",
730                       state_cookie_length, plurality(state_cookie_length, "", "s"));
731 }
732
733 static void
734 dissect_unrecognized_parameters_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
735 {
736   guint16 length, padding_length, parameter_value_length, unrecognized_parameter_type;
737   tvbuff_t *unrecognized_parameters_tvb;
738
739   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
740   padding_length = nr_of_padding_bytes(length);
741
742   parameter_value_length = length - PARAMETER_HEADER_LENGTH + padding_length;
743
744   unrecognized_parameters_tvb = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, 
745                                                parameter_value_length, parameter_value_length);
746   unrecognized_parameter_type = tvb_get_ntohs(unrecognized_parameters_tvb, PARAMETER_TYPE_OFFSET);
747   dissect_tlv_parameter_list(unrecognized_parameters_tvb, pinfo, parameter_tree);
748    
749   proto_item_set_text(parameter_item, "Unrecognized parameter of type %s (0x%x)",
750                       val_to_str(unrecognized_parameter_type, sctp_parameter_identifier_values, "unknown"), unrecognized_parameter_type);
751 }
752
753 static void
754 dissect_cookie_preservative_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
755 {
756   guint32 increment;
757
758   increment =  tvb_get_ntohl(parameter_tvb, COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET);
759   
760   proto_tree_add_uint(parameter_tree, hf_sctp_parameter_cookie_preservative_increment, parameter_tvb, 
761                       COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET, 
762                       COOKIE_PRESERVATIVE_PARAMETER_INCR_LENGTH,
763                       increment);
764   
765   proto_item_set_text(parameter_item, "Cookie preservative parameter requesting for a %u msec increment",
766                       increment);
767 }
768
769 static void
770 dissect_hostname_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
771 {
772   guint16  length, hostname_length;
773   char *hostname;
774
775   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
776   
777   hostname_length = length - PARAMETER_HEADER_LENGTH;
778   hostname = (char *)tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, hostname_length);
779   proto_tree_add_string(parameter_tree, hf_sctp_parameter_hostname_hostname, parameter_tvb,
780                         PARAMETER_VALUE_OFFSET, hostname_length,
781                         hostname);
782
783   proto_item_set_text(parameter_item, "Hostname parameter");
784 }
785
786 static void
787 dissect_supported_address_types_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
788 {
789   guint16 length, address_type, number_of_address_types, address_type_number, list_of_address_types_length ;
790   guint offset;
791   proto_item *address_list_item;
792   proto_tree *address_list_tree;
793
794   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
795   list_of_address_types_length = length - PARAMETER_HEADER_LENGTH;
796   number_of_address_types = list_of_address_types_length / SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH;
797
798   address_list_item = proto_tree_add_text(parameter_tree, parameter_tvb, PARAMETER_VALUE_OFFSET, list_of_address_types_length,
799                                           "Supported Address Types (%u address type%s)",
800                                           number_of_address_types, plurality(number_of_address_types, "", "s"));
801   address_list_tree = proto_item_add_subtree(address_list_item, ett_sctp_supported_address_types_parameter);
802  
803   offset = PARAMETER_VALUE_OFFSET;
804   for(address_type_number = 1; address_type_number <= number_of_address_types; address_type_number++) {
805     address_type = tvb_get_ntohs(parameter_tvb, offset);
806     proto_tree_add_uint_format(address_list_tree, hf_sctp_supported_address_types_parameter,
807                                parameter_tvb, offset, SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH,
808                                address_type, "Supported address type: 0x%04x (%s)",
809                                address_type, val_to_str(address_type, sctp_parameter_identifier_values, "unknown"));
810     offset += SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH;
811   };
812
813   proto_item_set_text(parameter_item, "Supported address types parameter reporting %u address type%s",
814                       number_of_address_types, plurality(number_of_address_types, "", "s"));
815 }
816
817 static void
818 dissect_ecn_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
819 {
820    proto_item_set_text(parameter_item, "ECN parameter");
821 }
822
823 #define USTREAMS_START_LENGTH    2
824 #define USTREAMS_END_LENGTH      2
825 #define USTREAMS_INTERVAL_LENGTH (USTREAMS_START_LENGTH + USTREAMS_END_LENGTH)
826
827 static void
828 dissect_unreliable_streams_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
829 {  
830     guint16 length, start, end, number_of_intervals, interval_number;
831     proto_item *interval_item;
832     proto_tree *interval_tree;
833     gint interval_offset;
834     
835     length              = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
836     number_of_intervals = (length - PARAMETER_HEADER_LENGTH) / USTREAMS_INTERVAL_LENGTH;
837     
838     interval_offset     = PARAMETER_VALUE_OFFSET;
839     for(interval_number = 1; interval_number <= number_of_intervals; interval_number++) {
840       start = tvb_get_ntohs(parameter_tvb, interval_offset);
841       end   = tvb_get_ntohs(parameter_tvb, interval_offset + USTREAMS_START_LENGTH);
842       interval_item = proto_tree_add_text(parameter_tree, parameter_tvb, interval_offset, USTREAMS_INTERVAL_LENGTH, "Unreliable streams (%u-%u)", start, end);
843       interval_tree = proto_item_add_subtree(interval_item, ett_sctp_unreliable_streams_interval);
844       proto_tree_add_uint(interval_tree, hf_sctp_ustreams_start, parameter_tvb, interval_offset, USTREAMS_START_LENGTH, start);
845       proto_tree_add_uint(interval_tree, hf_sctp_ustreams_end,  parameter_tvb, interval_offset + USTREAMS_START_LENGTH, USTREAMS_END_LENGTH, end);
846       interval_offset += USTREAMS_INTERVAL_LENGTH;
847     };
848    proto_item_set_text(parameter_item, "Unreliable streams parameter");
849 }
850
851 static void
852 dissect_add_ip_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
853 {
854   guint16 length, parameter_value_length;
855   tvbuff_t *address_tvb;
856
857   length                 = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
858   parameter_value_length = length - PARAMETER_HEADER_LENGTH;
859
860   address_tvb            =  tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length, parameter_value_length);
861   dissect_parameter(address_tvb, pinfo, parameter_tree); 
862
863   proto_item_set_text(parameter_item, "Add IP address parameter");
864 }
865
866 static void
867 dissect_del_ip_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
868 {
869   guint16 length, parameter_value_length;
870   tvbuff_t *address_tvb;
871
872   length                 = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
873   parameter_value_length = length - PARAMETER_HEADER_LENGTH;
874
875   address_tvb            =  tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length, parameter_value_length);
876   dissect_parameter(address_tvb, pinfo, parameter_tree); 
877
878   proto_item_set_text(parameter_item, "Delete IP address parameter");
879 }
880
881 static void
882 dissect_error_cause_indication_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
883 {
884   guint16 length, padding_length, total_length;
885   gint offset;
886   tvbuff_t *error_cause_tvb;
887
888   offset = PARAMETER_VALUE_OFFSET;
889   while(tvb_reported_length_remaining(parameter_tvb, offset)) {
890     length         = tvb_get_ntohs(parameter_tvb, offset + CAUSE_LENGTH_OFFSET);
891     padding_length = nr_of_padding_bytes(length);
892     total_length   = length + padding_length;
893     /* create a tvb for the chunk including the padding bytes */
894     error_cause_tvb    = tvb_new_subset(parameter_tvb, offset , total_length, total_length);
895     dissect_error_cause(error_cause_tvb, pinfo, parameter_tree); 
896     /* get rid of the handled parameter */
897     offset += total_length;
898   }
899   proto_item_set_text(parameter_item, "Error cause indication");
900 }
901
902 static void
903 dissect_set_primary_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
904 {
905   guint16 length, parameter_value_length;
906   tvbuff_t *address_tvb;
907
908   length                 = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
909   parameter_value_length = length - PARAMETER_HEADER_LENGTH;
910
911   address_tvb            =  tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length, parameter_value_length);
912   dissect_parameter(address_tvb, pinfo, parameter_tree); 
913
914   proto_item_set_text(parameter_item, "Set primary address parameter");
915 }
916
917 static void
918 dissect_success_report_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
919 {
920    proto_item_set_text(parameter_item, "Success report parameter");
921 }
922
923 #define ADAP_INDICATION_LENGTH 4
924 #define ADAP_INDICATION_OFFSET PARAMETER_VALUE_OFFSET
925
926 static void
927 dissect_adap_indication_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
928 {
929   guint32 indication;
930
931   indication =  tvb_get_ntohl(parameter_tvb, ADAP_INDICATION_OFFSET);
932   proto_tree_add_uint(parameter_tree, hf_sctp_adap_indication, parameter_tvb, ADAP_INDICATION_OFFSET, ADAP_INDICATION_LENGTH, indication);
933   proto_item_set_text(parameter_item, "Adaptation layer indication");
934 }
935
936 static void
937 dissect_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
938 {
939   guint16 type, length, parameter_value_length;
940   
941   type   = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
942   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
943   
944   parameter_value_length = length - PARAMETER_HEADER_LENGTH;
945
946   proto_tree_add_text(parameter_tree, parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length,
947                       "Parameter value (%u byte%s)",
948                       parameter_value_length, plurality(parameter_value_length, "", "s"));
949
950   proto_item_set_text(parameter_item, "Parameter of type %u and %u byte%s value",
951                       type, parameter_value_length, plurality(parameter_value_length, "", "s"));
952 }
953
954 static void
955 dissect_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *chunk_tree)
956 {
957   guint16 type, length, padding_length, total_length;
958   proto_item *parameter_item;
959   proto_tree *parameter_tree;
960
961   type           = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
962   length         = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
963   padding_length = nr_of_padding_bytes(length);
964   total_length   = length + padding_length;
965    
966   parameter_item = proto_tree_add_text(chunk_tree, parameter_tvb,
967         PARAMETER_HEADER_OFFSET, total_length, "%s parameter",
968         val_to_str(type, sctp_parameter_identifier_values, "Unknown"));
969   parameter_tree = proto_item_add_subtree(parameter_item, ett_sctp_chunk_parameter);
970  
971   proto_tree_add_uint(parameter_tree, hf_sctp_chunk_parameter_type, 
972                       parameter_tvb, PARAMETER_TYPE_OFFSET, PARAMETER_TYPE_LENGTH,
973                       type);
974   proto_tree_add_uint(parameter_tree, hf_sctp_chunk_parameter_length, 
975                       parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH,
976                       length);
977  
978   switch(type) {
979   case HEARTBEAT_INFO_PARAMETER_ID:
980     dissect_heartbeat_info_parameter(parameter_tvb, parameter_tree, parameter_item);
981     break;
982   case IPV4ADDRESS_PARAMETER_ID:
983     dissect_ipv4_parameter(parameter_tvb, parameter_tree, parameter_item);
984     break;
985   case IPV6ADDRESS_PARAMETER_ID:
986     dissect_ipv6_parameter(parameter_tvb, parameter_tree, parameter_item);
987     break;
988   case STATE_COOKIE_PARAMETER_ID:
989     dissect_state_cookie_parameter(parameter_tvb, parameter_tree, parameter_item);
990     break;
991   case UNREC_PARA_PARAMETER_ID:
992     dissect_unrecognized_parameters_parameter(parameter_tvb, pinfo,  parameter_tree, parameter_item);
993     break;
994   case COOKIE_PRESERVATIVE_PARAMETER_ID:
995     dissect_cookie_preservative_parameter(parameter_tvb, parameter_tree, parameter_item);
996     break;
997   case HOSTNAME_ADDRESS_PARAMETER_ID:
998     dissect_hostname_parameter(parameter_tvb, parameter_tree, parameter_item);
999     break;
1000   case SUPPORTED_ADDRESS_TYPES_PARAMETER_ID:
1001     dissect_supported_address_types_parameter(parameter_tvb, parameter_tree, parameter_item);
1002     break;
1003   case ECN_PARAMETER_ID:
1004     dissect_ecn_parameter(parameter_tvb, parameter_tree, parameter_item);
1005     break;
1006   case UNRELIABLE_STREAMS_PARAMETER_ID:
1007     dissect_unreliable_streams_parameter(parameter_tvb, parameter_tree, parameter_item);
1008     break;
1009   case ADD_IP_ADDRESS_PARAMETER_ID:
1010     dissect_add_ip_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
1011     break;
1012   case DEL_IP_ADDRESS_PARAMETER_ID:
1013     dissect_del_ip_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
1014     break;
1015   case ERROR_CAUSE_INDICATION_PARAMETER_ID:
1016     dissect_error_cause_indication_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
1017     break;
1018   case SET_PRIMARY_ADDRESS_PARAMETER_ID:
1019     dissect_set_primary_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
1020     break;    
1021   case SUCCESS_REPORT_PARAMETER_ID:
1022     dissect_success_report_parameter(parameter_tvb, parameter_tree, parameter_item);
1023     break; 
1024   case ADAP_LAYER_INDICATION_PARAMETER_ID:
1025     dissect_adap_indication_parameter(parameter_tvb, parameter_tree, parameter_item);
1026     break;    
1027   default:
1028     dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
1029     break;
1030   };
1031   if ((padding_length > 0) && (type != UNREC_PARA_PARAMETER_ID))
1032     proto_tree_add_text(parameter_tree, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length,
1033                         "Padding: %u byte%s",
1034                         padding_length, plurality(padding_length, "", "s"));
1035 }
1036
1037 /*
1038  * Code to handle error causes for ABORT and ERROR chunks
1039  */
1040 static void
1041 dissect_invalid_stream_identifier_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
1042 {
1043   guint16 stream_identifier;
1044
1045   stream_identifier   = tvb_get_ntohs(cause_tvb, CAUSE_STREAM_IDENTIFIER_OFFSET);
1046   proto_tree_add_uint(cause_tree, hf_sctp_cause_stream_identifier, 
1047                       cause_tvb, CAUSE_STREAM_IDENTIFIER_OFFSET, CAUSE_STREAM_IDENTIFIER_LENGTH,
1048                       stream_identifier);
1049   proto_tree_add_text(cause_tree, cause_tvb, CAUSE_RESERVED_OFFSET, CAUSE_RESERVED_LENGTH,
1050                       "Reserved (2 bytes)");
1051
1052   proto_item_set_text(cause_item, "Error cause reporting invalid stream identifier %u",
1053                       stream_identifier);
1054 }
1055
1056 static void
1057 dissect_missing_mandatory_parameters_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
1058 {
1059   guint32 number_of_missing_parameters, missing_parameter_number;
1060   guint16 parameter_type;
1061   guint   offset;
1062
1063   number_of_missing_parameters = tvb_get_ntohl(cause_tvb, CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET);
1064   proto_tree_add_uint(cause_tree, hf_sctp_cause_number_of_missing_parameters, 
1065                       cause_tvb, CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET, CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH,
1066                       number_of_missing_parameters);
1067   offset = CAUSE_FIRST_MISSING_PARAMETER_TYPE_OFFSET;
1068   for(missing_parameter_number = 1; missing_parameter_number <= number_of_missing_parameters; missing_parameter_number++) {
1069     parameter_type = tvb_get_ntohs(cause_tvb, offset);
1070     proto_tree_add_uint(cause_tree, hf_sctp_cause_missing_parameter_type,
1071                         cause_tvb, offset, CAUSE_MISSING_PARAMETER_TYPE_LENGTH,
1072                         parameter_type);
1073     offset +=  CAUSE_MISSING_PARAMETER_TYPE_LENGTH;
1074   };
1075
1076   proto_item_set_text(cause_item, "Error cause reporting %u missing mandatory parameter%s",
1077                       number_of_missing_parameters, plurality(number_of_missing_parameters, "", "s") );
1078 }
1079
1080 static void
1081 dissect_stale_cookie_error_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
1082 {
1083   guint32 measure_of_staleness;
1084
1085   measure_of_staleness =  tvb_get_ntohl(cause_tvb, CAUSE_MEASURE_OF_STALENESS_OFFSET);
1086   
1087   proto_tree_add_uint(cause_tree, hf_sctp_cause_measure_of_staleness, cause_tvb, 
1088                       CAUSE_MEASURE_OF_STALENESS_OFFSET, 
1089                       CAUSE_MEASURE_OF_STALENESS_LENGTH,
1090                       measure_of_staleness);
1091   
1092   proto_item_set_text(cause_item, "Error cause reporting a measure of staleness of %u usec",
1093                       measure_of_staleness);
1094 }
1095
1096 static void
1097 dissect_out_of_resource_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
1098 {
1099   proto_item_set_text(cause_item, "Error cause reporting lack of resources");
1100 }
1101
1102 static void
1103 dissect_unresolvable_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
1104 {
1105   guint16 code, length, parameter_length, parameter_type;
1106   tvbuff_t *parameter_tvb;
1107
1108   code   = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET);
1109   length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
1110   
1111   parameter_length = length - CAUSE_HEADER_LENGTH;
1112   parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, 
1113                                  parameter_length, parameter_length);
1114
1115   dissect_parameter(parameter_tvb, pinfo, cause_tree);
1116   parameter_type = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
1117  
1118   proto_item_set_text(cause_item, "Error cause reporting unresolvable address of type 0x%04x (%s)",
1119                       parameter_type, val_to_str(parameter_type, sctp_parameter_identifier_values, "unknown") );
1120 }
1121
1122 static void
1123 dissect_unrecognized_chunk_type_cause(tvbuff_t *cause_tvb,  packet_info *pinfo, 
1124                                       proto_tree *cause_tree, proto_item *cause_item)
1125 {
1126   guint16 length, chunk_length;
1127   guint8 unrecognized_type;
1128   tvbuff_t *unrecognized_chunk_tvb;
1129
1130   length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
1131   
1132   chunk_length = length - CAUSE_HEADER_LENGTH;
1133
1134   unrecognized_chunk_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, chunk_length, chunk_length);
1135   dissect_sctp_chunk(unrecognized_chunk_tvb, pinfo, cause_tree,cause_tree);
1136
1137   unrecognized_type   = tvb_get_guint8(unrecognized_chunk_tvb, CHUNK_TYPE_OFFSET);
1138  
1139   proto_item_set_text(cause_item, "Error cause reporting unrecognized chunk of type %u (%s)",
1140                       unrecognized_type,
1141                       val_to_str(unrecognized_type, sctp_chunk_type_values, "unknown"));
1142 }
1143
1144 static void
1145 dissect_invalid_mandatory_parameter_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
1146 {
1147   proto_item_set_text(cause_item, "Error cause reporting an invalid mandatory parameter");
1148 }
1149
1150 static void
1151 dissect_unrecognized_parameters_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
1152 {
1153   guint16 length, padding_length, cause_info_length;
1154   tvbuff_t *unrecognized_parameters_tvb;
1155
1156   length            = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
1157   padding_length    = nr_of_padding_bytes(length);
1158   cause_info_length = length - CAUSE_HEADER_LENGTH + padding_length;
1159
1160   unrecognized_parameters_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1161   dissect_tlv_parameter_list(unrecognized_parameters_tvb, pinfo, cause_tree);
1162  
1163   proto_item_set_text(cause_item, "Error cause reporting unrecognized parameters");
1164 }
1165
1166 static void
1167 dissect_no_user_data_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
1168 {
1169   guint32 tsn;
1170
1171   tsn = tvb_get_ntohl(cause_tvb, CAUSE_TSN_OFFSET);
1172   proto_tree_add_uint(cause_tree, hf_sctp_cause_tsn, cause_tvb, 
1173                       CAUSE_TSN_OFFSET, 
1174                       CAUSE_TSN_LENGTH,
1175                       tsn);
1176
1177   proto_item_set_text(cause_item, "Error cause reporting data chunk with TSN %u contains no data",
1178                       tsn);
1179 }
1180
1181 static void
1182 dissect_cookie_received_while_shutting_down_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
1183 {
1184   proto_item_set_text(cause_item, "Error cause reporting cookie reception while shutting down");
1185 }
1186
1187 static void
1188 dissect_delete_last_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
1189 {
1190   guint16 length, cause_info_length;
1191   tvbuff_t *parameter_tvb;
1192
1193   length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
1194   cause_info_length = length - CAUSE_HEADER_LENGTH;
1195   parameter_tvb    = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1196   dissect_parameter(parameter_tvb, pinfo, cause_tree); 
1197   proto_item_set_text(cause_item, "Delete last address cause");
1198 }
1199
1200 static void
1201 dissect_resource_outage_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
1202 {
1203   guint16 length, cause_info_length;
1204   tvbuff_t *parameter_tvb;
1205
1206   length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
1207   cause_info_length = length - CAUSE_HEADER_LENGTH;
1208   parameter_tvb    = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1209   dissect_parameter(parameter_tvb, pinfo, cause_tree); 
1210   proto_item_set_text(cause_item, "Operation refused due to resource shortage");
1211 }
1212
1213 static void
1214 dissect_delete_source_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
1215 {
1216   guint16 length, cause_info_length;
1217   tvbuff_t *parameter_tvb;
1218
1219   length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
1220   cause_info_length = length - CAUSE_HEADER_LENGTH;
1221   parameter_tvb    = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1222   dissect_parameter(parameter_tvb, pinfo, cause_tree); 
1223   proto_item_set_text(cause_item, "Delete source address cause");
1224 }
1225
1226 static void
1227 dissect_unknown_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
1228 {
1229   guint16 code, length, cause_info_length;
1230
1231   code   = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET);
1232   length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
1233   
1234   cause_info_length = length - CAUSE_HEADER_LENGTH;
1235
1236   proto_tree_add_text(cause_tree, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length,
1237                       "Cause specific information (%u byte%s)",
1238                       cause_info_length, plurality(cause_info_length, "", "s"));
1239
1240   proto_item_set_text(cause_item, "Error cause with code %u and %u byte%s information",
1241                       code, cause_info_length, plurality(cause_info_length, "", "s"));
1242 }
1243
1244 static void
1245 dissect_error_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *chunk_tree)
1246 {
1247   guint16 code, length, padding_length, total_length;
1248   proto_item *cause_item;
1249   proto_tree *cause_tree;
1250
1251   code           = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET);
1252   length         = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
1253   padding_length = nr_of_padding_bytes(length);
1254   total_length   = length + padding_length;
1255
1256   cause_item = proto_tree_add_text(chunk_tree, cause_tvb,
1257                                    CAUSE_HEADER_OFFSET, total_length,
1258                                    "BAD ERROR CAUSE");
1259   cause_tree = proto_item_add_subtree(cause_item, ett_sctp_chunk_cause);
1260  
1261   proto_tree_add_uint(cause_tree, hf_sctp_cause_code, 
1262                       cause_tvb, CAUSE_CODE_OFFSET, CAUSE_CODE_LENGTH,
1263                       code);
1264   proto_tree_add_uint(cause_tree, hf_sctp_cause_length, 
1265                       cause_tvb, CAUSE_LENGTH_OFFSET, CAUSE_LENGTH_LENGTH,
1266                       length);
1267  
1268   switch(code) {
1269   case INVALID_STREAM_IDENTIFIER:
1270     dissect_invalid_stream_identifier_cause(cause_tvb, cause_tree, cause_item);
1271     break;
1272   case MISSING_MANDATORY_PARAMETERS:
1273     dissect_missing_mandatory_parameters_cause(cause_tvb, cause_tree, cause_item);
1274     break;
1275   case STALE_COOKIE_ERROR:
1276     dissect_stale_cookie_error_cause(cause_tvb, cause_tree, cause_item);
1277     break;
1278   case OUT_OF_RESOURCE:
1279     dissect_out_of_resource_cause(cause_tvb, cause_tree, cause_item);
1280     break;
1281   case UNRESOLVABLE_ADDRESS:
1282     dissect_unresolvable_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
1283     break;
1284   case UNRECOGNIZED_CHUNK_TYPE:
1285     dissect_unrecognized_chunk_type_cause(cause_tvb, pinfo, cause_tree, cause_item);
1286     break;
1287   case INVALID_MANDATORY_PARAMETER:
1288     dissect_invalid_mandatory_parameter_cause(cause_tvb, cause_tree, cause_item);
1289     break;
1290   case UNRECOGNIZED_PARAMETERS:
1291     dissect_unrecognized_parameters_cause(cause_tvb, pinfo, cause_tree, cause_item);
1292     break;
1293   case NO_USER_DATA:
1294     dissect_no_user_data_cause(cause_tvb, cause_tree, cause_item);
1295     break;
1296   case COOKIE_RECEIVED_WHILE_SHUTTING_DOWN:
1297     dissect_cookie_received_while_shutting_down_cause(cause_tvb, cause_tree, cause_item);
1298     break;
1299   case REQUEST_TO_DELETE_LAST_ADDRESS:
1300     dissect_delete_last_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
1301     break;
1302   case OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE:
1303     dissect_resource_outage_cause(cause_tvb, pinfo, cause_tree, cause_item);
1304     break;
1305   case REQUEST_TO_DELETE_SOURCE_ADDRESS:
1306     dissect_delete_source_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
1307     break;
1308   default:
1309     dissect_unknown_cause(cause_tvb, cause_tree, cause_item);
1310     break;
1311   };
1312   if ((padding_length > 0) && (code != UNRECOGNIZED_PARAMETERS))
1313     proto_tree_add_text(cause_tree, cause_tvb, CAUSE_HEADER_OFFSET + length, padding_length,
1314                         "Padding: %u byte%s",
1315                         padding_length, plurality(padding_length, "", "s"));
1316 }
1317
1318 /*
1319  * Code to actually dissect the packets 
1320 */
1321
1322 static gboolean
1323 dissect_payload(tvbuff_t *payload_tvb, packet_info *pinfo, proto_tree *tree,
1324                 proto_tree *chunk_tree, guint32 ppi, guint16 payload_length, guint16 padding_length)
1325 {
1326   /* do lookup with the subdissector table */
1327   if (dissector_try_port (sctp_ppi_dissector_table, ppi,  payload_tvb, pinfo, tree) ||
1328       dissector_try_port(sctp_port_dissector_table, pinfo->srcport,  payload_tvb, pinfo, tree) ||
1329       dissector_try_port(sctp_port_dissector_table, pinfo->destport, payload_tvb, pinfo, tree)){
1330     return TRUE;
1331   }
1332   else {
1333     if (check_col(pinfo->cinfo, COL_INFO))
1334       col_append_str(pinfo->cinfo, COL_INFO, "DATA ");
1335     proto_tree_add_text(chunk_tree, payload_tvb, 0, payload_length,
1336                         "Payload (%u byte%s)",
1337                         payload_length, plurality(payload_length, "", "s")); 
1338     if (padding_length > 0)
1339       proto_tree_add_text(chunk_tree, payload_tvb, payload_length, padding_length,
1340                           "Padding: %u byte%s",
1341                           padding_length, plurality(padding_length, "", "s"));
1342     return FALSE;
1343   }
1344 }
1345
1346 static gboolean
1347 dissect_data_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1348                    proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1349
1350   guint8  flags;
1351   guint16 length, total_payload_length, payload_length, padding_length, stream_id, stream_seq_number;
1352   guint32 tsn, payload_proto_id;
1353   proto_tree *flag_tree;
1354   tvbuff_t *payload_tvb;
1355    
1356   length            = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1357   payload_length       = length - DATA_CHUNK_HEADER_LENGTH;
1358   padding_length       = nr_of_padding_bytes(length);
1359   total_payload_length = payload_length + padding_length;
1360   payload_tvb          = tvb_new_subset(chunk_tvb, DATA_CHUNK_PAYLOAD_OFFSET,
1361                                           total_payload_length, total_payload_length);
1362   payload_proto_id     = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET);
1363
1364   if (chunk_tree) {
1365     flags             = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
1366      
1367     flag_tree = proto_item_add_subtree(flags_item, ett_sctp_data_chunk_flags);
1368     proto_tree_add_boolean(flag_tree, hf_sctp_data_chunk_e_bit, chunk_tvb,
1369                            CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
1370     proto_tree_add_boolean(flag_tree, hf_sctp_data_chunk_b_bit, chunk_tvb,
1371                            CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
1372     proto_tree_add_boolean(flag_tree, hf_sctp_data_chunk_u_bit, chunk_tvb,
1373                            CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
1374     
1375     tsn               = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_TSN_OFFSET);
1376     stream_id         = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET);
1377     stream_seq_number = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET);
1378          
1379     proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_tsn, 
1380                         chunk_tvb,
1381                         DATA_CHUNK_TSN_OFFSET, DATA_CHUNK_TSN_LENGTH,
1382                         tsn);
1383     proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_stream_id, 
1384                         chunk_tvb, 
1385                         DATA_CHUNK_STREAM_ID_OFFSET, DATA_CHUNK_STREAM_ID_LENGTH,
1386                         stream_id);
1387     proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_stream_seq_number, 
1388                         chunk_tvb, 
1389                         DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET, DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH,
1390                         stream_seq_number);
1391     proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_payload_proto_id, 
1392                         chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH,
1393                         payload_proto_id);
1394     proto_item_set_text(chunk_item, "DATA chunk with TSN %u (%u:%u) containing %u byte%s of payload",
1395                         tsn, stream_id, stream_seq_number, 
1396                         payload_length, plurality(payload_length, "", "s"));
1397   };   
1398   return dissect_payload(payload_tvb, pinfo, tree, chunk_tree, payload_proto_id, payload_length, padding_length); 
1399 }
1400
1401 static void
1402 dissect_init_chunk(tvbuff_t *chunk_tvb,  packet_info *pinfo, proto_tree *tree,
1403                    proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1404
1405   guint32 initiate_tag, adv_rec_window_credit, initial_tsn;
1406   guint16 number_of_inbound_streams, number_of_outbound_streams;
1407   guint8  type;
1408   tvbuff_t *parameter_list_tvb;
1409
1410   type                       = tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET);
1411   
1412   if (check_col(pinfo->cinfo, COL_INFO)) {
1413     if (type == SCTP_INIT_CHUNK_ID) {
1414       col_append_str(pinfo->cinfo, COL_INFO, "INIT ");
1415     } else {
1416       col_append_str(pinfo->cinfo, COL_INFO, "INIT_ACK ");
1417     };
1418   };
1419   
1420   if (chunk_tree) {
1421     initiate_tag               = tvb_get_ntohl(chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET);
1422     adv_rec_window_credit      = tvb_get_ntohl(chunk_tvb, INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET);
1423     number_of_inbound_streams  = tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET);
1424     number_of_outbound_streams = tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET);
1425     initial_tsn                = tvb_get_ntohl(chunk_tvb, INIT_CHUNK_INITIAL_TSN_OFFSET);
1426     
1427     /* handle fixed parameters */
1428     proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_initiate_tag, 
1429                         chunk_tvb,
1430                         INIT_CHUNK_INITIATE_TAG_OFFSET, INIT_CHUNK_INITIATE_TAG_LENGTH,
1431                         initiate_tag);
1432     proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_adv_rec_window_credit, 
1433                         chunk_tvb,
1434                         INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET, INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH,
1435                         adv_rec_window_credit);
1436     proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_number_of_outbound_streams, 
1437                         chunk_tvb,
1438                         INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH,
1439                         number_of_outbound_streams);
1440     proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_number_of_inbound_streams, 
1441                         chunk_tvb,
1442                         INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH,
1443                         number_of_inbound_streams);
1444     proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_initial_tsn, 
1445                         chunk_tvb,
1446                         INIT_CHUNK_INITIAL_TSN_OFFSET, INIT_CHUNK_INITIAL_TSN_LENGTH,
1447                         initial_tsn);
1448     
1449     /* handle variable paramters */
1450     parameter_list_tvb = tvb_new_subset(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET, -1, -1);
1451     dissect_tlv_parameter_list(parameter_list_tvb, pinfo, chunk_tree);
1452     
1453     proto_item_set_text(chunk_item, 
1454                         "%s chunk requesting for %u outbound stream%s and accepting up to %u inbound stream%s",
1455                         val_to_str(type, sctp_chunk_type_values, "unknown"),
1456                         number_of_outbound_streams, plurality(number_of_outbound_streams, "", "s"),
1457                         number_of_inbound_streams, plurality(number_of_inbound_streams, "", "s"));
1458   }
1459
1460
1461 static void
1462 dissect_init_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1463                        proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1464
1465   dissect_init_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1466
1467
1468 static void
1469 dissect_sack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1470                    proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1471
1472   guint32 cumulative_tsn_ack, adv_rec_window_credit, dup_tsn;
1473   guint16 number_of_gap_blocks, number_of_dup_tsns;
1474   guint16 gap_block_number, dup_tsn_number, start, end;
1475   gint gap_block_offset, dup_tsn_offset;
1476   proto_item *block_item;
1477   proto_tree *block_tree;
1478   
1479   if (check_col(pinfo->cinfo, COL_INFO))
1480     col_append_str(pinfo->cinfo, COL_INFO, "SACK ");
1481
1482   if (chunk_tree) {
1483     cumulative_tsn_ack    = tvb_get_ntohl(chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
1484     adv_rec_window_credit = tvb_get_ntohl(chunk_tvb, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET);
1485     number_of_gap_blocks  = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET);
1486     number_of_dup_tsns    = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET);
1487     
1488     proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_cumulative_tsn_ack, 
1489                         chunk_tvb,
1490                         SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET, SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH,
1491                         cumulative_tsn_ack);
1492     proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_adv_rec_window_credit, 
1493                         chunk_tvb,
1494                         SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH,
1495                         adv_rec_window_credit);
1496     proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_number_of_gap_blocks, 
1497                         chunk_tvb,
1498                         SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH,
1499                         number_of_gap_blocks);
1500     proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_number_of_dup_tsns, 
1501                         chunk_tvb,
1502                         SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET, SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH,
1503                         number_of_dup_tsns);
1504     
1505     /* handle the gap acknowledgement blocks */
1506     gap_block_offset = SACK_CHUNK_GAP_BLOCK_OFFSET;
1507     for(gap_block_number = 1; gap_block_number <= number_of_gap_blocks; gap_block_number++) {
1508       start = tvb_get_ntohs(chunk_tvb, gap_block_offset);
1509       end   = tvb_get_ntohs(chunk_tvb, gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH);
1510       block_item = proto_tree_add_text(chunk_tree, chunk_tvb,
1511                                        gap_block_offset, SACK_CHUNK_GAP_BLOCK_LENGTH,
1512                                        "Gap Acknowledgement for %u TSN%s",
1513                                        1 + end - start, plurality(1 + end - start, "", "s"));
1514       block_tree = proto_item_add_subtree(block_item, ett_sctp_sack_chunk_gap_block);
1515       proto_tree_add_uint(block_tree, hf_sctp_sack_chunk_gap_block_start, 
1516                           chunk_tvb,
1517                           gap_block_offset, SACK_CHUNK_GAP_BLOCK_START_LENGTH,
1518                           start);
1519       proto_tree_add_uint(block_tree, hf_sctp_sack_chunk_gap_block_end, 
1520                           chunk_tvb,
1521                           gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH,
1522                           SACK_CHUNK_GAP_BLOCK_END_LENGTH,
1523                           end);
1524       gap_block_offset += SACK_CHUNK_GAP_BLOCK_LENGTH;
1525     };
1526     
1527     /* handle the duplicate TSNs */
1528     dup_tsn_offset = SACK_CHUNK_GAP_BLOCK_OFFSET + number_of_gap_blocks * SACK_CHUNK_GAP_BLOCK_LENGTH;
1529     for(dup_tsn_number = 1; dup_tsn_number <= number_of_dup_tsns; dup_tsn_number++) {
1530       dup_tsn = tvb_get_ntohl(chunk_tvb, dup_tsn_offset);
1531       proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_duplicate_tsn, 
1532                           chunk_tvb,
1533                           dup_tsn, SACK_CHUNK_DUP_TSN_LENGTH,
1534                           dup_tsn);
1535       dup_tsn_offset += SACK_CHUNK_DUP_TSN_LENGTH;
1536     }
1537     
1538     proto_item_set_text(chunk_item, 
1539                         "SACK chunk acknowledging TSN %u and reporting %u gap%s and %u duplicate TSN%s",
1540                         cumulative_tsn_ack,
1541                         number_of_gap_blocks, plurality(number_of_gap_blocks, "", "s"),
1542                         number_of_dup_tsns, plurality(number_of_dup_tsns, "", "s"));
1543   } 
1544 }
1545
1546 static void
1547 dissect_heartbeat_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1548                         proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1549 {
1550   tvbuff_t   *parameter_tvb;
1551   guint chunk_length, info_length, padding_length, total_length;
1552     
1553   if (check_col(pinfo->cinfo, COL_INFO))
1554     col_append_str(pinfo->cinfo, COL_INFO, "HEARTBEAT ");
1555
1556   if (chunk_tree) {
1557     chunk_length   = tvb_get_ntohs(chunk_tvb,  CHUNK_LENGTH_OFFSET);
1558     info_length    = chunk_length - CHUNK_HEADER_LENGTH;
1559     padding_length = nr_of_padding_bytes(info_length);
1560     total_length   = info_length + padding_length;
1561     parameter_tvb  = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, total_length, total_length);
1562     
1563     dissect_parameter(parameter_tvb, pinfo, chunk_tree);
1564     
1565     proto_item_set_text(chunk_item, "HEARTBEAT chunk");
1566   }
1567 }
1568  
1569 static void
1570 dissect_heartbeat_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1571                             proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1572 {  
1573   tvbuff_t   *parameter_tvb;
1574   guint chunk_length, info_length, padding_length, total_length;
1575   
1576   if (check_col(pinfo->cinfo, COL_INFO))
1577     col_append_str(pinfo->cinfo, COL_INFO, "HEARTBEAT_ACK ");
1578
1579   if (chunk_tree) {
1580     chunk_length   = tvb_get_ntohs(chunk_tvb,  CHUNK_LENGTH_OFFSET);
1581     info_length    = chunk_length - CHUNK_HEADER_LENGTH;
1582     padding_length = nr_of_padding_bytes(info_length);
1583     total_length   = info_length + padding_length;
1584
1585     parameter_tvb  = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, total_length, total_length);
1586     
1587     dissect_parameter(parameter_tvb, pinfo, chunk_tree);
1588     
1589     proto_item_set_text(chunk_item, "HEARTBEAT ACK chunk");
1590   } 
1591 }
1592
1593 static void
1594 dissect_abort_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1595                     proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1596 {
1597   guint offset, number_of_causes;
1598   guint16 length, padding_length, total_length;
1599   tvbuff_t *cause_tvb;
1600   
1601   if (check_col(pinfo->cinfo, COL_INFO))
1602     col_append_str(pinfo->cinfo, COL_INFO, "ABORT ");
1603
1604   if (chunk_tree) {
1605     number_of_causes = 0;
1606     offset = ABORT_CHUNK_FIRST_ERROR_CAUSE_OFFSET;
1607     while(tvb_reported_length_remaining(chunk_tvb, offset)) {
1608         length         = tvb_get_ntohs(chunk_tvb, offset + CAUSE_LENGTH_OFFSET);
1609         padding_length = nr_of_padding_bytes(length);
1610         total_length   = length + padding_length;
1611         /* create a tvb for the chunk including the padding bytes */
1612         cause_tvb      = tvb_new_subset(chunk_tvb, offset, total_length, total_length);
1613         dissect_error_cause(cause_tvb, pinfo, chunk_tree); 
1614         /* get rid of the handled parameter */
1615         offset += total_length;
1616         number_of_causes++;
1617     };
1618     
1619     proto_item_set_text(chunk_item, "Abort chunk with %u cause%s",
1620                         number_of_causes, plurality(number_of_causes, "", "s"));
1621   } 
1622 }
1623
1624 static void
1625 dissect_shutdown_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1626                        proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1627
1628   guint32 cumulative_tsn_ack;
1629  
1630   if (check_col(pinfo->cinfo, COL_INFO))
1631     col_append_str(pinfo->cinfo, COL_INFO, "SHUTDOWN ");
1632
1633   if (chunk_tree) {
1634     cumulative_tsn_ack = tvb_get_ntohl(chunk_tvb, SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
1635     proto_tree_add_uint(chunk_tree, hf_sctp_shutdown_chunk_cumulative_tsn_ack, 
1636                         chunk_tvb,
1637                         SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET,
1638                         SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_LENGTH,
1639                         cumulative_tsn_ack);
1640     
1641     proto_item_set_text(chunk_item, "SHUTDOWN chunk acknowledging up to TSN %u",
1642                         cumulative_tsn_ack);
1643   } 
1644 }
1645
1646 static void
1647 dissect_shutdown_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1648                            proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1649
1650   if (check_col(pinfo->cinfo, COL_INFO))
1651     col_append_str(pinfo->cinfo, COL_INFO, "SHUTDOWN_ACK ");
1652
1653   if (chunk_tree) {
1654     proto_item_set_text(chunk_item, "SHUTDOWN ACK chunk");
1655   } 
1656 }
1657
1658 static void
1659 dissect_error_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1660                     proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1661
1662   guint offset, number_of_causes;
1663   guint16 length, padding_length, total_length;
1664   tvbuff_t *cause_tvb;
1665   
1666   if (check_col(pinfo->cinfo, COL_INFO))
1667     col_append_str(pinfo->cinfo, COL_INFO, "ERROR ");
1668
1669   if (chunk_tree) {
1670     number_of_causes = 0;
1671     offset = ERROR_CHUNK_FIRST_ERROR_CAUSE_OFFSET;
1672     do {
1673       length         = tvb_get_ntohs(chunk_tvb, offset + CAUSE_LENGTH_OFFSET);
1674       padding_length = nr_of_padding_bytes(length);
1675       total_length   = length + padding_length;
1676       /* create a tvb for the chunk including the padding bytes */
1677       cause_tvb      = tvb_new_subset(chunk_tvb, offset, total_length, total_length);
1678       dissect_error_cause(cause_tvb, pinfo, chunk_tree); 
1679       /* get rid of the handled parameter */
1680       offset += total_length;
1681       number_of_causes++;
1682     } while(tvb_reported_length_remaining(chunk_tvb, offset));
1683     
1684     proto_item_set_text(chunk_item, "Error chunk with %u cause%s",
1685                         number_of_causes, plurality(number_of_causes, "", "s"));
1686   } 
1687 }
1688
1689 static void
1690 dissect_cookie_echo_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1691                           proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1692
1693   guint length, cookie_length, padding_length;
1694
1695   length         = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1696   padding_length = nr_of_padding_bytes(length);
1697   cookie_length  = length - CHUNK_HEADER_LENGTH;
1698  
1699   if (check_col(pinfo->cinfo, COL_INFO))
1700     col_append_str(pinfo->cinfo, COL_INFO, "COOKIE_ECHO ");
1701
1702   if (chunk_tree) {  
1703     proto_tree_add_text(chunk_tree, chunk_tvb, COOKIE_ECHO_CHUNK_COOKIE_OFFSET, cookie_length,
1704                         "Cookie (%u byte%s)",
1705                         cookie_length, plurality(cookie_length, "", "s"));
1706     proto_item_set_text(chunk_item, "COOKIE ECHO chunk containing a cookie of %u byte%s",
1707                         cookie_length, plurality(cookie_length, "", "s"));
1708     
1709     if (padding_length > 0)
1710       proto_tree_add_text(chunk_tree, chunk_tvb, CHUNK_HEADER_OFFSET + length, padding_length,
1711                           "Padding: %u byte%s",
1712                           padding_length, plurality(padding_length, "", "s"));
1713   } 
1714 }
1715
1716 static void
1717 dissect_cookie_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1718                          proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1719 {  
1720   if (check_col(pinfo->cinfo, COL_INFO))
1721     col_append_str(pinfo->cinfo, COL_INFO, "COOKIE_ACK ");
1722
1723   if (chunk_tree) {
1724     proto_item_set_text(chunk_item, "COOKIE ACK chunk");
1725   } 
1726 }
1727
1728 static void
1729 dissect_ecne_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1730                    proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1731
1732   guint32 lowest_tsn;
1733  
1734   if (check_col(pinfo->cinfo, COL_INFO))
1735     col_append_str(pinfo->cinfo, COL_INFO, "ECNE ");
1736
1737   if (chunk_tree) {
1738     lowest_tsn = tvb_get_ntohl(chunk_tvb, ECNE_CHUNK_LOWEST_TSN_OFFSET);
1739     proto_tree_add_uint(chunk_tree, hf_sctp_ecne_chunk_lowest_tsn, 
1740                         chunk_tvb,
1741                         ECNE_CHUNK_LOWEST_TSN_OFFSET, ECNE_CHUNK_LOWEST_TSN_LENGTH,
1742                         lowest_tsn);
1743     
1744     proto_item_set_text(chunk_item, "ECNE chunk");
1745   } 
1746 }
1747
1748 static void
1749 dissect_cwr_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1750                   proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1751
1752   guint32 lowest_tsn;
1753   
1754   if (check_col(pinfo->cinfo, COL_INFO))
1755     col_append_str(pinfo->cinfo, COL_INFO, "CWR ");
1756
1757   if (chunk_tree) {
1758     lowest_tsn = tvb_get_ntohl(chunk_tvb, CWR_CHUNK_LOWEST_TSN_OFFSET);
1759     proto_tree_add_uint(chunk_tree, hf_sctp_cwr_chunk_lowest_tsn, 
1760                         chunk_tvb,
1761                         CWR_CHUNK_LOWEST_TSN_OFFSET, CWR_CHUNK_LOWEST_TSN_LENGTH,
1762                         lowest_tsn);
1763     
1764     proto_item_set_text(chunk_item, "CWR chunk");
1765   } 
1766 }
1767
1768 static void
1769 dissect_shutdown_complete_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1770                                 proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1771
1772   guint8  flags;
1773   guint16 length;
1774   proto_tree *flag_tree;
1775  
1776   if (check_col(pinfo->cinfo, COL_INFO))
1777     col_append_str(pinfo->cinfo, COL_INFO, "SHUTDOWN_COMPLETE ");
1778
1779   if (chunk_tree) {
1780     flags             = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
1781     length            = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1782     
1783     flag_tree = proto_item_add_subtree(flags_item, ett_sctp_data_chunk_flags);
1784     proto_tree_add_boolean(flag_tree, hf_sctp_shutdown_complete_chunk_t_bit, chunk_tvb,
1785                            CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
1786     
1787     proto_item_set_text(chunk_item, "SHUTDOWN COMPLETE chunk");
1788   } 
1789 }
1790
1791 #define FORWARD_TSN_CHUNK_TSN_OFFSET CHUNK_VALUE_OFFSET
1792 #define FORWARD_TSN_CHUNK_TSN_LENGTH 4
1793
1794 static void
1795 dissect_forward_tsn_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1796
1797   guint32 tsn;
1798   
1799   if (check_col(pinfo->cinfo, COL_INFO))
1800     col_append_str(pinfo->cinfo, COL_INFO, "FORWARD TSN ");
1801
1802   if (chunk_tree) {
1803     tsn = tvb_get_ntohl(chunk_tvb, FORWARD_TSN_CHUNK_TSN_OFFSET);
1804     proto_tree_add_uint(chunk_tree, hf_sctp_forward_tsn_chunk_tsn, chunk_tvb, FORWARD_TSN_CHUNK_TSN_OFFSET, FORWARD_TSN_CHUNK_TSN_LENGTH, tsn);
1805     proto_item_set_text(chunk_item, "FORWARD TSN chunk (new cumulative TSN %u)", tsn);
1806   } 
1807 }
1808
1809 #define SERIAL_NUMBER_LENGTH    4
1810 #define CORRELATION_ID_LENGTH   4
1811 #define ASCONF_RESERVED_LENGTH  3
1812 #define ASCONF_ADDR_TYPE_LENGTH 1
1813 #define ASCONF_ADDR_LENGTH      16
1814 #define SERIAL_NUMBER_OFFSET    PARAMETER_VALUE_OFFSET
1815
1816 #define IP_V4_ADDRESS_TYPE      5
1817 #define IP_V6_ADDRESS_TYPE      6
1818
1819 static const value_string sctp_address_type_values[] = {
1820   { IP_V4_ADDRESS_TYPE,         "IP V4 address" },
1821   { IP_V6_ADDRESS_TYPE,         "IP V6 address" },
1822   { 0,                           NULL } };
1823
1824 static void
1825 dissect_asconf_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1826
1827   guint32 serial_number, correlation_id, ipv4_address;
1828   guint offset, length, padding_length, total_length;
1829   guint8 addr_type;
1830   tvbuff_t *parameter_tvb;
1831
1832   if (check_col(pinfo->cinfo, COL_INFO))
1833     col_append_str(pinfo->cinfo, COL_INFO, "ASCONF ");
1834
1835   if (chunk_tree) {
1836     offset = SERIAL_NUMBER_OFFSET;
1837     serial_number    = tvb_get_ntohl(chunk_tvb, offset);
1838     proto_tree_add_uint(chunk_tree, hf_sctp_asconf_serial, chunk_tvb, offset, SERIAL_NUMBER_LENGTH, serial_number);
1839     offset          += SERIAL_NUMBER_LENGTH;
1840     proto_tree_add_bytes(chunk_tree, hf_sctp_asconf_reserved, chunk_tvb, offset, ASCONF_RESERVED_LENGTH, tvb_get_ptr(chunk_tvb, offset, ASCONF_RESERVED_LENGTH));
1841     offset          += ASCONF_RESERVED_LENGTH;
1842     addr_type = tvb_get_guint8(chunk_tvb, offset);
1843     proto_tree_add_uint(chunk_tree, hf_sctp_asconf_addr_type, chunk_tvb, offset, ASCONF_ADDR_TYPE_LENGTH, addr_type);
1844     offset          += ASCONF_ADDR_TYPE_LENGTH;
1845     switch (addr_type) {
1846       case IP_V4_ADDRESS_TYPE:
1847         tvb_memcpy(chunk_tvb, (guint8 *)&ipv4_address, offset, IPV4_ADDRESS_LENGTH); 
1848         proto_tree_add_ipv4(chunk_tree, hf_sctp_asconf_ipv4_address, chunk_tvb, offset, IPV4_ADDRESS_LENGTH, ipv4_address);
1849         proto_tree_add_bytes(chunk_tree, hf_sctp_asconf_addr, chunk_tvb, offset + IPV4_ADDRESS_LENGTH, ASCONF_ADDR_LENGTH - IPV4_ADDRESS_LENGTH,
1850                              tvb_get_ptr(chunk_tvb, offset + IPV4_ADDRESS_LENGTH, ASCONF_ADDR_LENGTH - IPV4_ADDRESS_LENGTH));
1851         break;
1852       case IP_V6_ADDRESS_TYPE:
1853           proto_tree_add_ipv6(chunk_tree, hf_sctp_asconf_ipv6_address, chunk_tvb, offset, IPV6_ADDRESS_LENGTH,
1854                                           tvb_get_ptr(chunk_tvb, offset, IPV6_ADDRESS_LENGTH));
1855         break;
1856       default:
1857         proto_tree_add_bytes(chunk_tree, hf_sctp_asconf_addr, chunk_tvb, offset, ASCONF_ADDR_LENGTH, tvb_get_ptr(chunk_tvb, offset, ASCONF_ADDR_LENGTH));
1858         break;
1859     }
1860     offset          += ASCONF_ADDR_LENGTH;
1861     proto_item_set_text(chunk_item, "ASCONF chunk");
1862     
1863     while(tvb_reported_length_remaining(chunk_tvb, offset)) {
1864       correlation_id = tvb_get_ntohl(chunk_tvb, offset);
1865       proto_tree_add_uint(chunk_tree, hf_sctp_asconf_correlation_id, chunk_tvb, offset, CORRELATION_ID_LENGTH, correlation_id);
1866       offset        += CORRELATION_ID_LENGTH;
1867       length         = tvb_get_ntohs(chunk_tvb, offset + PARAMETER_LENGTH_OFFSET);
1868       padding_length = nr_of_padding_bytes(length);
1869       total_length   = length + padding_length;
1870       /* create a tvb for the chunk including the padding bytes */
1871       parameter_tvb  = tvb_new_subset(chunk_tvb, offset, total_length, total_length);
1872       dissect_parameter(parameter_tvb, pinfo, chunk_tree); 
1873       /* get rid of the handled parameter */
1874       offset        += total_length;
1875     }
1876   } 
1877 }
1878
1879 static void
1880 dissect_asconf_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1881
1882   guint32 serial_number, correlation_id;
1883   guint offset, length, padding_length, total_length;
1884   tvbuff_t *parameter_tvb;
1885
1886   if (check_col(pinfo->cinfo, COL_INFO))
1887     col_append_str(pinfo->cinfo, COL_INFO, "ASCONF-ACK ");
1888
1889   if (chunk_tree) {
1890     serial_number = tvb_get_ntohl(chunk_tvb, SERIAL_NUMBER_OFFSET);
1891     proto_tree_add_uint(chunk_tree, hf_sctp_asconf_ack_serial, chunk_tvb, SERIAL_NUMBER_OFFSET, SERIAL_NUMBER_LENGTH, serial_number);
1892     proto_item_set_text(chunk_item, "ASCONF-ACK chunk");
1893     
1894     offset = SERIAL_NUMBER_OFFSET + SERIAL_NUMBER_LENGTH;
1895     while(tvb_reported_length_remaining(chunk_tvb, offset)) {
1896       correlation_id = tvb_get_ntohl(chunk_tvb, offset);
1897       proto_tree_add_uint(chunk_tree, hf_sctp_asconf_ack_correlation_id, chunk_tvb, offset, CORRELATION_ID_LENGTH, correlation_id);
1898       offset        += CORRELATION_ID_LENGTH;
1899       length         = tvb_get_ntohs(chunk_tvb, offset + PARAMETER_LENGTH_OFFSET);
1900       padding_length = nr_of_padding_bytes(length);
1901       total_length   = length + padding_length;
1902       /* create a tvb for the chunk including the padding bytes */
1903       parameter_tvb  = tvb_new_subset(chunk_tvb, offset, total_length, total_length);
1904       dissect_parameter(parameter_tvb, pinfo, chunk_tree); 
1905       /* get rid of the handled parameter */
1906       offset        += total_length;
1907     }
1908   } 
1909 }
1910
1911 static void
1912 dissect_unknown_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1913                       proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1914
1915   guint length, chunk_value_length, padding_length;
1916   guint8 type;
1917   
1918   if (check_col(pinfo->cinfo, COL_INFO))
1919     col_append_str(pinfo->cinfo, COL_INFO, "UNKNOWN ");
1920
1921   if (chunk_tree) {
1922     length         = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1923     padding_length = nr_of_padding_bytes(length);
1924     type           = tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET);
1925     
1926     chunk_value_length = length - CHUNK_HEADER_LENGTH;
1927     
1928     proto_tree_add_text(chunk_tree, chunk_tvb, CHUNK_VALUE_OFFSET, chunk_value_length,
1929                         "Chunk value (%u byte%s)",
1930                         chunk_value_length, plurality(chunk_value_length, "", "s"));
1931     
1932     if (padding_length > 0)
1933       proto_tree_add_text(chunk_tree, chunk_tvb, CHUNK_HEADER_OFFSET + length, padding_length,
1934                           "Padding: %u byte%s",
1935                           padding_length, plurality(padding_length, "", "s"));
1936     
1937     proto_item_set_text(chunk_item, "Chunk of type %u and %u byte%s value",
1938                         type, chunk_value_length, plurality(chunk_value_length, "", "s"));
1939   }
1940
1941
1942
1943 static gboolean
1944 dissect_sctp_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *sctp_tree)
1945 {  
1946   guint8 type, flags;
1947   guint16 length;
1948   gboolean result;
1949   proto_item *flags_item;
1950   proto_item *chunk_item;
1951   proto_tree *chunk_tree;
1952
1953   result = FALSE;
1954   
1955   /* first extract the chunk header */
1956   type   = tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET);
1957   flags  = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
1958   length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1959  
1960   if (tree) {
1961     /* create proto_tree stuff */
1962     chunk_item   = proto_tree_add_text(sctp_tree, chunk_tvb, CHUNK_HEADER_OFFSET, -1, "Incomplete chunk");
1963     chunk_tree   = proto_item_add_subtree(chunk_item, ett_sctp_chunk);
1964     
1965     /* then insert the chunk header components into the protocol tree */
1966     proto_tree_add_uint(chunk_tree, hf_sctp_chunk_type, chunk_tvb, CHUNK_TYPE_OFFSET, CHUNK_TYPE_LENGTH, type);
1967     flags_item = proto_tree_add_uint(chunk_tree, hf_sctp_chunk_flags, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
1968     proto_tree_add_uint(chunk_tree, hf_sctp_chunk_length, chunk_tvb, CHUNK_LENGTH_OFFSET, CHUNK_LENGTH_LENGTH, length);
1969   } else {
1970     chunk_tree = NULL;
1971     chunk_item = NULL;
1972     flags_item = NULL;
1973   };
1974   
1975   /* now dissect the chunk value */
1976
1977   switch(type) {
1978   case SCTP_DATA_CHUNK_ID:
1979     result = dissect_data_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1980     break;
1981   case SCTP_INIT_CHUNK_ID:
1982     dissect_init_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1983     break;
1984   case SCTP_INIT_ACK_CHUNK_ID:
1985     dissect_init_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1986     break;
1987   case SCTP_SACK_CHUNK_ID:
1988     dissect_sack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1989     break; 
1990   case SCTP_HEARTBEAT_CHUNK_ID:
1991     dissect_heartbeat_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1992     break;
1993   case SCTP_HEARTBEAT_ACK_CHUNK_ID:
1994     dissect_heartbeat_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1995     break;
1996   case SCTP_ABORT_CHUNK_ID:
1997     dissect_abort_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1998     break;
1999   case SCTP_SHUTDOWN_CHUNK_ID:
2000     dissect_shutdown_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
2001     break;
2002   case SCTP_SHUTDOWN_ACK_CHUNK_ID:
2003     dissect_shutdown_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
2004     break;
2005   case SCTP_ERROR_CHUNK_ID:
2006     dissect_error_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
2007     break;
2008   case SCTP_COOKIE_ECHO_CHUNK_ID:
2009     dissect_cookie_echo_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
2010     break;
2011   case SCTP_COOKIE_ACK_CHUNK_ID:
2012     dissect_cookie_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
2013     break;
2014   case SCTP_ECNE_CHUNK_ID:
2015     dissect_ecne_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
2016     break;
2017   case SCTP_CWR_CHUNK_ID:
2018     dissect_cwr_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
2019     break;
2020   case SCTP_SHUTDOWN_COMPLETE_CHUNK_ID:
2021     dissect_shutdown_complete_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
2022     break;
2023   case SCTP_FORWARD_TSN_CHUNK_ID:
2024     dissect_forward_tsn_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
2025     break;
2026   case SCTP_ASCONF_ACK_CHUNK_ID:
2027     dissect_asconf_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
2028     break;
2029   case SCTP_ASCONF_CHUNK_ID:
2030     dissect_asconf_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
2031     break;
2032   default:
2033     dissect_unknown_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
2034     break;
2035   };
2036   return result;
2037 }
2038
2039 static void
2040 dissect_sctp_chunks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *sctp_item, proto_tree *sctp_tree)
2041
2042   tvbuff_t *chunk_tvb;
2043   guint16 length, padding_length, total_length;
2044   gint last_offset, offset;
2045   gboolean sctp_item_length_set;
2046
2047   /* the common header of the datagram is already handled */
2048   last_offset = 0;
2049   offset = COMMON_HEADER_LENGTH;
2050   sctp_item_length_set = FALSE;
2051
2052   while(tvb_reported_length_remaining(tvb, offset) > 0) {
2053     /* extract the chunk length and compute number of padding bytes */
2054     length         = tvb_get_ntohs(tvb, offset + CHUNK_LENGTH_OFFSET);
2055     padding_length = nr_of_padding_bytes(length);
2056     total_length   = length + padding_length;
2057     /* create a tvb for the chunk including the padding bytes */
2058     chunk_tvb    = tvb_new_subset(tvb, offset, total_length, total_length);
2059     /* call dissect_sctp_chunk for a actual work */
2060     if (dissect_sctp_chunk(chunk_tvb, pinfo, tree, sctp_tree) && (tree)) {
2061       proto_item_set_len(sctp_item, offset - last_offset + DATA_CHUNK_HEADER_LENGTH);
2062       sctp_item_length_set = TRUE;
2063       offset += total_length;
2064       last_offset = offset;
2065       if (tvb_reported_length_remaining(tvb, offset) > 0) {
2066         sctp_item = proto_tree_add_item(tree, proto_sctp, tvb, offset, -1, FALSE);
2067         sctp_tree = proto_item_add_subtree(sctp_item, ett_sctp);
2068         sctp_item_length_set = FALSE;
2069       }
2070     } else {
2071     /* get rid of the dissected chunk */
2072     offset += total_length;
2073     }
2074   };
2075   if (!sctp_item_length_set && (tree)) { 
2076     proto_item_set_len(sctp_item, offset - last_offset);
2077   };
2078 }
2079
2080 /* dissect_sctp handles the common header of a SCTP datagram.
2081  * For the handling of the chunks dissect_sctp_chunks is called.
2082  */
2083
2084 static void
2085 dissect_sctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2086 {
2087   guint16 source_port, destination_port;
2088   guint32 verification_tag, checksum, calculated_crc32c, calculated_adler32;
2089   guint length;
2090   gboolean crc32c_correct, adler32_correct;
2091   proto_item *sctp_item;
2092   proto_tree *sctp_tree;
2093
2094   /* Extract the common header */
2095   source_port      = tvb_get_ntohs(tvb, SOURCE_PORT_OFFSET);
2096   destination_port = tvb_get_ntohs(tvb, DESTINATION_PORT_OFFSET);
2097   verification_tag = tvb_get_ntohl(tvb, VERIFICATION_TAG_OFFSET);
2098   checksum         = tvb_get_ntohl(tvb, CHECKSUM_OFFSET);
2099
2100   /* update pi structure */
2101   pinfo->ptype    = PT_SCTP;
2102   pinfo->srcport  = source_port;
2103   pinfo->destport = destination_port;
2104
2105   /* make entry in the Protocol column on summary display */
2106   if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
2107     col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCTP");
2108
2109   /* Clear entries in Info column on summary display */
2110   if (check_col(pinfo->cinfo, COL_INFO))
2111     col_add_str(pinfo->cinfo, COL_INFO, "");
2112   
2113   /* In the interest of speed, if "tree" is NULL, don't do any work not
2114      necessary to generate protocol tree items. */
2115   if (tree) {
2116     /* create the sctp protocol tree */
2117     sctp_item = proto_tree_add_item(tree, proto_sctp, tvb, 0, -1, FALSE);
2118     sctp_tree = proto_item_add_subtree(sctp_item, ett_sctp);
2119     
2120     /* add the components of the common header to the protocol tree */
2121     proto_tree_add_uint(sctp_tree, hf_sctp_source_port, tvb, SOURCE_PORT_OFFSET, SOURCE_PORT_LENGTH, source_port);
2122     proto_tree_add_uint(sctp_tree, hf_sctp_destination_port, tvb, DESTINATION_PORT_OFFSET, DESTINATION_PORT_LENGTH, destination_port);
2123     proto_tree_add_uint(sctp_tree, hf_sctp_verification_tag, tvb, VERIFICATION_TAG_OFFSET, VERIFICATION_TAG_LENGTH, verification_tag);
2124     proto_tree_add_uint_hidden(sctp_tree, hf_sctp_port, tvb, SOURCE_PORT_OFFSET, SOURCE_PORT_LENGTH, source_port);
2125     proto_tree_add_uint_hidden(sctp_tree, hf_sctp_port, tvb, DESTINATION_PORT_OFFSET, DESTINATION_PORT_LENGTH, destination_port);
2126
2127     length = tvb_length(tvb);
2128     switch(sctp_checksum) {
2129     case SCTP_CHECKSUM_NONE:
2130       proto_tree_add_uint_format(sctp_tree, hf_sctp_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, checksum, "Checksum: 0x%08x (not verified)", checksum);
2131       break;
2132     case SCTP_CHECKSUM_ADLER32:
2133       calculated_adler32 = sctp_adler32(tvb_get_ptr(tvb, 0, length), length);
2134       adler32_correct    = (checksum == calculated_adler32);
2135       if (adler32_correct)
2136         proto_tree_add_uint_format(sctp_tree, hf_sctp_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2137                                    checksum, "Checksum: 0x%08x (correct Adler32)", checksum);
2138       else
2139         proto_tree_add_uint_format(sctp_tree, hf_sctp_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, 
2140                                    checksum, "Checksum: 0x%08x (incorrect Adler32, should be 0x%08x)", checksum, calculated_adler32);    
2141       proto_tree_add_boolean_hidden(sctp_tree, hf_sctp_checksum_bad, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, !(adler32_correct));
2142       break;
2143     case SCTP_CHECKSUM_CRC32C:
2144       calculated_crc32c = sctp_crc32c(tvb_get_ptr(tvb, 0, length), length);
2145       crc32c_correct    = (checksum == calculated_crc32c);
2146       if (crc32c_correct)
2147         proto_tree_add_uint_format(sctp_tree, hf_sctp_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2148                                    checksum, "Checksum: 0x%08x (correct CRC32C)", checksum);
2149       else
2150         proto_tree_add_uint_format(sctp_tree, hf_sctp_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, 
2151                                    checksum, "Checksum: 0x%08x (incorrect CRC32C, should be 0x%08x)", checksum, calculated_crc32c);    
2152       proto_tree_add_boolean_hidden(sctp_tree, hf_sctp_checksum_bad, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, !(crc32c_correct));
2153       break;
2154     case SCTP_CHECKSUM_AUTOMATIC:
2155       calculated_adler32 = sctp_adler32(tvb_get_ptr(tvb, 0, length), length);
2156       adler32_correct    = (checksum == calculated_adler32);
2157       calculated_crc32c  = sctp_crc32c(tvb_get_ptr(tvb, 0, length), length);
2158       crc32c_correct     = (checksum == calculated_crc32c);
2159       if ((adler32_correct) && !(crc32c_correct))
2160         proto_tree_add_uint_format(sctp_tree, hf_sctp_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2161                                    checksum, "Checksum: 0x%08x (correct Adler32)", checksum);
2162       else if (!(adler32_correct) && (crc32c_correct))
2163         proto_tree_add_uint_format(sctp_tree, hf_sctp_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2164                                    checksum, "Checksum: 0x%08x (correct CRC32C)", checksum);
2165       else if ((adler32_correct) && (crc32c_correct))
2166         proto_tree_add_uint_format(sctp_tree, hf_sctp_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2167                                    checksum, "Checksum: 0x%08x (correct Adler32 and CRC32C)", checksum);
2168       else
2169         proto_tree_add_uint_format(sctp_tree, hf_sctp_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, 
2170                                    checksum, "Checksum: 0x%08x (incorrect, should be 0x%08x (Adler32) or 0x%08x (CRC32C))",
2171                                    checksum, calculated_adler32, calculated_crc32c);
2172       proto_tree_add_boolean_hidden(sctp_tree, hf_sctp_checksum_bad, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, !(crc32c_correct || adler32_correct));
2173       break;
2174     }
2175   } else {
2176     sctp_tree = NULL;
2177     sctp_item = NULL;
2178   };
2179   /* add all chunks of the sctp datagram to the protocol tree */
2180   dissect_sctp_chunks(tvb, pinfo, tree, sctp_item, sctp_tree);
2181 }
2182
2183 /* Register the protocol with Ethereal */
2184 void
2185 proto_register_sctp(void)
2186 {                 
2187
2188   /* Setup list of header fields */
2189   static hf_register_info hf[] = {
2190     { &hf_sctp_source_port,
2191       { "Source port", "sctp.srcport",
2192               FT_UINT16, BASE_DEC, NULL, 0x0,          
2193               "", HFILL }
2194     },
2195     { &hf_sctp_destination_port,
2196       { "Destination port", "sctp.dstport",
2197                FT_UINT16, BASE_DEC, NULL, 0x0,          
2198                "", HFILL }
2199     }, 
2200     { &hf_sctp_port,
2201       { "Port", "sctp.port",
2202                FT_UINT16, BASE_DEC, NULL, 0x0,          
2203                "", HFILL }
2204     }, 
2205     { &hf_sctp_verification_tag,
2206       { "Verification tag", "sctp.verfication_tag",
2207                FT_UINT32, BASE_HEX, NULL, 0x0,          
2208                "", HFILL }
2209     },
2210     { &hf_sctp_checksum,
2211       { "Checksum", "sctp.checksum",
2212               FT_UINT32, BASE_HEX, NULL, 0x0,          
2213               "", HFILL }
2214     },
2215     { &hf_sctp_checksum_bad,
2216       { "Bad checksum", "sctp.checksum_bad",
2217               FT_BOOLEAN, BASE_NONE, NULL, 0x0,          
2218               "", HFILL }
2219     },
2220     { &hf_sctp_chunk_type,
2221       { "Identifier", "sctp.chunk_type",
2222         FT_UINT8, BASE_DEC, VALS(sctp_chunk_type_values), 0x0,          
2223         "", HFILL }
2224     },
2225     { &hf_sctp_chunk_flags,
2226       { "Flags", "sctp.chunk_flags",
2227         FT_UINT8, BASE_BIN, NULL, 0x0,          
2228         "", HFILL }
2229     },
2230     { &hf_sctp_chunk_length,
2231       { "Length", "sctp.chunk_length",
2232         FT_UINT16, BASE_DEC, NULL, 0x0,          
2233         "", HFILL }
2234     },
2235     { &hf_sctp_init_chunk_initiate_tag,
2236       { "Initiate tag", "sctp.init.chunk.initiate.tag",
2237         FT_UINT32, BASE_HEX, NULL, 0x0,          
2238         "", HFILL }
2239     },
2240     { &hf_sctp_init_chunk_adv_rec_window_credit,
2241       { "Advertised reciever window credit (a_rwnd)", "sctp.init.chunk.credit",
2242         FT_UINT32, BASE_DEC, NULL, 0x0,          
2243         "", HFILL }
2244     },
2245     { &hf_sctp_init_chunk_number_of_outbound_streams,
2246       { "Number of outbound streams", "sctp.init.chunk.nr.out.streams",
2247         FT_UINT16, BASE_DEC, NULL, 0x0,          
2248         "", HFILL }
2249     },
2250     { &hf_sctp_init_chunk_number_of_inbound_streams,
2251       { "Number of inbound streams", "sctp.init.chunk.nr.in.streams",
2252         FT_UINT16, BASE_DEC, NULL, 0x0,          
2253         "", HFILL }
2254     },
2255     {&hf_sctp_init_chunk_initial_tsn,
2256       { "Initial TSN", "sctp.init.chunk.initial.tsn",
2257         FT_UINT32, BASE_DEC, NULL, 0x0,          
2258         "", HFILL }
2259     }, 
2260     {&hf_sctp_cumulative_tsn_ack,
2261      { "Cumulative TSN Ack", "sctp.cumulative.tsn.ack",
2262         FT_UINT32, BASE_DEC, NULL, 0x0,          
2263         "", HFILL }
2264     },
2265     {&hf_sctp_data_chunk_tsn,
2266      { "TSN", "sctp.tsn",
2267        FT_UINT32, BASE_DEC, NULL, 0x0,          
2268         "", HFILL }
2269     },
2270     {&hf_sctp_data_chunk_stream_id,
2271      { "Stream Identifier", "sctp.stream_id",
2272         FT_UINT16, BASE_HEX, NULL, 0x0,          
2273         "", HFILL }
2274     },
2275     {&hf_sctp_data_chunk_stream_seq_number,
2276      { "Stream sequence number", "sctp.stream_seq_number",
2277        FT_UINT16, BASE_DEC, NULL, 0x0,          
2278        "", HFILL }
2279     },
2280     {&hf_sctp_data_chunk_payload_proto_id,
2281      { "Payload protocol identifier", "sctp.payload_proto_id",
2282         FT_UINT32, BASE_DEC, VALS(sctp_payload_proto_id_values), 0x0,          
2283         "", HFILL }
2284     },
2285     {&hf_sctp_data_chunk_e_bit,
2286      { "E-Bit", "sctp.data.e_bit",
2287        FT_BOOLEAN, 8, TFS(&sctp_data_chunk_e_bit_value), SCTP_DATA_CHUNK_E_BIT,          
2288        "", HFILL }
2289     },
2290     {&hf_sctp_data_chunk_b_bit,
2291      { "B-Bit", "sctp.data.b_bit",
2292        FT_BOOLEAN, 8, TFS(&sctp_data_chunk_b_bit_value), SCTP_DATA_CHUNK_B_BIT,          
2293        "", HFILL }
2294     },
2295     {&hf_sctp_data_chunk_u_bit,
2296      { "U-Bit", "sctp.data.u.bit",
2297        FT_BOOLEAN, 8, TFS(&sctp_data_chunk_u_bit_value), SCTP_DATA_CHUNK_U_BIT,          
2298        "", HFILL }
2299     },
2300     {&hf_sctp_sack_chunk_cumulative_tsn_ack,
2301      { "Cumulative TSN ACK", "sctp.sack.cumulative_tsn_ack",
2302        FT_UINT32, BASE_DEC, NULL, 0x0,          
2303        "", HFILL }
2304     }, 
2305     {&hf_sctp_sack_chunk_adv_rec_window_credit,
2306      { "Advertised receiver window credit (a_rwnd)", "sctp.sack.a_rwnd",
2307        FT_UINT32, BASE_DEC, NULL, 0x0,          
2308        "", HFILL }
2309     },
2310     {&hf_sctp_sack_chunk_number_of_gap_blocks,
2311      { "Number of gap acknowldgement blocks ", "sctp.sack.number_of_gap_blocks",
2312        FT_UINT16, BASE_DEC, NULL, 0x0,          
2313        "", HFILL }
2314     }, 
2315     {&hf_sctp_sack_chunk_number_of_dup_tsns,
2316      { "Number of duplicated TSNs", "sctp.sack.number_of_duplicated_tsns",
2317        FT_UINT16, BASE_DEC, NULL, 0x0,          
2318        "", HFILL }
2319     },
2320     {&hf_sctp_sack_chunk_gap_block_start,
2321      { "Start", "sctp.sack.gap_block_start",
2322        FT_UINT16, BASE_DEC, NULL, 0x0,          
2323        "", HFILL }
2324     },
2325     {&hf_sctp_sack_chunk_gap_block_end,
2326      { "End", "sctp.sack.gap_block_end",
2327        FT_UINT16, BASE_DEC, NULL, 0x0,          
2328        "", HFILL }
2329     },
2330     {&hf_sctp_sack_chunk_duplicate_tsn,
2331      { "Duplicate TSN", "sctp.sack.duplicate.tsn",
2332        FT_UINT16, BASE_DEC, NULL, 0x0,          
2333        "", HFILL }
2334     },  
2335     {&hf_sctp_shutdown_chunk_cumulative_tsn_ack,
2336      { "Cumulative TSN Ack", "sctp.shutdown.cumulative_tsn_ack",
2337         FT_UINT32, BASE_DEC, NULL, 0x0,          
2338         "", HFILL }
2339     },
2340     {&hf_sctp_ecne_chunk_lowest_tsn,
2341      { "Lowest TSN", "sctp.ecne.lowest_tsn",
2342        FT_UINT32, BASE_DEC, NULL, 0x0,          
2343        "", HFILL }
2344     }, 
2345     {&hf_sctp_cwr_chunk_lowest_tsn,
2346      { "Lowest TSN", "sctp.cwr.lowest_tsn",
2347        FT_UINT32, BASE_DEC, NULL, 0x0,          
2348        "", HFILL }
2349     }, 
2350     {&hf_sctp_shutdown_complete_chunk_t_bit,
2351      { "E-Bit", "sctp.shutdown_complete.t_bit",
2352        FT_BOOLEAN, 8, TFS(&sctp_shutdown_complete_chunk_t_bit_value), SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT,
2353        "", HFILL }
2354     },
2355     {&hf_sctp_forward_tsn_chunk_tsn,
2356      { "New cumulative TSN", "sctp.forward_tsn.tsn",
2357        FT_UINT32, BASE_DEC, NULL, 0x0,          
2358        "", HFILL }
2359     }, 
2360     {&hf_sctp_chunk_parameter_type,
2361      { "Parameter type", "sctp.parameter.type",
2362        FT_UINT16, BASE_HEX, VALS(sctp_parameter_identifier_values), 0x0,
2363        "", HFILL }
2364     },
2365     {&hf_sctp_chunk_parameter_length,
2366      { "Parameter length", "sctp.parameter.length",
2367        FT_UINT16, BASE_DEC, NULL, 0x0,          
2368        "", HFILL }
2369     },
2370     {&hf_sctp_parameter_ipv4_address,
2371      { "IP Version 4 address", "sctp.parameter.ipv4_address",
2372        FT_IPv4, BASE_NONE, NULL, 0x0,
2373        "", HFILL }
2374     },
2375     {&hf_sctp_parameter_ipv6_address,
2376      { "IP Version 6 address", "sctp.parameter.ipv6_address",
2377        FT_IPv6, BASE_NONE, NULL, 0x0,
2378        "", HFILL }
2379     },
2380     {&hf_sctp_parameter_cookie_preservative_increment,
2381      { "Suggested Cookie life-span increment (msec)", "sctp.parameter.cookie_preservative_incr",
2382        FT_UINT32, BASE_DEC, NULL, 0x0,          
2383        "", HFILL }
2384     },
2385     {&hf_sctp_parameter_hostname_hostname,
2386      { "Hostname", "sctp.parameter.hostname.hostname",
2387        FT_STRING, BASE_NONE, NULL, 0x0,          
2388        "", HFILL }
2389     }, 
2390     {&hf_sctp_supported_address_types_parameter,
2391      { "Supported address type", "sctp.parameter.supported_addres_type",
2392        FT_UINT16, BASE_DEC, NULL, 0x0,          
2393        "", HFILL }
2394     }, 
2395     {&hf_sctp_ustreams_start,
2396      { "Start", "sctp.unreliable_streams.start",
2397        FT_UINT16, BASE_DEC, NULL, 0x0,          
2398        "", HFILL }
2399     }, 
2400     {&hf_sctp_ustreams_end,
2401      { "End", "sctp.unreliable_streams.end",
2402        FT_UINT16, BASE_DEC, NULL, 0x0,          
2403        "", HFILL }
2404     },     
2405     {&hf_sctp_asconf_serial,
2406      { "Serial Number", "sctp.asconf.serial_number",
2407        FT_UINT32, BASE_HEX, NULL, 0x0,          
2408        "", HFILL }
2409     }, 
2410     {&hf_sctp_asconf_correlation_id,
2411      { "Correlation_id", "sctp.asconf.correlation_id",
2412        FT_UINT32, BASE_HEX, NULL, 0x0,          
2413        "", HFILL }
2414     }, 
2415     {&hf_sctp_asconf_reserved,
2416      { "Reserved", "sctp.asconf.reserved",
2417        FT_BYTES, BASE_NONE, NULL, 0x0,          
2418        "", HFILL }
2419     }, 
2420     {&hf_sctp_asconf_addr_type,
2421      { "Address type", "sctp.asconf.address_type",
2422        FT_UINT8, BASE_HEX, VALS(sctp_address_type_values), 0x0,          
2423        "", HFILL }
2424     }, 
2425     {&hf_sctp_asconf_addr,
2426      { "Address bytes", "sctp.asconf.address_bytes",
2427        FT_BYTES, BASE_NONE, NULL, 0x0,          
2428        "", HFILL }
2429     }, 
2430     {&hf_sctp_asconf_ipv4_address,
2431      { "IP Version 4 address", "sctp.asconf.ipv4_address",
2432        FT_IPv4, BASE_NONE, NULL, 0x0,
2433        "", HFILL }
2434     },
2435     {&hf_sctp_asconf_ipv6_address,
2436      { "IP Version 6 address", "sctp.asconf.ipv6_address",
2437        FT_IPv6, BASE_NONE, NULL, 0x0,
2438        "", HFILL }
2439     },
2440     {&hf_sctp_asconf_ack_serial,
2441      { "Serial Number", "sctp.asconf_ack.serial_number",
2442        FT_UINT32, BASE_HEX, NULL, 0x0,          
2443        "", HFILL }
2444     }, 
2445     {&hf_sctp_asconf_ack_correlation_id,
2446      { "Correlation_id", "sctp.asconf_ack.correlation_id",
2447        FT_UINT32, BASE_HEX, NULL, 0x0,          
2448        "", HFILL }
2449     },
2450     {&hf_sctp_adap_indication,
2451      { "Indication", "sctp.adapation_layer_indication.indication",
2452        FT_UINT32, BASE_HEX, NULL, 0x0,          
2453        "", HFILL }
2454     }, 
2455     {&hf_sctp_cause_code,
2456      { "Cause code", "sctp.cause.code",
2457        FT_UINT16, BASE_HEX, VALS(sctp_cause_code_values), 0x0,          
2458        "", HFILL }
2459     },
2460     {&hf_sctp_cause_length,
2461      { "Cause length", "sctp.cause.length",
2462        FT_UINT16, BASE_DEC, NULL, 0x0,          
2463        "", HFILL }
2464     }, 
2465     {&hf_sctp_cause_stream_identifier,
2466      { "Stream identifier", "sctp.cause.stream_identifier",
2467        FT_UINT16, BASE_DEC, NULL, 0x0,          
2468        "", HFILL }
2469     },
2470     {&hf_sctp_cause_number_of_missing_parameters,
2471      { "Number of missing parameters", "sctp.cause.nr_of_missing_parameters",
2472        FT_UINT32, BASE_DEC, NULL, 0x0,          
2473        "", HFILL }
2474     }, 
2475     {&hf_sctp_cause_missing_parameter_type,
2476      { "Missing parameter type", "sctp.cause.missing_parameter_type",
2477        FT_UINT16, BASE_HEX, VALS(sctp_parameter_identifier_values), 0x0,
2478        "", HFILL }
2479     },
2480     {&hf_sctp_cause_measure_of_staleness,
2481      { "Measure of staleness in usec", "sctp.cause.measure_of_staleness",
2482        FT_UINT32, BASE_DEC, NULL, 0x0,          
2483        "", HFILL }
2484     },
2485     {&hf_sctp_cause_tsn,
2486      { "TSN", "sctp.cause.tsn",
2487        FT_UINT32, BASE_DEC, NULL, 0x0,          
2488        "", HFILL }
2489     },
2490   };
2491   
2492   /* Setup protocol subtree array */
2493   static gint *ett[] = {
2494     &ett_sctp,
2495     &ett_sctp_chunk,
2496     &ett_sctp_chunk_parameter,
2497     &ett_sctp_chunk_cause,
2498     &ett_sctp_data_chunk_flags,
2499     &ett_sctp_sack_chunk_gap_block,
2500     &ett_sctp_supported_address_types_parameter,
2501     &ett_sctp_unrecognized_parameter_parameter,
2502     &ett_sctp_unreliable_streams_interval
2503   };
2504   
2505   static enum_val_t sctp_checksum_options[] = {
2506     { "None",        SCTP_CHECKSUM_NONE },
2507     { "Adler 32",    SCTP_CHECKSUM_ADLER32 },
2508     { "CRC 32c",     SCTP_CHECKSUM_CRC32C },
2509     { "Automatic",   SCTP_CHECKSUM_AUTOMATIC},
2510     { NULL, 0 }
2511   };
2512  
2513   /* Register the protocol name and description */
2514   proto_sctp = proto_register_protocol("Stream Control Transmission Protocol", "SCTP", "sctp");
2515   sctp_module = prefs_register_protocol(proto_sctp, NULL);
2516   prefs_register_enum_preference(sctp_module, "checksum",
2517                                  "Checksum type",
2518                                  "The type of checksum used in SCTP packets",
2519                                  &sctp_checksum, sctp_checksum_options, FALSE);
2520
2521   /* Required function calls to register the header fields and subtrees used */
2522   proto_register_field_array(proto_sctp, hf, array_length(hf));
2523   proto_register_subtree_array(ett, array_length(ett));
2524
2525   /* subdissector code */
2526   sctp_port_dissector_table = register_dissector_table("sctp.port", "SCTP port", FT_UINT16, BASE_DEC);
2527   sctp_ppi_dissector_table  = register_dissector_table("sctp.ppi",  "SCTP payload protocol identifier", FT_UINT32, BASE_HEX);
2528
2529 };
2530
2531 void
2532 proto_reg_handoff_sctp(void)
2533 {
2534   dissector_handle_t sctp_handle;
2535
2536   sctp_handle = create_dissector_handle(dissect_sctp, proto_sctp);
2537   dissector_add("ip.proto", IP_PROTO_SCTP, sctp_handle);
2538 }