Huge thanks to our Platinum Members Endace and LiveAction,
and our Silver Member Veeam, for supporting the Wireshark Foundation and project.

Wireshark-dev: Re: [Wireshark-dev] Malformed packet New dissector

From: Guy Harris <guy@xxxxxxxxxxxx>
Date: Fri, 16 Feb 2007 13:57:29 -0800

On Feb 16, 2007, at 7:06 AM, your highness wrote:

Hi everyone,

I managed to write a dissector for a new protocol (Condor) and it
works most of the time ; ) ... Thanks to Jaap Keuter and the README
files. I am starting a new thread for a new problem.

The problem is that I get errors for packets that are spread over
multiple TCP packets.

Condor runs on top of TCP. In the header of each condor packet the
length of the whole packet is given by a 3-octets field, thus as
suggested in the README.developer I used tcp_dissect_pdus() for
reassembling condor packets that span across more than one TCP
packets.

It also handles multiple packets in *one* TCP segment.

The skeleton of my code that is relevant to this issue is as follows:

static guint
get_condor_pdu_len(tvbuff_t *tvb, int offset)
{
// total packet length in 2nd, 3rd and 4th octets of a Condor packet
return tvb_get_ntoh24(tvb, offset+1);
}

So it's a 3-octet field at an offset of 1 octet into the packet, so you have to have at least 4 bytes of the packet in order to get the length field?

If so, then:

static void
dissect_condor_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
tcp_dissect_pdus(tvb, pinfo, tree, condor_desegment, 3, get_condor_pdu_len,
   dissect_condor_tcp_pdu);
}

...that should be

tcp_dissect_pdus(tvb, pinfo, tree, condor_desegment, 4, get_condor_pdu_len,
	   dissect_condor_tcp_pdu);

as you need the first *4* bytes of the packet in order to get the packet length.

I first got the error message [Packet size limited during capture]
when I sent a number of packets together (the length of the packets
together was more than 1024 bytes).

"Packet size limited during capture" usually means that the capture was done with a "snapshot length" shorter than the maximum packet length. tcpdump, by default, has a "snapshot length" of 68 or 96.

However, there are some cases where that error is incorrectly given for malformed or un-reassembled packets.

But must be caused by the
segmentation by the Data Link Layer.

Probably not.

Most data link layers either don't do segmentation (e.g., Ethernet and PPP), or do the reassembly on the adapter or in the adapter driver, so that the host doesn't see the segments (802.11, ATM AAL5).

Some Wireshark dissectors for data link layers that do fragmentation also support data link layer reassembly, for cases where the capture doesn't have reassembled packets (because, for example, the adapter was told not to do reassembly, or because the capture mechanism is supplied with raw packets rather than reassembled packets if the driver's doing reassembly); the 802.11 dissector can do that. We don't have that for ATM.

However, data link layers also have a maximum packet size that they'll *accept* from a higher layer - they might internally fragment, at the data link layer, packets at or below that maximum packet size, or they might not (Ethernet, for example, doesn't). This means that if a higher-layer protocol needs to send a packet larger than that, segmentation needs to be done at *that* layer.

That segmentation isn't done by the data link layer, even though it's caused by a limitation of the data link layer. It might be done at the network layer (IP or CLNP fragmentation, for example), or it might be done at the transport layer (TCP breaking the data stream into TCP segments, COTP breaking a COTP PDU into segments).

If, for example, you send a 16K Condor packet, that won't fit into most link-layer packets. The segmentation for that is done at the TCP layer, *not* by the data link layer.

Using tcp_dissect_pdus() solved
this problem. I don't understand how this happens because I supposed
that when a protocol runs on top of TCP, the tcp dissector itself
would take care of reassembly of the Data Link Layer packets. Is my
reasoning correct?

No.

When a protocol runs on top of TCP, the TCP implementation on the machine receiving packets will not reassemble all the data for a packet for that protocol and only hand a reassembled packet to the implementation of that higher-level protocol. That's because TCP has no idea when a packet for that protocol starts or ends; the service TCP provides to protocols running on top of it is a stream of bytes, with *NO* packet boundaries.

That's why Condor - and many other protocols running on top of TCP - need to put a length at the beginning of their packets. That way, the implementation of that protocol on the receiving side knows how big the packet is, and keeps reading from TCP until it has all the bytes of that packet.

The TCP dissector in Wireshark has the same problem, so it has to be told by the dissector for the protocol how big the packet is. That can be done by hand, but tcp_dissect_pdus() can do it for you in many cases.


So the problem that I get now appears when I send more than 8192 bytes
(8K). In that case some Condor packets will span accross different TCP
packets, right?

If you're running atop Ethernet, the number is more like 1460 bytes, assuming IPv4 with no options and TCP with no options (1514 bytes of Ethernet header plus data = 14 bytes of header + 1500 bytes of data; 1500 bytes of IPv4 header with no options + data = 20 bytes of IPv4 header with no options plus 1480 bytes of data; 1480 bytes of TCP header with no options + data = 20 bytes of TCP header with no options plus 1460 bytes of data).

Unless you're dealing with a link layer that handles packets with 8232 bytes of data (8192 bytes of TCP payload + 20 bytes of TCP header + 20 bytes of IP header; that 8232 does *NOT* count the link-layer header, so it's 8232 + link-layer header size), or whatever the appropriate value would be for IPv6 (or with IP or TCP options), you're going to see segmentation before you get to 8192-byte packets.

Only condor packets in the first TCP packet are
recognized as valid. The other ones are tagged "Malfored packet".

I am using netcat to send files that contain Condor packets for my
tests. Attached is a captured file that contains condor packets of 42
bytes. The first packet that is tagged Malformed has 2 bytes in the
first TCP packets (0x20 and 0x00) and 40 bytes in the second TCP
packet.

I'll take a look at that later.