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