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:
parent
19e901df9a
commit
9b5e0c99a3
|
@ -118,6 +118,14 @@ static const value_string dcp_reset_code_vals[] = {
|
||||||
{0, NULL}
|
{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[] = {
|
static const value_string dcp_feature_numbers_vals[] = {
|
||||||
{0x01, "CCID"},
|
{0x01, "CCID"},
|
||||||
{0x02, "Allow Short Seqnos"},
|
{0x02, "Allow Short Seqnos"},
|
||||||
|
@ -128,6 +136,7 @@ static const value_string dcp_feature_numbers_vals[] = {
|
||||||
{0x07, "Send NDP Count"},
|
{0x07, "Send NDP Count"},
|
||||||
{0x08, "Minimum Checksum Coverage"},
|
{0x08, "Minimum Checksum Coverage"},
|
||||||
{0x09, "Check Data Checksum"},
|
{0x09, "Check Data Checksum"},
|
||||||
|
{0xC0, "Send Loss Event Rate"}, /* CCID3, RFC 4342, 8.5 */
|
||||||
{0, NULL}
|
{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);
|
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
|
* 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 */
|
/* 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;
|
int offset=offset_start;
|
||||||
guint8 option_type = 0;
|
guint8 option_type = 0;
|
||||||
guint8 option_len = 0;
|
guint8 option_len = 0;
|
||||||
guint8 feature_number = 0;
|
|
||||||
int i;
|
int i;
|
||||||
|
guint32 p;
|
||||||
proto_item *dcp_item = NULL;
|
proto_item *dcp_item = NULL;
|
||||||
|
|
||||||
while( offset < offset_end ) {
|
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");
|
proto_tree_add_text(dcp_options_tree, tvb, offset, option_len, "Slow Receiver");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 32:
|
case 32 ... 35:
|
||||||
feature_number = tvb_get_guint8(tvb, offset + 2);
|
dissect_feature_options(dcp_options_tree, tvb, offset, option_len, option_type);
|
||||||
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)");
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 36:
|
case 36:
|
||||||
|
@ -439,51 +429,30 @@ static void dissect_options(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *d
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 37:
|
case 37:
|
||||||
if(option_len==3)
|
if (option_len > 8)
|
||||||
proto_tree_add_uint(dcp_options_tree, hf_dcp_ndp_count, tvb, offset + 2, 1,
|
proto_tree_add_text(dcp_options_tree, tvb, offset, option_len, "NDP Count too long (max 6 bytes)");
|
||||||
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));
|
|
||||||
else
|
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;
|
break;
|
||||||
|
|
||||||
case 38:
|
case 38:
|
||||||
dcp_item = proto_tree_add_text(dcp_options_tree, tvb, offset, option_len, "Ack Vector0(");
|
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++) {
|
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));
|
||||||
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, ")");
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 39:
|
case 39:
|
||||||
dcp_item = proto_tree_add_text(dcp_options_tree, tvb, offset, option_len, "Ack Vector1(");
|
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++) {
|
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));
|
||||||
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, ")");
|
proto_item_append_text(dcp_item, ")");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 40:
|
case 40:
|
||||||
dcp_item = proto_tree_add_text(dcp_options_tree, tvb, offset, option_len, "Data Dropped(");
|
dcp_item = proto_tree_add_text(dcp_options_tree, tvb, offset, option_len, "Data Dropped:");
|
||||||
for (i = 0; i < option_len - 2; i++) {
|
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));
|
||||||
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, ")");
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 41:
|
case 41:
|
||||||
|
@ -533,7 +502,28 @@ static void dissect_options(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *d
|
||||||
} else
|
} else
|
||||||
proto_tree_add_text(dcp_options_tree, tvb, offset, option_len, "Wrong Data checksum length");
|
proto_tree_add_text(dcp_options_tree, tvb, offset, option_len, "Wrong Data checksum length");
|
||||||
break;
|
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 :
|
default :
|
||||||
if(((option_type >= 45) && (option_type <= 127)) ||
|
if(((option_type >= 45) && (option_type <= 127)) ||
|
||||||
((option_type >= 3) && (option_type <= 31))) {
|
((option_type >= 3) && (option_type <= 31))) {
|
||||||
|
@ -1082,7 +1072,7 @@ void proto_register_dcp(void)
|
||||||
"", HFILL }},
|
"", HFILL }},
|
||||||
|
|
||||||
{ &hf_dcp_ndp_count,
|
{ &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 }},
|
"", HFILL }},
|
||||||
|
|
||||||
{ &hf_dcp_timestamp,
|
{ &hf_dcp_timestamp,
|
||||||
|
|
Loading…
Reference in New Issue