From Gerrit Renker:

This is an update for the DCCP dissector and has previously been sent to
the DCCP dissector maintainer, Francesco Fondelli, who supplied
the Acked-by. I have been using it with profit for several weeks.

This patch provides the following extensions:
 * type-dependent decoding of feature-negotiation options (NN and SP types of
options, NN is a 1..6 byte value in network-byte-order, SP is always a list of
unsigned char)
 * decoding for CCID3 Send Loss Event Rate feature
 * some pretty-printing of options
 * decoding of CCID3-specific options
       - Loss Event Rate (receiver report)
       - Receive Rate (also reported by receiver)
 * there was a change in the spec - the NDP count at sometime `grew' from 3 to
6 bytes (it was the same in the kernel). I have updated the data type from uint32 to
uint64
 * utility function to decode from network-byte-order into host byte order with
variable length

svn path=/trunk/; revision=22961
This commit is contained in:
Jaap Keuter 2007-09-25 19:42:46 +00:00
parent 19e901df9a
commit 9b5e0c99a3
1 changed files with 126 additions and 136 deletions

View File

@ -118,6 +118,14 @@ static const value_string dcp_reset_code_vals[] = {
{0, NULL}
};
static const value_string dcp_feature_options_vals[] = {
{0x20, "Change L"},
{0x21, "Confirm L"},
{0x22, "Change R"},
{0x23, "Confirm R"},
{0, NULL}
};
static const value_string dcp_feature_numbers_vals[] = {
{0x01, "CCID"},
{0x02, "Allow Short Seqnos"},
@ -128,6 +136,7 @@ static const value_string dcp_feature_numbers_vals[] = {
{0x07, "Send NDP Count"},
{0x08, "Minimum Checksum Coverage"},
{0x09, "Check Data Checksum"},
{0xC0, "Send Loss Event Rate"}, /* CCID3, RFC 4342, 8.5 */
{0, NULL}
};
@ -263,6 +272,83 @@ decode_dccp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tre
call_dissector(data_handle, next_tvb, pinfo, tree);
}
/*
* Auxiliary functions to dissect DCCP options
*/
/* decode a variable-length number of nbytes starting at offset. Based on a concept by Arnaldo de Melo */
static guint64 tvb_get_ntoh_var(tvbuff_t *tvb, gint offset, guint8 nbytes)
{
const guint8* ptr;
guint64 value = 0;
ptr = tvb_get_ptr(tvb, offset, nbytes);
if (nbytes > 5)
value += ((guint64)*ptr++) << 40;
if (nbytes > 4)
value += ((guint64)*ptr++) << 32;
if (nbytes > 3)
value += ((guint64)*ptr++) << 24;
if (nbytes > 2)
value += ((guint64)*ptr++) << 16;
if (nbytes > 1)
value += ((guint64)*ptr++) << 8;
if (nbytes > 0)
value += *ptr;
return value;
}
static void dissect_feature_options(proto_tree *dcp_options_tree, tvbuff_t *tvb, int offset, guint8 option_len,
guint8 option_type)
{
guint8 feature_number = tvb_get_guint8(tvb, offset + 2);
proto_item *dcp_item;
int i;
proto_tree_add_uint_hidden(dcp_options_tree, hf_dcp_feature_number, tvb, offset + 2, 1, feature_number);
dcp_item = proto_tree_add_text(dcp_options_tree, tvb, offset, option_len, "%s(",
val_to_str(option_type, dcp_feature_options_vals, "Unknown Type"));
/* decode the feature according to whether it is server-priority (list) or NN (single number) */
switch (feature_number) {
/* Server Priority features (RFC 4340, 6.3.1) */
case 1: /* Congestion Control ID (CCID); fall through */
case 2: /* Allow Short Seqnos; fall through */
case 4: /* ECN Incapable; fall through */
case 6: /* Send Ack Vector; fall through */
case 7: /* Send NDP Count; fall through */
case 8: /* Minimum Checksum Coverage; fall through */
case 9: /* Check Data Checksum; fall through */
case 192: /* Send Loss Event Rate, RFC 4342, section 8.4 */
proto_item_append_text(dcp_item, "%s",
val_to_str(feature_number, dcp_feature_numbers_vals, "Unknown Type"));
for (i = 0; i < option_len - 3; i++)
proto_item_append_text(dcp_item, "%s %d", i? "," : "", tvb_get_guint8(tvb, offset + 3 + i));
break;
/* Non-negotiable features (RFC 4340, 6.3.2) */
case 3: /* Sequence Window; fall through */
case 5: /* Ack Ratio */
proto_item_append_text(dcp_item, "%s",
val_to_str(feature_number, dcp_feature_numbers_vals, "Unknown Type"));
if (option_len > 3) /* could be empty Confirm */
proto_item_append_text(dcp_item, " %" G_GINT64_MODIFIER "u", tvb_get_ntoh_var(tvb, offset + 3, option_len - 3));
break;
/* Reserved, specific, or unknown features */
case 0: /* fall through */
case 10 ... 127:
proto_item_append_text(dcp_item, "Reserved feature number %d", feature_number);
break;
case 193 ... 255:
proto_item_append_text(dcp_item, "CCID-specific feature number %d", feature_number);
break;
default:
proto_item_append_text(dcp_item, "Unknown feature number %d", feature_number);
break;
}
proto_item_append_text(dcp_item, ")");
}
/*
* This function dissects DCCP options
@ -274,9 +360,9 @@ static void dissect_options(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *d
/* if here I'm sure there is at least offset_end - offset_start bytes in tvb and it should be options */
int offset=offset_start;
guint8 option_type = 0;
guint8 option_len = 0;
guint8 feature_number = 0;
guint8 option_len = 0;
int i;
guint32 p;
proto_item *dcp_item = NULL;
while( offset < offset_end ) {
@ -327,104 +413,8 @@ static void dissect_options(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *d
proto_tree_add_text(dcp_options_tree, tvb, offset, option_len, "Slow Receiver");
break;
case 32:
feature_number = tvb_get_guint8(tvb, offset + 2);
proto_tree_add_uint_hidden(dcp_options_tree, hf_dcp_feature_number, tvb, offset + 2, 1, feature_number);
if( (feature_number < 10) && (feature_number!=0) ) {
dcp_item = proto_tree_add_text(dcp_options_tree, tvb, offset, option_len,
"Change L(%s",
val_to_str(feature_number, dcp_feature_numbers_vals, "Unknown Type"));
for (i = 0; i < option_len - 3; i++) {
if(i==0)
proto_item_append_text(dcp_item, "%d", tvb_get_guint8(tvb, offset + 3 + i));
else
proto_item_append_text(dcp_item, ", %d", tvb_get_guint8(tvb, offset + 3 + i));
}
proto_item_append_text(dcp_item, ")");
} else {
if(((feature_number>=10)&&(feature_number<=127))||(feature_number==0))
proto_tree_add_text(dcp_options_tree, tvb, offset, option_len,
"Change L(Reserved feature number)");
else
proto_tree_add_text(dcp_options_tree, tvb, offset, option_len,
"Change L(CCID-specific features)");
}
break;
case 33:
feature_number = tvb_get_guint8(tvb, offset + 2);
proto_tree_add_uint_hidden(dcp_options_tree, hf_dcp_feature_number, tvb, offset + 2, 1, feature_number);
if( (feature_number < 10) && (feature_number!=0) ) {
dcp_item = proto_tree_add_text(dcp_options_tree, tvb, offset, option_len,
"Confirm L(%s",
val_to_str(feature_number, dcp_feature_numbers_vals, "Unknown Type"));
for (i = 0; i < option_len - 3; i++) {
if(i==0)
proto_item_append_text(dcp_item, "%d", tvb_get_guint8(tvb, offset + 3 + i));
else
proto_item_append_text(dcp_item, ", %d", tvb_get_guint8(tvb, offset + 3 + i));
}
proto_item_append_text(dcp_item, ")");
} else {
if(((feature_number>=10)&&(feature_number<=127))||(feature_number==0))
proto_tree_add_text(dcp_options_tree, tvb, offset, option_len,
"Confirm L(Reserved feature number)");
else
proto_tree_add_text(dcp_options_tree, tvb, offset, option_len,
"Confirm L(CCID-specific features)");
}
break;
case 34:
feature_number = tvb_get_guint8(tvb, offset + 2);
proto_tree_add_uint_hidden(dcp_options_tree, hf_dcp_feature_number, tvb, offset + 2, 1, feature_number);
if( (feature_number < 10) && (feature_number!=0) ) {
dcp_item = proto_tree_add_text(dcp_options_tree, tvb, offset, option_len,
"Change R(%s",
val_to_str(feature_number, dcp_feature_numbers_vals, "Unknown Type"));
for (i = 0; i < option_len - 3; i++) {
if(i==0)
proto_item_append_text(dcp_item, "%d", tvb_get_guint8(tvb, offset + 3 + i));
else
proto_item_append_text(dcp_item, ", %d", tvb_get_guint8(tvb, offset + 3 + i));
}
proto_item_append_text(dcp_item, ")");
} else {
if(((feature_number>=10)&&(feature_number<=127))||(feature_number==0))
proto_tree_add_text(dcp_options_tree, tvb, offset, option_len,
"Change R(Reserved feature number)");
else
proto_tree_add_text(dcp_options_tree, tvb, offset, option_len,
"Change R(CCID-specific features)");
}
break;
case 35:
feature_number = tvb_get_guint8(tvb, offset + 2);
proto_tree_add_uint_hidden(dcp_options_tree, hf_dcp_feature_number, tvb, offset + 2, 1, feature_number);
if( (feature_number < 10) && (feature_number!=0) ) {
dcp_item = proto_tree_add_text(dcp_options_tree, tvb, offset, option_len,
"Confirm R(%s",
val_to_str(feature_number, dcp_feature_numbers_vals, "Unknown Type"));
for (i = 0; i < option_len - 3; i++) {
if(i==0)
proto_item_append_text(dcp_item, "%d", tvb_get_guint8(tvb, offset + 3 + i));
else
proto_item_append_text(dcp_item, ", %d", tvb_get_guint8(tvb, offset + 3 + i));
}
proto_item_append_text(dcp_item, ")");
} else {
if(((feature_number>=10)&&(feature_number<=127))||(feature_number==0))
proto_tree_add_text(dcp_options_tree, tvb, offset, option_len,
"Confirm R(Reserved feature number)");
else
proto_tree_add_text(dcp_options_tree, tvb, offset, option_len,
"Confirm R(CCID-specific features)");
}
case 32 ... 35:
dissect_feature_options(dcp_options_tree, tvb, offset, option_len, option_type);
break;
case 36:
@ -439,51 +429,30 @@ static void dissect_options(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *d
break;
case 37:
if(option_len==3)
proto_tree_add_uint(dcp_options_tree, hf_dcp_ndp_count, tvb, offset + 2, 1,
tvb_get_guint8(tvb, offset + 2));
else if (option_len==4)
proto_tree_add_uint(dcp_options_tree, hf_dcp_ndp_count, tvb, offset + 2, 2,
tvb_get_ntohs(tvb, offset + 2));
else if (option_len==5)
proto_tree_add_uint(dcp_options_tree, hf_dcp_ndp_count, tvb, offset + 2, 3,
tvb_get_ntoh24(tvb, offset + 2));
if (option_len > 8)
proto_tree_add_text(dcp_options_tree, tvb, offset, option_len, "NDP Count too long (max 6 bytes)");
else
proto_tree_add_text(dcp_options_tree, tvb, offset, option_len, "NDP Count too long (max 3 bytes)");
proto_tree_add_text(dcp_options_tree, tvb, offset, option_len, "NDP Count: %" G_GINT64_MODIFIER "u",
tvb_get_ntoh_var(tvb, offset + 2, option_len - 2));
break;
case 38:
dcp_item = proto_tree_add_text(dcp_options_tree, tvb, offset, option_len, "Ack Vector0(");
for (i = 0; i < option_len - 2; i++) {
if(i==0)
proto_item_append_text(dcp_item, "%02x", tvb_get_guint8(tvb, offset + 2 + i));
else
proto_item_append_text(dcp_item, " %02x", tvb_get_guint8(tvb, offset + 2 + i));
}
proto_item_append_text(dcp_item, ")");
dcp_item = proto_tree_add_text(dcp_options_tree, tvb, offset, option_len, "Ack Vector [Nonce 0]:");
for (i = 0; i < option_len - 2; i++)
proto_item_append_text(dcp_item, " %02x", tvb_get_guint8(tvb, offset + 2 + i));
break;
case 39:
dcp_item = proto_tree_add_text(dcp_options_tree, tvb, offset, option_len, "Ack Vector1(");
for (i = 0; i < option_len - 2; i++) {
if(i==0)
proto_item_append_text(dcp_item, "%02x", tvb_get_guint8(tvb, offset + 2 + i));
else
proto_item_append_text(dcp_item, " %02x", tvb_get_guint8(tvb, offset + 2 + i));
}
dcp_item = proto_tree_add_text(dcp_options_tree, tvb, offset, option_len, "Ack Vector [Nonce 1]:");
for (i = 0; i < option_len - 2; i++)
proto_item_append_text(dcp_item, " %02x", tvb_get_guint8(tvb, offset + 2 + i));
proto_item_append_text(dcp_item, ")");
break;
case 40:
dcp_item = proto_tree_add_text(dcp_options_tree, tvb, offset, option_len, "Data Dropped(");
for (i = 0; i < option_len - 2; i++) {
if(i==0)
proto_item_append_text(dcp_item, "%02x", tvb_get_guint8(tvb, offset + 2 + i));
else
proto_item_append_text(dcp_item, " %02x", tvb_get_guint8(tvb, offset + 2 + i));
}
proto_item_append_text(dcp_item, ")");
dcp_item = proto_tree_add_text(dcp_options_tree, tvb, offset, option_len, "Data Dropped:");
for (i = 0; i < option_len - 2; i++)
proto_item_append_text(dcp_item, " %02x", tvb_get_guint8(tvb, offset + 2 + i));
break;
case 41:
@ -533,7 +502,28 @@ static void dissect_options(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *d
} else
proto_tree_add_text(dcp_options_tree, tvb, offset, option_len, "Wrong Data checksum length");
break;
case 192: /* RFC 4342, 8.5 */
if(option_len == 6) {
p = tvb_get_ntohl(tvb, offset + 2);
/* According to the comment in section 8.5 of RFC 4342, 0xffffffff can mean zero */
if (p == 0xFFFFFFFF)
proto_tree_add_text(dcp_options_tree, tvb, offset, option_len, "CCID3 Loss Event Rate: 0 (or max)");
else
proto_tree_add_text(dcp_options_tree, tvb, offset, option_len, "CCID3 Loss Event Rate: %u", p);
} else
proto_tree_add_text(dcp_options_tree, tvb, offset, option_len, "Wrong CCID3 Loss Event Rate length");
break;
case 193: /* RFC 4342, 8.6 */
proto_tree_add_text(dcp_options_tree, tvb, offset, option_len, "CCID3 Loss Intervals");
/* FIXME: not implemented and apparently not used by any implementation so far */
break;
case 194: /* RFC 4342, 8.3 */
if(option_len == 6)
proto_tree_add_text(dcp_options_tree, tvb, offset, option_len, "CCID3 Receive Rate: %u bytes/sec",
tvb_get_ntohl(tvb, offset + 2));
else
proto_tree_add_text(dcp_options_tree, tvb, offset, option_len, "Wrong CCID3 Receive Rate length");
break;
default :
if(((option_type >= 45) && (option_type <= 127)) ||
((option_type >= 3) && (option_type <= 31))) {
@ -1082,7 +1072,7 @@ void proto_register_dcp(void)
"", HFILL }},
{ &hf_dcp_ndp_count,
{ "NDP Count", "dcp.ndp_count", FT_UINT32, BASE_DEC, NULL, 0x0,
{ "NDP Count", "dcp.ndp_count", FT_UINT64, BASE_DEC, NULL, 0x0,
"", HFILL }},
{ &hf_dcp_timestamp,