diff options
author | Robert Jongbloed <robertj@voxlucida.com.au> | 2018-01-23 10:48:57 +0000 |
---|---|---|
committer | Michael Mann <mmann78@netscape.net> | 2018-02-10 20:51:55 +0000 |
commit | d16308c89a4399897874ea660267f0c6303872dc (patch) | |
tree | dae0b2a12cf3045e40ed04fda2c5643c2a9b909a /epan/conversation.c | |
parent | 9ff64c8d7c43cc7c819e0fdce4476b606e1cb28b (diff) |
UDP: Heuristic dissector for conversation taking precedence
When a single UDP port is supporting multiple protocols, for example RTP and
RTCP can share a port, and one of these protocols is detected through a
heuristic before a superior protocol (e.g. SIP/SDP) has established that the
port has multiple protocols, then only the heuristic is used. This is due to
only looking for an exact match with find_conversation() and not going any
further. The superior protocol only adds the dissector by source address/port.
So, to fix, if we do not find the exact match, we continue serching for a
dissector on the partial matches.
Bug: 14370
Change-Id: Icdded9ca1637cd594b920f979f6f0a003bef9aae
Reviewed-on: https://code.wireshark.org/review/25432
Petri-Dish: Michael Mann <mmann78@netscape.net>
Tested-by: Petri Dish Buildbot
Reviewed-by: Michael Mann <mmann78@netscape.net>
Diffstat (limited to 'epan/conversation.c')
-rw-r--r-- | epan/conversation.c | 62 |
1 files changed, 47 insertions, 15 deletions
diff --git a/epan/conversation.c b/epan/conversation.c index af49a4a8c7..817bb06c87 100644 --- a/epan/conversation.c +++ b/epan/conversation.c @@ -1233,6 +1233,23 @@ conversation_get_dissector(conversation_t *conversation, const guint32 frame_num return (dissector_handle_t)wmem_tree_lookup32_le(conversation->dissector_tree, frame_num); } +static gboolean try_conversation_call_dissector_helper(conversation_t *conversation, gboolean* dissector_success, + tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) +{ + int ret; + dissector_handle_t handle = (dissector_handle_t)wmem_tree_lookup32_le( + conversation->dissector_tree, pinfo->num); + if (handle == NULL) + return FALSE; + + ret = call_dissector_only(handle, tvb, pinfo, tree, data); + + /* Let the caller decide what to do with success or rejection */ + (*dissector_success) = (ret != 0); + + return TRUE; +} + /* * Given two address/port pairs for a packet, search for a matching * conversation and, if found and it has a conversation dissector, @@ -1246,28 +1263,43 @@ conversation_get_dissector(conversation_t *conversation, const guint32 frame_num gboolean try_conversation_dissector(const address *addr_a, const address *addr_b, const endpoint_type etype, const guint32 port_a, const guint32 port_b, tvbuff_t *tvb, packet_info *pinfo, - proto_tree *tree, void* data) + proto_tree *tree, void* data, const guint options) { conversation_t *conversation; + gboolean dissector_success; - conversation = find_conversation(pinfo->num, addr_a, addr_b, etype, port_a, - port_b, 0); + /* Try each mode based on option flags */ + conversation = find_conversation(pinfo->num, addr_a, addr_b, etype, port_a, port_b, 0); if (conversation != NULL) { - int ret; - dissector_handle_t handle = (dissector_handle_t)wmem_tree_lookup32_le(conversation->dissector_tree, pinfo->num); - if (handle == NULL) - return FALSE; - ret=call_dissector_only(handle, tvb, pinfo, tree, data); - if(!ret) { - /* this packet was rejected by the dissector - * so return FALSE in case our caller wants - * to do some cleaning up. - */ - return FALSE; + if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data)) + return dissector_success; + } + + if (options & NO_ADDR_B) { + conversation = find_conversation(pinfo->num, addr_a, addr_b, etype, port_a, port_b, NO_ADDR_B); + if (conversation != NULL) { + if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data)) + return dissector_success; } - return TRUE; } + + if (options & NO_PORT_B) { + conversation = find_conversation(pinfo->num, addr_a, addr_b, etype, port_a, port_b, NO_PORT_B); + if (conversation != NULL) { + if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data)) + return dissector_success; + } + } + + if (options & (NO_ADDR_B|NO_PORT_B)) { + conversation = find_conversation(pinfo->num, addr_a, addr_b, etype, port_a, port_b, NO_ADDR_B|NO_PORT_B); + if (conversation != NULL) { + if (try_conversation_call_dissector_helper(conversation, &dissector_success, tvb, pinfo, tree, data)) + return dissector_success; + } + } + return FALSE; } |