Update the URL for draft-stewart-sctp-pktdrprep to the -02 draft.

Clean up indentation.

Have the main loop for dissecting chunks check that the chunk size is
large enough for the chunk header, and have it pass the chunk size,
minus the size of the chunk header, to dissectors for particular chunk
types.  Make those dissectors check that value to make sure it's large
enough for any fixed-length portion before subtracting the length of
that portion and using the result as a remaining data length.

svn path=/trunk/; revision=13924
This commit is contained in:
Guy Harris 2005-03-26 21:31:13 +00:00
parent 8bd496faec
commit ff24a4ecc8
1 changed files with 122 additions and 93 deletions

View File

@ -6,7 +6,7 @@
* - RFC 3758
* - http://www.ietf.org/internet-drafts/draft-ietf-tsvwg-sctpimpguide-11.txt
* - http://www.ietf.org/internet-drafts/draft-ietf-tsvwg-addip-sctp-09.txt
* - http://www.ietf.org/internet-drafts/draft-stewart-sctp-pktdrprep-01.txt
* - http://www.ietf.org/internet-drafts/draft-stewart-sctp-pktdrprep-02.txt
* - http://www.ietf.org/internet-drafts/draft-tuexen-sctp-auth-chunk-01.txt
*
* Copyright 2000, 2001, 2002, 2003, 2004 Michael Tuexen <tuexen [AT] fh-muenster.de>
@ -24,8 +24,6 @@
* By Gerald Combs <gerald@ethereal.com>
* Copyright 1998 Gerald Combs
*
* Copied from README.developer
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
@ -516,10 +514,10 @@ dissect_ipv4_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, prot
proto_item_append_text(additional_item, "%s", ip_to_str((const guint8 *)tvb_get_ptr(parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH)));
}
if (dissecting_init_init_ack_chunk) {
if (sctp_info.number_of_tvbs < MAXIMUM_NUMBER_OF_TVBS)
sctp_info.tvb[sctp_info.number_of_tvbs++] = parameter_tvb;
else
sctp_info.incomplete = TRUE;
if (sctp_info.number_of_tvbs < MAXIMUM_NUMBER_OF_TVBS)
sctp_info.tvb[sctp_info.number_of_tvbs++] = parameter_tvb;
else
sctp_info.incomplete = TRUE;
}
}
@ -1354,15 +1352,20 @@ static const true_false_string sctp_data_chunk_u_bit_value = {
};
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)
dissect_data_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *tree, proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
{
guint number_of_ppid;
guint16 payload_length;
guint32 payload_proto_id;
tvbuff_t *payload_tvb;
proto_tree *flags_tree;
guint8 e_bit, b_bit, u_bit;
if (chunk_length < DATA_CHUNK_HEADER_LENGTH - CHUNK_HEADER_LENGTH) {
proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
chunk_length + CHUNK_HEADER_LENGTH,
DATA_CHUNK_HEADER_LENGTH);
return TRUE;
}
payload_proto_id = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET);
/* insert the PPID in the pinfo structure if it is non-zero, not already there and there is still room */
@ -1408,20 +1411,11 @@ dissect_data_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree, pr
tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET),
payload_proto_id);
}
payload_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
if (payload_length < DATA_CHUNK_HEADER_LENGTH) {
if (chunk_tree) {
proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
payload_length, DATA_CHUNK_HEADER_LENGTH);
}
return TRUE;
}
payload_length -= DATA_CHUNK_HEADER_LENGTH;
if (chunk_tree) {
proto_item_append_text(chunk_item, ", payload length: %u byte%s)",
payload_length, plurality(payload_length, "", "s"));
chunk_length, plurality(chunk_length, "", "s"));
}
payload_tvb = tvb_new_subset(chunk_tvb, DATA_CHUNK_PAYLOAD_OFFSET, payload_length, payload_length);
payload_tvb = tvb_new_subset(chunk_tvb, DATA_CHUNK_PAYLOAD_OFFSET, chunk_length, chunk_length);
return dissect_payload(payload_tvb, pinfo, tree, payload_proto_id);
}
@ -1449,11 +1443,16 @@ dissect_data_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree, pr
INIT_CHUNK_INITIAL_TSN_LENGTH )
static void
dissect_init_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
dissect_init_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
{
gint parameters_length;
tvbuff_t *parameters_tvb;
if (chunk_length < INIT_CHUNK_FIXED_PARAMTERS_LENGTH) {
proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
chunk_length + CHUNK_HEADER_LENGTH,
CHUNK_HEADER_LENGTH + INIT_CHUNK_FIXED_PARAMTERS_LENGTH);
return;
}
if (chunk_tree) {
/* handle fixed parameters */
proto_tree_add_item(chunk_tree, hf_init_chunk_initiate_tag, chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET, INIT_CHUNK_INITIATE_TAG_LENGTH, NETWORK_BYTE_ORDER);
@ -1467,18 +1466,23 @@ dissect_init_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_t
tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET),
tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET));
}
/* handle variable paramters */
parameters_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - INIT_CHUNK_FIXED_PARAMTERS_LENGTH - CHUNK_HEADER_LENGTH;
parameters_tvb = tvb_new_subset(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET, parameters_length, parameters_length);
/* handle variable parameters */
chunk_length -= INIT_CHUNK_FIXED_PARAMTERS_LENGTH;
parameters_tvb = tvb_new_subset(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET, chunk_length, chunk_length);
dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, TRUE);
}
static void
dissect_init_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
dissect_init_ack_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
{
gint parameters_length;
tvbuff_t *parameters_tvb;
if (chunk_length < INIT_CHUNK_FIXED_PARAMTERS_LENGTH) {
proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
chunk_length + CHUNK_HEADER_LENGTH,
CHUNK_HEADER_LENGTH + INIT_CHUNK_FIXED_PARAMTERS_LENGTH);
return;
}
if (chunk_tree) {
/* handle fixed parameters */
proto_tree_add_item(chunk_tree, hf_initack_chunk_initiate_tag, chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET, INIT_CHUNK_INITIATE_TAG_LENGTH, NETWORK_BYTE_ORDER);
@ -1493,8 +1497,8 @@ dissect_init_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chun
tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET));
}
/* handle variable paramters */
parameters_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - INIT_CHUNK_FIXED_PARAMTERS_LENGTH - CHUNK_HEADER_LENGTH;
parameters_tvb = tvb_new_subset(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET, parameters_length, parameters_length);
chunk_length -= INIT_CHUNK_FIXED_PARAMTERS_LENGTH;
parameters_tvb = tvb_new_subset(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET, chunk_length, chunk_length);
dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, TRUE);
}
@ -1566,30 +1570,26 @@ dissect_sack_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chun
#define HEARTBEAT_CHUNK_INFO_OFFSET CHUNK_VALUE_OFFSET
static void
dissect_heartbeat_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
dissect_heartbeat_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
{
tvbuff_t *parameter_tvb;
guint info_length;
if (chunk_tree) {
info_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
proto_item_append_text(chunk_item, " (Information: %u byte%s)", info_length, plurality(info_length, "", "s"));
parameter_tvb = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, info_length, info_length);
proto_item_append_text(chunk_item, " (Information: %u byte%s)", chunk_length, plurality(chunk_length, "", "s"));
parameter_tvb = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, chunk_length, chunk_length);
/* FIXME: Parameters or parameter? */
dissect_parameter(parameter_tvb, pinfo, chunk_tree, NULL, FALSE);
}
}
static void
dissect_heartbeat_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
dissect_heartbeat_ack_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
{
tvbuff_t *parameter_tvb;
guint info_length;
if (chunk_tree) {
info_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
proto_item_append_text(chunk_item, " (Information: %u byte%s)", info_length, plurality(info_length, "", "s"));
parameter_tvb = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, info_length, info_length);
proto_item_append_text(chunk_item, " (Information: %u byte%s)", chunk_length, plurality(chunk_length, "", "s"));
parameter_tvb = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, chunk_length, chunk_length);
/* FIXME: Parameters or parameter? */
dissect_parameter(parameter_tvb, pinfo, chunk_tree, NULL, FALSE);
}
@ -1597,9 +1597,8 @@ dissect_heartbeat_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree
#define ABORT_CHUNK_FIRST_ERROR_CAUSE_OFFSET 4
static void
dissect_abort_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *flags_item)
dissect_abort_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *flags_item)
{
guint16 causes_length;
tvbuff_t *causes_tvb;
proto_tree *flags_tree;
@ -1607,8 +1606,7 @@ dissect_abort_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_t
flags_tree = proto_item_add_subtree(flags_item, ett_sctp_abort_chunk_flags);
proto_tree_add_item(flags_tree, hf_abort_chunk_t_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
causes_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
causes_tvb = tvb_new_subset(chunk_tvb, CHUNK_VALUE_OFFSET, causes_length, causes_length);
causes_tvb = tvb_new_subset(chunk_tvb, CHUNK_VALUE_OFFSET, chunk_length, chunk_length);
dissect_error_causes(causes_tvb, pinfo, chunk_tree);
}
}
@ -1633,14 +1631,12 @@ dissect_shutdown_ack_chunk(tvbuff_t *chunk_tvb _U_)
#define ERROR_CAUSE_IND_CAUSES_OFFSET CHUNK_VALUE_OFFSET
static void
dissect_error_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree)
dissect_error_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree)
{
guint16 causes_length;
tvbuff_t *causes_tvb;
if (chunk_tree) {
causes_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
causes_tvb = tvb_new_subset(chunk_tvb, ERROR_CAUSE_IND_CAUSES_OFFSET, causes_length, causes_length);
causes_tvb = tvb_new_subset(chunk_tvb, ERROR_CAUSE_IND_CAUSES_OFFSET, chunk_length, chunk_length);
dissect_error_causes(causes_tvb, pinfo, chunk_tree);
}
}
@ -1648,14 +1644,11 @@ dissect_error_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_t
#define COOKIE_OFFSET CHUNK_VALUE_OFFSET
static void
dissect_cookie_echo_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
dissect_cookie_echo_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, proto_tree *chunk_tree, proto_item *chunk_item)
{
guint cookie_length;
if (chunk_tree) {
cookie_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
proto_tree_add_item(chunk_tree, hf_cookie, chunk_tvb, COOKIE_OFFSET, cookie_length, NETWORK_BYTE_ORDER);
proto_item_append_text(chunk_item, " (Cookie length: %u byte%s)", cookie_length, plurality(cookie_length, "", "s"));
proto_tree_add_item(chunk_tree, hf_cookie, chunk_tvb, COOKIE_OFFSET, chunk_length, NETWORK_BYTE_ORDER);
proto_item_append_text(chunk_item, " (Cookie length: %u byte%s)", chunk_length, plurality(chunk_length, "", "s"));
}
}
@ -1698,11 +1691,11 @@ static const true_false_string sctp_shutdown_complete_chunk_t_bit_value = {
static void
dissect_shutdown_complete_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *flags_item)
{
proto_tree *flags_tree;
proto_tree *flags_tree;
if (chunk_tree) {
flags_tree = proto_item_add_subtree(flags_item, ett_sctp_shutdown_complete_chunk_flags);
proto_tree_add_item(flags_tree, hf_shutdown_complete_chunk_t_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
proto_tree_add_item(flags_tree, hf_shutdown_complete_chunk_t_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
}
}
@ -1714,15 +1707,21 @@ dissect_shutdown_complete_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, pro
#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, proto_tree *chunk_tree, proto_item *chunk_item)
dissect_forward_tsn_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, proto_tree *chunk_tree, proto_item *chunk_item)
{
guint offset;
guint16 number_of_affected_streams, affected_stream, length;
if (chunk_length < FORWARD_TSN_CHUNK_TSN_LENGTH) {
proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
chunk_length + CHUNK_HEADER_LENGTH,
CHUNK_HEADER_LENGTH + FORWARD_TSN_CHUNK_TSN_LENGTH);
return;
}
if (chunk_tree) {
proto_tree_add_item(chunk_tree, hf_forward_tsn_chunk_tsn, chunk_tvb, FORWARD_TSN_CHUNK_TSN_OFFSET, FORWARD_TSN_CHUNK_TSN_LENGTH, NETWORK_BYTE_ORDER);
length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
number_of_affected_streams = (length - CHUNK_HEADER_LENGTH - FORWARD_TSN_CHUNK_TSN_LENGTH) /
number_of_affected_streams = (chunk_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;
@ -1740,15 +1739,20 @@ dissect_forward_tsn_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_ite
#define ASCONF_CHUNK_PARAMETERS_OFFSET (SERIAL_NUMBER_OFFSET + SERIAL_NUMBER_LENGTH)
static void
dissect_asconf_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree)
dissect_asconf_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
{
guint parameters_length;
tvbuff_t *parameters_tvb;
if (chunk_length < SERIAL_NUMBER_LENGTH) {
proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
chunk_length + CHUNK_HEADER_LENGTH,
CHUNK_HEADER_LENGTH + SERIAL_NUMBER_LENGTH);
return;
}
if (chunk_tree) {
proto_tree_add_item(chunk_tree, hf_asconf_serial, chunk_tvb, SERIAL_NUMBER_OFFSET, SERIAL_NUMBER_LENGTH, NETWORK_BYTE_ORDER);
parameters_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH - SERIAL_NUMBER_LENGTH;
parameters_tvb = tvb_new_subset(chunk_tvb, ASCONF_CHUNK_PARAMETERS_OFFSET, parameters_length, parameters_length);
chunk_length -= SERIAL_NUMBER_LENGTH;
parameters_tvb = tvb_new_subset(chunk_tvb, ASCONF_CHUNK_PARAMETERS_OFFSET, chunk_length, chunk_length);
dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, FALSE);
}
}
@ -1756,15 +1760,20 @@ dissect_asconf_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_
#define ASCONF_ACK_CHUNK_PARAMETERS_OFFSET (SERIAL_NUMBER_OFFSET + SERIAL_NUMBER_LENGTH)
static void
dissect_asconf_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree)
dissect_asconf_ack_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
{
guint parameters_length;
tvbuff_t *parameters_tvb;
if (chunk_length < SERIAL_NUMBER_LENGTH) {
proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
chunk_length + CHUNK_HEADER_LENGTH,
CHUNK_HEADER_LENGTH + SERIAL_NUMBER_LENGTH);
return;
}
if (chunk_tree) {
proto_tree_add_item(chunk_tree, hf_asconf_ack_serial, chunk_tvb, SERIAL_NUMBER_OFFSET, SERIAL_NUMBER_LENGTH, NETWORK_BYTE_ORDER);
parameters_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH - SERIAL_NUMBER_LENGTH;
parameters_tvb = tvb_new_subset(chunk_tvb, ASCONF_ACK_CHUNK_PARAMETERS_OFFSET, parameters_length, parameters_length);
chunk_length -= SERIAL_NUMBER_LENGTH;
parameters_tvb = tvb_new_subset(chunk_tvb, ASCONF_ACK_CHUNK_PARAMETERS_OFFSET, chunk_length, chunk_length);
dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, FALSE);
}
}
@ -1806,14 +1815,19 @@ static const true_false_string sctp_pktdropk_t_bit_value = {
};
static void
dissect_pktdrop_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *flags_item)
dissect_pktdrop_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
{
guint16 data_field_length;
tvbuff_t *data_field_tvb;
proto_tree *flags_tree;
data_field_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - PKTDROP_CHUNK_HEADER_LENGTH;
data_field_tvb = tvb_new_subset(chunk_tvb, PKTDROP_CHUNK_DATA_FIELD_OFFSET, data_field_length, data_field_length);
if (chunk_length < PKTDROP_CHUNK_HEADER_LENGTH - CHUNK_HEADER_LENGTH) {
proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
chunk_length + CHUNK_HEADER_LENGTH,
PKTDROP_CHUNK_HEADER_LENGTH);
return;
}
chunk_length -= PKTDROP_CHUNK_HEADER_LENGTH;
data_field_tvb = tvb_new_subset(chunk_tvb, PKTDROP_CHUNK_DATA_FIELD_OFFSET, chunk_length, chunk_length);
if (chunk_tree) {
flags_tree = proto_item_add_subtree(flags_item, ett_sctp_pktdrop_chunk_flags);
@ -1825,9 +1839,10 @@ dissect_pktdrop_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk
proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_queuesize, chunk_tvb, PKTDROP_CHUNK_QUEUESIZE_OFFSET, PKTDROP_CHUNK_QUEUESIZE_LENGTH, NETWORK_BYTE_ORDER);
proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_truncated_length, chunk_tvb, PKTDROP_CHUNK_TRUNCATED_SIZE_OFFSET, PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH, NETWORK_BYTE_ORDER);
proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_reserved, chunk_tvb, PKTDROP_CHUNK_RESERVED_SIZE_OFFSET, PKTDROP_CHUNK_RESERVED_SIZE_LENGTH, NETWORK_BYTE_ORDER);
if (data_field_length > 0) {
/* XXX - set pinfo->in_error_pkt? */
if (chunk_length > 0) {
if (tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_PKTDROP_CHUNK_T_BIT)
proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_data_field, chunk_tvb, PKTDROP_CHUNK_DATA_FIELD_OFFSET, data_field_length, NETWORK_BYTE_ORDER);
proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_data_field, chunk_tvb, PKTDROP_CHUNK_DATA_FIELD_OFFSET, chunk_length, NETWORK_BYTE_ORDER);
else
dissect_sctp_packet(data_field_tvb, pinfo, chunk_tree, TRUE);
}
@ -1835,15 +1850,12 @@ dissect_pktdrop_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk
}
static void
dissect_unknown_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
dissect_unknown_chunk(tvbuff_t *chunk_tvb, guint16 chunk_length, proto_tree *chunk_tree, proto_item *chunk_item)
{
gint chunk_value_length;
if (chunk_tree) {
chunk_value_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
if (chunk_value_length > 0)
proto_tree_add_item(chunk_tree, hf_chunk_value, chunk_tvb, CHUNK_VALUE_OFFSET, chunk_value_length, NETWORK_BYTE_ORDER);
proto_item_append_text(chunk_item, " (Type: %u, value length: %u byte%s)", tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET), chunk_value_length, plurality(chunk_value_length, "", "s"));
if (chunk_length > 0)
proto_tree_add_item(chunk_tree, hf_chunk_value, chunk_tvb, CHUNK_VALUE_OFFSET, chunk_length, NETWORK_BYTE_ORDER);
proto_item_append_text(chunk_item, " (Type: %u, value length: %u byte%s)", tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET), chunk_length, plurality(chunk_length, "", "s"));
}
}
@ -1895,35 +1907,52 @@ dissect_sctp_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree, pr
proto_tree_add_item(type_tree, hf_chunk_bit_1, chunk_tvb, CHUNK_TYPE_OFFSET, CHUNK_TYPE_LENGTH, NETWORK_BYTE_ORDER);
proto_tree_add_item(type_tree, hf_chunk_bit_2, chunk_tvb, CHUNK_TYPE_OFFSET, CHUNK_TYPE_LENGTH, NETWORK_BYTE_ORDER);
flags_item = proto_tree_add_item(chunk_tree, hf_chunk_flags, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
proto_tree_add_item(chunk_tree, hf_chunk_length, chunk_tvb, CHUNK_LENGTH_OFFSET, CHUNK_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
} else {
chunk_tree = NULL;
chunk_item = NULL;
flags_item = NULL;
};
}
if (length < CHUNK_HEADER_LENGTH) {
if (tree) {
proto_tree_add_uint_format(chunk_tree, hf_chunk_length, chunk_tvb,
CHUNK_LENGTH_OFFSET, CHUNK_LENGTH_LENGTH,
length,
"Chunk length: %u (invalid, should be >= %u)",
length, CHUNK_HEADER_LENGTH);
proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
length, CHUNK_HEADER_LENGTH);
}
if (type == SCTP_DATA_CHUNK_ID)
result = TRUE;
return result;
}
if (tree) {
proto_tree_add_uint(chunk_tree, hf_chunk_length, chunk_tvb, CHUNK_LENGTH_OFFSET, CHUNK_LENGTH_LENGTH, length);
}
length -= CHUNK_HEADER_LENGTH;
/* now dissect the chunk value */
switch(type) {
case SCTP_DATA_CHUNK_ID:
result = dissect_data_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
result = dissect_data_chunk(chunk_tvb, length, pinfo, tree, chunk_tree, chunk_item, flags_item);
break;
case SCTP_INIT_CHUNK_ID:
dissect_init_chunk(chunk_tvb, pinfo, chunk_tree, chunk_item);
dissect_init_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
break;
case SCTP_INIT_ACK_CHUNK_ID:
dissect_init_ack_chunk(chunk_tvb, pinfo, chunk_tree, chunk_item);
dissect_init_ack_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
break;
case SCTP_SACK_CHUNK_ID:
dissect_sack_chunk(chunk_tvb, chunk_tree, chunk_item);
break;
case SCTP_HEARTBEAT_CHUNK_ID:
dissect_heartbeat_chunk(chunk_tvb, pinfo, chunk_tree, chunk_item);
dissect_heartbeat_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
break;
case SCTP_HEARTBEAT_ACK_CHUNK_ID:
dissect_heartbeat_ack_chunk(chunk_tvb, pinfo, chunk_tree, chunk_item);
dissect_heartbeat_ack_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
break;
case SCTP_ABORT_CHUNK_ID:
dissect_abort_chunk(chunk_tvb, pinfo, chunk_tree, flags_item);
dissect_abort_chunk(chunk_tvb, length, pinfo, chunk_tree, flags_item);
break;
case SCTP_SHUTDOWN_CHUNK_ID:
dissect_shutdown_chunk(chunk_tvb, chunk_tree, chunk_item);
@ -1932,10 +1961,10 @@ dissect_sctp_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree, pr
dissect_shutdown_ack_chunk(chunk_tvb);
break;
case SCTP_ERROR_CHUNK_ID:
dissect_error_chunk(chunk_tvb, pinfo, chunk_tree);
dissect_error_chunk(chunk_tvb, length, pinfo, chunk_tree);
break;
case SCTP_COOKIE_ECHO_CHUNK_ID:
dissect_cookie_echo_chunk(chunk_tvb, chunk_tree, chunk_item);
dissect_cookie_echo_chunk(chunk_tvb, length, chunk_tree, chunk_item);
break;
case SCTP_COOKIE_ACK_CHUNK_ID:
dissect_cookie_ack_chunk(chunk_tvb);
@ -1950,21 +1979,21 @@ dissect_sctp_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree, pr
dissect_shutdown_complete_chunk(chunk_tvb, chunk_tree, flags_item);
break;
case SCTP_FORWARD_TSN_CHUNK_ID:
dissect_forward_tsn_chunk(chunk_tvb, chunk_tree, chunk_item);
dissect_forward_tsn_chunk(chunk_tvb, length, chunk_tree, chunk_item);
break;
case SCTP_ASCONF_ACK_CHUNK_ID:
dissect_asconf_ack_chunk(chunk_tvb, pinfo, chunk_tree);
dissect_asconf_ack_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
break;
case SCTP_ASCONF_CHUNK_ID:
dissect_asconf_chunk(chunk_tvb, pinfo, chunk_tree);
dissect_asconf_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
break;
case SCTP_PKTDROP_CHUNK_ID:
col_set_writable(pinfo->cinfo, FALSE);
dissect_pktdrop_chunk(chunk_tvb, pinfo, chunk_tree, flags_item);
dissect_pktdrop_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item, flags_item);
col_set_writable(pinfo->cinfo, TRUE);
break;
default:
dissect_unknown_chunk(chunk_tvb, chunk_tree, chunk_item);
dissect_unknown_chunk(chunk_tvb, length, chunk_tree, chunk_item);
break;
}