home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 1 / HamRadio.cdr / misc / tcpipsrc / trace.c < prev    next >
C/C++ Source or Header  |  1991-01-26  |  7KB  |  286 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. #include "mbuf.h"
  9. #include "iface.h"
  10. #include "trace.h"
  11. #include "pktdrvr.h"
  12. #include "commands.h"
  13.  
  14. static void ascii_dump __ARGS((FILE *fp,struct mbuf **bpp));
  15. static void ctohex __ARGS((char *buf,int16 c));
  16. static void fmtline __ARGS((FILE *fp,int16 addr,char *buf,int16 len));
  17. static void hex_dump __ARGS((FILE *fp,struct mbuf **bpp));
  18. static void showtrace __ARGS((struct iface *ifp));
  19.  
  20. /* Redefined here so that programs calling dump in the library won't pull
  21.  * in the rest of the package
  22.  */
  23. static char nospace[] = "No space!!\n";
  24.  
  25. void
  26. dump(iface,direction,type,bp)
  27. register struct iface *iface;
  28. int direction;
  29. unsigned type;
  30. struct mbuf *bp;
  31. {
  32.     struct mbuf *tbp;
  33.     void (*func) __ARGS((FILE *,struct mbuf **,int));
  34.     int16 size;
  35.     time_t timer;
  36.     char *cp;
  37.  
  38.     if(iface == NULL || (iface->trace & direction) == 0)
  39.         return;    /* Nothing to trace */
  40.  
  41.     switch(direction){
  42.     case IF_TRACE_IN:
  43.         if((iface->trace & IF_TRACE_NOBC)
  44.          && (Tracef[type].addrtest != NULLFP)
  45.          && (*Tracef[type].addrtest)(iface,bp) == 0)
  46.             return;        /* broadcasts are suppressed */
  47.         time(&timer);
  48.         cp = ctime(&timer);
  49.         cp[24] = '\0';
  50.         fprintf(iface->trfp,"%s  - %s recv:\n",cp,iface->name);
  51.         break;
  52.     case IF_TRACE_OUT:
  53.         time(&timer);
  54.         cp = ctime(&timer);
  55.         cp[24] = '\0';
  56.         fprintf(iface->trfp,"%s - %s sent:\n",cp,iface->name);
  57.         break;
  58.     }
  59.     if(bp == NULLBUF || (size = len_p(bp)) == 0){
  60.         fprintf(iface->trfp,"empty packet!!\n");
  61.         return;
  62.     }
  63.  
  64.     if(type < NCLASS)
  65.         func = Tracef[type].tracef;
  66.     else
  67.         func = NULLVFP;
  68.  
  69.     dup_p(&tbp,bp,0,size);
  70.     if(tbp == NULLBUF){
  71.         fprintf(iface->trfp,nospace);
  72.         return;
  73.     }
  74.     if(func != NULLVFP)
  75.         (*func)(iface->trfp,&tbp,1);
  76.     if(iface->trace & IF_TRACE_ASCII){
  77.         /* Dump only data portion of packet in ascii */
  78.         ascii_dump(iface->trfp,&tbp);
  79.     } else if(iface->trace & IF_TRACE_HEX){
  80.         /* Dump entire packet in hex/ascii */
  81.         free_p(tbp);
  82.         dup_p(&tbp,bp,0,len_p(bp));
  83.         if(tbp != NULLBUF)
  84.             hex_dump(iface->trfp,&tbp);
  85.         else
  86.             fprintf(iface->trfp,nospace);
  87.     }
  88.     free_p(tbp);
  89. }
  90.  
  91. /* Dump packet bytes, no interpretation */
  92. void
  93. raw_dump(iface,direction,bp)
  94. struct iface *iface;
  95. int direction;
  96. struct mbuf *bp;
  97. {
  98.     struct mbuf *tbp;
  99.  
  100.     /* Dump entire packet in hex/ascii */
  101.     fprintf(iface->trfp,"******* raw packet dump (%s %s)\n",
  102.         ((direction & IF_TRACE_OUT) ? "send" : "recv"),iface->name);
  103.     dup_p(&tbp,bp,0,len_p(bp));
  104.     if(tbp != NULLBUF)
  105.         hex_dump(iface->trfp,&tbp);
  106.     else
  107.         fprintf(iface->trfp,nospace);
  108.     fprintf(iface->trfp,"*******\n");
  109.     free_p(tbp);
  110.     return;
  111. }
  112.  
  113. /* Dump an mbuf in hex */
  114. static void
  115. hex_dump(fp,bpp)
  116. FILE *fp;
  117. register struct mbuf **bpp;
  118. {
  119.     int16 n;
  120.     int16 address;
  121.     char buf[16];
  122.  
  123.     if(bpp == NULLBUFP || *bpp == NULLBUF)
  124.         return;
  125.  
  126.     address = 0;
  127.     while((n = pullup(bpp,buf,sizeof(buf))) != 0){
  128.         fmtline(fp,address,buf,n);
  129.         address += n;
  130.     }
  131. }
  132. /* Dump an mbuf in ascii */
  133. static void
  134. ascii_dump(fp,bpp)
  135. FILE *fp;
  136. register struct mbuf **bpp;
  137. {
  138.     int c;
  139.     register int16 tot;
  140.  
  141.     if(bpp == NULLBUFP || *bpp == NULLBUF)
  142.         return;
  143.  
  144.     tot = 0;
  145.     while((c = PULLCHAR(bpp)) != -1){
  146.         if((tot % 64) == 0)
  147.             fprintf(fp,"%04x  ",tot);
  148.         putc(isprint(uchar(c)) ? c : '.',fp);
  149.         if((++tot % 64) == 0)
  150.             fprintf(fp,"\n");
  151.     }
  152.     if((tot % 64) != 0)
  153.         fprintf(fp,"\n");
  154. }
  155. /* Print a buffer up to 16 bytes long in formatted hex with ascii
  156.  * translation, e.g.,
  157.  * 0000: 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f  0123456789:;<=>?
  158.  */
  159. static void
  160. fmtline(fp,addr,buf,len)
  161. FILE *fp;
  162. int16 addr;
  163. char *buf;
  164. int16 len;
  165. {
  166.     char line[80];
  167.     register char *aptr,*cptr;
  168.     register char c;
  169.  
  170.     memset(line,' ',sizeof(line));
  171.     ctohex(line,(int16)hibyte(addr));
  172.     ctohex(line+2,(int16)lobyte(addr));
  173.     aptr = &line[6];
  174.     cptr = &line[55];
  175.     while(len-- != 0){
  176.         c = *buf++;
  177.         ctohex(aptr,(int16)uchar(c));
  178.         aptr += 3;
  179.         c &= 0x7f;
  180.         *cptr++ = isprint(uchar(c)) ? c : '.';
  181.     }
  182.     *cptr++ = '\n';
  183.     fwrite(line,1,(unsigned)(cptr-line),fp);
  184. }
  185. /* Convert byte to two ascii-hex characters */
  186. static void
  187. ctohex(buf,c)
  188. register char *buf;
  189. register int16 c;
  190. {
  191.     static char hex[] = "0123456789abcdef";
  192.  
  193.     *buf++ = hex[hinibble(c)];
  194.     *buf = hex[lonibble(c)];
  195. }
  196.  
  197. /* Modify or displace interface trace flags */
  198. int
  199. dotrace(argc,argv,p)
  200. int argc;
  201. char *argv[];
  202. void *p;
  203. {
  204.     struct iface *ifp;
  205.  
  206.     if(argc < 2){
  207.         for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  208.             showtrace(ifp);
  209.         return 0;
  210.     }
  211.     if((ifp = if_lookup(argv[1])) == NULLIF){
  212.         tprintf("Interface %s unknown\n",argv[1]);
  213.         return 1;
  214.     }
  215.     if(argc >= 3)
  216.         ifp->trace = htoi(argv[2]);
  217.  
  218.     /* Always default to stdout unless trace file is given */
  219.     if(ifp->trfp != NULLFILE && ifp->trfp != stdout)
  220.         fclose(ifp->trfp);
  221.     ifp->trfp = stdout;
  222.     if(ifp->trfile != NULLCHAR)
  223.         free(ifp->trfile);
  224.     ifp->trfile = NULLCHAR;
  225.  
  226.     if(argc >= 4){
  227.         if((ifp->trfp = fopen(argv[3],APPEND_TEXT)) == NULLFILE){
  228.             tprintf("Can't write to %s\n",argv[3]);
  229.             ifp->trfp = stdout;
  230.         } else {
  231.             ifp->trfile = strdup(argv[3]);
  232.         }
  233.     }
  234.     showtrace(ifp);
  235.     return 0;
  236. }
  237. /* Display the trace flags for a particular interface */
  238. static void
  239. showtrace(ifp)
  240. register struct iface *ifp;
  241. {
  242.     if(ifp == NULLIF)
  243.         return;
  244.     tprintf("%s:",ifp->name);
  245.     if(ifp->trace & (IF_TRACE_IN | IF_TRACE_OUT | IF_TRACE_RAW)){
  246.         if(ifp->trace & IF_TRACE_IN)
  247.             tprintf(" input");
  248.         if(ifp->trace & IF_TRACE_OUT)
  249.             tprintf(" output");
  250.  
  251.         if(ifp->trace & IF_TRACE_NOBC)
  252.             tprintf(" - no broadcasts");
  253.  
  254.         if(ifp->trace & IF_TRACE_HEX)
  255.             tprintf(" (Hex/ASCII dump)");
  256.         else if(ifp->trace & IF_TRACE_ASCII)
  257.             tprintf(" (ASCII dump)");
  258.         else
  259.             tprintf(" (headers only)");
  260.  
  261.         if(ifp->trace & IF_TRACE_RAW)
  262.             tprintf(" Raw output");
  263.  
  264.         if(ifp->trfile != NULLCHAR)
  265.             tprintf(" trace file: %s",ifp->trfile);
  266.         tprintf("\n");
  267.     } else
  268.         tprintf(" tracing off\n");
  269. }
  270.  
  271. /* shut down all trace files */
  272. void shuttrace()
  273. {
  274.     struct iface *ifp;
  275.  
  276.         for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next){
  277.                 if(ifp->trfp != NULLFILE && ifp->trfp != stdout)
  278.                         fclose(ifp->trfp);
  279.                 if(ifp->trfile != NULLCHAR)
  280.                         free(ifp->trfile);
  281.                 ifp->trfile = NULLCHAR;
  282.                 ifp->trfp = NULLFILE;
  283.         }
  284. }
  285.  
  286.