P8000/WEGA/contrib/K5JB/trace.c

413 lines
8.5 KiB
C

/* corrected some spurious prints to the screen when tracing to file and
* made timestamping switchable option. See TRACE_TIME in options.h - K5JB
*/
#include "config.h"
#include "options.h"
#ifdef TRACE
#include <stdio.h>
#include <ctype.h>
#include "global.h"
#include "mbuf.h"
#include "iface.h"
#include "trace.h"
#include "session.h"
#include "ax25.h" /* K5JB - all the following includes to eliminate */
#include "timer.h" /* undefined structure warnings */
#include "nr4.h"
#include "netuser.h"
#include "tcp.h"
#include "finger.h"
#include "lapb.h"
#include "telnet.h"
#include "ftp.h"
#include <string.h>
#ifdef _OSK
#include <time.h>
#endif
/* Redefined here so that programs calling dump in the library won't pull
* in the rest of the package
*/
static char nospace[] = "No space!!\n";
static char nullpak[] = "empty packet!!\n";
#ifdef TRACE_TIME
static char if_tr_i[] = "\n%s recv: [%s]\n";
static char if_tr_o[] = "\n%s sent: [%s]\n";
#else
static char if_tr_i[] = "\n%s recv:\n";
static char if_tr_o[] = "\n%s sent:\n";
#endif
char howtotrace[] = {
"Usage: trace [allmode|cmdmode|info_only]\n or <iface> <flags>\n or loopback <flags>\n or to <file>|console\n"
};
FILE *trfp = stdout; /* file pointer used for tracing */
int trcount = 0; /* used to close file for flushing */
char trname[40]; /* name if not stdout */
int notraceall; /* 0 = trace all, 1 = only in cmd mode */
extern int mode; /* command mode or not */
/* Protocol tracing function pointers */
void ax25_dump(),ether_dump(),ip_dump();
void (*tracef[])() = { /* must be in same order as in trace.h */
#ifdef AX25
ax25_dump,
#else
NULLVFP,
#endif
#ifdef ETHER
ether_dump,
#else
NULLVFP,
#endif
ip_dump
};
/* Dummy structure for loopback tracing */
struct interface loopback = {
NULLIF, "loopback"
};
#ifndef NO_INFO_CMD /* default is to have trace info_only command */
#ifdef TRACE_TIME
char axtrhdr[48]; /* should only need 41 */
#else
char axtrhdr[16]; /* should only need 13 */
#endif
int info_only = 1; /* default on (no supv frames) */
#endif
/* Display the trace flags for a particular interface */
static void
showtrace(ifp)
register struct interface *ifp;
{
char *tracingon = "Tracing on ";
if(ifp == NULLIF)
return;
if(!(ifp->trace & (IF_TRACE_IN | IF_TRACE_OUT)))
printf("%s%s: off\n",tracingon,ifp->name);
else
printf("%s%s:%s%s %s\n",tracingon,ifp->name,
ifp->trace & IF_TRACE_IN ? " input" : "",
ifp->trace & IF_TRACE_OUT ? " output" : "",
ifp->trace & IF_TRACE_HEX ? "(Hex/ASCII dump)" :
ifp->trace & IF_TRACE_ASCII ? "(ASCII dump)" : "(headers only)");
fflush(stdout);
}
int
dotrace(argc,argv)
int argc;
char *argv[];
{
struct interface *ifp;
int htoi();
if(argc < 2){
#ifndef NO_INFO_CMD
printf("Info_only trace is %s\n",info_only ? "on" : "off");
#endif
printf("Trace mode is %s\nTrace to %s\n",
notraceall ? "cmdmode" : "allmode",trfp == stdout ? "console" : trname);
showtrace(&loopback);
for(ifp = ifaces; ifp != NULLIF; ifp = ifp->next)
showtrace(ifp);
return 0;
}
for(ifp = ifaces; ifp != NULLIF; ifp = ifp->next)
if(strcmp(ifp->name,argv[1]) == 0)
break;
if(ifp == NULLIF && argv[1][0] == 'l') /* loopback? */
ifp = &loopback;
if(ifp != NULLIF){
if(argc < 3)
showtrace(ifp);
else
ifp->trace = htoi(argv[2]);
return 0;
}
switch(argv[1][0]){
case 'c': /* cmdmode */
notraceall = 1;
break;
case 'a': /* allmode */
notraceall = 0;
break;
#ifndef NO_INFO_CMD
case 'i':
info_only = !info_only;
break;
#endif
case 't': /* to */
if(argc < 3)
printf("trace to %s\n",trfp == stdout? "console" : trname);
else{
if(trfp != stdout)
fclose(trfp);
if(strncmp(argv[2],"con",3) == 0)
trfp = stdout;
else {
#ifdef MSDOS /* K5JB - fix tracefile treatment of \n */
if((trfp = fopen(argv[2],"at")) == NULLFILE)
#else
if((trfp = fopen(argv[2],"a")) == NULLFILE)
#endif
{
printf("%s: cannot open\n",argv[2]);
trfp = stdout;
return -1;
}
}
strcpy(trname,argv[2]);
} /* else */
break;
default:
printf("Interface %s unknown\n",argv[1]);
return -1;
}
return 0;
}
void
dump(interface,direction,type,bp)
register struct interface *interface;
int direction;
unsigned type;
struct mbuf *bp;
{
struct mbuf *tbp;
void ascii_dump(),hex_dump();
void (*func)();
#ifdef TRACE_TIME
char *cp;
long t;
#endif
char *errmsg = "";
int16 size;
void rip();
if((interface->trace & direction) == 0)
return; /* Nothing to trace */
if (notraceall && mode != CMD_MODE)
return; /* No trace while in session, if mode */
if(bp == NULLBUF || (size = len_mbuf(bp)) == 0)
return;
#ifdef TRACE_TIME
time(&t); /* DG2KK: get time */
cp = ctime(&t);
rip(cp);
#endif
switch(direction){
case IF_TRACE_IN:
#ifndef NO_INFO_CMD
#ifdef TRACE_TIME
sprintf(axtrhdr,if_tr_i,interface->name,cp);
#else
sprintf(axtrhdr,if_tr_i,interface->name);
#endif
break;
case IF_TRACE_OUT:
#ifdef TRACE_TIME
sprintf(axtrhdr,if_tr_o,interface->name,cp);
#else
sprintf(axtrhdr,if_tr_o,interface->name);
#endif
#else /* NO_INFO_CMD */
#ifdef TRACE_TIME
fprintf(trfp,if_tr_i,interface->name,cp);
#else
fprintf(trfp,if_tr_i,interface->name);
#endif
break;
case IF_TRACE_OUT:
#ifdef TRACE_TIME
fprintf(trfp,if_tr_o,interface->name,cp);
#else
fprintf(trfp,if_tr_o,interface->name);
#endif
#endif /* NO_INFO_CMD */
break;
}
if(bp == NULLBUF || (size = len_mbuf(bp)) == 0){
errmsg = nullpak;
goto trdone;
}
if(type < NTRACE)
func = tracef[type];
else
func = NULLVFP;
dup_p(&tbp,bp,0,size);
if(tbp == NULLBUF){
errmsg = nospace;
goto trdone;
}
if(func != NULLVFP)
(*func)(&tbp,1);
#ifndef NO_INFO_CMD
if(info_only && !*axtrhdr){ /* ax25_dump puts null if supv frame */
free_p(tbp);
goto trdone;
}
#endif
if(interface->trace & IF_TRACE_ASCII)
/* Dump only data portion of packet in ascii */
ascii_dump(&tbp);
else if(interface->trace & IF_TRACE_HEX){
/* Dump entire packet in hex/ascii */
free_p(tbp);
dup_p(&tbp,bp,0,len_mbuf(bp));
if(tbp != NULLBUF)
hex_dump(&tbp);
else{
errmsg = nospace; /* will do ugly display but should be rare */
goto trdone;
}
}
free_p(tbp);
trdone:
if(*errmsg){
#ifndef NO_INFO_CMD
fprintf(trfp,axtrhdr);
#endif
fprintf(trfp,errmsg);
}
if(trfp != stdout){
if(errmsg == nospace)
printf(errmsg); /* send to screen too */
fflush(trfp);
#ifdef MSDOS
if (++trcount > 25){
fclose(trfp); /* MS-DOS must close to flush file */
trfp = fopen(trname,"at"); /* fix EOL problem. See also pc.c */
trcount = 0;
}
#endif
/* in Unix version, watch out for this one if we go background */
if(trfp == NULLFILE || ferror(trfp)){
printf("Error on %s, will trace to console\n",trname);
#ifdef OBSCURE
if(trfp != NULLFILE && trfp != stdout)
#else
if(trfp != NULLFILE)
#endif
fclose(trfp);
trfp = stdout;
}
}
fflush(stdout);
}
/* Dump an mbuf in hex */
void
hex_dump(bpp)
register struct mbuf **bpp;
{
int16 n;
int16 address;
void fmtline();
char buf[16];
if(bpp == NULLBUFP || *bpp == NULLBUF)
return;
address = 0;
while((n = pullup(bpp,buf,sizeof(buf))) != 0){
fmtline(address,buf,n);
address += n;
}
}
/* Dump an mbuf in ascii */
void
ascii_dump(bpp)
register struct mbuf **bpp;
{
char c;
register int16 tot;
if(bpp == NULLBUFP || *bpp == NULLBUF)
return;
tot = 0;
while(pullup(bpp,&c,1) == 1){
if((tot % 64) == 0)
fprintf(trfp,"%04x ",tot);
if(isprint(c))
fprintf(trfp,"%c",c); /* was putchar */
else
fprintf(trfp,"."); /* ditto */
tot++;
if((tot % 64) == 0)
fprintf(trfp,"\n");
}
if((tot % 64) != 0)
fprintf(trfp,"\n");
}
/* Print a buffer up to 16 bytes long in formatted hex with ascii
* translation, e.g.,
* 0000: 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 0123456789:;<=>?
*/
void
fmtline(addr,buf,len)
int16 addr;
char *buf;
int16 len;
{
char line[80];
register char *aptr,*cptr;
register int16 c;
#ifdef UNIX
char *memset();
#else
void *memset();
#endif
void ctohex();
memset(line,' ',sizeof(line));
ctohex(line,(int16)hibyte(addr));
ctohex(line+2,(int16)lobyte(addr));
aptr = &line[6];
cptr = &line[55];
while(len-- != 0){
c = *buf++ & 0xff;
ctohex(aptr,c);
aptr += 3;
c &= 0x7f;
*cptr++ = isprint(c) ? c : '.';
}
/* *cptr++ = '\r'; don't need this */
*cptr++ = '\n';
fwrite(line,1,(unsigned)(cptr-line),trfp); /* was stdout - K5JB */
/* added */
}
/* Convert byte to two ascii-hex characters */
static
void
ctohex(buf,c)
register char *buf;
register int16 c;
{
static char hex[] = "0123456789abcdef";
buf[0] = hex[hinibble(c)];
buf[1] = hex[lonibble(c)];
}
#endif /* TRACE */