Wireshark-dev: Re: [Wireshark-dev] c-string dissector - desegmentation

From: Tomasz Noiński <noix@xxxxxxxxx>
Date: Tue, 12 Sep 2006 21:51:02 +0200
On Tue, 12 Sep 2006 12:00:48 +0000
"ronnie sahlberg" <ronniesahlberg@xxxxxxxxx> wrote:

Hello,

Thanks for replying.

> dissectors are assumed to return either TRUE or FALSE and not the
> number of consumed bytes so the lower layers will not call your
> dissector again for you.
>
> This only happens when you use tcp_dissect_pdus() since it uses a
> special callback that provides this information.

If so, I'm confused...
Comments about "new_dissector_t" in packet.h say:

/*
 * Dissector that returns:
 *
 *  The amount of data in the protocol's PDU, if it was able to
 *  dissect all the data;
 *
 *  0, if the tvbuff doesn't contain a PDU for that protocol;
 *
 *  The negative of the amount of additional data needed, if
 *  we need more data (e.g., from subsequent TCP segments) to
 *  dissect the entire PDU.
 */

> You will have to explicitely loop over the tvb in your dissector and
> consume one pdu at a time until you reach the end of the tvb.

I tried it, but couldn't get it to fully work.

It did pass the "test" (prepared sequence of tcp packets) I described in
my previous post.
But, it didn't work as expected on:

packet 1: "\001"
packet 2: "\001\001\000"

I'm sure I'm doing some stupid mistake...
I think my code is nearly as short as it can be, so I'll just paste it
here and hope for some comments...
(it is supposed to dissect "c strings" and has problems with
desegmentation):

--- 8< ---

static int dissect_noix(tvbuff_t *tvb, packet_info *pinfo, proto_tree
*tree) {
    gint offset = 0;

        gint available = tvb_reported_length_remaining(tvb, offset);

        while (1) {

                gint len = tvb_strnlen(tvb, offset, available);

                printf("offset=%d, len=%d\n", offset, len);

                if(-1 == len) {
                        if (offset >= available) {
                                return offset;
                        } else {
                                pinfo->desegment_offset = offset;
                                pinfo->desegment_len = 1;
                                return -1;
                        }
                }

                if (check_col(pinfo->cinfo, COL_INFO)) {
                        col_set_str(pinfo->cinfo, COL_INFO, "C String");
                }

                len += 1; /* Add one for the '\0' */

                if (tree) {
                        proto_tree_add_item(tree, hf_cstring, tvb,
offset, len, FALSE); }

                offset += len;

        }

}

--- 8< ---

TIA,

Noix