Added two new arguments to epan_init() and proto_init() to
[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.13 2001/01/25 06:14:14 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 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, 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 gboolean
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     return TRUE;
991   }
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     return FALSE;
1003   }
1004 }
1005
1006 static gboolean
1007 dissect_data_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
1008                    proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
1009
1010   guint8  flags;
1011   guint16 length, total_payload_length, payload_length, padding_length, stream_id, stream_seq_number;
1012   guint32 tsn, payload_proto_id;
1013   proto_tree *flag_tree;
1014   tvbuff_t *payload_tvb;
1015    
1016   length            = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
1017   payload_length       = length - DATA_CHUNK_HEADER_LENGTH;
1018   padding_length       = nr_of_padding_bytes(length);
1019   total_payload_length = payload_length + padding_length;
1020   payload_tvb          = tvb_new_subset(chunk_tvb, DATA_CHUNK_PAYLOAD_OFFSET,
1021                                           total_payload_length, total_payload_length);
1022   payload_proto_id     = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET);
1023
1024   if (chunk_tree) {
1025     flags             = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
1026      
1027     flag_tree = proto_item_add_subtree(flags_item, ett_sctp_data_chunk_flags);
1028     proto_tree_add_boolean(flag_tree, hf_sctp_data_chunk_e_bit, chunk_tvb,
1029                            CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
1030     proto_tree_add_boolean(flag_tree, hf_sctp_data_chunk_b_bit, chunk_tvb,
1031                            CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
1032     proto_tree_add_boolean(flag_tree, hf_sctp_data_chunk_u_bit, chunk_tvb,
1033                            CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
1034     
1035     tsn               = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_TSN_OFFSET);
1036     stream_id         = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET);
1037     stream_seq_number = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET);
1038          
1039     proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_tsn, 
1040                         chunk_tvb,
1041                         DATA_CHUNK_TSN_OFFSET, DATA_CHUNK_TSN_LENGTH,
1042                         tsn);
1043     proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_stream_id, 
1044                         chunk_tvb, 
1045                         DATA_CHUNK_STREAM_ID_OFFSET, DATA_CHUNK_STREAM_ID_LENGTH,
1046                         stream_id);
1047     proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_stream_seq_number, 
1048                         chunk_tvb, 
1049                         DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET, DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH,
1050                         stream_seq_number);
1051     proto_tree_add_uint_format(chunk_tree, hf_sctp_data_chunk_payload_proto_id, 
1052                                chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH,
1053                                payload_proto_id, "Payload protocol identifier: %u (%s)",
1054                                payload_proto_id, val_to_str(payload_proto_id, sctp_payload_proto_id_values, "unknown"));
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_format(chunk_tree, hf_sctp_chunk_type, 
1509                                chunk_tvb, CHUNK_TYPE_OFFSET, CHUNK_TYPE_LENGTH,
1510                                type, "Identifier: %u (%s)",
1511                                type, val_to_str(type, sctp_chunk_type_values, "unknown"));
1512     flags_item = proto_tree_add_uint(chunk_tree, hf_sctp_chunk_flags, 
1513                                      chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH,
1514                                      flags);
1515     proto_tree_add_uint(chunk_tree, hf_sctp_chunk_length, 
1516                         chunk_tvb, CHUNK_LENGTH_OFFSET, CHUNK_LENGTH_LENGTH,
1517                         length);
1518   } else {
1519     chunk_tree = NULL;
1520     chunk_item = NULL;
1521     flags_item = NULL;
1522   };
1523   
1524   /* now dissect the chunk value */
1525
1526   switch(type) {
1527   case SCTP_DATA_CHUNK_ID:
1528     result = dissect_data_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1529     break;
1530   case SCTP_INIT_CHUNK_ID:
1531     dissect_init_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1532     break;
1533   case SCTP_INIT_ACK_CHUNK_ID:
1534     dissect_init_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1535     break;
1536   case SCTP_SACK_CHUNK_ID:
1537     dissect_sack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1538     break; 
1539   case SCTP_HEARTBEAT_CHUNK_ID:
1540     dissect_heartbeat_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1541     break;
1542   case SCTP_HEARTBEAT_ACK_CHUNK_ID:
1543     dissect_heartbeat_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1544     break;
1545   case SCTP_ABORT_CHUNK_ID:
1546     dissect_abort_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1547     break;
1548   case SCTP_SHUTDOWN_CHUNK_ID:
1549     dissect_shutdown_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1550     break;
1551   case SCTP_SHUTDOWN_ACK_CHUNK_ID:
1552     dissect_shutdown_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1553     break;
1554   case SCTP_ERROR_CHUNK_ID:
1555     dissect_error_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1556     break;
1557   case SCTP_COOKIE_ECHO_CHUNK_ID:
1558     dissect_cookie_echo_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1559     break;
1560   case SCTP_COOKIE_ACK_CHUNK_ID:
1561     dissect_cookie_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1562     break;
1563   case SCTP_ECNE_CHUNK_ID:
1564     dissect_ecne_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1565     break;
1566   case SCTP_CWR_CHUNK_ID:
1567     dissect_cwr_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1568     break;
1569   case SCTP_SHUTDOWN_COMPLETE_CHUNK_ID:
1570     dissect_shutdown_complete_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1571       break;
1572   default:
1573     dissect_unknown_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1574     break;
1575   };
1576   return result;
1577 }
1578
1579 static void
1580 dissect_sctp_chunks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1581                     proto_item *sctp_item, proto_tree *sctp_tree)
1582
1583   tvbuff_t *chunk_tvb;
1584   guint16 length, padding_length, total_length;
1585   gint last_offset, offset;
1586   gboolean sctp_item_length_set;
1587
1588   /* the common header of the datagram is already handled */
1589   last_offset = 0;
1590   offset = COMMON_HEADER_LENGTH;
1591   sctp_item_length_set = FALSE;
1592
1593   while(tvb_length_remaining(tvb, offset) > 0) {
1594     /* extract the chunk length and compute number of padding bytes */
1595     length         = tvb_get_ntohs(tvb, offset + CHUNK_LENGTH_OFFSET);
1596     padding_length = nr_of_padding_bytes(length);
1597     total_length   = length + padding_length;
1598     /* create a tvb for the chunk including the padding bytes */
1599     chunk_tvb    = tvb_new_subset(tvb, offset, total_length, total_length);
1600     /* call dissect_sctp_chunk for a actual work */
1601     if (dissect_sctp_chunk(chunk_tvb, pinfo, tree, sctp_tree) && (tree)) {
1602       proto_item_set_len(sctp_item, offset - last_offset + DATA_CHUNK_HEADER_LENGTH);
1603       sctp_item_length_set = TRUE;
1604       offset += total_length;
1605       last_offset = offset;
1606       if (tvb_length_remaining(tvb, offset) > 0) {
1607         sctp_item = proto_tree_add_item(tree, proto_sctp, tvb, offset, 0, FALSE);
1608         sctp_tree = proto_item_add_subtree(sctp_item, ett_sctp);
1609         sctp_item_length_set = FALSE;
1610       }
1611     } else {
1612     /* get rid of the dissected chunk */
1613     offset += total_length;
1614     }
1615   };
1616   if (!sctp_item_length_set && (tree)) { 
1617     proto_item_set_len(sctp_item, offset - last_offset);
1618   };
1619 }
1620
1621 /* dissect_sctp handles the common header of a SCTP datagram.
1622  * For the handling of the chunks dissect_sctp_chunks is called.
1623  */
1624
1625 static void
1626 dissect_sctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1627 {
1628   guint16 source_port, destination_port;
1629   guint32 verification_tag, checksum;
1630   proto_item *sctp_item;
1631   proto_tree *sctp_tree;
1632
1633   /* Extract the common header */
1634   source_port      = tvb_get_ntohs(tvb, SOURCE_PORT_OFFSET);
1635   destination_port = tvb_get_ntohs(tvb, DESTINATION_PORT_OFFSET);
1636   verification_tag = tvb_get_ntohl(tvb, VERIFICATION_TAG_OFFSET);
1637   checksum         = tvb_get_ntohl(tvb, CHECKSUM_OFFSET);
1638
1639   /* update pi structure */
1640   pinfo->ptype    = PT_SCTP;
1641   pinfo->srcport  = source_port;
1642   pinfo->destport = destination_port;
1643
1644   /* make entry in the Protocol column on summary display */
1645   if (check_col(pinfo->fd, COL_PROTOCOL)) 
1646     col_set_str(pinfo->fd, COL_PROTOCOL, "SCTP");
1647
1648   /* Clear entries in Info column on summary display */
1649   if (check_col(pinfo->fd, COL_INFO))
1650     col_add_str(pinfo->fd, COL_INFO, "");
1651   
1652   /* In the interest of speed, if "tree" is NULL, don't do any work not
1653      necessary to generate protocol tree items. */
1654   if (tree) {
1655     /* create the sctp protocol tree */
1656     sctp_item = proto_tree_add_item(tree, proto_sctp, tvb, 0, 0, FALSE);
1657     sctp_tree = proto_item_add_subtree(sctp_item, ett_sctp);
1658
1659     /* add the components of the common header to the protocol tree */
1660     proto_tree_add_uint(sctp_tree, hf_sctp_source_port, 
1661                         tvb, SOURCE_PORT_OFFSET, SOURCE_PORT_LENGTH,
1662                         source_port);
1663     proto_tree_add_uint(sctp_tree, hf_sctp_destination_port,
1664                         tvb, DESTINATION_PORT_OFFSET, DESTINATION_PORT_LENGTH,
1665                         destination_port);
1666     proto_tree_add_uint(sctp_tree, hf_sctp_verification_tag,
1667                         tvb, VERIFICATION_TAG_OFFSET, VERIFICATION_TAG_LENGTH,
1668                         verification_tag);
1669     proto_tree_add_uint_format(sctp_tree, hf_sctp_checksum,
1670                                tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, checksum,
1671                                "Adler-32 checksum: 0x%08x (%s)",
1672                                checksum, sctp_checksum_state(tvb, checksum));
1673   } else {
1674     sctp_tree = NULL;
1675     sctp_item = NULL;
1676   };
1677   /* add all chunks of the sctp datagram to the protocol tree */
1678   dissect_sctp_chunks(tvb, pinfo, tree, sctp_item, sctp_tree);
1679 }
1680
1681 /* Register the protocol with Ethereal */
1682 void
1683 proto_register_sctp(void)
1684 {                 
1685
1686   /* Setup list of header fields */
1687   static hf_register_info hf[] = {
1688     { &hf_sctp_source_port,
1689       { "Source port", "sctp.srcport",
1690         FT_UINT16, BASE_DEC, NULL, 0x0,          
1691         ""}
1692     },
1693     { &hf_sctp_destination_port,
1694       { "Destination port", "sctp.dstport",
1695         FT_UINT16, BASE_DEC, NULL, 0x0,          
1696         ""}
1697     }, 
1698     { &hf_sctp_verification_tag,
1699       { "Verification tag", "sctp.verfication_tag",
1700         FT_UINT32, BASE_HEX, NULL, 0x0,          
1701         ""}
1702     },
1703     { &hf_sctp_checksum,
1704       { "Adler-32 checksum", "sctp.checksum",
1705         FT_UINT32, BASE_HEX, NULL, 0x0,          
1706         ""}
1707     },
1708     { &hf_sctp_chunk_type,
1709       { "Identifier", "sctp.chunk_type",
1710         FT_UINT8, BASE_DEC, NULL, 0x0,          
1711         ""}
1712     },
1713     { &hf_sctp_chunk_flags,
1714       { "Flags", "sctp.chunk_flags",
1715         FT_UINT8, BASE_BIN, NULL, 0x0,          
1716         ""}
1717     },
1718     { &hf_sctp_chunk_length,
1719       { "Length", "sctp.chunk_length",
1720         FT_UINT16, BASE_DEC, NULL, 0x0,          
1721         ""}
1722     },
1723     { &hf_sctp_init_chunk_initiate_tag,
1724       { "Initiate tag", "sctp.init.chunk.initiate.tag",
1725         FT_UINT32, BASE_HEX, NULL, 0x0,          
1726         ""}
1727     },
1728     { &hf_sctp_init_chunk_adv_rec_window_credit,
1729       { "Advertised reciever window credit (a_rwnd)", "sctp.init.chunk.credit",
1730         FT_UINT32, BASE_DEC, NULL, 0x0,          
1731         ""}
1732     },
1733     { &hf_sctp_init_chunk_number_of_outbound_streams,
1734       { "Number of outbound streams", "sctp.init.chunk.nr.out.streams",
1735         FT_UINT16, BASE_DEC, NULL, 0x0,          
1736         ""}
1737     },
1738     { &hf_sctp_init_chunk_number_of_inbound_streams,
1739       { "Number of inbound streams", "sctp.init.chunk.nr.in.streams",
1740         FT_UINT16, BASE_DEC, NULL, 0x0,          
1741         ""}
1742     },
1743     {&hf_sctp_init_chunk_initial_tsn,
1744       { "Initial TSN", "sctp.init.chunk.initial.tsn",
1745         FT_UINT32, BASE_DEC, NULL, 0x0,          
1746         ""}
1747     }, 
1748     {&hf_sctp_cumulative_tsn_ack,
1749      { "Cumulative TSN Ack", "sctp.cumulative.tsn.ack",
1750         FT_UINT32, BASE_DEC, NULL, 0x0,          
1751         ""}
1752     },
1753     {&hf_sctp_data_chunk_tsn,
1754      { "TSN", "sctp.tsn",
1755        FT_UINT32, BASE_DEC, NULL, 0x0,          
1756         ""}
1757     },
1758     {&hf_sctp_data_chunk_stream_id,
1759      { "Stream Identifier", "sctp.stream_id",
1760         FT_UINT16, BASE_HEX, NULL, 0x0,          
1761         ""}
1762     },
1763     {&hf_sctp_data_chunk_stream_seq_number,
1764      { "Stream sequence number", "sctp.stream_seq_number",
1765        FT_UINT16, BASE_DEC, NULL, 0x0,          
1766        ""}
1767     },
1768     {&hf_sctp_data_chunk_payload_proto_id,
1769      { "Payload Protocol identifier", "sctp.payload_proto_id",
1770         FT_UINT32, BASE_HEX, NULL, 0x0,          
1771         ""}
1772     },
1773     {&hf_sctp_data_chunk_e_bit,
1774      { "E-Bit", "sctp.data.e_bit",
1775        FT_BOOLEAN, 8, TFS(&sctp_data_chunk_e_bit_value), SCTP_DATA_CHUNK_E_BIT,          
1776        ""}
1777     },
1778     {&hf_sctp_data_chunk_b_bit,
1779      { "B-Bit", "sctp.data.b_bit",
1780        FT_BOOLEAN, 8, TFS(&sctp_data_chunk_b_bit_value), SCTP_DATA_CHUNK_B_BIT,          
1781        ""}
1782     },
1783     {&hf_sctp_data_chunk_u_bit,
1784      { "U-Bit", "sctp.data.u.bit",
1785        FT_BOOLEAN, 8, TFS(&sctp_data_chunk_u_bit_value), SCTP_DATA_CHUNK_U_BIT,          
1786        ""}
1787     },
1788     {&hf_sctp_sack_chunk_cumulative_tsn_ack,
1789      { "Cumulative TSN ACK", "sctp.sack.cumulative_tsn_ack",
1790        FT_UINT32, BASE_DEC, NULL, 0x0,          
1791        ""}
1792     }, 
1793     {&hf_sctp_sack_chunk_adv_rec_window_credit,
1794      { "Advertised receiver window credit (a_rwnd)", "sctp.sack.a_rwnd",
1795        FT_UINT32, BASE_DEC, NULL, 0x0,          
1796        ""}
1797     },
1798     {&hf_sctp_sack_chunk_number_of_gap_blocks,
1799      { "Number of gap acknowldgement blocks ", "sctp.sack.number_of_gap_blocks",
1800        FT_UINT16, BASE_DEC, NULL, 0x0,          
1801        ""}
1802     }, 
1803     {&hf_sctp_sack_chunk_number_of_dup_tsns,
1804      { "Number of duplicated TSNs", "sctp.sack.number_of_duplicated_tsns",
1805        FT_UINT16, BASE_DEC, NULL, 0x0,          
1806        ""}
1807     },
1808     {&hf_sctp_sack_chunk_gap_block_start,
1809      { "Start", "sctp.sack.gap_block_start",
1810        FT_UINT16, BASE_DEC, NULL, 0x0,          
1811        ""}
1812     },
1813     {&hf_sctp_sack_chunk_gap_block_end,
1814      { "End", "sctp.sack.gap_block_end",
1815        FT_UINT16, BASE_DEC, NULL, 0x0,          
1816        ""}
1817     },
1818     {&hf_sctp_sack_chunk_duplicate_tsn,
1819      { "Duplicate TSN", "sctp.sack.duplicate.tsn",
1820        FT_UINT16, BASE_DEC, NULL, 0x0,          
1821        ""}
1822     },  
1823     {&hf_sctp_shutdown_chunk_cumulative_tsn_ack,
1824      { "Cumulative TSN Ack", "sctp.shutdown.cumulative_tsn_ack",
1825         FT_UINT32, BASE_DEC, NULL, 0x0,          
1826         ""}
1827     },
1828     {&hf_sctp_ecne_chunk_lowest_tsn,
1829      { "Lowest TSN", "sctp.ecne.lowest_tsn",
1830        FT_UINT32, BASE_DEC, NULL, 0x0,          
1831        ""}
1832     }, 
1833     {&hf_sctp_cwr_chunk_lowest_tsn,
1834      { "Lowest TSN", "sctp.cwr.lowest_tsn",
1835        FT_UINT32, BASE_DEC, NULL, 0x0,          
1836        ""}
1837     }, 
1838     {&hf_sctp_shutdown_complete_chunk_t_bit,
1839      { "E-Bit", "sctp.shutdown_complete.t_bit",
1840        FT_BOOLEAN, 8, TFS(&sctp_shutdown_complete_chunk_t_bit_value), SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT,
1841        ""}
1842     },
1843     {&hf_sctp_chunk_parameter_type,
1844      { "Parameter type", "sctp.parameter.type",
1845        FT_UINT16, BASE_HEX, NULL, 0x0,          
1846        ""}
1847     },
1848     {&hf_sctp_chunk_parameter_length,
1849      { "Parameter length", "sctp.parameter.length",
1850        FT_UINT16, BASE_DEC, NULL, 0x0,          
1851        ""}
1852     },
1853     {&hf_sctp_parameter_ipv4_address,
1854      { "IP Version 4 address", "sctp.parameter.ipv4_address",
1855        FT_IPv4, BASE_NONE, NULL, 0x0,
1856        ""}
1857     },
1858     {&hf_sctp_parameter_ipv6_address,
1859      { "IP Version 6 address", "sctp.parameter.ipv6_address",
1860        FT_IPv6, BASE_NONE, NULL, 0x0,
1861        ""}
1862     },
1863     {&hf_sctp_parameter_cookie_preservative_increment,
1864      { "Suggested Cookie life-span increment (msec)", "sctp.parameter.cookie_preservative_incr",
1865        FT_UINT32, BASE_DEC, NULL, 0x0,          
1866        ""}
1867     },
1868     {&hf_sctp_parameter_hostname_hostname,
1869      { "Hostname", "sctp.parameter.hostname.hostname",
1870        FT_STRING, BASE_NONE, NULL, 0x0,          
1871        ""}
1872     }, 
1873     {&hf_sctp_supported_address_types_parameter,
1874      { "Supported address type", "sctp.parameter.supported_addres_type",
1875        FT_UINT16, BASE_DEC, NULL, 0x0,          
1876        ""}
1877     }, 
1878     {&hf_sctp_cause_code,
1879      { "Cause code", "sctp.cause.code",
1880        FT_UINT16, BASE_DEC, NULL, 0x0,          
1881        ""}
1882     },
1883     {&hf_sctp_cause_length,
1884      { "Cause length", "sctp.cause.length",
1885        FT_UINT16, BASE_DEC, NULL, 0x0,          
1886        ""}
1887     }, 
1888     {&hf_sctp_cause_stream_identifier,
1889      { "Stream identifier", "sctp.cause.stream_identifier",
1890        FT_UINT16, BASE_DEC, NULL, 0x0,          
1891        ""}
1892     },
1893     {&hf_sctp_cause_number_of_missing_parameters,
1894      { "Number of missing parameters", "sctp.cause.nr_of_missing_parameters",
1895        FT_UINT32, BASE_DEC, NULL, 0x0,          
1896        ""}
1897     }, 
1898     {&hf_sctp_cause_missing_parameter_type,
1899      { "Missing parameters type", "sctp.cause.missing_parameter_type",
1900        FT_UINT16, BASE_DEC, NULL, 0x0,          
1901        ""}
1902     },
1903     {&hf_sctp_cause_measure_of_staleness,
1904      { "Measure of staleness in usec", "sctp.cause.measure_of_staleness",
1905        FT_UINT32, BASE_DEC, NULL, 0x0,          
1906        ""}
1907     },
1908     {&hf_sctp_cause_tsn,
1909      { "TSN", "sctp.cause.tsn",
1910        FT_UINT32, BASE_DEC, NULL, 0x0,          
1911        ""}
1912     },
1913   };
1914   
1915   /* Setup protocol subtree array */
1916   static gint *ett[] = {
1917     &ett_sctp,
1918     &ett_sctp_chunk,
1919     &ett_sctp_chunk_parameter,
1920     &ett_sctp_chunk_cause,
1921     &ett_sctp_data_chunk_flags,
1922     &ett_sctp_sack_chunk_gap_block,
1923     &ett_sctp_supported_address_types_parameter,
1924     &ett_sctp_unrecognized_parameter_parameter
1925   };
1926   
1927   /* Register the protocol name and description */
1928   proto_sctp = proto_register_protocol("Stream Control Transmission Protcol",
1929                                        "SCTP", "sctp");
1930   
1931   /* Required function calls to register the header fields and subtrees used */
1932   proto_register_field_array(proto_sctp, hf, array_length(hf));
1933   proto_register_subtree_array(ett, array_length(ett));
1934
1935   /* subdissector code */
1936   sctp_port_dissector_table = register_dissector_table("sctp.port");
1937   sctp_ppi_dissector_table  = register_dissector_table("sctp.ppi");
1938
1939 };
1940
1941 void
1942 proto_reg_handoff_sctp(void)
1943 {
1944         dissector_add("ip.proto", IP_PROTO_SCTP, dissect_sctp, proto_sctp);
1945 }