home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 3 / hamradioversion3.0examsandprograms1992.iso / misc / 9q920411 / trace.c < prev    next >
C/C++ Source or Header  |  1991-09-18  |  8KB  |  370 lines

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