aboutsummaryrefslogtreecommitdiffstats
path: root/packet-sctp.c
diff options
context:
space:
mode:
authorGilbert Ramirez <gram@alumni.rice.edu>2001-01-11 16:46:21 +0000
committerGilbert Ramirez <gram@alumni.rice.edu>2001-01-11 16:46:21 +0000
commit9e6d0e17178f8f031fa55df98e8683722f6922f3 (patch)
tree53cf1a43a0d15ed33fc00f7686a545c4fa3d1c76 /packet-sctp.c
parent916044629f1b566587752b9b06eb5028fb289459 (diff)
Update the SCTP dissector, and add a dissector for
ISDN Q.921-User Adaptation Layer (IUA). Both are from Michael.Tuexen@icn.siemens.de> svn path=/trunk/; revision=2876
Diffstat (limited to 'packet-sctp.c')
-rw-r--r--packet-sctp.c773
1 files changed, 437 insertions, 336 deletions
diff --git a/packet-sctp.c b/packet-sctp.c
index a07fbd485e..284cb2b2a5 100644
--- a/packet-sctp.c
+++ b/packet-sctp.c
@@ -2,7 +2,7 @@
* Routines for Stream Control Transmission Protocol dissection
* Copyright 2000, Michael Tüxen <Michael.Tuexen@icn.siemens.de>
*
- * $Id: packet-sctp.c,v 1.9 2001/01/09 06:31:41 guy Exp $
+ * $Id: packet-sctp.c,v 1.10 2001/01/11 16:46:21 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@unicom.net>
@@ -146,20 +146,20 @@ static gint ett_sctp_unrecognized_parameter_parameter = -1;
static const value_string sctp_chunk_type_values[] = {
{ SCTP_DATA_CHUNK_ID, "DATA" },
{ SCTP_INIT_CHUNK_ID, "INIT" },
- { SCTP_INIT_ACK_CHUNK_ID, "INIT ACK" },
+ { SCTP_INIT_ACK_CHUNK_ID, "INIT_ACK" },
{ SCTP_SACK_CHUNK_ID, "SACK" },
{ SCTP_HEARTBEAT_CHUNK_ID, "HEARTBEAT" },
- { SCTP_HEARTBEAT_ACK_CHUNK_ID, "HEARTBEAT ACK" },
+ { SCTP_HEARTBEAT_ACK_CHUNK_ID, "HEARTBEAT_ACK" },
{ SCTP_ABORT_CHUNK_ID, "ABORT" },
{ SCTP_SHUTDOWN_CHUNK_ID, "SHUTDOWN" },
- { SCTP_SHUTDOWN_ACK_CHUNK_ID, "SHUTDOWN ACK" },
+ { SCTP_SHUTDOWN_ACK_CHUNK_ID, "SHUTDOWN_ACK" },
{ SCTP_ERROR_CHUNK_ID, "ERROR" },
- { SCTP_COOKIE_ECHO_CHUNK_ID, "COOKIE ECHO" },
- { SCTP_COOKIE_ACK_CHUNK_ID, "COOKIE ACK" },
+ { SCTP_COOKIE_ECHO_CHUNK_ID, "COOKIE_ECHO" },
+ { SCTP_COOKIE_ACK_CHUNK_ID, "COOKIE_ACK" },
{ SCTP_ECNE_CHUNK_ID, "ECNE" },
{ SCTP_CWR_CHUNK_ID, "CWR" },
- { SCTP_SHUTDOWN_COMPLETE_CHUNK_ID, "SHUTDOWN COMPLETE" },
- { SCTP_IETF_EXT, "IETF EXTENSION" },
+ { SCTP_SHUTDOWN_COMPLETE_CHUNK_ID, "SHUTDOWN_COMPLETE" },
+ { SCTP_IETF_EXT, "IETF_EXTENSION" },
{ 0, NULL } };
#define HEARTBEAT_INFO_PARAMETER_ID 0x0001
@@ -257,6 +257,24 @@ static const value_string sctp_cause_code_values[] = {
{ COOKIE_RECEIVED_WHILE_SHUTTING_DOWN, "Cookie received while shutting down" },
{ 0, NULL } };
+#define NOT_SPECIFIED_PROTOCOL_ID 0
+#define IUA_PAYLOAD_PROTOCOL_ID 1
+#define M2UA_PAYLOAD_PROTOCOL_ID 2
+#define M3UA_PAYLOAD_PROTOCOL_ID 3
+#define SUA_PAYLOAD_PROTOCOL_ID 4
+#define M2PA_PAYLOAD_PROTOCOL_ID 5
+#define V5UA_PAYLOAD_PROTOCOL_ID 6
+
+static const value_string sctp_payload_proto_id_values[] = {
+ { NOT_SPECIFIED_PROTOCOL_ID, "not specified" },
+ { IUA_PAYLOAD_PROTOCOL_ID, "IUA" },
+ { M2UA_PAYLOAD_PROTOCOL_ID, "M2UA" },
+ { M3UA_PAYLOAD_PROTOCOL_ID, "M3UA" },
+ { SUA_PAYLOAD_PROTOCOL_ID, "SUA" },
+ { M2PA_PAYLOAD_PROTOCOL_ID, "M2PA" },
+ { V5UA_PAYLOAD_PROTOCOL_ID, "V5UA" },
+ { 0, NULL } };
+
/* The structure of the common header is described by the following constants */
#define SOURCE_PORT_LENGTH 2
#define DESTINATION_PORT_LENGTH 2
@@ -403,8 +421,9 @@ static const true_false_string sctp_shutdown_complete_chunk_t_bit_value = {
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
#define DO16(buf) DO8(buf,0); DO8(buf,8);
-unsigned int sctp_adler_32(const unsigned char* buf,
- unsigned int len)
+static unsigned int
+sctp_adler_32(const unsigned char* buf,
+ unsigned int len)
{
unsigned int s1 = 1L;
unsigned int s2 = 0L;
@@ -442,7 +461,8 @@ unsigned int sctp_adler_32(const unsigned char* buf,
return (s2 << 16) | s1;
}
-static char *sctp_checksum_state(tvbuff_t *tvb, guint orig_checksum)
+static char
+*sctp_checksum_state(tvbuff_t *tvb, guint orig_checksum)
{
guint length;
@@ -453,7 +473,7 @@ static char *sctp_checksum_state(tvbuff_t *tvb, guint orig_checksum)
return "incorrect";
}
-guint
+static guint
nr_of_padding_bytes (guint length)
{
guint remainder;
@@ -470,13 +490,14 @@ nr_of_padding_bytes (guint length)
* TLV parameter stuff for INIT and INIT-ACK chunks
*/
-void
+static void
dissect_parameter(tvbuff_t *, proto_tree *);
-void
+static void
dissect_sctp_chunk(tvbuff_t *, packet_info *, proto_tree *, proto_tree *);
-void dissect_tlv_parameter_list(tvbuff_t *parameter_list_tvb, proto_tree *tree)
+static void
+dissect_tlv_parameter_list(tvbuff_t *parameter_list_tvb, proto_tree *tree)
{
guint offset, length, padding_length, total_length;
tvbuff_t *parameter_tvb;
@@ -494,7 +515,7 @@ void dissect_tlv_parameter_list(tvbuff_t *parameter_list_tvb, proto_tree *tree)
}
}
-void
+static void
dissect_heartbeat_info_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
{
guint16 length, heartbeat_info_length;
@@ -511,7 +532,7 @@ dissect_heartbeat_info_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_
heartbeat_info_length, plurality(heartbeat_info_length, "", "s"));
}
-void
+static void
dissect_ipv4_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
{
guint32 ipv4_address;
@@ -523,7 +544,7 @@ dissect_ipv4_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, prot
proto_item_set_text(parameter_item, "IPV4 address parameter");
}
-void
+static void
dissect_ipv6_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
{
proto_tree_add_ipv6(parameter_tree, hf_sctp_parameter_ipv6_address,
@@ -533,7 +554,7 @@ dissect_ipv6_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, prot
proto_item_set_text(parameter_item, "IPV6 address parameter");
}
-void
+static void
dissect_state_cookie_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
{
guint16 length, state_cookie_length;
@@ -550,7 +571,7 @@ dissect_state_cookie_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tr
state_cookie_length, plurality(state_cookie_length, "", "s"));
}
-void
+static void
dissect_unrecognized_parameters_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
{
guint16 length, parameter_value_length;
@@ -567,7 +588,7 @@ dissect_unrecognized_parameters_parameter(tvbuff_t *parameter_tvb, proto_tree *p
proto_item_set_text(parameter_item, "Unrecognized parameter of type");
}
-void
+static void
dissect_cookie_preservative_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
{
guint32 increment;
@@ -583,7 +604,7 @@ dissect_cookie_preservative_parameter(tvbuff_t *parameter_tvb, proto_tree *param
increment);
}
-void
+static void
dissect_hostname_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
{
guint16 length, hostname_length;
@@ -600,7 +621,7 @@ dissect_hostname_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree,
proto_item_set_text(parameter_item, "Hostname parameter");
}
-void
+static void
dissect_supported_address_types_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
{
guint16 length, address_type, number_of_address_types, address_type_number, list_of_address_types_length ;
@@ -631,13 +652,13 @@ dissect_supported_address_types_parameter(tvbuff_t *parameter_tvb, proto_tree *p
number_of_address_types, plurality(number_of_address_types, "", "s"));
}
-void
+static void
dissect_ecn_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
{
proto_item_set_text(parameter_item, "ECN parameter");
}
-void
+static void
dissect_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
{
guint16 type, length, parameter_value_length;
@@ -655,7 +676,7 @@ dissect_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, p
type, parameter_value_length, plurality(parameter_value_length, "", "s"));
}
-void
+static void
dissect_parameter(tvbuff_t *parameter_tvb, proto_tree *chunk_tree)
{
guint16 type, length, padding_length, total_length;
@@ -719,7 +740,7 @@ dissect_parameter(tvbuff_t *parameter_tvb, proto_tree *chunk_tree)
/*
* Code to handle error causes for ABORT and ERROR chunks
*/
-void
+static void
dissect_invalid_stream_identifier_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
{
guint16 stream_identifier;
@@ -735,7 +756,7 @@ dissect_invalid_stream_identifier_cause(tvbuff_t *cause_tvb, proto_tree *cause_t
stream_identifier);
}
-void
+static void
dissect_missing_mandatory_parameters_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
{
guint32 number_of_missing_parameters, missing_parameter_number;
@@ -761,7 +782,7 @@ dissect_missing_mandatory_parameters_cause(tvbuff_t *cause_tvb, proto_tree *caus
number_of_missing_parameters, plurality(number_of_missing_parameters, "", "s") );
}
-void
+static void
dissect_stale_cookie_error_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
{
guint32 measure_of_staleness;
@@ -777,13 +798,13 @@ dissect_stale_cookie_error_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, pr
measure_of_staleness);
}
-void
+static void
dissect_out_of_resource_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
{
proto_item_set_text(cause_item, "Error cause reporting lack of resources");
}
-void
+static void
dissect_unresolvable_address_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
{
guint16 code, length, parameter_length, parameter_type;
@@ -803,7 +824,7 @@ dissect_unresolvable_address_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree,
parameter_type, val_to_str(parameter_type, sctp_parameter_identifier_values, "unknown") );
}
-void
+static void
dissect_unrecognized_chunk_type_cause(tvbuff_t *cause_tvb, packet_info *pinfo,
proto_tree *cause_tree, proto_item *cause_item)
{
@@ -826,13 +847,13 @@ dissect_unrecognized_chunk_type_cause(tvbuff_t *cause_tvb, packet_info *pinfo,
val_to_str(unrecognized_type, sctp_chunk_type_values, "unknown"));
}
-void
+static void
dissect_invalid_mandatory_parameter_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
{
proto_item_set_text(cause_item, "Error cause reporting an invalid mandatory parameter");
}
-void
+static void
dissect_unrecognized_parameters_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
{
guint16 length, cause_info_length;
@@ -849,7 +870,7 @@ dissect_unrecognized_parameters_cause(tvbuff_t *cause_tvb, proto_tree *cause_tre
proto_item_set_text(cause_item, "Error cause reporting unrecognized parameters");
}
-void
+static void
dissect_no_user_data_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
{
guint32 tsn;
@@ -864,13 +885,13 @@ dissect_no_user_data_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_it
tsn);
}
-void
+static void
dissect_cookie_received_while_shutting_down_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
{
proto_item_set_text(cause_item, "Error cause reporting cookie reception while shutting down");
}
-void
+static void
dissect_unknown_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
{
guint16 code, length, cause_info_length;
@@ -888,7 +909,7 @@ dissect_unknown_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *c
code, cause_info_length, plurality(cause_info_length, "", "s"));
}
-void
+static void
dissect_error_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *chunk_tree)
{
guint16 code, length, padding_length, total_length;
@@ -964,8 +985,11 @@ dissect_payload(tvbuff_t *payload_tvb, packet_info *pinfo, proto_tree *tree,
/* do lookup with the subdissector table */
if (dissector_try_port(sctp_dissector_table, pi.srcport, payload_tvb, pinfo, tree) ||
dissector_try_port(sctp_dissector_table, pi.destport, payload_tvb, pinfo, tree))
+
return;
else {
+ if (check_col(pinfo->fd, COL_INFO))
+ col_append_str(pinfo->fd, COL_INFO, "DATA ");
proto_tree_add_text(chunk_tree, payload_tvb, 0, payload_length,
"Payload (%u byte%s)",
payload_length, plurality(payload_length, "", "s"));
@@ -976,10 +1000,6 @@ dissect_payload(tvbuff_t *payload_tvb, packet_info *pinfo, proto_tree *tree,
}
}
-
-
-
-
static void
dissect_data_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
@@ -989,53 +1009,54 @@ dissect_data_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
guint32 tsn, payload_proto_id;
proto_tree *flag_tree;
tvbuff_t *payload_tvb;
-
- flags = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
- length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
- flag_tree = proto_item_add_subtree(flags_item, ett_sctp_data_chunk_flags);
- proto_tree_add_boolean(flag_tree, hf_sctp_data_chunk_e_bit, chunk_tvb,
- CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
- proto_tree_add_boolean(flag_tree, hf_sctp_data_chunk_b_bit, chunk_tvb,
- CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
- proto_tree_add_boolean(flag_tree, hf_sctp_data_chunk_u_bit, chunk_tvb,
- CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
-
- tsn = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_TSN_OFFSET);
- stream_id = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET);
- stream_seq_number = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET);
- payload_proto_id = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET);
-
+ length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
payload_length = length - DATA_CHUNK_HEADER_LENGTH;
padding_length = nr_of_padding_bytes(length);
total_payload_length = payload_length + padding_length;
payload_tvb = tvb_new_subset(chunk_tvb, DATA_CHUNK_PAYLOAD_OFFSET,
- total_payload_length, total_payload_length);
-
- proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_tsn,
- chunk_tvb,
- DATA_CHUNK_TSN_OFFSET, DATA_CHUNK_TSN_LENGTH,
- tsn);
- proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_stream_id,
- chunk_tvb,
- DATA_CHUNK_STREAM_ID_OFFSET, DATA_CHUNK_STREAM_ID_LENGTH,
- stream_id);
- proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_stream_seq_number,
- chunk_tvb,
- DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET, DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH,
- stream_seq_number);
- proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_payload_proto_id,
- chunk_tvb,
- DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH,
- payload_proto_id);
- proto_item_set_text(chunk_item, "DATA chunk with TSN %u (%u:%u) containing %u byte%s of payload",
- tsn, stream_id, stream_seq_number,
- payload_length, plurality(payload_length, "", "s"));
-
- dissect_payload(payload_tvb, pinfo, tree, chunk_tree, payload_length, padding_length);
-}
+ total_payload_length, total_payload_length);
+
+ if (chunk_tree) {
+ flags = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
+
+ flag_tree = proto_item_add_subtree(flags_item, ett_sctp_data_chunk_flags);
+ proto_tree_add_boolean(flag_tree, hf_sctp_data_chunk_e_bit, chunk_tvb,
+ CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
+ proto_tree_add_boolean(flag_tree, hf_sctp_data_chunk_b_bit, chunk_tvb,
+ CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
+ proto_tree_add_boolean(flag_tree, hf_sctp_data_chunk_u_bit, chunk_tvb,
+ CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
+
+ tsn = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_TSN_OFFSET);
+ stream_id = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET);
+ stream_seq_number = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET);
+ payload_proto_id = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET);
+
+ proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_tsn,
+ chunk_tvb,
+ DATA_CHUNK_TSN_OFFSET, DATA_CHUNK_TSN_LENGTH,
+ tsn);
+ proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_stream_id,
+ chunk_tvb,
+ DATA_CHUNK_STREAM_ID_OFFSET, DATA_CHUNK_STREAM_ID_LENGTH,
+ stream_id);
+ proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_stream_seq_number,
+ chunk_tvb,
+ DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET, DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH,
+ stream_seq_number);
+ proto_tree_add_uint_format(chunk_tree, hf_sctp_data_chunk_payload_proto_id,
+ chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH,
+ payload_proto_id, "Payload protocol identifier: %u (%s)",
+ payload_proto_id, val_to_str(payload_proto_id, sctp_payload_proto_id_values, "unknown"));
+ proto_item_set_text(chunk_item, "DATA chunk with TSN %u (%u:%u) containing %u byte%s of payload",
+ tsn, stream_id, stream_seq_number,
+ payload_length, plurality(payload_length, "", "s"));
+ };
+ dissect_payload(payload_tvb, pinfo, tree, chunk_tree, payload_length, padding_length);
+}
-void
+static void
dissect_init_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
{
@@ -1045,54 +1066,64 @@ dissect_init_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
tvbuff_t *parameter_list_tvb;
type = tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET);
-
- initiate_tag = tvb_get_ntohl(chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET);
- adv_rec_window_credit = tvb_get_ntohl(chunk_tvb, INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET);
- number_of_inbound_streams = tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET);
- number_of_outbound_streams = tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET);
- initial_tsn = tvb_get_ntohl(chunk_tvb, INIT_CHUNK_INITIAL_TSN_OFFSET);
-
- /* handle fixed parameters */
- proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_initiate_tag,
- chunk_tvb,
- INIT_CHUNK_INITIATE_TAG_OFFSET, INIT_CHUNK_INITIATE_TAG_LENGTH,
- initiate_tag);
- proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_adv_rec_window_credit,
- chunk_tvb,
- INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET, INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH,
- adv_rec_window_credit);
- proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_number_of_outbound_streams,
- chunk_tvb,
- INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH,
- number_of_outbound_streams);
- proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_number_of_inbound_streams,
- chunk_tvb,
- INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH,
- number_of_inbound_streams);
- proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_initial_tsn,
- chunk_tvb,
- INIT_CHUNK_INITIAL_TSN_OFFSET, INIT_CHUNK_INITIAL_TSN_LENGTH,
- initial_tsn);
- /* handle variable paramters */
- parameter_list_tvb = tvb_new_subset(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET, -1, -1);
- dissect_tlv_parameter_list(parameter_list_tvb, chunk_tree);
-
- proto_item_set_text(chunk_item,
- "%s chunk requesting for %u outbound stream%s and accepting up to %u inbound stream%s",
- val_to_str(type, sctp_chunk_type_values, "unknown"),
- number_of_outbound_streams, plurality(number_of_outbound_streams, "", "s"),
- number_of_inbound_streams, plurality(number_of_inbound_streams, "", "s"));
+ if (check_col(pinfo->fd, COL_INFO)) {
+ if (type == SCTP_INIT_CHUNK_ID) {
+ col_append_str(pinfo->fd, COL_INFO, "INIT ");
+ } else {
+ col_append_str(pinfo->fd, COL_INFO, "INIT_ACK ");
+ };
+ };
+
+ if (chunk_tree) {
+ initiate_tag = tvb_get_ntohl(chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET);
+ adv_rec_window_credit = tvb_get_ntohl(chunk_tvb, INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET);
+ number_of_inbound_streams = tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET);
+ number_of_outbound_streams = tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET);
+ initial_tsn = tvb_get_ntohl(chunk_tvb, INIT_CHUNK_INITIAL_TSN_OFFSET);
+
+ /* handle fixed parameters */
+ proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_initiate_tag,
+ chunk_tvb,
+ INIT_CHUNK_INITIATE_TAG_OFFSET, INIT_CHUNK_INITIATE_TAG_LENGTH,
+ initiate_tag);
+ proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_adv_rec_window_credit,
+ chunk_tvb,
+ INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET, INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH,
+ adv_rec_window_credit);
+ proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_number_of_outbound_streams,
+ chunk_tvb,
+ INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH,
+ number_of_outbound_streams);
+ proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_number_of_inbound_streams,
+ chunk_tvb,
+ INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH,
+ number_of_inbound_streams);
+ proto_tree_add_uint(chunk_tree, hf_sctp_init_chunk_initial_tsn,
+ chunk_tvb,
+ INIT_CHUNK_INITIAL_TSN_OFFSET, INIT_CHUNK_INITIAL_TSN_LENGTH,
+ initial_tsn);
+
+ /* handle variable paramters */
+ parameter_list_tvb = tvb_new_subset(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET, -1, -1);
+ dissect_tlv_parameter_list(parameter_list_tvb, chunk_tree);
+
+ proto_item_set_text(chunk_item,
+ "%s chunk requesting for %u outbound stream%s and accepting up to %u inbound stream%s",
+ val_to_str(type, sctp_chunk_type_values, "unknown"),
+ number_of_outbound_streams, plurality(number_of_outbound_streams, "", "s"),
+ number_of_inbound_streams, plurality(number_of_inbound_streams, "", "s"));
+ }
}
-void
+static void
dissect_init_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
{
dissect_init_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
}
-void
+static void
dissect_sack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
{
@@ -1102,117 +1133,136 @@ dissect_sack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
gint gap_block_offset, dup_tsn_offset;
proto_item *block_item;
proto_tree *block_tree;
-
- cumulative_tsn_ack = tvb_get_ntohl(chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
- adv_rec_window_credit = tvb_get_ntohl(chunk_tvb, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET);
- number_of_gap_blocks = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET);
- number_of_dup_tsns = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET);
-
- proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_cumulative_tsn_ack,
- chunk_tvb,
- SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET, SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH,
- cumulative_tsn_ack);
- proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_adv_rec_window_credit,
- chunk_tvb,
- SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH,
- adv_rec_window_credit);
- proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_number_of_gap_blocks,
- chunk_tvb,
- SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH,
- number_of_gap_blocks);
- proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_number_of_dup_tsns,
- chunk_tvb,
- SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET, SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH,
- number_of_dup_tsns);
- /* handle the gap acknowledgement blocks */
- gap_block_offset = SACK_CHUNK_GAP_BLOCK_OFFSET;
- for(gap_block_number = 1; gap_block_number <= number_of_gap_blocks; gap_block_number++) {
- start = tvb_get_ntohs(chunk_tvb, gap_block_offset);
- end = tvb_get_ntohs(chunk_tvb, gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH);
- block_item = proto_tree_add_text(chunk_tree, chunk_tvb,
- gap_block_offset, SACK_CHUNK_GAP_BLOCK_LENGTH,
- "Gap Acknowledgement for %u TSN%s",
- 1 + end - start, plurality(1 + end - start, "", "s"));
- block_tree = proto_item_add_subtree(block_item, ett_sctp_sack_chunk_gap_block);
- proto_tree_add_uint(block_tree, hf_sctp_sack_chunk_gap_block_start,
+ if (check_col(pinfo->fd, COL_INFO))
+ col_append_str(pinfo->fd, COL_INFO, "SACK ");
+
+ if (chunk_tree) {
+ cumulative_tsn_ack = tvb_get_ntohl(chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
+ adv_rec_window_credit = tvb_get_ntohl(chunk_tvb, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET);
+ number_of_gap_blocks = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET);
+ number_of_dup_tsns = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET);
+
+ proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_cumulative_tsn_ack,
chunk_tvb,
- gap_block_offset, SACK_CHUNK_GAP_BLOCK_START_LENGTH,
- start);
- proto_tree_add_uint(block_tree, hf_sctp_sack_chunk_gap_block_end,
+ SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET, SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH,
+ cumulative_tsn_ack);
+ proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_adv_rec_window_credit,
chunk_tvb,
- gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH,
- SACK_CHUNK_GAP_BLOCK_END_LENGTH,
- end);
- gap_block_offset += SACK_CHUNK_GAP_BLOCK_LENGTH;
- };
-
- /* handle the duplicate TSNs */
- dup_tsn_offset = SACK_CHUNK_GAP_BLOCK_OFFSET + number_of_gap_blocks * SACK_CHUNK_GAP_BLOCK_LENGTH;
- for(dup_tsn_number = 1; dup_tsn_number <= number_of_dup_tsns; dup_tsn_number++) {
- dup_tsn = tvb_get_ntohl(chunk_tvb, dup_tsn_offset);
- proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_duplicate_tsn,
+ SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH,
+ adv_rec_window_credit);
+ proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_number_of_gap_blocks,
chunk_tvb,
- dup_tsn, SACK_CHUNK_DUP_TSN_LENGTH,
- dup_tsn);
- dup_tsn_offset += SACK_CHUNK_DUP_TSN_LENGTH;
- };
-
- proto_item_set_text(chunk_item,
- "SACK chunk acknowledging TSN %u and reporting %u gap%s and %u duplicate TSN%s",
- cumulative_tsn_ack,
- number_of_gap_blocks, plurality(number_of_gap_blocks, "", "s"),
- number_of_dup_tsns, plurality(number_of_dup_tsns, "", "s"));
-}
+ SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH,
+ number_of_gap_blocks);
+ proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_number_of_dup_tsns,
+ chunk_tvb,
+ SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET, SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH,
+ number_of_dup_tsns);
+
+ /* handle the gap acknowledgement blocks */
+ gap_block_offset = SACK_CHUNK_GAP_BLOCK_OFFSET;
+ for(gap_block_number = 1; gap_block_number <= number_of_gap_blocks; gap_block_number++) {
+ start = tvb_get_ntohs(chunk_tvb, gap_block_offset);
+ end = tvb_get_ntohs(chunk_tvb, gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH);
+ block_item = proto_tree_add_text(chunk_tree, chunk_tvb,
+ gap_block_offset, SACK_CHUNK_GAP_BLOCK_LENGTH,
+ "Gap Acknowledgement for %u TSN%s",
+ 1 + end - start, plurality(1 + end - start, "", "s"));
+ block_tree = proto_item_add_subtree(block_item, ett_sctp_sack_chunk_gap_block);
+ proto_tree_add_uint(block_tree, hf_sctp_sack_chunk_gap_block_start,
+ chunk_tvb,
+ gap_block_offset, SACK_CHUNK_GAP_BLOCK_START_LENGTH,
+ start);
+ proto_tree_add_uint(block_tree, hf_sctp_sack_chunk_gap_block_end,
+ chunk_tvb,
+ gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH,
+ SACK_CHUNK_GAP_BLOCK_END_LENGTH,
+ end);
+ gap_block_offset += SACK_CHUNK_GAP_BLOCK_LENGTH;
+ };
+
+ /* handle the duplicate TSNs */
+ dup_tsn_offset = SACK_CHUNK_GAP_BLOCK_OFFSET + number_of_gap_blocks * SACK_CHUNK_GAP_BLOCK_LENGTH;
+ for(dup_tsn_number = 1; dup_tsn_number <= number_of_dup_tsns; dup_tsn_number++) {
+ dup_tsn = tvb_get_ntohl(chunk_tvb, dup_tsn_offset);
+ proto_tree_add_uint(chunk_tree, hf_sctp_sack_chunk_duplicate_tsn,
+ chunk_tvb,
+ dup_tsn, SACK_CHUNK_DUP_TSN_LENGTH,
+ dup_tsn);
+ dup_tsn_offset += SACK_CHUNK_DUP_TSN_LENGTH;
+ }
+
+ proto_item_set_text(chunk_item,
+ "SACK chunk acknowledging TSN %u and reporting %u gap%s and %u duplicate TSN%s",
+ cumulative_tsn_ack,
+ number_of_gap_blocks, plurality(number_of_gap_blocks, "", "s"),
+ number_of_dup_tsns, plurality(number_of_dup_tsns, "", "s"));
+ }
+}
-void
+static void
dissect_heartbeat_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
{
tvbuff_t *parameter_tvb;
guint chunk_length, info_length, padding_length, total_length;
-
- chunk_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
- info_length = chunk_length - CHUNK_HEADER_LENGTH;
- padding_length = nr_of_padding_bytes(info_length);
- total_length = info_length + padding_length;
- parameter_tvb = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, total_length, total_length);
- dissect_parameter(parameter_tvb, chunk_tree);
-
- proto_item_set_text(chunk_item, "HEARTBEAT chunk");
+ if (check_col(pinfo->fd, COL_INFO))
+ col_append_str(pinfo->fd, COL_INFO, "HEARTBEAT ");
+
+ if (chunk_tree) {
+ chunk_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
+ info_length = chunk_length - CHUNK_HEADER_LENGTH;
+ padding_length = nr_of_padding_bytes(info_length);
+ total_length = info_length + padding_length;
+ parameter_tvb = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, total_length, total_length);
+
+ dissect_parameter(parameter_tvb, chunk_tree);
+
+ proto_item_set_text(chunk_item, "HEARTBEAT chunk");
+ }
}
-void
+static void
dissect_heartbeat_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
{
tvbuff_t *parameter_tvb;
guint chunk_length, info_length, padding_length, total_length;
+
+ if (check_col(pinfo->fd, COL_INFO))
+ col_append_str(pinfo->fd, COL_INFO, "HEARTBEAT_ACK ");
- chunk_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
- info_length = chunk_length - CHUNK_HEADER_LENGTH;
- padding_length = nr_of_padding_bytes(info_length);
- total_length = info_length + padding_length;
+ if (chunk_tree) {
+ chunk_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
+ info_length = chunk_length - CHUNK_HEADER_LENGTH;
+ padding_length = nr_of_padding_bytes(info_length);
+ total_length = info_length + padding_length;
- parameter_tvb = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, total_length, total_length);
+ parameter_tvb = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, total_length, total_length);
- dissect_parameter(parameter_tvb, chunk_tree);
-
- proto_item_set_text(chunk_item, "HEARTBEAT ACK chunk");
-}
+ dissect_parameter(parameter_tvb, chunk_tree);
+
+ proto_item_set_text(chunk_item, "HEARTBEAT ACK chunk");
+ }
+}
-void
+static void
dissect_abort_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
{
guint offset, number_of_causes;
guint16 length, padding_length, total_length;
tvbuff_t *cause_tvb;
+
+ if (check_col(pinfo->fd, COL_INFO))
+ col_append_str(pinfo->fd, COL_INFO, "ABORT ");
- number_of_causes = 0;
- offset = ABORT_CHUNK_FIRST_ERROR_CAUSE_OFFSET;
- while(tvb_length_remaining(chunk_tvb, offset)) {
+ if (chunk_tree) {
+ number_of_causes = 0;
+ offset = ABORT_CHUNK_FIRST_ERROR_CAUSE_OFFSET;
+ while(tvb_length_remaining(chunk_tvb, offset)) {
length = tvb_get_ntohs(chunk_tvb, offset + CAUSE_LENGTH_OFFSET);
padding_length = nr_of_padding_bytes(length);
total_length = length + padding_length;
@@ -1222,37 +1272,48 @@ dissect_abort_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
/* get rid of the handled parameter */
offset += total_length;
number_of_causes++;
- };
-
- proto_item_set_text(chunk_item, "Abort chunk with %u cause%s",
- number_of_causes, plurality(number_of_causes, "", "s"));
-}
+ };
+
+ proto_item_set_text(chunk_item, "Abort chunk with %u cause%s",
+ number_of_causes, plurality(number_of_causes, "", "s"));
+ }
+}
-void
+static void
dissect_shutdown_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
{
guint32 cumulative_tsn_ack;
+
+ if (check_col(pinfo->fd, COL_INFO))
+ col_append_str(pinfo->fd, COL_INFO, "SHUTDOWN ");
- cumulative_tsn_ack = tvb_get_ntohl(chunk_tvb, SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
- proto_tree_add_uint(chunk_tree, hf_sctp_shutdown_chunk_cumulative_tsn_ack,
- chunk_tvb,
- SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET,
- SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_LENGTH,
- cumulative_tsn_ack);
-
- proto_item_set_text(chunk_item, "SHUTDOWN chunk acknowledging up to TSN %u",
- cumulative_tsn_ack);
-}
+ if (chunk_tree) {
+ cumulative_tsn_ack = tvb_get_ntohl(chunk_tvb, SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
+ proto_tree_add_uint(chunk_tree, hf_sctp_shutdown_chunk_cumulative_tsn_ack,
+ chunk_tvb,
+ SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET,
+ SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_LENGTH,
+ cumulative_tsn_ack);
+
+ proto_item_set_text(chunk_item, "SHUTDOWN chunk acknowledging up to TSN %u",
+ cumulative_tsn_ack);
+ }
+}
-void
+static void
dissect_shutdown_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
{
- proto_item_set_text(chunk_item, "SHUTDOWN ACK chunk");
-}
+ if (check_col(pinfo->fd, COL_INFO))
+ col_append_str(pinfo->fd, COL_INFO, "SHUTDOWN_ACK ");
-void
+ if (chunk_tree) {
+ proto_item_set_text(chunk_item, "SHUTDOWN ACK chunk");
+ }
+}
+
+static void
dissect_error_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
{
@@ -1260,25 +1321,30 @@ dissect_error_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
guint16 length, padding_length, total_length;
tvbuff_t *cause_tvb;
- number_of_causes = 0;
- offset = ERROR_CHUNK_FIRST_ERROR_CAUSE_OFFSET;
- do {
- length = tvb_get_ntohs(chunk_tvb, offset + CAUSE_LENGTH_OFFSET);
- padding_length = nr_of_padding_bytes(length);
- total_length = length + padding_length;
- /* create a tvb for the chunk including the padding bytes */
- cause_tvb = tvb_new_subset(chunk_tvb, offset, total_length, total_length);
- dissect_error_cause(cause_tvb, pinfo, chunk_tree);
- /* get rid of the handled parameter */
- offset += total_length;
- number_of_causes++;
- } while(tvb_length_remaining(chunk_tvb, offset));
-
- proto_item_set_text(chunk_item, "Error chunk with %u cause%s",
- number_of_causes, plurality(number_of_causes, "", "s"));
-}
+ if (check_col(pinfo->fd, COL_INFO))
+ col_append_str(pinfo->fd, COL_INFO, "ERROR ");
+
+ if (chunk_tree) {
+ number_of_causes = 0;
+ offset = ERROR_CHUNK_FIRST_ERROR_CAUSE_OFFSET;
+ do {
+ length = tvb_get_ntohs(chunk_tvb, offset + CAUSE_LENGTH_OFFSET);
+ padding_length = nr_of_padding_bytes(length);
+ total_length = length + padding_length;
+ /* create a tvb for the chunk including the padding bytes */
+ cause_tvb = tvb_new_subset(chunk_tvb, offset, total_length, total_length);
+ dissect_error_cause(cause_tvb, pinfo, chunk_tree);
+ /* get rid of the handled parameter */
+ offset += total_length;
+ number_of_causes++;
+ } while(tvb_length_remaining(chunk_tvb, offset));
+
+ proto_item_set_text(chunk_item, "Error chunk with %u cause%s",
+ number_of_causes, plurality(number_of_causes, "", "s"));
+ }
+}
-void
+static void
dissect_cookie_echo_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
{
@@ -1287,104 +1353,132 @@ dissect_cookie_echo_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *t
length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
padding_length = nr_of_padding_bytes(length);
cookie_length = length - CHUNK_HEADER_LENGTH;
-
- proto_tree_add_text(chunk_tree, chunk_tvb, COOKIE_ECHO_CHUNK_COOKIE_OFFSET, cookie_length,
- "Cookie (%u byte%s)",
- cookie_length, plurality(cookie_length, "", "s"));
- proto_item_set_text(chunk_item, "COOKIE ECHO chunk containing a cookie of %u byte%s",
- cookie_length, plurality(cookie_length, "", "s"));
-
- if (padding_length > 0)
- proto_tree_add_text(chunk_tree, chunk_tvb, CHUNK_HEADER_OFFSET + length, padding_length,
- "Padding: %u byte%s",
- padding_length, plurality(padding_length, "", "s"));
-}
+
+ if (check_col(pinfo->fd, COL_INFO))
+ col_append_str(pinfo->fd, COL_INFO, "COOKIE_ECHO ");
+
+ if (chunk_tree) {
+ proto_tree_add_text(chunk_tree, chunk_tvb, COOKIE_ECHO_CHUNK_COOKIE_OFFSET, cookie_length,
+ "Cookie (%u byte%s)",
+ cookie_length, plurality(cookie_length, "", "s"));
+ proto_item_set_text(chunk_item, "COOKIE ECHO chunk containing a cookie of %u byte%s",
+ cookie_length, plurality(cookie_length, "", "s"));
+
+ if (padding_length > 0)
+ proto_tree_add_text(chunk_tree, chunk_tvb, CHUNK_HEADER_OFFSET + length, padding_length,
+ "Padding: %u byte%s",
+ padding_length, plurality(padding_length, "", "s"));
+ }
+}
-void
+static void
dissect_cookie_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
-{
- proto_item_set_text(chunk_item, "COOKIE ACK chunk");
-}
+{
+ if (check_col(pinfo->fd, COL_INFO))
+ col_append_str(pinfo->fd, COL_INFO, "COOKIE_ACK ");
-void
+ if (chunk_tree) {
+ proto_item_set_text(chunk_item, "COOKIE ACK chunk");
+ }
+}
+
+static void
dissect_ecne_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
{
guint32 lowest_tsn;
+
+ if (check_col(pinfo->fd, COL_INFO))
+ col_append_str(pinfo->fd, COL_INFO, "ECNE ");
- lowest_tsn = tvb_get_ntohl(chunk_tvb, ECNE_CHUNK_LOWEST_TSN_OFFSET);
- proto_tree_add_uint(chunk_tree, hf_sctp_ecne_chunk_lowest_tsn,
- chunk_tvb,
- ECNE_CHUNK_LOWEST_TSN_OFFSET, ECNE_CHUNK_LOWEST_TSN_LENGTH,
- lowest_tsn);
-
- proto_item_set_text(chunk_item, "ECNE chunk");
-}
+ if (chunk_tree) {
+ lowest_tsn = tvb_get_ntohl(chunk_tvb, ECNE_CHUNK_LOWEST_TSN_OFFSET);
+ proto_tree_add_uint(chunk_tree, hf_sctp_ecne_chunk_lowest_tsn,
+ chunk_tvb,
+ ECNE_CHUNK_LOWEST_TSN_OFFSET, ECNE_CHUNK_LOWEST_TSN_LENGTH,
+ lowest_tsn);
+
+ proto_item_set_text(chunk_item, "ECNE chunk");
+ }
+}
-void
+static void
dissect_cwr_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
{
guint32 lowest_tsn;
+
+ if (check_col(pinfo->fd, COL_INFO))
+ col_append_str(pinfo->fd, COL_INFO, "CWR ");
- lowest_tsn = tvb_get_ntohl(chunk_tvb, CWR_CHUNK_LOWEST_TSN_OFFSET);
- proto_tree_add_uint(chunk_tree, hf_sctp_cwr_chunk_lowest_tsn,
- chunk_tvb,
- CWR_CHUNK_LOWEST_TSN_OFFSET, CWR_CHUNK_LOWEST_TSN_LENGTH,
- lowest_tsn);
-
- proto_item_set_text(chunk_item, "CWR chunk");
-}
+ if (chunk_tree) {
+ lowest_tsn = tvb_get_ntohl(chunk_tvb, CWR_CHUNK_LOWEST_TSN_OFFSET);
+ proto_tree_add_uint(chunk_tree, hf_sctp_cwr_chunk_lowest_tsn,
+ chunk_tvb,
+ CWR_CHUNK_LOWEST_TSN_OFFSET, CWR_CHUNK_LOWEST_TSN_LENGTH,
+ lowest_tsn);
+
+ proto_item_set_text(chunk_item, "CWR chunk");
+ }
+}
-void
+static void
dissect_shutdown_complete_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
{
guint8 flags;
guint16 length;
proto_tree *flag_tree;
+
+ if (check_col(pinfo->fd, COL_INFO))
+ col_append_str(pinfo->fd, COL_INFO, "SHUTDOWN_COMPLETE ");
- flags = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
- length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
-
- flag_tree = proto_item_add_subtree(flags_item, ett_sctp_data_chunk_flags);
- proto_tree_add_boolean(flag_tree, hf_sctp_shutdown_complete_chunk_t_bit, chunk_tvb,
- CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
-
- proto_item_set_text(chunk_item, "SHUTDOWN COMPLETE chunk");
-}
+ if (chunk_tree) {
+ flags = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
+ length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
+
+ flag_tree = proto_item_add_subtree(flags_item, ett_sctp_data_chunk_flags);
+ proto_tree_add_boolean(flag_tree, hf_sctp_shutdown_complete_chunk_t_bit, chunk_tvb,
+ CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, flags);
+
+ proto_item_set_text(chunk_item, "SHUTDOWN COMPLETE chunk");
+ }
+}
-void
+static void
dissect_unknown_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
{
guint length, chunk_value_length, padding_length;
guint8 type;
-
- length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
- padding_length = nr_of_padding_bytes(length);
- type = tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET);
-
- chunk_value_length = length - CHUNK_HEADER_LENGTH;
-
- proto_tree_add_text(chunk_tree, chunk_tvb, CHUNK_VALUE_OFFSET, chunk_value_length,
- "Chunk value (%u byte%s)",
- chunk_value_length, plurality(chunk_value_length, "", "s"));
- if (padding_length > 0)
- proto_tree_add_text(chunk_tree, chunk_tvb, CHUNK_HEADER_OFFSET + length, padding_length,
- "Padding: %u byte%s",
- padding_length, plurality(padding_length, "", "s"));
-
- proto_item_set_text(chunk_item, "Chunk of type %u and %u byte%s value",
- type, chunk_value_length, plurality(chunk_value_length, "", "s"));
+ if (check_col(pinfo->fd, COL_INFO))
+ col_append_str(pinfo->fd, COL_INFO, "UNKNOWN ");
-
+ if (chunk_tree) {
+ length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
+ padding_length = nr_of_padding_bytes(length);
+ type = tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET);
+
+ chunk_value_length = length - CHUNK_HEADER_LENGTH;
+
+ proto_tree_add_text(chunk_tree, chunk_tvb, CHUNK_VALUE_OFFSET, chunk_value_length,
+ "Chunk value (%u byte%s)",
+ chunk_value_length, plurality(chunk_value_length, "", "s"));
+
+ if (padding_length > 0)
+ proto_tree_add_text(chunk_tree, chunk_tvb, CHUNK_HEADER_OFFSET + length, padding_length,
+ "Padding: %u byte%s",
+ padding_length, plurality(padding_length, "", "s"));
+
+ proto_item_set_text(chunk_item, "Chunk of type %u and %u byte%s value",
+ type, chunk_value_length, plurality(chunk_value_length, "", "s"));
+ }
}
-void
+static void
dissect_sctp_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *sctp_tree)
{
guint8 type, flags;
@@ -1397,25 +1491,32 @@ dissect_sctp_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree, pr
type = tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET);
flags = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
-
- /* create proto_tree stuff */
- chunk_item = proto_tree_add_text(sctp_tree, chunk_tvb,
- CHUNK_HEADER_OFFSET, tvb_length(chunk_tvb), "Incomplete chunk");
- chunk_tree = proto_item_add_subtree(chunk_item, ett_sctp_chunk);
-
- /* then insert the chunk header components into the protocol tree */
- proto_tree_add_uint_format(chunk_tree, hf_sctp_chunk_type,
- chunk_tvb, CHUNK_TYPE_OFFSET, CHUNK_TYPE_LENGTH,
- type, "Identifier: %u (%s)",
- type, val_to_str(type, sctp_chunk_type_values, "unknown"));
- flags_item = proto_tree_add_uint(chunk_tree, hf_sctp_chunk_flags,
- chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH,
- flags);
- proto_tree_add_uint(chunk_tree, hf_sctp_chunk_length,
- chunk_tvb, CHUNK_LENGTH_OFFSET, CHUNK_LENGTH_LENGTH,
- length);
+
+ if (tree) {
+ /* create proto_tree stuff */
+ chunk_item = proto_tree_add_text(sctp_tree, chunk_tvb,
+ CHUNK_HEADER_OFFSET, tvb_length(chunk_tvb), "Incomplete chunk");
+ chunk_tree = proto_item_add_subtree(chunk_item, ett_sctp_chunk);
+
+ /* then insert the chunk header components into the protocol tree */
+ proto_tree_add_uint_format(chunk_tree, hf_sctp_chunk_type,
+ chunk_tvb, CHUNK_TYPE_OFFSET, CHUNK_TYPE_LENGTH,
+ type, "Identifier: %u (%s)",
+ type, val_to_str(type, sctp_chunk_type_values, "unknown"));
+ flags_item = proto_tree_add_uint(chunk_tree, hf_sctp_chunk_flags,
+ chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH,
+ flags);
+ proto_tree_add_uint(chunk_tree, hf_sctp_chunk_length,
+ chunk_tvb, CHUNK_LENGTH_OFFSET, CHUNK_LENGTH_LENGTH,
+ length);
+ } else {
+ chunk_tree = NULL;
+ chunk_item = NULL;
+ flags_item = NULL;
+ };
/* now dissect the chunk value */
+
switch(type) {
case SCTP_DATA_CHUNK_ID:
dissect_data_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
@@ -1461,14 +1562,14 @@ dissect_sctp_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree, pr
break;
case SCTP_SHUTDOWN_COMPLETE_CHUNK_ID:
dissect_shutdown_complete_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
- break;
+ break;
default:
dissect_unknown_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
break;
- }
+ }
}
-void
+static void
dissect_sctp_chunks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *sctp_tree)
{
tvbuff_t *chunk_tvb;
@@ -1517,18 +1618,17 @@ dissect_sctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
checksum = tvb_get_ntohl(tvb, CHECKSUM_OFFSET);
/* update pi structure */
- pi.ptype = PT_SCTP;
- pi.srcport = source_port;
+ pi.ptype = PT_SCTP;
+ pi.srcport = source_port;
pi.destport = destination_port;
/* make entry in the Protocol column on summary display */
if (check_col(pinfo->fd, COL_PROTOCOL))
col_set_str(pinfo->fd, COL_PROTOCOL, "SCTP");
- /* Make entries in Info column on summary display */
- if (check_col(pinfo->fd, COL_INFO))
- col_add_fstr(pinfo->fd, COL_INFO, "%u > %u: tag 0x%x",
- source_port, destination_port, verification_tag);
+ /* Clear entries in Info column on summary display */
+ if (check_col(pinfo->fd, COL_INFO))
+ col_add_str(pinfo->fd, COL_INFO, "");
/* In the interest of speed, if "tree" is NULL, don't do any work not
necessary to generate protocol tree items. */
@@ -1552,10 +1652,11 @@ dissect_sctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, checksum,
"Adler-32 checksum: 0x%08x (%s)",
checksum, sctp_checksum_state(tvb, checksum));
-
- /* add all chunks of the sctp datagram to the protocol tree */
- dissect_sctp_chunks(tvb, pinfo, tree, sctp_tree);
+ } else {
+ sctp_tree = NULL;
};
+ /* add all chunks of the sctp datagram to the protocol tree */
+ dissect_sctp_chunks(tvb, pinfo, tree, sctp_tree);
}
/* Register the protocol with Ethereal */
@@ -1820,5 +1921,5 @@ proto_register_sctp(void)
void
proto_reg_handoff_sctp(void)
{
- dissector_add("ip.proto", IP_PROTO_SCTP, dissect_sctp, proto_sctp);
+ dissector_add("ip.proto", IP_PROTO_SCTP, dissect_sctp, proto_sctp);
}