Wireshark-dev: Re: [Wireshark-dev] TCP dissect issue when app-level message spans multiple TCP
From: Chris Maynard <[email protected]>
Date: Thu, 5 May 2011 15:00:06 +0000 (UTC)
Fernandez, Rafael <[email protected]> writes:

> I am writing a dissector plugin and I am using tcp_dissect_pdus in order to
reassemble packets. However, I
> am experiencing issues when there are multiple application layer messages in
one packet and the last one
> is not complete. Specifically, I have 5 messages in one TCP packet. There are
5 calls to the get_pdu_len
> function and four calls to the dissect_pdu function. Since there is not enough
data in the current
> tvbuff_t, tcp_dissect_pdus returns. When dissect_message is called again, the
beginning of the
> message is lost. When get_pdu_len gets called again it reads a garbage size.
> 
> Per https://www.wireshark.org/docs/wsdg_html_chunked/ChDissectReassemble.html,
I thought that
> tcp_dissect_pdus is supposed to handle this. I can't find example code in any
dissector in
> /epan/dissectors/* that handles this unlike I am. Am I missing something?
> 
> This is part of my code:
> 
> void dissect_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
> {
>         if(pinfo->tcp_tree != NULL) {
>                 tcp_dissect_pdus(tvb, pinfo, tree, TRUE, MESSAGE_HEADER_SIZE,
>                                  get_message_tcpmessage_len,
dissect_message_tcpmessage);
>         }
>         else {
>                 // For UDP just print the data for now.
>                 call_dissector(data_handle, tvb, pinfo, tree);
>         }
> }
> 
> guint get_message_tcpmessage_len(packet_info *pinfo, tvbuff_t *tvb, int offset)
> {
>         if(tvb_length_remaining(tvb, offset) <= 8)
>                 return 0;
> 
>         gint32 size = tvb_get_letohl(tvb, offset)+MESSAGE_HEADER_SIZE;
>         gint32 type = tvb_get_letohl(tvb, offset+4);
>         printf("Len: %u type %d\n", size, type);
>         if(strcmp(typeAsString(type), "Unknown") == 0)
>         {
>                 return tvb_length_remaining(tvb, offset);
>         }
>         return size;
> }

I don't think your get_message_tcpmessage_len() function is coded correctly.  It
looks like you're trying to do some heuristics in there when all you really
should be doing is returning the length of your PDU.  In your case, it looks
like the length field is the 1st 4-bytes of the header, so I think you should
probably just be doing something like this:

    if(pinfo->tcp_tree != NULL) {
        tcp_dissect_pdus(tvb, pinfo, tree, TRUE, 4, get_message_tcpmessage_len, 
                         dissect_message_tcpmessage);
    }

(NOTE: Here, you could use MESSAGE_HEADER_SIZE instead of 4, but you really only
need the 1st 4 bytes to determine the length of the entire PDU.)

guint get_message_tcpmessage_len(packet_info *pinfo, tvbuff_t *tvb, int offset)
{
    return tvb_get_letohl(tvb, offset) + MESSAGE_HEADER_SIZE;
}