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:
- Frame x : start of msg 1 Frame x+1
- Frame x+1 : missing, received later
- Frame x+2 : end of msg2 + start of msg3
- Frame x+1 : end of msg1 + start of msg2 --> msg1 is dissected
- 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
21●1●1●3
accept rate: 0%