aboutsummaryrefslogtreecommitdiffstats
path: root/epan/conversation.c
diff options
context:
space:
mode:
authorRobert Jongbloed <robertj@voxlucida.com.au>2018-01-23 10:48:57 +0000
committerMichael Mann <mmann78@netscape.net>2018-02-10 20:51:55 +0000
commitd16308c89a4399897874ea660267f0c6303872dc (patch)
treedae0b2a12cf3045e40ed04fda2c5643c2a9b909a /epan/conversation.c
parent9ff64c8d7c43cc7c819e0fdce4476b606e1cb28b (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.c62
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;
}