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