Add in some heuristics to try to detect AIX libpcap format. (This works
[obnox/wireshark/wip.git] / packet-sctp.c
1 /* packet-sctp.c
2  * Routines for Stream Control Transmission Protocol dissection
3  * Copyright 2000, Michael Tüxen <Michael.Tuexen@icn.siemens.de>
4  *
5  * $Id: packet-sctp.c,v 1.21 2001/10/23 20:14:20 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
11  * Copied from README.developer
12  * 
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  * 
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  * 
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <stdio.h>
33 #include <stdlib.h>
34
35
36 #ifdef HAVE_SYS_TYPES_H
37 # include <sys/types.h>
38 #endif
39
40 #ifdef HAVE_NETINET_IN_H
41 # include <netinet/in.h>
42 #endif
43
44 #include <string.h>
45 #include <glib.h>
46
47 #ifdef NEED_SNPRINTF_H
48 # include "snprintf.h"
49 #endif
50
51 #include "packet.h"
52 #include "ipproto.h"
53
54 /* Initialize the protocol and registered fields */
55 static int proto_sctp = -1;
56 static int hf_sctp_source_port      = -1;
57 static int hf_sctp_destination_port = -1;
58 static int hf_sctp_verification_tag = -1;
59 static int hf_sctp_checksum         = -1;
60
61 static int hf_sctp_chunk_type       = -1;
62 static int hf_sctp_chunk_flags      = -1;
63 static int hf_sctp_chunk_length     = -1;
64
65 static int hf_sctp_init_chunk_initiate_tag   = -1;
66 static int hf_sctp_init_chunk_adv_rec_window_credit = -1;
67 static int hf_sctp_init_chunk_number_of_outbound_streams = -1;
68 static int hf_sctp_init_chunk_number_of_inbound_streams  = -1;
69 static int hf_sctp_init_chunk_initial_tsn    = -1;
70
71 static int hf_sctp_cumulative_tsn_ack = -1;
72
73 static int hf_sctp_data_chunk_tsn = -1;
74 static int hf_sctp_data_chunk_stream_id = -1;
75 static int hf_sctp_data_chunk_stream_seq_number = -1;
76 static int hf_sctp_data_chunk_payload_proto_id = -1;
77
78 static int hf_sctp_data_chunk_e_bit = -1;
79 static int hf_sctp_data_chunk_b_bit = -1;
80 static int hf_sctp_data_chunk_u_bit = -1;
81
82 static int hf_sctp_sack_chunk_cumulative_tsn_ack = -1;
83 static int hf_sctp_sack_chunk_adv_rec_window_credit = -1;
84 static int hf_sctp_sack_chunk_number_of_gap_blocks = -1;
85 static int hf_sctp_sack_chunk_number_of_dup_tsns = -1;
86 static int hf_sctp_sack_chunk_gap_block_start = -1;
87 static int hf_sctp_sack_chunk_gap_block_end = -1;
88 static int hf_sctp_sack_chunk_duplicate_tsn = -1;
89
90 static int hf_sctp_shutdown_chunk_cumulative_tsn_ack = -1;
91
92 static int hf_sctp_cwr_chunk_lowest_tsn = -1;
93
94 static int hf_sctp_ecne_chunk_lowest_tsn = -1;
95
96 static int hf_sctp_shutdown_complete_chunk_t_bit = -1;
97
98 static int hf_sctp_chunk_parameter_type = -1;
99 static int hf_sctp_chunk_parameter_length = -1;
100 static int hf_sctp_parameter_ipv4_address = -1;
101 static int hf_sctp_parameter_ipv6_address = -1;
102 static int hf_sctp_parameter_cookie_preservative_increment = -1;
103 static int hf_sctp_parameter_hostname_hostname = -1;
104 static int hf_sctp_supported_address_types_parameter = -1;
105
106 static int hf_sctp_cause_code = -1;
107 static int hf_sctp_cause_length = -1;
108 static int hf_sctp_cause_stream_identifier = -1;
109
110 static int hf_sctp_cause_number_of_missing_parameters = -1;
111 static int hf_sctp_cause_missing_parameter_type = -1;
112
113 static int hf_sctp_cause_measure_of_staleness = -1;
114
115 static int hf_sctp_cause_tsn = -1;
116
117 static dissector_table_t sctp_port_dissector_table;
118 static dissector_table_t sctp_ppi_dissector_table;
119
120 /* Initialize the subtree pointers */
121 static gint ett_sctp = -1;
122 static gint ett_sctp_chunk = -1;
123 static gint ett_sctp_chunk_parameter = -1;
124 static gint ett_sctp_chunk_cause = -1;
125 static gint ett_sctp_data_chunk_flags = -1;
126 static gint ett_sctp_sack_chunk_gap_block = -1;
127 static gint ett_sctp_supported_address_types_parameter = -1;
128 static gint ett_sctp_unrecognized_parameter_parameter = -1;
129
130 #define SCTP_DATA_CHUNK_ID               0
131 #define SCTP_INIT_CHUNK_ID               1
132 #define SCTP_INIT_ACK_CHUNK_ID           2
133 #define SCTP_SACK_CHUNK_ID               3
134 #define SCTP_HEARTBEAT_CHUNK_ID          4
135 #define SCTP_HEARTBEAT_ACK_CHUNK_ID      5
136 #define SCTP_ABORT_CHUNK_ID              6
137 #define SCTP_SHUTDOWN_CHUNK_ID           7
138 #define SCTP_SHUTDOWN_ACK_CHUNK_ID       8
139 #define SCTP_ERROR_CHUNK_ID              9
140 #define SCTP_COOKIE_ECHO_CHUNK_ID       10
141 #define SCTP_COOKIE_ACK_CHUNK_ID        11
142 #define SCTP_ECNE_CHUNK_ID              12
143 #define SCTP_CWR_CHUNK_ID               13
144 #define SCTP_SHUTDOWN_COMPLETE_CHUNK_ID 14
145 #define SCTP_IETF_EXT                  255
146
147 static const value_string sctp_chunk_type_values[] = {
148   { SCTP_DATA_CHUNK_ID,              "DATA" },
149   { SCTP_INIT_CHUNK_ID,              "INIT" },
150   { SCTP_INIT_ACK_CHUNK_ID,          "INIT_ACK" },
151   { SCTP_SACK_CHUNK_ID,              "SACK" },
152   { SCTP_HEARTBEAT_CHUNK_ID,         "HEARTBEAT" },
153   { SCTP_HEARTBEAT_ACK_CHUNK_ID,     "HEARTBEAT_ACK" },
154   { SCTP_ABORT_CHUNK_ID,             "ABORT" },
155   { SCTP_SHUTDOWN_CHUNK_ID,          "SHUTDOWN" },
156   { SCTP_SHUTDOWN_ACK_CHUNK_ID,      "SHUTDOWN_ACK" },
157   { SCTP_ERROR_CHUNK_ID,             "ERROR" },
158   { SCTP_COOKIE_ECHO_CHUNK_ID,       "COOKIE_ECHO" },
159   { SCTP_COOKIE_ACK_CHUNK_ID,        "COOKIE_ACK" },
160   { SCTP_ECNE_CHUNK_ID,              "ECNE" },
161   { SCTP_CWR_CHUNK_ID,               "CWR" },
162   { SCTP_SHUTDOWN_COMPLETE_CHUNK_ID, "SHUTDOWN_COMPLETE" },
163   { SCTP_IETF_EXT,                   "IETF_EXTENSION" },
164   { 0,                               NULL } };
165
166 #define HEARTBEAT_INFO_PARAMETER_ID          0x0001
167 #define IPV4ADDRESS_PARAMETER_ID             0x0005
168 #define IPV6ADDRESS_PARAMETER_ID             0x0006
169 #define STATE_COOKIE_PARAMETER_ID            0x0007
170 #define UNREC_PARA_PARAMETER_ID              0x0008
171 #define COOKIE_PRESERVATIVE_PARAMETER_ID     0x0009
172 #define HOSTNAME_ADDRESS_PARAMETER_ID        0x000b
173 #define SUPPORTED_ADDRESS_TYPES_PARAMETER_ID 0x000c
174 #define ECN_PARAMETER_ID                     0x8000
175
176 static const value_string sctp_parameter_identifier_values[] = {
177   { HEARTBEAT_INFO_PARAMETER_ID,          "Heartbeat info" },
178   { IPV4ADDRESS_PARAMETER_ID,             "IPv4 address" },
179   { IPV6ADDRESS_PARAMETER_ID,             "IPv6 address" },
180   { STATE_COOKIE_PARAMETER_ID,            "State cookie" },
181   { UNREC_PARA_PARAMETER_ID,              "Unrecognized parameters" },
182   { COOKIE_PRESERVATIVE_PARAMETER_ID,     "Cookie preservative" },
183   { HOSTNAME_ADDRESS_PARAMETER_ID,        "Hostname address" },
184   { SUPPORTED_ADDRESS_TYPES_PARAMETER_ID, "Supported address types" },
185   { ECN_PARAMETER_ID,                     "ECN" },
186   { 0,                                    NULL } };
187
188 #define PARAMETER_TYPE_LENGTH            2
189 #define PARAMETER_LENGTH_LENGTH          2
190 #define PARAMETER_HEADER_LENGTH          (PARAMETER_TYPE_LENGTH + PARAMETER_LENGTH_LENGTH)
191
192 #define PARAMETER_HEADER_OFFSET          0
193 #define PARAMETER_TYPE_OFFSET            PARAMETER_HEADER_OFFSET
194 #define PARAMETER_LENGTH_OFFSET          (PARAMETER_TYPE_OFFSET + PARAMETER_TYPE_LENGTH)
195 #define PARAMETER_VALUE_OFFSET           (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
196
197 #define HEARTBEAT_INFO_PARAMETER_INFO_OFFSET PARAMETER_VALUE_OFFSET
198 #define HEARTBEAT_INFO_PARAMETER_HEADER_LENGTH PARAMETER_HEADER_LENGTH
199
200 #define IPV4_ADDRESS_LENGTH              4
201 #define IPV6_ADDRESS_LENGTH              16
202
203 #define STATE_COOKIE_PARAMETER_HEADER_LENGTH   PARAMETER_HEADER_LENGTH
204 #define STATE_COOKIE_PARAMETER_COOKIE_OFFSET   PARAMETER_VALUE_OFFSET
205
206 #define COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET PARAMETER_VALUE_OFFSET
207 #define COOKIE_PRESERVATIVE_PARAMETER_INCR_LENGTH 4
208 #define SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH 2
209
210 #define CAUSE_CODE_LENGTH            2
211 #define CAUSE_LENGTH_LENGTH          2
212 #define CAUSE_HEADER_LENGTH          (CAUSE_CODE_LENGTH + CAUSE_LENGTH_LENGTH)
213
214 #define CAUSE_HEADER_OFFSET          0
215 #define CAUSE_CODE_OFFSET            CAUSE_HEADER_OFFSET
216 #define CAUSE_LENGTH_OFFSET          (CAUSE_CODE_OFFSET + CAUSE_CODE_LENGTH)
217 #define CAUSE_INFO_OFFSET            (CAUSE_LENGTH_OFFSET + CAUSE_LENGTH_LENGTH)
218
219 #define CAUSE_STREAM_IDENTIFIER_LENGTH 2
220 #define CAUSE_RESERVED_LENGTH 2
221 #define CAUSE_STREAM_IDENTIFIER_OFFSET CAUSE_INFO_OFFSET
222 #define CAUSE_RESERVED_OFFSET          (CAUSE_STREAM_IDENTIFIER_OFFSET + CAUSE_STREAM_IDENTIFIER_LENGTH)
223
224 #define CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH 4
225 #define CAUSE_MISSING_PARAMETER_TYPE_LENGTH       2
226
227 #define CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET CAUSE_INFO_OFFSET
228 #define CAUSE_FIRST_MISSING_PARAMETER_TYPE_OFFSET (CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET + \
229                                                    CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH )
230
231 #define CAUSE_MEASURE_OF_STALENESS_LENGTH 4
232 #define CAUSE_MEASURE_OF_STALENESS_OFFSET CAUSE_INFO_OFFSET
233
234 #define CAUSE_TSN_LENGTH 4
235 #define CAUSE_TSN_OFFSET CAUSE_INFO_OFFSET
236
237 #define INVALID_STREAM_IDENTIFIER              0x01
238 #define MISSING_MANDATORY_PARAMETERS           0x02
239 #define STALE_COOKIE_ERROR                     0x03
240 #define OUT_OF_RESOURCE                        0x04
241 #define UNRESOLVABLE_ADDRESS                   0x05
242 #define UNRECOGNIZED_CHUNK_TYPE                0x06
243 #define INVALID_MANDATORY_PARAMETER            0x07
244 #define UNRECOGNIZED_PARAMETERS                0x08
245 #define NO_USER_DATA                           0x09
246 #define COOKIE_RECEIVED_WHILE_SHUTTING_DOWN    0x0a
247
248 static const value_string sctp_cause_code_values[] = {
249   { INVALID_STREAM_IDENTIFIER,           "Invalid stream identifier" },
250   { MISSING_MANDATORY_PARAMETERS,        "Missing mandator parameter" },
251   { STALE_COOKIE_ERROR,                  "Stale cookie error" },
252   { OUT_OF_RESOURCE,                     "Out of resource" },
253   { UNRESOLVABLE_ADDRESS,                "Unresolvable address" },
254   { UNRECOGNIZED_CHUNK_TYPE,             "Unrecognized chunk type " },
255   { INVALID_MANDATORY_PARAMETER,         "Invalid mandatory parameter" },
256   { UNRECOGNIZED_PARAMETERS,             "Unrecognized parameters" },
257   { NO_USER_DATA,                        "No user data" },
258   { COOKIE_RECEIVED_WHILE_SHUTTING_DOWN, "Cookie received while shutting down" },
259   { 0,                           NULL } };
260
261 #define NOT_SPECIFIED_PROTOCOL_ID  0
262 #define IUA_PAYLOAD_PROTOCOL_ID    1
263 #define M2UA_PAYLOAD_PROTOCOL_ID   2
264 #define M3UA_PAYLOAD_PROTOCOL_ID   3
265 #define SUA_PAYLOAD_PROTOCOL_ID    4
266 #define M2PA_PAYLOAD_PROTOCOL_ID   5
267 #define V5UA_PAYLOAD_PROTOCOL_ID   6
268
269 static const value_string sctp_payload_proto_id_values[] = {
270   { NOT_SPECIFIED_PROTOCOL_ID,           "not specified" },
271   { IUA_PAYLOAD_PROTOCOL_ID,             "IUA" },
272   { M2UA_PAYLOAD_PROTOCOL_ID,            "M2UA" },
273   { M3UA_PAYLOAD_PROTOCOL_ID,            "M3UA" },
274   { SUA_PAYLOAD_PROTOCOL_ID,             "SUA" },
275   { M2PA_PAYLOAD_PROTOCOL_ID,            "M2PA" },
276   { V5UA_PAYLOAD_PROTOCOL_ID,            "V5UA" },
277   { 0,                                   NULL } };
278
279 /* The structure of the common header is described by the following constants */
280 #define SOURCE_PORT_LENGTH      2
281 #define DESTINATION_PORT_LENGTH 2
282 #define VERIFICATION_TAG_LENGTH 4
283 #define CHECKSUM_LENGTH         4
284 #define COMMON_HEADER_LENGTH    (SOURCE_PORT_LENGTH + \
285                                  DESTINATION_PORT_LENGTH + \
286                                  VERIFICATION_TAG_LENGTH + \
287                                  CHECKSUM_LENGTH)
288 #define SOURCE_PORT_OFFSET      0
289 #define DESTINATION_PORT_OFFSET (SOURCE_PORT_OFFSET + SOURCE_PORT_LENGTH)
290 #define VERIFICATION_TAG_OFFSET (DESTINATION_PORT_OFFSET + DESTINATION_PORT_LENGTH)
291 #define CHECKSUM_OFFSET         (VERIFICATION_TAG_OFFSET + VERIFICATION_TAG_LENGTH)
292
293 /* The structure of the chunk header is described by the following constants */
294 #define CHUNK_TYPE_LENGTH             1
295 #define CHUNK_FLAGS_LENGTH            1
296 #define CHUNK_LENGTH_LENGTH           2
297 #define CHUNK_HEADER_LENGTH           (CHUNK_TYPE_LENGTH + \
298                                        CHUNK_FLAGS_LENGTH + \
299                                        CHUNK_LENGTH_LENGTH)
300 #define CHUNK_HEADER_OFFSET           0
301 #define CHUNK_TYPE_OFFSET             CHUNK_HEADER_OFFSET
302 #define CHUNK_FLAGS_OFFSET            (CHUNK_TYPE_OFFSET + CHUNK_TYPE_LENGTH)
303 #define CHUNK_LENGTH_OFFSET           (CHUNK_FLAGS_OFFSET + CHUNK_FLAGS_LENGTH)
304 #define CHUNK_VALUE_OFFSET            (CHUNK_LENGTH_OFFSET + CHUNK_LENGTH_LENGTH)
305
306 /* The following constants describe the structure of DATA chunks */
307 #define DATA_CHUNK_TSN_LENGTH         4
308 #define DATA_CHUNK_STREAM_ID_LENGTH   2
309 #define DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH 2
310 #define DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH 4
311
312 #define DATA_CHUNK_TSN_OFFSET         (CHUNK_VALUE_OFFSET + 0)
313 #define DATA_CHUNK_STREAM_ID_OFFSET   (DATA_CHUNK_TSN_OFFSET + DATA_CHUNK_TSN_LENGTH)
314 #define DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET (DATA_CHUNK_STREAM_ID_OFFSET + \
315                                              DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH)
316 #define DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET (DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET + \
317                                                DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH)
318 #define DATA_CHUNK_PAYLOAD_OFFSET     (DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET + \
319                                        DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH)
320
321 #define DATA_CHUNK_HEADER_LENGTH      (CHUNK_HEADER_LENGTH + \
322                                        DATA_CHUNK_TSN_LENGTH + \
323                                        DATA_CHUNK_STREAM_ID_LENGTH + \
324                                        DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH + \
325                                        DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH)
326
327 #define SCTP_DATA_CHUNK_E_BIT 0x01
328 #define SCTP_DATA_CHUNK_B_BIT 0x02
329 #define SCTP_DATA_CHUNK_U_BIT 0x04
330
331 #define INIT_CHUNK_INITIATE_TAG_LENGTH               4
332 #define INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH      4
333 #define INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH 2
334 #define INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH  2
335 #define INIT_CHUNK_INITIAL_TSN_LENGTH                4
336
337 #define INIT_CHUNK_INITIATE_TAG_OFFSET               CHUNK_VALUE_OFFSET
338 #define INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET      (INIT_CHUNK_INITIATE_TAG_OFFSET + \
339                                                       INIT_CHUNK_INITIATE_TAG_LENGTH )
340 #define INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET (INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET + \
341                                                       INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH )
342 #define INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET  (INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET + \
343                                                       INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH )
344 #define INIT_CHUNK_INITIAL_TSN_OFFSET                (INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET + \
345                                                       INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH )
346 #define INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET  (INIT_CHUNK_INITIAL_TSN_OFFSET + \
347                                                       INIT_CHUNK_INITIAL_TSN_LENGTH )
348
349
350 #define SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH    4
351 #define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH 4
352 #define SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH  2
353 #define SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH    2
354 #define SACK_CHUNK_GAP_BLOCK_LENGTH             4
355 #define SACK_CHUNK_GAP_BLOCK_START_LENGTH       2
356 #define SACK_CHUNK_GAP_BLOCK_END_LENGTH         2
357 #define SACK_CHUNK_DUP_TSN_LENGTH               4
358
359 #define SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET (CHUNK_VALUE_OFFSET + 0)
360 #define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET (SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET + \
361                                                  SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH)
362 #define SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET (SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET + \
363                                                 SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH)
364 #define SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET (SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET + \
365                                               SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH)
366 #define SACK_CHUNK_GAP_BLOCK_OFFSET (SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET + \
367                                      SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH)
368
369 #define HEARTBEAT_CHUNK_INFO_OFFSET CHUNK_VALUE_OFFSET
370
371 #define SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET CHUNK_VALUE_OFFSET
372 #define SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_LENGTH 4
373                 
374 #define ABORT_CHUNK_FIRST_ERROR_CAUSE_OFFSET 4     
375 #define ERROR_CHUNK_FIRST_ERROR_CAUSE_OFFSET 4     
376
377 #define COOKIE_ECHO_CHUNK_COOKIE_OFFSET CHUNK_VALUE_OFFSET
378
379 #define ECNE_CHUNK_LOWEST_TSN_OFFSET CHUNK_VALUE_OFFSET
380 #define ECNE_CHUNK_LOWEST_TSN_LENGTH 4
381
382 #define CWR_CHUNK_LOWEST_TSN_OFFSET CHUNK_VALUE_OFFSET
383 #define CWR_CHUNK_LOWEST_TSN_LENGTH 4
384                      
385 #define SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT 0x01
386
387 static const true_false_string sctp_data_chunk_e_bit_value = {
388   "Last segment",
389   "Not the last segment"
390 };
391
392 static const true_false_string sctp_data_chunk_b_bit_value = {
393   "First segment",
394   "Subsequent segment"
395 };
396
397 static const true_false_string sctp_data_chunk_u_bit_value = {
398   "Unordered delivery",
399   "Ordered deliviery"
400 };
401
402 static const true_false_string sctp_shutdown_complete_chunk_t_bit_value = {
403   "No TCB destroyed",
404   "TCB destroyed"
405 };
406
407 /* adler32.c -- compute the Adler-32 checksum of a data stream
408  * Copyright (C) 1995-1996 Mark Adler
409  * For conditions of distribution and use, see copyright notice in zlib.h
410  * available, e.g. from  http://www.cdrom.com/pub/infozip/zlib/
411  *
412  * It was modified for the use in this dissector.
413  */
414
415 #define BASE 65521L /* largest prime smaller than 65536      */
416 #define NMAX 5540   /* NMAX is the largest n - 12 such that  */
417                     /* 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
418
419 #define DO1(buf,i)  {s1 += buf[i]; s2 += s1;}
420 #define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
421 #define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
422 #define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
423 #define DO16(buf)   DO8(buf,0); DO8(buf,8);
424
425 static unsigned int
426 sctp_adler_32(const unsigned char* buf,
427               unsigned int len)
428 {
429     unsigned int s1 = 1L;
430     unsigned int s2 = 0L;
431     int k;
432     
433     /* handle the first 8 bytes of the datagram */
434     DO8(buf,0);
435     buf += SOURCE_PORT_LENGTH + 
436            DESTINATION_PORT_LENGTH + 
437            VERIFICATION_TAG_LENGTH;
438     
439     /* handle four 0 bytes as checksum */
440     s2  += CHECKSUM_LENGTH * s1;
441     buf += CHECKSUM_LENGTH;
442
443     /* now we have 12 bytes handled */
444     len -= COMMON_HEADER_LENGTH;
445
446     /* handle the rest of the datagram */
447     while (len > 0) {
448         k = len < NMAX ? len : NMAX;
449         len -= k;
450         while (k >= 16) {
451             DO16(buf);
452             buf += 16;
453             k -= 16;
454         }
455         if (k != 0) do {
456             s1 += *buf++;
457             s2 += s1;
458         } while (--k);
459         s1 %= BASE;
460         s2 %= BASE;
461     }
462     return (s2 << 16) | s1;
463 }
464
465 static char 
466 *sctp_checksum_state(tvbuff_t *tvb, guint orig_checksum)
467 {
468   guint length;
469   
470   length = tvb_length(tvb);
471   if (orig_checksum == sctp_adler_32(tvb_get_ptr(tvb, 0, length), length))
472     return "correct";
473   else
474     return "incorrect";
475 }
476
477 static guint 
478 nr_of_padding_bytes (guint length)
479 {
480   guint remainder;
481
482   remainder = length % 4;
483
484   if (remainder == 0)
485     return 0;
486   else
487     return 4 - remainder;
488 }
489
490 /* 
491  * TLV parameter stuff for INIT and INIT-ACK chunks
492  */
493
494 static void
495 dissect_parameter(tvbuff_t *, proto_tree *);
496
497 static gboolean
498 dissect_sctp_chunk(tvbuff_t *, packet_info *, proto_tree *, proto_tree *);
499
500 static void 
501 dissect_tlv_parameter_list(tvbuff_t *parameter_list_tvb, proto_tree *tree)
502 {
503   guint offset, length, padding_length, total_length;
504   tvbuff_t *parameter_tvb;
505
506   offset = 0;
507   while(tvb_length_remaining(parameter_list_tvb, offset)) {
508     length         = tvb_get_ntohs(parameter_list_tvb, offset + PARAMETER_LENGTH_OFFSET);
509     padding_length = nr_of_padding_bytes(length);
510     total_length   = length + padding_length;
511     /* create a tvb for the chunk including the padding bytes */
512     parameter_tvb    = tvb_new_subset(parameter_list_tvb, offset, total_length, total_length);
513     dissect_parameter(parameter_tvb, tree); 
514     /* get rid of the handled parameter */
515     offset += total_length;
516   }
517 }
518
519 static void
520 dissect_heartbeat_info_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
521 {
522   guint16 length, heartbeat_info_length;
523   
524   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
525   
526   heartbeat_info_length = length - HEARTBEAT_INFO_PARAMETER_HEADER_LENGTH;
527
528   proto_tree_add_text(parameter_tree, parameter_tvb, HEARTBEAT_INFO_PARAMETER_INFO_OFFSET, heartbeat_info_length,
529                       "Heartbeat info (%u byte%s)",
530                       heartbeat_info_length, plurality(heartbeat_info_length, "", "s"));
531
532   proto_item_set_text(parameter_item, "Heartbeat info parameter with %u byte%s of info",
533                       heartbeat_info_length, plurality(heartbeat_info_length, "", "s"));
534 }
535
536 static void
537 dissect_ipv4_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
538 {
539   guint32 ipv4_address;
540
541   tvb_memcpy(parameter_tvb, (guint8 *)&ipv4_address, PARAMETER_VALUE_OFFSET, IPV4_ADDRESS_LENGTH); 
542   proto_tree_add_ipv4(parameter_tree, hf_sctp_parameter_ipv4_address,
543                       parameter_tvb, PARAMETER_VALUE_OFFSET, IPV4_ADDRESS_LENGTH,
544                       ipv4_address);  
545   proto_item_set_text(parameter_item, "IPV4 address parameter");
546 }
547
548 static void
549 dissect_ipv6_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
550 {
551   proto_tree_add_ipv6(parameter_tree, hf_sctp_parameter_ipv6_address,
552                       parameter_tvb, PARAMETER_VALUE_OFFSET, IPV6_ADDRESS_LENGTH,
553                       tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, IPV6_ADDRESS_LENGTH));
554   
555   proto_item_set_text(parameter_item, "IPV6 address parameter");
556 }
557
558 static void
559 dissect_state_cookie_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
560 {
561   guint16 length, state_cookie_length;
562   
563   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
564   
565   state_cookie_length = length - STATE_COOKIE_PARAMETER_HEADER_LENGTH;
566
567   proto_tree_add_text(parameter_tree, parameter_tvb, STATE_COOKIE_PARAMETER_COOKIE_OFFSET, state_cookie_length,
568                       "State cookie (%u byte%s)",
569                       state_cookie_length, plurality(state_cookie_length, "", "s"));
570
571   proto_item_set_text(parameter_item, "State Cookie Parameter with %u byte%s cookie",
572                       state_cookie_length, plurality(state_cookie_length, "", "s"));
573 }
574
575 static void
576 dissect_unrecognized_parameters_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
577 {
578   guint16 length, padding_length, parameter_value_length;
579   tvbuff_t *unrecognized_parameters_tvb;
580
581   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
582   padding_length = nr_of_padding_bytes(length);
583
584   parameter_value_length = length - PARAMETER_HEADER_LENGTH + padding_length;
585
586   unrecognized_parameters_tvb = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, 
587                                                parameter_value_length, parameter_value_length);
588   dissect_tlv_parameter_list(unrecognized_parameters_tvb, parameter_tree);
589    
590   proto_item_set_text(parameter_item, "Unrecognized parameter of type");
591 }
592
593 static void
594 dissect_cookie_preservative_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
595 {
596   guint32 increment;
597
598   increment =  tvb_get_ntohl(parameter_tvb, COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET);
599   
600   proto_tree_add_uint(parameter_tree, hf_sctp_parameter_cookie_preservative_increment, parameter_tvb, 
601                       COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET, 
602                       COOKIE_PRESERVATIVE_PARAMETER_INCR_LENGTH,
603                       increment);
604   
605   proto_item_set_text(parameter_item, "Cookie preservative parameter requesting for a %u msec increment",
606                       increment);
607 }
608
609 static void
610 dissect_hostname_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
611 {
612   guint16  length, hostname_length;
613   char *hostname;
614
615   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
616   
617   hostname_length = length - PARAMETER_HEADER_LENGTH;
618   hostname = (char *)tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, hostname_length);
619   proto_tree_add_string(parameter_tree, hf_sctp_parameter_hostname_hostname, parameter_tvb,
620                         PARAMETER_VALUE_OFFSET, hostname_length,
621                         hostname);
622
623   proto_item_set_text(parameter_item, "Hostname parameter");
624 }
625
626 static void
627 dissect_supported_address_types_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
628 {
629   guint16 length, address_type, number_of_address_types, address_type_number, list_of_address_types_length ;
630   guint offset;
631   proto_item *address_list_item;
632   proto_tree *address_list_tree;
633
634   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
635   list_of_address_types_length = length - PARAMETER_HEADER_LENGTH;
636   number_of_address_types = list_of_address_types_length / SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH;
637
638   address_list_item = proto_tree_add_text(parameter_tree, parameter_tvb, PARAMETER_VALUE_OFFSET, list_of_address_types_length,
639                                           "Supported Address Types (%u address type%s)",
640                                           number_of_address_types, plurality(number_of_address_types, "", "s"));
641   address_list_tree = proto_item_add_subtree(address_list_item, ett_sctp_supported_address_types_parameter);
642  
643   offset = PARAMETER_VALUE_OFFSET;
644   for(address_type_number = 1; address_type_number <= number_of_address_types; address_type_number++) {
645     address_type = tvb_get_ntohs(parameter_tvb, offset);
646     proto_tree_add_uint_format(address_list_tree, hf_sctp_supported_address_types_parameter,
647                                parameter_tvb, offset, SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH,
648                                address_type, "Supported address type: 0x%04x (%s)",
649                                address_type, val_to_str(address_type, sctp_parameter_identifier_values, "unknown"));
650     offset += SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH;
651   };
652
653   proto_item_set_text(parameter_item, "Supported address types parameter reporting %u address type%s",
654                       number_of_address_types, plurality(number_of_address_types, "", "s"));
655 }
656
657 static void
658 dissect_ecn_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
659 {
660    proto_item_set_text(parameter_item, "ECN parameter");
661 }
662
663 static void
664 dissect_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
665 {
666   guint16 type, length, parameter_value_length;
667   
668   type   = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
669   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
670   
671   parameter_value_length = length - PARAMETER_HEADER_LENGTH;
672
673   proto_tree_add_text(parameter_tree, parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length,
674                       "Parameter value (%u byte%s)",
675                       parameter_value_length, plurality(parameter_value_length, "", "s"));
676
677   proto_item_set_text(parameter_item, "Parameter of type %u and %u byte%s value",
678                       type, parameter_value_length, plurality(parameter_value_length, "", "s"));
679 }
680
681 static void
682 dissect_parameter(tvbuff_t *parameter_tvb, proto_tree *chunk_tree)
683 {
684   guint16 type, length, padding_length, total_length;
685   proto_item *parameter_item;
686   proto_tree *parameter_tree;
687
688   type           = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
689   length         = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
690   padding_length = nr_of_padding_bytes(length);
691   total_length   = length + padding_length;
692    
693   parameter_item = proto_tree_add_text(chunk_tree, parameter_tvb,
694         PARAMETER_HEADER_OFFSET, total_length, "%s parameter",
695         val_to_str(type, sctp_parameter_identifier_values, "Unknown"));
696   parameter_tree = proto_item_add_subtree(parameter_item, ett_sctp_chunk_parameter);
697  
698   proto_tree_add_uint(parameter_tree, hf_sctp_chunk_parameter_type, 
699                       parameter_tvb, PARAMETER_TYPE_OFFSET, PARAMETER_TYPE_LENGTH,
700                       type);
701   proto_tree_add_uint(parameter_tree, hf_sctp_chunk_parameter_length, 
702                       parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH,
703                       length);
704  
705   switch(type) {
706   case HEARTBEAT_INFO_PARAMETER_ID:
707     dissect_heartbeat_info_parameter(parameter_tvb, parameter_tree, parameter_item);
708     break;
709   case IPV4ADDRESS_PARAMETER_ID:
710     dissect_ipv4_parameter(parameter_tvb, parameter_tree, parameter_item);
711     break;
712   case IPV6ADDRESS_PARAMETER_ID:
713     dissect_ipv6_parameter(parameter_tvb, parameter_tree, parameter_item);
714     break;
715   case STATE_COOKIE_PARAMETER_ID:
716     dissect_state_cookie_parameter(parameter_tvb, parameter_tree, parameter_item);
717     break;
718   case UNREC_PARA_PARAMETER_ID:
719     dissect_unrecognized_parameters_parameter(parameter_tvb, parameter_tree, parameter_item);
720     break;
721   case COOKIE_PRESERVATIVE_PARAMETER_ID:
722     dissect_cookie_preservative_parameter(parameter_tvb, parameter_tree, parameter_item);
723     break;
724   case HOSTNAME_ADDRESS_PARAMETER_ID:
725     dissect_hostname_parameter(parameter_tvb, parameter_tree, parameter_item);
726     break;
727   case SUPPORTED_ADDRESS_TYPES_PARAMETER_ID:
728     dissect_supported_address_types_parameter(parameter_tvb, parameter_tree, parameter_item);
729     break;
730   case ECN_PARAMETER_ID:
731     dissect_ecn_parameter(parameter_tvb, parameter_tree, parameter_item);
732     break;
733   default:
734     dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
735     break;
736   };
737   if ((padding_length > 0) && (type != UNREC_PARA_PARAMETER_ID))
738     proto_tree_add_text(parameter_tree, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length,
739                         "Padding: %u byte%s",
740                         padding_length, plurality(padding_length, "", "s"));
741 }
742
743 /*
744  * Code to handle error causes for ABORT and ERROR chunks
745  */
746 static void
747 dissect_invalid_stream_identifier_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
748 {
749   guint16 stream_identifier;
750
751   stream_identifier   = tvb_get_ntohs(cause_tvb, CAUSE_STREAM_IDENTIFIER_OFFSET);
752   proto_tree_add_uint(cause_tree, hf_sctp_cause_stream_identifier, 
753                       cause_tvb, CAUSE_STREAM_IDENTIFIER_OFFSET, CAUSE_STREAM_IDENTIFIER_LENGTH,
754                       stream_identifier);
755   proto_tree_add_text(cause_tree, cause_tvb, CAUSE_RESERVED_OFFSET, CAUSE_RESERVED_LENGTH,
756                       "Reserved (2 bytes)");
757
758   proto_item_set_text(cause_item, "Error cause reporting invalid stream identifier %u",
759                       stream_identifier);
760 }
761
762 static void
763 dissect_missing_mandatory_parameters_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
764 {
765   guint32 number_of_missing_parameters, missing_parameter_number;
766   guint16 parameter_type;
767   guint   offset;
768
769   number_of_missing_parameters = tvb_get_ntohl(cause_tvb, CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET);
770   proto_tree_add_uint(cause_tree, hf_sctp_cause_number_of_missing_parameters, 
771                       cause_tvb, CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET, CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH,
772                       number_of_missing_parameters);
773   offset = CAUSE_FIRST_MISSING_PARAMETER_TYPE_OFFSET;
774   for(missing_parameter_number = 1; missing_parameter_number <= number_of_missing_parameters; missing_parameter_number++) {
775     parameter_type = tvb_get_ntohs(cause_tvb, offset);
776     proto_tree_add_uint(cause_tree, hf_sctp_cause_missing_parameter_type,
777                         cause_tvb, offset, CAUSE_MISSING_PARAMETER_TYPE_LENGTH,
778                         parameter_type);
779     offset +=  CAUSE_MISSING_PARAMETER_TYPE_LENGTH;
780   };
781
782   proto_item_set_text(cause_item, "Error cause reporting %u missing mandatory parameter%s",
783                       number_of_missing_parameters, plurality(number_of_missing_parameters, "", "s") );
784 }
785
786 static void
787 dissect_stale_cookie_error_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
788 {
789   guint32 measure_of_staleness;
790
791   measure_of_staleness =  tvb_get_ntohl(cause_tvb, CAUSE_MEASURE_OF_STALENESS_OFFSET);
792   
793   proto_tree_add_uint(cause_tree, hf_sctp_cause_measure_of_staleness, cause_tvb, 
794                       CAUSE_MEASURE_OF_STALENESS_OFFSET, 
795                       CAUSE_MEASURE_OF_STALENESS_LENGTH,
796                       measure_of_staleness);
797   
798   proto_item_set_text(cause_item, "Error cause reporting a measure of staleness of %u usec",
799                       measure_of_staleness);
800 }
801
802 static void
803 dissect_out_of_resource_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
804 {
805   proto_item_set_text(cause_item, "Error cause reporting lack of resources");
806 }
807
808 static void
809 dissect_unresolvable_address_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
810 {
811   guint16 code, length, parameter_length, parameter_type;
812   tvbuff_t *parameter_tvb;
813
814   code   = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET);
815   length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
816   
817   parameter_length = length - CAUSE_HEADER_LENGTH;
818   parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, 
819                                  parameter_length, parameter_length);
820
821   dissect_parameter(parameter_tvb, cause_tree);
822   parameter_type = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
823  
824   proto_item_set_text(cause_item, "Error cause reporting unresolvable address of type 0x%04x (%s)",
825                       parameter_type, val_to_str(parameter_type, sctp_parameter_identifier_values, "unknown") );
826 }
827
828 static void
829 dissect_unrecognized_chunk_type_cause(tvbuff_t *cause_tvb,  packet_info *pinfo, 
830                                       proto_tree *cause_tree, proto_item *cause_item)
831 {
832   guint16 length, chunk_length;
833   guint8 unrecognized_type;
834   tvbuff_t *unrecognized_chunk_tvb;
835
836   length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
837   
838   chunk_length = length - CAUSE_HEADER_LENGTH;
839
840   unrecognized_chunk_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, 
841                                           chunk_length, chunk_length);
842   dissect_sctp_chunk(unrecognized_chunk_tvb, pinfo, cause_tree,cause_tree);
843
844   unrecognized_type   = tvb_get_guint8(unrecognized_chunk_tvb, CHUNK_TYPE_OFFSET);
845  
846   proto_item_set_text(cause_item, "Error cause reporting unrecognized chunk of type %u (%s)",
847                       unrecognized_type,
848                       val_to_str(unrecognized_type, sctp_chunk_type_values, "unknown"));
849 }
850
851 static void
852 dissect_invalid_mandatory_parameter_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
853 {
854   proto_item_set_text(cause_item, "Error cause reporting an invalid mandatory parameter");
855 }
856
857 static void
858 dissect_unrecognized_parameters_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
859 {
860   guint16 length, padding_length, cause_info_length;
861   tvbuff_t *unrecognized_parameters_tvb;
862
863   length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
864   padding_length = nr_of_padding_bytes(length);
865
866   cause_info_length = length - CAUSE_HEADER_LENGTH + padding_length;
867
868   unrecognized_parameters_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, 
869                                                cause_info_length, cause_info_length);
870   dissect_tlv_parameter_list(unrecognized_parameters_tvb, cause_tree);
871  
872   proto_item_set_text(cause_item, "Error cause reporting unrecognized parameters");
873 }
874
875 static void
876 dissect_no_user_data_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
877 {
878   guint32 tsn;
879
880   tsn = tvb_get_ntohl(cause_tvb, CAUSE_TSN_OFFSET);
881   proto_tree_add_uint(cause_tree, hf_sctp_cause_tsn, cause_tvb, 
882                       CAUSE_TSN_OFFSET, 
883                       CAUSE_TSN_LENGTH,
884                       tsn);
885
886   proto_item_set_text(cause_item, "Error cause reporting data chunk with TSN %u contains no data",
887                       tsn);
888 }
889
890 static void
891 dissect_cookie_received_while_shutting_down_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
892 {
893   proto_item_set_text(cause_item, "Error cause reporting cookie reception while shutting down");
894 }
895
896 static void
897 dissect_unknown_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
898 {
899   guint16 code, length, cause_info_length;
900
901   code   = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET);
902   length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
903   
904   cause_info_length = length - CAUSE_HEADER_LENGTH;
905
906   proto_tree_add_text(cause_tree, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length,
907                       "Cause specific information (%u byte%s)",
908                       cause_info_length, plurality(cause_info_length, "", "s"));
909
910   proto_item_set_text(cause_item, "Error cause with code %u and %u byte%s information",
911                       code, cause_info_length, plurality(cause_info_length, "", "s"));
912 }
913
914 static void
915 dissect_error_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *chunk_tree)
916 {
917   guint16 code, length, padding_length, total_length;
918   proto_item *cause_item;
919   proto_tree *cause_tree;
920
921   code           = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET);
922   length         = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
923   padding_length = nr_of_padding_bytes(length);
924   total_length   = length + padding_length;
925
926   cause_item = proto_tree_add_text(chunk_tree, cause_tvb,
927                                    CAUSE_HEADER_OFFSET, total_length,
928                                    "BAD ERROR CAUSE");
929   cause_tree = proto_item_add_subtree(cause_item, ett_sctp_chunk_cause);
930  
931   proto_tree_add_uint(cause_tree, hf_sctp_cause_code, 
932                       cause_tvb, CAUSE_CODE_OFFSET, CAUSE_CODE_LENGTH,
933                       code);
934   proto_tree_add_uint(cause_tree, hf_sctp_cause_length, 
935                       cause_tvb, CAUSE_LENGTH_OFFSET, CAUSE_LENGTH_LENGTH,
936                       length);
937  
938   switch(code) {
939   case INVALID_STREAM_IDENTIFIER:
940     dissect_invalid_stream_identifier_cause(cause_tvb, cause_tree, cause_item);
941     break;
942   case MISSING_MANDATORY_PARAMETERS:
943     dissect_missing_mandatory_parameters_cause(cause_tvb, cause_tree, cause_item);
944     break;
945   case STALE_COOKIE_ERROR:
946     dissect_stale_cookie_error_cause(cause_tvb, cause_tree, cause_item);
947     break;
948   case OUT_OF_RESOURCE:
949     dissect_out_of_resource_cause(cause_tvb, cause_tree, cause_item);
950     break;
951   case UNRESOLVABLE_ADDRESS:
952     dissect_unresolvable_address_cause(cause_tvb, cause_tree, cause_item);
953     break;
954   case UNRECOGNIZED_CHUNK_TYPE:
955     dissect_unrecognized_chunk_type_cause(cause_tvb, pinfo, cause_tree, cause_item);
956     break;
957   case INVALID_MANDATORY_PARAMETER:
958     dissect_invalid_mandatory_parameter_cause(cause_tvb, cause_tree, cause_item);
959     break;
960   case UNRECOGNIZED_PARAMETERS:
961     dissect_unrecognized_parameters_cause(cause_tvb, cause_tree, cause_item);
962     break;
963   case NO_USER_DATA:
964     dissect_no_user_data_cause(cause_tvb, cause_tree, cause_item);
965     break;
966   case COOKIE_RECEIVED_WHILE_SHUTTING_DOWN:
967     dissect_cookie_received_while_shutting_down_cause(cause_tvb, cause_tree, cause_item);
968     break;
969   default:
970     dissect_unknown_cause(cause_tvb, cause_tree, cause_item);
971     break;
972   };
973   if ((padding_length > 0) && (code != UNRECOGNIZED_PARAMETERS))
974     proto_tree_add_text(cause_tree, cause_tvb, CAUSE_HEADER_OFFSET + length, padding_length,
975                         "Padding: %u byte%s",
976                         padding_length, plurality(padding_length, "", "s"));
977 }
978
979 /*
980  * Code to actually dissect the packets 
981 */
982
983 static gboolean
984 dissect_payload(tvbuff_t *payload_tvb, packet_info *pinfo, proto_tree *tree,
985                 proto_tree *chunk_tree, guint32 ppi, guint16 payload_length, guint16 padding_length)
986 {
987   /* do lookup with the subdissector table */
988   if (dissector_try_port (sctp_ppi_dissector_table, ppi,  payload_tvb, pinfo, tree) ||
989       dissector_try_port(sctp_port_dissector_table, pinfo->srcport,  payload_tvb, pinfo, tree) ||
990       dissector_try_port(sctp_port_dissector_table, pinfo->destport, payload_tvb, pinfo, tree)){
991     return TRUE;
992   }
993   else {
994     if (check_col(pinfo->fd, COL_INFO))
995       col_append_str(pinfo->fd, COL_INFO, "DATA ");
996     proto_tree_add_text(chunk_tree, payload_tvb, 0, payload_length,
997                         "Payload (%u byte%s)",
998                         payload_length, plurality(payload_length, "", "s")); 
999     if (padding_length > 0)
1000       proto_tree_add_text(chunk_tree, payload_tvb, payload_length, padding_length,
1001                           "Padding: %u byte%s",
1002                           padding_length, plurality(padding_length, "", "s"));
1003     return FALSE;
1004   }
1005 }
1006
1007 static gboolean
1008 dissect_data_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1009                    proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1010
1011   guint8  flags;
1012   guint16 length, total_payload_length, payload_length, padding_length, stream_id, stream_seq_number;
1013   guint32 tsn, payload_proto_id;
1014   proto_tree *flag_tree;
1015   tvbuff_t *payload_tvb;
1016    
1017   length            = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1018   payload_length       = length - DATA_CHUNK_HEADER_LENGTH;
1019   padding_length       = nr_of_padding_bytes(length);
1020   total_payload_length = payload_length + padding_length;
1021   payload_tvb          = tvb_new_subset(chunk_tvb, DATA_CHUNK_PAYLOAD_OFFSET,
1022                                           total_payload_length, total_payload_length);
1023   payload_proto_id     = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET);
1024
1025   if (chunk_tree) {
1026     flags             = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
1027      
1028     flag_tree = proto_item_add_subtree(flags_item, ett_sctp_data_chunk_flags);
1029     proto_tree_add_boolean(flag_tree, hf_sctp_data_chunk_e_bit, chunk_tvb,
1030                            CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
1031     proto_tree_add_boolean(flag_tree, hf_sctp_data_chunk_b_bit, chunk_tvb,
1032                            CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
1033     proto_tree_add_boolean(flag_tree, hf_sctp_data_chunk_u_bit, chunk_tvb,
1034                            CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
1035     
1036     tsn               = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_TSN_OFFSET);
1037     stream_id         = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET);
1038     stream_seq_number = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET);
1039          
1040     proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_tsn, 
1041                         chunk_tvb,
1042                         DATA_CHUNK_TSN_OFFSET, DATA_CHUNK_TSN_LENGTH,
1043                         tsn);
1044     proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_stream_id, 
1045                         chunk_tvb, 
1046                         DATA_CHUNK_STREAM_ID_OFFSET, DATA_CHUNK_STREAM_ID_LENGTH,
1047                         stream_id);
1048     proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_stream_seq_number, 
1049                         chunk_tvb, 
1050                         DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET, DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH,
1051                         stream_seq_number);
1052     proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_payload_proto_id, 
1053                         chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH,
1054                         payload_proto_id);
1055     proto_item_set_text(chunk_item, "DATA chunk with TSN %u (%u:%u) containing %u byte%s of payload",
1056                         tsn, stream_id, stream_seq_number, 
1057                         payload_length, plurality(payload_length, "", "s"));
1058   };   
1059   return dissect_payload(payload_tvb, pinfo, tree, chunk_tree, payload_proto_id, payload_length, padding_length); 
1060 }
1061
1062 static void
1063 dissect_init_chunk(tvbuff_t *chunk_tvb,  packet_info *pinfo, proto_tree *tree,
1064                    proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1065
1066   guint32 initiate_tag, adv_rec_window_credit, initial_tsn;
1067   guint16 number_of_inbound_streams, number_of_outbound_streams;
1068   guint8  type;
1069   tvbuff_t *parameter_list_tvb;
1070
1071   type                       = tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET);
1072   
1073   if (check_col(pinfo->fd, COL_INFO)) {
1074     if (type == SCTP_INIT_CHUNK_ID) {
1075       col_append_str(pinfo->fd, COL_INFO, "INIT ");
1076     } else {
1077       col_append_str(pinfo->fd, COL_INFO, "INIT_ACK ");
1078     };
1079   };
1080   
1081   if (chunk_tree) {
1082     initiate_tag               = tvb_get_ntohl(chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET);
1083     adv_rec_window_credit      = tvb_get_ntohl(chunk_tvb, INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET);
1084     number_of_inbound_streams  = tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET);
1085     number_of_outbound_streams = tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET);
1086     initial_tsn                = tvb_get_ntohl(chunk_tvb, INIT_CHUNK_INITIAL_TSN_OFFSET);
1087     
1088     /* handle fixed parameters */
1089     proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_initiate_tag, 
1090                         chunk_tvb,
1091                         INIT_CHUNK_INITIATE_TAG_OFFSET, INIT_CHUNK_INITIATE_TAG_LENGTH,
1092                         initiate_tag);
1093     proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_adv_rec_window_credit, 
1094                         chunk_tvb,
1095                         INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET, INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH,
1096                         adv_rec_window_credit);
1097     proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_number_of_outbound_streams, 
1098                         chunk_tvb,
1099                         INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH,
1100                         number_of_outbound_streams);
1101     proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_number_of_inbound_streams, 
1102                         chunk_tvb,
1103                         INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH,
1104                         number_of_inbound_streams);
1105     proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_initial_tsn, 
1106                         chunk_tvb,
1107                         INIT_CHUNK_INITIAL_TSN_OFFSET, INIT_CHUNK_INITIAL_TSN_LENGTH,
1108                         initial_tsn);
1109     
1110     /* handle variable paramters */
1111     parameter_list_tvb = tvb_new_subset(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET, -1, -1);
1112     dissect_tlv_parameter_list(parameter_list_tvb, chunk_tree);
1113     
1114     proto_item_set_text(chunk_item, 
1115                         "%s chunk requesting for %u outbound stream%s and accepting up to %u inbound stream%s",
1116                         val_to_str(type, sctp_chunk_type_values, "unknown"),
1117                         number_of_outbound_streams, plurality(number_of_outbound_streams, "", "s"),
1118                         number_of_inbound_streams, plurality(number_of_inbound_streams, "", "s"));
1119   }
1120
1121
1122 static void
1123 dissect_init_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1124                        proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1125
1126   dissect_init_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1127
1128
1129 static void
1130 dissect_sack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1131                    proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1132
1133   guint32 cumulative_tsn_ack, adv_rec_window_credit, dup_tsn;
1134   guint16 number_of_gap_blocks, number_of_dup_tsns;
1135   guint16 gap_block_number, dup_tsn_number, start, end;
1136   gint gap_block_offset, dup_tsn_offset;
1137   proto_item *block_item;
1138   proto_tree *block_tree;
1139   
1140   if (check_col(pinfo->fd, COL_INFO))
1141     col_append_str(pinfo->fd, COL_INFO, "SACK ");
1142
1143   if (chunk_tree) {
1144     cumulative_tsn_ack    = tvb_get_ntohl(chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
1145     adv_rec_window_credit = tvb_get_ntohl(chunk_tvb, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET);
1146     number_of_gap_blocks  = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET);
1147     number_of_dup_tsns    = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET);
1148     
1149     proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_cumulative_tsn_ack, 
1150                         chunk_tvb,
1151                         SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET, SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH,
1152                         cumulative_tsn_ack);
1153     proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_adv_rec_window_credit, 
1154                         chunk_tvb,
1155                         SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH,
1156                         adv_rec_window_credit);
1157     proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_number_of_gap_blocks, 
1158                         chunk_tvb,
1159                         SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH,
1160                         number_of_gap_blocks);
1161     proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_number_of_dup_tsns, 
1162                         chunk_tvb,
1163                         SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET, SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH,
1164                         number_of_dup_tsns);
1165     
1166     /* handle the gap acknowledgement blocks */
1167     gap_block_offset = SACK_CHUNK_GAP_BLOCK_OFFSET;
1168     for(gap_block_number = 1; gap_block_number <= number_of_gap_blocks; gap_block_number++) {
1169       start = tvb_get_ntohs(chunk_tvb, gap_block_offset);
1170       end   = tvb_get_ntohs(chunk_tvb, gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH);
1171       block_item = proto_tree_add_text(chunk_tree, chunk_tvb,
1172                                        gap_block_offset, SACK_CHUNK_GAP_BLOCK_LENGTH,
1173                                        "Gap Acknowledgement for %u TSN%s",
1174                                        1 + end - start, plurality(1 + end - start, "", "s"));
1175       block_tree = proto_item_add_subtree(block_item, ett_sctp_sack_chunk_gap_block);
1176       proto_tree_add_uint(block_tree, hf_sctp_sack_chunk_gap_block_start, 
1177                           chunk_tvb,
1178                           gap_block_offset, SACK_CHUNK_GAP_BLOCK_START_LENGTH,
1179                           start);
1180       proto_tree_add_uint(block_tree, hf_sctp_sack_chunk_gap_block_end, 
1181                           chunk_tvb,
1182                           gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH,
1183                           SACK_CHUNK_GAP_BLOCK_END_LENGTH,
1184                           end);
1185       gap_block_offset += SACK_CHUNK_GAP_BLOCK_LENGTH;
1186     };
1187     
1188     /* handle the duplicate TSNs */
1189     dup_tsn_offset = SACK_CHUNK_GAP_BLOCK_OFFSET + number_of_gap_blocks * SACK_CHUNK_GAP_BLOCK_LENGTH;
1190     for(dup_tsn_number = 1; dup_tsn_number <= number_of_dup_tsns; dup_tsn_number++) {
1191       dup_tsn = tvb_get_ntohl(chunk_tvb, dup_tsn_offset);
1192       proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_duplicate_tsn, 
1193                           chunk_tvb,
1194                           dup_tsn, SACK_CHUNK_DUP_TSN_LENGTH,
1195                           dup_tsn);
1196       dup_tsn_offset += SACK_CHUNK_DUP_TSN_LENGTH;
1197     }
1198     
1199     proto_item_set_text(chunk_item, 
1200                         "SACK chunk acknowledging TSN %u and reporting %u gap%s and %u duplicate TSN%s",
1201                         cumulative_tsn_ack,
1202                         number_of_gap_blocks, plurality(number_of_gap_blocks, "", "s"),
1203                         number_of_dup_tsns, plurality(number_of_dup_tsns, "", "s"));
1204   } 
1205 }
1206
1207 static void
1208 dissect_heartbeat_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1209                         proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1210 {
1211   tvbuff_t   *parameter_tvb;
1212   guint chunk_length, info_length, padding_length, total_length;
1213     
1214   if (check_col(pinfo->fd, COL_INFO))
1215     col_append_str(pinfo->fd, COL_INFO, "HEARTBEAT ");
1216
1217   if (chunk_tree) {
1218     chunk_length   = tvb_get_ntohs(chunk_tvb,  CHUNK_LENGTH_OFFSET);
1219     info_length    = chunk_length - CHUNK_HEADER_LENGTH;
1220     padding_length = nr_of_padding_bytes(info_length);
1221     total_length   = info_length + padding_length;
1222     parameter_tvb  = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, total_length, total_length);
1223     
1224     dissect_parameter(parameter_tvb, chunk_tree);
1225     
1226     proto_item_set_text(chunk_item, "HEARTBEAT chunk");
1227   }
1228 }
1229  
1230 static void
1231 dissect_heartbeat_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1232                             proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1233 {  
1234   tvbuff_t   *parameter_tvb;
1235   guint chunk_length, info_length, padding_length, total_length;
1236   
1237   if (check_col(pinfo->fd, COL_INFO))
1238     col_append_str(pinfo->fd, COL_INFO, "HEARTBEAT_ACK ");
1239
1240   if (chunk_tree) {
1241     chunk_length   = tvb_get_ntohs(chunk_tvb,  CHUNK_LENGTH_OFFSET);
1242     info_length    = chunk_length - CHUNK_HEADER_LENGTH;
1243     padding_length = nr_of_padding_bytes(info_length);
1244     total_length   = info_length + padding_length;
1245
1246     parameter_tvb  = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, total_length, total_length);
1247     
1248     dissect_parameter(parameter_tvb, chunk_tree);
1249     
1250     proto_item_set_text(chunk_item, "HEARTBEAT ACK chunk");
1251   } 
1252 }
1253
1254 static void
1255 dissect_abort_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1256                     proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1257 {
1258   guint offset, number_of_causes;
1259   guint16 length, padding_length, total_length;
1260   tvbuff_t *cause_tvb;
1261   
1262   if (check_col(pinfo->fd, COL_INFO))
1263     col_append_str(pinfo->fd, COL_INFO, "ABORT ");
1264
1265   if (chunk_tree) {
1266     number_of_causes = 0;
1267     offset = ABORT_CHUNK_FIRST_ERROR_CAUSE_OFFSET;
1268     while(tvb_length_remaining(chunk_tvb, offset)) {
1269     length         = tvb_get_ntohs(chunk_tvb, offset + CAUSE_LENGTH_OFFSET);
1270     padding_length = nr_of_padding_bytes(length);
1271     total_length   = length + padding_length;
1272     /* create a tvb for the chunk including the padding bytes */
1273     cause_tvb      = tvb_new_subset(chunk_tvb, offset, total_length, total_length);
1274     dissect_error_cause(cause_tvb, pinfo, chunk_tree); 
1275     /* get rid of the handled parameter */
1276     offset += total_length;
1277     number_of_causes++;
1278     };
1279     
1280     proto_item_set_text(chunk_item, "Abort chunk with %u cause%s",
1281                         number_of_causes, plurality(number_of_causes, "", "s"));
1282   } 
1283 }
1284
1285 static void
1286 dissect_shutdown_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1287                        proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1288
1289   guint32 cumulative_tsn_ack;
1290  
1291   if (check_col(pinfo->fd, COL_INFO))
1292     col_append_str(pinfo->fd, COL_INFO, "SHUTDOWN ");
1293
1294   if (chunk_tree) {
1295     cumulative_tsn_ack = tvb_get_ntohl(chunk_tvb, SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
1296     proto_tree_add_uint(chunk_tree, hf_sctp_shutdown_chunk_cumulative_tsn_ack, 
1297                         chunk_tvb,
1298                         SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET,
1299                         SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_LENGTH,
1300                         cumulative_tsn_ack);
1301     
1302     proto_item_set_text(chunk_item, "SHUTDOWN chunk acknowledging up to TSN %u",
1303                         cumulative_tsn_ack);
1304   } 
1305 }
1306
1307 static void
1308 dissect_shutdown_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1309                            proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1310
1311   if (check_col(pinfo->fd, COL_INFO))
1312     col_append_str(pinfo->fd, COL_INFO, "SHUTDOWN_ACK ");
1313
1314   if (chunk_tree) {
1315     proto_item_set_text(chunk_item, "SHUTDOWN ACK chunk");
1316   } 
1317 }
1318
1319 static void
1320 dissect_error_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1321                     proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1322
1323   guint offset, number_of_causes;
1324   guint16 length, padding_length, total_length;
1325   tvbuff_t *cause_tvb;
1326   
1327   if (check_col(pinfo->fd, COL_INFO))
1328     col_append_str(pinfo->fd, COL_INFO, "ERROR ");
1329
1330   if (chunk_tree) {
1331     number_of_causes = 0;
1332     offset = ERROR_CHUNK_FIRST_ERROR_CAUSE_OFFSET;
1333     do {
1334       length         = tvb_get_ntohs(chunk_tvb, offset + CAUSE_LENGTH_OFFSET);
1335       padding_length = nr_of_padding_bytes(length);
1336       total_length   = length + padding_length;
1337       /* create a tvb for the chunk including the padding bytes */
1338       cause_tvb      = tvb_new_subset(chunk_tvb, offset, total_length, total_length);
1339       dissect_error_cause(cause_tvb, pinfo, chunk_tree); 
1340       /* get rid of the handled parameter */
1341       offset += total_length;
1342       number_of_causes++;
1343     } while(tvb_length_remaining(chunk_tvb, offset));
1344     
1345     proto_item_set_text(chunk_item, "Error chunk with %u cause%s",
1346                         number_of_causes, plurality(number_of_causes, "", "s"));
1347   } 
1348 }
1349
1350 static void
1351 dissect_cookie_echo_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1352                           proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1353
1354   guint length, cookie_length, padding_length;
1355
1356   length         = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1357   padding_length = nr_of_padding_bytes(length);
1358   cookie_length  = length - CHUNK_HEADER_LENGTH;
1359  
1360   if (check_col(pinfo->fd, COL_INFO))
1361     col_append_str(pinfo->fd, COL_INFO, "COOKIE_ECHO ");
1362
1363   if (chunk_tree) {  
1364     proto_tree_add_text(chunk_tree, chunk_tvb, COOKIE_ECHO_CHUNK_COOKIE_OFFSET, cookie_length,
1365                         "Cookie (%u byte%s)",
1366                         cookie_length, plurality(cookie_length, "", "s"));
1367     proto_item_set_text(chunk_item, "COOKIE ECHO chunk containing a cookie of %u byte%s",
1368                         cookie_length, plurality(cookie_length, "", "s"));
1369     
1370     if (padding_length > 0)
1371       proto_tree_add_text(chunk_tree, chunk_tvb, CHUNK_HEADER_OFFSET + length, padding_length,
1372                           "Padding: %u byte%s",
1373                           padding_length, plurality(padding_length, "", "s"));
1374   } 
1375 }
1376
1377 static void
1378 dissect_cookie_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1379                          proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1380 {  
1381   if (check_col(pinfo->fd, COL_INFO))
1382     col_append_str(pinfo->fd, COL_INFO, "COOKIE_ACK ");
1383
1384   if (chunk_tree) {
1385     proto_item_set_text(chunk_item, "COOKIE ACK chunk");
1386   } 
1387 }
1388
1389 static void
1390 dissect_ecne_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1391                    proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1392
1393   guint32 lowest_tsn;
1394  
1395   if (check_col(pinfo->fd, COL_INFO))
1396     col_append_str(pinfo->fd, COL_INFO, "ECNE ");
1397
1398   if (chunk_tree) {
1399     lowest_tsn = tvb_get_ntohl(chunk_tvb, ECNE_CHUNK_LOWEST_TSN_OFFSET);
1400     proto_tree_add_uint(chunk_tree, hf_sctp_ecne_chunk_lowest_tsn, 
1401                         chunk_tvb,
1402                         ECNE_CHUNK_LOWEST_TSN_OFFSET, ECNE_CHUNK_LOWEST_TSN_LENGTH,
1403                         lowest_tsn);
1404     
1405     proto_item_set_text(chunk_item, "ECNE chunk");
1406   } 
1407 }
1408
1409 static void
1410 dissect_cwr_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1411                   proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1412
1413   guint32 lowest_tsn;
1414   
1415   if (check_col(pinfo->fd, COL_INFO))
1416     col_append_str(pinfo->fd, COL_INFO, "CWR ");
1417
1418   if (chunk_tree) {
1419     lowest_tsn = tvb_get_ntohl(chunk_tvb, CWR_CHUNK_LOWEST_TSN_OFFSET);
1420     proto_tree_add_uint(chunk_tree, hf_sctp_cwr_chunk_lowest_tsn, 
1421                         chunk_tvb,
1422                         CWR_CHUNK_LOWEST_TSN_OFFSET, CWR_CHUNK_LOWEST_TSN_LENGTH,
1423                         lowest_tsn);
1424     
1425     proto_item_set_text(chunk_item, "CWR chunk");
1426   } 
1427 }
1428
1429 static void
1430 dissect_shutdown_complete_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1431                                 proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1432
1433   guint8  flags;
1434   guint16 length;
1435   proto_tree *flag_tree;
1436  
1437   if (check_col(pinfo->fd, COL_INFO))
1438     col_append_str(pinfo->fd, COL_INFO, "SHUTDOWN_COMPLETE ");
1439
1440   if (chunk_tree) {
1441     flags             = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
1442     length            = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1443     
1444     flag_tree = proto_item_add_subtree(flags_item, ett_sctp_data_chunk_flags);
1445     proto_tree_add_boolean(flag_tree, hf_sctp_shutdown_complete_chunk_t_bit, chunk_tvb,
1446                            CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
1447     
1448     proto_item_set_text(chunk_item, "SHUTDOWN COMPLETE chunk");
1449   } 
1450 }
1451
1452 static void
1453 dissect_unknown_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1454                       proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1455
1456   guint length, chunk_value_length, padding_length;
1457   guint8 type;
1458   
1459   if (check_col(pinfo->fd, COL_INFO))
1460     col_append_str(pinfo->fd, COL_INFO, "UNKNOWN ");
1461
1462   if (chunk_tree) {
1463     length         = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1464     padding_length = nr_of_padding_bytes(length);
1465     type           = tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET);
1466     
1467     chunk_value_length = length - CHUNK_HEADER_LENGTH;
1468     
1469     proto_tree_add_text(chunk_tree, chunk_tvb, CHUNK_VALUE_OFFSET, chunk_value_length,
1470                         "Chunk value (%u byte%s)",
1471                         chunk_value_length, plurality(chunk_value_length, "", "s"));
1472     
1473     if (padding_length > 0)
1474       proto_tree_add_text(chunk_tree, chunk_tvb, CHUNK_HEADER_OFFSET + length, padding_length,
1475                           "Padding: %u byte%s",
1476                           padding_length, plurality(padding_length, "", "s"));
1477     
1478     proto_item_set_text(chunk_item, "Chunk of type %u and %u byte%s value",
1479                         type, chunk_value_length, plurality(chunk_value_length, "", "s"));
1480   }
1481
1482
1483
1484 static gboolean
1485 dissect_sctp_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *sctp_tree)
1486 {  
1487   guint8 type, flags;
1488   guint16 length;
1489   gboolean result;
1490   proto_item *flags_item;
1491   proto_item *chunk_item;
1492   proto_tree *chunk_tree;
1493
1494   result = FALSE;
1495   
1496   /* first extract the chunk header */
1497   type   = tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET);
1498   flags  = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
1499   length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1500  
1501   if (tree) {
1502     /* create proto_tree stuff */
1503     chunk_item   = proto_tree_add_text(sctp_tree, chunk_tvb,
1504                                        CHUNK_HEADER_OFFSET, tvb_length(chunk_tvb), "Incomplete chunk");
1505     chunk_tree   = proto_item_add_subtree(chunk_item, ett_sctp_chunk);
1506     
1507     /* then insert the chunk header components into the protocol tree */
1508     proto_tree_add_uint(chunk_tree, hf_sctp_chunk_type, 
1509                         chunk_tvb, CHUNK_TYPE_OFFSET, CHUNK_TYPE_LENGTH,
1510                         type);
1511     flags_item = proto_tree_add_uint(chunk_tree, hf_sctp_chunk_flags, 
1512                                      chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH,
1513                                      flags);
1514     proto_tree_add_uint(chunk_tree, hf_sctp_chunk_length, 
1515                         chunk_tvb, CHUNK_LENGTH_OFFSET, CHUNK_LENGTH_LENGTH,
1516                         length);
1517   } else {
1518     chunk_tree = NULL;
1519     chunk_item = NULL;
1520     flags_item = NULL;
1521   };
1522   
1523   /* now dissect the chunk value */
1524
1525   switch(type) {
1526   case SCTP_DATA_CHUNK_ID:
1527     result = dissect_data_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1528     break;
1529   case SCTP_INIT_CHUNK_ID:
1530     dissect_init_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1531     break;
1532   case SCTP_INIT_ACK_CHUNK_ID:
1533     dissect_init_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1534     break;
1535   case SCTP_SACK_CHUNK_ID:
1536     dissect_sack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1537     break; 
1538   case SCTP_HEARTBEAT_CHUNK_ID:
1539     dissect_heartbeat_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1540     break;
1541   case SCTP_HEARTBEAT_ACK_CHUNK_ID:
1542     dissect_heartbeat_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1543     break;
1544   case SCTP_ABORT_CHUNK_ID:
1545     dissect_abort_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1546     break;
1547   case SCTP_SHUTDOWN_CHUNK_ID:
1548     dissect_shutdown_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1549     break;
1550   case SCTP_SHUTDOWN_ACK_CHUNK_ID:
1551     dissect_shutdown_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1552     break;
1553   case SCTP_ERROR_CHUNK_ID:
1554     dissect_error_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1555     break;
1556   case SCTP_COOKIE_ECHO_CHUNK_ID:
1557     dissect_cookie_echo_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1558     break;
1559   case SCTP_COOKIE_ACK_CHUNK_ID:
1560     dissect_cookie_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1561     break;
1562   case SCTP_ECNE_CHUNK_ID:
1563     dissect_ecne_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1564     break;
1565   case SCTP_CWR_CHUNK_ID:
1566     dissect_cwr_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1567     break;
1568   case SCTP_SHUTDOWN_COMPLETE_CHUNK_ID:
1569     dissect_shutdown_complete_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1570       break;
1571   default:
1572     dissect_unknown_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1573     break;
1574   };
1575   return result;
1576 }
1577
1578 static void
1579 dissect_sctp_chunks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1580                     proto_item *sctp_item, proto_tree *sctp_tree)
1581
1582   tvbuff_t *chunk_tvb;
1583   guint16 length, padding_length, total_length;
1584   gint last_offset, offset;
1585   gboolean sctp_item_length_set;
1586
1587   /* the common header of the datagram is already handled */
1588   last_offset = 0;
1589   offset = COMMON_HEADER_LENGTH;
1590   sctp_item_length_set = FALSE;
1591
1592   while(tvb_length_remaining(tvb, offset) > 0) {
1593     /* extract the chunk length and compute number of padding bytes */
1594     length         = tvb_get_ntohs(tvb, offset + CHUNK_LENGTH_OFFSET);
1595     padding_length = nr_of_padding_bytes(length);
1596     total_length   = length + padding_length;
1597     /* create a tvb for the chunk including the padding bytes */
1598     chunk_tvb    = tvb_new_subset(tvb, offset, total_length, total_length);
1599     /* call dissect_sctp_chunk for a actual work */
1600     if (dissect_sctp_chunk(chunk_tvb, pinfo, tree, sctp_tree) && (tree)) {
1601       proto_item_set_len(sctp_item, offset - last_offset + DATA_CHUNK_HEADER_LENGTH);
1602       sctp_item_length_set = TRUE;
1603       offset += total_length;
1604       last_offset = offset;
1605       if (tvb_length_remaining(tvb, offset) > 0) {
1606         sctp_item = proto_tree_add_item(tree, proto_sctp, tvb, offset, 0, FALSE);
1607         sctp_tree = proto_item_add_subtree(sctp_item, ett_sctp);
1608         sctp_item_length_set = FALSE;
1609       }
1610     } else {
1611     /* get rid of the dissected chunk */
1612     offset += total_length;
1613     }
1614   };
1615   if (!sctp_item_length_set && (tree)) { 
1616     proto_item_set_len(sctp_item, offset - last_offset);
1617   };
1618 }
1619
1620 /* dissect_sctp handles the common header of a SCTP datagram.
1621  * For the handling of the chunks dissect_sctp_chunks is called.
1622  */
1623
1624 static void
1625 dissect_sctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1626 {
1627   guint16 source_port, destination_port;
1628   guint32 verification_tag, checksum;
1629   proto_item *sctp_item;
1630   proto_tree *sctp_tree;
1631
1632   /* Extract the common header */
1633   source_port      = tvb_get_ntohs(tvb, SOURCE_PORT_OFFSET);
1634   destination_port = tvb_get_ntohs(tvb, DESTINATION_PORT_OFFSET);
1635   verification_tag = tvb_get_ntohl(tvb, VERIFICATION_TAG_OFFSET);
1636   checksum         = tvb_get_ntohl(tvb, CHECKSUM_OFFSET);
1637
1638   /* update pi structure */
1639   pinfo->ptype    = PT_SCTP;
1640   pinfo->srcport  = source_port;
1641   pinfo->destport = destination_port;
1642
1643   /* make entry in the Protocol column on summary display */
1644   if (check_col(pinfo->fd, COL_PROTOCOL)) 
1645     col_set_str(pinfo->fd, COL_PROTOCOL, "SCTP");
1646
1647   /* Clear entries in Info column on summary display */
1648   if (check_col(pinfo->fd, COL_INFO))
1649     col_add_str(pinfo->fd, COL_INFO, "");
1650   
1651   /* In the interest of speed, if "tree" is NULL, don't do any work not
1652      necessary to generate protocol tree items. */
1653   if (tree) {
1654     /* create the sctp protocol tree */
1655     sctp_item = proto_tree_add_item(tree, proto_sctp, tvb, 0, 0, FALSE);
1656     sctp_tree = proto_item_add_subtree(sctp_item, ett_sctp);
1657
1658     /* add the components of the common header to the protocol tree */
1659     proto_tree_add_uint(sctp_tree, hf_sctp_source_port, 
1660                         tvb, SOURCE_PORT_OFFSET, SOURCE_PORT_LENGTH,
1661                         source_port);
1662     proto_tree_add_uint(sctp_tree, hf_sctp_destination_port,
1663                         tvb, DESTINATION_PORT_OFFSET, DESTINATION_PORT_LENGTH,
1664                         destination_port);
1665     proto_tree_add_uint(sctp_tree, hf_sctp_verification_tag,
1666                         tvb, VERIFICATION_TAG_OFFSET, VERIFICATION_TAG_LENGTH,
1667                         verification_tag);
1668     proto_tree_add_uint_format(sctp_tree, hf_sctp_checksum,
1669                                tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, checksum,
1670                                "Adler-32 checksum: 0x%08x (%s)",
1671                                checksum, sctp_checksum_state(tvb, checksum));
1672   } else {
1673     sctp_tree = NULL;
1674     sctp_item = NULL;
1675   };
1676   /* add all chunks of the sctp datagram to the protocol tree */
1677   dissect_sctp_chunks(tvb, pinfo, tree, sctp_item, sctp_tree);
1678 }
1679
1680 /* Register the protocol with Ethereal */
1681 void
1682 proto_register_sctp(void)
1683 {                 
1684
1685   /* Setup list of header fields */
1686   static hf_register_info hf[] = {
1687     { &hf_sctp_source_port,
1688       { "Source port", "sctp.srcport",
1689         FT_UINT16, BASE_DEC, NULL, 0x0,          
1690         "", HFILL }
1691     },
1692     { &hf_sctp_destination_port,
1693       { "Destination port", "sctp.dstport",
1694         FT_UINT16, BASE_DEC, NULL, 0x0,          
1695         "", HFILL }
1696     }, 
1697     { &hf_sctp_verification_tag,
1698       { "Verification tag", "sctp.verfication_tag",
1699         FT_UINT32, BASE_HEX, NULL, 0x0,          
1700         "", HFILL }
1701     },
1702     { &hf_sctp_checksum,
1703       { "Adler-32 checksum", "sctp.checksum",
1704         FT_UINT32, BASE_HEX, NULL, 0x0,          
1705         "", HFILL }
1706     },
1707     { &hf_sctp_chunk_type,
1708       { "Identifier", "sctp.chunk_type",
1709         FT_UINT8, BASE_DEC, VALS(sctp_chunk_type_values), 0x0,          
1710         "", HFILL }
1711     },
1712     { &hf_sctp_chunk_flags,
1713       { "Flags", "sctp.chunk_flags",
1714         FT_UINT8, BASE_BIN, NULL, 0x0,          
1715         "", HFILL }
1716     },
1717     { &hf_sctp_chunk_length,
1718       { "Length", "sctp.chunk_length",
1719         FT_UINT16, BASE_DEC, NULL, 0x0,          
1720         "", HFILL }
1721     },
1722     { &hf_sctp_init_chunk_initiate_tag,
1723       { "Initiate tag", "sctp.init.chunk.initiate.tag",
1724         FT_UINT32, BASE_HEX, NULL, 0x0,          
1725         "", HFILL }
1726     },
1727     { &hf_sctp_init_chunk_adv_rec_window_credit,
1728       { "Advertised reciever window credit (a_rwnd)", "sctp.init.chunk.credit",
1729         FT_UINT32, BASE_DEC, NULL, 0x0,          
1730         "", HFILL }
1731     },
1732     { &hf_sctp_init_chunk_number_of_outbound_streams,
1733       { "Number of outbound streams", "sctp.init.chunk.nr.out.streams",
1734         FT_UINT16, BASE_DEC, NULL, 0x0,          
1735         "", HFILL }
1736     },
1737     { &hf_sctp_init_chunk_number_of_inbound_streams,
1738       { "Number of inbound streams", "sctp.init.chunk.nr.in.streams",
1739         FT_UINT16, BASE_DEC, NULL, 0x0,          
1740         "", HFILL }
1741     },
1742     {&hf_sctp_init_chunk_initial_tsn,
1743       { "Initial TSN", "sctp.init.chunk.initial.tsn",
1744         FT_UINT32, BASE_DEC, NULL, 0x0,          
1745         "", HFILL }
1746     }, 
1747     {&hf_sctp_cumulative_tsn_ack,
1748      { "Cumulative TSN Ack", "sctp.cumulative.tsn.ack",
1749         FT_UINT32, BASE_DEC, NULL, 0x0,          
1750         "", HFILL }
1751     },
1752     {&hf_sctp_data_chunk_tsn,
1753      { "TSN", "sctp.tsn",
1754        FT_UINT32, BASE_DEC, NULL, 0x0,          
1755         "", HFILL }
1756     },
1757     {&hf_sctp_data_chunk_stream_id,
1758      { "Stream Identifier", "sctp.stream_id",
1759         FT_UINT16, BASE_HEX, NULL, 0x0,          
1760         "", HFILL }
1761     },
1762     {&hf_sctp_data_chunk_stream_seq_number,
1763      { "Stream sequence number", "sctp.stream_seq_number",
1764        FT_UINT16, BASE_DEC, NULL, 0x0,          
1765        "", HFILL }
1766     },
1767     {&hf_sctp_data_chunk_payload_proto_id,
1768      { "Payload protocol identifier", "sctp.payload_proto_id",
1769         FT_UINT32, BASE_DEC, VALS(sctp_payload_proto_id_values), 0x0,          
1770         "", HFILL }
1771     },
1772     {&hf_sctp_data_chunk_e_bit,
1773      { "E-Bit", "sctp.data.e_bit",
1774        FT_BOOLEAN, 8, TFS(&sctp_data_chunk_e_bit_value), SCTP_DATA_CHUNK_E_BIT,          
1775        "", HFILL }
1776     },
1777     {&hf_sctp_data_chunk_b_bit,
1778      { "B-Bit", "sctp.data.b_bit",
1779        FT_BOOLEAN, 8, TFS(&sctp_data_chunk_b_bit_value), SCTP_DATA_CHUNK_B_BIT,          
1780        "", HFILL }
1781     },
1782     {&hf_sctp_data_chunk_u_bit,
1783      { "U-Bit", "sctp.data.u.bit",
1784        FT_BOOLEAN, 8, TFS(&sctp_data_chunk_u_bit_value), SCTP_DATA_CHUNK_U_BIT,          
1785        "", HFILL }
1786     },
1787     {&hf_sctp_sack_chunk_cumulative_tsn_ack,
1788      { "Cumulative TSN ACK", "sctp.sack.cumulative_tsn_ack",
1789        FT_UINT32, BASE_DEC, NULL, 0x0,          
1790        "", HFILL }
1791     }, 
1792     {&hf_sctp_sack_chunk_adv_rec_window_credit,
1793      { "Advertised receiver window credit (a_rwnd)", "sctp.sack.a_rwnd",
1794        FT_UINT32, BASE_DEC, NULL, 0x0,          
1795        "", HFILL }
1796     },
1797     {&hf_sctp_sack_chunk_number_of_gap_blocks,
1798      { "Number of gap acknowldgement blocks ", "sctp.sack.number_of_gap_blocks",
1799        FT_UINT16, BASE_DEC, NULL, 0x0,          
1800        "", HFILL }
1801     }, 
1802     {&hf_sctp_sack_chunk_number_of_dup_tsns,
1803      { "Number of duplicated TSNs", "sctp.sack.number_of_duplicated_tsns",
1804        FT_UINT16, BASE_DEC, NULL, 0x0,          
1805        "", HFILL }
1806     },
1807     {&hf_sctp_sack_chunk_gap_block_start,
1808      { "Start", "sctp.sack.gap_block_start",
1809        FT_UINT16, BASE_DEC, NULL, 0x0,          
1810        "", HFILL }
1811     },
1812     {&hf_sctp_sack_chunk_gap_block_end,
1813      { "End", "sctp.sack.gap_block_end",
1814        FT_UINT16, BASE_DEC, NULL, 0x0,          
1815        "", HFILL }
1816     },
1817     {&hf_sctp_sack_chunk_duplicate_tsn,
1818      { "Duplicate TSN", "sctp.sack.duplicate.tsn",
1819        FT_UINT16, BASE_DEC, NULL, 0x0,          
1820        "", HFILL }
1821     },  
1822     {&hf_sctp_shutdown_chunk_cumulative_tsn_ack,
1823      { "Cumulative TSN Ack", "sctp.shutdown.cumulative_tsn_ack",
1824         FT_UINT32, BASE_DEC, NULL, 0x0,          
1825         "", HFILL }
1826     },
1827     {&hf_sctp_ecne_chunk_lowest_tsn,
1828      { "Lowest TSN", "sctp.ecne.lowest_tsn",
1829        FT_UINT32, BASE_DEC, NULL, 0x0,          
1830        "", HFILL }
1831     }, 
1832     {&hf_sctp_cwr_chunk_lowest_tsn,
1833      { "Lowest TSN", "sctp.cwr.lowest_tsn",
1834        FT_UINT32, BASE_DEC, NULL, 0x0,          
1835        "", HFILL }
1836     }, 
1837     {&hf_sctp_shutdown_complete_chunk_t_bit,
1838      { "E-Bit", "sctp.shutdown_complete.t_bit",
1839        FT_BOOLEAN, 8, TFS(&sctp_shutdown_complete_chunk_t_bit_value), SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT,
1840        "", HFILL }
1841     },
1842     {&hf_sctp_chunk_parameter_type,
1843      { "Parameter type", "sctp.parameter.type",
1844        FT_UINT16, BASE_HEX, VALS(sctp_parameter_identifier_values), 0x0,
1845        "", HFILL }
1846     },
1847     {&hf_sctp_chunk_parameter_length,
1848      { "Parameter length", "sctp.parameter.length",
1849        FT_UINT16, BASE_DEC, NULL, 0x0,          
1850        "", HFILL }
1851     },
1852     {&hf_sctp_parameter_ipv4_address,
1853      { "IP Version 4 address", "sctp.parameter.ipv4_address",
1854        FT_IPv4, BASE_NONE, NULL, 0x0,
1855        "", HFILL }
1856     },
1857     {&hf_sctp_parameter_ipv6_address,
1858      { "IP Version 6 address", "sctp.parameter.ipv6_address",
1859        FT_IPv6, BASE_NONE, NULL, 0x0,
1860        "", HFILL }
1861     },
1862     {&hf_sctp_parameter_cookie_preservative_increment,
1863      { "Suggested Cookie life-span increment (msec)", "sctp.parameter.cookie_preservative_incr",
1864        FT_UINT32, BASE_DEC, NULL, 0x0,          
1865        "", HFILL }
1866     },
1867     {&hf_sctp_parameter_hostname_hostname,
1868      { "Hostname", "sctp.parameter.hostname.hostname",
1869        FT_STRING, BASE_NONE, NULL, 0x0,          
1870        "", HFILL }
1871     }, 
1872     {&hf_sctp_supported_address_types_parameter,
1873      { "Supported address type", "sctp.parameter.supported_addres_type",
1874        FT_UINT16, BASE_DEC, NULL, 0x0,          
1875        "", HFILL }
1876     }, 
1877     {&hf_sctp_cause_code,
1878      { "Cause code", "sctp.cause.code",
1879        FT_UINT16, BASE_HEX, VALS(sctp_cause_code_values), 0x0,          
1880        "", HFILL }
1881     },
1882     {&hf_sctp_cause_length,
1883      { "Cause length", "sctp.cause.length",
1884        FT_UINT16, BASE_DEC, NULL, 0x0,          
1885        "", HFILL }
1886     }, 
1887     {&hf_sctp_cause_stream_identifier,
1888      { "Stream identifier", "sctp.cause.stream_identifier",
1889        FT_UINT16, BASE_DEC, NULL, 0x0,          
1890        "", HFILL }
1891     },
1892     {&hf_sctp_cause_number_of_missing_parameters,
1893      { "Number of missing parameters", "sctp.cause.nr_of_missing_parameters",
1894        FT_UINT32, BASE_DEC, NULL, 0x0,          
1895        "", HFILL }
1896     }, 
1897     {&hf_sctp_cause_missing_parameter_type,
1898      { "Missing parameter type", "sctp.cause.missing_parameter_type",
1899        FT_UINT16, BASE_HEX, VALS(sctp_parameter_identifier_values), 0x0,
1900        "", HFILL }
1901     },
1902     {&hf_sctp_cause_measure_of_staleness,
1903      { "Measure of staleness in usec", "sctp.cause.measure_of_staleness",
1904        FT_UINT32, BASE_DEC, NULL, 0x0,          
1905        "", HFILL }
1906     },
1907     {&hf_sctp_cause_tsn,
1908      { "TSN", "sctp.cause.tsn",
1909        FT_UINT32, BASE_DEC, NULL, 0x0,          
1910        "", HFILL }
1911     },
1912   };
1913   
1914   /* Setup protocol subtree array */
1915   static gint *ett[] = {
1916     &ett_sctp,
1917     &ett_sctp_chunk,
1918     &ett_sctp_chunk_parameter,
1919     &ett_sctp_chunk_cause,
1920     &ett_sctp_data_chunk_flags,
1921     &ett_sctp_sack_chunk_gap_block,
1922     &ett_sctp_supported_address_types_parameter,
1923     &ett_sctp_unrecognized_parameter_parameter
1924   };
1925   
1926   /* Register the protocol name and description */
1927   proto_sctp = proto_register_protocol("Stream Control Transmission Protocol",
1928                                        "SCTP", "sctp");
1929   
1930   /* Required function calls to register the header fields and subtrees used */
1931   proto_register_field_array(proto_sctp, hf, array_length(hf));
1932   proto_register_subtree_array(ett, array_length(ett));
1933
1934   /* subdissector code */
1935   sctp_port_dissector_table = register_dissector_table("sctp.port");
1936   sctp_ppi_dissector_table  = register_dissector_table("sctp.ppi");
1937
1938 };
1939
1940 void
1941 proto_reg_handoff_sctp(void)
1942 {
1943         dissector_add("ip.proto", IP_PROTO_SCTP, dissect_sctp, proto_sctp);
1944 }