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

TCP reassembly and misordered frames

1

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%