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