/*
* TCPVIEW
*
* Author: Martin Hunt
* Networks and Distributed Computing
* Computing & Communications
* University of Washington
* Administration Building, AG-44
* Seattle, WA 98195
* Internet: martinh@cac.washington.edu
*
*
* Copyright 1992 by the University of Washington
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted, provided
* that the above copyright notice appears in all copies and that both the
* above copyright notice and this permission notice appear in supporting
* documentation, and that the name of the University of Washington not be
* used in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. This software is made
* available "as is", and
* THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
* WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
* NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
* (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#ifndef lint
static char rcsid[] =
"@(#) $Header: /usr/staff/martinh/tcpview/RCS/callbacks.c,v 1.2 1993/04/22 20:14:10 martinh Exp martinh $ (UW)";
#endif
#include <stdio.h>
#ifdef __STDC__
#include <stdlib.h>
#endif
#include <stdarg.h>
#include <sys/types.h>
#include <sys/time.h>
#include <string.h>
#include <errno.h>
#include <net/bpf.h>
#include "interface.h"
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <Xm/Xm.h>
#include <Xm/FileSB.h>
#include <Xm/MessageB.h>
#include <Xm/List.h>
#include <Xm/Text.h>
#include "tcpview.h"
#include "filter.h"
#include "motif.h"
extern Widget summary_list_widget; /* summary (top) window */
extern Widget detail_list_widget; /* detail (middle) window */
extern Widget hex_text_widget; /* hex (bottom) window */
extern Widget packet_label;
extern __const char *__const sys_errlist[];
#ifdef __STDC__
void redisplay_current_list(void);
void print2hexwindow (char *);
static void setpackets (void);
void readfile(char *);
void xperror( char *);
int sniff_next_packet(struct packet_header *, u_char *, int);
void redisplay_entire_list(void);
struct bpf_program *parse(char *, int, int, u_long); /* gencode.c */
void (*lookup_printer(int))();
static void do_detail( int );
u_int bpf_filter(register struct bpf_insn *, register u_char *, u_int, register u_int );
void hd(u_char *, u_char *, int);
#else
void redisplay_current_list();
void print2hexwindow ();
void setpackets ();
void readfile();
void xperror();
int sniff_next_packet();
void redisplay_entire_list();
struct bpf_program *parse(); /* gencode.c */
void (*lookup_printer())();
static void do_detail();
u_int bpf_filter();
void hd();
#endif /* __STDC__ */
int errno;
/* these are set when files are read in */
int Linktype;
long thiszone;
int snaplen=DEFAULT_SNAPLEN;
int Precision;
struct printer {
void (*f)();
int type;
};
static struct printer printers[] = {
{ ether_if_print, DLT_EN10MB },
{ sl_if_print, DLT_SLIP },
{ ppp_if_print, DLT_PPP },
{ fddi_if_print, DLT_FDDI },
{ null_if_print, DLT_NULL },
{ 0, 0 },
};
void (*PrintIt)();
struct bpf_insn *Fcode;
struct packet_list {
struct packet_header hdr;
u_char *buf;
struct packet_list *next;
};
static struct packet_list *PacketList=NULL; /* always points to start of the list */
static struct packet_list **PL=NULL;
u_long Packet_Count=0; /* total number of packets */
u_long Current_Packets=0; /* number of packets currently displayed */
static XmString *LList=NULL; /* list for summary widget. size is Packet_Count */
static long CurrP = -1; /* number of the currently selected packet */
extern char FileName1[]; /* current file name */
static u_short DetailHeaders[10]; /* list of header line numbers in detail window */
static u_short Header = 0; /* current header number in detail window */
static u_short NumHeaders = 0; /* number of headers in detail window */
static u_short HeaderOffset = 0; /* current offset in header window */
/* track highlighting in hex window */
static int highlight[64][2];
static int numhigh=0;
void summary_list_callback( widget, client_data, list_data )
Widget widget;
caddr_t client_data;
XmListCallbackStruct *list_data;
{
struct packet_list *p;
char *s, *t;
static char str[8192], *buffer=NULL;
int len, line_num, num;
XmListDeleteAllItems( detail_list_widget );
CurrP = list_data->item_position-1;
p = PL[CurrP];
StrPtr = str;
Phdr = &(p->hdr);
PrintIt(p->buf,&p->hdr.ts,p->hdr.len,p->hdr.caplen);
StrPtr = str;
detail_ether(p->buf);
num = 0;
line_num = 1;
s=t=str;
len = strlen(str);
while (*t) {
if (*t=='\n') {
*t++ = '\0';
if( !strncmp( s, "-----", 5) )
DetailHeaders[num++] = line_num;
line_num++;
AddToList( detail_list_widget, s, 0);
s=t;
} else
t++;
}
NumHeaders = num;
num = line_num-1; /* number of lines */
/* now update hex window */
if (buffer==NULL)
buffer = (char *)malloc(10000);
hd(buffer,p->buf,p->hdr.caplen);
print2hexwindow(buffer);
/* now highlight proper section of detail window */
if( Header && (Header <= NumHeaders) ) {
line_num = DetailHeaders[Header-1]+HeaderOffset;
if( line_num <= num ) {
do_detail( line_num );
XmListSelectPos(detail_list_widget,line_num,(Boolean)0);
XmListSetPos(detail_list_widget,line_num);
}
}
} /* summary_list_callback */
void detail_list_callback( widget, client_data, list_data )
Widget widget;
caddr_t client_data;
XmListCallbackStruct *list_data;
{
register int i, line;
int header_line=0;
line = list_data->item_position;
/* new detail line, so reset the header and offset */
for(i=0;i<NumHeaders;i++)
if( DetailHeaders[i] <= line )
header_line = DetailHeaders[i];
else
break;
Header = i;
HeaderOffset = line - header_line;
do_detail(line);
}
static void do_detail( line )
int line;
{
register int i;
int n, i1, j1, i2, j2;
int left, right; /* ASCII highlight */
int hexl, hexr; /* hex highlight */
for (i=0;i<numhigh;i++)
XmTextSetHighlight(hex_text_widget,highlight[i][0],
highlight[i][1],XmHIGHLIGHT_NORMAL);
numhigh=0;
n = hex_start(line - 1);
if (n==-1) {
return;
}
i1 = (int)(n/16);
j1 = n%16;
hexl = i1*76 + 6 + j1*3;
left = i1*76 + 59 + j1;
n = hex_stop(line - 1);
i2 = (int)(n/16);
j2 = n%16;
hexr = i2*76 + 5 + (j2+1)*3;
right = i2*76 + 60 + j2;
if(i1==i2) { /* same row */
highlight[numhigh][0] = hexl;
highlight[numhigh++][1] = hexr;
highlight[numhigh][0] = left;
highlight[numhigh++][1] = right;
} else {
highlight[numhigh][0] = hexl;
highlight[numhigh++][1] = i1*76+53;
highlight[numhigh][0] = left;
highlight[numhigh++][1] = i1*76+75;
highlight[numhigh][0] = i2*76+6;
highlight[numhigh++][1] = hexr;
highlight[numhigh][0] = i2*76+59;
highlight[numhigh++][1] = right;
for(i=i1+1;i<i2;i++) {
highlight[numhigh][0] = i*76+6;
highlight[numhigh++][1] = i*76+53;
highlight[numhigh][0] = i*76+59;
highlight[numhigh++][1] = i*76+75;
}
}
for (i=0;i<numhigh;i++)
XmTextSetHighlight(hex_text_widget,highlight[i][0],
highlight[i][1],XmHIGHLIGHT_SELECTED);
} /* do_detail */
static void file_callback( widget, client_data, file_struct )
Widget widget;
caddr_t client_data;
XmFileSelectionBoxCallbackStruct *file_struct;
{
char *string;
XmStringGetLtoR( file_struct->value,
XmSTRING_DEFAULT_CHARSET,
&string );
XtUnmanageChild(widget);
readfile(string);
strcpy(FileName1,string);
XmListDeleteAllItems( detail_list_widget );
XtFree(string);
} /* file_callback */
static Widget filesel;
static void cancel_callback( widget, client_data, file_struct )
Widget widget;
caddr_t client_data;
XmFileSelectionBoxCallbackStruct *file_struct;
{
XtUnmanageChild(filesel);
} /* cancel_callback */
void open_callback( widget, name, call_data )
Widget widget;
char *name;
caddr_t call_data;
{
Widget help;
Arg args[5];
int n=0;
XmString xms;
char temp[128];
*temp=0;
if( *FileName1 ) {
strcpy(temp,FileName1);
if( temp[strlen(FileName1)] == '/')
strcat(temp,"..");
else
strcat(temp,"/..");
xms = XmStringCreateSimple(temp);
XtSetArg( args[n], XmNdirectory, xms); n++;
}
XtSetArg( args[n], XmNtextColumns, 60); n++;
XtSetArg( args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL ); n++;
filesel = XmCreateFileSelectionDialog( widget,"",args,n);
XtAddCallback(filesel, XmNokCallback, file_callback, 0);
XtAddCallback(filesel, XmNcancelCallback, cancel_callback, 0);
help = XmFileSelectionBoxGetChild(filesel,XmDIALOG_HELP_BUTTON);
XtUnmanageChild( help );
XtManageChild( filesel );
if( *temp ) XmStringFree(xms);
} /* open_callback */
void generic_callback( widget, name, call_data )
Widget widget;
char *name;
caddr_t call_data;
{
printf( "Menu choice was [%s]\n", name );
} /* generic_callback */
void free_packet_list()
{
struct packet_list *p;
if( LList ) {
free( LList );
LList = NULL;
}
if (PacketList) {
p=PacketList;
do {
free(p->buf);
free(p);
} while (p=p->next);
free(PL);
PacketList = NULL;
PL = NULL;
Packet_Count = 0;
}
Packet_Count=0;
CurrP = -1;
}
void readfile(filename)
char *filename;
{
struct packet_list *p, *prev;
unsigned char *buf;
int n;
int sniff=0;
int (*next_pack)();
free_packet_list();
n = sf_read_init(filename,&Linktype,&thiszone,&snaplen,&Precision);
if( n == -1 )
return;
if( n>0 ) {
sniff++;
if (sniff_rinit(filename,&Linktype,&thiszone,&snaplen,&Precision)) {
ErrorDialog(summary_list_widget,"error","Unrecognized file format");
return;
}
}
buf = (u_char *)malloc(snaplen);
if( sniff )
next_pack = sniff_next_packet;
else
next_pack = sf_next_packet;
prev = NULL;
while(1) {
p = (struct packet_list *)malloc(sizeof(struct packet_list));
if (next_pack(&p->hdr,buf,snaplen)!=0) {
free(p);
break;
}
p->buf = (u_char *)malloc(p->hdr.caplen);
bcopy(buf,p->buf,p->hdr.caplen);
if (prev==NULL)
PacketList = p;
else
prev->next=p;
p->next=NULL;
prev = p;
Packet_Count++;
};
if( Packet_Count==0 ) {
ErrorDialog(summary_list_widget,"warn","No packets found in file");
return;
}
fprintf(stderr,"%d packets read\n",Packet_Count);
PL = (struct packet_list **)malloc(Packet_Count*4);
PrintIt = lookup_printer(Linktype);
LList = (XmString *)malloc(Packet_Count*sizeof(XmString));
redisplay_entire_list();
}
void redisplay_current_list()
{
struct packet_list *p, **pl;
char str[2048];
register int i, n, cp;
XmString *plist;
if( PacketList == NULL )
return;
XtUnmanageChild(summary_list_widget);
XmListDeleteAllItems( summary_list_widget );
/* pl is the new packet list */
pl = (struct packet_list **)malloc(Packet_Count*4);
plist = LList;
cp = -1;
n = 0;
HighlightPacket=0;
ts_print(0); /* reset */
Fcode = parse(Fstr, 1, Linktype, 0)->bf_insns;
for(i=0;i<Current_Packets;i++) {
p = PL[i];
StrPtr = str;
Phdr = &(p->hdr);
if( bpf_filter(Fcode,p->buf,p->hdr.len,p->hdr.caplen) ) {
PrintIt(p->buf,&p->hdr.ts,p->hdr.len,p->hdr.caplen);
*StrPtr=0;
if( HighlightPacket ) {
*plist++ = XmStringCreate( str, "chset2" );
HighlightPacket = 0;
} else
*plist++ = XmStringCreate( str, "chset1" );
if( i == CurrP)
cp = n;
pl[n++] = p;
}
}
XmListAddItems( summary_list_widget, LList, n, 0 );
Current_Packets = n;
plist = LList;
for(n=0;n<Current_Packets;n++)
XmStringFree( *plist++ );
free(PL);
PL = pl;
setpackets();
XtManageChild(summary_list_widget);
CurrP = cp;
if( cp == -1) {
print2hexwindow("");
XmListDeleteAllItems( detail_list_widget );
} else {
XmListSelectPos( summary_list_widget, CurrP+1, False );
XmListSetPos( summary_list_widget, CurrP+1 );
}
}
void redisplay_entire_list()
{
struct packet_list *p, *cp;
char str[2048];
int n;
XmString *plist;
if( PacketList == NULL )
return;
XtUnmanageChild(summary_list_widget);
XmListDeleteAllItems( summary_list_widget );
if( CurrP >= 0 )
cp = PL[CurrP];
else
cp = (struct packet_list *)-1;
CurrP = -1;
n = 0;
plist = LList;
HighlightPacket=0;
ts_print(0); /* reset */
Fcode = parse(Fstr, 1, Linktype, 0)->bf_insns;
p = PacketList;
do {
StrPtr = str;
Phdr = &(p->hdr);
if( bpf_filter(Fcode,p->buf,p->hdr.len,p->hdr.caplen) ) {
PrintIt(p->buf,&p->hdr.ts,p->hdr.len,p->hdr.caplen);
*StrPtr=0;
if( p == cp )
CurrP = n;
if( HighlightPacket ) {
*plist++ = XmStringCreate( str, "chset2" );
HighlightPacket = 0;
} else
*plist++ = XmStringCreate( str, "chset1" );
PL[n++] = p;
}
} while( p = p->next );
XmListAddItems( summary_list_widget, LList, n, 0 );
Current_Packets = n;
plist = LList;
for(n=0;n<Current_Packets;n++)
XmStringFree( *plist++ );
setpackets();
XtManageChild(summary_list_widget);
if( CurrP<0) {
print2hexwindow("");
XmListDeleteAllItems( detail_list_widget );
} else {
XmListSelectPos( summary_list_widget, CurrP+1, False );
XmListSetPos( summary_list_widget, CurrP+1 );
}
}
void save_entire_list(name, type)
char *name;
u_short type;
{
struct packet_list *p;
p = PacketList;
do {
if( type )
sf_write( p->buf, &(p->hdr.ts), p->hdr.len, p->hdr.caplen);
else
sniff_write( p->buf, &(p->hdr.ts), p->hdr.len, p->hdr.caplen);
} while( p = p->next );
if( type )
sf_write_end();
else
sniff_end("w");
}
void savefile( name, all, type )
char *name;
Boolean all;
u_short type;
{
struct packet_list *p;
register int i;
int sf_write_init();
if( PacketList == NULL || ( all==False && Current_Packets==0 ))
return;
if( type ) {
if( sf_write_init( name, Linktype, thiszone, snaplen, Precision) )
return;
} else {
if( sniff_winit( name, Linktype, thiszone, snaplen, Precision) )
return;
}
if( all==True ) {
save_entire_list(name, type);
return;
}
/* save_current_list */
for(i=0;i<Current_Packets;i++) {
p = PL[i];
if( type )
sf_write( p->buf, &(p->hdr.ts), p->hdr.len, p->hdr.caplen);
else
sniff_write( p->buf, &(p->hdr.ts), p->hdr.len, p->hdr.caplen);
}
if( type )
sf_write_end();
else
sniff_end("w");
}
void print_entire_list(fp, detail, str)
FILE *fp;
u_short detail;
char *str;
{
struct packet_list *p;
if( PacketList == NULL )
return;
ts_print(0); /* reset */
p = PacketList;
do {
StrPtr = str;
Phdr = &(p->hdr);
if( detail )
detail_ether(p->buf);
else
PrintIt(p->buf,&p->hdr.ts,p->hdr.len,p->hdr.caplen);
*StrPtr=0;
fprintf(fp,"%s\n",str);
} while( p = p->next );
fclose(fp);
}
void printfile( name, all, detail )
char *name;
Boolean all;
u_short detail;
{
struct packet_list *p;
register int i;
char str[8192];
FILE *fp;
if( PacketList == NULL || (Current_Packets == 0 && all==False) ) {
iprint("No packets to print");
return;
}
if( name[0] == '-' && name[1] == '\0' )
fp = stdout;
else {
fp = fopen(name,"w");
if( !fp ) {
xperror(name);
return;
}
}
if( all==True ) {
print_entire_list(fp, detail, str);
return;
}
ts_print(0); /* reset */
for(i=0;i<Current_Packets;i++) {
p = PL[i];
StrPtr = str;
Phdr = &(p->hdr);
if( detail )
detail_ether(p->buf);
else
PrintIt(p->buf,&p->hdr.ts,p->hdr.len,p->hdr.caplen);
*StrPtr=0;
fprintf(fp,"%s\n",str);
}
fclose(fp);
}
void print2hexwindow(str)
char *str;
{
static short end=0;
/* turn off any highlighted text */
XmTextSetHighlight(hex_text_widget,0,end,XmHIGHLIGHT_NORMAL);
numhigh = 0;
XmTextSetString( hex_text_widget,str);
end = strlen(str);
}
static void setpackets()
{
char buf[25];
Arg args[3];
XmString ms;
sprintf(buf," %d/%d packets ",Current_Packets,Packet_Count);
ms = XmStringCreateSimple(buf);
XtSetArg( args[0], XmNlabelString, ms );
XtSetValues(packet_label,args,1);
XmStringFree( ms );
}
void xperror(str)
char *str;
{
char *str2, buf[128];
str2 = sys_errlist[errno];
if(str[0]!='\0')
sprintf(buf,"%s: %s\n",str,str2);
else
strcpy(buf,str2);
ErrorDialog(summary_list_widget,"error",buf);
}
void eprintv(char *fmt, va_list ap)
{
char str[128];
(void)vsprintf(str, fmt, ap);
ErrorDialog(summary_list_widget, "error", str);
}
void eprint(char *fmt, ...)
{
va_list args;
va_start(args, fmt);
eprintv(fmt, args);
va_end(args);
}
void iprint(char *fmt, ...)
{
va_list args;
char str[128];
Widget widget;
XmString ms;
Arg a[2];
int n;
va_start(args, fmt);
(void)vsprintf(str,fmt,args);
va_end(args);
ms = XmStringCreateSimple( str );
n=0;
XtSetArg( a[n], XmNmessageString, ms ); n++;
widget = XmCreateInformationDialog(summary_list_widget, "info", a, n );
RemoveDialButton( widget, XmDIALOG_CANCEL_BUTTON );
RemoveDialButton( widget, XmDIALOG_HELP_BUTTON );
XtManageChild(widget);
XmStringFree(ms);
}
void
(*lookup_printer(type))()
int type;
{
struct printer *p;
for (p = printers; p->f; ++p)
if (type == p->type)
return p->f;
eprint("unknown data link type 0x%x", type);
return NULL;
}
syntax highlighted by Code2HTML, v. 0.9.1