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

  1. /*
  2.  * Copyright (c) 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-pf.c,v 1.19 92/06/02 18:56:55 mccanne Exp $ (LBL)";
  24. #endif
  25.  
  26. /*
  27.  * packet filter subroutines for tcpdump
  28.  *    Extraction/creation by Jeffrey Mogul, DECWRL
  29.  *
  30.  * Extracted from tcpdump.c.
  31.  */
  32.  
  33. #include <stdio.h>
  34. #include <netdb.h>
  35. #include <ctype.h>
  36. #include <signal.h>
  37. #include <errno.h>
  38. #include <sys/types.h>
  39. #include <sys/time.h>
  40. #include <sys/timeb.h>
  41. #include <sys/socket.h>
  42. #include <sys/file.h>
  43. #include <sys/ioctl.h>
  44. #include <net/pfilt.h>
  45.  
  46. #include <net/if.h>
  47. #include <netinet/in.h>
  48. #include <netinet/in_systm.h>
  49. #include <netinet/ip.h>
  50. #include <netinet/if_ether.h>
  51. #include <netinet/ip_var.h>
  52. #include <netinet/udp.h>
  53. #include <netinet/udp_var.h>
  54. #include <netinet/tcp.h>
  55. #include <netinet/tcpip.h>
  56. #include <net/bpf.h>
  57.  
  58. #include "interface.h"
  59.  
  60. static    u_long    TotPkts = 0;        /* can't oflow for 79 hrs on ether */
  61. static    u_long    TotDrops = 0;        /* count of dropped packets */
  62. static    long    TotMissed = 0;        /* missed by i/f during this run */
  63. static    long    OrigMissed = -1;    /* missed by i/f before this run */
  64.  
  65. void pfReadError();
  66. static void PrintPFStats();
  67.  
  68. extern int errno;
  69.  
  70. /*
  71.  * BUFSPACE is the size in bytes of the packet read buffer.  Most tcpdump
  72.  * applications aren't going to need more than 200 bytes of packet header
  73.  * and the read shouldn't return more packets than packetfilter's internal
  74.  * queue limit (bounded at 256).
  75.  */
  76. #define BUFSPACE (200*256)
  77.  
  78. void
  79. readloop(cnt, if_fd, fp, printit)
  80.     int cnt;
  81.     int if_fd;
  82.     struct bpf_program *fp;
  83.     void (*printit)();
  84. {
  85.     u_char *p;
  86.     struct bpf_insn *fcode;
  87.     int cc;
  88.     /* This funny declaration forces buf to be properly aligned.
  89.        We really just want a u_char buffer that is BUFSPACE
  90.        bytes large. */
  91.     struct enstamp buf[BUFSPACE / sizeof(struct enstamp)];
  92.  
  93.     fcode = fp->bf_insns;
  94.     while (1) {
  95.         register u_char *bp;
  96.         int buflen, inc;
  97.         struct enstamp stamp;
  98.  
  99.         if ((cc = read(if_fd, (char *)buf, sizeof(buf))) < 0) {
  100.             pfReadError(if_fd, "reader");
  101.         }
  102.         /*
  103.          * Loop through each packet.
  104.          */
  105.         bp = (u_char *)buf;
  106.         while (cc > 0) {
  107.             /* avoid alignment issues here */
  108.             bcopy((char *)bp, (char *)&stamp, sizeof(stamp));
  109.  
  110.             if (stamp.ens_stamplen != sizeof(stamp)) {
  111.                 /* buffer is garbage, treat it as poison */
  112.                 break;
  113.             }
  114.  
  115.             p = bp + stamp.ens_stamplen;
  116.  
  117.             buflen = stamp.ens_count;
  118.             if (buflen > snaplen)
  119.                 buflen = snaplen;
  120.  
  121.             if (bpf_filter(fcode, p, stamp.ens_count, buflen)) { 
  122.                 if (cnt >= 0 && --cnt < 0)
  123.                     goto out;
  124.                 (*printit)(p, &stamp.ens_tstamp,
  125.                        stamp.ens_count, buflen);
  126.             }
  127.             TotPkts++;
  128.             TotDrops += stamp.ens_dropped;
  129.             TotMissed = stamp.ens_ifoverflows;
  130.             if (OrigMissed < 0)
  131.                 OrigMissed = TotMissed;
  132.  
  133.             inc = ENALIGN(buflen + stamp.ens_stamplen);
  134.             cc -= inc;
  135.             bp += inc;
  136.         }
  137.     }
  138.  out:
  139.     wrapup(if_fd);
  140. }
  141.  
  142. /* Call ONLY if read() has returned an error on packet filter */
  143. void
  144. pfReadError(fid, msg)
  145.     int fid;
  146.     char *msg;
  147. {
  148.     if (errno == EINVAL) {    /* read MAXINT bytes already! */
  149.         if (lseek(fid, 0L, 0) < 0) {
  150.             perror("tcpdump: pfReadError/lseek");
  151.             exit(-1);
  152.         }
  153.         else
  154.             return;
  155.     }
  156.     else {
  157.         (void) fprintf(stderr, "tcpdump: ");
  158.         perror(msg);
  159.         exit(-1);
  160.     }
  161. }
  162.  
  163. wrapup(fd)
  164.     int fd;
  165. {
  166.     PrintPFStats();
  167.     (void)close(fd);
  168. }
  169.  
  170. static void
  171. PrintPFStats()
  172. {
  173.     int missed = TotMissed - OrigMissed;
  174.     
  175.     (void)printf("%d packets", TotPkts);
  176.     if (TotDrops)
  177.         (void)printf(" + %d discarded by kernel", TotDrops);
  178.     if (missed)
  179.         (void)printf(" + %d discarded by interface", missed);
  180.     (void)printf("\n");
  181. }
  182.  
  183. int
  184. initdevice(device, pflag, linktype)
  185.     char *device;
  186.     int pflag;
  187.     int *linktype;
  188. {
  189.     struct timeval timeout;
  190.     short enmode;
  191.     int backlog = -1;    /* request the most */
  192.     struct enfilter Filter;
  193.     int if_fd;
  194.     
  195.     if_fd = pfopen(device, 0);
  196.     if (if_fd < 0) {
  197.         (void) fprintf(stderr, "tcpdump: pf open:");
  198.         perror(device);
  199.         error(
  200. "your system may not be properly configured; see \"man packetfilter(4)\"");
  201.     }
  202.  
  203.     /* set timeout */
  204.     timeout.tv_sec = 1;
  205.     timeout.tv_usec = 0;
  206.     if (ioctl(if_fd, EIOCSRTIMEOUT, &timeout) < 0) {
  207.         perror("tcpdump: EIOCSRTIMEOUT");
  208.         exit(-1);
  209.     }
  210.  
  211.     enmode = ENTSTAMP|ENBATCH|ENNONEXCL;
  212.     /* set promiscuous mode if requested */
  213.     if (pflag == 0) {
  214.         enmode |= ENPROMISC;
  215.     }
  216.     if (ioctl(if_fd, EIOCMBIS, &enmode) < 0) {
  217.         perror("tcpdump: EIOCMBIS");
  218.         exit(-1);
  219.     }
  220.  
  221. #ifdef    ENCOPYALL
  222.     /* Try to set COPYALL mode so that we see packets to ourself */
  223.     enmode = ENCOPYALL;
  224.     ioctl(if_fd, EIOCMBIS, &enmode);    /* OK if this fails */
  225. #endif    ENCOPYALL
  226.  
  227.     /* set the backlog */
  228.     if (ioctl(if_fd, EIOCSETW, &backlog) < 0) {
  229.         perror("tcpdump: EIOCSETW");
  230.         exit(-1);
  231.     }
  232.  
  233.     /* set truncation */
  234.     if (ioctl(if_fd, EIOCTRUNCATE, &snaplen) < 0) {
  235.         perror("tcpdump: EIOCTRUNCATE");
  236.         exit(-1);
  237.     }
  238.     /* accept all packets */
  239.     Filter.enf_Priority = 37;    /* anything > 2 */
  240.     Filter.enf_FilterLen = 0;    /* means "always true" */
  241.     if (ioctl(if_fd, EIOCSETF, &Filter) < 0) {
  242.         perror("tcpdump: EIOCSETF");
  243.         exit(-1);
  244.     }
  245.     /*
  246.      * XXX
  247.      * Currently, the Ultrix packet filter supports only Ethernets.
  248.      * Eventually, support for FDDI and PPP (and possibly others) will
  249.      * be added.  At some point, we will have to recode this to do 
  250.      * the EIOCDEVP ioctl to get the ENDT_* type, and then convert 
  251.      * that to a DLT_* type.
  252.      */
  253.     *linktype = DLT_EN10MB;
  254.  
  255.     return(if_fd);
  256. }
  257.