* Added Mike Hall's TCP reconstruction code.

svn path=/trunk/; revision=10
This commit is contained in:
Gerald Combs 1998-09-17 03:12:28 +00:00
parent 3ad9f39915
commit 5110b21fd8
12 changed files with 417 additions and 22 deletions

View File

@ -8,6 +8,7 @@ ethereal_SOURCES = \
ethertype.c \
file.c \
filter.c \
follow.c \
menu.c \
packet.c \
packet-arp.c \
@ -40,6 +41,7 @@ ethereal_SOURCES = \
etypes.h \
file.h \
filter.h \
follow.h \
menu.h \
packet.h \
packet-ipv6.h \

View File

@ -77,6 +77,7 @@ ethereal_SOURCES = \
ethertype.c \
file.c \
filter.c \
follow.c \
menu.c \
packet.c \
packet-arp.c \
@ -109,6 +110,7 @@ ethereal_SOURCES = \
etypes.h \
file.h \
filter.h \
follow.h \
menu.h \
packet.h \
packet-ipv6.h \
@ -145,11 +147,11 @@ CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
ethereal_OBJECTS = capture.o ethereal.o ethertype.o file.o filter.o \
menu.o packet.o packet-arp.o packet-bootp.o packet-data.o packet-dns.o \
packet-eth.o packet-llc.o packet-lpd.o packet-ip.o packet-ipv6.o \
packet-ipx.o packet-osi.o packet-ospf.o packet-ppp.o packet-raw.o \
packet-rip.o packet-tcp.o packet-tr.o packet-trmac.o packet-udp.o \
packet-vines.o print.o ps.o resolv.o util.o
follow.o menu.o packet.o packet-arp.o packet-bootp.o packet-data.o \
packet-dns.o packet-eth.o packet-llc.o packet-lpd.o packet-ip.o \
packet-ipv6.o packet-ipx.o packet-osi.o packet-ospf.o packet-ppp.o \
packet-raw.o packet-rip.o packet-tcp.o packet-tr.o packet-trmac.o \
packet-udp.o packet-vines.o print.o ps.o resolv.o util.o
ethereal_LDADD = $(LDADD)
ethereal_LDFLAGS =
CFLAGS = @CFLAGS@
@ -169,15 +171,15 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP = --best
DEP_FILES = .deps/capture.P .deps/ethereal.P .deps/ethertype.P \
.deps/file.P .deps/filter.P .deps/menu.P .deps/packet-arp.P \
.deps/packet-bootp.P .deps/packet-data.P .deps/packet-dns.P \
.deps/packet-eth.P .deps/packet-ip.P .deps/packet-ipv6.P \
.deps/packet-ipx.P .deps/packet-llc.P .deps/packet-lpd.P \
.deps/packet-osi.P .deps/packet-ospf.P .deps/packet-ppp.P \
.deps/packet-raw.P .deps/packet-rip.P .deps/packet-tcp.P \
.deps/packet-tr.P .deps/packet-trmac.P .deps/packet-udp.P \
.deps/packet-vines.P .deps/packet.P .deps/print.P .deps/ps.P \
.deps/resolv.P .deps/util.P
.deps/file.P .deps/filter.P .deps/follow.P .deps/menu.P \
.deps/packet-arp.P .deps/packet-bootp.P .deps/packet-data.P \
.deps/packet-dns.P .deps/packet-eth.P .deps/packet-ip.P \
.deps/packet-ipv6.P .deps/packet-ipx.P .deps/packet-llc.P \
.deps/packet-lpd.P .deps/packet-osi.P .deps/packet-ospf.P \
.deps/packet-ppp.P .deps/packet-raw.P .deps/packet-rip.P \
.deps/packet-tcp.P .deps/packet-tr.P .deps/packet-trmac.P \
.deps/packet-udp.P .deps/packet-vines.P .deps/packet.P .deps/print.P \
.deps/ps.P .deps/resolv.P .deps/util.P
SOURCES = $(ethereal_SOURCES) $(EXTRA_ethereal_SOURCES)
OBJECTS = $(ethereal_OBJECTS)

