home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR3 / KA9Q212.ZIP / TRACE.C < prev    next >
C/C++ Source or Header  |  1993-07-16  |  9KB  |  377 lines

  1. /* Packet tracing - top level and generic routines, including hex/ascii
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4.  
  5. /****************************************************************************
  6. *    $Id: trace.c 1.2 93/07/16 11:51:47 ROOT_DOS Exp $
  7. *    15 Jul 93    1.2        GT    Fix warnings.                                    *
  8. ****************************************************************************/
  9.  
  10. #include <stdio.h>
  11. #include <ctype.h>
  12. #include <time.h>
  13. #include "global.h"
  14. #ifdef    ANSIPROTO
  15. #include <stdarg.h>
  16. #endif
  17. #include "mbuf.h"
  18. #include "iface.h"
  19. #include "pktdrvr.h"
  20. #include "commands.h"
  21. #include "trace.h"
  22. #include "ip.h"
  23.  
  24. static void ascii_dump __ARGS((FILE *fp,struct mbuf **bpp));
  25. static void ctohex __ARGS((char *buf,int16 c));
  26. static void fmtline __ARGS((FILE *fp,int16 addr,char *buf,int16 len));
  27. static void hex_dump __ARGS((FILE *fp,struct mbuf **bpp));
  28. static void showtrace __ARGS((struct iface *ifp));
  29.  
  30. /* Redefined here so that programs calling dump in the library won't pull
  31.  * in the rest of the package
  32.  */
  33. static char nospace[] = "No space!!\n";
  34.  
  35. struct tracecmd Tracecmd[] = {
  36.     { "input",    IF_TRACE_IN,    IF_TRACE_IN },
  37.     { "-input",    0,        IF_TRACE_IN },
  38.     { "output",    IF_TRACE_OUT,    IF_TRACE_OUT },
  39.     { "-output",    0,        IF_TRACE_OUT },
  40.     { "broadcast",    0,        IF_TRACE_NOBC },
  41.     { "-broadcast",    IF_TRACE_NOBC,    IF_TRACE_NOBC },
  42.     { "raw",        IF_TRACE_RAW,    IF_TRACE_RAW },
  43.     { "-raw",        0,        IF_TRACE_RAW },
  44.     { "ascii",    IF_TRACE_ASCII,    IF_TRACE_ASCII|IF_TRACE_HEX },
  45.     { "-ascii",    0,        IF_TRACE_ASCII|IF_TRACE_HEX },
  46.     { "hex",        IF_TRACE_HEX,    IF_TRACE_ASCII|IF_TRACE_HEX },
  47.     { "-hex",        IF_TRACE_ASCII,    IF_TRACE_ASCII|IF_TRACE_HEX },
  48.     { "off",        0,        0xffff },
  49.     { NULLCHAR,    0,        0 }
  50. };
  51.  
  52.  
  53. void
  54. dump(ifp,direction,type,bp)
  55. register struct iface *ifp;
  56. int direction;
  57. unsigned type;
  58. struct mbuf *bp;
  59. {
  60.     struct mbuf *tbp;
  61.     void (*func) __ARGS((FILE *,struct mbuf **,int));
  62.     int16 size;
  63.     time_t timer;
  64.     char *cp;
  65.  
  66.     if(ifp == NULL || (ifp->trace & direction) == 0)
  67.         return;    /* Nothing to trace */
  68.  
  69.     switch(direction){
  70.     case IF_TRACE_IN:
  71.         if((ifp->trace & IF_TRACE_NOBC)
  72.          && (Tracef[type].addrtest != NULLFP)
  73.          && (*Tracef[type].addrtest)(ifp,bp) == 0)
  74.             return;        /* broadcasts are suppressed */
  75.         time(&timer);
  76.         cp = ctime(&timer);
  77.         cp[24] = '\0';
  78.         fprintf(ifp->trfp,"\n%s - %s recv:\n",cp,ifp->name);
  79.         break;
  80.     case IF_TRACE_OUT:
  81.         time(&timer);
  82.         cp = ctime(&timer);
  83.         cp[24] = '\0';
  84.         fprintf(ifp->trfp,"\n%s - %s sent:\n",cp,ifp->name);
  85.         break;
  86.     }
  87.     if(bp == NULLBUF || (size = len_p(bp)) == 0){
  88.         fprintf(ifp->trfp,"empty packet!!\n");
  89.         return;
  90.     }
  91.  
  92.     if(type < NCLASS)
  93.         func = Tracef[type].tracef;
  94.     else
  95.         func = NULLVFP;
  96.  
  97.     dup_p(&tbp,bp,0,size);
  98.     if(tbp == NULLBUF){
  99.         fprintf(ifp->trfp,nospace);
  100.         return;
  101.     }
  102.     if(func != NULLVFP)
  103.         (*func)(ifp->trfp,&tbp,1);
  104.     if(ifp->trace & IF_TRACE_ASCII){
  105.         /* Dump only data portion of packet in ascii */
  106.         ascii_dump(ifp->trfp,&tbp);
  107.     } else if(ifp->trace & IF_TRACE_HEX){
  108.         /* Dump entire packet in hex/ascii */
  109.         free_p(tbp);
  110.         dup_p(&tbp,bp,0,len_p(bp));
  111.         if(tbp != NULLBUF)
  112.             hex_dump(ifp->trfp,&tbp);
  113.         else
  114.             fprintf(ifp->trfp,nospace);
  115.     }
  116.     free_p(tbp);
  117. }
  118.  
  119. /* Dump packet bytes, no interpretation */
  120. void
  121. raw_dump(ifp,direction,bp)
  122. struct iface *ifp;
  123. int direction;
  124. struct mbuf *bp;
  125. {
  126.     struct mbuf *tbp;
  127.  
  128.     /* Dump entire packet in hex/ascii */
  129.     fprintf(ifp->trfp,"\n******* raw packet dump (%s %s)\n",
  130.         ((direction & IF_TRACE_OUT) ? "send" : "recv"),ifp->name);
  131.     dup_p(&tbp,bp,0,len_p(bp));
  132.     if(tbp != NULLBUF)
  133.         hex_dump(ifp->trfp,&tbp);
  134.     else
  135.         fprintf(ifp->trfp,nospace);
  136.     fprintf(ifp->trfp,"*******\n");
  137.     free_p(tbp);
  138.     return;
  139. }
  140.  
  141. /* Dump an mbuf in hex */
  142. static void
  143. hex_dump(fp,bpp)
  144. FILE *fp;
  145. register struct mbuf **bpp;
  146. {
  147.     int16 n;
  148.     int16 address;
  149.     char buf[16];
  150.  
  151.     if(bpp == NULLBUFP || *bpp == NULLBUF)
  152.         return;
  153.  
  154.     address = 0;
  155.     while((n = pullup(bpp,buf,sizeof(buf))) != 0){
  156.         fmtline(fp,address,buf,n);
  157.         address += n;
  158.     }
  159. }
  160. /* Dump an mbuf in ascii */
  161. static void
  162. ascii_dump(fp,bpp)
  163. FILE *fp;
  164. register struct mbuf **bpp;
  165. {
  166.     int c;
  167.     register int16 tot;
  168.  
  169.     if(bpp == NULLBUFP || *bpp == NULLBUF)
  170.         return;
  171.  
  172.     tot = 0;
  173.     while((c = PULLCHAR(bpp)) != -1){
  174.         if((tot % 64) == 0)
  175.             fprintf(fp,"%04x  ",tot);
  176.         putc(isprint(uchar(c)) ? c : '.',fp);
  177.         if((++tot % 64) == 0)
  178.             fprintf(fp,"\n");
  179.     }
  180.     if((tot % 64) != 0)
  181.         fprintf(fp,"\n");
  182. }
  183. /* Print a buffer up to 16 bytes long in formatted hex with ascii
  184.  * translation, e.g.,
  185.  * 0000: 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f  0123456789:;<=>?
  186.  */
  187. static void
  188. fmtline(fp,addr,buf,len)
  189. FILE *fp;
  190. int16 addr;
  191. char *buf;
  192. int16 len;
  193. {
  194.     char line[80];
  195.     register char *aptr,*cptr;
  196.     register char c;
  197.  
  198.     memset(line,' ',sizeof(line));
  199.     ctohex(line,(int16)hibyte(addr));
  200.     ctohex(line+2,(int16)lobyte(addr));
  201.     aptr = &line[6];
  202.     cptr = &line[55];
  203.     while(len-- != 0){
  204.         c = *buf++;
  205.         ctohex(aptr,(int16)uchar(c));
  206.         aptr += 3;
  207.         c &= 0x7f;
  208.         *cptr++ = isprint(uchar(c)) ? c : '.';
  209.     }
  210.     *cptr++ = '\n';
  211.     fwrite(line,1,(unsigned)(cptr-line),fp);
  212. }
  213. /* Convert byte to two ascii-hex characters */
  214. static void
  215. ctohex(buf,c)
  216. register char *buf;
  217. register int16 c;
  218. {
  219.     static char hex[] = "0123456789abcdef";
  220.  
  221.     *buf++ = hex[hinibble(c)];
  222.     *buf = hex[lonibble(c)];
  223. }
  224.  
  225. /* Modify or displace interface trace flags */
  226. int
  227. dotrace(argc,argv,p)
  228. int argc;
  229. char *argv[];
  230. void *p;
  231. {
  232.     struct iface *ifp;
  233.     struct tracecmd *tp;
  234.  
  235.     if(argc < 2){
  236.         for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  237.             showtrace(ifp);
  238.         return 0;
  239.     }
  240.     if((ifp = if_lookup(argv[1])) == NULLIF){
  241.         tprintf("Interface %s unknown\n",argv[1]);
  242.         return 1;
  243.     }
  244.     if(argc == 2){
  245.         showtrace(ifp);
  246.         return 0;
  247.     }
  248.     /* MODIFY THIS TO HANDLE MULTIPLE OPTIONS */
  249.     if(argc >= 3){
  250.         for(tp = Tracecmd;tp->name != NULLCHAR;tp++)
  251.             if(strncmp(tp->name,argv[2],strlen(argv[2])) == 0)
  252.                 break;
  253.         if(tp->name != NULLCHAR)
  254.             ifp->trace = (ifp->trace & ~tp->mask) | tp->val;
  255.         else
  256.             ifp->trace = htoi(argv[2]);
  257.     }
  258.     /* Always default to stdout unless trace file is given */
  259.     if(ifp->trfp != NULLFILE && ifp->trfp != stdout)
  260.         fclose(ifp->trfp);
  261.     ifp->trfp = stdout;
  262.     if(ifp->trfile != NULLCHAR)
  263.         free(ifp->trfile);
  264.     ifp->trfile = NULLCHAR;
  265.  
  266.     if(argc >= 4){
  267.         if((ifp->trfp = fopen(argv[3],APPEND_TEXT)) == NULLFILE){
  268.             tprintf("Can't write to %s\n",argv[3]);
  269.             ifp->trfp = stdout;
  270.         } else {
  271.             ifp->trfile = strdup(argv[3]);
  272.         }
  273.     }
  274.     showtrace(ifp);
  275.     return 0;
  276. }
  277. /* Display the trace flags for a particular interface */
  278. static void
  279. showtrace(ifp)
  280. register struct iface *ifp;
  281. {
  282.     if(ifp == NULLIF)
  283.         return;
  284.     tprintf("%s:",ifp->name);
  285.     if(ifp->trace & (IF_TRACE_IN | IF_TRACE_OUT | IF_TRACE_RAW)){
  286.         if(ifp->trace & IF_TRACE_IN)
  287.             tprintf(" input");
  288.         if(ifp->trace & IF_TRACE_OUT)
  289.             tprintf(" output");
  290.  
  291.         if(ifp->trace & IF_TRACE_NOBC)
  292.             tprintf(" - no broadcasts");
  293.  
  294.         if(ifp->trace & IF_TRACE_HEX)
  295.             tprintf(" (Hex/ASCII dump)");
  296.         else if(ifp->trace & IF_TRACE_ASCII)
  297.             tprintf(" (ASCII dump)");
  298.         else
  299.             tprintf(" (headers only)");
  300.  
  301.         if(ifp->trace & IF_TRACE_RAW)
  302.             tprintf(" Raw output");
  303.  
  304.         if(ifp->trfile != NULLCHAR)
  305.             tprintf(" trace file: %s",ifp->trfile);
  306.         tprintf("\n");
  307.     } else
  308.         tprintf(" tracing off\n");
  309. }
  310.  
  311. /* shut down all trace files */
  312. void
  313. shuttrace()
  314. {
  315.     struct iface *ifp;
  316.  
  317.     for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next){
  318.         if(ifp->trfp != NULLFILE && ifp->trfp != stdout)
  319.             fclose(ifp->trfp);
  320.         if(ifp->trfile != NULLCHAR)
  321.             free(ifp->trfile);
  322.         ifp->trfile = NULLCHAR;
  323.         ifp->trfp = NULLFILE;
  324.     }
  325. }
  326.  
  327. /* Log messages of the form
  328.  * Tue Jan 31 00:00:00 1987 44.64.0.7:1003 open FTP
  329.  */
  330. #if    defined(ANSIPROTO)
  331. void
  332. trace_log(struct iface *ifp,char *fmt, ...)
  333. {
  334.     va_list ap;
  335.     char *cp;
  336.     long t;
  337.  
  338.     if(ifp->trfp == NULLFILE)
  339.         return;
  340.  
  341.     time(&t);
  342.     cp = ctime(&t);
  343.     rip(cp);
  344.     fprintf(ifp->trfp,"%s",cp);
  345.  
  346.     fprintf(ifp->trfp," - ");
  347.     va_start(ap,fmt);
  348.     vfprintf(ifp->trfp,fmt,ap);
  349.     va_end(ap);
  350.     fprintf(ifp->trfp,"\n");
  351. }
  352. #else
  353. /*VARARGS2*/
  354. void
  355. trace_log(ifp,fmt,arg1,arg2,arg3,arg4,arg5)
  356. struct iface *ifp;
  357. char *fmt;
  358. int arg1,arg2,arg3,arg4,arg5;
  359. {
  360.     char *cp;
  361.     long t;
  362.  
  363.     if(ifp->trfp == NULLFILE)
  364.         return;
  365.  
  366.     time(&t);
  367.     cp = ctime(&t);
  368.     rip(cp);
  369.     fprintf(ifp->trfp,"%s",cp);
  370.  
  371.     fprintf(ifp->trfp," - ");
  372.     fprintf(ifp->trfp,fmt,arg1,arg2,arg3,arg4,arg5);
  373.     fprintf(ifp->trfp,"\n");
  374. }
  375. #endif
  376.  
  377.