home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1893 / ntrace.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-28  |  6.6 KB  |  327 lines

  1. /*
  2.  * ntrace.c
  3.  *
  4.  * Collects (source,dest) traces on Ethernet
  5.  *
  6.  * Usage:
  7.  *    ntrace ifname [-debug] [-multicast] [-broadcast] [-w filename]
  8.  *    
  9.  *    INTR to get current stats
  10.  *    QUIT to get out
  11.  *
  12.  */
  13.  
  14. #include <sys/types.h>
  15. #include <sys/time.h>
  16. #include <sys/socket.h>
  17. #include <net/if.h>
  18. #include <net/pfilt.h>
  19. #include <netinet/in_systm.h>
  20. #include <netinet/in.h>
  21. #include <netinet/ip.h>
  22. #include <netinet/tcp.h>
  23. #include <netinet/udp.h>
  24. #include <netinet/if_ether.h>
  25. #include <signal.h>
  26. #include <stdio.h>
  27. #include <errno.h>
  28. #include <arpa/inet.h>
  29. #include "ntrace.h"
  30.  
  31. #define    TRUNCATION    (sizeof(struct ether_header) + \
  32.              sizeof(struct ip) + \
  33.              sizeof(struct tcphdr))
  34.  
  35. float atof();
  36.  
  37. int MulticastOnly = 0;
  38. int BroadcastOnly = 0;
  39. int debug = 0;
  40. int Writing = 0;
  41.  
  42. int TotDrops = 0;
  43. int TotMissed = 0;
  44. int Complex = 0;
  45. int Counted = 0;
  46.  
  47. int dumpf = 0;
  48.  
  49. long StartTime;
  50.  
  51. /* signal mask: ignore everything but SIGQUIT when this is set */
  52. #define    SMASK    (0xFFFF & ~(1<<(SIGQUIT-1)))
  53.  
  54. void catcher()
  55. {
  56.     printf("\n");    /* after the ^C */
  57.     DoStats(1);
  58. }
  59.  
  60. void dostats()
  61. {
  62.     DoStats(0);
  63. }
  64.  
  65. int olddrops = -1;
  66. int oldmissed = 0;
  67.  
  68. DoStats(force)
  69. int force;
  70. {
  71.     if (force || (TotDrops > olddrops) || (TotMissed > oldmissed)) {
  72.         printf("Drops %d Missed %d ", TotDrops, TotMissed);
  73.         olddrops = TotDrops;
  74.         oldmissed = TotMissed;
  75.         printf("Complex %d Counted %d\n", Complex, Counted);
  76.     }
  77. }
  78.  
  79. void GoAway()
  80. {
  81.     printf("\n");
  82.     DoStats(1);
  83.     exit(1);
  84. }
  85.  
  86. main(argc, argv)
  87. int argc;
  88. char **argv;
  89. {
  90.     char *ifname = argv[1];
  91.     struct sigvec svec;
  92.     register int i;
  93.     struct itimerval itval;
  94.     int EtherFid;
  95.  
  96.     DoOptions((argc - 2), &(argv[2]));
  97.  
  98.     svec.sv_handler = catcher;
  99.     svec.sv_mask = SMASK;
  100.     svec.sv_onstack = 0;
  101.     sigvec(SIGINT, &svec, 0);
  102.  
  103.     svec.sv_handler = GoAway;
  104.     svec.sv_mask = SMASK;
  105.     svec.sv_onstack = 0;
  106.     sigvec(SIGQUIT, &svec, 0);
  107.  
  108.     svec.sv_handler = dostats;
  109.     svec.sv_mask = SMASK;
  110.     svec.sv_onstack = 0;
  111.     sigvec(SIGALRM, &svec, 0);
  112.  
  113.     StartTime = time(0);
  114.  
  115.     EtherFid = StartEther(ifname, MulticastOnly, BroadcastOnly);
  116.  
  117.     itval.it_interval.tv_usec = 0;
  118.     itval.it_interval.tv_sec = 1;
  119.     itval.it_value.tv_usec = 0;
  120.     itval.it_value.tv_sec = 1;
  121.     setitimer(ITIMER_REAL, &itval, 0);
  122.  
  123.     RecvLoop(EtherFid);
  124. }
  125.  
  126. char buffer[1600*256];    /* big enough */
  127.  
  128. RecvLoop(EtherFid)
  129. int EtherFid;
  130. {
  131.     register int buflen;
  132.     register int stamplen;
  133.     register int pktlen;
  134.     register char *bufp;
  135.     int truncation;
  136.     
  137.     truncation = TRUNCATION;
  138.     if (ioctl(EtherFid, EIOCTRUNCATE, &truncation) < 0)
  139.         perror("ioctl/truncate");
  140.  
  141.     while (1) {
  142.         buflen = read(EtherFid, buffer, (sizeof(buffer)-20));
  143.         bufp = buffer;
  144.         if (buflen < 0) {
  145.             PFReadError(EtherFid, "reader");
  146.         }
  147.         else if (buflen == 0)
  148.             continue;
  149.         else {
  150.             while (buflen > 0) {
  151.             struct enstamp *stp = (struct enstamp *)bufp;
  152.  
  153.                 stamplen = stp->ens_stamplen;
  154.             if (stamplen != sizeof(struct enstamp)) {
  155.                 fprintf(stderr, "dropping bad stamp\n");
  156.                 buflen = -1;
  157.             }
  158.             else {
  159.                 pktlen = stp->ens_count;
  160.                 TraceIt(&(stp->ens_tstamp), pktlen,
  161.                     &(bufp[stamplen]));
  162.                 TotDrops += stp->ens_dropped;
  163.                 TotMissed = stp->ens_ifoverflows;
  164.                 if (pktlen > truncation)
  165.                 pktlen = truncation;
  166.                 if (buflen == (pktlen + stamplen))
  167.                     break;
  168.                 pktlen = ENALIGN(pktlen);
  169.                 buflen -= (pktlen + stamplen);
  170.                 bufp += (pktlen + stamplen);
  171.             }
  172.             }
  173.             if (buflen < 0)
  174.                printf(
  175.                 "Warning: part of one or more packets dropped\n");
  176.         }
  177.     }
  178. }
  179.  
  180. DoOptions(optc, optv)
  181. int optc;
  182. char **optv;
  183. {
  184.     while (optc > 0) {
  185.         if (optv[0][0] == '-') {
  186.         switch (optv[0][1]) {
  187.         
  188.         case 'm':
  189.             MulticastOnly++;
  190.             break;
  191.  
  192.         case 'b':
  193.             BroadcastOnly++;
  194.             break;
  195.  
  196.         case 'd':
  197.             debug++;
  198.             break;
  199.  
  200.         case 'w':
  201.             if (optc < 2) {
  202.                 fprintf(stderr,
  203.                         "-w takes a file name argument\n");
  204.                 exit(1);
  205.             }
  206.             optc--;
  207.             optv++;
  208.             dumpf = creat(optv[0], 0666);
  209.             if (dumpf < 0) {
  210.                 perror(optv[0]);
  211.                 exit(1);
  212.             }
  213.             Writing++;
  214.             break;
  215.  
  216.         default:
  217.             fprintf(stderr, "Unknown option %s\n", optv[0]);
  218.         }
  219.         }
  220.         optc--;
  221.         optv++;
  222.     }
  223. }
  224.  
  225. #define    BUFITEMS    1024
  226. struct NetTrace nettrace[BUFITEMS];
  227. struct NetTrace *ntcur = nettrace;
  228. struct NetTrace *ntend = &(nettrace[BUFITEMS]);
  229.  
  230. TraceIt(tvp, len, bufp)
  231. struct timeval *tvp;
  232. int len;
  233. char *bufp;
  234. {
  235.     struct ether_header *ehp;
  236.     struct ip *ipp;
  237.     struct tcphdr *tcpp;
  238.     struct udphdr *udpp;
  239.     int remlen;
  240.     char *ipdata;
  241.     struct NetTrace *ntp = ntcur;
  242.  
  243.     ehp = (struct ether_header *)bufp;
  244.     
  245.     if (ehp->ether_type != ntohs(ETHERTYPE_IP)) {
  246. /*        printf("Not IP %x\n", ehp->ether_type); */
  247.         return;
  248.     }
  249.  
  250.     remlen = len - (sizeof(*ehp) + sizeof(*ipp));
  251.     if (remlen < 0) {
  252.         printf("Runt, len %d\n", len);
  253.         return;
  254.     }
  255.     ipp = (struct ip *)&(bufp[sizeof(*ehp)]);
  256.     ipdata = &(bufp[(sizeof(*ehp) + sizeof(*ipp))]);
  257.     if (ipp->ip_hl != 5) {
  258.         Complex++;
  259.         printf("Options present, hl %d\n", ipp->ip_hl);
  260.         return;
  261.     }
  262.     if (ipp->ip_off) {
  263. /*        printf("Not first frag, off %d\n", ntohs(ipp->ip_off)); */
  264.         return;
  265.     }
  266.     
  267.     /* looks like a keeper? */
  268.     ntp->nt_timestamp = *tvp;
  269. #ifdef    vax
  270.     ntp->nt_srcaddr = ipp->ip_src;
  271.     ntp->nt_dstaddr = ipp->ip_dst;
  272. #else
  273.     /* possible unaligned access */
  274.     ntp->nt_srcaddr.S_un.S_un_b.s_b1 = ipp->ip_src.S_un.S_un_b.s_b1;
  275.     ntp->nt_srcaddr.S_un.S_un_b.s_b2 = ipp->ip_src.S_un.S_un_b.s_b2;
  276.     ntp->nt_srcaddr.S_un.S_un_b.s_b3 = ipp->ip_src.S_un.S_un_b.s_b3;
  277.     ntp->nt_srcaddr.S_un.S_un_b.s_b4 = ipp->ip_src.S_un.S_un_b.s_b4;
  278.     ntp->nt_dstaddr.S_un.S_un_b.s_b1 = ipp->ip_dst.S_un.S_un_b.s_b1;
  279.     ntp->nt_dstaddr.S_un.S_un_b.s_b2 = ipp->ip_dst.S_un.S_un_b.s_b2;
  280.     ntp->nt_dstaddr.S_un.S_un_b.s_b3 = ipp->ip_dst.S_un.S_un_b.s_b3;
  281.     ntp->nt_dstaddr.S_un.S_un_b.s_b4 = ipp->ip_dst.S_un.S_un_b.s_b4;
  282. #endif    vax
  283.     ntp->nt_proto = ipp->ip_p;
  284.     
  285.     switch (ipp->ip_p) {
  286.     case IPPROTO_UDP:
  287.         if (remlen < sizeof(*udpp)) {
  288.         printf("Runt UDP header (%d short)\n",
  289.             sizeof(*udpp) - remlen);
  290.         return;
  291.         }
  292.         udpp = (struct udphdr *)ipdata;
  293.         ntp->nt_srcport = udpp->uh_sport;
  294.         ntp->nt_dstport = udpp->uh_dport;
  295.         break;
  296.     case IPPROTO_TCP:
  297.         if (remlen < sizeof(*tcpp)) {
  298.         printf("Runt TCP header (%d short)\n",
  299.             sizeof(*tcpp) - remlen);
  300.         return;
  301.         }
  302.         tcpp = (struct tcphdr *)ipdata;
  303.         ntp->nt_srcport = tcpp->th_sport;
  304.         ntp->nt_dstport = tcpp->th_dport;
  305.         break;
  306.     /* known but not handled protocols: */
  307.     case IPPROTO_ICMP:
  308.         return;
  309.     default:
  310.         printf("Unknown protocol %d\n", ipp->ip_p);
  311.         return;
  312.     }
  313.     
  314.     Counted++;
  315.     if (debug)
  316.         PrintNetTrace(ntp);
  317.     if (ntcur++ >= ntend) {
  318.         if (Writing)
  319.         if (write(dumpf, nettrace, sizeof(nettrace))
  320.                          < sizeof(nettrace)) {
  321.             perror("writing trace buffer");
  322.             exit(1);
  323.         }
  324.         ntcur = nettrace;
  325.     }
  326. }
  327.