Ethereal-dev: [Ethereal-dev] General problem for reassembling WTP packets

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Georg von Zezschwitz <gvz@xxxxxxxxxx>
Date: Sat, 26 Apr 2003 16:13:13 +0200
Hi,

the reassembly functions used e.g. by packet-wtp.c use a key to
gather fragments.

This key is based on source and destination ip, as well as the
TID of the WTP packet. However, in my case this key will reoccur
in other WSP sessions very soon, when gathering just some
minutes of activity on the LAN. This is dued to the fact that
both the mobiles assigned IP addresses are reused quickly, as
well as the mobiles are not that creative regarding their TID.

Therefore, ethereal and tethereal crash after some parsing a
few minutes of data, (g_assert(fd_head->len >= dfpos + fd->len)
from reassemble.c:974), as a fragment of a new customer
session exceeds the reassembled packet of a former session
on the same IP with the same TID.

I can think of two approaches to solve this:
 1) The hash_table is invalidated for a certain IP on a "stop"
    event (e.g. WSP disconnect for WAP).
 2) A timeout is used, which only glues fragments together, if
    they fall within a defined time frame. I guess this is
    the better and more general approach.

I have patched ethereal on my own based on the second approach,
howether I think my patch is too much of a "quick&dirty"
solution to include it like that.

I use a time-out of 10 seconds, which works fine for my data.
The patch only touches the fragment handling of packet-wtp.c,
however adds a "time last packet was seen"-value the fragement_data
structure.

Any ideas how to deal with this problem in a more general way?

Cheers,


Georg


Index: packet-wtp.c
===================================================================
RCS file: /cvsroot/ethereal/packet-wtp.c,v
retrieving revision 1.45
diff -r1.45 packet-wtp.c
612,613c612,613
< 	    fd_head = fragment_add_seq(tvb, dataOffset, pinfo, TID,
< 			    wtp_fragment_table, psn, dataLen, !fTTR);
---
> 	    fd_head = fragment_add_seq_with_timeout(tvb, dataOffset, pinfo, TID,
> 			    wtp_fragment_table, psn, dataLen, !fTTR, 10);
Index: reassemble.c
===================================================================
RCS file: /cvsroot/ethereal/reassemble.c,v
retrieving revision 1.37
diff -r1.37 reassemble.c
917a918,919
> 	if (fd_head->time_last_frag < pinfo->fd->abs_secs)
>         fd_head->time_last_frag = pinfo->fd->abs_secs;
1094a1097,1110
> 	return fragment_add_seq_with_timeout (tvb, offset, pinfo, id,
> 					fragment_table, frag_number, frag_data_len,
> 					more_frags, 0);
> }
> 
> /*
>  * original version of fragment_add_seq, plus a timeout how much 
>  * time might have passed between fragments to glue them together
>  */
> fragment_data *
> fragment_add_seq_with_timeout(tvbuff_t *tvb, int offset, packet_info *pinfo,
> 		 guint32 id, GHashTable *fragment_table, guint32 frag_number,
> 	     guint32 frag_data_len, gboolean more_frags, guint32 timeout)
> {
1113a1130,1139
> 	if (timeout > 0 && fd_head!=NULL &&
> 		pinfo->fd->abs_secs - fd_head->time_last_frag >= timeout) {
> # ifdef DEBUG
> 		fprintf (stderr, "Deleting old fragment buffer: %d vs %d\n",
> 						pinfo->fd->abs_secs, fd_head->time_last_frag);
> # endif
> 	    g_hash_table_remove(fragment_table, &key);
> 		fd_head = NULL;
> 	}
> 
1130a1157
> 		fd_head->time_last_frag = 0;
Index: reassemble.h
===================================================================
RCS file: /cvsroot/ethereal/reassemble.h,v
retrieving revision 1.18
diff -r1.18 reassemble.h
63a64
> 	guint32 time_last_frag;	/* timestamp when the last fragment was seen */
109a111,116
> 
> /* same as fragment_add_seq(), but adds a timeout how many secs
>  * might be between the last and our new fragment to correlate them */
> extern fragment_data *fragment_add_seq_with_timeout(tvbuff_t *tvb, int offset, packet_info *pinfo,
>     guint32 id, GHashTable *fragment_table, guint32 frag_number,
>     guint32 frag_data_len, gboolean more_frags, guint32 timeout);