home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / trace / tcpdump-2.2.1 / pcap-snit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-02  |  6.1 KB  |  259 lines

  1. /*
  2.  * Copyright (c) 1989, 1990 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that: (1) source code distributions
  7.  * retain the above copyright notice and this paragraph in its entirety, (2)
  8.  * distributions including binary code include the above copyright notice and
  9.  * this paragraph in its entirety in the documentation or other materials
  10.  * provided with the distribution, and (3) all advertising materials mentioning
  11.  * features or use of this software display the following acknowledgement:
  12.  * ``This product includes software developed by the University of California,
  13.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14.  * the University nor the names of its contributors may be used to endorse
  15.  * or promote products derived from this software without specific prior
  16.  * written permission.
  17.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20.  */
  21. #ifndef lint
  22. static  char rcsid[] =
  23.     "@(#)$Header: pcap-snit.c,v 1.15 92/06/02 17:57:39 mccanne Exp $ (LBL)";
  24. #endif
  25.  
  26. /*
  27.  * Modifications made to accomodate the new SunOS4.0 NIT facility by
  28.  * Micky Liu, micky@cunixc.cc.columbia.edu, Columbia University in May, 1989.
  29.  * This module now handles the STREAMS based NIT.
  30.  */
  31.  
  32. #include <stdio.h>
  33. #include <netdb.h>
  34. #include <ctype.h>
  35. #include <signal.h>
  36. #include <errno.h>
  37. #include <sys/types.h>
  38. #include <sys/time.h>
  39. #include <sys/timeb.h>
  40. #include <sys/socket.h>
  41. #include <sys/file.h>
  42. #include <sys/ioctl.h>
  43. #include <net/nit.h>
  44.  
  45. /* Sun OS 4.x includes */
  46.  
  47. #include <sys/fcntlcom.h>
  48.  
  49. #include <sys/dir.h>
  50. #include <net/nit_if.h>
  51. #include <net/nit_pf.h>
  52. #include <net/nit_buf.h>
  53. #include <sys/stropts.h>
  54.  
  55. #include <net/if.h>
  56. #include <netinet/in.h>
  57. #include <netinet/in_systm.h>
  58. #include <netinet/ip.h>
  59. #include <netinet/if_ether.h>
  60. #include <netinet/ip_var.h>
  61. #include <netinet/udp.h>
  62. #include <netinet/udp_var.h>
  63. #include <netinet/tcp.h>
  64. #include <netinet/tcpip.h>
  65.  
  66. #include <net/bpf.h>
  67.  
  68. #include "interface.h"
  69.  
  70. /*
  71.  * The chunk size for NIT.  This is the amount of buffering
  72.  * done for read calls.
  73.  */
  74. #define CHUNKSIZE (2*1024)
  75.  
  76. /*
  77.  * The total buffer space used by NIT.
  78.  */
  79. #define BUFSPACE (4*CHUNKSIZE)
  80.  
  81. struct nit_stat {
  82.     int dcount;
  83.     int rcount;
  84. } nstat;
  85.  
  86. static void
  87. snit_stats()
  88. {
  89.     fflush(stdout);
  90.     (void)fprintf(stderr, "%d packets received by filter\n", nstat.rcount);
  91.     (void)fprintf(stderr, "%d packets dropped by kernel\n", nstat.dcount);
  92. }
  93.  
  94. void
  95. readloop(cnt, if_fd, fp, printit)
  96.     int cnt;
  97.     int if_fd;
  98.     struct bpf_program *fp;
  99.     void (*printit)();
  100. {
  101.     u_char buf[CHUNKSIZE];
  102.     int cc;
  103.     int drops;
  104.     struct nit_stat *nsp = &nstat;
  105.     register struct bpf_insn *fcode = fp->bf_insns;
  106.  
  107.     while ((cc = read(if_fd, (char*)buf, sizeof buf)) >= 0) {
  108.         register u_char *bp, *cp, *bufstop;
  109.         struct nit_bufhdr *hdrp;
  110.         struct nit_iftime *ntp;
  111.         struct nit_iflen *nlp;
  112.         struct nit_ifdrops *ndp;
  113.         int caplen;
  114.  
  115.         bp = buf;
  116.         bufstop = buf + cc;
  117.         /*
  118.         * loop through each snapshot in the chunk
  119.         */
  120.         while (bp < bufstop) {
  121.             ++nsp->rcount;
  122.             cp = bp;
  123.             /* get past NIT buffer  */
  124.             hdrp = (struct nit_bufhdr *)cp;
  125.             cp += sizeof(*hdrp);
  126.  
  127.             /* get past NIT timer   */
  128.             ntp = (struct nit_iftime *)cp;
  129.             cp += sizeof(*ntp);
  130.  
  131.             ndp = (struct nit_ifdrops *)cp;
  132.             nsp->dcount = ndp->nh_drops;
  133.             cp += sizeof *ndp;
  134.  
  135.             /* get past packet len  */
  136.             nlp = (struct nit_iflen *)cp;
  137.             cp += sizeof(*nlp);
  138.  
  139.             /* next snapshot        */
  140.             bp += hdrp->nhb_totlen;
  141.  
  142.             caplen = nlp->nh_pktlen;
  143.             if (caplen > snaplen)
  144.                 caplen = snaplen;
  145.  
  146.             if (bpf_filter(fcode, cp, nlp->nh_pktlen, caplen)) {
  147.                 if (cnt >= 0 && --cnt < 0) {
  148.                     wrapup(if_fd);
  149.                     return;
  150.                 }
  151.                 (*printit)(cp, &ntp->nh_timestamp,
  152.                        nlp->nh_pktlen, caplen);
  153.             }
  154.         }
  155.     }
  156.     perror("tcpdump: read");
  157.     exit(-1);
  158. }
  159.  
  160. wrapup(fd)
  161.     int fd;
  162. {
  163.     snit_stats();
  164.     close(fd);
  165. }
  166.  
  167. int
  168. initdevice(device, pflag, linktype)
  169.     char *device;
  170.     int pflag;
  171.     int *linktype;
  172. {
  173.     struct strioctl si;        /* struct for ioctl() */
  174.     struct timeval timeout;        /* timeout for ioctl() */
  175.     struct ifreq ifr;        /* interface request struct */
  176.     u_long if_flags;        /* modes for interface             */
  177.     int  ret;
  178.     int chunksize = CHUNKSIZE;
  179.     int if_fd;
  180.     char *dev = "/dev/nit";
  181.  
  182.     if (snaplen < 96)
  183.         /*
  184.          * NIT requires a snapshot length of at least 96.
  185.          */
  186.         snaplen = 96;
  187.  
  188.     if ((if_fd = open(dev, O_RDONLY)) < 0) {
  189.         (void) fprintf(stderr, "tcpdump: open: ");
  190.         perror(dev);
  191.         exit(-1);
  192.     }
  193.  
  194.     /* arrange to get discrete messages from the STREAM and use NIT_BUF */
  195.     ioctl(if_fd, I_SRDOPT, (char*)RMSGD);
  196.     ioctl(if_fd, I_PUSH, "nbuf");
  197.  
  198.     /* set the timeout */
  199.     si.ic_timout = INFTIM;
  200.     timeout.tv_sec = 1;
  201.     timeout.tv_usec = 0;
  202.     si.ic_cmd = NIOCSTIME;
  203.     si.ic_len = sizeof(timeout);
  204.     si.ic_dp = (char*)&timeout;
  205.     if ((ret = ioctl(if_fd, I_STR, (char*)&si)) < 0) {
  206.         perror("tcpdump: NIOCSTIME");
  207.         exit(-1);
  208.     }
  209.  
  210.     /* set the chunksize */
  211.     si.ic_cmd = NIOCSCHUNK;
  212.     si.ic_len = sizeof(chunksize);
  213.     si.ic_dp = (char*)&chunksize;
  214.     if ((ret = ioctl(if_fd, I_STR, (char*)&si)) < 0) {
  215.         perror("tcpdump: NIOCSCHUNK");
  216.         exit(-1);
  217.     }
  218.  
  219.     /* request the interface */
  220.     strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
  221.     ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = ' ';
  222.     si.ic_cmd = NIOCBIND;
  223.     si.ic_len = sizeof(ifr);
  224.     si.ic_dp = (char*)𝔦
  225.     if ((ret = ioctl(if_fd, I_STR, (char*)&si)) < 0) {
  226.         (void) fprintf(stderr, "tcpdump: NIOCBIND");
  227.         perror(ifr.ifr_name);
  228.         exit(1);
  229.     }
  230.  
  231.     /* set the snapshot length */
  232.     si.ic_cmd = NIOCSSNAP;
  233.     si.ic_len = sizeof(snaplen);
  234.     si.ic_dp = (char*)&snaplen;
  235.     if ((ret = ioctl(if_fd, I_STR, (char*)&si)) < 0) {
  236.         perror("tcpdump: NIOCSSNAP");
  237.         exit(1);
  238.     }
  239.  
  240.     /* set the interface flags */
  241.     si.ic_cmd = NIOCSFLAGS;
  242.     if_flags = NI_TIMESTAMP | NI_LEN | NI_DROPS;
  243.     if (pflag == 0)
  244.         if_flags |= NI_PROMISC;
  245.     si.ic_len = sizeof(if_flags);
  246.     si.ic_dp = (char*)&if_flags;
  247.     if ((ret = ioctl(if_fd, I_STR, (char*)&si)) < 0) {
  248.         perror("tcpdump: NIOCSFLAGS");
  249.         exit(1);
  250.     }
  251.     ioctl(if_fd, I_FLUSH, (char*)FLUSHR);
  252.     /*
  253.      * NIT supports only ethernets.
  254.      */
  255.     *linktype = DLT_EN10MB;
  256.  
  257.     return if_fd;
  258. }
  259.