This is our old Q&A Site. Please post any new questions and answers at ask.wireshark.org.

Hi,

I have created a dissector over TCP layer. Size of messages could vary a lot (from as little as 8 bytes to several Mbytes). Part of the network on which these messages are sent generates some packet error rate. Therefore, when I analyse the capture file, some messages part are misordered. Using the tcp_dissect_pdus helps a lot to handle this, but, in some cases, messages are missing. This occurs when the misorder TCP fragment contains start of a new message.

Following is a quick summary that tries to explain what I am seeing:

  1. Frame x : start of msg 1 Frame x+1
  2. Frame x+1 : missing, received later
  3. Frame x+2 : end of msg2 + start of msg3
  4. Frame x+1 : end of msg1 + start of msg2 --> msg1 is dissected
  5. Frame x+3 : end of msg3 --> msg3 is dissected

Unfortunately, I am working on a quite old version of wireshark (1.8.3).

Has anyone had this kind of problem and found a solution ?

Following is the dissector part that deals with pdu re-assembly (sorry, it is quite long). Each message is preceded by a header that will contain a magic number (to identify the protocol) and the message length.

static const MYPROTO_MAGIC myProtoMagic = {xx, xx, xx, xx};
static guint get_myproto_message_len(packet_info *pinfo,
                                     tvbuff_t    *tvb,
                                     int          offset)
{
    guint l_len = 0;
    MYPROTO_MAGIC HeadPattern;
    guint i;

    for (i= 0; i < sizeof(MYPROTO_MAGIC); i++)
        HeadPattern[i] = g_htonl(myProtoMagic[i]);

    //Check frame is a MYPROTO one, otherwise dismiss it
    if(tvb_memeql(tvb, offsetof(MYPROTO_HEAD, headPatternA), (const guint8 *) HeadPattern, sizeof(MY_PROTO_MAGIC)) == 0)
        l_len = tvb_get_ntohl(tvb, offset + offsetof(MYPROTO_HEAD, msgTotalSizeUI));
    else l_len = 0;

    return (l_len);
}

static int dissect_myproto_tcp(tvbuff_t     *tvb,
                               packet_info  *pinfo,
                               proto_tree   *tree)
{
    guint len = tvb_length(tvb);
    int ret = TRUE;
    MYPROTO_MAGIC HeadPattern;
    guint i;

    //Check packet is a MYPROTO ones
    // if tvb length is too short for comparison, consider frame as a MYPROTO ones,
    // but new comparison should be performed while retrieving PDU length
    //The following checks are performed :
    // - Frame length (sizeUI field should be large enough to contain MYPROTO header and trailer)
    // - Head pattern (used to identify MYPROTO frames) --> Check the biggest possible part of this pattern
    for (i= 0; i< sizeof(HeadPattern); i++)
        HeadPattern[i] = g_htonl(myProtoMagic[i]);

    if ((len > offsetof(MYPROTO_HEAD, headPatternAUI)) AND (len >= (offsetof(MYPROTO_HEAD, msgTotalSizeUI) + sizeof(guint))))
    {
        guint comparison_len = len - offsetof(MYPROTO_HEAD, headPatternAUI);

        if (comparison_len > sizeof(HeadPattern))
            comparison_len = sizeof(HeadPattern);

        if (tvb_memeql(tvb, offsetof(MYPROTO_HEAD, headPatternAUI), (const guint8 *) HeadPattern, comparison_len) != 0)
            ret = FALSE;
    }
    else if (len >= (offsetof(MYPROTO_HEAD, msgTotalSizeUI) + sizeof(guint)))
    {
        if (tvb_get_ntohl(tvb, offsetof(MYPROTO_HEAD, msgTotalSizeUI)) < (sizeof(MYPROTO_HEAD) + sizeof(MYPROTO_TRAIL)))
            ret = FALSE;
    }

    if (ret != FALSE)
    {
        tcp_dissect_pdus(tvb, pinfo, tree, TRUE, sizeof(MYPROTO_HEAD), get_myproto_message_len, dissect_myproto);
        return ret;
    }
    else
    {
        /* Start of tvb does not match a MYPROTO message, try to find another MYPROTO marker in tvb */
        tvbuff_t * tvbHead = tvb_new_real_data((const guint8 *) HeadPattern, 4, 4);
        gint offset = tvb_find_tvb(tvb, tvbHead, 0);

        if (offset == -1) /* No MYPROTO header found --> return */
            return FALSE;
        else
        {
            gint l_len, l_remain;
            tvbuff_t * tv;

            offset -= offsetof(MYPROTO_HEAD, headPattern);
            l_len = tvb_get_ntohl(tvb, offset + offsetof(MYPROTO_HEAD, msgTotalSizeUI));
            l_remain = tvb_length_remaining(tvb, offset);
            tv = tvb_new_subset(tvb, offset, l_len > l_remain ? -1 : l_len, l_len > l_remain ? -1 : l_len);

            tcp_dissect_pdus(tv, pinfo, tree, TRUE, sizeof(MYPROTO_HEAD), get_myproto_message_len, dissect_myproto);
            return TRUE;
        }
    }
}

asked 26 Feb '15, 05:30

baronju's gravatar image

baronju
21113
accept rate: 0%

Be the first one to answer this question!
toggle preview

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Markdown Basics

  • *italic* or _italic_
  • **bold** or __bold__
  • link:[text](http://url.com/ "title")
  • image?![alt text](/path/img.jpg "title")
  • numbered list: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • basic HTML tags are also supported

Question tags:

×752
×18
×8

question asked: 26 Feb '15, 05:30

question was seen: 1,188 times

last updated: 26 Feb '15, 05:30

p​o​w​e​r​e​d by O​S​Q​A