MP-DCCP: Implemented MP-DCCP up-to V4.

Used Leonard Walter's MP-DCCP dissector code.
This commit is contained in:
GREGORIO-M 2022-11-16 12:05:24 +00:00
parent 74dc39697f
commit 16ea20120c
1 changed files with 206 additions and 34 deletions

View File

@ -80,8 +80,6 @@
void proto_register_dccp(void);
void proto_reg_handoff_dccp(void);
static dissector_handle_t dccp_handle;
/*
* FF: please keep this list in sync with
* http://www.iana.org/assignments/dccp-parameters/dccp-parameters.xml
@ -162,7 +160,9 @@ static const range_string dccp_options_rvals[] = {
{0x2A, 0x2A, "Timestamp Echo"},
{0x2B, 0x2B, "Elapsed Time"},
{0x2C, 0x2C, "Data checksum"},
{0x2D, 0x7F, "Reserved"},
{0x2D, 0x2D, "Reserved"},
{0x2E, 0x2E, "MPDCCP"},
{0x2F, 0x7F, "Reserved"},
{0x80, 0xBF, "CCID option"},
{0xC0, 0xC0, "CCID3 Loss Event Rate"},
{0xC1, 0xC1, "CCID3 Loss Intervals"},
@ -229,6 +229,40 @@ static int hf_dccp_timestamp_echo = -1;
static int hf_dccp_elapsed_time = -1;
static int hf_dccp_data_checksum = -1;
/* MP-DCCP Option fields */
static int hf_mpdccp_confirm = -1;
static int hf_mpdccp_join = -1;
static int hf_mpdccp_join_id = -1;
static int hf_mpdccp_join_token = -1;
static int hf_mpdccp_join_nonce = -1;
static int hf_mpdccp_fast_close = -1;
static int hf_mpdccp_key = -1;
static int hf_mpdccp_key_type = -1;
static int hf_mpdccp_key_key = -1;
static int hf_mpdccp_seq = -1;
static int hf_mpdccp_hmac = -1;
static int hf_mpdccp_rtt = -1;
static int hf_mpdccp_rtt_type = -1;
static int hf_mpdccp_rtt_value = -1;
static int hf_mpdccp_rtt_age = -1;
//static int hf_mpdccp_addaddr = -1;
//static int hf_mpdccp_removeaddr = -1;
static int hf_mpdccp_prio = -1;
static int hf_mpdccp_prio_value = -1;
static int hf_mpdccp_prio_id = -1;
static int hf_mpdccp_close = -1;
static int hf_dccp_option_data = -1;
/* Generated from convert_proto_tree_add_text.pl */
static int hf_dccp_padding = -1;
static int hf_dccp_mandatory = -1;
@ -283,7 +317,7 @@ decode_dccp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
* determine if this packet is part of a conversation and call dissector
* for the conversation if available
*/
if (try_conversation_dissector(&pinfo->src, &pinfo->dst, CONVERSATION_DCCP, sport,
if (try_conversation_dissector(&pinfo->src, &pinfo->dst, ENDPOINT_DCCP, sport,
dport, next_tvb, pinfo, tree, NULL, 0)) {
return;
}
@ -442,18 +476,17 @@ static const char* dccp_conv_get_filter_type(conv_item_t* conv, conv_filter_type
static ct_dissector_info_t dccp_ct_dissector_info = {&dccp_conv_get_filter_type};
static tap_packet_status
dccpip_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip, tap_flags_t flags)
dccpip_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip)
{
conv_hash_t *hash = (conv_hash_t*) pct;
hash->flags = flags;
const e_dccphdr *dccphdr=(const e_dccphdr *)vip;
add_conversation_table_data_with_conv_id(hash, &dccphdr->ip_src, &dccphdr->ip_dst, dccphdr->sport, dccphdr->dport, (conv_id_t) dccphdr->stream, 1, pinfo->fd->pkt_len, &pinfo->rel_ts, &pinfo->abs_ts, &dccp_ct_dissector_info, CONVERSATION_DCCP);
add_conversation_table_data_with_conv_id(hash, &dccphdr->ip_src, &dccphdr->ip_dst, dccphdr->sport, dccphdr->dport, (conv_id_t) dccphdr->stream, 1, pinfo->fd->pkt_len, &pinfo->rel_ts, &pinfo->abs_ts, &dccp_ct_dissector_info, ENDPOINT_DCCP);
return TAP_PACKET_REDRAW;
}
static const char* dccp_endpoint_get_filter_type(endpoint_item_t* endpoint, conv_filter_type_e filter)
static const char* dccp_host_get_filter_type(hostlist_talker_t* host, conv_filter_type_e filter)
{
if (filter == CONV_FT_SRC_PORT)
@ -465,49 +498,48 @@ static const char* dccp_endpoint_get_filter_type(endpoint_item_t* endpoint, conv
if (filter == CONV_FT_ANY_PORT)
return "dccp.port";
if(!endpoint) {
if(!host) {
return CONV_FILTER_INVALID;
}
if (filter == CONV_FT_SRC_ADDRESS) {
if (endpoint->myaddress.type == AT_IPv4)
if (host->myaddress.type == AT_IPv4)
return "ip.src";
if (endpoint->myaddress.type == AT_IPv6)
if (host->myaddress.type == AT_IPv6)
return "ipv6.src";
}
if (filter == CONV_FT_DST_ADDRESS) {
if (endpoint->myaddress.type == AT_IPv4)
if (host->myaddress.type == AT_IPv4)
return "ip.dst";
if (endpoint->myaddress.type == AT_IPv6)
if (host->myaddress.type == AT_IPv6)
return "ipv6.dst";
}
if (filter == CONV_FT_ANY_ADDRESS) {
if (endpoint->myaddress.type == AT_IPv4)
if (host->myaddress.type == AT_IPv4)
return "ip.addr";
if (endpoint->myaddress.type == AT_IPv6)
if (host->myaddress.type == AT_IPv6)
return "ipv6.addr";
}
return CONV_FILTER_INVALID;
}
static et_dissector_info_t dccp_endpoint_dissector_info = {&dccp_endpoint_get_filter_type};
static hostlist_dissector_info_t dccp_host_dissector_info = {&dccp_host_get_filter_type};
static tap_packet_status
dccpip_endpoint_packet(void *pit, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip, tap_flags_t flags )
dccpip_hostlist_packet(void *pit, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip)
{
conv_hash_t *hash = (conv_hash_t*) pit;
hash->flags = flags;
const e_dccphdr *dccphdr=(const e_dccphdr *)vip;
/* Take two "add" passes per packet, adding for each direction, ensures that all
packets are counted properly (even if address is sending to itself)
XXX - this could probably be done more efficiently inside endpoint_table */
add_endpoint_table_data(hash, &dccphdr->ip_src, dccphdr->sport, TRUE, 1, pinfo->fd->pkt_len, &dccp_endpoint_dissector_info, ENDPOINT_DCCP);
add_endpoint_table_data(hash, &dccphdr->ip_dst, dccphdr->dport, FALSE, 1, pinfo->fd->pkt_len, &dccp_endpoint_dissector_info, ENDPOINT_DCCP);
XXX - this could probably be done more efficiently inside hostlist_table */
add_hostlist_table_data(hash, &dccphdr->ip_src, dccphdr->sport, TRUE, 1, pinfo->fd->pkt_len, &dccp_host_dissector_info, ENDPOINT_DCCP);
add_hostlist_table_data(hash, &dccphdr->ip_dst, dccphdr->dport, FALSE, 1, pinfo->fd->pkt_len, &dccp_host_dissector_info, ENDPOINT_DCCP);
return TAP_PACKET_REDRAW;
}
@ -551,16 +583,9 @@ static gchar *dccp_follow_conv_filter(epan_dissect_t *edt _U_, packet_info *pinf
conversation_t *conv;
struct dccp_analysis *dccpd;
/* XXX: Since DCCP doesn't use the endpoint API, we can only look
* up using the current pinfo addresses and ports. We don't want
* to create a new conversation or stream.
* Eventually the endpoint API should support storing multiple
* endpoints and DCCP should be changed to use the endpoint API.
*/
if (((pinfo->net_src.type == AT_IPv4 && pinfo->net_dst.type == AT_IPv4) ||
(pinfo->net_src.type == AT_IPv6 && pinfo->net_dst.type == AT_IPv6))
&& (pinfo->ptype == PT_DCCP) &&
(conv=find_conversation(pinfo->num, &pinfo->net_src, &pinfo->net_dst, CONVERSATION_DCCP, pinfo->srcport, pinfo->destport, 0)) != NULL)
if( ((pinfo->net_src.type == AT_IPv4 && pinfo->net_dst.type == AT_IPv4) ||
(pinfo->net_src.type == AT_IPv6 && pinfo->net_dst.type == AT_IPv6))
&& (conv=find_conversation_pinfo(pinfo, 0)) != NULL )
{
/* DCCP over IPv4/6 */
dccpd = get_dccp_conversation_data(conv, pinfo);
@ -711,8 +736,14 @@ dissect_options(tvbuff_t *tvb, packet_info *pinfo,
guint8 option_type = 0;
guint8 option_len = 0;
guint32 p;
guint8 mp_option_type = 0;
proto_item *option_item;
proto_tree *option_tree;
proto_item *mp_option_sub_item;
proto_tree *mp_option_sub_tree;
while (offset < offset_end) {
/* first byte is the option type */
@ -822,6 +853,110 @@ dissect_options(tvbuff_t *tvb, packet_info *pinfo,
expert_add_info_format(pinfo, option_item, &ei_dccp_option_len_bad,
"Wrong Data checksum length");
break;
case 46:
mp_option_type = tvb_get_guint8(tvb, offset);
option_len -= 1;
switch (mp_option_type) {
case 0:
proto_tree_add_item(option_tree, hf_mpdccp_confirm, tvb, offset, option_len, ENC_BIG_ENDIAN);
break;
case 1:
mp_option_sub_item = proto_tree_add_item(option_tree, hf_mpdccp_join, tvb, offset, 1, ENC_BIG_ENDIAN);
mp_option_sub_tree = proto_item_add_subtree(mp_option_sub_item, ett_dccp_options_item);
offset += 1;
if (option_len == 9) {
proto_tree_add_item(mp_option_sub_tree, hf_mpdccp_join_id, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(mp_option_sub_tree, hf_mpdccp_join_token, tvb, offset+1, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(mp_option_sub_tree, hf_mpdccp_join_nonce, tvb, offset+5, 4, ENC_BIG_ENDIAN);
} else {
mp_option_sub_item = proto_tree_add_item(option_tree, hf_dccp_option_data, tvb, offset, option_len, ENC_NA);
expert_add_info_format(pinfo, mp_option_sub_item, &ei_dccp_option_len_bad,
"Wrong Data checksum length, [%u != 9]", option_len);
}
break;
case 2:
proto_tree_add_item(option_tree, hf_mpdccp_fast_close, tvb, offset, option_len, ENC_BIG_ENDIAN);
break;
case 3:
mp_option_sub_item = proto_tree_add_item(option_tree, hf_mpdccp_key, tvb, offset, 1, ENC_BIG_ENDIAN);
mp_option_sub_tree = proto_item_add_subtree(mp_option_sub_item, ett_dccp_options_item);
offset += 1;
if (option_len > 8 && option_len < 69) {
proto_tree_add_item(mp_option_sub_tree, hf_mpdccp_key_type, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(mp_option_sub_tree, hf_mpdccp_key_key, tvb, offset+1, option_len, ENC_BIG_ENDIAN);
} else {
mp_option_sub_item = proto_tree_add_item(mp_option_sub_tree, hf_dccp_option_data, tvb, offset, option_len, ENC_NA);
expert_add_info_format(pinfo, mp_option_sub_item, &ei_dccp_option_len_bad,
"Wrong Data checksum length, [%u < 9]", option_len);
}
break;
case 4:
if (option_len == 4) {
proto_tree_add_item(option_tree, hf_mpdccp_seq, tvb, offset, 4, ENC_BIG_ENDIAN);
//col_add_fstr(pinfo->cinfo, COL_INFO, "OaSeq: %u", tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN));
} else {
mp_option_sub_item = proto_tree_add_item(option_tree, hf_mpdccp_seq, tvb, offset, option_len, ENC_BIG_ENDIAN);
expert_add_info_format(pinfo, mp_option_sub_item, &ei_dccp_option_len_bad,
"Wrong Data checksum length, [%u != 4]", option_len);
}
break;
case 5:
if (option_len == 20) {
proto_tree_add_item(option_tree, hf_mpdccp_hmac, tvb, offset, 20, ENC_BIG_ENDIAN);
} else {
mp_option_sub_item = proto_tree_add_item(option_tree, hf_mpdccp_hmac, tvb, offset, option_len, ENC_BIG_ENDIAN);
expert_add_info_format(pinfo, mp_option_sub_item, &ei_dccp_option_len_bad,
"Wrong Data checksum length, [%u != 20]", option_len);
}
break;
case 6:
mp_option_sub_item = proto_tree_add_item(option_tree, hf_mpdccp_rtt, tvb, offset, 1, ENC_BIG_ENDIAN);
mp_option_sub_tree = proto_item_add_subtree(mp_option_sub_item, ett_dccp_options_item);
offset += 1;
if (option_len == 9) {
proto_tree_add_item(mp_option_sub_tree, hf_mpdccp_rtt_type,
tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(mp_option_sub_tree, hf_mpdccp_rtt_value,
tvb, offset+1, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(mp_option_sub_tree, hf_mpdccp_rtt_age,
tvb, offset+5, 4, ENC_BIG_ENDIAN);
} else {
mp_option_sub_item = proto_tree_add_item(mp_option_sub_tree, hf_dccp_option_data, tvb, offset, option_len, ENC_NA);
expert_add_info_format(pinfo, mp_option_sub_item, &ei_dccp_option_len_bad,
"Wrong Data checksum length, [%u != 9]", option_len);
}
break;
/* case 7: //To-Do add MP_ADDADDR and MP_REMOVEADDR
break;
case 8:
break; */
case 9:
mp_option_sub_item = proto_tree_add_item(option_tree, hf_mpdccp_prio, tvb, offset, 1, ENC_BIG_ENDIAN);
mp_option_sub_tree = proto_item_add_subtree(mp_option_sub_item, ett_dccp_options_item);
offset += 1;
if (option_len == 2) {
proto_tree_add_item(mp_option_sub_tree, hf_mpdccp_prio_id, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(mp_option_sub_tree, hf_mpdccp_prio_value, tvb, offset+1, 1, ENC_BIG_ENDIAN);
} else {
mp_option_sub_item = proto_tree_add_item(mp_option_sub_tree, hf_dccp_option_data, tvb, offset, option_len, ENC_NA);
expert_add_info_format(pinfo, mp_option_sub_item, &ei_dccp_option_len_bad,
"Wrong Data checksum length, [%u != 2]", option_len);
}
break;
case 10:
mp_option_sub_item = proto_tree_add_item(option_tree, hf_mpdccp_close,
tvb, offset, option_len, ENC_BIG_ENDIAN);
break;
default:
mp_option_sub_item = proto_tree_add_item(mp_option_sub_tree, hf_dccp_option_data, tvb, offset, option_len, ENC_NA);
expert_add_info_format(pinfo, mp_option_sub_item, &ei_dccp_option_len_bad,
"MP-DCCP option [%u] not defined, [len: %u ]", mp_option_type, option_len);
break;
}
break;
case 192: /* RFC 4342, 8.5 */
if (option_len == 4) {
p = tvb_get_ntohl(tvb, offset);
@ -1644,6 +1779,41 @@ proto_register_dccp(void)
NULL, HFILL
}
},
/* MP-DCCP related option fields */
{&hf_mpdccp_confirm,{"MP_CONFIRM", "mpdccp.mp_confirm",FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
{&hf_mpdccp_join,{"MP_JOIN", "mpdccp.mp_join",FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
{&hf_mpdccp_join_id,{"MP_JOIN id", "mpdccp.mp_join",FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
{&hf_mpdccp_join_token,{"MP_JOIN token", "mpdccp.mp_join",FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}},
{&hf_mpdccp_join_nonce,{"MP_JOIN nonce", "mpdccp.mp_join",FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}},
{&hf_mpdccp_fast_close,{"MP_FAST_CLOSE", "mpdccp.mp_fast_close",FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
{&hf_mpdccp_key,{"MP_KEY", "mpdccp.mp_key",FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
{&hf_mpdccp_key_type,{"MP_KEY type", "mpdccp.mp_key_type",FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
{&hf_mpdccp_key_key,{"MP_KEY hash", "mpdccp.mp_key_hash",FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
{&hf_mpdccp_seq,{"MP_SEQ", "mpdccp.mp_seq",FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
{&hf_mpdccp_hmac,{"MP_HMAC", "mpdccp.mp_hmac",FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
{&hf_mpdccp_rtt,{"MP_RTT", "mpdccp.mp_rtt",FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
{&hf_mpdccp_rtt_type,{"RTT_TYPE", "mpdccp.rtt_type",FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
{&hf_mpdccp_rtt_value,{"RTT_VALUE", "mpdccp.rtt_value",FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
{&hf_mpdccp_rtt_age,{"RTT_AGE", "mpdccp.rtt_age",FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
// {&hf_mpdccp_addaddr,{"MP_ADDADDR", "mpdccp.mp_addaddr",FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
// {&hf_mpdccp_removeaddr,{"MP_REMOVEADDR", "mpdccp.mp_removeaddr",FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
{&hf_mpdccp_prio,{"MP_PRIO", "mpdccp.mp_prio",FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
{&hf_mpdccp_prio_id,{"MP_PRIO id", "mpdccp.mp_prio",FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
{&hf_mpdccp_prio_value,{"MP_PRIO value", "mpdccp.mp_prio",FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
{&hf_mpdccp_close,{"MP_CLOSE", "mpdccp.mp_close",FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
{&hf_dccp_option_data,{"Option data", "mpdccp.mp_option",FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
{
&hf_dccp_options,
{
@ -1688,7 +1858,6 @@ proto_register_dccp(void)
proto_dccp =
proto_register_protocol("Datagram Congestion Control Protocol", "DCCP",
"dccp");
dccp_handle = register_dissector("dccp", dissect_dccp, proto_dccp);
proto_register_field_array(proto_dccp, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
expert_dccp = expert_register_protocol(proto_dccp);
@ -1730,10 +1899,10 @@ proto_register_dccp(void)
"Make the DCCP dissector use relative sequence numbers instead of absolute ones.",
&dccp_relative_seq);
register_conversation_table(proto_dccp, FALSE, dccpip_conversation_packet, dccpip_endpoint_packet);
register_conversation_table(proto_dccp, FALSE, dccpip_conversation_packet, dccpip_hostlist_packet);
register_conversation_filter("dccp", "DCCP", dccp_filter_valid, dccp_build_filter);
register_follow_stream(proto_dccp, "dccp_follow", dccp_follow_conv_filter, dccp_follow_index_filter, dccp_follow_address_filter,
dccp_port_to_display, follow_tvb_tap_listener, get_dccp_stream_count);
dccp_port_to_display, follow_tvb_tap_listener);
register_init_routine(dccp_init);
}
@ -1741,6 +1910,9 @@ proto_register_dccp(void)
void
proto_reg_handoff_dccp(void)
{
dissector_handle_t dccp_handle;
dccp_handle = create_dissector_handle(dissect_dccp, proto_dccp);
dissector_add_uint("ip.proto", IP_PROTO_DCCP, dccp_handle);
dccp_tap = register_tap("dccp");
dccp_follow_tap = register_tap("dccp_follow");