Wireshark-dev: Re: [Wireshark-dev] Dissect multiple PDUs in one TCP Segment

From: Guy Harris <guy@xxxxxxxxxxxx>
Date: Wed, 23 May 2007 10:45:07 -0700
Robert Naumann wrote:

i'm new to the dissector developement for wireshark. I've read that it should be actually possible to dissect multiple PDUs from one TCP Segment with tcp_dissect_pdus(), but i don't get it working.
For example: i've got 2 different PDUs with different lengths (5 and 6). 
I already got the pdu lengths. The Length of the TCP Datasegment is 11.
So for the first PDU the function:

tcp_dissect_pdus(tvb, pinfo, tree, TRUE, min_pdu_size, *first_pdu_size*, dissect_pdu_sc);
tcp_dissect_pdus() isn't called for every PDU; it's called *once* in the 
dissector for your protocol, and the argument you mark as "first pdu 
size" is a function that gets the PDU size of a PDU.
"min_pdu_size" should be the minimum amount of packet data needed to 
calculate the PDU size.  For example, if every PDU starts with a 2-byte 
PDU type and a 2-byte PDU length, in that order, "min_pdu_size" should 
be 4, to include the PDU length.  If the length comes *before* the type, 
it'd be 2.
If the value of the length field in the PDU includes the lengths of the 
type and length fields, and the fields are in big-endian order, then:
In the case where there's a type and length, in that order, the function 
to get the PDU size would be
	static gint
	get_sc_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
	{
		return tvb_get_ntohs(tvb, offset + 2);
	}

and in the case where the length comes before the type, it'd be

	static gint
	get_sc_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
	{
		return tvb_get_ntohs(tvb, offset);
	}

Replace "tvb_get_ntohs()" with "tvb_get_letohs()" if the fields are in little-endian order.
If the value of the length field in the PDU *doesn't* include the 
lengths of the type and length field, you'd add 4 to the length field in 
the first of those functions and add 2 to the length field in the second 
of those functions.
so the first PDU with the correct size (proved) should be passed to the dissector function dissect_pdu_sc.
My first problem:   
=============
At the dissection of my top level protocol the PDU is marked as 
[Malformed Packet], why? Size is correct! bitstream show the complete 
data of my PDU
So your function is returning the value 5 for the first PDU?

Is your dissector trying to dissect more than 5 bytes in the PDU? If so, it's acting as if the packet should be longer than 5 bytes long, and thus a 5-byte-long packet would be malformed. An attempt to fetch data past the end of the 5-byte tvbuff your dissector is handed will cause an exception to be thrown and your packet marked as malformed.
My second problem: =============== The second PDU within the the TCP Segment wont be dissected and not shown as a part of my top level protocol. Is the second PDU automatically processed
Yes.

or do i have to call the function tcp_dissect_pdus() again?
No.  It's called "tcp_dissect_pdus()", plural, not "tcp_dissect_pdu()", 
singular, because it's supposed to be handed all the data that's passed 
to the disector and dissects all the PDUs in that data.