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