* Routines for Stream Control Transmission Protocol dissection
* It should be compilant to
* - RFC 2960, for basic SCTP support
- * - http://www.ietf.org/internet-drafts/draft-ietf-tsvwg-addip-sctp-05.txt for the add-IP extension
- * - http://www.ietf.org/internet-drafts/draft-stewart-prsctp-00.txt for the 'Partial Reliability' extension
+ * - http://www.ietf.org/internet-drafts/draft-ietf-tsvwg-addip-sctp-06.txt for the add-IP extension
+ * - http://www.ietf.org/internet-drafts/draft-stewart-tsvwg-prsctp-01.txt for the 'Partial Reliability' extension
* - http://www.ietf.org/internet-drafts/draft-ietf-tsvwg-sctpcsum-07.txt
* Copyright 2000, 2001, 2002, Michael Tuexen <Michael.Tuexen@icn.siemens.de>
* Still to do (so stay tuned)
* - support for reassembly
* - code cleanup
*
- * $Id: packet-sctp.c,v 1.38 2002/06/08 21:54:52 guy Exp $
+ * $Id: packet-sctp.c,v 1.40 2002/07/10 21:01:57 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
# include "config.h"
#endif
-#include <stdio.h>
-#include <stdlib.h>
-
-
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-
-#include <string.h>
-#include <glib.h>
-
-#ifdef NEED_SNPRINTF_H
-# include "snprintf.h"
-#endif
-
#include "prefs.h"
#include <epan/packet.h>
#include "ipproto.h"
static int hf_sctp_cause_tsn = -1;
static int hf_sctp_forward_tsn_chunk_tsn = -1;
+static int hf_sctp_forward_tsn_chunk_sid = -1;
+static int hf_sctp_forward_tsn_chunk_ssn = -1;
static int hf_sctp_asconf_ack_serial = -1;
static int hf_sctp_asconf_serial = -1;
static gint ett_sctp_supported_address_types_parameter = -1;
static gint ett_sctp_unrecognized_parameter_parameter = -1;
+static dissector_handle_t data_handle;
+
#define SCTP_DATA_CHUNK_ID 0
#define SCTP_INIT_CHUNK_ID 1
#define SCTP_INIT_ACK_CHUNK_ID 2
#define NO_USER_DATA 0x09
#define COOKIE_RECEIVED_WHILE_SHUTTING_DOWN 0x0a
#define RESTART_WITH_NEW_ADDRESSES 0x0b
-#define REQUEST_TO_DELETE_LAST_ADDRESS 0x0c
-#define OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE 0X0d
-#define REQUEST_TO_DELETE_SOURCE_ADDRESS 0x0e
-#define ABORT_DUE_TO_ILLEGAL_ASCONF 0x0f
+#define REQUEST_TO_DELETE_LAST_ADDRESS 0x0100
+#define OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE 0X0101
+#define REQUEST_TO_DELETE_SOURCE_ADDRESS 0x0102
+#define ABORT_DUE_TO_ILLEGAL_ASCONF 0x0103
static const value_string sctp_cause_code_values[] = {
{ INVALID_STREAM_IDENTIFIER, "Invalid stream identifier" },
*/
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)
+dissect_payload(tvbuff_t *payload_tvb, packet_info *pinfo, proto_tree *tree, guint32 ppi)
{
guint32 low_port, high_port;
if (check_col(pinfo->cinfo, COL_INFO))
col_append_str(pinfo->cinfo, 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;
+ call_dissector(data_handle, payload_tvb, pinfo, tree);
+ return TRUE;
}
static gboolean
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_length, payload_length);
payload_proto_id = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET);
if (chunk_tree) {
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);
+ if (padding_length > 0)
+ proto_tree_add_text(chunk_tree, chunk_tvb, DATA_CHUNK_PAYLOAD_OFFSET + payload_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"));
+ proto_item_set_len(chunk_item, DATA_CHUNK_HEADER_LENGTH);
+
};
- return dissect_payload(payload_tvb, pinfo, tree, chunk_tree, payload_proto_id, payload_length, padding_length);
+ return dissect_payload(payload_tvb, pinfo, tree, payload_proto_id);
}
static void
}
}
-#define FORWARD_TSN_CHUNK_TSN_OFFSET CHUNK_VALUE_OFFSET
#define FORWARD_TSN_CHUNK_TSN_LENGTH 4
+#define FORWARD_TSN_CHUNK_SID_LENGTH 2
+#define FORWARD_TSN_CHUNK_SSN_LENGTH 2
+#define FORWARD_TSN_CHUNK_TSN_OFFSET CHUNK_VALUE_OFFSET
+#define FORWARD_TSN_CHUNK_SID_OFFSET 0
+#define FORWARD_TSN_CHUNK_SSN_OFFSET (FORWARD_TSN_CHUNK_SID_OFFSET + FORWARD_TSN_CHUNK_SID_LENGTH)
static void
dissect_forward_tsn_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
{
guint32 tsn;
+ guint offset;
+ guint16 number_of_affected_streams, affected_stream, length, sid, ssn;
if (check_col(pinfo->cinfo, COL_INFO))
col_append_str(pinfo->cinfo, COL_INFO, "FORWARD TSN ");
if (chunk_tree) {
tsn = tvb_get_ntohl(chunk_tvb, FORWARD_TSN_CHUNK_TSN_OFFSET);
proto_tree_add_uint(chunk_tree, hf_sctp_forward_tsn_chunk_tsn, chunk_tvb, FORWARD_TSN_CHUNK_TSN_OFFSET, FORWARD_TSN_CHUNK_TSN_LENGTH, tsn);
+ length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
+ number_of_affected_streams = (length - CHUNK_HEADER_LENGTH - FORWARD_TSN_CHUNK_TSN_LENGTH) /
+ (FORWARD_TSN_CHUNK_SID_LENGTH + FORWARD_TSN_CHUNK_SSN_LENGTH);
+ offset = CHUNK_VALUE_OFFSET + FORWARD_TSN_CHUNK_TSN_LENGTH;
+
+ for(affected_stream = 0; affected_stream < number_of_affected_streams; affected_stream++) {
+ sid = tvb_get_ntohs(chunk_tvb, offset + FORWARD_TSN_CHUNK_SID_OFFSET);
+ ssn = tvb_get_ntohs(chunk_tvb, offset + FORWARD_TSN_CHUNK_SSN_OFFSET);
+ proto_tree_add_uint(chunk_tree, hf_sctp_forward_tsn_chunk_sid,
+ chunk_tvb, offset + FORWARD_TSN_CHUNK_SID_OFFSET, FORWARD_TSN_CHUNK_SID_LENGTH, sid);
+ proto_tree_add_uint(chunk_tree, hf_sctp_forward_tsn_chunk_ssn,
+ chunk_tvb, offset + FORWARD_TSN_CHUNK_SSN_OFFSET, FORWARD_TSN_CHUNK_SSN_LENGTH, ssn);
+ offset = offset + (FORWARD_TSN_CHUNK_SID_LENGTH + FORWARD_TSN_CHUNK_SSN_LENGTH);
+ }
proto_item_set_text(chunk_item, "FORWARD TSN chunk (new cumulative TSN %u)", tsn);
}
}
FT_UINT32, BASE_DEC, NULL, 0x0,
"", HFILL }
},
+ {&hf_sctp_forward_tsn_chunk_sid,
+ { "Stream identifier", "sctp.forward_tsn.sid",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ {&hf_sctp_forward_tsn_chunk_ssn,
+ { "Stream sequence number", "sctp.forward_tsn.ssn",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
{&hf_sctp_chunk_parameter_type,
{ "Parameter type", "sctp.parameter.type",
FT_UINT16, BASE_HEX, VALS(sctp_parameter_identifier_values), 0x0,
{
dissector_handle_t sctp_handle;
+ data_handle = find_dissector("data");
sctp_handle = create_dissector_handle(dissect_sctp, proto_sctp);
dissector_add("ip.proto", IP_PROTO_SCTP, sctp_handle);
}