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