* Routines for Stream Control Transmission Protocol dissection
* Copyright 2000, Michael Tüxen <Michael.Tuexen@icn.siemens.de>
*
- * $Id: packet-sctp.c,v 1.1 2000/07/21 12:56:58 gram Exp $
+ * $Id: packet-sctp.c,v 1.19 2001/07/03 04:56:46 guy Exp $
*
* Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@unicom.net>
+ * By Gerald Combs <gerald@ethereal.com>
* Copyright 1998 Gerald Combs
*
* Copied from README.developer
# include <netinet/in.h>
#endif
+#include <string.h>
+#include <glib.h>
+
#ifdef NEED_SNPRINTF_H
-# ifdef HAVE_STDARG_H
-# include <stdarg.h>
-# else
-# include <varargs.h>
-# endif
# include "snprintf.h"
#endif
-#include <string.h>
-#include <glib.h>
-#include <packet.h>
-
-#include "packet-ip.h"
+#include "packet.h"
+#include "ipproto.h"
/* Initialize the protocol and registered fields */
static int proto_sctp = -1;
static int hf_sctp_cause_tsn = -1;
+static dissector_table_t sctp_port_dissector_table;
+static dissector_table_t sctp_ppi_dissector_table;
+
/* Initialize the subtree pointers */
static gint ett_sctp = -1;
static gint ett_sctp_chunk = -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
{ 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
#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;
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;
return "incorrect";
}
-guint
+static guint
nr_of_padding_bytes (guint length)
{
guint remainder;
* TLV parameter stuff for INIT and INIT-ACK chunks
*/
-void
+static void
dissect_parameter(tvbuff_t *, proto_tree *);
-void
-dissect_sctp_chunk(tvbuff_t *, proto_tree *);
+static gboolean
+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;
}
}
-void
+static void
dissect_heartbeat_info_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
{
guint16 length, heartbeat_info_length;
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;
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,
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;
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;
+ guint16 length, padding_length, parameter_value_length;
tvbuff_t *unrecognized_parameters_tvb;
length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
-
- parameter_value_length = length - PARAMETER_HEADER_LENGTH;
+ padding_length = nr_of_padding_bytes(length);
+
+ parameter_value_length = length - PARAMETER_HEADER_LENGTH + padding_length;
unrecognized_parameters_tvb = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET,
parameter_value_length, parameter_value_length);
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;
increment);
}
-void
+static void
dissect_hostname_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
{
guint16 length, hostname_length;
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 ;
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;
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;
dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
break;
};
- if (padding_length > 0)
+ if ((padding_length > 0) && (type != UNREC_PARA_PARAMETER_ID))
proto_tree_add_text(parameter_tree, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length,
"Padding: %u byte%s",
padding_length, plurality(padding_length, "", "s"));
/*
* 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;
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;
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;
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;
parameter_type, val_to_str(parameter_type, sctp_parameter_identifier_values, "unknown") );
}
-void
-dissect_unrecognized_chunk_type_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
+static void
+dissect_unrecognized_chunk_type_cause(tvbuff_t *cause_tvb, packet_info *pinfo,
+ proto_tree *cause_tree, proto_item *cause_item)
{
guint16 length, chunk_length;
guint8 unrecognized_type;
unrecognized_chunk_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET,
chunk_length, chunk_length);
- dissect_sctp_chunk(unrecognized_chunk_tvb, cause_tree);
+ dissect_sctp_chunk(unrecognized_chunk_tvb, pinfo, cause_tree,cause_tree);
unrecognized_type = tvb_get_guint8(unrecognized_chunk_tvb, CHUNK_TYPE_OFFSET);
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;
+ guint16 length, padding_length, cause_info_length;
tvbuff_t *unrecognized_parameters_tvb;
length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
-
- cause_info_length = length - CAUSE_HEADER_LENGTH;
+ padding_length = nr_of_padding_bytes(length);
+
+ cause_info_length = length - CAUSE_HEADER_LENGTH + padding_length;
unrecognized_parameters_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET,
cause_info_length, cause_info_length);
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;
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;
code, cause_info_length, plurality(cause_info_length, "", "s"));
}
-void
-dissect_error_cause(tvbuff_t *cause_tvb, proto_tree *chunk_tree)
+static void
+dissect_error_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *chunk_tree)
{
guint16 code, length, padding_length, total_length;
proto_item *cause_item;
length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
padding_length = nr_of_padding_bytes(length);
total_length = length + padding_length;
-
+
cause_item = proto_tree_add_notext(chunk_tree, cause_tvb, CAUSE_HEADER_OFFSET, total_length);
proto_item_set_text(cause_item, "BAD ERROR CAUSE");
cause_tree = proto_item_add_subtree(cause_item, ett_sctp_chunk_cause);
dissect_unresolvable_address_cause(cause_tvb, cause_tree, cause_item);
break;
case UNRECOGNIZED_CHUNK_TYPE:
- dissect_unrecognized_chunk_type_cause(cause_tvb, cause_tree, cause_item);
+ dissect_unrecognized_chunk_type_cause(cause_tvb, pinfo, cause_tree, cause_item);
break;
case INVALID_MANDATORY_PARAMETER:
dissect_invalid_mandatory_parameter_cause(cause_tvb, cause_tree, cause_item);
dissect_unknown_cause(cause_tvb, cause_tree, cause_item);
break;
};
- if (padding_length > 0)
+ if ((padding_length > 0) && (code != UNRECOGNIZED_PARAMETERS))
proto_tree_add_text(cause_tree, cause_tvb, CAUSE_HEADER_OFFSET + length, padding_length,
"Padding: %u byte%s",
padding_length, plurality(padding_length, "", "s"));
* Code to actually dissect the packets
*/
-void
-dissect_data_chunk(tvbuff_t *chunk_tvb,
+static gboolean
+dissect_payload(tvbuff_t *payload_tvb, packet_info *pinfo, proto_tree *tree,
+ proto_tree *chunk_tree, guint32 ppi, guint16 payload_length, guint16 padding_length)
+{
+ /* do lookup with the subdissector table */
+ if (dissector_try_port (sctp_ppi_dissector_table, ppi, payload_tvb, pinfo, tree) ||
+ dissector_try_port(sctp_port_dissector_table, pinfo->srcport, payload_tvb, pinfo, tree) ||
+ dissector_try_port(sctp_port_dissector_table, pinfo->destport, payload_tvb, pinfo, tree)){
+ return TRUE;
+ }
+ 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"));
+ if (padding_length > 0)
+ proto_tree_add_text(chunk_tree, payload_tvb, payload_length, padding_length,
+ "Padding: %u byte%s",
+ padding_length, plurality(padding_length, "", "s"));
+ return FALSE;
+ }
+}
+
+static gboolean
+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)
{
guint8 flags;
- guint16 length, payload_length, padding_length, stream_id, stream_seq_number;
+ guint16 length, total_payload_length, payload_length, padding_length, stream_id, stream_seq_number;
guint32 tsn, payload_proto_id;
proto_tree *flag_tree;
-
- flags = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
- length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
+ tvbuff_t *payload_tvb;
- 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);
-
- payload_length = length - DATA_CHUNK_HEADER_LENGTH;
- padding_length = nr_of_padding_bytes(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_tree_add_text(chunk_tree, chunk_tvb, DATA_CHUNK_PAYLOAD_OFFSET, payload_length,
- "Payload (%u byte%s)",
- payload_length, plurality(payload_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, "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"));
-}
+ 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);
+ payload_proto_id = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET);
+
+ 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);
+
+ 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"));
+ };
+ return dissect_payload(payload_tvb, pinfo, tree, chunk_tree, payload_proto_id, payload_length, padding_length);
+}
-void
-dissect_init_chunk(tvbuff_t *chunk_tvb,
+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)
{
guint32 initiate_tag, adv_rec_window_credit, initial_tsn;
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
-dissect_init_ack_chunk(tvbuff_t *chunk_tvb,
+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, chunk_tree, chunk_item, flags_item);
+ dissect_init_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
}
-void
-dissect_sack_chunk(tvbuff_t *chunk_tvb,
+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)
{
guint32 cumulative_tsn_ack, adv_rec_window_credit, dup_tsn;
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
-dissect_heartbeat_chunk(tvbuff_t *chunk_tvb,
+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
-dissect_heartbeat_ack_chunk(tvbuff_t *chunk_tvb,
+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
-dissect_abort_chunk(tvbuff_t *chunk_tvb,
+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;
/* 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, chunk_tree);
+ dissect_error_cause(cause_tvb, pinfo, chunk_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
-dissect_shutdown_chunk(tvbuff_t *chunk_tvb,
+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
-dissect_shutdown_ack_chunk(tvbuff_t *chunk_tvb,
+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
-dissect_error_chunk(tvbuff_t *chunk_tvb,
+ 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)
{
guint offset, number_of_causes;
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, 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
-dissect_cookie_echo_chunk(tvbuff_t *chunk_tvb,
+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)
{
guint length, cookie_length, padding_length;
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
-dissect_cookie_ack_chunk(tvbuff_t *chunk_tvb,
+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
-dissect_ecne_chunk(tvbuff_t *chunk_tvb,
+ 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
-dissect_cwr_chunk(tvbuff_t *chunk_tvb,
+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
-dissect_shutdown_complete_chunk(tvbuff_t *chunk_tvb,
+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
-dissect_unknown_chunk(tvbuff_t *chunk_tvb,
+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
-dissect_sctp_chunk(tvbuff_t *chunk_tvb, proto_tree *sctp_tree)
+static gboolean
+dissect_sctp_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *sctp_tree)
{
guint8 type, flags;
guint16 length;
+ gboolean result;
proto_item *flags_item;
proto_item *chunk_item;
proto_tree *chunk_tree;
+ result = FALSE;
+
/* first extract the chunk header */
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, chunk_tree, chunk_item, flags_item);
+ result = dissect_data_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
break;
case SCTP_INIT_CHUNK_ID:
- dissect_init_chunk(chunk_tvb, chunk_tree, chunk_item, flags_item);
+ dissect_init_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
break;
case SCTP_INIT_ACK_CHUNK_ID:
- dissect_init_ack_chunk(chunk_tvb, chunk_tree, chunk_item, flags_item);
+ dissect_init_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
break;
case SCTP_SACK_CHUNK_ID:
- dissect_sack_chunk(chunk_tvb, chunk_tree, chunk_item, flags_item);
+ dissect_sack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
break;
case SCTP_HEARTBEAT_CHUNK_ID:
- dissect_heartbeat_chunk(chunk_tvb, chunk_tree, chunk_item, flags_item);
+ dissect_heartbeat_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
break;
case SCTP_HEARTBEAT_ACK_CHUNK_ID:
- dissect_heartbeat_ack_chunk(chunk_tvb, chunk_tree, chunk_item, flags_item);
+ dissect_heartbeat_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
break;
case SCTP_ABORT_CHUNK_ID:
- dissect_abort_chunk(chunk_tvb, chunk_tree, chunk_item, flags_item);
+ dissect_abort_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
break;
case SCTP_SHUTDOWN_CHUNK_ID:
- dissect_shutdown_chunk(chunk_tvb, chunk_tree, chunk_item, flags_item);
+ dissect_shutdown_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
break;
case SCTP_SHUTDOWN_ACK_CHUNK_ID:
- dissect_shutdown_ack_chunk(chunk_tvb, chunk_tree, chunk_item, flags_item);
+ dissect_shutdown_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
break;
case SCTP_ERROR_CHUNK_ID:
- dissect_error_chunk(chunk_tvb, chunk_tree, chunk_item, flags_item);
+ dissect_error_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
break;
case SCTP_COOKIE_ECHO_CHUNK_ID:
- dissect_cookie_echo_chunk(chunk_tvb, chunk_tree, chunk_item, flags_item);
+ dissect_cookie_echo_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
break;
case SCTP_COOKIE_ACK_CHUNK_ID:
- dissect_cookie_ack_chunk(chunk_tvb, chunk_tree, chunk_item, flags_item);
+ dissect_cookie_ack_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
break;
case SCTP_ECNE_CHUNK_ID:
- dissect_ecne_chunk(chunk_tvb, chunk_tree, chunk_item, flags_item);
+ dissect_ecne_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
break;
case SCTP_CWR_CHUNK_ID:
- dissect_cwr_chunk(chunk_tvb, chunk_tree, chunk_item, flags_item);
+ dissect_cwr_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
break;
case SCTP_SHUTDOWN_COMPLETE_CHUNK_ID:
- dissect_shutdown_complete_chunk(chunk_tvb, chunk_tree, chunk_item, flags_item);
- break;
+ dissect_shutdown_complete_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
+ break;
default:
- dissect_unknown_chunk(chunk_tvb, chunk_tree, chunk_item, flags_item);
+ dissect_unknown_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
break;
- }
+ };
+ return result;
}
-void
-dissect_sctp_chunks(tvbuff_t *tvb, proto_tree *sctp_tree)
+static void
+dissect_sctp_chunks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ proto_item *sctp_item, proto_tree *sctp_tree)
{
tvbuff_t *chunk_tvb;
guint16 length, padding_length, total_length;
- gint offset;
-
+ gint last_offset, offset;
+ gboolean sctp_item_length_set;
+
/* the common header of the datagram is already handled */
+ last_offset = 0;
offset = COMMON_HEADER_LENGTH;
+ sctp_item_length_set = FALSE;
while(tvb_length_remaining(tvb, offset) > 0) {
/* extract the chunk length and compute number of padding bytes */
/* create a tvb for the chunk including the padding bytes */
chunk_tvb = tvb_new_subset(tvb, offset, total_length, total_length);
/* call dissect_sctp_chunk for a actual work */
- dissect_sctp_chunk(chunk_tvb, sctp_tree);
+ if (dissect_sctp_chunk(chunk_tvb, pinfo, tree, sctp_tree) && (tree)) {
+ proto_item_set_len(sctp_item, offset - last_offset + DATA_CHUNK_HEADER_LENGTH);
+ sctp_item_length_set = TRUE;
+ offset += total_length;
+ last_offset = offset;
+ if (tvb_length_remaining(tvb, offset) > 0) {
+ sctp_item = proto_tree_add_item(tree, proto_sctp, tvb, offset, 0, FALSE);
+ sctp_tree = proto_item_add_subtree(sctp_item, ett_sctp);
+ sctp_item_length_set = FALSE;
+ }
+ } else {
/* get rid of the dissected chunk */
offset += total_length;
- }
+ }
+ };
+ if (!sctp_item_length_set && (tree)) {
+ proto_item_set_len(sctp_item, offset - last_offset);
+ };
}
-
-
/* dissect_sctp handles the common header of a SCTP datagram.
* For the handling of the chunks dissect_sctp_chunks is called.
*/
-#if 0
static void
dissect_sctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
-#else
-static void
-dissect_sctp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
-{
- tvbuff_t *tvb = tvb_create_from_top(offset);
- packet_info *pinfo = π
-#endif
-
guint16 source_port, destination_port;
guint32 verification_tag, checksum;
- proto_item *ti;
+ proto_item *sctp_item;
proto_tree *sctp_tree;
- pinfo->current_proto = "SCTP";
-
/* Extract the common header */
source_port = tvb_get_ntohs(tvb, SOURCE_PORT_OFFSET);
destination_port = tvb_get_ntohs(tvb, DESTINATION_PORT_OFFSET);
verification_tag = tvb_get_ntohl(tvb, VERIFICATION_TAG_OFFSET);
checksum = tvb_get_ntohl(tvb, CHECKSUM_OFFSET);
+ /* update pi structure */
+ pinfo->ptype = PT_SCTP;
+ pinfo->srcport = source_port;
+ pinfo->destport = destination_port;
+
/* make entry in the Protocol column on summary display */
- if (check_col(fd, COL_PROTOCOL))
- col_add_str(fd, COL_PROTOCOL, "SCTP");
+ 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(fd, COL_INFO))
- col_add_fstr(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. */
if (tree) {
/* create the sctp protocol tree */
- ti = proto_tree_add_protocol_format(tree, proto_sctp, tvb, 0, tvb_length(tvb),
- "Stream Control Transmission Protocol");
- sctp_tree = proto_item_add_subtree(ti, ett_sctp);
+ sctp_item = proto_tree_add_item(tree, proto_sctp, tvb, 0, 0, FALSE);
+ sctp_tree = proto_item_add_subtree(sctp_item, ett_sctp);
/* add the components of the common header to the protocol tree */
proto_tree_add_uint(sctp_tree, hf_sctp_source_port,
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, sctp_tree);
+ } else {
+ sctp_tree = NULL;
+ sctp_item = NULL;
};
+ /* add all chunks of the sctp datagram to the protocol tree */
+ dissect_sctp_chunks(tvb, pinfo, tree, sctp_item, sctp_tree);
}
/* Register the protocol with Ethereal */
{ &hf_sctp_source_port,
{ "Source port", "sctp.srcport",
FT_UINT16, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{ &hf_sctp_destination_port,
{ "Destination port", "sctp.dstport",
FT_UINT16, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{ &hf_sctp_verification_tag,
{ "Verification tag", "sctp.verfication_tag",
FT_UINT32, BASE_HEX, NULL, 0x0,
- ""}
+ "", HFILL }
},
{ &hf_sctp_checksum,
{ "Adler-32 checksum", "sctp.checksum",
FT_UINT32, BASE_HEX, NULL, 0x0,
- ""}
+ "", HFILL }
},
{ &hf_sctp_chunk_type,
{ "Identifier", "sctp.chunk_type",
FT_UINT8, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{ &hf_sctp_chunk_flags,
{ "Flags", "sctp.chunk_flags",
FT_UINT8, BASE_BIN, NULL, 0x0,
- ""}
+ "", HFILL }
},
{ &hf_sctp_chunk_length,
{ "Length", "sctp.chunk_length",
FT_UINT16, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{ &hf_sctp_init_chunk_initiate_tag,
{ "Initiate tag", "sctp.init.chunk.initiate.tag",
FT_UINT32, BASE_HEX, NULL, 0x0,
- ""}
+ "", HFILL }
},
{ &hf_sctp_init_chunk_adv_rec_window_credit,
{ "Advertised reciever window credit (a_rwnd)", "sctp.init.chunk.credit",
FT_UINT32, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{ &hf_sctp_init_chunk_number_of_outbound_streams,
{ "Number of outbound streams", "sctp.init.chunk.nr.out.streams",
FT_UINT16, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{ &hf_sctp_init_chunk_number_of_inbound_streams,
{ "Number of inbound streams", "sctp.init.chunk.nr.in.streams",
FT_UINT16, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_init_chunk_initial_tsn,
{ "Initial TSN", "sctp.init.chunk.initial.tsn",
FT_UINT32, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_cumulative_tsn_ack,
{ "Cumulative TSN Ack", "sctp.cumulative.tsn.ack",
FT_UINT32, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_data_chunk_tsn,
{ "TSN", "sctp.tsn",
FT_UINT32, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_data_chunk_stream_id,
{ "Stream Identifier", "sctp.stream_id",
FT_UINT16, BASE_HEX, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_data_chunk_stream_seq_number,
{ "Stream sequence number", "sctp.stream_seq_number",
FT_UINT16, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_data_chunk_payload_proto_id,
{ "Payload Protocol identifier", "sctp.payload_proto_id",
FT_UINT32, BASE_HEX, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_data_chunk_e_bit,
{ "E-Bit", "sctp.data.e_bit",
FT_BOOLEAN, 8, TFS(&sctp_data_chunk_e_bit_value), SCTP_DATA_CHUNK_E_BIT,
- ""}
+ "", HFILL }
},
{&hf_sctp_data_chunk_b_bit,
{ "B-Bit", "sctp.data.b_bit",
FT_BOOLEAN, 8, TFS(&sctp_data_chunk_b_bit_value), SCTP_DATA_CHUNK_B_BIT,
- ""}
+ "", HFILL }
},
{&hf_sctp_data_chunk_u_bit,
{ "U-Bit", "sctp.data.u.bit",
FT_BOOLEAN, 8, TFS(&sctp_data_chunk_u_bit_value), SCTP_DATA_CHUNK_U_BIT,
- ""}
+ "", HFILL }
},
{&hf_sctp_sack_chunk_cumulative_tsn_ack,
{ "Cumulative TSN ACK", "sctp.sack.cumulative_tsn_ack",
FT_UINT32, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_sack_chunk_adv_rec_window_credit,
{ "Advertised receiver window credit (a_rwnd)", "sctp.sack.a_rwnd",
FT_UINT32, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_sack_chunk_number_of_gap_blocks,
{ "Number of gap acknowldgement blocks ", "sctp.sack.number_of_gap_blocks",
FT_UINT16, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_sack_chunk_number_of_dup_tsns,
{ "Number of duplicated TSNs", "sctp.sack.number_of_duplicated_tsns",
FT_UINT16, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_sack_chunk_gap_block_start,
{ "Start", "sctp.sack.gap_block_start",
FT_UINT16, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_sack_chunk_gap_block_end,
{ "End", "sctp.sack.gap_block_end",
FT_UINT16, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_sack_chunk_duplicate_tsn,
{ "Duplicate TSN", "sctp.sack.duplicate.tsn",
FT_UINT16, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_shutdown_chunk_cumulative_tsn_ack,
{ "Cumulative TSN Ack", "sctp.shutdown.cumulative_tsn_ack",
FT_UINT32, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_ecne_chunk_lowest_tsn,
{ "Lowest TSN", "sctp.ecne.lowest_tsn",
FT_UINT32, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_cwr_chunk_lowest_tsn,
{ "Lowest TSN", "sctp.cwr.lowest_tsn",
FT_UINT32, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_shutdown_complete_chunk_t_bit,
{ "E-Bit", "sctp.shutdown_complete.t_bit",
FT_BOOLEAN, 8, TFS(&sctp_shutdown_complete_chunk_t_bit_value), SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT,
- ""}
+ "", HFILL }
},
{&hf_sctp_chunk_parameter_type,
{ "Parameter type", "sctp.parameter.type",
FT_UINT16, BASE_HEX, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_chunk_parameter_length,
{ "Parameter length", "sctp.parameter.length",
FT_UINT16, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_parameter_ipv4_address,
{ "IP Version 4 address", "sctp.parameter.ipv4_address",
FT_IPv4, BASE_NONE, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_parameter_ipv6_address,
{ "IP Version 6 address", "sctp.parameter.ipv6_address",
FT_IPv6, BASE_NONE, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_parameter_cookie_preservative_increment,
{ "Suggested Cookie life-span increment (msec)", "sctp.parameter.cookie_preservative_incr",
FT_UINT32, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_parameter_hostname_hostname,
{ "Hostname", "sctp.parameter.hostname.hostname",
FT_STRING, BASE_NONE, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_supported_address_types_parameter,
{ "Supported address type", "sctp.parameter.supported_addres_type",
FT_UINT16, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_cause_code,
{ "Cause code", "sctp.cause.code",
FT_UINT16, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_cause_length,
{ "Cause length", "sctp.cause.length",
FT_UINT16, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_cause_stream_identifier,
{ "Stream identifier", "sctp.cause.stream_identifier",
FT_UINT16, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_cause_number_of_missing_parameters,
{ "Number of missing parameters", "sctp.cause.nr_of_missing_parameters",
FT_UINT32, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_cause_missing_parameter_type,
{ "Missing parameters type", "sctp.cause.missing_parameter_type",
FT_UINT16, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_cause_measure_of_staleness,
{ "Measure of staleness in usec", "sctp.cause.measure_of_staleness",
FT_UINT32, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
{&hf_sctp_cause_tsn,
{ "TSN", "sctp.cause.tsn",
FT_UINT32, BASE_DEC, NULL, 0x0,
- ""}
+ "", HFILL }
},
};
};
/* Register the protocol name and description */
- proto_sctp = proto_register_protocol("Stream Control Transmission Protcol",
- "sctp");
+ proto_sctp = proto_register_protocol("Stream Control Transmission Protocol",
+ "SCTP", "sctp");
/* Required function calls to register the header fields and subtrees used */
proto_register_field_array(proto_sctp, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
+
+ /* subdissector code */
+ sctp_port_dissector_table = register_dissector_table("sctp.port");
+ sctp_ppi_dissector_table = register_dissector_table("sctp.ppi");
+
};
void
proto_reg_handoff_sctp(void)
{
- dissector_add("ip.proto", IP_PROTO_SCTP, dissect_sctp);
+ dissector_add("ip.proto", IP_PROTO_SCTP, dissect_sctp, proto_sctp);
}
-
-
-
-
-
-
-