View File

@ -1,6 +1,6 @@
/* ethereal.c
*
* $Id: ethereal.c,v 1.2 1998/09/16 03:21:54 gerald Exp $
* $Id: ethereal.c,v 1.3 1998/09/17 03:12:23 gerald Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -63,7 +63,11 @@
#include "etypes.h"
#include "print.h"
#include "resolv.h"
#include "follow.h"
#include "util.h"
FILE *data_out_file = NULL;
packet_info pi;
capture_file cf;
GtkWidget *file_sel, *packet_list, *tree_view, *byte_view, *prog_bar,
*info_bar;
@ -99,6 +103,97 @@ file_progress_cb(gpointer p) {
return TRUE;
}
/* Follow a TCP stream */
void
follow_stream_cb( GtkWidget *widget, gpointer data ) {
char filename1[128];
char buf[128];
GtkWidget *streamwindow, *box, *text, *vscrollbar, *table;
if( pi.ipproto == 6 ) {
/* we got tcp so we can follow */
/* check to see if we are using a filter */
if( cf.filter != NULL ) {
/* get rid of this one */
g_free( cf.filter );
cf.filter = NULL;
}
/* create a new one */
cf.filter = build_follow_filter( &pi );
/* reload so it goes in effect. Also we set data_out_file which
tells the tcp code to output the data */
close_cap_file( &cf, info_bar, file_ctx);
strcpy( filename1, tmpnam(NULL) );
data_out_file = fopen( filename1, "a" );
if( data_out_file == NULL ) {
fprintf( stderr, "Could not open tmp file %s\n", filename1 );
}
reset_tcp_reassembly();
load_cap_file( cf.filename, &cf );
/* the data_out_file should now be full of the streams information */
fclose( data_out_file );
/* the filename1 file now has all the text that was in the session */
streamwindow = gtk_window_new( GTK_WINDOW_TOPLEVEL);
gtk_widget_set_name( streamwindow, "TCP stream window" );
gtk_signal_connect( GTK_OBJECT(streamwindow), "delete_event",
NULL, "WM destroy" );
gtk_signal_connect( GTK_OBJECT(streamwindow), "destroy",
NULL, "WM destroy" );
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 */
box = gtk_vbox_new( FALSE, 0 );
gtk_container_add( GTK_CONTAINER(streamwindow), box );
gtk_widget_show( box );
/* set up the table we attach to */
table = gtk_table_new( 1, 2, FALSE );
gtk_table_set_col_spacing( GTK_TABLE(table), 0, 2);
gtk_box_pack_start( GTK_BOX(box), table, TRUE, TRUE, 0 );
gtk_widget_show( table );
/* create a text box */
text = gtk_text_new( NULL, NULL );
gtk_text_set_editable( GTK_TEXT(text), FALSE);
gtk_table_attach( GTK_TABLE(table), text, 0, 1, 0, 1,
GTK_EXPAND | GTK_SHRINK | GTK_FILL,
GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0 );
gtk_widget_show(text);
/* create the scrollbar */
vscrollbar = gtk_vscrollbar_new( GTK_TEXT(text)->vadj );
gtk_table_attach( GTK_TABLE(table), vscrollbar, 1, 2, 0, 1,
GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0 );
gtk_widget_show( vscrollbar );
gtk_widget_realize( text );
/* stop the updates while we fill the text box */
gtk_text_freeze( GTK_TEXT(text) );
data_out_file = NULL;
data_out_file = fopen( filename1, "r" );
if( data_out_file ) {
char buffer[1024];
int nchars;
while( 1 ) {
nchars = fread( buffer, 1, 1024, data_out_file );
gtk_text_insert( GTK_TEXT(text), m_r_font, NULL, NULL, buffer, nchars );
if( nchars < 1024 ) {
break;
}
}
fclose( data_out_file );
unlink( filename1 );
}
gtk_text_thaw( GTK_TEXT(text) );
data_out_file = NULL;
gtk_widget_show( streamwindow );
if( cf.filter != NULL ) {
g_free( cf.filter );
cf.filter = NULL;
}
} else {
simple_dialog(ESD_TYPE_WARN, NULL,
"Error following stream. Please make\n"
"sure you have a TCP packet selected.");
}
}
/* Open a file */
void
file_open_cmd_cb(GtkWidget *widget, gpointer data) {
@ -136,6 +231,7 @@ void
packet_list_select_cb(GtkWidget *w, gint row, gint col, gpointer evt) {
GList *l;
blank_packetinfo();
gtk_text_freeze(GTK_TEXT(byte_view));
gtk_text_set_point(GTK_TEXT(byte_view), 0);
gtk_text_forward_delete(GTK_TEXT(byte_view),
@ -186,6 +282,14 @@ file_quit_cmd_cb (GtkWidget *widget, gpointer data) {
gtk_exit(0);
}
void blank_packetinfo() {
pi.srcip = 0;
pi.destip = 0;
pi.ipproto = 0;
pi.srcport = 0;
pi.destport = 0;
}
/* Things to do when the OK button is pressed */
void
main_realize_cb(GtkWidget *w, gpointer data) {

View File

@ -1,7 +1,7 @@
/* ethereal.h
* Global defines, etc.
*
* $Id: ethereal.h,v 1.2 1998/09/16 03:21:55 gerald Exp $
* $Id: ethereal.h,v 1.3 1998/09/17 03:12:24 gerald Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -34,6 +34,7 @@
#define DEF_WIDTH 750
#define DEF_HEIGHT 550
#define DEF_READY_MESSAGE " Ready to load or capture"
#define EXTERNAL_FILTER "/usr/local/bin/ethereal_tcp_filter -f"
/* Byte swapping routines */
#define SWAP16(x) \
@ -71,7 +72,9 @@ typedef struct _selection_info {
} selection_info;
void file_sel_ok_cb(GtkWidget *, GtkFileSelection *);
void blank_packetinfo();
gint file_progress_cb(gpointer);
void follow_stream_cb( GtkWidget *, gpointer);
void file_open_cmd_cb(GtkWidget *, gpointer);
void file_close_cmd_cb(GtkWidget *, gpointer);
void file_quit_cmd_cb(GtkWidget *, gpointer);

5
file.c
View File

@ -1,7 +1,7 @@
/* file.c
* File I/O routines
*
* $Id: file.c,v 1.2 1998/09/16 03:21:57 gerald Exp $
* $Id: file.c,v 1.3 1998/09/17 03:12:24 gerald Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -83,6 +83,9 @@ open_cap_file(char *fname, capture_file *cf) {
fclose(cf->fh);
cf->fh = NULL;
/* set the file name beacuse we need it to set the follow stream filter */
cf->filename = strdup( fname );
/* Next, find out what type of file we're dealing with */
cf->cd_t = CD_UNKNOWN;

3
file.h
View File

@ -1,7 +1,7 @@
/* file.h
* Definitions for file structures and routines
*
* $Id: file.h,v 1.2 1998/09/16 03:21:57 gerald Exp $
* $Id: file.h,v 1.3 1998/09/17 03:12:25 gerald Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -54,6 +54,7 @@ typedef struct bpf_program bpf_prog;
typedef struct _capture_file {
FILE *fh; /* Capture file */
gchar *filename; /* filename */
long f_len; /* File length */
int swap; /* Swap data bytes? */
guint16 cd_t; /* Capture data type */

197
follow.c Normal file
View File

@ -0,0 +1,197 @@
/* follow.c
*
* $Id: follow.c,v 1.1 1998/09/17 03:12:26 gerald Exp $
*
* Copyright 1998 Mike Hall <mlh@io.com>
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
* Copyright 1998 Gerald Combs
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include <gtk/gtk.h>
#include <string.h>
#include <unistd.h>
#include "packet.h"
#include "follow.h"
extern FILE* data_out_file;
/* 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
very good one */
char*
build_follow_filter( packet_info *pi ) {
char* buf = malloc(1024);
if( pi->ipproto == 6 ) {
/* TCP */
sprintf( buf, "host %s and host %s and (ip proto \\tcp) and (port %d and port %d)",
pi->srcip, pi->destip, pi->srcport, pi->destport );
}
else {
free( buf );
return NULL;
}
return buf;
}
/* here we are going to try and reconstruct the data portion of a TCP
session. We will try and handle duplicates, TCP fragments, and out
of order packets in a smart way. */
static tcp_frag *frags[2] = { 0, 0};
static u_long seq[2];
static u_long src[2] = { 0, 0 };
void
reassemble_tcp( u_long sequence, u_long length, char* data, int synflag, u_long srcx ) {
int src_index, j, first = 0;
u_long newseq;
tcp_frag *tmp_frag;
src_index = -1;
/* first we check to see if we have seen this src ip before. */
for( j=0; j<2; j++ ) {
if( src[j] == srcx ) {
src_index = j;
}
}
/* we didn't find it if src_index == -1 */
if( src_index < 0 ) {
/* assign it to a src_index and get going */
for( j=0; j<2; j++ ) {
if( src[j] == 0 ) {
src[j] = srcx;
src_index = j;
first = 1;
break;
}
}
}
if( src_index < 0 ) {
fprintf( stderr, "ERROR in reassemble_tcp: Too many addresses!\n");
return;
}
/* now that we have filed away the srcs, lets get the sequence number stuff
figured out */
if( first ) {
/* this is the first time we have seen this src's sequence number */
seq[src_index] = sequence + length;
if( synflag ) {
seq[src_index]++;
}
/* write out the packet data */
write_packet_data( data, length );
return;
}
/* if we are here, we have already seen this src, let's
try and figure out if this packet is in the right place */
if( sequence < seq[src_index] ) {
/* this sequence number seems dated, but
check the end to make sure it has no more
info than we have already seen */
newseq = sequence + length;
if( newseq > seq[src_index] ) {
/* this one has more than we have seen. let's get the
payload that we have not seen. */
data += ( seq[src_index] - sequence );
sequence = seq[src_index];
length = newseq - seq[src_index];
/* this will now appear to be right on time :) */
}
}
if ( sequence == seq[src_index] ) {
/* right on time */
seq[src_index] += length;
if( synflag ) seq[src_index]++;
write_packet_data( data, length );
/* done with the packet, see if it caused a fragment to fit */
while( check_fragments( src_index ) )
;
}
else {
/* 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->seq = sequence;
tmp_frag->len = length;
bcopy( data, tmp_frag->data, length );
if( frags[src_index] ) {
tmp_frag->next = frags[src_index];
} else {
tmp_frag->next = NULL;
}
frags[src_index] = tmp_frag;
}
}
} /* end reassemble_tcp */
/* here we search through all the frag we have collected to see if
one fits */
int
check_fragments( int index ) {
tcp_frag *prev = NULL;
tcp_frag *current;
current = frags[index];
while( current ) {
if( current->seq == seq[index] ) {
/* this fragment fits the stream */
write_packet_data( current->data, current->len );
seq[index] += current->len;
if( prev ) {
prev->next = current->next;
} else {
src[index] = current->next;
}
free( current->data );
free( current );
return 1;
}
prev = current;
current = current->next;
}
return 0;
}
/* this should always be called before we start to reassemble a stream */
void
reset_tcp_reassembly() {
tcp_frag *current, *next;
int i;
for( i=0; i<2; i++ ) {
seq[i] = 0;
src[i] = 0;
current = frags[i];
while( current ) {
next = current->next;
free( current->data );
free( current );
current = next;
}
frags[i] = NULL;
}
}
void
write_packet_data( u_char* data, int length ) {
fwrite( data, 1, length, data_out_file );
}

45
follow.h Normal file
View File

@ -0,0 +1,45 @@
/* follow.h
*
* $Id: follow.h,v 1.1 1998/09/17 03:12:26 gerald Exp $
*
* Copyright 1998 Mike Hall <mlh@io.com>
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
* Copyright 1998 Gerald Combs
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __FOLLOW_H__
#define __FOLLOW_H__
#include "packet.h"
typedef struct _tcp_frag {
u_long seq;
u_long len;
u_char *data;
struct _tcp_frag *next;
} tcp_frag;
char* build_follow_filter( packet_info * );
void reassemble_tcp( u_long, u_long, char*, int, u_long );
int check_fragments( int );
void write_packet_data( u_char *, int );
#endif

4
menu.c
View File

@ -1,7 +1,7 @@
/* menu.c
* Menu routines
*
* $Id: menu.c,v 1.2 1998/09/16 03:21:59 gerald Exp $
* $Id: menu.c,v 1.3 1998/09/17 03:12:27 gerald Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -40,6 +40,7 @@
#include "filter.h"
#include "packet.h"
#include "print.h"
#include "follow.h"
/* Much of this was take from the GTK+ tuturial at http://www.gtk.org */
@ -73,6 +74,7 @@ static GtkMenuEntry menu_items[] =
{"<Main>/Edit/Printer Options", NULL, printer_opts_cb, NULL},
{"<Main>/Tools/Capture", "<control>K", capture_prep_cb, NULL},
{"<Main>/Tools/Filter", NULL, filter_sel_cb, NULL},
{"<Main>/Tools/Follow TCP Stream", NULL, follow_stream_cb, NULL},
{"<Main>/Tools/Graph", NULL, NULL, NULL},
{"<Main>/Help/About Ethereal", NULL, NULL, NULL}
};

View File

@ -1,7 +1,7 @@
/* packet-ip.c
* Routines for IP and miscellaneous IP protocol packet disassembly
*
* $Id: packet-ip.c,v 1.2 1998/09/16 03:22:04 gerald Exp $
* $Id: packet-ip.c,v 1.3 1998/09/17 03:12:27 gerald Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -45,6 +45,8 @@
#include "etypes.h"
#include "resolv.h"
extern packet_info pi;
void
dissect_ip(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
e_ip iph;
@ -126,6 +128,13 @@ dissect_ip(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
get_hostname(iph.ip_dst));
}
pi.srcip = ip_to_str( (guint8 *) &iph.ip_src);
pi.destip = ip_to_str( (guint8 *) &iph.ip_dst);
pi.ipproto = iph.ip_p;
pi.iplen = iph.ip_len;
pi.iphdrlen = iph.ip_hl;
pi.ip_src = iph.ip_src;
offset += iph.ip_hl * 4;
switch (iph.ip_p) {
case IP_PROTO_ICMP:

View File

@ -1,7 +1,7 @@
/* packet-tcp.c
* Routines for TCP packet disassembly
*
* $Id: packet-tcp.c,v 1.2 1998/09/16 03:22:11 gerald Exp $
* $Id: packet-tcp.c,v 1.3 1998/09/17 03:12:28 gerald Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -42,6 +42,9 @@
#include "ethereal.h"
#include "packet.h"
extern FILE* data_out_file;
extern packet_info pi;
void
dissect_tcp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
e_tcphdr th;
@ -115,4 +118,17 @@ dissect_tcp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
dissect_data(pd, offset, fd, tree);
}
}
pi.srcport = th.th_sport;
pi.destport = th.th_dport;
if( data_out_file ) {
reassemble_tcp( th.th_seq, /* sequence number */
( pi.iplen -( pi.iphdrlen * 4 )-( th.th_off * 4 ) ), /* length */
( pd+offset ), /* data */
( th.th_flags & 0x02 ), /* is syn set? */
pi.ip_src ); /* src ip */
}
}

View File

@ -1,7 +1,7 @@
/* packet.h
* Definitions for packet disassembly structures and routines
*
* $Id: packet.h,v 1.4 1998/09/17 02:37:47 gerald Exp $
* $Id: packet.h,v 1.5 1998/09/17 03:12:28 gerald Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -64,6 +64,17 @@ typedef struct _frame_data {
gchar *win_info[5]; /* Packet list text */
} frame_data;
typedef struct _packet_info {
char *srcip;
int ip_src;
char *destip;
int ipproto;
int srcport;
int destport;
int iplen;
int iphdrlen;
} packet_info;
/* Many of the structs and definitions below were taken from include files
* in the Linux distribution. */