/*
* 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/filter-dialog.c,v 1.2 1993/03/23 21:50:24 martinh Exp $ (UW)";
#endif
#include <stdio.h>
#include <string.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <Xm/Xm.h>
#include <Xm/Frame.h>
#include <Xm/MessageB.h>
#include <Xm/RowColumn.h>
#include <Xm/SeparatoG.h>
#include <Xm/ToggleB.h>
#include <Xm/BulletinB.h>
#include <Xm/TextF.h>
#include <Xm/SelectioB.h>
#include "tcpview.h"
#include "filter.h"
#include "motif.h"
#include "addrtoname.h"
#define status(x) ( (Filter.protocol & 1<<x) ? (True) : (False) )
#ifdef __STDC__
char *intoa(u_long);
void createpdmenu( Widget, char *, char **, int);
void update_fstr( struct filter *);
int GetEtherList( XmString *, int );
#else
char *intoa();
void createpdmenu();
void update_fstr();
int GetEtherList();
#endif
static Widget bb_widget, Pt[NUM_PROTOS];
static Widget name[4]; /* four names in address filter */
static Widget level[2], arrow[2], include[2], addr_and[2];
static Widget port_widget;
static char *arrowstr[] = { "-->","<->","<--" };
static char *levelstr[] = { "IP", "DLC" };
static char *incstr[] = { "EXCLUDE", "INCLUDE" };
static char *Andstr[] = { "OFF", "AND", "OR" };
static char *Onstr[] = { "OFF", "ON" };
static char filter_ipname[4][64], filter_dlcname[4][64];
static char portstring[64];
struct filter Filter;
void init_filter()
{
int i;
struct address_filter *af;
extern struct timeval Timeout;
Filter.protocol = 0;
Filter.port = 0;
strcpy(portstring,"ANY");
for(i=0;i<2;i++) {
af = &Filter.addr[i];
af->level=1;
strcpy(af->name1,"ANY");
strcpy(af->name2,"ANY");
af->address1[0] = 0;
af->address2[0] = 0;
af->direction = DIR_TO;
af->include = 1;
af->and = 0;
}
for(i=0;i<4;i++) {
strcpy(filter_ipname[i],"ANY");
strcpy(filter_dlcname[i],"ANY");
}
/* initialize timeout value */
Timeout.tv_sec = 1;
Timeout.tv_usec = 0;
}
static void clear_callback( widget, foo, call_data )
Widget widget;
char *foo;
caddr_t call_data;
{
int i;
init_filter();
for(i=0;i<3;i++)
SetLabel(name[i],"ANY");
for(i=0;i<2;i++) {
SetLabel(arrow[i],arrowstr[DIR_TO]);
SetLabel(include[i],incstr[1]);
SetLabel(level[i],levelstr[1]);
SetLabel(addr_and[i],Onstr[0]);
}
for(i=1;i<7;i++)
SetToggle(Pt[i],False);
SetToggle(Pt[0],True);
SetLabel(port_widget,"ANY");
}
static
void my_callback( widget, name, call_data )
Widget widget;
char *name;
caddr_t call_data;
{
XtUnrealizeWidget( bb_widget );
} /* my_callback */
static void current_callback( widget, name, call_data )
Widget widget;
char *name;
caddr_t call_data;
{
extern void redisplay_current_list();
XtUnrealizeWidget( bb_widget );
update_fstr( &Filter );
redisplay_current_list();
} /* current_callback */
static void all_callback( widget, name, call_data )
Widget widget;
char *name;
caddr_t call_data;
{
extern void redisplay_entire_list();
/* turn off highlighting */
HighlightTimeout = 0;
XtUnrealizeWidget( bb_widget );
update_fstr( &Filter );
redisplay_entire_list();
} /* all_callback */
static
void sel_callback( parent, data, cd )
Widget parent;
caddr_t data;
XmSelectionBoxCallbackStruct *cd;
{
char *string, *str, buf[64];
int d;
char *GetEtherFromName();
d = (int)data>>1;
XmStringGetLtoR( cd->value, XmSTRING_DEFAULT_CHARSET, &string);
str = string;
if( (int)data & 1 ) { /* address 2 */
if(strcasecmp(string,"ALL") && strcasecmp(string,"ANY") && *string) {
strcpy( Filter.addr[d].name2, string );
if (Filter.addr[d].level == ADDR_DLC) {
strcpy( Filter.addr[d].address2, GetEtherFromName(string) );
if( Filter.addr[d].address2[0] == '\0' ) {
sprintf(buf,"DLC name %s not found",string);
ErrorDialog( parent, "ERROR", buf);
}
} else
strcpy( Filter.addr[d].address2, string );
} else {
strcpy(Filter.addr[d].name2,"ANY");
Filter.addr[d].address2[0] = '\0';
str = "ANY";
}
} else { /* address 1 */
if( strcasecmp(string,"ALL") && strcasecmp(string,"ANY") && *string) {
strcpy( Filter.addr[d].name1, string );
if (Filter.addr[d].level == ADDR_DLC) {
strcpy( Filter.addr[d].address1, GetEtherFromName(string) );
if( Filter.addr[d].address1[0] == '\0' ) {
sprintf(buf,"DLC name %s not found",string);
ErrorDialog( parent, "ERROR", buf);
}
} else
strcpy( Filter.addr[d].address1, string );
} else {
strcpy( Filter.addr[d].name1, "ANY" );
Filter.addr[d].address1[0] = '\0';
str = "ANY";
}
}
SetLabel(name[(int)data], str);
XtFree(string);
}
static
void addr_name_callback( parent, data, call_data )
Widget parent;
caddr_t data;
caddr_t call_data;
{
Widget sel, list;
Arg args[10];
XmString list_items[512], current, label=0;
int d = (int)data;
int n, num=0;
d = d>>1;
n = (int)data & 1;
if( n )
current = XmStringCreateSimple(Filter.addr[d].name2);
else
current = XmStringCreateSimple(Filter.addr[d].name1);
n=0;
if (Filter.addr[d].level == ADDR_DLC) {
num = GetEtherList( list_items, 512);
label = XmStringCreateSimple("DLC Name List");
XtSetArg( args[n], XmNlistLabelString, label ); n++;
XtSetArg( args[n], XmNtextString, current ); n++;
XtSetArg( args[n], XmNlistItems, list_items ); n++;
XtSetArg( args[n], XmNlistItemCount, num ); n++;
sel = XmCreateSelectionDialog(parent,"AddressSelect",args, n);
} else {
sel = XmCreatePromptDialog(parent,"AddressSelect",args,n);
}
XtAddCallback( sel, XmNokCallback, sel_callback, data);
list = XmSelectionBoxGetChild(sel,XmDIALOG_HELP_BUTTON);
XtUnmanageChild(list);
XtManageChild(sel);
for(n=0;n<num;n++)
XmStringFree(list_items[n]);
if( label )
XmStringFree(label);
XmStringFree(current);
} /* addr_name_callback */
static void port_sel_callback( parent, data, cd )
Widget parent;
caddr_t data;
XmSelectionBoxCallbackStruct *cd;
{
char *string, *str, buf[64];
char str1[64], str2[12];
int port, proto;
XmStringGetLtoR( cd->value, XmSTRING_DEFAULT_CHARSET, &string);
if( s_nametoport(string,&port,&proto) )
Filter.port = port;
else
Filter.port = atoi(string);
if( Filter.port ) {
strcpy(portstring,tcpport_string(Filter.port));
strcpy(str1,udpport_string(Filter.port));
if( strcasecmp(portstring,str1) ) {
strcat(portstring," / ");
strcat(portstring,str1);
}
sprintf(str2,"%d",Filter.port);
if( strcmp(portstring,str2) & strcmp(str1,str2) ) {
strcat(portstring," (");
strcat(portstring,str2);
strcat(portstring,")");
}
} else
strcpy(portstring,"ANY");
SetLabel(port_widget, portstring);
XtFree(string);
}
static void port_name_callback( parent, data, call_data )
Widget parent;
caddr_t data;
caddr_t call_data;
{
Widget sel, list;
Arg args[2];
int n=0;
sel = XmCreatePromptDialog(parent,"AddressSelect",args,n);
XtAddCallback( sel, XmNokCallback, port_sel_callback, data);
list = XmSelectionBoxGetChild(sel,XmDIALOG_HELP_BUTTON);
XtUnmanageChild(list);
XtManageChild(sel);
} /* port_name_callback */
static
void addr_dir_callback( widget, data, call_data )
Widget widget;
caddr_t data;
caddr_t call_data;
{
int d = (int)data;
if (Filter.addr[d].direction==2)
Filter.addr[d].direction = 0;
else
Filter.addr[d].direction++;
SetLabel(arrow[d],arrowstr[Filter.addr[d].direction]);
} /* addr_dir_callback */
static
void addr_level_callback( widget, data, call_data )
Widget widget;
caddr_t data;
caddr_t call_data;
{
char *GetEtherFromName();
int d = (int)data;
if(Filter.addr[d].level==ADDR_DLC) {
/* change from DLC to IP */
Filter.addr[d].level = 0;
strcpy( filter_dlcname[d<<1], Filter.addr[d].name1);
strcpy( filter_dlcname[(d<<1)+1], Filter.addr[d].name2);
strcpy( Filter.addr[d].name1, filter_ipname[d<<1] );
strcpy( Filter.addr[d].name2, filter_ipname[(d<<1)+1] );
if( !strcmp(Filter.addr[d].name1, "ANY") )
Filter.addr[d].address1[0] = '\0';
else
strcpy( Filter.addr[d].address1, filter_ipname[d<<1] );
if( !strcmp(Filter.addr[d].name2, "ANY") )
Filter.addr[d].address2[0] = '\0';
else
strcpy( Filter.addr[d].address2, filter_ipname[(d<<1)+1] );
} else {
/* change from IP to to DLC */
Filter.addr[d].level = ADDR_DLC;
/* save ip names */
strcpy( filter_ipname[d<<1], Filter.addr[d].name1);
strcpy( filter_ipname[(d<<1)+1], Filter.addr[d].name2);
strcpy( Filter.addr[d].name1, filter_dlcname[d<<1] );
strcpy( Filter.addr[d].name2, filter_dlcname[(d<<1)+1] );
strcpy( Filter.addr[d].address1, GetEtherFromName(Filter.addr[d].name1) );
strcpy( Filter.addr[d].address2, GetEtherFromName(Filter.addr[d].name2) );
}
SetLabel(level[d],levelstr[Filter.addr[d].level]);
SetLabel(name[(int)data<<1], Filter.addr[d].name1);
SetLabel(name[((int)data<<1)+1], Filter.addr[d].name2);
} /* addr_level_callback */
static
void addr_include_callback( widget, data, call_data )
Widget widget;
caddr_t data;
caddr_t call_data;
{
int d = (int)data;
if(Filter.addr[d].include==0)
Filter.addr[d].include = 1;
else
Filter.addr[d].include = 0;
SetLabel(include[d],incstr[Filter.addr[d].include]);
} /* addr_include_callback */
static
void addr_and_callback( widget, data, call_data )
Widget widget;
caddr_t data;
caddr_t call_data;
{
int d = (int)data;
int i;
int first = 1;
/* first is 1 only if this is the first active toggle */
for(i=0;i<d;i++)
if( Filter.addr[i].and )
first=0;
if( first ) {
/* only allowable states are "ON" and "OFF" */
Filter.addr[d].and++;
if(Filter.addr[d].and>1)
Filter.addr[d].and = 0;
SetLabel(addr_and[d],Onstr[Filter.addr[d].and]);
if(d==0 && Filter.addr[1].and>0)
if( Filter.addr[0].and )
SetLabel(addr_and[1],Andstr[Filter.addr[1].and]);
else {
/* if the second line is 'OR' then change to 'ON' */
if( Filter.addr[1].and==2 )
Filter.addr[1].and=1;
SetLabel(addr_and[1],Onstr[Filter.addr[1].and]);
}
} else {
/* allowable states are "AND", "OR" and "OFF" */
Filter.addr[d].and++;
if(Filter.addr[d].and>2)
Filter.addr[d].and = 0;
SetLabel(addr_and[d],Andstr[Filter.addr[d].and]);
}
} /* addr_and_callback */
static
void proto_callback( widget, data, X_data )
Widget widget;
caddr_t data;
XmToggleButtonCallbackStruct *X_data;
{
int d = (int)data;
/* if ALL then turn off others */
if( d == PROTO_ALL ) {
int i;
Filter.protocol = 0;
for(i=1;i<7;i++)
SetToggle(Pt[i],False);
return;
}
if (X_data->set == True) {
if( Filter.protocol == 0 )
SetToggle(Pt[0],False);
Filter.protocol |= 1<<d;
} else
if (Filter.protocol & 1<<d)
Filter.protocol ^= 1<<d;
}
void FilterDialog (parent, nam, callback)
Widget parent;
char *nam;
void (*callback)();
{
Widget main_row, ok, current, cancel;
Widget frame1, rc1, rc2;
Arg args[10];
int n, i, first;
char *str;
n=0;
XtSetArg( args[n], XmNautoUnmanage, False ); n++;
XtSetArg( args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL ); n++;
bb_widget = XmCreateBulletinBoardDialog (parent,"filter",args,n);
n = 0;
XtSetArg( args[n], XmNorientation, XmVERTICAL ); n++;
main_row = XmCreateRowColumn( bb_widget,"main",args,n);
XtManageChild( main_row );
n=0;
CreateLabelWidget (main_row, "addrfilter","ADDRESS FILTER",args,n);
n=0;
XtSetArg ( args[n], XmNshadowThickness, 4 ); n++;
frame1 = XmCreateFrame (main_row,"frame",args,n);
XtManageChild(frame1);
n = 0;
XtSetArg( args[n], XmNorientation, XmVERTICAL ); n++;
rc1 = XmCreateRowColumn( frame1,"arow1",args,n);
XtManageChild( rc1 );
/* Now do both rows */
first = 1;
for (i=0;i<2;i++) {
n=0;
XtSetArg( args[n], XmNorientation, XmHORIZONTAL ); n++;
rc2 = XmCreateRowColumn( rc1,"arow2",args,n);
XtManageChild( rc2 );
if( first ) {
addr_and[i] = CreateSimpleButton( rc2, Onstr[Filter.addr[i].and],
addr_and_callback, (caddr_t)i);
if( Filter.addr[i].and ) first=0;
} else
addr_and[i] = CreateSimpleButton( rc2, Andstr[Filter.addr[i].and],
addr_and_callback, (caddr_t)i);
level[i] = CreateSimpleButton( rc2, levelstr[Filter.addr[i].level],
addr_level_callback, (caddr_t)i);
str = Filter.addr[i].name1;
name[i+i] = CreateSimpleButton( rc2, str, addr_name_callback,(caddr_t)(i+i) );
arrow[i] = CreateSimpleButton( rc2, arrowstr[Filter.addr[i].direction],
addr_dir_callback, (caddr_t)i);
str = Filter.addr[i].name2;
name[i+i+1] = CreateSimpleButton( rc2, str, addr_name_callback, (caddr_t)(i+i+1) );
include[i] = CreateSimpleButton( rc2, incstr[Filter.addr[i].include],
addr_include_callback, (caddr_t)i);
}
/******** PATTERN FILTER ***********/
#ifdef NOTDEF
CreateLabelWidget (main_row, "patfilter"," PATTERN FILTER ",args,0);
n=0;
XtSetArg ( args[n], XmNshadowThickness, 4 ); n++;
frame1 = XmCreateFrame (main_row,"patframe",args,n);
XtManageChild(frame1);
n = 0;
XtSetArg( args[n], XmNorientation, XmVERTICAL ); n++;
rc1 = XmCreateRowColumn( frame1,"patcol",args,n);
XtManageChild( rc1 );
/*
n = 0;
XtSetArg( args[n], XmNorientation, XmHORIZONTAL ); n++;
rc2 = XmCreateRowColumn( rc1,"patrow",args,n);
XtManageChild( rc2 );
*/
/* These should be textfields */
(void)CreateLabelWidget (rc1, "pattern1","00XX1500 at offset 3B OR ",args,0);
(void)CreateLabelWidget (rc1, "pattern2","10XX1500 at offset 3B ",args,0);
#endif
n=0;
(void)CreateLabelWidget (main_row, "protofilter","PROTOCOL FILTER",args,n);
/* make a frame */
n=0;
XtSetArg ( args[n], XmNshadowThickness, 4 ); n++;
frame1 = XmCreateFrame (main_row,"frame",args,n);
XtManageChild(frame1);
/* create a row column to hold toggle buttons */
n = 0;
XtSetArg( args[n], XmNorientation, XmVERTICAL ); n++;
XtSetArg( args[n], XmNnumColumns, 5 ); n++;
XtSetArg( args[n], XmNpacking, XmPACK_COLUMN ); n++;
rc1 = XmCreateRowColumn(frame1,"protocols",args,n);
Pt[PROTO_ALL] = CreateSimpleToggle (rc1, "ALL",Filter.protocol==PROTO_ALL,
XmONE_OF_MANY,proto_callback, (caddr_t)PROTO_ALL);
Pt[PROTO_ARP] = CreateSimpleToggle (rc1, "ARP",status(PROTO_ARP),
XmN_OF_MANY,proto_callback, (caddr_t)PROTO_ARP);
Pt[PROTO_RARP] = CreateSimpleToggle (rc1, "RARP",status(PROTO_RARP),
XmN_OF_MANY,proto_callback, (caddr_t)PROTO_RARP);
Pt[PROTO_IP] = CreateSimpleToggle (rc1, "IP",status(PROTO_IP),
XmN_OF_MANY,proto_callback, (caddr_t)PROTO_IP);
Pt[PROTO_ICMP] = CreateSimpleToggle (rc1, "ICMP",status(PROTO_ICMP),
XmN_OF_MANY,proto_callback, (caddr_t)PROTO_ICMP);
Pt[PROTO_UDP] = CreateSimpleToggle (rc1, "UDP",status(PROTO_UDP),
XmN_OF_MANY,proto_callback, (caddr_t)PROTO_UDP);
Pt[PROTO_TCP] = CreateSimpleToggle (rc1, "TCP",status(PROTO_TCP),
XmN_OF_MANY,proto_callback, (caddr_t)PROTO_TCP);
XtManageChild ( rc1 );
/* port filter */
n = 0;
XtSetArg( args[n], XmNorientation, XmHORIZONTAL ); n++;
rc1 = XmCreateRowColumn( main_row,"port",args,n);
n=0;
(void)CreateLabelWidget (rc1, "","PORT ",args,n);
port_widget = CreateSimpleButton( rc1, portstring, port_name_callback,(caddr_t)0 );
XtManageChild(rc1);
/* clear button */
CreateSimpleButton(main_row,"CLEAR FILTER",clear_callback,(caddr_t)0);
/***** now do buttons *****/
n = 0;
XtSetArg( args[n], XmNorientation, XmHORIZONTAL ); n++;
rc1 = XmCreateRowColumn( main_row,"buttons",args,n);
ok = CreatePushButton( rc1, "all", "Apply To All" ,args, 0, all_callback );
current = CreatePushButton( rc1, "current", "Apply to Current" ,args, 0, current_callback );
cancel = CreatePushButton( rc1, "cancel", "Cancel" ,args, 0, my_callback );
BulletinDefaultButton( bb_widget, current );
XtManageChild( rc1 );
XtManageChild( bb_widget );
}
static char *dirstr1[] = { "src ","host ","dst " };
static char *dirstr2[] = { "dst ","host ","src " };
static char *andstr[] = { "foo"," and "," or " };
static char *protofstr[] = { "foo","ether proto \\ip ", "ether proto \\arp ",
"ether proto \\rarp ", "ip proto \\icmp ", "ip proto \\udp ",
"ip proto \\tcp " };
char Fstr[256];
void update_fstr( filt )
struct filter *filt;
{
int i, prev=0;
u_long p;
struct address_filter *f;
Fstr[0] = '\0';
for(i=0;i<2;i++) {
f = &filt->addr[i];
if( f->and && (*f->address1 || *f->address2) ) {
if( prev++ && i > 0 )
strcat(Fstr,andstr[f->and]);
if( f->include == 0 )
strcat(Fstr,"not ( ");
if( *f->address1 ) {
if( f->level )
strcat(Fstr,"ether ");
strcat(Fstr,dirstr1[f->direction]);
strcat(Fstr,f->address1);
if( *f->address2)
strcat(Fstr," and ");
}
if( *f->address2 ) {
if( f->level )
strcat(Fstr,"ether ");
strcat(Fstr,dirstr2[f->direction]);
strcat(Fstr,f->address2);
}
if( f->include == 0 )
strcat(Fstr," )");
}
}
/* now for the protocols */
prev = 0;
p = filt->protocol;
if( p != PROTO_ALL ) {
if( *Fstr )
strcat(Fstr," and ");
strcat(Fstr,"( ");
for(i=1;i<NUM_PROTOS;i++) {
if( p & (1<<i) ) {
if( prev++ ) strcat(Fstr,"or ");
strcat(Fstr,protofstr[i]);
}
}
strcat(Fstr,")");
}
/* and finally the port */
if( filt->port ) {
char buf[64];
if( *Fstr) strcat(Fstr," and ");
sprintf(buf,"port %d",filt->port);
strcat(Fstr,buf);
}
/* fprintf(stderr,"Fstr=%s\n",Fstr); */
}
syntax highlighted by Code2HTML, v. 0.9.1