From Michael Tuexen:
[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-01.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.31 2002/02/02 21:17:10 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             
608   for (i = 0; i < SOURCE_PORT_LENGTH + DESTINATION_PORT_LENGTH + VERIFICATION_TAG_LENGTH; i++) 
609   { 
610     CRC32C(crc32, buf[i]); 
611   }
612   CRC32C(crc32, 0);
613   CRC32C(crc32, 0);
614   CRC32C(crc32, 0);
615   CRC32C(crc32, 0);
616   for (i = COMMON_HEADER_LENGTH; i < len; i++) 
617   { 
618     CRC32C(crc32, buf[i]); 
619   }  
620   return crc32; 
621 }
622
623 static guint 
624 nr_of_padding_bytes (guint length)
625 {
626   guint remainder;
627
628   remainder = length % 4;
629
630   if (remainder == 0)
631     return 0;
632   else
633     return 4 - remainder;
634 }
635
636 /* 
637  * TLV parameter stuff for INIT and INIT-ACK chunks
638  */
639
640 static void
641 dissect_parameter(tvbuff_t *, packet_info *, proto_tree *);
642
643 static void
644 dissect_error_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *chunk_tree);
645
646 static gboolean
647 dissect_sctp_chunk(tvbuff_t *, packet_info *, proto_tree *, proto_tree *);
648
649 static void 
650 dissect_tlv_parameter_list(tvbuff_t *parameter_list_tvb, packet_info *pinfo, proto_tree *tree)
651 {
652   guint offset, length, padding_length, total_length;
653   tvbuff_t *parameter_tvb;
654
655   offset = 0;
656   while(tvb_reported_length_remaining(parameter_list_tvb, offset)) {
657     length         = tvb_get_ntohs(parameter_list_tvb, offset + PARAMETER_LENGTH_OFFSET);
658     padding_length = nr_of_padding_bytes(length);
659     total_length   = length + padding_length;
660     /* create a tvb for the chunk including the padding bytes */
661     parameter_tvb    = tvb_new_subset(parameter_list_tvb, offset, total_length, total_length);
662     dissect_parameter(parameter_tvb, pinfo, tree); 
663     /* get rid of the handled parameter */
664     offset += total_length;
665   }
666 }
667
668 static void
669 dissect_heartbeat_info_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
670 {
671   guint16 length, heartbeat_info_length;
672   
673   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
674   
675   heartbeat_info_length = length - HEARTBEAT_INFO_PARAMETER_HEADER_LENGTH;
676
677   proto_tree_add_text(parameter_tree, parameter_tvb, HEARTBEAT_INFO_PARAMETER_INFO_OFFSET, heartbeat_info_length,
678                       "Heartbeat info (%u byte%s)",
679                       heartbeat_info_length, plurality(heartbeat_info_length, "", "s"));
680
681   proto_item_set_text(parameter_item, "Heartbeat info parameter with %u byte%s of info",
682                       heartbeat_info_length, plurality(heartbeat_info_length, "", "s"));
683 }
684
685 static void
686 dissect_ipv4_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
687 {
688   guint32 ipv4_address;
689
690   tvb_memcpy(parameter_tvb, (guint8 *)&ipv4_address, PARAMETER_VALUE_OFFSET, IPV4_ADDRESS_LENGTH); 
691   proto_tree_add_ipv4(parameter_tree, hf_sctp_parameter_ipv4_address,
692                       parameter_tvb, PARAMETER_VALUE_OFFSET, IPV4_ADDRESS_LENGTH,
693                       ipv4_address);  
694   proto_item_set_text(parameter_item, "IPV4 address parameter");
695 }
696
697 static void
698 dissect_ipv6_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
699 {
700   proto_tree_add_ipv6(parameter_tree, hf_sctp_parameter_ipv6_address,
701                       parameter_tvb, PARAMETER_VALUE_OFFSET, IPV6_ADDRESS_LENGTH,
702                       tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, IPV6_ADDRESS_LENGTH));
703   
704   proto_item_set_text(parameter_item, "IPV6 address parameter");
705 }
706
707 static void
708 dissect_state_cookie_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
709 {
710   guint16 length, state_cookie_length;
711   
712   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
713   
714   state_cookie_length = length - STATE_COOKIE_PARAMETER_HEADER_LENGTH;
715
716   proto_tree_add_text(parameter_tree, parameter_tvb, STATE_COOKIE_PARAMETER_COOKIE_OFFSET, state_cookie_length,
717                       "State cookie (%u byte%s)",
718                       state_cookie_length, plurality(state_cookie_length, "", "s"));
719
720   proto_item_set_text(parameter_item, "State Cookie Parameter with %u byte%s cookie",
721                       state_cookie_length, plurality(state_cookie_length, "", "s"));
722 }
723
724 static void
725 dissect_unrecognized_parameters_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
726 {
727   guint16 length, padding_length, parameter_value_length;
728   tvbuff_t *unrecognized_parameters_tvb;
729
730   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
731   padding_length = nr_of_padding_bytes(length);
732
733   parameter_value_length = length - PARAMETER_HEADER_LENGTH + padding_length;
734
735   unrecognized_parameters_tvb = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, 
736                                                parameter_value_length, parameter_value_length);
737   dissect_tlv_parameter_list(unrecognized_parameters_tvb, pinfo, parameter_tree);
738    
739   proto_item_set_text(parameter_item, "Unrecognized parameter of type");
740 }
741
742 static void
743 dissect_cookie_preservative_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
744 {
745   guint32 increment;
746
747   increment =  tvb_get_ntohl(parameter_tvb, COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET);
748   
749   proto_tree_add_uint(parameter_tree, hf_sctp_parameter_cookie_preservative_increment, parameter_tvb, 
750                       COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET, 
751                       COOKIE_PRESERVATIVE_PARAMETER_INCR_LENGTH,
752                       increment);
753   
754   proto_item_set_text(parameter_item, "Cookie preservative parameter requesting for a %u msec increment",
755                       increment);
756 }
757
758 static void
759 dissect_hostname_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
760 {
761   guint16  length, hostname_length;
762   char *hostname;
763
764   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
765   
766   hostname_length = length - PARAMETER_HEADER_LENGTH;
767   hostname = (char *)tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, hostname_length);
768   proto_tree_add_string(parameter_tree, hf_sctp_parameter_hostname_hostname, parameter_tvb,
769                         PARAMETER_VALUE_OFFSET, hostname_length,
770                         hostname);
771
772   proto_item_set_text(parameter_item, "Hostname parameter");
773 }
774
775 static void
776 dissect_supported_address_types_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
777 {
778   guint16 length, address_type, number_of_address_types, address_type_number, list_of_address_types_length ;
779   guint offset;
780   proto_item *address_list_item;
781   proto_tree *address_list_tree;
782
783   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
784   list_of_address_types_length = length - PARAMETER_HEADER_LENGTH;
785   number_of_address_types = list_of_address_types_length / SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH;
786
787   address_list_item = proto_tree_add_text(parameter_tree, parameter_tvb, PARAMETER_VALUE_OFFSET, list_of_address_types_length,
788                                           "Supported Address Types (%u address type%s)",
789                                           number_of_address_types, plurality(number_of_address_types, "", "s"));
790   address_list_tree = proto_item_add_subtree(address_list_item, ett_sctp_supported_address_types_parameter);
791  
792   offset = PARAMETER_VALUE_OFFSET;
793   for(address_type_number = 1; address_type_number <= number_of_address_types; address_type_number++) {
794     address_type = tvb_get_ntohs(parameter_tvb, offset);
795     proto_tree_add_uint_format(address_list_tree, hf_sctp_supported_address_types_parameter,
796                                parameter_tvb, offset, SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH,
797                                address_type, "Supported address type: 0x%04x (%s)",
798                                address_type, val_to_str(address_type, sctp_parameter_identifier_values, "unknown"));
799     offset += SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH;
800   };
801
802   proto_item_set_text(parameter_item, "Supported address types parameter reporting %u address type%s",
803                       number_of_address_types, plurality(number_of_address_types, "", "s"));
804 }
805
806 static void
807 dissect_ecn_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
808 {
809    proto_item_set_text(parameter_item, "ECN parameter");
810 }
811
812 #define USTREAMS_START_LENGTH    2
813 #define USTREAMS_END_LENGTH      2
814 #define USTREAMS_INTERVAL_LENGTH (USTREAMS_START_LENGTH + USTREAMS_END_LENGTH)
815
816 static void
817 dissect_unreliable_streams_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
818 {  
819     guint16 length, start, end, number_of_intervals, interval_number;
820     proto_item *interval_item;
821     proto_tree *interval_tree;
822     gint interval_offset;
823     
824     length              = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
825     number_of_intervals = (length - PARAMETER_HEADER_LENGTH) / USTREAMS_INTERVAL_LENGTH;
826     
827     interval_offset     = PARAMETER_VALUE_OFFSET;
828     for(interval_number = 1; interval_number <= number_of_intervals; interval_number++) {
829       start = tvb_get_ntohs(parameter_tvb, interval_offset);
830       end   = tvb_get_ntohs(parameter_tvb, interval_offset + USTREAMS_START_LENGTH);
831       interval_item = proto_tree_add_text(parameter_tree, parameter_tvb, interval_offset, USTREAMS_INTERVAL_LENGTH, "Unreliable streams (%u-%u)", start, end);
832       interval_tree = proto_item_add_subtree(interval_item, ett_sctp_unreliable_streams_interval);
833       proto_tree_add_uint(interval_tree, hf_sctp_ustreams_start, parameter_tvb, interval_offset, USTREAMS_START_LENGTH, start);
834       proto_tree_add_uint(interval_tree, hf_sctp_ustreams_end,  parameter_tvb, interval_offset + USTREAMS_START_LENGTH, USTREAMS_END_LENGTH, end);
835       interval_offset += USTREAMS_INTERVAL_LENGTH;
836     };
837    proto_item_set_text(parameter_item, "Unreliable streams parameter");
838 }
839
840 static void
841 dissect_add_ip_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
842 {
843   guint16 length, parameter_value_length;
844   tvbuff_t *address_tvb;
845
846   length                 = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
847   parameter_value_length = length - PARAMETER_HEADER_LENGTH;
848
849   address_tvb            =  tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length, parameter_value_length);
850   dissect_parameter(address_tvb, pinfo, parameter_tree); 
851
852   proto_item_set_text(parameter_item, "Add IP address parameter");
853 }
854
855 static void
856 dissect_del_ip_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
857 {
858   guint16 length, parameter_value_length;
859   tvbuff_t *address_tvb;
860
861   length                 = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
862   parameter_value_length = length - PARAMETER_HEADER_LENGTH;
863
864   address_tvb            =  tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length, parameter_value_length);
865   dissect_parameter(address_tvb, pinfo, parameter_tree); 
866
867   proto_item_set_text(parameter_item, "Delete IP address parameter");
868 }
869
870 static void
871 dissect_error_cause_indication_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
872 {
873   guint16 length, padding_length, total_length;
874   gint offset;
875   tvbuff_t *error_cause_tvb;
876
877   offset = PARAMETER_VALUE_OFFSET;
878   while(tvb_reported_length_remaining(parameter_tvb, offset)) {
879     length         = tvb_get_ntohs(parameter_tvb, offset + CAUSE_LENGTH_OFFSET);
880     padding_length = nr_of_padding_bytes(length);
881     total_length   = length + padding_length;
882     /* create a tvb for the chunk including the padding bytes */
883     error_cause_tvb    = tvb_new_subset(parameter_tvb, offset , total_length, total_length);
884     dissect_error_cause(error_cause_tvb, pinfo, parameter_tree); 
885     /* get rid of the handled parameter */
886     offset += total_length;
887   }
888   proto_item_set_text(parameter_item, "Error cause indication");
889 }
890
891 static void
892 dissect_set_primary_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
893 {
894   guint16 length, parameter_value_length;
895   tvbuff_t *address_tvb;
896
897   length                 = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
898   parameter_value_length = length - PARAMETER_HEADER_LENGTH;
899
900   address_tvb            =  tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length, parameter_value_length);
901   dissect_parameter(address_tvb, pinfo, parameter_tree); 
902
903   proto_item_set_text(parameter_item, "Set primary address parameter");
904 }
905
906 static void
907 dissect_success_report_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
908 {
909    proto_item_set_text(parameter_item, "Success report parameter");
910 }
911
912 #define ADAP_INDICATION_LENGTH 4
913 #define ADAP_INDICATION_OFFSET PARAMETER_VALUE_OFFSET
914
915 static void
916 dissect_adap_indication_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
917 {
918   guint32 indication;
919
920   indication =  tvb_get_ntohl(parameter_tvb, ADAP_INDICATION_OFFSET);
921   proto_tree_add_uint(parameter_tree, hf_sctp_adap_indication, parameter_tvb, ADAP_INDICATION_OFFSET, ADAP_INDICATION_LENGTH, indication);
922   proto_item_set_text(parameter_item, "Adaptation layer indication");
923 }
924
925 static void
926 dissect_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
927 {
928   guint16 type, length, parameter_value_length;
929   
930   type   = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
931   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
932   
933   parameter_value_length = length - PARAMETER_HEADER_LENGTH;
934
935   proto_tree_add_text(parameter_tree, parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length,
936                       "Parameter value (%u byte%s)",
937                       parameter_value_length, plurality(parameter_value_length, "", "s"));
938
939   proto_item_set_text(parameter_item, "Parameter of type %u and %u byte%s value",
940                       type, parameter_value_length, plurality(parameter_value_length, "", "s"));
941 }
942
943 static void
944 dissect_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *chunk_tree)
945 {
946   guint16 type, length, padding_length, total_length;
947   proto_item *parameter_item;
948   proto_tree *parameter_tree;
949
950   type           = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
951   length         = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
952   padding_length = nr_of_padding_bytes(length);
953   total_length   = length + padding_length;
954    
955   parameter_item = proto_tree_add_text(chunk_tree, parameter_tvb,
956         PARAMETER_HEADER_OFFSET, total_length, "%s parameter",
957         val_to_str(type, sctp_parameter_identifier_values, "Unknown"));
958   parameter_tree = proto_item_add_subtree(parameter_item, ett_sctp_chunk_parameter);
959  
960   proto_tree_add_uint(parameter_tree, hf_sctp_chunk_parameter_type, 
961                       parameter_tvb, PARAMETER_TYPE_OFFSET, PARAMETER_TYPE_LENGTH,
962                       type);
963   proto_tree_add_uint(parameter_tree, hf_sctp_chunk_parameter_length, 
964                       parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH,
965                       length);
966  
967   switch(type) {
968   case HEARTBEAT_INFO_PARAMETER_ID:
969     dissect_heartbeat_info_parameter(parameter_tvb, parameter_tree, parameter_item);
970     break;
971   case IPV4ADDRESS_PARAMETER_ID:
972     dissect_ipv4_parameter(parameter_tvb, parameter_tree, parameter_item);
973     break;
974   case IPV6ADDRESS_PARAMETER_ID:
975     dissect_ipv6_parameter(parameter_tvb, parameter_tree, parameter_item);
976     break;
977   case STATE_COOKIE_PARAMETER_ID:
978     dissect_state_cookie_parameter(parameter_tvb, parameter_tree, parameter_item);
979     break;
980   case UNREC_PARA_PARAMETER_ID:
981     dissect_unrecognized_parameters_parameter(parameter_tvb, pinfo,  parameter_tree, parameter_item);
982     break;
983   case COOKIE_PRESERVATIVE_PARAMETER_ID:
984     dissect_cookie_preservative_parameter(parameter_tvb, parameter_tree, parameter_item);
985     break;
986   case HOSTNAME_ADDRESS_PARAMETER_ID:
987     dissect_hostname_parameter(parameter_tvb, parameter_tree, parameter_item);
988     break;
989   case SUPPORTED_ADDRESS_TYPES_PARAMETER_ID:
990     dissect_supported_address_types_parameter(parameter_tvb, parameter_tree, parameter_item);
991     break;
992   case ECN_PARAMETER_ID:
993     dissect_ecn_parameter(parameter_tvb, parameter_tree, parameter_item);
994     break;
995   case UNRELIABLE_STREAMS_PARAMETER_ID:
996     dissect_unreliable_streams_parameter(parameter_tvb, parameter_tree, parameter_item);
997     break;
998   case ADD_IP_ADDRESS_PARAMETER_ID:
999     dissect_add_ip_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
1000     break;
1001   case DEL_IP_ADDRESS_PARAMETER_ID:
1002     dissect_del_ip_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
1003     break;
1004   case ERROR_CAUSE_INDICATION_PARAMETER_ID:
1005     dissect_error_cause_indication_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
1006     break;
1007   case SET_PRIMARY_ADDRESS_PARAMETER_ID:
1008     dissect_set_primary_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
1009     break;    
1010   case SUCCESS_REPORT_PARAMETER_ID:
1011     dissect_success_report_parameter(parameter_tvb, parameter_tree, parameter_item);
1012     break; 
1013   case ADAP_LAYER_INDICATION_PARAMETER_ID:
1014     dissect_adap_indication_parameter(parameter_tvb, parameter_tree, parameter_item);
1015     break;    
1016   default:
1017     dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
1018     break;
1019   };
1020   if ((padding_length > 0) && (type != UNREC_PARA_PARAMETER_ID))
1021     proto_tree_add_text(parameter_tree, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length,
1022                         "Padding: %u byte%s",
1023                         padding_length, plurality(padding_length, "", "s"));
1024 }
1025
1026 /*
1027  * Code to handle error causes for ABORT and ERROR chunks
1028  */
1029 static void
1030 dissect_invalid_stream_identifier_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
1031 {
1032   guint16 stream_identifier;
1033
1034   stream_identifier   = tvb_get_ntohs(cause_tvb, CAUSE_STREAM_IDENTIFIER_OFFSET);
1035   proto_tree_add_uint(cause_tree, hf_sctp_cause_stream_identifier, 
1036                       cause_tvb, CAUSE_STREAM_IDENTIFIER_OFFSET, CAUSE_STREAM_IDENTIFIER_LENGTH,
1037                       stream_identifier);
1038   proto_tree_add_text(cause_tree, cause_tvb, CAUSE_RESERVED_OFFSET, CAUSE_RESERVED_LENGTH,
1039                       "Reserved (2 bytes)");
1040
1041   proto_item_set_text(cause_item, "Error cause reporting invalid stream identifier %u",
1042                       stream_identifier);
1043 }
1044
1045 static void
1046 dissect_missing_mandatory_parameters_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
1047 {
1048   guint32 number_of_missing_parameters, missing_parameter_number;
1049   guint16 parameter_type;
1050   guint   offset;
1051
1052   number_of_missing_parameters = tvb_get_ntohl(cause_tvb, CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET);
1053   proto_tree_add_uint(cause_tree, hf_sctp_cause_number_of_missing_parameters, 
1054                       cause_tvb, CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET, CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH,
1055                       number_of_missing_parameters);
1056   offset = CAUSE_FIRST_MISSING_PARAMETER_TYPE_OFFSET;
1057   for(missing_parameter_number = 1; missing_parameter_number <= number_of_missing_parameters; missing_parameter_number++) {
1058     parameter_type = tvb_get_ntohs(cause_tvb, offset);
1059     proto_tree_add_uint(cause_tree, hf_sctp_cause_missing_parameter_type,
1060                         cause_tvb, offset, CAUSE_MISSING_PARAMETER_TYPE_LENGTH,
1061                         parameter_type);
1062     offset +=  CAUSE_MISSING_PARAMETER_TYPE_LENGTH;
1063   };
1064
1065   proto_item_set_text(cause_item, "Error cause reporting %u missing mandatory parameter%s",
1066                       number_of_missing_parameters, plurality(number_of_missing_parameters, "", "s") );
1067 }
1068
1069 static void
1070 dissect_stale_cookie_error_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
1071 {
1072   guint32 measure_of_staleness;
1073
1074   measure_of_staleness =  tvb_get_ntohl(cause_tvb, CAUSE_MEASURE_OF_STALENESS_OFFSET);
1075   
1076   proto_tree_add_uint(cause_tree, hf_sctp_cause_measure_of_staleness, cause_tvb, 
1077                       CAUSE_MEASURE_OF_STALENESS_OFFSET, 
1078                       CAUSE_MEASURE_OF_STALENESS_LENGTH,
1079                       measure_of_staleness);
1080   
1081   proto_item_set_text(cause_item, "Error cause reporting a measure of staleness of %u usec",
1082                       measure_of_staleness);
1083 }
1084
1085 static void
1086 dissect_out_of_resource_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
1087 {
1088   proto_item_set_text(cause_item, "Error cause reporting lack of resources");
1089 }
1090
1091 static void
1092 dissect_unresolvable_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
1093 {
1094   guint16 code, length, parameter_length, parameter_type;
1095   tvbuff_t *parameter_tvb;
1096
1097   code   = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET);
1098   length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
1099   
1100   parameter_length = length - CAUSE_HEADER_LENGTH;
1101   parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, 
1102                                  parameter_length, parameter_length);
1103
1104   dissect_parameter(parameter_tvb, pinfo, cause_tree);
1105   parameter_type = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
1106  
1107   proto_item_set_text(cause_item, "Error cause reporting unresolvable address of type 0x%04x (%s)",
1108                       parameter_type, val_to_str(parameter_type, sctp_parameter_identifier_values, "unknown") );
1109 }
1110
1111 static void
1112 dissect_unrecognized_chunk_type_cause(tvbuff_t *cause_tvb,  packet_info *pinfo, 
1113                                       proto_tree *cause_tree, proto_item *cause_item)
1114 {
1115   guint16 length, chunk_length;
1116   guint8 unrecognized_type;
1117   tvbuff_t *unrecognized_chunk_tvb;
1118
1119   length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
1120   
1121   chunk_length = length - CAUSE_HEADER_LENGTH;
1122
1123   unrecognized_chunk_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, chunk_length, chunk_length);
1124   dissect_sctp_chunk(unrecognized_chunk_tvb, pinfo, cause_tree,cause_tree);
1125
1126   unrecognized_type   = tvb_get_guint8(unrecognized_chunk_tvb, CHUNK_TYPE_OFFSET);
1127  
1128   proto_item_set_text(cause_item, "Error cause reporting unrecognized chunk of type %u (%s)",
1129                       unrecognized_type,
1130                       val_to_str(unrecognized_type, sctp_chunk_type_values, "unknown"));
1131 }
1132
1133 static void
1134 dissect_invalid_mandatory_parameter_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
1135 {
1136   proto_item_set_text(cause_item, "Error cause reporting an invalid mandatory parameter");
1137 }
1138
1139 static void
1140 dissect_unrecognized_parameters_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
1141 {
1142   guint16 length, padding_length, cause_info_length;
1143   tvbuff_t *unrecognized_parameters_tvb;
1144
1145   length            = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
1146   padding_length    = nr_of_padding_bytes(length);
1147   cause_info_length = length - CAUSE_HEADER_LENGTH + padding_length;
1148
1149   unrecognized_parameters_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1150   dissect_tlv_parameter_list(unrecognized_parameters_tvb, pinfo, cause_tree);
1151  
1152   proto_item_set_text(cause_item, "Error cause reporting unrecognized parameters");
1153 }
1154
1155 static void
1156 dissect_no_user_data_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
1157 {
1158   guint32 tsn;
1159
1160   tsn = tvb_get_ntohl(cause_tvb, CAUSE_TSN_OFFSET);
1161   proto_tree_add_uint(cause_tree, hf_sctp_cause_tsn, cause_tvb, 
1162                       CAUSE_TSN_OFFSET, 
1163                       CAUSE_TSN_LENGTH,
1164                       tsn);
1165
1166   proto_item_set_text(cause_item, "Error cause reporting data chunk with TSN %u contains no data",
1167                       tsn);
1168 }
1169
1170 static void
1171 dissect_cookie_received_while_shutting_down_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
1172 {
1173   proto_item_set_text(cause_item, "Error cause reporting cookie reception while shutting down");
1174 }
1175
1176 static void
1177 dissect_delete_last_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
1178 {
1179   guint16 length, cause_info_length;
1180   tvbuff_t *parameter_tvb;
1181
1182   length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
1183   cause_info_length = length - CAUSE_HEADER_LENGTH;
1184   parameter_tvb    = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1185   dissect_parameter(parameter_tvb, pinfo, cause_tree); 
1186   proto_item_set_text(cause_item, "Delete last address cause");
1187 }
1188
1189 static void
1190 dissect_resource_outage_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
1191 {
1192   guint16 length, cause_info_length;
1193   tvbuff_t *parameter_tvb;
1194
1195   length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
1196   cause_info_length = length - CAUSE_HEADER_LENGTH;
1197   parameter_tvb    = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1198   dissect_parameter(parameter_tvb, pinfo, cause_tree); 
1199   proto_item_set_text(cause_item, "Operation refused due to resource shortage");
1200 }
1201
1202 static void
1203 dissect_delete_source_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
1204 {
1205   guint16 length, cause_info_length;
1206   tvbuff_t *parameter_tvb;
1207
1208   length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
1209   cause_info_length = length - CAUSE_HEADER_LENGTH;
1210   parameter_tvb    = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
1211   dissect_parameter(parameter_tvb, pinfo, cause_tree); 
1212   proto_item_set_text(cause_item, "Delete source address cause");
1213 }
1214
1215 static void
1216 dissect_unknown_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
1217 {
1218   guint16 code, length, cause_info_length;
1219
1220   code   = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET);
1221   length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
1222   
1223   cause_info_length = length - CAUSE_HEADER_LENGTH;
1224
1225   proto_tree_add_text(cause_tree, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length,
1226                       "Cause specific information (%u byte%s)",
1227                       cause_info_length, plurality(cause_info_length, "", "s"));
1228
1229   proto_item_set_text(cause_item, "Error cause with code %u and %u byte%s information",
1230                       code, cause_info_length, plurality(cause_info_length, "", "s"));
1231 }
1232
1233 static void
1234 dissect_error_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *chunk_tree)
1235 {
1236   guint16 code, length, padding_length, total_length;
1237   proto_item *cause_item;
1238   proto_tree *cause_tree;
1239
1240   code           = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET);
1241   length         = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
1242   padding_length = nr_of_padding_bytes(length);
1243   total_length   = length + padding_length;
1244
1245   cause_item = proto_tree_add_text(chunk_tree, cause_tvb,
1246                                    CAUSE_HEADER_OFFSET, total_length,
1247                                    "BAD ERROR CAUSE");
1248   cause_tree = proto_item_add_subtree(cause_item, ett_sctp_chunk_cause);
1249  
1250   proto_tree_add_uint(cause_tree, hf_sctp_cause_code, 
1251                       cause_tvb, CAUSE_CODE_OFFSET, CAUSE_CODE_LENGTH,
1252                       code);
1253   proto_tree_add_uint(cause_tree, hf_sctp_cause_length, 
1254                       cause_tvb, CAUSE_LENGTH_OFFSET, CAUSE_LENGTH_LENGTH,
1255                       length);
1256  
1257   switch(code) {
1258   case INVALID_STREAM_IDENTIFIER:
1259     dissect_invalid_stream_identifier_cause(cause_tvb, cause_tree, cause_item);
1260     break;
1261   case MISSING_MANDATORY_PARAMETERS:
1262     dissect_missing_mandatory_parameters_cause(cause_tvb, cause_tree, cause_item);
1263     break;
1264   case STALE_COOKIE_ERROR:
1265     dissect_stale_cookie_error_cause(cause_tvb, cause_tree, cause_item);
1266     break;
1267   case OUT_OF_RESOURCE:
1268     dissect_out_of_resource_cause(cause_tvb, cause_tree, cause_item);
1269     break;
1270   case UNRESOLVABLE_ADDRESS:
1271     dissect_unresolvable_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
1272     break;
1273   case UNRECOGNIZED_CHUNK_TYPE:
1274     dissect_unrecognized_chunk_type_cause(cause_tvb, pinfo, cause_tree, cause_item);
1275     break;
1276   case INVALID_MANDATORY_PARAMETER:
1277     dissect_invalid_mandatory_parameter_cause(cause_tvb, cause_tree, cause_item);
1278     break;
1279   case UNRECOGNIZED_PARAMETERS:
1280     dissect_unrecognized_parameters_cause(cause_tvb, pinfo, cause_tree, cause_item);
1281     break;
1282   case NO_USER_DATA:
1283     dissect_no_user_data_cause(cause_tvb, cause_tree, cause_item);
1284     break;
1285   case COOKIE_RECEIVED_WHILE_SHUTTING_DOWN:
1286     dissect_cookie_received_while_shutting_down_cause(cause_tvb, cause_tree, cause_item);
1287     break;
1288   case REQUEST_TO_DELETE_LAST_ADDRESS:
1289     dissect_delete_last_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
1290     break;
1291   case OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE:
1292     dissect_resource_outage_cause(cause_tvb, pinfo, cause_tree, cause_item);
1293     break;
1294   case REQUEST_TO_DELETE_SOURCE_ADDRESS:
1295     dissect_delete_source_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
1296     break;
1297   default:
1298     dissect_unknown_cause(cause_tvb, cause_tree, cause_item);
1299     break;
1300   };
1301   if ((padding_length > 0) && (code != UNRECOGNIZED_PARAMETERS))
1302     proto_tree_add_text(cause_tree, cause_tvb, CAUSE_HEADER_OFFSET + length, padding_length,
1303                         "Padding: %u byte%s",
1304                         padding_length, plurality(padding_length, "", "s"));
1305 }
1306
1307 /*
1308  * Code to actually dissect the packets 
1309 */
1310
1311 static gboolean
1312 dissect_payload(tvbuff_t *payload_tvb, packet_info *pinfo, proto_tree *tree,
1313                 proto_tree *chunk_tree, guint32 ppi, guint16 payload_length, guint16 padding_length)
1314 {
1315   /* do lookup with the subdissector table */
1316   if (dissector_try_port (sctp_ppi_dissector_table, ppi,  payload_tvb, pinfo, tree) ||
1317       dissector_try_port(sctp_port_dissector_table, pinfo->srcport,  payload_tvb, pinfo, tree) ||
1318       dissector_try_port(sctp_port_dissector_table, pinfo->destport, payload_tvb, pinfo, tree)){
1319     return TRUE;
1320   }
1321   else {
1322     if (check_col(pinfo->cinfo, COL_INFO))
1323       col_append_str(pinfo->cinfo, COL_INFO, "DATA ");
1324     proto_tree_add_text(chunk_tree, payload_tvb, 0, payload_length,
1325                         "Payload (%u byte%s)",
1326                         payload_length, plurality(payload_length, "", "s")); 
1327     if (padding_length > 0)
1328       proto_tree_add_text(chunk_tree, payload_tvb, payload_length, padding_length,
1329                           "Padding: %u byte%s",
1330                           padding_length, plurality(padding_length, "", "s"));
1331     return FALSE;
1332   }
1333 }
1334
1335 static gboolean
1336 dissect_data_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1337                    proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1338
1339   guint8  flags;
1340   guint16 length, total_payload_length, payload_length, padding_length, stream_id, stream_seq_number;
1341   guint32 tsn, payload_proto_id;
1342   proto_tree *flag_tree;
1343   tvbuff_t *payload_tvb;
1344    
1345   length            = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1346   payload_length       = length - DATA_CHUNK_HEADER_LENGTH;
1347   padding_length       = nr_of_padding_bytes(length);
1348   total_payload_length = payload_length + padding_length;
1349   payload_tvb          = tvb_new_subset(chunk_tvb, DATA_CHUNK_PAYLOAD_OFFSET,
1350                                           total_payload_length, total_payload_length);
1351   payload_proto_id     = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET);
1352
1353   if (chunk_tree) {
1354     flags             = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
1355      
1356     flag_tree = proto_item_add_subtree(flags_item, ett_sctp_data_chunk_flags);
1357     proto_tree_add_boolean(flag_tree, hf_sctp_data_chunk_e_bit, chunk_tvb,
1358                            CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
1359     proto_tree_add_boolean(flag_tree, hf_sctp_data_chunk_b_bit, chunk_tvb,
1360                            CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
1361     proto_tree_add_boolean(flag_tree, hf_sctp_data_chunk_u_bit, chunk_tvb,
1362                            CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
1363     
1364     tsn               = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_TSN_OFFSET);
1365     stream_id         = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET);
1366     stream_seq_number = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET);
1367          
1368     proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_tsn, 
1369                         chunk_tvb,
1370                         DATA_CHUNK_TSN_OFFSET, DATA_CHUNK_TSN_LENGTH,
1371                         tsn);
1372     proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_stream_id, 
1373                         chunk_tvb, 
1374                         DATA_CHUNK_STREAM_ID_OFFSET, DATA_CHUNK_STREAM_ID_LENGTH,
1375                         stream_id);
1376     proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_stream_seq_number, 
1377                         chunk_tvb, 
1378                         DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET, DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH,
1379                         stream_seq_number);
1380     proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_payload_proto_id, 
1381                         chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH,
1382                         payload_proto_id);
1383     proto_item_set_text(chunk_item, "DATA chunk with TSN %u (%u:%u) containing %u byte%s of payload",
1384                         tsn, stream_id, stream_seq_number, 
1385                         payload_length, plurality(payload_length, "", "s"));
1386   };   
1387   return dissect_payload(payload_tvb, pinfo, tree, chunk_tree, payload_proto_id, payload_length, padding_length); 
1388 }
1389
1390 static void
1391 dissect_init_chunk(tvbuff_t *chunk_tvb,  packet_info *pinfo, proto_tree *tree,
1392                    proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1393
1394   guint32 initiate_tag, adv_rec_window_credit, initial_tsn;
1395   guint16 number_of_inbound_streams, number_of_outbound_streams;
1396   guint8  type;
1397   tvbuff_t *parameter_list_tvb;
1398
1399   type                       = tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET);
1400   
1401   if (check_col(pinfo->cinfo, COL_INFO)) {
1402     if (type == SCTP_INIT_CHUNK_ID) {
1403       col_append_str(pinfo->cinfo, COL_INFO, "INIT ");
1404     } else {
1405       col_append_str(pinfo->cinfo, COL_INFO, "INIT_ACK ");
1406     };
1407   };
1408   
1409   if (chunk_tree) {
1410     initiate_tag               = tvb_get_ntohl(chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET);
1411     adv_rec_window_credit      = tvb_get_ntohl(chunk_tvb, INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET);
1412     number_of_inbound_streams  = tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET);
1413     number_of_outbound_streams = tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET);
1414     initial_tsn                = tvb_get_ntohl(chunk_tvb, INIT_CHUNK_INITIAL_TSN_OFFSET);
1415     
1416     /* handle fixed parameters */
1417     proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_initiate_tag, 
1418                         chunk_tvb,
1419                         INIT_CHUNK_INITIATE_TAG_OFFSET, INIT_CHUNK_INITIATE_TAG_LENGTH,
1420                         initiate_tag);
1421     proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_adv_rec_window_credit, 
1422                         chunk_tvb,
1423                         INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET, INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH,
1424                         adv_rec_window_credit);
1425     proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_number_of_outbound_streams, 
1426                         chunk_tvb,
1427                         INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH,
1428                         number_of_outbound_streams);
1429     proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_number_of_inbound_streams, 
1430                         chunk_tvb,
1431                         INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH,
1432                         number_of_inbound_streams);
1433     proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_initial_tsn, 
1434                         chunk_tvb,
1435                         INIT_CHUNK_INITIAL_TSN_OFFSET, INIT_CHUNK_INITIAL_TSN_LENGTH,
1436                         initial_tsn);
1437     
1438     /* handle variable paramters */
1439     parameter_list_tvb = tvb_new_subset(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET, -1, -1);
1440     dissect_tlv_parameter_list(parameter_list_tvb, pinfo, chunk_tree);
1441     
1442     proto_item_set_text(chunk_item, 
1443                         "%s chunk requesting for %u outbound stream%s and accepting up to %u inbound stream%s",
1444                         val_to_str(type, sctp_chunk_type_values, "unknown"),
1445                         number_of_outbound_streams, plurality(number_of_outbound_streams, "", "s"),
1446                         number_of_inbound_streams, plurality(number_of_inbound_streams, "", "s"));
1447   }
1448
1449
1450 static void
1451 dissect_init_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1452                        proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1453
1454   dissect_init_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1455
1456
1457 static void
1458 dissect_sack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1459                    proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1460
1461   guint32 cumulative_tsn_ack, adv_rec_window_credit, dup_tsn;
1462   guint16 number_of_gap_blocks, number_of_dup_tsns;
1463   guint16 gap_block_number, dup_tsn_number, start, end;
1464   gint gap_block_offset, dup_tsn_offset;
1465   proto_item *block_item;
1466   proto_tree *block_tree;
1467   
1468   if (check_col(pinfo->cinfo, COL_INFO))
1469     col_append_str(pinfo->cinfo, COL_INFO, "SACK ");
1470
1471   if (chunk_tree) {
1472     cumulative_tsn_ack    = tvb_get_ntohl(chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
1473     adv_rec_window_credit = tvb_get_ntohl(chunk_tvb, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET);
1474     number_of_gap_blocks  = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET);
1475     number_of_dup_tsns    = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET);
1476     
1477     proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_cumulative_tsn_ack, 
1478                         chunk_tvb,
1479                         SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET, SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH,
1480                         cumulative_tsn_ack);
1481     proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_adv_rec_window_credit, 
1482                         chunk_tvb,
1483                         SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH,
1484                         adv_rec_window_credit);
1485     proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_number_of_gap_blocks, 
1486                         chunk_tvb,
1487                         SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH,
1488                         number_of_gap_blocks);
1489     proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_number_of_dup_tsns, 
1490                         chunk_tvb,
1491                         SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET, SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH,
1492                         number_of_dup_tsns);
1493     
1494     /* handle the gap acknowledgement blocks */
1495     gap_block_offset = SACK_CHUNK_GAP_BLOCK_OFFSET;
1496     for(gap_block_number = 1; gap_block_number <= number_of_gap_blocks; gap_block_number++) {
1497       start = tvb_get_ntohs(chunk_tvb, gap_block_offset);
1498       end   = tvb_get_ntohs(chunk_tvb, gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH);
1499       block_item = proto_tree_add_text(chunk_tree, chunk_tvb,
1500                                        gap_block_offset, SACK_CHUNK_GAP_BLOCK_LENGTH,
1501                                        "Gap Acknowledgement for %u TSN%s",
1502                                        1 + end - start, plurality(1 + end - start, "", "s"));
1503       block_tree = proto_item_add_subtree(block_item, ett_sctp_sack_chunk_gap_block);
1504       proto_tree_add_uint(block_tree, hf_sctp_sack_chunk_gap_block_start, 
1505                           chunk_tvb,
1506                           gap_block_offset, SACK_CHUNK_GAP_BLOCK_START_LENGTH,
1507                           start);
1508       proto_tree_add_uint(block_tree, hf_sctp_sack_chunk_gap_block_end, 
1509                           chunk_tvb,
1510                           gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH,
1511                           SACK_CHUNK_GAP_BLOCK_END_LENGTH,
1512                           end);
1513       gap_block_offset += SACK_CHUNK_GAP_BLOCK_LENGTH;
1514     };
1515     
1516     /* handle the duplicate TSNs */
1517     dup_tsn_offset = SACK_CHUNK_GAP_BLOCK_OFFSET + number_of_gap_blocks * SACK_CHUNK_GAP_BLOCK_LENGTH;
1518     for(dup_tsn_number = 1; dup_tsn_number <= number_of_dup_tsns; dup_tsn_number++) {
1519       dup_tsn = tvb_get_ntohl(chunk_tvb, dup_tsn_offset);
1520       proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_duplicate_tsn, 
1521                           chunk_tvb,
1522                           dup_tsn, SACK_CHUNK_DUP_TSN_LENGTH,
1523                           dup_tsn);
1524       dup_tsn_offset += SACK_CHUNK_DUP_TSN_LENGTH;
1525     }
1526     
1527     proto_item_set_text(chunk_item, 
1528                         "SACK chunk acknowledging TSN %u and reporting %u gap%s and %u duplicate TSN%s",
1529                         cumulative_tsn_ack,
1530                         number_of_gap_blocks, plurality(number_of_gap_blocks, "", "s"),
1531                         number_of_dup_tsns, plurality(number_of_dup_tsns, "", "s"));
1532   } 
1533 }
1534
1535 static void
1536 dissect_heartbeat_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1537                         proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1538 {
1539   tvbuff_t   *parameter_tvb;
1540   guint chunk_length, info_length, padding_length, total_length;
1541     
1542   if (check_col(pinfo->cinfo, COL_INFO))
1543     col_append_str(pinfo->cinfo, COL_INFO, "HEARTBEAT ");
1544
1545   if (chunk_tree) {
1546     chunk_length   = tvb_get_ntohs(chunk_tvb,  CHUNK_LENGTH_OFFSET);
1547     info_length    = chunk_length - CHUNK_HEADER_LENGTH;
1548     padding_length = nr_of_padding_bytes(info_length);
1549     total_length   = info_length + padding_length;
1550     parameter_tvb  = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, total_length, total_length);
1551     
1552     dissect_parameter(parameter_tvb, pinfo, chunk_tree);
1553     
1554     proto_item_set_text(chunk_item, "HEARTBEAT chunk");
1555   }
1556 }
1557  
1558 static void
1559 dissect_heartbeat_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1560                             proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1561 {  
1562   tvbuff_t   *parameter_tvb;
1563   guint chunk_length, info_length, padding_length, total_length;
1564   
1565   if (check_col(pinfo->cinfo, COL_INFO))
1566     col_append_str(pinfo->cinfo, COL_INFO, "HEARTBEAT_ACK ");
1567
1568   if (chunk_tree) {
1569     chunk_length   = tvb_get_ntohs(chunk_tvb,  CHUNK_LENGTH_OFFSET);
1570     info_length    = chunk_length - CHUNK_HEADER_LENGTH;
1571     padding_length = nr_of_padding_bytes(info_length);
1572     total_length   = info_length + padding_length;
1573
1574     parameter_tvb  = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, total_length, total_length);
1575     
1576     dissect_parameter(parameter_tvb, pinfo, chunk_tree);
1577     
1578     proto_item_set_text(chunk_item, "HEARTBEAT ACK chunk");
1579   } 
1580 }
1581
1582 static void
1583 dissect_abort_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1584                     proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1585 {
1586   guint offset, number_of_causes;
1587   guint16 length, padding_length, total_length;
1588   tvbuff_t *cause_tvb;
1589   
1590   if (check_col(pinfo->cinfo, COL_INFO))
1591     col_append_str(pinfo->cinfo, COL_INFO, "ABORT ");
1592
1593   if (chunk_tree) {
1594     number_of_causes = 0;
1595     offset = ABORT_CHUNK_FIRST_ERROR_CAUSE_OFFSET;
1596     while(tvb_reported_length_remaining(chunk_tvb, offset)) {
1597         length         = tvb_get_ntohs(chunk_tvb, offset + CAUSE_LENGTH_OFFSET);
1598         padding_length = nr_of_padding_bytes(length);
1599         total_length   = length + padding_length;
1600         /* create a tvb for the chunk including the padding bytes */
1601         cause_tvb      = tvb_new_subset(chunk_tvb, offset, total_length, total_length);
1602         dissect_error_cause(cause_tvb, pinfo, chunk_tree); 
1603         /* get rid of the handled parameter */
1604         offset += total_length;
1605         number_of_causes++;
1606     };
1607     
1608     proto_item_set_text(chunk_item, "Abort chunk with %u cause%s",
1609                         number_of_causes, plurality(number_of_causes, "", "s"));
1610   } 
1611 }
1612
1613 static void
1614 dissect_shutdown_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1615                        proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1616
1617   guint32 cumulative_tsn_ack;
1618  
1619   if (check_col(pinfo->cinfo, COL_INFO))
1620     col_append_str(pinfo->cinfo, COL_INFO, "SHUTDOWN ");
1621
1622   if (chunk_tree) {
1623     cumulative_tsn_ack = tvb_get_ntohl(chunk_tvb, SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
1624     proto_tree_add_uint(chunk_tree, hf_sctp_shutdown_chunk_cumulative_tsn_ack, 
1625                         chunk_tvb,
1626                         SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET,
1627                         SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_LENGTH,
1628                         cumulative_tsn_ack);
1629     
1630     proto_item_set_text(chunk_item, "SHUTDOWN chunk acknowledging up to TSN %u",
1631                         cumulative_tsn_ack);
1632   } 
1633 }
1634
1635 static void
1636 dissect_shutdown_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1637                            proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1638
1639   if (check_col(pinfo->cinfo, COL_INFO))
1640     col_append_str(pinfo->cinfo, COL_INFO, "SHUTDOWN_ACK ");
1641
1642   if (chunk_tree) {
1643     proto_item_set_text(chunk_item, "SHUTDOWN ACK chunk");
1644   } 
1645 }
1646
1647 static void
1648 dissect_error_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1649                     proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1650
1651   guint offset, number_of_causes;
1652   guint16 length, padding_length, total_length;
1653   tvbuff_t *cause_tvb;
1654   
1655   if (check_col(pinfo->cinfo, COL_INFO))
1656     col_append_str(pinfo->cinfo, COL_INFO, "ERROR ");
1657
1658   if (chunk_tree) {
1659     number_of_causes = 0;
1660     offset = ERROR_CHUNK_FIRST_ERROR_CAUSE_OFFSET;
1661     do {
1662       length         = tvb_get_ntohs(chunk_tvb, offset + CAUSE_LENGTH_OFFSET);
1663       padding_length = nr_of_padding_bytes(length);
1664       total_length   = length + padding_length;
1665       /* create a tvb for the chunk including the padding bytes */
1666       cause_tvb      = tvb_new_subset(chunk_tvb, offset, total_length, total_length);
1667       dissect_error_cause(cause_tvb, pinfo, chunk_tree); 
1668       /* get rid of the handled parameter */
1669       offset += total_length;
1670       number_of_causes++;
1671     } while(tvb_reported_length_remaining(chunk_tvb, offset));
1672     
1673     proto_item_set_text(chunk_item, "Error chunk with %u cause%s",
1674                         number_of_causes, plurality(number_of_causes, "", "s"));
1675   } 
1676 }
1677
1678 static void
1679 dissect_cookie_echo_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1680                           proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1681
1682   guint length, cookie_length, padding_length;
1683
1684   length         = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1685   padding_length = nr_of_padding_bytes(length);
1686   cookie_length  = length - CHUNK_HEADER_LENGTH;
1687  
1688   if (check_col(pinfo->cinfo, COL_INFO))
1689     col_append_str(pinfo->cinfo, COL_INFO, "COOKIE_ECHO ");
1690
1691   if (chunk_tree) {  
1692     proto_tree_add_text(chunk_tree, chunk_tvb, COOKIE_ECHO_CHUNK_COOKIE_OFFSET, cookie_length,
1693                         "Cookie (%u byte%s)",
1694                         cookie_length, plurality(cookie_length, "", "s"));
1695     proto_item_set_text(chunk_item, "COOKIE ECHO chunk containing a cookie of %u byte%s",
1696                         cookie_length, plurality(cookie_length, "", "s"));
1697     
1698     if (padding_length > 0)
1699       proto_tree_add_text(chunk_tree, chunk_tvb, CHUNK_HEADER_OFFSET + length, padding_length,
1700                           "Padding: %u byte%s",
1701                           padding_length, plurality(padding_length, "", "s"));
1702   } 
1703 }
1704
1705 static void
1706 dissect_cookie_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1707                          proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1708 {  
1709   if (check_col(pinfo->cinfo, COL_INFO))
1710     col_append_str(pinfo->cinfo, COL_INFO, "COOKIE_ACK ");
1711
1712   if (chunk_tree) {
1713     proto_item_set_text(chunk_item, "COOKIE ACK chunk");
1714   } 
1715 }
1716
1717 static void
1718 dissect_ecne_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1719                    proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1720
1721   guint32 lowest_tsn;
1722  
1723   if (check_col(pinfo->cinfo, COL_INFO))
1724     col_append_str(pinfo->cinfo, COL_INFO, "ECNE ");
1725
1726   if (chunk_tree) {
1727     lowest_tsn = tvb_get_ntohl(chunk_tvb, ECNE_CHUNK_LOWEST_TSN_OFFSET);
1728     proto_tree_add_uint(chunk_tree, hf_sctp_ecne_chunk_lowest_tsn, 
1729                         chunk_tvb,
1730                         ECNE_CHUNK_LOWEST_TSN_OFFSET, ECNE_CHUNK_LOWEST_TSN_LENGTH,
1731                         lowest_tsn);
1732     
1733     proto_item_set_text(chunk_item, "ECNE chunk");
1734   } 
1735 }
1736
1737 static void
1738 dissect_cwr_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1739                   proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1740
1741   guint32 lowest_tsn;
1742   
1743   if (check_col(pinfo->cinfo, COL_INFO))
1744     col_append_str(pinfo->cinfo, COL_INFO, "CWR ");
1745
1746   if (chunk_tree) {
1747     lowest_tsn = tvb_get_ntohl(chunk_tvb, CWR_CHUNK_LOWEST_TSN_OFFSET);
1748     proto_tree_add_uint(chunk_tree, hf_sctp_cwr_chunk_lowest_tsn, 
1749                         chunk_tvb,
1750                         CWR_CHUNK_LOWEST_TSN_OFFSET, CWR_CHUNK_LOWEST_TSN_LENGTH,
1751                         lowest_tsn);
1752     
1753     proto_item_set_text(chunk_item, "CWR chunk");
1754   } 
1755 }
1756
1757 static void
1758 dissect_shutdown_complete_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1759                                 proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1760
1761   guint8  flags;
1762   guint16 length;
1763   proto_tree *flag_tree;
1764  
1765   if (check_col(pinfo->cinfo, COL_INFO))
1766     col_append_str(pinfo->cinfo, COL_INFO, "SHUTDOWN_COMPLETE ");
1767
1768   if (chunk_tree) {
1769     flags             = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
1770     length            = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1771     
1772     flag_tree = proto_item_add_subtree(flags_item, ett_sctp_data_chunk_flags);
1773     proto_tree_add_boolean(flag_tree, hf_sctp_shutdown_complete_chunk_t_bit, chunk_tvb,
1774                            CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
1775     
1776     proto_item_set_text(chunk_item, "SHUTDOWN COMPLETE chunk");
1777   } 
1778 }
1779
1780 #define FORWARD_TSN_CHUNK_TSN_OFFSET CHUNK_VALUE_OFFSET
1781 #define FORWARD_TSN_CHUNK_TSN_LENGTH 4
1782
1783 static void
1784 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)
1785
1786   guint32 tsn;
1787   
1788   if (check_col(pinfo->cinfo, COL_INFO))
1789     col_append_str(pinfo->cinfo, COL_INFO, "FORWARD TSN ");
1790
1791   if (chunk_tree) {
1792     tsn = tvb_get_ntohl(chunk_tvb, FORWARD_TSN_CHUNK_TSN_OFFSET);
1793     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);
1794     proto_item_set_text(chunk_item, "FORWARD TSN chunk (new cumulative TSN %u)", tsn);
1795   } 
1796 }
1797
1798 #define SERIAL_NUMBER_LENGTH    4
1799 #define CORRELATION_ID_LENGTH   4
1800 #define ASCONF_RESERVED_LENGTH  3
1801 #define ASCONF_ADDR_TYPE_LENGTH 1
1802 #define ASCONF_ADDR_LENGTH      16
1803 #define SERIAL_NUMBER_OFFSET    PARAMETER_VALUE_OFFSET
1804
1805 #define IP_V4_ADDRESS_TYPE      5
1806 #define IP_V6_ADDRESS_TYPE      6
1807
1808 static const value_string sctp_address_type_values[] = {
1809   { IP_V4_ADDRESS_TYPE,         "IP V4 address" },
1810   { IP_V6_ADDRESS_TYPE,         "IP V6 address" },
1811   { 0,                           NULL } };
1812
1813 static void
1814 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)
1815
1816   guint32 serial_number, correlation_id, ipv4_address;
1817   guint offset, length, padding_length, total_length;
1818   guint8 addr_type;
1819   tvbuff_t *parameter_tvb;
1820
1821   if (check_col(pinfo->cinfo, COL_INFO))
1822     col_append_str(pinfo->cinfo, COL_INFO, "ASCONF ");
1823
1824   if (chunk_tree) {
1825     offset = SERIAL_NUMBER_OFFSET;
1826     serial_number    = tvb_get_ntohl(chunk_tvb, offset);
1827     proto_tree_add_uint(chunk_tree, hf_sctp_asconf_serial, chunk_tvb, offset, SERIAL_NUMBER_LENGTH, serial_number);
1828     offset          += SERIAL_NUMBER_LENGTH;
1829     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));
1830     offset          += ASCONF_RESERVED_LENGTH;
1831     addr_type = tvb_get_guint8(chunk_tvb, offset);
1832     proto_tree_add_uint(chunk_tree, hf_sctp_asconf_addr_type, chunk_tvb, offset, ASCONF_ADDR_TYPE_LENGTH, addr_type);
1833     offset          += ASCONF_ADDR_TYPE_LENGTH;
1834     switch (addr_type) {
1835       case IP_V4_ADDRESS_TYPE:
1836         tvb_memcpy(chunk_tvb, (guint8 *)&ipv4_address, offset, IPV4_ADDRESS_LENGTH); 
1837         proto_tree_add_ipv4(chunk_tree, hf_sctp_asconf_ipv4_address, chunk_tvb, offset, IPV4_ADDRESS_LENGTH, ipv4_address);
1838         proto_tree_add_bytes(chunk_tree, hf_sctp_asconf_addr, chunk_tvb, offset + IPV4_ADDRESS_LENGTH, ASCONF_ADDR_LENGTH - IPV4_ADDRESS_LENGTH,
1839                              tvb_get_ptr(chunk_tvb, offset + IPV4_ADDRESS_LENGTH, ASCONF_ADDR_LENGTH - IPV4_ADDRESS_LENGTH));
1840         break;
1841       case IP_V6_ADDRESS_TYPE:
1842           proto_tree_add_ipv6(chunk_tree, hf_sctp_asconf_ipv6_address, chunk_tvb, offset, IPV6_ADDRESS_LENGTH,
1843                                           tvb_get_ptr(chunk_tvb, offset, IPV6_ADDRESS_LENGTH));
1844         break;
1845       default:
1846         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));
1847         break;
1848     }
1849     offset          += ASCONF_ADDR_LENGTH;
1850     proto_item_set_text(chunk_item, "ASCONF chunk");
1851     
1852     while(tvb_reported_length_remaining(chunk_tvb, offset)) {
1853       correlation_id = tvb_get_ntohl(chunk_tvb, offset);
1854       proto_tree_add_uint(chunk_tree, hf_sctp_asconf_correlation_id, chunk_tvb, offset, CORRELATION_ID_LENGTH, correlation_id);
1855       offset        += CORRELATION_ID_LENGTH;
1856       length         = tvb_get_ntohs(chunk_tvb, offset + PARAMETER_LENGTH_OFFSET);
1857       padding_length = nr_of_padding_bytes(length);
1858       total_length   = length + padding_length;
1859       /* create a tvb for the chunk including the padding bytes */
1860       parameter_tvb  = tvb_new_subset(chunk_tvb, offset, total_length, total_length);
1861       dissect_parameter(parameter_tvb, pinfo, chunk_tree); 
1862       /* get rid of the handled parameter */
1863       offset        += total_length;
1864     }
1865   } 
1866 }
1867
1868 static void
1869 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)
1870
1871   guint32 serial_number, correlation_id;
1872   guint offset, length, padding_length, total_length;
1873   tvbuff_t *parameter_tvb;
1874
1875   if (check_col(pinfo->cinfo, COL_INFO))
1876     col_append_str(pinfo->cinfo, COL_INFO, "ASCONF-ACK ");
1877
1878   if (chunk_tree) {
1879     serial_number = tvb_get_ntohl(chunk_tvb, SERIAL_NUMBER_OFFSET);
1880     proto_tree_add_uint(chunk_tree, hf_sctp_asconf_ack_serial, chunk_tvb, SERIAL_NUMBER_OFFSET, SERIAL_NUMBER_LENGTH, serial_number);
1881     proto_item_set_text(chunk_item, "ASCONF-ACK chunk");
1882     
1883     offset = SERIAL_NUMBER_OFFSET + SERIAL_NUMBER_LENGTH;
1884     while(tvb_reported_length_remaining(chunk_tvb, offset)) {
1885       correlation_id = tvb_get_ntohl(chunk_tvb, offset);
1886       proto_tree_add_uint(chunk_tree, hf_sctp_asconf_ack_correlation_id, chunk_tvb, offset, CORRELATION_ID_LENGTH, correlation_id);
1887       offset        += CORRELATION_ID_LENGTH;
1888       length         = tvb_get_ntohs(chunk_tvb, offset + PARAMETER_LENGTH_OFFSET);
1889       padding_length = nr_of_padding_bytes(length);
1890       total_length   = length + padding_length;
1891       /* create a tvb for the chunk including the padding bytes */
1892       parameter_tvb  = tvb_new_subset(chunk_tvb, offset, total_length, total_length);
1893       dissect_parameter(parameter_tvb, pinfo, chunk_tree); 
1894       /* get rid of the handled parameter */
1895       offset        += total_length;
1896     }
1897   } 
1898 }
1899
1900 static void
1901 dissect_unknown_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1902                       proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1903
1904   guint length, chunk_value_length, padding_length;
1905   guint8 type;
1906   
1907   if (check_col(pinfo->cinfo, COL_INFO))
1908     col_append_str(pinfo->cinfo, COL_INFO, "UNKNOWN ");
1909
1910   if (chunk_tree) {
1911     length         = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1912     padding_length = nr_of_padding_bytes(length);
1913     type           = tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET);
1914     
1915     chunk_value_length = length - CHUNK_HEADER_LENGTH;
1916     
1917     proto_tree_add_text(chunk_tree, chunk_tvb, CHUNK_VALUE_OFFSET, chunk_value_length,
1918                         "Chunk value (%u byte%s)",
1919                         chunk_value_length, plurality(chunk_value_length, "", "s"));
1920     
1921     if (padding_length > 0)
1922       proto_tree_add_text(chunk_tree, chunk_tvb, CHUNK_HEADER_OFFSET + length, padding_length,
1923                           "Padding: %u byte%s",
1924                           padding_length, plurality(padding_length, "", "s"));
1925     
1926     proto_item_set_text(chunk_item, "Chunk of type %u and %u byte%s value",
1927                         type, chunk_value_length, plurality(chunk_value_length, "", "s"));
1928   }
1929
1930
1931
1932 static gboolean
1933 dissect_sctp_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *sctp_tree)
1934 {  
1935   guint8 type, flags;
1936   guint16 length;
1937   gboolean result;
1938   proto_item *flags_item;
1939   proto_item *chunk_item;
1940   proto_tree *chunk_tree;
1941
1942   result = FALSE;
1943   
1944   /* first extract the chunk header */
1945   type   = tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET);
1946   flags  = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
1947   length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1948  
1949   if (tree) {
1950     /* create proto_tree stuff */
1951     chunk_item   = proto_tree_add_text(sctp_tree, chunk_tvb, CHUNK_HEADER_OFFSET, -1, "Incomplete chunk");
1952     chunk_tree   = proto_item_add_subtree(chunk_item, ett_sctp_chunk);
1953     
1954     /* then insert the chunk header components into the protocol tree */
1955     proto_tree_add_uint(chunk_tree, hf_sctp_chunk_type, chunk_tvb, CHUNK_TYPE_OFFSET, CHUNK_TYPE_LENGTH, type);
1956     flags_item = proto_tree_add_uint(chunk_tree, hf_sctp_chunk_flags, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
1957     proto_tree_add_uint(chunk_tree, hf_sctp_chunk_length, chunk_tvb, CHUNK_LENGTH_OFFSET, CHUNK_LENGTH_LENGTH, length);
1958   } else {
1959     chunk_tree = NULL;
1960     chunk_item = NULL;
1961     flags_item = NULL;
1962   };
1963   
1964   /* now dissect the chunk value */
1965
1966   switch(type) {
1967   case SCTP_DATA_CHUNK_ID:
1968     result = dissect_data_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1969     break;
1970   case SCTP_INIT_CHUNK_ID:
1971     dissect_init_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1972     break;
1973   case SCTP_INIT_ACK_CHUNK_ID:
1974     dissect_init_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1975     break;
1976   case SCTP_SACK_CHUNK_ID:
1977     dissect_sack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1978     break; 
1979   case SCTP_HEARTBEAT_CHUNK_ID:
1980     dissect_heartbeat_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1981     break;
1982   case SCTP_HEARTBEAT_ACK_CHUNK_ID:
1983     dissect_heartbeat_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1984     break;
1985   case SCTP_ABORT_CHUNK_ID:
1986     dissect_abort_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1987     break;
1988   case SCTP_SHUTDOWN_CHUNK_ID:
1989     dissect_shutdown_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1990     break;
1991   case SCTP_SHUTDOWN_ACK_CHUNK_ID:
1992     dissect_shutdown_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1993     break;
1994   case SCTP_ERROR_CHUNK_ID:
1995     dissect_error_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1996     break;
1997   case SCTP_COOKIE_ECHO_CHUNK_ID:
1998     dissect_cookie_echo_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1999     break;
2000   case SCTP_COOKIE_ACK_CHUNK_ID:
2001     dissect_cookie_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
2002     break;
2003   case SCTP_ECNE_CHUNK_ID:
2004     dissect_ecne_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
2005     break;
2006   case SCTP_CWR_CHUNK_ID:
2007     dissect_cwr_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
2008     break;
2009   case SCTP_SHUTDOWN_COMPLETE_CHUNK_ID:
2010     dissect_shutdown_complete_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
2011     break;
2012   case SCTP_FORWARD_TSN_CHUNK_ID:
2013     dissect_forward_tsn_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
2014     break;
2015   case SCTP_ASCONF_ACK_CHUNK_ID:
2016     dissect_asconf_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
2017     break;
2018   case SCTP_ASCONF_CHUNK_ID:
2019     dissect_asconf_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
2020     break;
2021   default:
2022     dissect_unknown_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
2023     break;
2024   };
2025   return result;
2026 }
2027
2028 static void
2029 dissect_sctp_chunks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *sctp_item, proto_tree *sctp_tree)
2030
2031   tvbuff_t *chunk_tvb;
2032   guint16 length, padding_length, total_length;
2033   gint last_offset, offset;
2034   gboolean sctp_item_length_set;
2035
2036   /* the common header of the datagram is already handled */
2037   last_offset = 0;
2038   offset = COMMON_HEADER_LENGTH;
2039   sctp_item_length_set = FALSE;
2040
2041   while(tvb_reported_length_remaining(tvb, offset) > 0) {
2042     /* extract the chunk length and compute number of padding bytes */
2043     length         = tvb_get_ntohs(tvb, offset + CHUNK_LENGTH_OFFSET);
2044     padding_length = nr_of_padding_bytes(length);
2045     total_length   = length + padding_length;
2046     /* create a tvb for the chunk including the padding bytes */
2047     chunk_tvb    = tvb_new_subset(tvb, offset, total_length, total_length);
2048     /* call dissect_sctp_chunk for a actual work */
2049     if (dissect_sctp_chunk(chunk_tvb, pinfo, tree, sctp_tree) && (tree)) {
2050       proto_item_set_len(sctp_item, offset - last_offset + DATA_CHUNK_HEADER_LENGTH);
2051       sctp_item_length_set = TRUE;
2052       offset += total_length;
2053       last_offset = offset;
2054       if (tvb_reported_length_remaining(tvb, offset) > 0) {
2055         sctp_item = proto_tree_add_item(tree, proto_sctp, tvb, offset, -1, FALSE);
2056         sctp_tree = proto_item_add_subtree(sctp_item, ett_sctp);
2057         sctp_item_length_set = FALSE;
2058       }
2059     } else {
2060     /* get rid of the dissected chunk */
2061     offset += total_length;
2062     }
2063   };
2064   if (!sctp_item_length_set && (tree)) { 
2065     proto_item_set_len(sctp_item, offset - last_offset);
2066   };
2067 }
2068
2069 /* dissect_sctp handles the common header of a SCTP datagram.
2070  * For the handling of the chunks dissect_sctp_chunks is called.
2071  */
2072
2073 static void
2074 dissect_sctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2075 {
2076   guint16 source_port, destination_port;
2077   guint32 verification_tag, checksum, calculated_crc32c, calculated_adler32;
2078   guint length;
2079   gboolean crc32c_correct, adler32_correct;
2080   proto_item *sctp_item;
2081   proto_tree *sctp_tree;
2082
2083   /* Extract the common header */
2084   source_port      = tvb_get_ntohs(tvb, SOURCE_PORT_OFFSET);
2085   destination_port = tvb_get_ntohs(tvb, DESTINATION_PORT_OFFSET);
2086   verification_tag = tvb_get_ntohl(tvb, VERIFICATION_TAG_OFFSET);
2087   checksum         = tvb_get_ntohl(tvb, CHECKSUM_OFFSET);
2088
2089   /* update pi structure */
2090   pinfo->ptype    = PT_SCTP;
2091   pinfo->srcport  = source_port;
2092   pinfo->destport = destination_port;
2093
2094   /* make entry in the Protocol column on summary display */
2095   if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
2096     col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCTP");
2097
2098   /* Clear entries in Info column on summary display */
2099   if (check_col(pinfo->cinfo, COL_INFO))
2100     col_add_str(pinfo->cinfo, COL_INFO, "");
2101   
2102   /* In the interest of speed, if "tree" is NULL, don't do any work not
2103      necessary to generate protocol tree items. */
2104   if (tree) {
2105     /* create the sctp protocol tree */
2106     sctp_item = proto_tree_add_item(tree, proto_sctp, tvb, 0, -1, FALSE);
2107     sctp_tree = proto_item_add_subtree(sctp_item, ett_sctp);
2108     
2109     /* add the components of the common header to the protocol tree */
2110     proto_tree_add_uint(sctp_tree, hf_sctp_source_port, tvb, SOURCE_PORT_OFFSET, SOURCE_PORT_LENGTH, source_port);
2111     proto_tree_add_uint(sctp_tree, hf_sctp_destination_port, tvb, DESTINATION_PORT_OFFSET, DESTINATION_PORT_LENGTH, destination_port);
2112     proto_tree_add_uint(sctp_tree, hf_sctp_verification_tag, tvb, VERIFICATION_TAG_OFFSET, VERIFICATION_TAG_LENGTH, verification_tag);
2113     proto_tree_add_uint_hidden(sctp_tree, hf_sctp_port, tvb, SOURCE_PORT_OFFSET, SOURCE_PORT_LENGTH, source_port);
2114     proto_tree_add_uint_hidden(sctp_tree, hf_sctp_port, tvb, DESTINATION_PORT_OFFSET, DESTINATION_PORT_LENGTH, destination_port);
2115
2116     length = tvb_length(tvb);
2117     switch(sctp_checksum) {
2118     case SCTP_CHECKSUM_NONE:
2119       proto_tree_add_uint_format(sctp_tree, hf_sctp_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, checksum, "Checksum: 0x%08x (not verified)", checksum);
2120       break;
2121     case SCTP_CHECKSUM_ADLER32:
2122       calculated_adler32 = sctp_adler32(tvb_get_ptr(tvb, 0, length), length);
2123       adler32_correct    = (checksum == calculated_adler32);
2124       if (adler32_correct)
2125         proto_tree_add_uint_format(sctp_tree, hf_sctp_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2126                                    checksum, "Checksum: 0x%08x (correct Adler32)", checksum);
2127       else
2128         proto_tree_add_uint_format(sctp_tree, hf_sctp_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, 
2129                                    checksum, "Checksum: 0x%08x (incorrect Adler32, should be 0x%08x)", checksum, calculated_adler32);    
2130       proto_tree_add_boolean_hidden(sctp_tree, hf_sctp_checksum_bad, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, !(adler32_correct));
2131       break;
2132     case SCTP_CHECKSUM_CRC32C:
2133       calculated_crc32c = sctp_crc32c(tvb_get_ptr(tvb, 0, length), length);
2134       crc32c_correct    = (checksum == calculated_crc32c);
2135       if (crc32c_correct)
2136         proto_tree_add_uint_format(sctp_tree, hf_sctp_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2137                                    checksum, "Checksum: 0x%08x (correct CRC32C)", 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 CRC32C, should be 0x%08x)", checksum, calculated_crc32c);    
2141       proto_tree_add_boolean_hidden(sctp_tree, hf_sctp_checksum_bad, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, !(crc32c_correct));
2142       break;
2143     case SCTP_CHECKSUM_AUTOMATIC:
2144       calculated_adler32 = sctp_adler32(tvb_get_ptr(tvb, 0, length), length);
2145       adler32_correct    = (checksum == calculated_adler32);
2146       calculated_crc32c  = sctp_crc32c(tvb_get_ptr(tvb, 0, length), length);
2147       crc32c_correct     = (checksum == calculated_crc32c);
2148       if ((adler32_correct) && !(crc32c_correct))
2149         proto_tree_add_uint_format(sctp_tree, hf_sctp_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2150                                    checksum, "Checksum: 0x%08x (correct Adler32)", checksum);
2151       else if (!(adler32_correct) && (crc32c_correct))
2152         proto_tree_add_uint_format(sctp_tree, hf_sctp_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2153                                    checksum, "Checksum: 0x%08x (correct CRC32C)", checksum);
2154       else if ((adler32_correct) && (crc32c_correct))
2155         proto_tree_add_uint_format(sctp_tree, hf_sctp_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
2156                                    checksum, "Checksum: 0x%08x (correct Adler32 and CRC32C)", checksum);
2157       else
2158         proto_tree_add_uint_format(sctp_tree, hf_sctp_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, 
2159                                    checksum, "Checksum: 0x%08x (incorrect, should be 0x%08x (Adler32) or 0x%08x (CRC32C))",
2160                                    checksum, calculated_adler32, calculated_crc32c);
2161       proto_tree_add_boolean_hidden(sctp_tree, hf_sctp_checksum_bad, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, !(crc32c_correct || adler32_correct));
2162       break;
2163     }
2164   } else {
2165     sctp_tree = NULL;
2166     sctp_item = NULL;
2167   };
2168   /* add all chunks of the sctp datagram to the protocol tree */
2169   dissect_sctp_chunks(tvb, pinfo, tree, sctp_item, sctp_tree);
2170 }
2171
2172 /* Register the protocol with Ethereal */
2173 void
2174 proto_register_sctp(void)
2175 {                 
2176
2177   /* Setup list of header fields */
2178   static hf_register_info hf[] = {
2179     { &hf_sctp_source_port,
2180       { "Source port", "sctp.srcport",
2181               FT_UINT16, BASE_DEC, NULL, 0x0,          
2182               "", HFILL }
2183     },
2184     { &hf_sctp_destination_port,
2185       { "Destination port", "sctp.dstport",
2186                FT_UINT16, BASE_DEC, NULL, 0x0,          
2187                "", HFILL }
2188     }, 
2189     { &hf_sctp_port,
2190       { "Port", "sctp.port",
2191                FT_UINT16, BASE_DEC, NULL, 0x0,          
2192                "", HFILL }
2193     }, 
2194     { &hf_sctp_verification_tag,
2195       { "Verification tag", "sctp.verfication_tag",
2196                FT_UINT32, BASE_HEX, NULL, 0x0,          
2197                "", HFILL }
2198     },
2199     { &hf_sctp_checksum,
2200       { "Checksum", "sctp.checksum",
2201               FT_UINT32, BASE_HEX, NULL, 0x0,          
2202               "", HFILL }
2203     },
2204     { &hf_sctp_checksum_bad,
2205       { "Bad checksum", "sctp.checksum_bad",
2206               FT_BOOLEAN, BASE_NONE, NULL, 0x0,          
2207               "", HFILL }
2208     },
2209     { &hf_sctp_chunk_type,
2210       { "Identifier", "sctp.chunk_type",
2211         FT_UINT8, BASE_DEC, VALS(sctp_chunk_type_values), 0x0,          
2212         "", HFILL }
2213     },
2214     { &hf_sctp_chunk_flags,
2215       { "Flags", "sctp.chunk_flags",
2216         FT_UINT8, BASE_BIN, NULL, 0x0,          
2217         "", HFILL }
2218     },
2219     { &hf_sctp_chunk_length,
2220       { "Length", "sctp.chunk_length",
2221         FT_UINT16, BASE_DEC, NULL, 0x0,          
2222         "", HFILL }
2223     },
2224     { &hf_sctp_init_chunk_initiate_tag,
2225       { "Initiate tag", "sctp.init.chunk.initiate.tag",
2226         FT_UINT32, BASE_HEX, NULL, 0x0,          
2227         "", HFILL }
2228     },
2229     { &hf_sctp_init_chunk_adv_rec_window_credit,
2230       { "Advertised reciever window credit (a_rwnd)", "sctp.init.chunk.credit",
2231         FT_UINT32, BASE_DEC, NULL, 0x0,          
2232         "", HFILL }
2233     },
2234     { &hf_sctp_init_chunk_number_of_outbound_streams,
2235       { "Number of outbound streams", "sctp.init.chunk.nr.out.streams",
2236         FT_UINT16, BASE_DEC, NULL, 0x0,          
2237         "", HFILL }
2238     },
2239     { &hf_sctp_init_chunk_number_of_inbound_streams,
2240       { "Number of inbound streams", "sctp.init.chunk.nr.in.streams",
2241         FT_UINT16, BASE_DEC, NULL, 0x0,          
2242         "", HFILL }
2243     },
2244     {&hf_sctp_init_chunk_initial_tsn,
2245       { "Initial TSN", "sctp.init.chunk.initial.tsn",
2246         FT_UINT32, BASE_DEC, NULL, 0x0,          
2247         "", HFILL }
2248     }, 
2249     {&hf_sctp_cumulative_tsn_ack,
2250      { "Cumulative TSN Ack", "sctp.cumulative.tsn.ack",
2251         FT_UINT32, BASE_DEC, NULL, 0x0,          
2252         "", HFILL }
2253     },
2254     {&hf_sctp_data_chunk_tsn,
2255      { "TSN", "sctp.tsn",
2256        FT_UINT32, BASE_DEC, NULL, 0x0,          
2257         "", HFILL }
2258     },
2259     {&hf_sctp_data_chunk_stream_id,
2260      { "Stream Identifier", "sctp.stream_id",
2261         FT_UINT16, BASE_HEX, NULL, 0x0,          
2262         "", HFILL }
2263     },
2264     {&hf_sctp_data_chunk_stream_seq_number,
2265      { "Stream sequence number", "sctp.stream_seq_number",
2266        FT_UINT16, BASE_DEC, NULL, 0x0,          
2267        "", HFILL }
2268     },
2269     {&hf_sctp_data_chunk_payload_proto_id,
2270      { "Payload protocol identifier", "sctp.payload_proto_id",
2271         FT_UINT32, BASE_DEC, VALS(sctp_payload_proto_id_values), 0x0,          
2272         "", HFILL }
2273     },
2274     {&hf_sctp_data_chunk_e_bit,
2275      { "E-Bit", "sctp.data.e_bit",
2276        FT_BOOLEAN, 8, TFS(&sctp_data_chunk_e_bit_value), SCTP_DATA_CHUNK_E_BIT,          
2277        "", HFILL }
2278     },
2279     {&hf_sctp_data_chunk_b_bit,
2280      { "B-Bit", "sctp.data.b_bit",
2281        FT_BOOLEAN, 8, TFS(&sctp_data_chunk_b_bit_value), SCTP_DATA_CHUNK_B_BIT,          
2282        "", HFILL }
2283     },
2284     {&hf_sctp_data_chunk_u_bit,
2285      { "U-Bit", "sctp.data.u.bit",
2286        FT_BOOLEAN, 8, TFS(&sctp_data_chunk_u_bit_value), SCTP_DATA_CHUNK_U_BIT,          
2287        "", HFILL }
2288     },
2289     {&hf_sctp_sack_chunk_cumulative_tsn_ack,
2290      { "Cumulative TSN ACK", "sctp.sack.cumulative_tsn_ack",
2291        FT_UINT32, BASE_DEC, NULL, 0x0,          
2292        "", HFILL }
2293     }, 
2294     {&hf_sctp_sack_chunk_adv_rec_window_credit,
2295      { "Advertised receiver window credit (a_rwnd)", "sctp.sack.a_rwnd",
2296        FT_UINT32, BASE_DEC, NULL, 0x0,          
2297        "", HFILL }
2298     },
2299     {&hf_sctp_sack_chunk_number_of_gap_blocks,
2300      { "Number of gap acknowldgement blocks ", "sctp.sack.number_of_gap_blocks",
2301        FT_UINT16, BASE_DEC, NULL, 0x0,          
2302        "", HFILL }
2303     }, 
2304     {&hf_sctp_sack_chunk_number_of_dup_tsns,
2305      { "Number of duplicated TSNs", "sctp.sack.number_of_duplicated_tsns",
2306        FT_UINT16, BASE_DEC, NULL, 0x0,          
2307        "", HFILL }
2308     },
2309     {&hf_sctp_sack_chunk_gap_block_start,
2310      { "Start", "sctp.sack.gap_block_start",
2311        FT_UINT16, BASE_DEC, NULL, 0x0,          
2312        "", HFILL }
2313     },
2314     {&hf_sctp_sack_chunk_gap_block_end,
2315      { "End", "sctp.sack.gap_block_end",
2316        FT_UINT16, BASE_DEC, NULL, 0x0,          
2317        "", HFILL }
2318     },
2319     {&hf_sctp_sack_chunk_duplicate_tsn,
2320      { "Duplicate TSN", "sctp.sack.duplicate.tsn",
2321        FT_UINT16, BASE_DEC, NULL, 0x0,          
2322        "", HFILL }
2323     },  
2324     {&hf_sctp_shutdown_chunk_cumulative_tsn_ack,
2325      { "Cumulative TSN Ack", "sctp.shutdown.cumulative_tsn_ack",
2326         FT_UINT32, BASE_DEC, NULL, 0x0,          
2327         "", HFILL }
2328     },
2329     {&hf_sctp_ecne_chunk_lowest_tsn,
2330      { "Lowest TSN", "sctp.ecne.lowest_tsn",
2331        FT_UINT32, BASE_DEC, NULL, 0x0,          
2332        "", HFILL }
2333     }, 
2334     {&hf_sctp_cwr_chunk_lowest_tsn,
2335      { "Lowest TSN", "sctp.cwr.lowest_tsn",
2336        FT_UINT32, BASE_DEC, NULL, 0x0,          
2337        "", HFILL }
2338     }, 
2339     {&hf_sctp_shutdown_complete_chunk_t_bit,
2340      { "E-Bit", "sctp.shutdown_complete.t_bit",
2341        FT_BOOLEAN, 8, TFS(&sctp_shutdown_complete_chunk_t_bit_value), SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT,
2342        "", HFILL }
2343     },
2344     {&hf_sctp_forward_tsn_chunk_tsn,
2345      { "New cumulative TSN", "sctp.forward_tsn.tsn",
2346        FT_UINT32, BASE_DEC, NULL, 0x0,          
2347        "", HFILL }
2348     }, 
2349     {&hf_sctp_chunk_parameter_type,
2350      { "Parameter type", "sctp.parameter.type",
2351        FT_UINT16, BASE_HEX, VALS(sctp_parameter_identifier_values), 0x0,
2352        "", HFILL }
2353     },
2354     {&hf_sctp_chunk_parameter_length,
2355      { "Parameter length", "sctp.parameter.length",
2356        FT_UINT16, BASE_DEC, NULL, 0x0,          
2357        "", HFILL }
2358     },
2359     {&hf_sctp_parameter_ipv4_address,
2360      { "IP Version 4 address", "sctp.parameter.ipv4_address",
2361        FT_IPv4, BASE_NONE, NULL, 0x0,
2362        "", HFILL }
2363     },
2364     {&hf_sctp_parameter_ipv6_address,
2365      { "IP Version 6 address", "sctp.parameter.ipv6_address",
2366        FT_IPv6, BASE_NONE, NULL, 0x0,
2367        "", HFILL }
2368     },
2369     {&hf_sctp_parameter_cookie_preservative_increment,
2370      { "Suggested Cookie life-span increment (msec)", "sctp.parameter.cookie_preservative_incr",
2371        FT_UINT32, BASE_DEC, NULL, 0x0,          
2372        "", HFILL }
2373     },
2374     {&hf_sctp_parameter_hostname_hostname,
2375      { "Hostname", "sctp.parameter.hostname.hostname",
2376        FT_STRING, BASE_NONE, NULL, 0x0,          
2377        "", HFILL }
2378     }, 
2379     {&hf_sctp_supported_address_types_parameter,
2380      { "Supported address type", "sctp.parameter.supported_addres_type",
2381        FT_UINT16, BASE_DEC, NULL, 0x0,          
2382        "", HFILL }
2383     }, 
2384     {&hf_sctp_ustreams_start,
2385      { "Start", "sctp.unreliable_streams.start",
2386        FT_UINT16, BASE_DEC, NULL, 0x0,          
2387        "", HFILL }
2388     }, 
2389     {&hf_sctp_ustreams_end,
2390      { "End", "sctp.unreliable_streams.end",
2391        FT_UINT16, BASE_DEC, NULL, 0x0,          
2392        "", HFILL }
2393     },     
2394     {&hf_sctp_asconf_serial,
2395      { "Serial Number", "sctp.asconf.serial_number",
2396        FT_UINT32, BASE_HEX, NULL, 0x0,          
2397        "", HFILL }
2398     }, 
2399     {&hf_sctp_asconf_correlation_id,
2400      { "Correlation_id", "sctp.asconf.correlation_id",
2401        FT_UINT32, BASE_HEX, NULL, 0x0,          
2402        "", HFILL }
2403     }, 
2404     {&hf_sctp_asconf_reserved,
2405      { "Reserved", "sctp.asconf.reserved",
2406        FT_BYTES, BASE_NONE, NULL, 0x0,          
2407        "", HFILL }
2408     }, 
2409     {&hf_sctp_asconf_addr_type,
2410      { "Address type", "sctp.asconf.address_type",
2411        FT_UINT8, BASE_HEX, VALS(sctp_address_type_values), 0x0,          
2412        "", HFILL }
2413     }, 
2414     {&hf_sctp_asconf_addr,
2415      { "Address bytes", "sctp.asconf.address_bytes",
2416        FT_BYTES, BASE_NONE, NULL, 0x0,          
2417        "", HFILL }
2418     }, 
2419     {&hf_sctp_asconf_ipv4_address,
2420      { "IP Version 4 address", "sctp.asconf.ipv4_address",
2421        FT_IPv4, BASE_NONE, NULL, 0x0,
2422        "", HFILL }
2423     },
2424     {&hf_sctp_asconf_ipv6_address,
2425      { "IP Version 6 address", "sctp.asconf.ipv6_address",
2426        FT_IPv6, BASE_NONE, NULL, 0x0,
2427        "", HFILL }
2428     },
2429     {&hf_sctp_asconf_ack_serial,
2430      { "Serial Number", "sctp.asconf_ack.serial_number",
2431        FT_UINT32, BASE_HEX, NULL, 0x0,          
2432        "", HFILL }
2433     }, 
2434     {&hf_sctp_asconf_ack_correlation_id,
2435      { "Correlation_id", "sctp.asconf_ack.correlation_id",
2436        FT_UINT32, BASE_HEX, NULL, 0x0,          
2437        "", HFILL }
2438     },
2439     {&hf_sctp_adap_indication,
2440      { "Indication", "sctp.adapation_layer_indication.indication",
2441        FT_UINT32, BASE_HEX, NULL, 0x0,          
2442        "", HFILL }
2443     }, 
2444     {&hf_sctp_cause_code,
2445      { "Cause code", "sctp.cause.code",
2446        FT_UINT16, BASE_HEX, VALS(sctp_cause_code_values), 0x0,          
2447        "", HFILL }
2448     },
2449     {&hf_sctp_cause_length,
2450      { "Cause length", "sctp.cause.length",
2451        FT_UINT16, BASE_DEC, NULL, 0x0,          
2452        "", HFILL }
2453     }, 
2454     {&hf_sctp_cause_stream_identifier,
2455      { "Stream identifier", "sctp.cause.stream_identifier",
2456        FT_UINT16, BASE_DEC, NULL, 0x0,          
2457        "", HFILL }
2458     },
2459     {&hf_sctp_cause_number_of_missing_parameters,
2460      { "Number of missing parameters", "sctp.cause.nr_of_missing_parameters",
2461        FT_UINT32, BASE_DEC, NULL, 0x0,          
2462        "", HFILL }
2463     }, 
2464     {&hf_sctp_cause_missing_parameter_type,
2465      { "Missing parameter type", "sctp.cause.missing_parameter_type",
2466        FT_UINT16, BASE_HEX, VALS(sctp_parameter_identifier_values), 0x0,
2467        "", HFILL }
2468     },
2469     {&hf_sctp_cause_measure_of_staleness,
2470      { "Measure of staleness in usec", "sctp.cause.measure_of_staleness",
2471        FT_UINT32, BASE_DEC, NULL, 0x0,          
2472        "", HFILL }
2473     },
2474     {&hf_sctp_cause_tsn,
2475      { "TSN", "sctp.cause.tsn",
2476        FT_UINT32, BASE_DEC, NULL, 0x0,          
2477        "", HFILL }
2478     },
2479   };
2480   
2481   /* Setup protocol subtree array */
2482   static gint *ett[] = {
2483     &ett_sctp,
2484     &ett_sctp_chunk,
2485     &ett_sctp_chunk_parameter,
2486     &ett_sctp_chunk_cause,
2487     &ett_sctp_data_chunk_flags,
2488     &ett_sctp_sack_chunk_gap_block,
2489     &ett_sctp_supported_address_types_parameter,
2490     &ett_sctp_unrecognized_parameter_parameter,
2491     &ett_sctp_unreliable_streams_interval
2492   };
2493   
2494   static enum_val_t sctp_checksum_options[] = {
2495     { "None",        SCTP_CHECKSUM_NONE },
2496     { "Adler 32",    SCTP_CHECKSUM_ADLER32 },
2497     { "CRC 32c",     SCTP_CHECKSUM_CRC32C },
2498     { "Automatic",   SCTP_CHECKSUM_AUTOMATIC},
2499     { NULL, 0 }
2500   };
2501  
2502   /* Register the protocol name and description */
2503   proto_sctp = proto_register_protocol("Stream Control Transmission Protocol", "SCTP", "sctp");
2504   sctp_module = prefs_register_protocol(proto_sctp, NULL);
2505   prefs_register_enum_preference(sctp_module, "checksum",
2506                                  "Checksum type",
2507                                  "The type of checksum used in SCTP packets",
2508                                  &sctp_checksum, sctp_checksum_options, FALSE);
2509
2510   /* Required function calls to register the header fields and subtrees used */
2511   proto_register_field_array(proto_sctp, hf, array_length(hf));
2512   proto_register_subtree_array(ett, array_length(ett));
2513
2514   /* subdissector code */
2515   sctp_port_dissector_table = register_dissector_table("sctp.port", "SCTP port", FT_UINT16, BASE_DEC);
2516   sctp_ppi_dissector_table  = register_dissector_table("sctp.ppi",  "SCTP payload protocol identifier", FT_UINT32, BASE_HEX);
2517
2518 };
2519
2520 void
2521 proto_reg_handoff_sctp(void)
2522 {
2523   dissector_handle_t sctp_handle;
2524
2525   sctp_handle = create_dissector_handle(dissect_sctp, proto_sctp);
2526   dissector_add("ip.proto", IP_PROTO_SCTP, sctp_handle);
2527 }