follow: Only retrieve matching conversations

The TCP and UDP follow conversation filter functions should
only retrieve a conversation and conversation data, not
create new conversations or new stream numbers. (That should
only happen during actual packet processing.) So they should
match on the endpoint type and not look up endpoints (since
TCP and UDP don't use the endpoint API.)

They still don't work with tunneling, or any other situation where
the addresses and ports have been changed (see #18231), but this
at least works when some other protocol _has_ used the endpoint
API, and also avoids creating nonsensical streams.

Making them work properly with tunneling either requires adding
packet info to each packet with the stream information, or using
the endpoint API (after finishing it to allow more than one endpoint
on the packet, and a way of searching for endpoints other than
the most recent.)
This commit is contained in:
John Thacker 2022-07-31 15:29:57 -04:00 committed by A Wireshark GitLab Utility
parent 210a891fb7
commit 66b26d7251
5 changed files with 44 additions and 10 deletions

View File

@ -549,9 +549,16 @@ static gchar *dccp_follow_conv_filter(epan_dissect_t *edt _U_, packet_info *pinf
conversation_t *conv;
struct dccp_analysis *dccpd;
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 )
/* 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, ENDPOINT_DCCP, pinfo->srcport, pinfo->destport, 0)) != NULL)
{
/* DCCP over IPv4/6 */
dccpd = get_dccp_conversation_data(conv, pinfo);

View File

@ -2347,10 +2347,18 @@ http2_follow_conv_filter(epan_dissect_t *edt _U_, packet_info *pinfo, guint *str
{
http2_session_t *h2session;
struct tcp_analysis *tcpd;
conversation_t* conversation = find_or_create_conversation(pinfo);
conversation_t* conversation;
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)))
/* XXX: Since TCP doesn't use the endpoint API (and HTTP2 is
* over TCP), we can only look up using the current pinfo addresses
* and ports. We don't want to create a new conversion or stream.
* Eventually the endpoint API should support storing multiple
* endpoints and TCP 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_TCP) &&
(conversation=find_conversation(pinfo->num, &pinfo->net_src, &pinfo->net_dst, ENDPOINT_TCP, pinfo->srcport, pinfo->destport, 0)) != NULL)
{
h2session = get_http2_session(pinfo, conversation);
tcpd = get_tcp_conversation_data(conversation, pinfo);

View File

@ -1008,9 +1008,16 @@ gchar *tcp_follow_conv_filter(epan_dissect_t *edt _U_, packet_info *pinfo, guint
conversation_t *conv;
struct tcp_analysis *tcpd;
/* XXX: Since TCP 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 new TCP stream.
* Eventually the endpoint API should support storing multiple
* endpoints and TCP 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))
&& (conv=find_conversation_pinfo(pinfo, 0)) != NULL )
&& (pinfo->ptype == PT_TCP) &&
(conv=find_conversation(pinfo->num, &pinfo->net_src, &pinfo->net_dst, ENDPOINT_TCP, pinfo->srcport, pinfo->destport, 0)) != NULL)
{
/* TCP over IPv4/6 */
tcpd=get_tcp_conversation_data(conv, pinfo);

View File

@ -379,9 +379,17 @@ static gchar *udp_follow_conv_filter(epan_dissect_t *edt _U_, packet_info *pinfo
conversation_t *conv;
struct udp_analysis *udpd;
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 ) {
/* XXX: Since UDP 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 new UDP stream.
* Eventually the endpoint API should support storing multiple
* endpoints and UDP 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_UDP) &&
(conv=find_conversation(pinfo->num, &pinfo->net_src, &pinfo->net_dst, ENDPOINT_UDP, pinfo->srcport, pinfo->destport, 0)) != NULL)
{
/* UDP over IPv4/6 */
udpd=get_udp_conversation_data(conv, pinfo);
if (udpd == NULL)

View File

@ -992,6 +992,10 @@ bool FollowStreamDialog::follow(QString previous_filter, bool use_stream_index,
tr("Error creating filter for this stream."),
tr("QUIC streams not found on the selected packet."));
} else {
// XXX: This error probably has to do with tunneling, where
// the addresses or ports changed after the TCP or UDP layer.
// (The appropriate layer must be present, or else the GUI
// doesn't allow the option to be selected.)
QMessageBox::warning(this,
tr("Error creating filter for this stream."),
tr("A transport or network layer header is needed."));