Wireshark-dev: Re: [Wireshark-dev] Packets within packets within packets...
From: Guy Harris <guy@xxxxxxxxxxxx>
Date: Fri, 13 Jul 2007 14:01:09 -0700

On Jul 13, 2007, at 1:09 PM, Jon Andersen wrote:

I'm working on a protocol dissector for several layered protocols on top of TCP and have a general dissection issue for which I'd like some advice or wizardry.

I have a packeted connection protocol on top of TCP, which itself contains packets of another protocol:
TCP
P1
P2

The issue is that the packets of P2 may be split up into multiple packets of P1, and P1 may be split up into multiple packets by TCP. This makes the reassembly and dissection tricky (-;

tcp_dissect_pdus() works beautifully for handling fragmented P1 packets. However, it doesn't help with the recursive problem of P2 packets being fragmented.

It's not supposed to. The information about the fragmentation of P2 packets into multiple P1 packets is either known to the P1 dissector (see, for example, IP fragmentation) or the P2 dissector.

Thus, either the P1 dissector should be handling the reassembly, or the P2 dissector should be handling the reassembly, possibly with the help of the P1 dissector.

There's no master general reassembly mechanism in Wireshark, because there's no single scheme used by all protocols for fragmentation. There are helper routines in epan/reassemble.c for dissectors to use, and the reassembly code in a particular dissector might consist only of a few calls to those helper routines, which do the vast majority of the work - but different dissectors need to call different routines, as their protocols do fragmentation differently.

tcp_dissect_pdus() is only a small part of the TCP reassembly mechanism; it's just a wrapper for certain types of protocols, but other protocols, such as HTTP, do the reassembly differently, as HTTP requests and responses don't have a message length in a header near the beginning of the message (the HTTP header is terminated by a blank line, so you have to keep grabbing data until you find the blank line; the HTTP body might have its length specified by the Content-Length field of the header, or it might run until the connection closes).

The TCP reassembly mechanism is, by design and intent designed to handle only the reassembly of messages that cross TCP segment boundaries. It involves both the TCP dissector and the dissector above it, as the service TCP provides is a byte stream, with no message boundaries, so only the dissector above TCP knows what the message boundaries are. tcp_dissect_pdus() is a wrapper that

	1) handles multiple messages in a single segment

and

2) handles the details of telling the TCP dissector that more data is needed for messages that cross segment boundaries.

Burdening the TCP reassembly mechanism with handling reassembly for other protocols would complicate that code - and it's already complicated, and has some known bugs that need to be fixed.

Think about what happens when a P2 packet is split across two P1 packets, and each of the P1 packets is encapsulated in a different TCP packet.

Think about what happens when a TDS packet is split across multiple NETLIB packets. See packet-tds.c for an example of a set of protocols that work the way your P1 and P2 protocols work.

What is needed is a fancier or more general implementation of tcp_dissect_pdus, updated to handle new-style dissectors.

No, what is needed is dissectors for P1 and P2 that do the reassembly of P2 packets fragmented over multiple P1 packets. Again, see packet- tds.c.