Wireshark-dev: Re: [Wireshark-dev] TCP dissect issue when app-level message spans multiple TCP

From: "Fernandez, Rafael" <Rafael.Fernandez@xxxxxxxxxxxxxxxx>
Date: Thu, 5 May 2011 15:56:30 -0500
I completely agree with your answer. That is what I expect to happen.
I was able to download wireshark-1.5.2-SVN-36997, compile against it, and the issue still happens.
I must note that there is a [TCP Previous segment lost] and a [TCP out-of-order] 10 frames apart and it is also where the problem starts occurring until the end of the capture file.
I now register a different dissector for UDP and TCP.

Nonetheless, This is my current code:

void dissect_tcp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
        tcp_dissect_pdus(tvb, pinfo, tree, TRUE, 4,
                         get_tcp_message_len,
                         dissect_tcp_message);
}

void dissect_tcp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
      if (check_col(pinfo->cinfo, COL_PROTOCOL))
            col_set_str(pinfo->cinfo, COL_PROTOCOL, "MyMessage");

        gint32 length, type, legacy;
        if(tvb_bytes_exist(tvb, 0, MESSAGE_HEADER_SIZE))
        {
                length = tvb_get_letohl(tvb, 0);
                type   = tvb_get_letohl(tvb, 4);
                legacy = tvb_get_letohl(tvb, 8);
        }
        else
        {
                call_dissector(data_handle, tvb, pinfo, tree);
                return;
        }

        if (check_col(pinfo->cinfo, COL_INFO))
        {
                col_add_fstr(pinfo->cinfo, COL_INFO, "[%s] ",
                               typeAsString(type));
                col_set_fence(pinfo->cinfo, COL_INFO);
        }

        if(!tree)
        {
                return;
        }

        proto_item *base_item, *header_item, *body_item;
        proto_tree *base_tree, *header_tree;
        base_item = header_item = body_item = NULL;
        base_tree = header_tree = NULL;

        base_item = proto_tree_add_item(tree, proto_mymessage, tvb, 0, -1, FALSE);
        base_tree = proto_item_add_subtree(base_item, ett_mymessage);

        header_tree = proto_item_add_subtree(base_item, ett_mymessage);
        header_item = proto_tree_add_item(base_tree, hf_header, tvb, 0, MESSAGE_HEADER_SIZE, FALSE);

        body_item = proto_tree_add_item(base_tree, hf_body, tvb, MESSAGE_HEADER_SIZE, -1, FALSE);

        header_tree = proto_item_add_subtree(header_item, ett_mymessage);
        proto_tree_add_int(header_tree, hf_header_length, tvb, 0, 4, length);
        proto_tree_add_string_format_value(header_tree, hf_header_type, tvb, 4, 4, "", "%s [%d]",
                                                        typeAsString(type), type);
        proto_tree_add_int(header_tree, hf_header_seq, tvb, 8, 4, legacy);
}

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

-----Original Message-----
From: wireshark-dev-bounces@xxxxxxxxxxxxx [mailto:wireshark-dev-bounces@xxxxxxxxxxxxx] On Behalf Of Guy Harris
Sent: Thursday, May 05, 2011 2:59 PM
To: Developer support list for Wireshark
Subject: Re: [Wireshark-dev] TCP dissect issue when app-level message spans multiple TCP packets


On May 5, 2011, at 10:39 AM, Fernandez, Rafael wrote:

> The issue is the following:
>
> In epan/dissectors/packet-tcp.c-tcp_dissect_pdus():
> line 1993: get_pdu_len returns 322. Sets plen to 322.
> line 2053-2061: length_remaining is 144. Thus (length_remaining < plen) is true. Sets pinfo->desegment_offset and pinfo->desegment_len. tcp_dissect_pdus returns.

...meaning that the TCP segment handed to tcp_dissect_pdus() didn't have a complete message, so there's nothing more for it to do at that point.

> In my_dissector.c:
> 1. Once tcp_dissect_pdus returns, dissect_message returns.
> 2. dissect_message gets called soon after and calls tcp_dissect_pdus again.

...when the next segment is available.

dissect_message() should, at that point, have been handed to it by the TCP dissector a reassembled tvbuff containing:

        the 144 bytes from the TCP segment that was handed to it in the previous call;

        following it, up to 178 bytes of additional data from the next segment;

in which case...

> In packet-tcp.c-tcp_dissect_pdus:
> Line 1993: get_pdu_len gets called again. It read 4 bytes starting from the 178th (322-144) byte of the application message. Thus, it returns a garbage size.

...get_pdu_len() should be handed the reassembled tvbuff in question, with an offset argument of 0, so it should be reading the same 4 bytes that it did on the first call, *not* the first 4 bytes of the second segment.

dissect_message() is the dissector you registered with TCP as the dissector for your protocol, right?

> Don't you think there is an issue with this?

There's an issue with *something*, but, given that tcp_dissect_pdus() has worked and continues to work fine for a number of other protocols, it's not a simple or obvious issue.
___________________________________________________________________________
Sent via:    Wireshark-dev mailing list <wireshark-dev@xxxxxxxxxxxxx>
Archives:    http://www.wireshark.org/lists/wireshark-dev
Unsubscribe: https://wireshark.org/mailman/options/wireshark-dev
             mailto:wireshark-dev-request@xxxxxxxxxxxxx?subject=unsubscribe


CONFIDENTIALITY AND SECURITY NOTICE

The contents of this message and any attachments may be confidential and proprietary and also may be covered by the Electronic Communications Privacy Act. This message is not intended to be used by, and should not be relied upon in any way, by any third party.  If you are not an intended recipient, please inform the sender of the transmission error and delete this message immediately without reading, disseminating, distributing or copying the contents. Citadel makes no assurances that this e-mail and any attachments are free of viruses and other harmful code.