Support for dissectors registering themselves with a particular SCTP
[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.11 2001/01/13 04:30:20 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@unicom.net>
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 "packet-ip.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 idetifier" },
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 void
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, parameter_value_length;
579   tvbuff_t *unrecognized_parameters_tvb;
580
581   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
582   
583   parameter_value_length = length - PARAMETER_HEADER_LENGTH;
584
585   unrecognized_parameters_tvb = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, 
586                                                parameter_value_length, parameter_value_length);
587   dissect_tlv_parameter_list(unrecognized_parameters_tvb, parameter_tree);
588    
589   proto_item_set_text(parameter_item, "Unrecognized parameter of type");
590 }
591
592 static void
593 dissect_cookie_preservative_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
594 {
595   guint32 increment;
596
597   increment =  tvb_get_ntohl(parameter_tvb, COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET);
598   
599   proto_tree_add_uint(parameter_tree, hf_sctp_parameter_cookie_preservative_increment, parameter_tvb, 
600                       COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET, 
601                       COOKIE_PRESERVATIVE_PARAMETER_INCR_LENGTH,
602                       increment);
603   
604   proto_item_set_text(parameter_item, "Cookie preservative parameter requesting for a %u msec increment",
605                       increment);
606 }
607
608 static void
609 dissect_hostname_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
610 {
611   guint16  length, hostname_length;
612   char *hostname;
613
614   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
615   
616   hostname_length = length - PARAMETER_HEADER_LENGTH;
617   hostname = (char *)tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, hostname_length);
618   proto_tree_add_string(parameter_tree, hf_sctp_parameter_hostname_hostname, parameter_tvb,
619                         PARAMETER_VALUE_OFFSET, hostname_length,
620                         hostname);
621
622   proto_item_set_text(parameter_item, "Hostname parameter");
623 }
624
625 static void
626 dissect_supported_address_types_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
627 {
628   guint16 length, address_type, number_of_address_types, address_type_number, list_of_address_types_length ;
629   guint offset;
630   proto_item *address_list_item;
631   proto_tree *address_list_tree;
632
633   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
634   list_of_address_types_length = length - PARAMETER_HEADER_LENGTH;
635   number_of_address_types = list_of_address_types_length / SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH;
636
637   address_list_item = proto_tree_add_text(parameter_tree, parameter_tvb, PARAMETER_VALUE_OFFSET, list_of_address_types_length,
638                                           "Supported Address Types (%u address type%s)",
639                                           number_of_address_types, plurality(number_of_address_types, "", "s"));
640   address_list_tree = proto_item_add_subtree(address_list_item, ett_sctp_supported_address_types_parameter);
641  
642   offset = PARAMETER_VALUE_OFFSET;
643   for(address_type_number = 1; address_type_number <= number_of_address_types; address_type_number++) {
644     address_type = tvb_get_ntohs(parameter_tvb, offset);
645     proto_tree_add_uint_format(address_list_tree, hf_sctp_supported_address_types_parameter,
646                                parameter_tvb, offset, SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH,
647                                address_type, "Supported address type: %u (%s)",
648                                address_type, val_to_str(address_type, sctp_parameter_identifier_values, "unknown"));
649     offset += SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH;
650   };
651
652   proto_item_set_text(parameter_item, "Supported address types parameter reporting %u address type%s",
653                       number_of_address_types, plurality(number_of_address_types, "", "s"));
654 }
655
656 static void
657 dissect_ecn_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
658 {
659    proto_item_set_text(parameter_item, "ECN parameter");
660 }
661
662 static void
663 dissect_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
664 {
665   guint16 type, length, parameter_value_length;
666   
667   type   = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
668   length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
669   
670   parameter_value_length = length - PARAMETER_HEADER_LENGTH;
671
672   proto_tree_add_text(parameter_tree, parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length,
673                       "Parameter value (%u byte%s)",
674                       parameter_value_length, plurality(parameter_value_length, "", "s"));
675
676   proto_item_set_text(parameter_item, "Parameter of type %u and %u byte%s value",
677                       type, parameter_value_length, plurality(parameter_value_length, "", "s"));
678 }
679
680 static void
681 dissect_parameter(tvbuff_t *parameter_tvb, proto_tree *chunk_tree)
682 {
683   guint16 type, length, padding_length, total_length;
684   proto_item *parameter_item;
685   proto_tree *parameter_tree;
686
687   type           = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
688   length         = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
689   padding_length = nr_of_padding_bytes(length);
690   total_length   = length + padding_length;
691    
692   parameter_item = proto_tree_add_notext(chunk_tree, parameter_tvb, PARAMETER_HEADER_OFFSET, total_length);
693   parameter_tree = proto_item_add_subtree(parameter_item, ett_sctp_chunk_parameter);
694  
695   proto_tree_add_uint_format(parameter_tree, hf_sctp_chunk_parameter_type, 
696                              parameter_tvb, PARAMETER_TYPE_OFFSET, PARAMETER_TYPE_LENGTH,
697                              type, "Parameter type: %u (%s)",
698                              type, val_to_str(type, sctp_parameter_identifier_values, "unknown"));
699   proto_tree_add_uint(parameter_tree, hf_sctp_chunk_parameter_length, 
700                       parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH,
701                       length);
702  
703   switch(type) {
704   case HEARTBEAT_INFO_PARAMETER_ID:
705     dissect_heartbeat_info_parameter(parameter_tvb, parameter_tree, parameter_item);
706     break;
707   case IPV4ADDRESS_PARAMETER_ID:
708     dissect_ipv4_parameter(parameter_tvb, parameter_tree, parameter_item);
709     break;
710   case IPV6ADDRESS_PARAMETER_ID:
711     dissect_ipv6_parameter(parameter_tvb, parameter_tree, parameter_item);
712     break;
713   case STATE_COOKIE_PARAMETER_ID:
714     dissect_state_cookie_parameter(parameter_tvb, parameter_tree, parameter_item);
715     break;
716   case UNREC_PARA_PARAMETER_ID:
717     dissect_unrecognized_parameters_parameter(parameter_tvb, parameter_tree, parameter_item);
718     break;
719   case COOKIE_PRESERVATIVE_PARAMETER_ID:
720     dissect_cookie_preservative_parameter(parameter_tvb, parameter_tree, parameter_item);
721     break;
722   case HOSTNAME_ADDRESS_PARAMETER_ID:
723     dissect_hostname_parameter(parameter_tvb, parameter_tree, parameter_item);
724     break;
725   case SUPPORTED_ADDRESS_TYPES_PARAMETER_ID:
726     dissect_supported_address_types_parameter(parameter_tvb, parameter_tree, parameter_item);
727     break;
728   case ECN_PARAMETER_ID:
729     dissect_ecn_parameter(parameter_tvb, parameter_tree, parameter_item);
730     break;
731   default:
732     dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
733     break;
734   };
735   if (padding_length > 0)
736     proto_tree_add_text(parameter_tree, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length,
737                         "Padding: %u byte%s",
738                         padding_length, plurality(padding_length, "", "s"));
739 }
740
741 /*
742  * Code to handle error causes for ABORT and ERROR chunks
743  */
744 static void
745 dissect_invalid_stream_identifier_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
746 {
747   guint16 stream_identifier;
748
749   stream_identifier   = tvb_get_ntohs(cause_tvb, CAUSE_STREAM_IDENTIFIER_OFFSET);
750   proto_tree_add_uint(cause_tree, hf_sctp_cause_stream_identifier, 
751                       cause_tvb, CAUSE_STREAM_IDENTIFIER_OFFSET, CAUSE_STREAM_IDENTIFIER_LENGTH,
752                       stream_identifier);
753   proto_tree_add_text(cause_tree, cause_tvb, CAUSE_RESERVED_OFFSET, CAUSE_RESERVED_LENGTH,
754                       "Reserved (2 bytes)");
755
756   proto_item_set_text(cause_item, "Error cause reporting invalid stream identifier %u",
757                       stream_identifier);
758 }
759
760 static void
761 dissect_missing_mandatory_parameters_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
762 {
763   guint32 number_of_missing_parameters, missing_parameter_number;
764   guint16 parameter_type;
765   guint   offset;
766
767   number_of_missing_parameters = tvb_get_ntohl(cause_tvb, CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET);
768   proto_tree_add_uint(cause_tree, hf_sctp_cause_number_of_missing_parameters, 
769                       cause_tvb, CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET, CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH,
770                       number_of_missing_parameters);
771   offset = CAUSE_FIRST_MISSING_PARAMETER_TYPE_OFFSET;
772   for(missing_parameter_number = 1; missing_parameter_number <= number_of_missing_parameters; missing_parameter_number++) {
773     parameter_type = tvb_get_ntohs(cause_tvb, offset);
774     proto_tree_add_uint_format(cause_tree, hf_sctp_cause_missing_parameter_type,
775                                cause_tvb, offset, CAUSE_MISSING_PARAMETER_TYPE_LENGTH,
776                                parameter_type, "Missing parameter type: %u (%s)",
777                                parameter_type, 
778                                val_to_str(parameter_type, sctp_parameter_identifier_values, "unknown"));
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 %u (%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, cause_info_length;
861   tvbuff_t *unrecognized_parameters_tvb;
862
863   length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
864   
865   cause_info_length = length - CAUSE_HEADER_LENGTH;
866
867   unrecognized_parameters_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, 
868                                                cause_info_length, cause_info_length);
869   dissect_tlv_parameter_list(unrecognized_parameters_tvb, cause_tree);
870  
871   proto_item_set_text(cause_item, "Error cause reporting unrecognized parameters");
872 }
873
874 static void
875 dissect_no_user_data_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
876 {
877   guint32 tsn;
878
879   tsn = tvb_get_ntohl(cause_tvb, CAUSE_TSN_OFFSET);
880   proto_tree_add_uint(cause_tree, hf_sctp_cause_tsn, cause_tvb, 
881                       CAUSE_TSN_OFFSET, 
882                       CAUSE_TSN_LENGTH,
883                       tsn);
884
885   proto_item_set_text(cause_item, "Error cause reporting data chunk with TSN %u contains no data",
886                       tsn);
887 }
888
889 static void
890 dissect_cookie_received_while_shutting_down_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
891 {
892   proto_item_set_text(cause_item, "Error cause reporting cookie reception while shutting down");
893 }
894
895 static void
896 dissect_unknown_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
897 {
898   guint16 code, length, cause_info_length;
899
900   code   = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET);
901   length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
902   
903   cause_info_length = length - CAUSE_HEADER_LENGTH;
904
905   proto_tree_add_text(cause_tree, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length,
906                       "Cause specific information (%u byte%s)",
907                       cause_info_length, plurality(cause_info_length, "", "s"));
908
909   proto_item_set_text(cause_item, "Error cause with code %u and %u byte%s information",
910                       code, cause_info_length, plurality(cause_info_length, "", "s"));
911 }
912
913 static void
914 dissect_error_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *chunk_tree)
915 {
916   guint16 code, length, padding_length, total_length;
917   proto_item *cause_item;
918   proto_tree *cause_tree;
919
920   code           = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET);
921   length         = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
922   padding_length = nr_of_padding_bytes(length);
923   total_length   = length + padding_length;
924   
925   cause_item = proto_tree_add_notext(chunk_tree, cause_tvb, CAUSE_HEADER_OFFSET, total_length);
926   proto_item_set_text(cause_item, "BAD ERROR CAUSE");
927   cause_tree = proto_item_add_subtree(cause_item, ett_sctp_chunk_cause);
928  
929   proto_tree_add_uint_format(cause_tree, hf_sctp_cause_code, 
930                              cause_tvb, CAUSE_CODE_OFFSET, CAUSE_CODE_LENGTH,
931                              code, "Cause code: %u (%s)",
932                              code, val_to_str(code, sctp_cause_code_values, "unknown"));
933   proto_tree_add_uint(cause_tree, hf_sctp_cause_length, 
934                       cause_tvb, CAUSE_LENGTH_OFFSET, CAUSE_LENGTH_LENGTH,
935                       length);
936  
937   switch(code) {
938   case INVALID_STREAM_IDENTIFIER:
939     dissect_invalid_stream_identifier_cause(cause_tvb, cause_tree, cause_item);
940     break;
941   case MISSING_MANDATORY_PARAMETERS:
942     dissect_missing_mandatory_parameters_cause(cause_tvb, cause_tree, cause_item);
943     break;
944   case STALE_COOKIE_ERROR:
945     dissect_stale_cookie_error_cause(cause_tvb, cause_tree, cause_item);
946     break;
947   case OUT_OF_RESOURCE:
948     dissect_out_of_resource_cause(cause_tvb, cause_tree, cause_item);
949     break;
950   case UNRESOLVABLE_ADDRESS:
951     dissect_unresolvable_address_cause(cause_tvb, cause_tree, cause_item);
952     break;
953   case UNRECOGNIZED_CHUNK_TYPE:
954     dissect_unrecognized_chunk_type_cause(cause_tvb, pinfo, cause_tree, cause_item);
955     break;
956   case INVALID_MANDATORY_PARAMETER:
957     dissect_invalid_mandatory_parameter_cause(cause_tvb, cause_tree, cause_item);
958     break;
959   case UNRECOGNIZED_PARAMETERS:
960     dissect_unrecognized_parameters_cause(cause_tvb, cause_tree, cause_item);
961     break;
962   case NO_USER_DATA:
963     dissect_no_user_data_cause(cause_tvb, cause_tree, cause_item);
964     break;
965   case COOKIE_RECEIVED_WHILE_SHUTTING_DOWN:
966     dissect_cookie_received_while_shutting_down_cause(cause_tvb, cause_tree, cause_item);
967     break;
968   default:
969     dissect_unknown_cause(cause_tvb, cause_tree, cause_item);
970     break;
971   };
972   if (padding_length > 0)
973     proto_tree_add_text(cause_tree, cause_tvb, CAUSE_HEADER_OFFSET + length, padding_length,
974                         "Padding: %u byte%s",
975                         padding_length, plurality(padding_length, "", "s"));
976 }
977
978 /*
979  * Code to actually dissect the packets 
980 */
981
982 static void
983 dissect_payload(tvbuff_t *payload_tvb, packet_info *pinfo, proto_tree *tree,
984                 proto_tree *chunk_tree, guint32 ppi, guint16 payload_length, guint16 padding_length)
985 {
986   /* do lookup with the subdissector table */
987   if (dissector_try_port (sctp_ppi_dissector_table, ppi,  payload_tvb, pinfo, tree) ||
988       dissector_try_port(sctp_port_dissector_table, pi.srcport,  payload_tvb, pinfo, tree) ||
989       dissector_try_port(sctp_port_dissector_table, pi.destport, payload_tvb, pinfo, tree))
990     
991     return;
992   else {
993     if (check_col(pinfo->fd, COL_INFO))
994       col_append_str(pinfo->fd, COL_INFO, "DATA ");
995     proto_tree_add_text(chunk_tree, payload_tvb, 0, payload_length,
996                         "Payload (%u byte%s)",
997                         payload_length, plurality(payload_length, "", "s")); 
998     if (padding_length > 0)
999       proto_tree_add_text(chunk_tree, payload_tvb, payload_length, padding_length,
1000                           "Padding: %u byte%s",
1001                           padding_length, plurality(padding_length, "", "s"));
1002   }
1003 }
1004
1005 static void
1006 dissect_data_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1007                    proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1008
1009   guint8  flags;
1010   guint16 length, total_payload_length, payload_length, padding_length, stream_id, stream_seq_number;
1011   guint32 tsn, payload_proto_id;
1012   proto_tree *flag_tree;
1013   tvbuff_t *payload_tvb;
1014    
1015   length            = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1016   payload_length       = length - DATA_CHUNK_HEADER_LENGTH;
1017   padding_length       = nr_of_padding_bytes(length);
1018   total_payload_length = payload_length + padding_length;
1019   payload_tvb          = tvb_new_subset(chunk_tvb, DATA_CHUNK_PAYLOAD_OFFSET,
1020                                           total_payload_length, total_payload_length);
1021   payload_proto_id     = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET);
1022
1023   if (chunk_tree) {
1024     flags             = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
1025      
1026     flag_tree = proto_item_add_subtree(flags_item, ett_sctp_data_chunk_flags);
1027     proto_tree_add_boolean(flag_tree, hf_sctp_data_chunk_e_bit, chunk_tvb,
1028                            CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
1029     proto_tree_add_boolean(flag_tree, hf_sctp_data_chunk_b_bit, chunk_tvb,
1030                            CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
1031     proto_tree_add_boolean(flag_tree, hf_sctp_data_chunk_u_bit, chunk_tvb,
1032                            CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
1033     
1034     tsn               = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_TSN_OFFSET);
1035     stream_id         = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET);
1036     stream_seq_number = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET);
1037          
1038     proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_tsn, 
1039                         chunk_tvb,
1040                         DATA_CHUNK_TSN_OFFSET, DATA_CHUNK_TSN_LENGTH,
1041                         tsn);
1042     proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_stream_id, 
1043                         chunk_tvb, 
1044                         DATA_CHUNK_STREAM_ID_OFFSET, DATA_CHUNK_STREAM_ID_LENGTH,
1045                         stream_id);
1046     proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_stream_seq_number, 
1047                         chunk_tvb, 
1048                         DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET, DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH,
1049                         stream_seq_number);
1050     proto_tree_add_uint_format(chunk_tree, hf_sctp_data_chunk_payload_proto_id, 
1051                                chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH,
1052                                payload_proto_id, "Payload protocol identifier: %u (%s)",
1053                                payload_proto_id, val_to_str(payload_proto_id, sctp_payload_proto_id_values, "unknown"));
1054     proto_item_set_text(chunk_item, "DATA chunk with TSN %u (%u:%u) containing %u byte%s of payload",
1055                         tsn, stream_id, stream_seq_number, 
1056                         payload_length, plurality(payload_length, "", "s"));
1057   };   
1058   dissect_payload(payload_tvb, pinfo, tree, chunk_tree, payload_proto_id, payload_length, padding_length); 
1059 }
1060
1061 static void
1062 dissect_init_chunk(tvbuff_t *chunk_tvb,  packet_info *pinfo, proto_tree *tree,
1063                    proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1064
1065   guint32 initiate_tag, adv_rec_window_credit, initial_tsn;
1066   guint16 number_of_inbound_streams, number_of_outbound_streams;
1067   guint8  type;
1068   tvbuff_t *parameter_list_tvb;
1069
1070   type                       = tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET);
1071   
1072   if (check_col(pinfo->fd, COL_INFO)) {
1073     if (type == SCTP_INIT_CHUNK_ID) {
1074       col_append_str(pinfo->fd, COL_INFO, "INIT ");
1075     } else {
1076       col_append_str(pinfo->fd, COL_INFO, "INIT_ACK ");
1077     };
1078   };
1079   
1080   if (chunk_tree) {
1081     initiate_tag               = tvb_get_ntohl(chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET);
1082     adv_rec_window_credit      = tvb_get_ntohl(chunk_tvb, INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET);
1083     number_of_inbound_streams  = tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET);
1084     number_of_outbound_streams = tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET);
1085     initial_tsn                = tvb_get_ntohl(chunk_tvb, INIT_CHUNK_INITIAL_TSN_OFFSET);
1086     
1087     /* handle fixed parameters */
1088     proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_initiate_tag, 
1089                         chunk_tvb,
1090                         INIT_CHUNK_INITIATE_TAG_OFFSET, INIT_CHUNK_INITIATE_TAG_LENGTH,
1091                         initiate_tag);
1092     proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_adv_rec_window_credit, 
1093                         chunk_tvb,
1094                         INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET, INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH,
1095                         adv_rec_window_credit);
1096     proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_number_of_outbound_streams, 
1097                         chunk_tvb,
1098                         INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH,
1099                         number_of_outbound_streams);
1100     proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_number_of_inbound_streams, 
1101                         chunk_tvb,
1102                         INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH,
1103                         number_of_inbound_streams);
1104     proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_initial_tsn, 
1105                         chunk_tvb,
1106                         INIT_CHUNK_INITIAL_TSN_OFFSET, INIT_CHUNK_INITIAL_TSN_LENGTH,
1107                         initial_tsn);
1108     
1109     /* handle variable paramters */
1110     parameter_list_tvb = tvb_new_subset(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET, -1, -1);
1111     dissect_tlv_parameter_list(parameter_list_tvb, chunk_tree);
1112     
1113     proto_item_set_text(chunk_item, 
1114                         "%s chunk requesting for %u outbound stream%s and accepting up to %u inbound stream%s",
1115                         val_to_str(type, sctp_chunk_type_values, "unknown"),
1116                         number_of_outbound_streams, plurality(number_of_outbound_streams, "", "s"),
1117                         number_of_inbound_streams, plurality(number_of_inbound_streams, "", "s"));
1118   }
1119
1120
1121 static void
1122 dissect_init_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1123                        proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1124
1125   dissect_init_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1126
1127
1128 static void
1129 dissect_sack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1130                    proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1131
1132   guint32 cumulative_tsn_ack, adv_rec_window_credit, dup_tsn;
1133   guint16 number_of_gap_blocks, number_of_dup_tsns;
1134   guint16 gap_block_number, dup_tsn_number, start, end;
1135   gint gap_block_offset, dup_tsn_offset;
1136   proto_item *block_item;
1137   proto_tree *block_tree;
1138   
1139   if (check_col(pinfo->fd, COL_INFO))
1140     col_append_str(pinfo->fd, COL_INFO, "SACK ");
1141
1142   if (chunk_tree) {
1143     cumulative_tsn_ack    = tvb_get_ntohl(chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
1144     adv_rec_window_credit = tvb_get_ntohl(chunk_tvb, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET);
1145     number_of_gap_blocks  = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET);
1146     number_of_dup_tsns    = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET);
1147     
1148     proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_cumulative_tsn_ack, 
1149                         chunk_tvb,
1150                         SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET, SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH,
1151                         cumulative_tsn_ack);
1152     proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_adv_rec_window_credit, 
1153                         chunk_tvb,
1154                         SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH,
1155                         adv_rec_window_credit);
1156     proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_number_of_gap_blocks, 
1157                         chunk_tvb,
1158                         SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH,
1159                         number_of_gap_blocks);
1160     proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_number_of_dup_tsns, 
1161                         chunk_tvb,
1162                         SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET, SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH,
1163                         number_of_dup_tsns);
1164     
1165     /* handle the gap acknowledgement blocks */
1166     gap_block_offset = SACK_CHUNK_GAP_BLOCK_OFFSET;
1167     for(gap_block_number = 1; gap_block_number <= number_of_gap_blocks; gap_block_number++) {
1168       start = tvb_get_ntohs(chunk_tvb, gap_block_offset);
1169       end   = tvb_get_ntohs(chunk_tvb, gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH);
1170       block_item = proto_tree_add_text(chunk_tree, chunk_tvb,
1171                                        gap_block_offset, SACK_CHUNK_GAP_BLOCK_LENGTH,
1172                                        "Gap Acknowledgement for %u TSN%s",
1173                                        1 + end - start, plurality(1 + end - start, "", "s"));
1174       block_tree = proto_item_add_subtree(block_item, ett_sctp_sack_chunk_gap_block);
1175       proto_tree_add_uint(block_tree, hf_sctp_sack_chunk_gap_block_start, 
1176                           chunk_tvb,
1177                           gap_block_offset, SACK_CHUNK_GAP_BLOCK_START_LENGTH,
1178                           start);
1179       proto_tree_add_uint(block_tree, hf_sctp_sack_chunk_gap_block_end, 
1180                           chunk_tvb,
1181                           gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH,
1182                           SACK_CHUNK_GAP_BLOCK_END_LENGTH,
1183                           end);
1184       gap_block_offset += SACK_CHUNK_GAP_BLOCK_LENGTH;
1185     };
1186     
1187     /* handle the duplicate TSNs */
1188     dup_tsn_offset = SACK_CHUNK_GAP_BLOCK_OFFSET + number_of_gap_blocks * SACK_CHUNK_GAP_BLOCK_LENGTH;
1189     for(dup_tsn_number = 1; dup_tsn_number <= number_of_dup_tsns; dup_tsn_number++) {
1190       dup_tsn = tvb_get_ntohl(chunk_tvb, dup_tsn_offset);
1191       proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_duplicate_tsn, 
1192                           chunk_tvb,
1193                           dup_tsn, SACK_CHUNK_DUP_TSN_LENGTH,
1194                           dup_tsn);
1195       dup_tsn_offset += SACK_CHUNK_DUP_TSN_LENGTH;
1196     }
1197     
1198     proto_item_set_text(chunk_item, 
1199                         "SACK chunk acknowledging TSN %u and reporting %u gap%s and %u duplicate TSN%s",
1200                         cumulative_tsn_ack,
1201                         number_of_gap_blocks, plurality(number_of_gap_blocks, "", "s"),
1202                         number_of_dup_tsns, plurality(number_of_dup_tsns, "", "s"));
1203   } 
1204 }
1205
1206 static void
1207 dissect_heartbeat_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1208                         proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1209 {
1210   tvbuff_t   *parameter_tvb;
1211   guint chunk_length, info_length, padding_length, total_length;
1212     
1213   if (check_col(pinfo->fd, COL_INFO))
1214     col_append_str(pinfo->fd, COL_INFO, "HEARTBEAT ");
1215
1216   if (chunk_tree) {
1217     chunk_length   = tvb_get_ntohs(chunk_tvb,  CHUNK_LENGTH_OFFSET);
1218     info_length    = chunk_length - CHUNK_HEADER_LENGTH;
1219     padding_length = nr_of_padding_bytes(info_length);
1220     total_length   = info_length + padding_length;
1221     parameter_tvb  = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, total_length, total_length);
1222     
1223     dissect_parameter(parameter_tvb, chunk_tree);
1224     
1225     proto_item_set_text(chunk_item, "HEARTBEAT chunk");
1226   }
1227 }
1228  
1229 static void
1230 dissect_heartbeat_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1231                             proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1232 {  
1233   tvbuff_t   *parameter_tvb;
1234   guint chunk_length, info_length, padding_length, total_length;
1235   
1236   if (check_col(pinfo->fd, COL_INFO))
1237     col_append_str(pinfo->fd, COL_INFO, "HEARTBEAT_ACK ");
1238
1239   if (chunk_tree) {
1240     chunk_length   = tvb_get_ntohs(chunk_tvb,  CHUNK_LENGTH_OFFSET);
1241     info_length    = chunk_length - CHUNK_HEADER_LENGTH;
1242     padding_length = nr_of_padding_bytes(info_length);
1243     total_length   = info_length + padding_length;
1244
1245     parameter_tvb  = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, total_length, total_length);
1246     
1247     dissect_parameter(parameter_tvb, chunk_tree);
1248     
1249     proto_item_set_text(chunk_item, "HEARTBEAT ACK chunk");
1250   } 
1251 }
1252
1253 static void
1254 dissect_abort_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1255                     proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1256 {
1257   guint offset, number_of_causes;
1258   guint16 length, padding_length, total_length;
1259   tvbuff_t *cause_tvb;
1260   
1261   if (check_col(pinfo->fd, COL_INFO))
1262     col_append_str(pinfo->fd, COL_INFO, "ABORT ");
1263
1264   if (chunk_tree) {
1265     number_of_causes = 0;
1266     offset = ABORT_CHUNK_FIRST_ERROR_CAUSE_OFFSET;
1267     while(tvb_length_remaining(chunk_tvb, offset)) {
1268     length         = tvb_get_ntohs(chunk_tvb, offset + CAUSE_LENGTH_OFFSET);
1269     padding_length = nr_of_padding_bytes(length);
1270     total_length   = length + padding_length;
1271     /* create a tvb for the chunk including the padding bytes */
1272     cause_tvb      = tvb_new_subset(chunk_tvb, offset, total_length, total_length);
1273     dissect_error_cause(cause_tvb, pinfo, chunk_tree); 
1274     /* get rid of the handled parameter */
1275     offset += total_length;
1276     number_of_causes++;
1277     };
1278     
1279     proto_item_set_text(chunk_item, "Abort chunk with %u cause%s",
1280                         number_of_causes, plurality(number_of_causes, "", "s"));
1281   } 
1282 }
1283
1284 static void
1285 dissect_shutdown_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1286                        proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1287
1288   guint32 cumulative_tsn_ack;
1289  
1290   if (check_col(pinfo->fd, COL_INFO))
1291     col_append_str(pinfo->fd, COL_INFO, "SHUTDOWN ");
1292
1293   if (chunk_tree) {
1294     cumulative_tsn_ack = tvb_get_ntohl(chunk_tvb, SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
1295     proto_tree_add_uint(chunk_tree, hf_sctp_shutdown_chunk_cumulative_tsn_ack, 
1296                         chunk_tvb,
1297                         SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET,
1298                         SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_LENGTH,
1299                         cumulative_tsn_ack);
1300     
1301     proto_item_set_text(chunk_item, "SHUTDOWN chunk acknowledging up to TSN %u",
1302                         cumulative_tsn_ack);
1303   } 
1304 }
1305
1306 static void
1307 dissect_shutdown_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1308                            proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1309
1310   if (check_col(pinfo->fd, COL_INFO))
1311     col_append_str(pinfo->fd, COL_INFO, "SHUTDOWN_ACK ");
1312
1313   if (chunk_tree) {
1314     proto_item_set_text(chunk_item, "SHUTDOWN ACK chunk");
1315   } 
1316 }
1317
1318 static void
1319 dissect_error_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1320                     proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1321
1322   guint offset, number_of_causes;
1323   guint16 length, padding_length, total_length;
1324   tvbuff_t *cause_tvb;
1325   
1326   if (check_col(pinfo->fd, COL_INFO))
1327     col_append_str(pinfo->fd, COL_INFO, "ERROR ");
1328
1329   if (chunk_tree) {
1330     number_of_causes = 0;
1331     offset = ERROR_CHUNK_FIRST_ERROR_CAUSE_OFFSET;
1332     do {
1333       length         = tvb_get_ntohs(chunk_tvb, offset + CAUSE_LENGTH_OFFSET);
1334       padding_length = nr_of_padding_bytes(length);
1335       total_length   = length + padding_length;
1336       /* create a tvb for the chunk including the padding bytes */
1337       cause_tvb      = tvb_new_subset(chunk_tvb, offset, total_length, total_length);
1338       dissect_error_cause(cause_tvb, pinfo, chunk_tree); 
1339       /* get rid of the handled parameter */
1340       offset += total_length;
1341       number_of_causes++;
1342     } while(tvb_length_remaining(chunk_tvb, offset));
1343     
1344     proto_item_set_text(chunk_item, "Error chunk with %u cause%s",
1345                         number_of_causes, plurality(number_of_causes, "", "s"));
1346   } 
1347 }
1348
1349 static void
1350 dissect_cookie_echo_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1351                           proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1352
1353   guint length, cookie_length, padding_length;
1354
1355   length         = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1356   padding_length = nr_of_padding_bytes(length);
1357   cookie_length  = length - CHUNK_HEADER_LENGTH;
1358  
1359   if (check_col(pinfo->fd, COL_INFO))
1360     col_append_str(pinfo->fd, COL_INFO, "COOKIE_ECHO ");
1361
1362   if (chunk_tree) {  
1363     proto_tree_add_text(chunk_tree, chunk_tvb, COOKIE_ECHO_CHUNK_COOKIE_OFFSET, cookie_length,
1364                         "Cookie (%u byte%s)",
1365                         cookie_length, plurality(cookie_length, "", "s"));
1366     proto_item_set_text(chunk_item, "COOKIE ECHO chunk containing a cookie of %u byte%s",
1367                         cookie_length, plurality(cookie_length, "", "s"));
1368     
1369     if (padding_length > 0)
1370       proto_tree_add_text(chunk_tree, chunk_tvb, CHUNK_HEADER_OFFSET + length, padding_length,
1371                           "Padding: %u byte%s",
1372                           padding_length, plurality(padding_length, "", "s"));
1373   } 
1374 }
1375
1376 static void
1377 dissect_cookie_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1378                          proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1379 {  
1380   if (check_col(pinfo->fd, COL_INFO))
1381     col_append_str(pinfo->fd, COL_INFO, "COOKIE_ACK ");
1382
1383   if (chunk_tree) {
1384     proto_item_set_text(chunk_item, "COOKIE ACK chunk");
1385   } 
1386 }
1387
1388 static void
1389 dissect_ecne_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1390                    proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1391
1392   guint32 lowest_tsn;
1393  
1394   if (check_col(pinfo->fd, COL_INFO))
1395     col_append_str(pinfo->fd, COL_INFO, "ECNE ");
1396
1397   if (chunk_tree) {
1398     lowest_tsn = tvb_get_ntohl(chunk_tvb, ECNE_CHUNK_LOWEST_TSN_OFFSET);
1399     proto_tree_add_uint(chunk_tree, hf_sctp_ecne_chunk_lowest_tsn, 
1400                         chunk_tvb,
1401                         ECNE_CHUNK_LOWEST_TSN_OFFSET, ECNE_CHUNK_LOWEST_TSN_LENGTH,
1402                         lowest_tsn);
1403     
1404     proto_item_set_text(chunk_item, "ECNE chunk");
1405   } 
1406 }
1407
1408 static void
1409 dissect_cwr_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1410                   proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1411
1412   guint32 lowest_tsn;
1413   
1414   if (check_col(pinfo->fd, COL_INFO))
1415     col_append_str(pinfo->fd, COL_INFO, "CWR ");
1416
1417   if (chunk_tree) {
1418     lowest_tsn = tvb_get_ntohl(chunk_tvb, CWR_CHUNK_LOWEST_TSN_OFFSET);
1419     proto_tree_add_uint(chunk_tree, hf_sctp_cwr_chunk_lowest_tsn, 
1420                         chunk_tvb,
1421                         CWR_CHUNK_LOWEST_TSN_OFFSET, CWR_CHUNK_LOWEST_TSN_LENGTH,
1422                         lowest_tsn);
1423     
1424     proto_item_set_text(chunk_item, "CWR chunk");
1425   } 
1426 }
1427
1428 static void
1429 dissect_shutdown_complete_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1430                                 proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1431
1432   guint8  flags;
1433   guint16 length;
1434   proto_tree *flag_tree;
1435  
1436   if (check_col(pinfo->fd, COL_INFO))
1437     col_append_str(pinfo->fd, COL_INFO, "SHUTDOWN_COMPLETE ");
1438
1439   if (chunk_tree) {
1440     flags             = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
1441     length            = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1442     
1443     flag_tree = proto_item_add_subtree(flags_item, ett_sctp_data_chunk_flags);
1444     proto_tree_add_boolean(flag_tree, hf_sctp_shutdown_complete_chunk_t_bit, chunk_tvb,
1445                            CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
1446     
1447     proto_item_set_text(chunk_item, "SHUTDOWN COMPLETE chunk");
1448   } 
1449 }
1450
1451 static void
1452 dissect_unknown_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1453                       proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1454
1455   guint length, chunk_value_length, padding_length;
1456   guint8 type;
1457   
1458   if (check_col(pinfo->fd, COL_INFO))
1459     col_append_str(pinfo->fd, COL_INFO, "UNKNOWN ");
1460
1461   if (chunk_tree) {
1462     length         = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1463     padding_length = nr_of_padding_bytes(length);
1464     type           = tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET);
1465     
1466     chunk_value_length = length - CHUNK_HEADER_LENGTH;
1467     
1468     proto_tree_add_text(chunk_tree, chunk_tvb, CHUNK_VALUE_OFFSET, chunk_value_length,
1469                         "Chunk value (%u byte%s)",
1470                         chunk_value_length, plurality(chunk_value_length, "", "s"));
1471     
1472     if (padding_length > 0)
1473       proto_tree_add_text(chunk_tree, chunk_tvb, CHUNK_HEADER_OFFSET + length, padding_length,
1474                           "Padding: %u byte%s",
1475                           padding_length, plurality(padding_length, "", "s"));
1476     
1477     proto_item_set_text(chunk_item, "Chunk of type %u and %u byte%s value",
1478                         type, chunk_value_length, plurality(chunk_value_length, "", "s"));
1479   }
1480
1481
1482
1483 static void
1484 dissect_sctp_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *sctp_tree)
1485 {  
1486   guint8 type, flags;
1487   guint16 length;
1488   proto_item *flags_item;
1489   proto_item *chunk_item;
1490   proto_tree *chunk_tree;
1491
1492   /* first extract the chunk header */
1493   type   = tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET);
1494   flags  = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
1495   length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1496  
1497   if (tree) {
1498     /* create proto_tree stuff */
1499     chunk_item   = proto_tree_add_text(sctp_tree, chunk_tvb,
1500                                        CHUNK_HEADER_OFFSET, tvb_length(chunk_tvb), "Incomplete chunk");
1501     chunk_tree   = proto_item_add_subtree(chunk_item, ett_sctp_chunk);
1502     
1503     /* then insert the chunk header components into the protocol tree */
1504     proto_tree_add_uint_format(chunk_tree, hf_sctp_chunk_type, 
1505                                chunk_tvb, CHUNK_TYPE_OFFSET, CHUNK_TYPE_LENGTH,
1506                                type, "Identifier: %u (%s)",
1507                                type, val_to_str(type, sctp_chunk_type_values, "unknown"));
1508     flags_item = proto_tree_add_uint(chunk_tree, hf_sctp_chunk_flags, 
1509                                      chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH,
1510                                      flags);
1511     proto_tree_add_uint(chunk_tree, hf_sctp_chunk_length, 
1512                         chunk_tvb, CHUNK_LENGTH_OFFSET, CHUNK_LENGTH_LENGTH,
1513                         length);
1514   } else {
1515     chunk_tree = NULL;
1516     chunk_item = NULL;
1517     flags_item = NULL;
1518   };
1519   
1520   /* now dissect the chunk value */
1521
1522   switch(type) {
1523   case SCTP_DATA_CHUNK_ID:
1524     dissect_data_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1525     break;
1526   case SCTP_INIT_CHUNK_ID:
1527     dissect_init_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1528     break;
1529   case SCTP_INIT_ACK_CHUNK_ID:
1530     dissect_init_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1531     break;
1532   case SCTP_SACK_CHUNK_ID:
1533     dissect_sack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1534     break; 
1535   case SCTP_HEARTBEAT_CHUNK_ID:
1536     dissect_heartbeat_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1537     break;
1538   case SCTP_HEARTBEAT_ACK_CHUNK_ID:
1539     dissect_heartbeat_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1540     break;
1541   case SCTP_ABORT_CHUNK_ID:
1542     dissect_abort_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1543     break;
1544   case SCTP_SHUTDOWN_CHUNK_ID:
1545     dissect_shutdown_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1546     break;
1547   case SCTP_SHUTDOWN_ACK_CHUNK_ID:
1548     dissect_shutdown_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1549     break;
1550   case SCTP_ERROR_CHUNK_ID:
1551     dissect_error_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1552     break;
1553   case SCTP_COOKIE_ECHO_CHUNK_ID:
1554     dissect_cookie_echo_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1555     break;
1556   case SCTP_COOKIE_ACK_CHUNK_ID:
1557     dissect_cookie_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1558     break;
1559   case SCTP_ECNE_CHUNK_ID:
1560     dissect_ecne_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1561     break;
1562   case SCTP_CWR_CHUNK_ID:
1563     dissect_cwr_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1564     break;
1565   case SCTP_SHUTDOWN_COMPLETE_CHUNK_ID:
1566     dissect_shutdown_complete_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1567       break;
1568   default:
1569     dissect_unknown_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1570     break;
1571   }
1572 }
1573
1574 static void
1575 dissect_sctp_chunks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *sctp_tree)
1576
1577   tvbuff_t *chunk_tvb;
1578   guint16 length, padding_length, total_length;
1579   gint offset;
1580   
1581   /* the common header of the datagram is already handled */
1582   offset = COMMON_HEADER_LENGTH;
1583
1584   while(tvb_length_remaining(tvb, offset) > 0) {
1585     /* extract the chunk length and compute number of padding bytes */
1586     length         = tvb_get_ntohs(tvb, offset + CHUNK_LENGTH_OFFSET);
1587     padding_length = nr_of_padding_bytes(length);
1588     total_length   = length + padding_length;
1589     /* create a tvb for the chunk including the padding bytes */
1590     chunk_tvb    = tvb_new_subset(tvb, offset, total_length, total_length);
1591     /* call dissect_sctp_chunk for a actual work */
1592     dissect_sctp_chunk(chunk_tvb, pinfo, tree, sctp_tree);
1593     /* get rid of the dissected chunk */
1594     offset += total_length;
1595   }
1596 }
1597
1598
1599
1600 /* dissect_sctp handles the common header of a SCTP datagram.
1601  * For the handling of the chunks dissect_sctp_chunks is called.
1602  */
1603
1604 static void
1605 dissect_sctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1606 {
1607   guint16 source_port, destination_port;
1608   guint32 verification_tag, checksum;
1609   proto_item *ti;
1610   proto_tree *sctp_tree;
1611
1612   CHECK_DISPLAY_AS_DATA(proto_sctp, tvb, pinfo, tree);
1613
1614   pinfo->current_proto = "SCTP";
1615
1616   /* Extract the common header */
1617   source_port      = tvb_get_ntohs(tvb, SOURCE_PORT_OFFSET);
1618   destination_port = tvb_get_ntohs(tvb, DESTINATION_PORT_OFFSET);
1619   verification_tag = tvb_get_ntohl(tvb, VERIFICATION_TAG_OFFSET);
1620   checksum         = tvb_get_ntohl(tvb, CHECKSUM_OFFSET);
1621
1622   /* update pi structure */
1623   pi.ptype    = PT_SCTP;
1624   pi.srcport  = source_port;
1625   pi.destport = destination_port;
1626
1627   /* make entry in the Protocol column on summary display */
1628   if (check_col(pinfo->fd, COL_PROTOCOL)) 
1629     col_set_str(pinfo->fd, COL_PROTOCOL, "SCTP");
1630
1631   /* Clear entries in Info column on summary display */
1632   if (check_col(pinfo->fd, COL_INFO))
1633     col_add_str(pinfo->fd, COL_INFO, "");
1634   
1635   /* In the interest of speed, if "tree" is NULL, don't do any work not
1636      necessary to generate protocol tree items. */
1637   if (tree) {
1638     /* create the sctp protocol tree */
1639     ti = proto_tree_add_protocol_format(tree, proto_sctp, tvb, 0, tvb_length(tvb), 
1640                                         "Stream Control Transmission Protocol");
1641     sctp_tree = proto_item_add_subtree(ti, ett_sctp);
1642
1643     /* add the components of the common header to the protocol tree */
1644     proto_tree_add_uint(sctp_tree, hf_sctp_source_port, 
1645                         tvb, SOURCE_PORT_OFFSET, SOURCE_PORT_LENGTH,
1646                         source_port);
1647     proto_tree_add_uint(sctp_tree, hf_sctp_destination_port,
1648                         tvb, DESTINATION_PORT_OFFSET, DESTINATION_PORT_LENGTH,
1649                         destination_port);
1650     proto_tree_add_uint(sctp_tree, hf_sctp_verification_tag,
1651                         tvb, VERIFICATION_TAG_OFFSET, VERIFICATION_TAG_LENGTH,
1652                         verification_tag);
1653     proto_tree_add_uint_format(sctp_tree, hf_sctp_checksum,
1654                                tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, checksum,
1655                                "Adler-32 checksum: 0x%08x (%s)",
1656                                checksum, sctp_checksum_state(tvb, checksum));
1657   } else {
1658     sctp_tree = NULL;
1659   };
1660   /* add all chunks of the sctp datagram to the protocol tree */
1661   dissect_sctp_chunks(tvb, pinfo, tree, sctp_tree);
1662 }
1663
1664 /* Register the protocol with Ethereal */
1665 void
1666 proto_register_sctp(void)
1667 {                 
1668
1669   /* Setup list of header fields */
1670   static hf_register_info hf[] = {
1671     { &hf_sctp_source_port,
1672       { "Source port", "sctp.srcport",
1673         FT_UINT16, BASE_DEC, NULL, 0x0,          
1674         ""}
1675     },
1676     { &hf_sctp_destination_port,
1677       { "Destination port", "sctp.dstport",
1678         FT_UINT16, BASE_DEC, NULL, 0x0,          
1679         ""}
1680     }, 
1681     { &hf_sctp_verification_tag,
1682       { "Verification tag", "sctp.verfication_tag",
1683         FT_UINT32, BASE_HEX, NULL, 0x0,          
1684         ""}
1685     },
1686     { &hf_sctp_checksum,
1687       { "Adler-32 checksum", "sctp.checksum",
1688         FT_UINT32, BASE_HEX, NULL, 0x0,          
1689         ""}
1690     },
1691     { &hf_sctp_chunk_type,
1692       { "Identifier", "sctp.chunk_type",
1693         FT_UINT8, BASE_DEC, NULL, 0x0,          
1694         ""}
1695     },
1696     { &hf_sctp_chunk_flags,
1697       { "Flags", "sctp.chunk_flags",
1698         FT_UINT8, BASE_BIN, NULL, 0x0,          
1699         ""}
1700     },
1701     { &hf_sctp_chunk_length,
1702       { "Length", "sctp.chunk_length",
1703         FT_UINT16, BASE_DEC, NULL, 0x0,          
1704         ""}
1705     },
1706     { &hf_sctp_init_chunk_initiate_tag,
1707       { "Initiate tag", "sctp.init.chunk.initiate.tag",
1708         FT_UINT32, BASE_HEX, NULL, 0x0,          
1709         ""}
1710     },
1711     { &hf_sctp_init_chunk_adv_rec_window_credit,
1712       { "Advertised reciever window credit (a_rwnd)", "sctp.init.chunk.credit",
1713         FT_UINT32, BASE_DEC, NULL, 0x0,          
1714         ""}
1715     },
1716     { &hf_sctp_init_chunk_number_of_outbound_streams,
1717       { "Number of outbound streams", "sctp.init.chunk.nr.out.streams",
1718         FT_UINT16, BASE_DEC, NULL, 0x0,          
1719         ""}
1720     },
1721     { &hf_sctp_init_chunk_number_of_inbound_streams,
1722       { "Number of inbound streams", "sctp.init.chunk.nr.in.streams",
1723         FT_UINT16, BASE_DEC, NULL, 0x0,          
1724         ""}
1725     },
1726     {&hf_sctp_init_chunk_initial_tsn,
1727       { "Initial TSN", "sctp.init.chunk.initial.tsn",
1728         FT_UINT32, BASE_DEC, NULL, 0x0,          
1729         ""}
1730     }, 
1731     {&hf_sctp_cumulative_tsn_ack,
1732      { "Cumulative TSN Ack", "sctp.cumulative.tsn.ack",
1733         FT_UINT32, BASE_DEC, NULL, 0x0,          
1734         ""}
1735     },
1736     {&hf_sctp_data_chunk_tsn,
1737      { "TSN", "sctp.tsn",
1738        FT_UINT32, BASE_DEC, NULL, 0x0,          
1739         ""}
1740     },
1741     {&hf_sctp_data_chunk_stream_id,
1742      { "Stream Identifier", "sctp.stream_id",
1743         FT_UINT16, BASE_HEX, NULL, 0x0,          
1744         ""}
1745     },
1746     {&hf_sctp_data_chunk_stream_seq_number,
1747      { "Stream sequence number", "sctp.stream_seq_number",
1748        FT_UINT16, BASE_DEC, NULL, 0x0,          
1749        ""}
1750     },
1751     {&hf_sctp_data_chunk_payload_proto_id,
1752      { "Payload Protocol identifier", "sctp.payload_proto_id",
1753         FT_UINT32, BASE_HEX, NULL, 0x0,          
1754         ""}
1755     },
1756     {&hf_sctp_data_chunk_e_bit,
1757      { "E-Bit", "sctp.data.e_bit",
1758        FT_BOOLEAN, 8, TFS(&sctp_data_chunk_e_bit_value), SCTP_DATA_CHUNK_E_BIT,          
1759        ""}
1760     },
1761     {&hf_sctp_data_chunk_b_bit,
1762      { "B-Bit", "sctp.data.b_bit",
1763        FT_BOOLEAN, 8, TFS(&sctp_data_chunk_b_bit_value), SCTP_DATA_CHUNK_B_BIT,          
1764        ""}
1765     },
1766     {&hf_sctp_data_chunk_u_bit,
1767      { "U-Bit", "sctp.data.u.bit",
1768        FT_BOOLEAN, 8, TFS(&sctp_data_chunk_u_bit_value), SCTP_DATA_CHUNK_U_BIT,          
1769        ""}
1770     },
1771     {&hf_sctp_sack_chunk_cumulative_tsn_ack,
1772      { "Cumulative TSN ACK", "sctp.sack.cumulative_tsn_ack",
1773        FT_UINT32, BASE_DEC, NULL, 0x0,          
1774        ""}
1775     }, 
1776     {&hf_sctp_sack_chunk_adv_rec_window_credit,
1777      { "Advertised receiver window credit (a_rwnd)", "sctp.sack.a_rwnd",
1778        FT_UINT32, BASE_DEC, NULL, 0x0,          
1779        ""}
1780     },
1781     {&hf_sctp_sack_chunk_number_of_gap_blocks,
1782      { "Number of gap acknowldgement blocks ", "sctp.sack.number_of_gap_blocks",
1783        FT_UINT16, BASE_DEC, NULL, 0x0,          
1784        ""}
1785     }, 
1786     {&hf_sctp_sack_chunk_number_of_dup_tsns,
1787      { "Number of duplicated TSNs", "sctp.sack.number_of_duplicated_tsns",
1788        FT_UINT16, BASE_DEC, NULL, 0x0,          
1789        ""}
1790     },
1791     {&hf_sctp_sack_chunk_gap_block_start,
1792      { "Start", "sctp.sack.gap_block_start",
1793        FT_UINT16, BASE_DEC, NULL, 0x0,          
1794        ""}
1795     },
1796     {&hf_sctp_sack_chunk_gap_block_end,
1797      { "End", "sctp.sack.gap_block_end",
1798        FT_UINT16, BASE_DEC, NULL, 0x0,          
1799        ""}
1800     },
1801     {&hf_sctp_sack_chunk_duplicate_tsn,
1802      { "Duplicate TSN", "sctp.sack.duplicate.tsn",
1803        FT_UINT16, BASE_DEC, NULL, 0x0,          
1804        ""}
1805     },  
1806     {&hf_sctp_shutdown_chunk_cumulative_tsn_ack,
1807      { "Cumulative TSN Ack", "sctp.shutdown.cumulative_tsn_ack",
1808         FT_UINT32, BASE_DEC, NULL, 0x0,          
1809         ""}
1810     },
1811     {&hf_sctp_ecne_chunk_lowest_tsn,
1812      { "Lowest TSN", "sctp.ecne.lowest_tsn",
1813        FT_UINT32, BASE_DEC, NULL, 0x0,          
1814        ""}
1815     }, 
1816     {&hf_sctp_cwr_chunk_lowest_tsn,
1817      { "Lowest TSN", "sctp.cwr.lowest_tsn",
1818        FT_UINT32, BASE_DEC, NULL, 0x0,          
1819        ""}
1820     }, 
1821     {&hf_sctp_shutdown_complete_chunk_t_bit,
1822      { "E-Bit", "sctp.shutdown_complete.t_bit",
1823        FT_BOOLEAN, 8, TFS(&sctp_shutdown_complete_chunk_t_bit_value), SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT,
1824        ""}
1825     },
1826     {&hf_sctp_chunk_parameter_type,
1827      { "Parameter type", "sctp.parameter.type",
1828        FT_UINT16, BASE_HEX, NULL, 0x0,          
1829        ""}
1830     },
1831     {&hf_sctp_chunk_parameter_length,
1832      { "Parameter length", "sctp.parameter.length",
1833        FT_UINT16, BASE_DEC, NULL, 0x0,          
1834        ""}
1835     },
1836     {&hf_sctp_parameter_ipv4_address,
1837      { "IP Version 4 address", "sctp.parameter.ipv4_address",
1838        FT_IPv4, BASE_NONE, NULL, 0x0,
1839        ""}
1840     },
1841     {&hf_sctp_parameter_ipv6_address,
1842      { "IP Version 6 address", "sctp.parameter.ipv6_address",
1843        FT_IPv6, BASE_NONE, NULL, 0x0,
1844        ""}
1845     },
1846     {&hf_sctp_parameter_cookie_preservative_increment,
1847      { "Suggested Cookie life-span increment (msec)", "sctp.parameter.cookie_preservative_incr",
1848        FT_UINT32, BASE_DEC, NULL, 0x0,          
1849        ""}
1850     },
1851     {&hf_sctp_parameter_hostname_hostname,
1852      { "Hostname", "sctp.parameter.hostname.hostname",
1853        FT_STRING, BASE_NONE, NULL, 0x0,          
1854        ""}
1855     }, 
1856     {&hf_sctp_supported_address_types_parameter,
1857      { "Supported address type", "sctp.parameter.supported_addres_type",
1858        FT_UINT16, BASE_DEC, NULL, 0x0,          
1859        ""}
1860     }, 
1861     {&hf_sctp_cause_code,
1862      { "Cause code", "sctp.cause.code",
1863        FT_UINT16, BASE_DEC, NULL, 0x0,          
1864        ""}
1865     },
1866     {&hf_sctp_cause_length,
1867      { "Cause length", "sctp.cause.length",
1868        FT_UINT16, BASE_DEC, NULL, 0x0,          
1869        ""}
1870     }, 
1871     {&hf_sctp_cause_stream_identifier,
1872      { "Stream identifier", "sctp.cause.stream_identifier",
1873        FT_UINT16, BASE_DEC, NULL, 0x0,          
1874        ""}
1875     },
1876     {&hf_sctp_cause_number_of_missing_parameters,
1877      { "Number of missing parameters", "sctp.cause.nr_of_missing_parameters",
1878        FT_UINT32, BASE_DEC, NULL, 0x0,          
1879        ""}
1880     }, 
1881     {&hf_sctp_cause_missing_parameter_type,
1882      { "Missing parameters type", "sctp.cause.missing_parameter_type",
1883        FT_UINT16, BASE_DEC, NULL, 0x0,          
1884        ""}
1885     },
1886     {&hf_sctp_cause_measure_of_staleness,
1887      { "Measure of staleness in usec", "sctp.cause.measure_of_staleness",
1888        FT_UINT32, BASE_DEC, NULL, 0x0,          
1889        ""}
1890     },
1891     {&hf_sctp_cause_tsn,
1892      { "TSN", "sctp.cause.tsn",
1893        FT_UINT32, BASE_DEC, NULL, 0x0,          
1894        ""}
1895     },
1896   };
1897   
1898   /* Setup protocol subtree array */
1899   static gint *ett[] = {
1900     &ett_sctp,
1901     &ett_sctp_chunk,
1902     &ett_sctp_chunk_parameter,
1903     &ett_sctp_chunk_cause,
1904     &ett_sctp_data_chunk_flags,
1905     &ett_sctp_sack_chunk_gap_block,
1906     &ett_sctp_supported_address_types_parameter,
1907     &ett_sctp_unrecognized_parameter_parameter
1908   };
1909   
1910   /* Register the protocol name and description */
1911   proto_sctp = proto_register_protocol("Stream Control Transmission Protcol",
1912                                        "SCTP", "sctp");
1913   
1914   /* Required function calls to register the header fields and subtrees used */
1915   proto_register_field_array(proto_sctp, hf, array_length(hf));
1916   proto_register_subtree_array(ett, array_length(ett));
1917
1918   /* subdissector code */
1919   sctp_port_dissector_table = register_dissector_table("sctp.port");
1920   sctp_ppi_dissector_table  = register_dissector_table("sctp.ppi");
1921
1922 };
1923
1924 void
1925 proto_reg_handoff_sctp(void)
1926 {
1927         dissector_add("ip.proto", IP_PROTO_SCTP, dissect_sctp, proto_sctp);
1928 }