Include VLAN ID in key for ICMP request/response tracking

Add global preference to allow for "stricter" conversation tracking

Bug: 13518
Change-Id: I166a084c402374fa76dac7bb54f941e2e9c9325a
Reviewed-on: https://code.wireshark.org/review/22842
Petri-Dish: Michael Mann <mmann78@netscape.net>
Tested-by: Petri Dish Buildbot
Reviewed-by: Michael Mann <mmann78@netscape.net>
This commit is contained in:
Christopher Maynard 2017-07-29 12:18:26 -04:00 committed by Michael Mann
parent 05b1d35586
commit ea49c337c5
4 changed files with 57 additions and 21 deletions

View File

@ -967,6 +967,19 @@ dissect_extensions(tvbuff_t * tvb, packet_info *pinfo, gint offset, proto_tree *
}
/* ======================================================================= */
/*
Note: We are tracking conversations via these keys:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |G| Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identifier | Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| VLAN ID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
static icmp_transaction_t *transaction_start(packet_info * pinfo,
proto_tree * tree,
guint32 * key)
@ -992,7 +1005,7 @@ static icmp_transaction_t *transaction_start(packet_info * pinfo,
/* this is a new request, create a new transaction structure and map it to the
unmatched table
*/
icmp_key[0].length = 2;
icmp_key[0].length = 3;
icmp_key[0].key = key;
icmp_key[1].length = 0;
icmp_key[1].key = NULL;
@ -1008,7 +1021,7 @@ static icmp_transaction_t *transaction_start(packet_info * pinfo,
/* Already visited this frame */
guint32 frame_num = pinfo->num;
icmp_key[0].length = 2;
icmp_key[0].length = 3;
icmp_key[0].key = key;
icmp_key[1].length = 1;
icmp_key[1].key = &frame_num;
@ -1082,7 +1095,7 @@ static icmp_transaction_t *transaction_end(packet_info * pinfo,
if (!PINFO_FD_VISITED(pinfo)) {
guint32 frame_num;
icmp_key[0].length = 2;
icmp_key[0].length = 3;
icmp_key[0].key = key;
icmp_key[1].length = 0;
icmp_key[1].key = NULL;
@ -1102,7 +1115,7 @@ static icmp_transaction_t *transaction_end(packet_info * pinfo,
/* we found a match. Add entries to the matched table for both request and reply frames
*/
icmp_key[0].length = 2;
icmp_key[0].length = 3;
icmp_key[0].key = key;
icmp_key[1].length = 1;
icmp_key[1].key = &frame_num;
@ -1120,7 +1133,7 @@ static icmp_transaction_t *transaction_end(packet_info * pinfo,
/* Already visited this frame */
guint32 frame_num = pinfo->num;
icmp_key[0].length = 2;
icmp_key[0].length = 3;
icmp_key[0].key = key;
icmp_key[1].length = 1;
icmp_key[1].key = &frame_num;
@ -1238,7 +1251,7 @@ dissect_icmp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data)
guint32 i;
gboolean save_in_error_pkt;
tvbuff_t *next_tvb;
guint32 conv_key[2];
guint32 conv_key[3];
icmp_transaction_t *trans = NULL;
nstime_t ts, time_relative;
ws_ip4 *iph = WS_IP4_PTR(data);
@ -1506,11 +1519,12 @@ dissect_icmp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data)
if (!pinfo->flags.in_error_pkt) {
conv_key[0] =
(guint32) tvb_get_ntohs(tvb, 2);
if (pinfo->flags.in_gre_pkt)
if (pinfo->flags.in_gre_pkt && prefs.strict_conversation_tracking_heuristics)
conv_key[0] |= 0x00010000; /* set a bit for "in GRE" */
conv_key[1] =
((guint32) tvb_get_ntohs(tvb, 4) << 16) |
tvb_get_ntohs(tvb, 6);
conv_key[2] = prefs.strict_conversation_tracking_heuristics ? pinfo->vlan_id : 0;
trans =
transaction_end(pinfo, icmp_tree,
conv_key);
@ -1527,12 +1541,13 @@ dissect_icmp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data)
if (conv_key[0] == 0) {
conv_key[0] = 0xffff;
}
if (pinfo->flags.in_gre_pkt) {
if (pinfo->flags.in_gre_pkt && prefs.strict_conversation_tracking_heuristics) {
conv_key[0] |= 0x00010000; /* set a bit for "in GRE" */
}
conv_key[1] =
((guint32) tvb_get_ntohs(tvb, 4) << 16) |
tvb_get_ntohs(tvb, 6);
conv_key[2] = prefs.strict_conversation_tracking_heuristics ? pinfo->vlan_id : 0;
trans =
transaction_start(pinfo, icmp_tree,
conv_key);

View File

@ -1387,6 +1387,19 @@ static conversation_t *_find_or_create_conversation(packet_info *pinfo)
}
/* ======================================================================= */
/*
Note: We are tracking conversations via these keys:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |G| Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identifier | Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| VLAN ID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
static icmp_transaction_t *transaction_start(packet_info *pinfo, proto_tree *tree, guint32 *key)
{
conversation_t *conversation;
@ -1410,7 +1423,7 @@ static icmp_transaction_t *transaction_start(packet_info *pinfo, proto_tree *tre
* This is a new request, create a new transaction structure and map it
* to the unmatched table.
*/
icmpv6_key[0].length = 2;
icmpv6_key[0].length = 3;
icmpv6_key[0].key = key;
icmpv6_key[1].length = 0;
icmpv6_key[1].key = NULL;
@ -1425,7 +1438,7 @@ static icmp_transaction_t *transaction_start(packet_info *pinfo, proto_tree *tre
/* Already visited this frame */
guint32 frame_num = pinfo->num;
icmpv6_key[0].length = 2;
icmpv6_key[0].length = 3;
icmpv6_key[0].key = key;
icmpv6_key[1].length = 1;
icmpv6_key[1].key = &frame_num;
@ -1496,7 +1509,7 @@ static icmp_transaction_t *transaction_end(packet_info *pinfo, proto_tree *tree,
if (!PINFO_FD_VISITED(pinfo)) {
guint32 frame_num;
icmpv6_key[0].length = 2;
icmpv6_key[0].length = 3;
icmpv6_key[0].key = key;
icmpv6_key[1].length = 0;
icmpv6_key[1].key = NULL;
@ -1515,7 +1528,7 @@ static icmp_transaction_t *transaction_end(packet_info *pinfo, proto_tree *tree,
* we found a match. Add entries to the matched table for both
* request and reply frames
*/
icmpv6_key[0].length = 2;
icmpv6_key[0].length = 3;
icmpv6_key[0].key = key;
icmpv6_key[1].length = 1;
icmpv6_key[1].key = &frame_num;
@ -1531,7 +1544,7 @@ static icmp_transaction_t *transaction_end(packet_info *pinfo, proto_tree *tree,
/* Already visited this frame */
guint32 frame_num = pinfo->num;
icmpv6_key[0].length = 2;
icmpv6_key[0].length = 3;
icmpv6_key[0].key = key;
icmpv6_key[1].length = 1;
icmpv6_key[1].key = &frame_num;
@ -3949,8 +3962,8 @@ dissect_icmpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
reported_length = tvb_reported_length(tvb);
if (!pinfo->fragmented && length >= reported_length && !pinfo->flags.in_error_pkt) {
/* The packet isn't part of a fragmented datagram, isn't truncated,
* and we aren't in an ICMP error packet, so we can checksum it.
*/
* and we aren't in an ICMP error packet, so we can checksum it.
*/
/* Set up the fields of the pseudo-header. */
SET_CKSUM_VEC_PTR(cksum_vec[0], (const guint8 *)pinfo->src.data, pinfo->src.len);
@ -3961,10 +3974,10 @@ dissect_icmpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
SET_CKSUM_VEC_TVB(cksum_vec[3], tvb, 0, reported_length);
proto_tree_add_checksum(icmp6_tree, tvb, 2, hf_icmpv6_checksum, hf_icmpv6_checksum_status, &ei_icmpv6_checksum, pinfo, in_cksum(cksum_vec, 4),
ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_IN_CKSUM);
ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_IN_CKSUM);
} else {
checksum_item = proto_tree_add_checksum(icmp6_tree, tvb, 2, hf_icmpv6_checksum, hf_icmpv6_checksum_status, &ei_icmpv6_checksum, pinfo, 0,
ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
checksum_item = proto_tree_add_checksum(icmp6_tree, tvb, 2, hf_icmpv6_checksum, hf_icmpv6_checksum_status, &ei_icmpv6_checksum, pinfo, 0,
ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
proto_item_append_text(checksum_item, " [%s]",
pinfo->flags.in_error_pkt ? "in ICMP error packet" : "fragmented datagram");
}
@ -4006,13 +4019,14 @@ dissect_icmpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
offset += 4;
} else {
if (!pinfo->flags.in_error_pkt) {
guint32 conv_key[2];
guint32 conv_key[3];
conv_key[1] = (guint32)((identifier << 16) | sequence);
conv_key[2] = prefs.strict_conversation_tracking_heuristics ? pinfo->vlan_id : 0;
if (icmp6_type == ICMP6_ECHO_REQUEST) {
conv_key[0] = (guint32)cksum;
if (pinfo->flags.in_gre_pkt)
if (pinfo->flags.in_gre_pkt && prefs.strict_conversation_tracking_heuristics)
conv_key[0] |= 0x00010000; /* set a bit for "in GRE" */
trans = transaction_start(pinfo, icmp6_tree, conv_key);
} else { /* ICMP6_ECHO_REPLY */
@ -4024,7 +4038,7 @@ dissect_icmpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
conv_key[0] = in_cksum(cksum_vec, 1);
if (conv_key[0] == 0)
conv_key[0] = 0xffff;
if (pinfo->flags.in_gre_pkt)
if (pinfo->flags.in_gre_pkt && prefs.strict_conversation_tracking_heuristics)
conv_key[0] |= 0x00010000; /* set a bit for "in GRE" */
trans = transaction_end(pinfo, icmp6_tree, conv_key);
}

View File

@ -3595,6 +3595,12 @@ prefs_register_modules(void)
"Look for dissectors that left some bytes undecoded.",
&prefs.enable_incomplete_dissectors_check);
prefs_register_bool_preference(protocols_module, "strict_conversation_tracking_heuristics",
"Enable stricter conversation tracking heuristics",
"Protocols may use things like VLAN ID or interface ID to narrow the potential for duplicate conversations."
"Currently only ICMP and ICMPv6 use this preference to add VLAN ID to conversation tracking",
&prefs.strict_conversation_tracking_heuristics);
/* Obsolete preferences
* These "modules" were reorganized/renamed to correspond to their GUI
* configuration screen within the preferences dialog

View File

@ -221,6 +221,7 @@ typedef struct _e_prefs {
gboolean display_byte_fields_with_spaces;
gboolean enable_incomplete_dissectors_check;
gboolean incomplete_dissectors_check_debug;
gboolean strict_conversation_tracking_heuristics;
gboolean gui_update_enabled;
software_update_channel_e gui_update_channel;
gint gui_update_interval;