forked from osmocom/wireshark
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>
This commit is contained in:
parent
9ff64c8d7c
commit
d16308c89a
|
@ -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;
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -224,7 +224,7 @@ WS_DLL_PUBLIC guint32 conversation_get_endpoint_by_id(struct _packet_info *pinfo
|
|||
extern 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);
|
||||
|
||||
extern gboolean
|
||||
try_conversation_dissector_by_id(const endpoint_type etype, const guint32 id, tvbuff_t *tvb,
|
||||
|
|
|
@ -859,7 +859,7 @@ dissect_atp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
|
|||
conversation_set_dissector(conversation, sub);
|
||||
}
|
||||
else if (!try_conversation_dissector(&pinfo->src, &pinfo->dst, conversation_pt_to_endpoint_type(pinfo->ptype),
|
||||
pinfo->srcport, pinfo->destport, new_tvb,pinfo, tree, &aspinfo)) {
|
||||
pinfo->srcport, pinfo->destport, new_tvb,pinfo, tree, &aspinfo, 0)) {
|
||||
call_data_dissector(new_tvb, pinfo, tree);
|
||||
|
||||
}
|
||||
|
|
|
@ -250,7 +250,7 @@ decode_dccp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
|||
* for the conversation if available
|
||||
*/
|
||||
if (try_conversation_dissector(&pinfo->src, &pinfo->dst, ENDPOINT_DCCP, sport,
|
||||
dport, next_tvb, pinfo, tree, NULL)) {
|
||||
dport, next_tvb, pinfo, tree, NULL, 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ static void dissect_payload(tvbuff_t *next_tvb, packet_info *pinfo, proto_tree *
|
|||
|
||||
/* Trying a dissector assigned to the conversation (Usually from NBAP) */
|
||||
conv_dissected = try_conversation_dissector(&pinfo->dst, &pinfo->src, ENDPOINT_UDP,
|
||||
pinfo->destport, pinfo->srcport, next_tvb, pinfo, tree, NULL);
|
||||
pinfo->destport, pinfo->srcport, next_tvb, pinfo, tree, NULL, 0);
|
||||
if (!conv_dissected) {
|
||||
/* No conversation dissector / TVB was rejected, try other options */
|
||||
if(call_fp_heur) {
|
||||
|
|
|
@ -5503,7 +5503,7 @@ decode_tcp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
|||
/* for the conversation if available */
|
||||
|
||||
if (try_conversation_dissector(&pinfo->src, &pinfo->dst, ENDPOINT_TCP,
|
||||
src_port, dst_port, next_tvb, pinfo, tree, tcpinfo)) {
|
||||
src_port, dst_port, next_tvb, pinfo, tree, tcpinfo, 0)) {
|
||||
pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
|
||||
handle_export_pdu_conversation(pinfo, next_tvb, src_port, dst_port, tcpinfo);
|
||||
return TRUE;
|
||||
|
|
|
@ -632,7 +632,7 @@ decode_udp_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->dst, &pinfo->src, ENDPOINT_UDP,
|
||||
uh_dport, uh_sport, next_tvb, pinfo, tree, NULL)) {
|
||||
uh_dport, uh_sport, next_tvb, pinfo, tree, NULL, NO_ADDR_B|NO_PORT_B)) {
|
||||
handle_export_pdu_conversation(pinfo, next_tvb, uh_dport, uh_sport);
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue