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