Wireshark-dev: Re: [Wireshark-dev] Updating COL_INFO column during packet dissection

From: Evan Huus <eapache@xxxxxxxxx>
Date: Thu, 24 Oct 2013 10:54:30 -0400
On Thu, Oct 24, 2013 at 10:00 AM, David Bilsby <dbilsby@xxxxxxxxxxxxxx> wrote:
> Hi
>     Apologies in advance if this is not the correct place to post this but I
> originally tried ask.wireshark.org and was pointed here instead.

This is the correct place for this kind of question, welcome!

>     I am writing a custom protocol dissector plugin for our protocol layered
> on top of UDP. From the protocol header I can determine various packet
> attributes which allows me to group the packets into conversations of
> related data and ack packets.
>
>     As part of the protocol header I have a source channel ID which I
> extract and store in the conversation. Unfortunately there is no destination
> channel ID in the packet so I have to infer this when the ACK packet is
> returned. That seemed to work fine as I then stash this away in the
> conversation. I then use these channel IDs to set a string in the COL_INFO
> column, for example "data packet channel 3 > 7", or "ACK packet channel 7 >
> 3".
>
>     This seemed to work OK but then sometimes I would notice that the first
> packet would have my undefined channel init value set, -1, but subsequent
> packets would be fine. This did not happen ever time however.
>
>     From comments on the ask.wireshark.org list I now realise that the
> COL_INFO column is only settable on one call to the dissector, so code which
> I assumed was rewriting the COL_INFO column to put the correct destination
> channel ID in was never actually doing anything because the cinfo structure
> pointer was NULL. However as I said the wrong COL_INFO did not happen every
> time. It never seemed to happen on dissecting captures stored to file and
> only sometimes on live captures.
>
>     I added some debug to my dissector in my set_info_column_summary()
> function which I call on every packet after the update_conversation_data()
> function. This latter function is the one which determines the src and dst
> channel IDs from my packets, each packet only containing the src channel ID,
> therefore to get the full src/dst pair the conversation update function must
> have seen the first and second (ACK) packet in each conversation. This
> src/dst pair is used to set the channel IDs in the COL_INFO column.
>
>     pkt 5 is the start of a new conversation. From its packet I can
> determine the src chan as 4, dst chan is unknown -1. Interestingly cinfo
> pointer is NULL. pkt 6 is the ACK reply which gives us the dst chan ID of 0,
> again the cinfo field is NULL. pkt 5 and 6 then get dissected again with a
> valid cinfo and by now I know both src and dst channel IDs so the Info field
> gets set correctly so the COL_INFO text is correct. pkts 7-9 then get
> processed all with cinfo NULL the first time, then again with valid cinfo.
>
> Pkt 5: new conversation
> Pkt 5: Src chan = 4, dst chan = -1, cinfo = 0x00000000
> Pkt 6: Src chan = 4, dst chan = 0, cinfo = 0x00000000
> Pkt 5: Src chan = 4, dst chan = 0, cinfo = 0x3f9f9138
> Pkt 6: Src chan = 4, dst chan = 0, cinfo = 0x3f9f9138
> Pkt 7: Src chan = 4, dst chan = 0, cinfo = 0x00000000
> Pkt 8: Src chan = 4, dst chan = 0, cinfo = 0x00000000
> Pkt 9: Src chan = 4, dst chan = 0, cinfo = 0x00000000
> Pkt 7: Src chan = 4, dst chan = 0, cinfo = 0x3f9f9138
> Pkt 8: Src chan = 4, dst chan = 0, cinfo = 0x3f9f9138
> Pkt 9: Src chan = 4, dst chan = 0, cinfo = 0x3f9f9138
>
>     When it does not work I get packet debug as below. Here pkt 27 is the
> first packet in a conversation and gets dissected first without cinfo set,
> then again with cinfo set but before I have seen pkt 28 which defines the
> destination channel. Hence this time the COL_INFO text is wrong.
>
> Pkt 27: new conversation
> Pkt 27: Src chan = 4, dst chan = -1, cinfo = 0x00000000
> Pkt 27: Src chan = 4, dst chan = -1, cinfo = 0x3f9f9138
> Pkt 28: Src chan = 4, dst chan = 0, cinfo = 0x00000000
> Pkt 29: Src chan = 4, dst chan = 0, cinfo = 0x00000000
> Pkt 30: Src chan = 4, dst chan = 0, cinfo = 0x00000000
> Pkt 28: Src chan = 4, dst chan = 0, cinfo = 0x3f9f9138
> Pkt 29: Src chan = 4, dst chan = 0, cinfo = 0x3f9f9138
> Pkt 30: Src chan = 4, dst chan = 0, cinfo = 0x3f9f9138
>
>     Is this variation in the order in which the packets are dissected
> expected?

More-or-less. Each packet is dissected once (with, I believe, NULL
tree and NULL cinfo) as it is loaded or captured. All other
dissections are triggered as callbacks from the GUI based on which
packets are visible. Selecting a packet will trigger a dissection with
a non-NULL tree (in order to display the complete dissection tree).
Scrolling the summary list will (should?) trigger dissections with
non-NULL cinfo in order to display the column info, unless that's
being cached somewhere.

It probably also depends on whether this is the GTK or QT-based
interface you're using, since they may behave slightly differently in
this regard.

The text-based "tshark" is simpler at least - normally it will only
dissect each packet exactly once, in order, so you will never be able
to see "future" information like destination channel. You can pass it
the -2 flag however (when reading an existing capture file) and it
will run the entire file twice so all your information should appear
correctly.

>     As it is not possible to rely on a subsequent packet having been
> dissected and therefore set data in a conversation would I be right is
> thinking that the COL_INFO column should be limited to just data decoded
> from the current packet being dissected?

There are certainly cases (like single-pass tshark) where COL_INFO is
limited to "present and past" data and no future data, so it has to be
coherent in that case. However, it *should* always display future data
when loading captures from a file into the GUI. When doing live
captures in the GUI, I think simply scrolling it off the screen and
then scrolling back will be enough to trigger a refresh with the new
data? Obviously before the ACK has arrived it's going to display only
the data it has.

>     If that's the case how would I for example alert a user to packets
> making up a bad conversation if it's not possible to update the COL_INFO
> column after processing the packets on the first pass, at which time you may
> not know if the conversation is bad? I know you can add expert info data to
> the protocol tree pane, and I do that also, but having to scroll through
> each packet to see when a conversation is bad would be a pain, the COL_INFO
> column seems to naturally provide a nice summary area to indicate this?

In the latest development releases, the expert information API has
been changed to be filterable just like regular packet fields, so that
should be sufficient. If there is a case where the COL_INFO is not
refreshing when it should we can also try to fix that, thought it will
likely be tricky.

The GTK version (including 1.10 stable) also has a dialogue for
browsing just the expert information in the capture at each severity
level, so you could use that. It doesn't exist (yet?) in the QT
version that I'm aware of.

Hope this helps,
Evan