2 * Routines for Stream Control Transmission Protocol dissection
3 * Copyright 2000, Michael Tüxen <Michael.Tuexen@icn.siemens.de>
5 * $Id: packet-sctp.c,v 1.17 2001/06/18 02:17:52 guy Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
9 * Copyright 1998 Gerald Combs
11 * Copied from README.developer
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.
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.
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.
36 #ifdef HAVE_SYS_TYPES_H
37 # include <sys/types.h>
40 #ifdef HAVE_NETINET_IN_H
41 # include <netinet/in.h>
47 #ifdef NEED_SNPRINTF_H
48 # include "snprintf.h"
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;
61 static int hf_sctp_chunk_type = -1;
62 static int hf_sctp_chunk_flags = -1;
63 static int hf_sctp_chunk_length = -1;
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;
71 static int hf_sctp_cumulative_tsn_ack = -1;
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;
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;
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;
90 static int hf_sctp_shutdown_chunk_cumulative_tsn_ack = -1;
92 static int hf_sctp_cwr_chunk_lowest_tsn = -1;
94 static int hf_sctp_ecne_chunk_lowest_tsn = -1;
96 static int hf_sctp_shutdown_complete_chunk_t_bit = -1;
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;
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;
110 static int hf_sctp_cause_number_of_missing_parameters = -1;
111 static int hf_sctp_cause_missing_parameter_type = -1;
113 static int hf_sctp_cause_measure_of_staleness = -1;
115 static int hf_sctp_cause_tsn = -1;
117 static dissector_table_t sctp_port_dissector_table;
118 static dissector_table_t sctp_ppi_dissector_table;
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;
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
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" },
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
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" },
188 #define PARAMETER_TYPE_LENGTH 2
189 #define PARAMETER_LENGTH_LENGTH 2
190 #define PARAMETER_HEADER_LENGTH (PARAMETER_TYPE_LENGTH + PARAMETER_LENGTH_LENGTH)
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)
197 #define HEARTBEAT_INFO_PARAMETER_INFO_OFFSET PARAMETER_VALUE_OFFSET
198 #define HEARTBEAT_INFO_PARAMETER_HEADER_LENGTH PARAMETER_HEADER_LENGTH
200 #define IPV4_ADDRESS_LENGTH 4
201 #define IPV6_ADDRESS_LENGTH 16
203 #define STATE_COOKIE_PARAMETER_HEADER_LENGTH PARAMETER_HEADER_LENGTH
204 #define STATE_COOKIE_PARAMETER_COOKIE_OFFSET PARAMETER_VALUE_OFFSET
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
210 #define CAUSE_CODE_LENGTH 2
211 #define CAUSE_LENGTH_LENGTH 2
212 #define CAUSE_HEADER_LENGTH (CAUSE_CODE_LENGTH + CAUSE_LENGTH_LENGTH)
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)
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)
224 #define CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH 4
225 #define CAUSE_MISSING_PARAMETER_TYPE_LENGTH 2
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 )
231 #define CAUSE_MEASURE_OF_STALENESS_LENGTH 4
232 #define CAUSE_MEASURE_OF_STALENESS_OFFSET CAUSE_INFO_OFFSET
234 #define CAUSE_TSN_LENGTH 4
235 #define CAUSE_TSN_OFFSET CAUSE_INFO_OFFSET
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
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" },
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
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" },
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 + \
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)
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 + \
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)
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
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)
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)
327 #define SCTP_DATA_CHUNK_E_BIT 0x01
328 #define SCTP_DATA_CHUNK_B_BIT 0x02
329 #define SCTP_DATA_CHUNK_U_BIT 0x04
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
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 )
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
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)
369 #define HEARTBEAT_CHUNK_INFO_OFFSET CHUNK_VALUE_OFFSET
371 #define SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET CHUNK_VALUE_OFFSET
372 #define SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_LENGTH 4
374 #define ABORT_CHUNK_FIRST_ERROR_CAUSE_OFFSET 4
375 #define ERROR_CHUNK_FIRST_ERROR_CAUSE_OFFSET 4
377 #define COOKIE_ECHO_CHUNK_COOKIE_OFFSET CHUNK_VALUE_OFFSET
379 #define ECNE_CHUNK_LOWEST_TSN_OFFSET CHUNK_VALUE_OFFSET
380 #define ECNE_CHUNK_LOWEST_TSN_LENGTH 4
382 #define CWR_CHUNK_LOWEST_TSN_OFFSET CHUNK_VALUE_OFFSET
383 #define CWR_CHUNK_LOWEST_TSN_LENGTH 4
385 #define SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT 0x01
387 static const true_false_string sctp_data_chunk_e_bit_value = {
389 "Not the last segment"
392 static const true_false_string sctp_data_chunk_b_bit_value = {
397 static const true_false_string sctp_data_chunk_u_bit_value = {
398 "Unordered delivery",
402 static const true_false_string sctp_shutdown_complete_chunk_t_bit_value = {
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/
412 * It was modified for the use in this dissector.
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 */
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);
426 sctp_adler_32(const unsigned char* buf,
429 unsigned int s1 = 1L;
430 unsigned int s2 = 0L;
433 /* handle the first 8 bytes of the datagram */
435 buf += SOURCE_PORT_LENGTH +
436 DESTINATION_PORT_LENGTH +
437 VERIFICATION_TAG_LENGTH;
439 /* handle four 0 bytes as checksum */
440 s2 += CHECKSUM_LENGTH * s1;
441 buf += CHECKSUM_LENGTH;
443 /* now we have 12 bytes handled */
444 len -= COMMON_HEADER_LENGTH;
446 /* handle the rest of the datagram */
448 k = len < NMAX ? len : NMAX;
462 return (s2 << 16) | s1;
466 *sctp_checksum_state(tvbuff_t *tvb, guint orig_checksum)
470 length = tvb_length(tvb);
471 if (orig_checksum == sctp_adler_32(tvb_get_ptr(tvb, 0, length), length))
478 nr_of_padding_bytes (guint length)
482 remainder = length % 4;
487 return 4 - remainder;
491 * TLV parameter stuff for INIT and INIT-ACK chunks
495 dissect_parameter(tvbuff_t *, proto_tree *);
498 dissect_sctp_chunk(tvbuff_t *, packet_info *, proto_tree *, proto_tree *);
501 dissect_tlv_parameter_list(tvbuff_t *parameter_list_tvb, proto_tree *tree)
503 guint offset, length, padding_length, total_length;
504 tvbuff_t *parameter_tvb;
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;
520 dissect_heartbeat_info_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
522 guint16 length, heartbeat_info_length;
524 length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
526 heartbeat_info_length = length - HEARTBEAT_INFO_PARAMETER_HEADER_LENGTH;
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"));
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"));
537 dissect_ipv4_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
539 guint32 ipv4_address;
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,
545 proto_item_set_text(parameter_item, "IPV4 address parameter");
549 dissect_ipv6_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
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));
555 proto_item_set_text(parameter_item, "IPV6 address parameter");
559 dissect_state_cookie_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
561 guint16 length, state_cookie_length;
563 length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
565 state_cookie_length = length - STATE_COOKIE_PARAMETER_HEADER_LENGTH;
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"));
571 proto_item_set_text(parameter_item, "State Cookie Parameter with %u byte%s cookie",
572 state_cookie_length, plurality(state_cookie_length, "", "s"));
576 dissect_unrecognized_parameters_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
578 guint16 length, padding_length, parameter_value_length;
579 tvbuff_t *unrecognized_parameters_tvb;
581 length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
582 padding_length = nr_of_padding_bytes(length);
584 parameter_value_length = length - PARAMETER_HEADER_LENGTH + padding_length;
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);
590 proto_item_set_text(parameter_item, "Unrecognized parameter of type");
594 dissect_cookie_preservative_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
598 increment = tvb_get_ntohl(parameter_tvb, COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET);
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,
605 proto_item_set_text(parameter_item, "Cookie preservative parameter requesting for a %u msec increment",
610 dissect_hostname_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
612 guint16 length, hostname_length;
615 length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
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,
623 proto_item_set_text(parameter_item, "Hostname parameter");
627 dissect_supported_address_types_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
629 guint16 length, address_type, number_of_address_types, address_type_number, list_of_address_types_length ;
631 proto_item *address_list_item;
632 proto_tree *address_list_tree;
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;
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);
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;
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"));
658 dissect_ecn_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
660 proto_item_set_text(parameter_item, "ECN parameter");
664 dissect_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
666 guint16 type, length, parameter_value_length;
668 type = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
669 length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
671 parameter_value_length = length - PARAMETER_HEADER_LENGTH;
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"));
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"));
682 dissect_parameter(tvbuff_t *parameter_tvb, proto_tree *chunk_tree)
684 guint16 type, length, padding_length, total_length;
685 proto_item *parameter_item;
686 proto_tree *parameter_tree;
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;
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);
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,
705 case HEARTBEAT_INFO_PARAMETER_ID:
706 dissect_heartbeat_info_parameter(parameter_tvb, parameter_tree, parameter_item);
708 case IPV4ADDRESS_PARAMETER_ID:
709 dissect_ipv4_parameter(parameter_tvb, parameter_tree, parameter_item);
711 case IPV6ADDRESS_PARAMETER_ID:
712 dissect_ipv6_parameter(parameter_tvb, parameter_tree, parameter_item);
714 case STATE_COOKIE_PARAMETER_ID:
715 dissect_state_cookie_parameter(parameter_tvb, parameter_tree, parameter_item);
717 case UNREC_PARA_PARAMETER_ID:
718 dissect_unrecognized_parameters_parameter(parameter_tvb, parameter_tree, parameter_item);
720 case COOKIE_PRESERVATIVE_PARAMETER_ID:
721 dissect_cookie_preservative_parameter(parameter_tvb, parameter_tree, parameter_item);
723 case HOSTNAME_ADDRESS_PARAMETER_ID:
724 dissect_hostname_parameter(parameter_tvb, parameter_tree, parameter_item);
726 case SUPPORTED_ADDRESS_TYPES_PARAMETER_ID:
727 dissect_supported_address_types_parameter(parameter_tvb, parameter_tree, parameter_item);
729 case ECN_PARAMETER_ID:
730 dissect_ecn_parameter(parameter_tvb, parameter_tree, parameter_item);
733 dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
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"));
743 * Code to handle error causes for ABORT and ERROR chunks
746 dissect_invalid_stream_identifier_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
748 guint16 stream_identifier;
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,
754 proto_tree_add_text(cause_tree, cause_tvb, CAUSE_RESERVED_OFFSET, CAUSE_RESERVED_LENGTH,
755 "Reserved (2 bytes)");
757 proto_item_set_text(cause_item, "Error cause reporting invalid stream identifier %u",
762 dissect_missing_mandatory_parameters_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
764 guint32 number_of_missing_parameters, missing_parameter_number;
765 guint16 parameter_type;
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)",
779 val_to_str(parameter_type, sctp_parameter_identifier_values, "unknown"));
780 offset += CAUSE_MISSING_PARAMETER_TYPE_LENGTH;
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") );
788 dissect_stale_cookie_error_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
790 guint32 measure_of_staleness;
792 measure_of_staleness = tvb_get_ntohl(cause_tvb, CAUSE_MEASURE_OF_STALENESS_OFFSET);
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);
799 proto_item_set_text(cause_item, "Error cause reporting a measure of staleness of %u usec",
800 measure_of_staleness);
804 dissect_out_of_resource_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
806 proto_item_set_text(cause_item, "Error cause reporting lack of resources");
810 dissect_unresolvable_address_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
812 guint16 code, length, parameter_length, parameter_type;
813 tvbuff_t *parameter_tvb;
815 code = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET);
816 length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
818 parameter_length = length - CAUSE_HEADER_LENGTH;
819 parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET,
820 parameter_length, parameter_length);
822 dissect_parameter(parameter_tvb, cause_tree);
823 parameter_type = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
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") );
830 dissect_unrecognized_chunk_type_cause(tvbuff_t *cause_tvb, packet_info *pinfo,
831 proto_tree *cause_tree, proto_item *cause_item)
833 guint16 length, chunk_length;
834 guint8 unrecognized_type;
835 tvbuff_t *unrecognized_chunk_tvb;
837 length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
839 chunk_length = length - CAUSE_HEADER_LENGTH;
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);
845 unrecognized_type = tvb_get_guint8(unrecognized_chunk_tvb, CHUNK_TYPE_OFFSET);
847 proto_item_set_text(cause_item, "Error cause reporting unrecognized chunk of type %u (%s)",
849 val_to_str(unrecognized_type, sctp_chunk_type_values, "unknown"));
853 dissect_invalid_mandatory_parameter_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
855 proto_item_set_text(cause_item, "Error cause reporting an invalid mandatory parameter");
859 dissect_unrecognized_parameters_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
861 guint16 length, padding_length, cause_info_length;
862 tvbuff_t *unrecognized_parameters_tvb;
864 length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
865 padding_length = nr_of_padding_bytes(length);
867 cause_info_length = length - CAUSE_HEADER_LENGTH + padding_length;
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);
873 proto_item_set_text(cause_item, "Error cause reporting unrecognized parameters");
877 dissect_no_user_data_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
881 tsn = tvb_get_ntohl(cause_tvb, CAUSE_TSN_OFFSET);
882 proto_tree_add_uint(cause_tree, hf_sctp_cause_tsn, cause_tvb,
887 proto_item_set_text(cause_item, "Error cause reporting data chunk with TSN %u contains no data",
892 dissect_cookie_received_while_shutting_down_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
894 proto_item_set_text(cause_item, "Error cause reporting cookie reception while shutting down");
898 dissect_unknown_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
900 guint16 code, length, cause_info_length;
902 code = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET);
903 length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
905 cause_info_length = length - CAUSE_HEADER_LENGTH;
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"));
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"));
916 dissect_error_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *chunk_tree)
918 guint16 code, length, padding_length, total_length;
919 proto_item *cause_item;
920 proto_tree *cause_tree;
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;
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);
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,
940 case INVALID_STREAM_IDENTIFIER:
941 dissect_invalid_stream_identifier_cause(cause_tvb, cause_tree, cause_item);
943 case MISSING_MANDATORY_PARAMETERS:
944 dissect_missing_mandatory_parameters_cause(cause_tvb, cause_tree, cause_item);
946 case STALE_COOKIE_ERROR:
947 dissect_stale_cookie_error_cause(cause_tvb, cause_tree, cause_item);
949 case OUT_OF_RESOURCE:
950 dissect_out_of_resource_cause(cause_tvb, cause_tree, cause_item);
952 case UNRESOLVABLE_ADDRESS:
953 dissect_unresolvable_address_cause(cause_tvb, cause_tree, cause_item);
955 case UNRECOGNIZED_CHUNK_TYPE:
956 dissect_unrecognized_chunk_type_cause(cause_tvb, pinfo, cause_tree, cause_item);
958 case INVALID_MANDATORY_PARAMETER:
959 dissect_invalid_mandatory_parameter_cause(cause_tvb, cause_tree, cause_item);
961 case UNRECOGNIZED_PARAMETERS:
962 dissect_unrecognized_parameters_cause(cause_tvb, cause_tree, cause_item);
965 dissect_no_user_data_cause(cause_tvb, cause_tree, cause_item);
967 case COOKIE_RECEIVED_WHILE_SHUTTING_DOWN:
968 dissect_cookie_received_while_shutting_down_cause(cause_tvb, cause_tree, cause_item);
971 dissect_unknown_cause(cause_tvb, cause_tree, cause_item);
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"));
981 * Code to actually dissect the packets
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)
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, pi.srcport, payload_tvb, pinfo, tree) ||
991 dissector_try_port(sctp_port_dissector_table, pi.destport, payload_tvb, pinfo, tree)){
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"));
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)
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;
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);
1027 flags = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
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);
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);
1041 proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_tsn,
1043 DATA_CHUNK_TSN_OFFSET, DATA_CHUNK_TSN_LENGTH,
1045 proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_stream_id,
1047 DATA_CHUNK_STREAM_ID_OFFSET, DATA_CHUNK_STREAM_ID_LENGTH,
1049 proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_stream_seq_number,
1051 DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET, DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH,
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"));
1061 return dissect_payload(payload_tvb, pinfo, tree, chunk_tree, payload_proto_id, payload_length, padding_length);
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)
1068 guint32 initiate_tag, adv_rec_window_credit, initial_tsn;
1069 guint16 number_of_inbound_streams, number_of_outbound_streams;
1071 tvbuff_t *parameter_list_tvb;
1073 type = tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET);
1075 if (check_col(pinfo->fd, COL_INFO)) {
1076 if (type == SCTP_INIT_CHUNK_ID) {
1077 col_append_str(pinfo->fd, COL_INFO, "INIT ");
1079 col_append_str(pinfo->fd, COL_INFO, "INIT_ACK ");
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);
1090 /* handle fixed parameters */
1091 proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_initiate_tag,
1093 INIT_CHUNK_INITIATE_TAG_OFFSET, INIT_CHUNK_INITIATE_TAG_LENGTH,
1095 proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_adv_rec_window_credit,
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,
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,
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,
1109 INIT_CHUNK_INITIAL_TSN_OFFSET, INIT_CHUNK_INITIAL_TSN_LENGTH,
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);
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"));
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)
1128 dissect_init_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
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)
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;
1142 if (check_col(pinfo->fd, COL_INFO))
1143 col_append_str(pinfo->fd, COL_INFO, "SACK ");
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);
1151 proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_cumulative_tsn_ack,
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,
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,
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,
1165 SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET, SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH,
1166 number_of_dup_tsns);
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,
1180 gap_block_offset, SACK_CHUNK_GAP_BLOCK_START_LENGTH,
1182 proto_tree_add_uint(block_tree, hf_sctp_sack_chunk_gap_block_end,
1184 gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH,
1185 SACK_CHUNK_GAP_BLOCK_END_LENGTH,
1187 gap_block_offset += SACK_CHUNK_GAP_BLOCK_LENGTH;
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,
1196 dup_tsn, SACK_CHUNK_DUP_TSN_LENGTH,
1198 dup_tsn_offset += SACK_CHUNK_DUP_TSN_LENGTH;
1201 proto_item_set_text(chunk_item,
1202 "SACK chunk acknowledging TSN %u and reporting %u gap%s and %u duplicate TSN%s",
1204 number_of_gap_blocks, plurality(number_of_gap_blocks, "", "s"),
1205 number_of_dup_tsns, plurality(number_of_dup_tsns, "", "s"));
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)
1213 tvbuff_t *parameter_tvb;
1214 guint chunk_length, info_length, padding_length, total_length;
1216 if (check_col(pinfo->fd, COL_INFO))
1217 col_append_str(pinfo->fd, COL_INFO, "HEARTBEAT ");
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);
1226 dissect_parameter(parameter_tvb, chunk_tree);
1228 proto_item_set_text(chunk_item, "HEARTBEAT chunk");
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)
1236 tvbuff_t *parameter_tvb;
1237 guint chunk_length, info_length, padding_length, total_length;
1239 if (check_col(pinfo->fd, COL_INFO))
1240 col_append_str(pinfo->fd, COL_INFO, "HEARTBEAT_ACK ");
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;
1248 parameter_tvb = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, total_length, total_length);
1250 dissect_parameter(parameter_tvb, chunk_tree);
1252 proto_item_set_text(chunk_item, "HEARTBEAT ACK chunk");
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)
1260 guint offset, number_of_causes;
1261 guint16 length, padding_length, total_length;
1262 tvbuff_t *cause_tvb;
1264 if (check_col(pinfo->fd, COL_INFO))
1265 col_append_str(pinfo->fd, COL_INFO, "ABORT ");
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;
1282 proto_item_set_text(chunk_item, "Abort chunk with %u cause%s",
1283 number_of_causes, plurality(number_of_causes, "", "s"));
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)
1291 guint32 cumulative_tsn_ack;
1293 if (check_col(pinfo->fd, COL_INFO))
1294 col_append_str(pinfo->fd, COL_INFO, "SHUTDOWN ");
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,
1300 SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET,
1301 SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_LENGTH,
1302 cumulative_tsn_ack);
1304 proto_item_set_text(chunk_item, "SHUTDOWN chunk acknowledging up to TSN %u",
1305 cumulative_tsn_ack);
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)
1313 if (check_col(pinfo->fd, COL_INFO))
1314 col_append_str(pinfo->fd, COL_INFO, "SHUTDOWN_ACK ");
1317 proto_item_set_text(chunk_item, "SHUTDOWN ACK chunk");
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)
1325 guint offset, number_of_causes;
1326 guint16 length, padding_length, total_length;
1327 tvbuff_t *cause_tvb;
1329 if (check_col(pinfo->fd, COL_INFO))
1330 col_append_str(pinfo->fd, COL_INFO, "ERROR ");
1333 number_of_causes = 0;
1334 offset = ERROR_CHUNK_FIRST_ERROR_CAUSE_OFFSET;
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;
1345 } while(tvb_length_remaining(chunk_tvb, offset));
1347 proto_item_set_text(chunk_item, "Error chunk with %u cause%s",
1348 number_of_causes, plurality(number_of_causes, "", "s"));
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)
1356 guint length, cookie_length, padding_length;
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;
1362 if (check_col(pinfo->fd, COL_INFO))
1363 col_append_str(pinfo->fd, COL_INFO, "COOKIE_ECHO ");
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"));
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"));
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)
1383 if (check_col(pinfo->fd, COL_INFO))
1384 col_append_str(pinfo->fd, COL_INFO, "COOKIE_ACK ");
1387 proto_item_set_text(chunk_item, "COOKIE ACK chunk");
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)
1397 if (check_col(pinfo->fd, COL_INFO))
1398 col_append_str(pinfo->fd, COL_INFO, "ECNE ");
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,
1404 ECNE_CHUNK_LOWEST_TSN_OFFSET, ECNE_CHUNK_LOWEST_TSN_LENGTH,
1407 proto_item_set_text(chunk_item, "ECNE chunk");
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)
1417 if (check_col(pinfo->fd, COL_INFO))
1418 col_append_str(pinfo->fd, COL_INFO, "CWR ");
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,
1424 CWR_CHUNK_LOWEST_TSN_OFFSET, CWR_CHUNK_LOWEST_TSN_LENGTH,
1427 proto_item_set_text(chunk_item, "CWR chunk");
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)
1437 proto_tree *flag_tree;
1439 if (check_col(pinfo->fd, COL_INFO))
1440 col_append_str(pinfo->fd, COL_INFO, "SHUTDOWN_COMPLETE ");
1443 flags = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
1444 length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
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);
1450 proto_item_set_text(chunk_item, "SHUTDOWN COMPLETE chunk");
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)
1458 guint length, chunk_value_length, padding_length;
1461 if (check_col(pinfo->fd, COL_INFO))
1462 col_append_str(pinfo->fd, COL_INFO, "UNKNOWN ");
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);
1469 chunk_value_length = length - CHUNK_HEADER_LENGTH;
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"));
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"));
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"));
1487 dissect_sctp_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *sctp_tree)
1492 proto_item *flags_item;
1493 proto_item *chunk_item;
1494 proto_tree *chunk_tree;
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);
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);
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,
1517 proto_tree_add_uint(chunk_tree, hf_sctp_chunk_length,
1518 chunk_tvb, CHUNK_LENGTH_OFFSET, CHUNK_LENGTH_LENGTH,
1526 /* now dissect the chunk value */
1529 case SCTP_DATA_CHUNK_ID:
1530 result = dissect_data_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1532 case SCTP_INIT_CHUNK_ID:
1533 dissect_init_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1535 case SCTP_INIT_ACK_CHUNK_ID:
1536 dissect_init_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1538 case SCTP_SACK_CHUNK_ID:
1539 dissect_sack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1541 case SCTP_HEARTBEAT_CHUNK_ID:
1542 dissect_heartbeat_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1544 case SCTP_HEARTBEAT_ACK_CHUNK_ID:
1545 dissect_heartbeat_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1547 case SCTP_ABORT_CHUNK_ID:
1548 dissect_abort_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1550 case SCTP_SHUTDOWN_CHUNK_ID:
1551 dissect_shutdown_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1553 case SCTP_SHUTDOWN_ACK_CHUNK_ID:
1554 dissect_shutdown_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1556 case SCTP_ERROR_CHUNK_ID:
1557 dissect_error_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1559 case SCTP_COOKIE_ECHO_CHUNK_ID:
1560 dissect_cookie_echo_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1562 case SCTP_COOKIE_ACK_CHUNK_ID:
1563 dissect_cookie_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1565 case SCTP_ECNE_CHUNK_ID:
1566 dissect_ecne_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1568 case SCTP_CWR_CHUNK_ID:
1569 dissect_cwr_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1571 case SCTP_SHUTDOWN_COMPLETE_CHUNK_ID:
1572 dissect_shutdown_complete_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1575 dissect_unknown_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
1582 dissect_sctp_chunks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1583 proto_item *sctp_item, proto_tree *sctp_tree)
1585 tvbuff_t *chunk_tvb;
1586 guint16 length, padding_length, total_length;
1587 gint last_offset, offset;
1588 gboolean sctp_item_length_set;
1590 /* the common header of the datagram is already handled */
1592 offset = COMMON_HEADER_LENGTH;
1593 sctp_item_length_set = FALSE;
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;
1614 /* get rid of the dissected chunk */
1615 offset += total_length;
1618 if (!sctp_item_length_set && (tree)) {
1619 proto_item_set_len(sctp_item, offset - last_offset);
1623 /* dissect_sctp handles the common header of a SCTP datagram.
1624 * For the handling of the chunks dissect_sctp_chunks is called.
1628 dissect_sctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1630 guint16 source_port, destination_port;
1631 guint32 verification_tag, checksum;
1632 proto_item *sctp_item;
1633 proto_tree *sctp_tree;
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);
1641 /* update pi structure */
1642 pinfo->ptype = PT_SCTP;
1643 pinfo->srcport = source_port;
1644 pinfo->destport = destination_port;
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");
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, "");
1654 /* In the interest of speed, if "tree" is NULL, don't do any work not
1655 necessary to generate protocol tree items. */
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);
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,
1665 proto_tree_add_uint(sctp_tree, hf_sctp_destination_port,
1666 tvb, DESTINATION_PORT_OFFSET, DESTINATION_PORT_LENGTH,
1668 proto_tree_add_uint(sctp_tree, hf_sctp_verification_tag,
1669 tvb, VERIFICATION_TAG_OFFSET, VERIFICATION_TAG_LENGTH,
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));
1679 /* add all chunks of the sctp datagram to the protocol tree */
1680 dissect_sctp_chunks(tvb, pinfo, tree, sctp_item, sctp_tree);
1683 /* Register the protocol with Ethereal */
1685 proto_register_sctp(void)
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,
1695 { &hf_sctp_destination_port,
1696 { "Destination port", "sctp.dstport",
1697 FT_UINT16, BASE_DEC, NULL, 0x0,
1700 { &hf_sctp_verification_tag,
1701 { "Verification tag", "sctp.verfication_tag",
1702 FT_UINT32, BASE_HEX, NULL, 0x0,
1705 { &hf_sctp_checksum,
1706 { "Adler-32 checksum", "sctp.checksum",
1707 FT_UINT32, BASE_HEX, NULL, 0x0,
1710 { &hf_sctp_chunk_type,
1711 { "Identifier", "sctp.chunk_type",
1712 FT_UINT8, BASE_DEC, NULL, 0x0,
1715 { &hf_sctp_chunk_flags,
1716 { "Flags", "sctp.chunk_flags",
1717 FT_UINT8, BASE_BIN, NULL, 0x0,
1720 { &hf_sctp_chunk_length,
1721 { "Length", "sctp.chunk_length",
1722 FT_UINT16, BASE_DEC, NULL, 0x0,
1725 { &hf_sctp_init_chunk_initiate_tag,
1726 { "Initiate tag", "sctp.init.chunk.initiate.tag",
1727 FT_UINT32, BASE_HEX, NULL, 0x0,
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,
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,
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,
1745 {&hf_sctp_init_chunk_initial_tsn,
1746 { "Initial TSN", "sctp.init.chunk.initial.tsn",
1747 FT_UINT32, BASE_DEC, NULL, 0x0,
1750 {&hf_sctp_cumulative_tsn_ack,
1751 { "Cumulative TSN Ack", "sctp.cumulative.tsn.ack",
1752 FT_UINT32, BASE_DEC, NULL, 0x0,
1755 {&hf_sctp_data_chunk_tsn,
1756 { "TSN", "sctp.tsn",
1757 FT_UINT32, BASE_DEC, NULL, 0x0,
1760 {&hf_sctp_data_chunk_stream_id,
1761 { "Stream Identifier", "sctp.stream_id",
1762 FT_UINT16, BASE_HEX, NULL, 0x0,
1765 {&hf_sctp_data_chunk_stream_seq_number,
1766 { "Stream sequence number", "sctp.stream_seq_number",
1767 FT_UINT16, BASE_DEC, NULL, 0x0,
1770 {&hf_sctp_data_chunk_payload_proto_id,
1771 { "Payload Protocol identifier", "sctp.payload_proto_id",
1772 FT_UINT32, BASE_HEX, NULL, 0x0,
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,
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,
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,
1790 {&hf_sctp_sack_chunk_cumulative_tsn_ack,
1791 { "Cumulative TSN ACK", "sctp.sack.cumulative_tsn_ack",
1792 FT_UINT32, BASE_DEC, NULL, 0x0,
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,
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,
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,
1810 {&hf_sctp_sack_chunk_gap_block_start,
1811 { "Start", "sctp.sack.gap_block_start",
1812 FT_UINT16, BASE_DEC, NULL, 0x0,
1815 {&hf_sctp_sack_chunk_gap_block_end,
1816 { "End", "sctp.sack.gap_block_end",
1817 FT_UINT16, BASE_DEC, NULL, 0x0,
1820 {&hf_sctp_sack_chunk_duplicate_tsn,
1821 { "Duplicate TSN", "sctp.sack.duplicate.tsn",
1822 FT_UINT16, BASE_DEC, NULL, 0x0,
1825 {&hf_sctp_shutdown_chunk_cumulative_tsn_ack,
1826 { "Cumulative TSN Ack", "sctp.shutdown.cumulative_tsn_ack",
1827 FT_UINT32, BASE_DEC, NULL, 0x0,
1830 {&hf_sctp_ecne_chunk_lowest_tsn,
1831 { "Lowest TSN", "sctp.ecne.lowest_tsn",
1832 FT_UINT32, BASE_DEC, NULL, 0x0,
1835 {&hf_sctp_cwr_chunk_lowest_tsn,
1836 { "Lowest TSN", "sctp.cwr.lowest_tsn",
1837 FT_UINT32, BASE_DEC, NULL, 0x0,
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,
1845 {&hf_sctp_chunk_parameter_type,
1846 { "Parameter type", "sctp.parameter.type",
1847 FT_UINT16, BASE_HEX, NULL, 0x0,
1850 {&hf_sctp_chunk_parameter_length,
1851 { "Parameter length", "sctp.parameter.length",
1852 FT_UINT16, BASE_DEC, NULL, 0x0,
1855 {&hf_sctp_parameter_ipv4_address,
1856 { "IP Version 4 address", "sctp.parameter.ipv4_address",
1857 FT_IPv4, BASE_NONE, NULL, 0x0,
1860 {&hf_sctp_parameter_ipv6_address,
1861 { "IP Version 6 address", "sctp.parameter.ipv6_address",
1862 FT_IPv6, BASE_NONE, NULL, 0x0,
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,
1870 {&hf_sctp_parameter_hostname_hostname,
1871 { "Hostname", "sctp.parameter.hostname.hostname",
1872 FT_STRING, BASE_NONE, NULL, 0x0,
1875 {&hf_sctp_supported_address_types_parameter,
1876 { "Supported address type", "sctp.parameter.supported_addres_type",
1877 FT_UINT16, BASE_DEC, NULL, 0x0,
1880 {&hf_sctp_cause_code,
1881 { "Cause code", "sctp.cause.code",
1882 FT_UINT16, BASE_DEC, NULL, 0x0,
1885 {&hf_sctp_cause_length,
1886 { "Cause length", "sctp.cause.length",
1887 FT_UINT16, BASE_DEC, NULL, 0x0,
1890 {&hf_sctp_cause_stream_identifier,
1891 { "Stream identifier", "sctp.cause.stream_identifier",
1892 FT_UINT16, BASE_DEC, NULL, 0x0,
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,
1900 {&hf_sctp_cause_missing_parameter_type,
1901 { "Missing parameters type", "sctp.cause.missing_parameter_type",
1902 FT_UINT16, BASE_DEC, NULL, 0x0,
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,
1910 {&hf_sctp_cause_tsn,
1911 { "TSN", "sctp.cause.tsn",
1912 FT_UINT32, BASE_DEC, NULL, 0x0,
1917 /* Setup protocol subtree array */
1918 static gint *ett[] = {
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
1929 /* Register the protocol name and description */
1930 proto_sctp = proto_register_protocol("Stream Control Transmission Protcol",
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));
1937 /* subdissector code */
1938 sctp_port_dissector_table = register_dissector_table("sctp.port");
1939 sctp_ppi_dissector_table = register_dissector_table("sctp.ppi");
1944 proto_reg_handoff_sctp(void)
1946 dissector_add("ip.proto", IP_PROTO_SCTP, dissect_sctp, proto_sctp);