From 4cb8f0fd085e6d2b96420b9f10e45efb208508cd Mon Sep 17 00:00:00 2001
From: John Thacker <johnthacker@gmail.com>
Date: Mon, 20 Apr 2026 07:40:34 -0400
Subject: [PATCH] conversation: Don't use X.25 conversation after dissecting IP
 on X.25

The conversation API has several functions that find "the conversation"
for a frame using what is currently in the packet_info struct. This is
often used by dissectors that did not create that conversation, in order
to, e.g., have the TCP dissector call a particular subdissector after
heuristics succeed.

Most of the time, the current source and destination addresses, and
ports if set, are used to find this conversation. Conversations using
this are generally bidirectional, and there's special support for
wildcarding.[1]

There are some dissectors whose idea of a conversation does not fit
into this scheme, and which use "exact" conversation matching. Some
of these, such as with circuit-based protocols, also need to set the
default conversation so that subdissectors find their conversation
instead of the port-and-address based one.[2]

X.25 is such a dissector. It has a heuristic subdissector list,
because X.25 over TCP (TOP) exists, X.25 needs to set its circuit
conversation to be the one retrieved by its heuristic subdissectors
so that they can set themselves to its converstation, and not the
underlying TCP conversation that carries X.25.

A complication with X.25 is that X.25 can itself carry IP, and it is
thus possible to have IP over X.25 over TCP over IP. (See #2341.)[3]
In such cases, for the same reason as members of the X.25 heuristic
subdissector list want to retrieve the X.25 conversation and not
the addresses-and-ports conversation, members of heuristic subdissector
lists over IP[4] want to find the addresses-and-ports conversation,
not the conversation element based X.25 conversation, so as to set
themselves to the proper conversation and not mess up dissection by
attempting to skip layers.

The conv_elements added to pinfo are allocated via pinfo->pool, so
as a workaround we can simply set them to NULL once dissecting IP.
This fixes #21185 at least temporarily, although it is not the ideal
long term solution.[5]

1 - There are additional conversations with the recently introduced
"deinterlacing" conversation functions.

2 - There's also another category of dissectors that have address-and-ports
used for conversations that for some reason do not want to set the source
and destination port of the frame itself. Most of these are proxy protocols.
They are not further discussed here, but present their own issues. For
now, note that once those are set, they prevent the conversation
elements based converssation from being found as well.

3 - This includes IPv6, see https://www.iana.org/assignments/nlpids/nlpids.xhtml

4 - Including those in further protocol layers often found over IP, such as
the TCP, UDP, or SCTP heuristic subdissector lists.

5 - This ideal long term solution has been pending circa a decade.
Cf. 800b26edbe34e135cc9be1d4395db2c13ae1213f

AI-Assisted: no


(cherry picked from commit f361a7c8f9f9b3133f5ce72009c79b239831cc2d)

Co-authored-by: John Thacker <johnthacker@gmail.com>
---
 epan/dissectors/packet-ip.c   | 6 ++++++
 epan/dissectors/packet-ipv6.c | 3 +++
 2 files changed, 9 insertions(+)

Index: wireshark-3.6.24/epan/dissectors/packet-ip.c
===================================================================
--- wireshark-3.6.24.orig/epan/dissectors/packet-ip.c
+++ wireshark-3.6.24/epan/dissectors/packet-ip.c
@@ -2139,6 +2139,12 @@ dissect_ip_v4(tvbuff_t *tvb, packet_info
   copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
   copy_address_shallow(&iph->ip_dst, &pinfo->net_dst);
 
+  /* XXX - We do not want pinfo->conv_elements, if set, to be used to find the
+   * default conversation after this, or else subdissectors will set the
+   * wrong dissector. This is a bit of a hack, it should be solved more
+   * generally. */
+  pinfo->conv_endpoint = NULL;
+
   /* If an IP is destined for an IP address in the Local Network Control Block
    * (e.g. 224.0.0.0/24), the packet should never be routed and the TTL would
    * be expected to be 1.  (see RFC 3171)  Flag a TTL greater than 1.
Index: wireshark-3.6.24/epan/dissectors/packet-ipv6.c
===================================================================
--- wireshark-3.6.24.orig/epan/dissectors/packet-ipv6.c
+++ wireshark-3.6.24/epan/dissectors/packet-ipv6.c
@@ -2470,6 +2470,9 @@ dissect_ipv6(tvbuff_t *tvb, packet_info
     alloc_address_wmem_ipv6(pinfo->pool, &pinfo->net_dst, ip6_dst);
     copy_address_shallow(&pinfo->dst, &pinfo->net_dst);
 
+    /* XXX - See comment in the IPv4 disector. */
+    pinfo->conv_endpoint = NULL;
+
     if (tree) {
         if (ipv6_summary_in_tree) {
             proto_item_append_text(ipv6_item, ", Src: %s, Dst: %s",
