Fixes to the TCP reassembly code to correctly handle too short

caplen or incomplete data (avoid crashes or erroneous display).

svn path=/trunk/; revision=227
This commit is contained in:
Laurent Deniel 1999-03-23 20:25:50 +00:00
parent 6cbabed4c2
commit 210d386532
4 changed files with 49 additions and 13 deletions

View File

@ -1,6 +1,6 @@
/* ethereal.c
*
* $Id: ethereal.c,v 1.25 1999/03/23 03:14:33 gram Exp $
* $Id: ethereal.c,v 1.26 1999/03/23 20:25:50 deniel Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -191,7 +191,13 @@ follow_stream_cb( GtkWidget *w, gpointer data ) {
NULL, "WM destroy" );
gtk_signal_connect( GTK_OBJECT(streamwindow), "destroy",
NULL, "WM destroy" );
gtk_window_set_title( GTK_WINDOW(streamwindow), "Contents of TCP stream" );
if( incomplete_tcp_stream ) {
gtk_window_set_title( GTK_WINDOW(streamwindow),
"Contents of TCP stream (incomplete)" );
} else {
gtk_window_set_title( GTK_WINDOW(streamwindow),
"Contents of TCP stream" );
}
gtk_widget_set_usize( GTK_WIDGET(streamwindow), DEF_WIDTH, DEF_HEIGHT );
gtk_container_border_width( GTK_CONTAINER(streamwindow), 2 );
/* setup the container */

View File

@ -1,6 +1,6 @@
/* follow.c
*
* $Id: follow.c,v 1.5 1998/12/17 05:42:25 gram Exp $
* $Id: follow.c,v 1.6 1999/03/23 20:25:49 deniel Exp $
*
* Copyright 1998 Mike Hall <mlh@io.com>
*
@ -45,6 +45,8 @@
extern FILE* data_out_file;
gboolean incomplete_tcp_stream = FALSE;
/* this will build libpcap filter text that will only
pass the packets related to the stream. There is a
chance that two streams could intersect, but not a
@ -73,7 +75,7 @@ static u_long seq[2];
static u_long src[2] = { 0, 0 };
void
reassemble_tcp( u_long sequence, u_long length, const char* data, int synflag, u_long srcx ) {
reassemble_tcp( u_long sequence, u_long length, const char* data, u_long data_length, int synflag, u_long srcx ) {
int src_index, j, first = 0;
u_long newseq;
tcp_frag *tmp_frag;
@ -100,6 +102,11 @@ reassemble_tcp( u_long sequence, u_long length, const char* data, int synflag, u
fprintf( stderr, "ERROR in reassemble_tcp: Too many addresses!\n");
return;
}
if( data_length < length ) {
incomplete_tcp_stream = TRUE;
}
/* now that we have filed away the srcs, lets get the sequence number stuff
figured out */
if( first ) {
@ -109,7 +116,7 @@ reassemble_tcp( u_long sequence, u_long length, const char* data, int synflag, u
seq[src_index]++;
}
/* write out the packet data */
write_packet_data( data, length );
write_packet_data( data, data_length );
return;
}
/* if we are here, we have already seen this src, let's
@ -120,11 +127,24 @@ reassemble_tcp( u_long sequence, u_long length, const char* data, int synflag, u
info than we have already seen */
newseq = sequence + length;
if( newseq > seq[src_index] ) {
u_long new_len;
/* this one has more than we have seen. let's get the
payload that we have not seen. */
data += ( seq[src_index] - sequence );
new_len = seq[src_index] - sequence;
if ( data_length <= new_len ) {
data = NULL;
data_length = 0;
incomplete_tcp_stream = TRUE;
} else {
data += new_len;
data_length -= new_len;
}
sequence = seq[src_index];
length = newseq - seq[src_index];
/* this will now appear to be right on time :) */
}
}
@ -132,7 +152,9 @@ reassemble_tcp( u_long sequence, u_long length, const char* data, int synflag, u
/* right on time */
seq[src_index] += length;
if( synflag ) seq[src_index]++;
write_packet_data( data, length );
if( data ) {
write_packet_data( data, data_length );
}
/* done with the packet, see if it caused a fragment to fit */
while( check_fragments( src_index ) )
;
@ -141,10 +163,11 @@ reassemble_tcp( u_long sequence, u_long length, const char* data, int synflag, u
/* out of order packet */
if( sequence > seq[src_index] ) {
tmp_frag = (tcp_frag *)malloc( sizeof( tcp_frag ) );
tmp_frag->data = (u_char *)malloc( length );
tmp_frag->data = (u_char *)malloc( data_length );
tmp_frag->seq = sequence;
tmp_frag->len = length;
memcpy( tmp_frag->data, data, length );
tmp_frag->data_len = data_length;
memcpy( tmp_frag->data, data, data_length );
if( frags[src_index] ) {
tmp_frag->next = frags[src_index];
} else {
@ -165,7 +188,9 @@ check_fragments( int index ) {
while( current ) {
if( current->seq == seq[index] ) {
/* this fragment fits the stream */
write_packet_data( current->data, current->len );
if( current->data ) {
write_packet_data( current->data, current->data_len );
}
seq[index] += current->len;
if( prev ) {
prev->next = current->next;
@ -187,6 +212,7 @@ void
reset_tcp_reassembly() {
tcp_frag *current, *next;
int i;
incomplete_tcp_stream = FALSE;
for( i=0; i<2; i++ ) {
seq[i] = 0;
src[i] = 0;

View File

@ -1,6 +1,6 @@
/* follow.h
*
* $Id: follow.h,v 1.2 1998/09/27 22:12:26 gerald Exp $
* $Id: follow.h,v 1.3 1999/03/23 20:25:50 deniel Exp $
*
* Copyright 1998 Mike Hall <mlh@io.com>
*
@ -30,15 +30,18 @@
#include "packet.h"
extern gboolean incomplete_tcp_stream;
typedef struct _tcp_frag {
u_long seq;
u_long len;
u_long data_len;
u_char *data;
struct _tcp_frag *next;
} tcp_frag;
char* build_follow_filter( packet_info * );
void reassemble_tcp( u_long, u_long, const char*, int, u_long );
void reassemble_tcp( u_long, u_long, const char*, u_long, int, u_long );
int check_fragments( int );
void reset_tcp_reassembly( void );
void write_packet_data( const u_char *, int );

View File

@ -1,7 +1,7 @@
/* packet-tcp.c
* Routines for TCP packet disassembly
*
* $Id: packet-tcp.c,v 1.17 1999/03/23 03:58:59 guy Exp $
* $Id: packet-tcp.c,v 1.18 1999/03/23 20:25:50 deniel Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -469,6 +469,7 @@ dissect_tcp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
reassemble_tcp( th.th_seq, /* sequence number */
( pi.iplen -( pi.iphdrlen * 4 )-( hi_nibble(th.th_off_x2) * 4 ) ), /* length */
( pd+offset ), /* data */
( fd->cap_len - offset ), /* captured data length */
( th.th_flags & 0x02 ), /* is syn set? */
pi.ip_src ); /* src ip */
}