Wireshark-dev: Re: [Wireshark-dev] Is there a good way of handling "per pdu" info ?
From: "Bryant Eastham" <[email protected]>
Date: Tue, 13 Nov 2007 09:07:19 -0700
Richard van der Hoff wrote:
>Stephen Fisher wrote:
>> On Mon, Nov 12, 2007 at 06:05:38PM -0000, Neil Piercy wrote:
>> 
>> 
>>>I know there is per-packet info, but is there a way of
>>>adding/retrieving per PDU info which copes with multiple PDUs in a
>>>packet ? How does a dissector even know if it is handfling the first,
>>>second etc PDU in a packet ?
>> 
>> 
>> This has been requested before, but has not been implemented to date
in
>> Wireshark.  A workaround you can use is to use a linked list from
GLib
>> (which has a nice easy interface to them) and store that in the per
>> packet info.  Each item in your list would correspond to a different
>> PDU.
>
>But, as Neil asked, how would you know which PDU you were
>handling in the dissector?
>
>> One of us should get around to implementing per-pdu packet info in
>> Wireshark itself.  It wouldn't be too difficult.  All we need is
spare
>> time :)
>
>Hrm; it gets quite a lot harder when your PDUs can
>themselves span 
>multiple packets (ie, there is no correspondence between PDUs and 
>packets). See H.223 for details...

I do not consider myself an expert by any means, but here is what I
ended up doing.

The easy part is the data structures; however I stayed away from lists.
Wireshark does a great job of giving you the right structures for the
task (check se_tree_create_non_persistent and se_tree_lookup32). My
particular PDU state involves encryption state. I create appropriate
conversations and put my PDU structures in them.

The hard part (for me) was determining the right key for the PDU. This
is IMHO where Wireshark falls a little short. In order for the data
structures to be of use the key must be unique to the PDU in the context
of the conversation. Assuming that you need lookups not just during the
initial pass but also when packets are selected, the things you have
available are rather limited. You must use things that don't depend on
order and are always available. Also, never forget about TCP
retransmissions (yes, everyone should test with captures over
large-latency links!).

In the TCP case I use a combination of the sequence and the offset. The
offset is TVB_RAW_OFFSET(tvb). Assuming that you call this on the tvb
that represents your PDU you should always get the same number - however
it is not unique to the session, only the tvb. To make it unique I add
the seq field of the tcpinfo structure. The structure pointer is present
in the pinfo->private_data for tcp dissectors, so I stash the seq value
in the conversation before I call tcp_dissect_pdus. Using this number is
almost required if (as in my case) you really want your data associated
with the logical PDU and not each transmitted instance of the PDU. The
seq field plus the offset should remain constant even in the case of
retransmissions (at least that is my understanding - experts may know
otherwise).

Unfortunately I do not have a good solution for UDP or other
connectionless cases. In my case each UDP packet was self describing, so
I didn't need to solve the problem. My protocol doesn't allow multiple
PDUs per UDP packet either. In general it seems that there is no
guarantee of shared state in these cases, so the need for per PDU
information may be lessened. I suppose you could still use
TVB_RAW_OFFSET to determine each individual PDU in a packet, but you
would need to handle retransmission logic in your dissector since the
transport doesn't do it.

As to your question of determining which PDU sequence you are looking
at, that would be stored in your per PDU data and initialized during the
first pass when all of the data structures are set up. Each packet you
handle would reset the count, each PDU you parse would increase it and
store it in your PDU data.

Hope this was helpful...

By the way, if experts find holes in my approach I would love to know!

Bryant Eastham