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