1 /*        $NetBSD: sbpf.c,v 1.1.1.1 2012/03/23 21:20:06 christos Exp $          */
2 
3 /*
4  * (C)opyright 1995-1998 Darren Reed. (from tcplog)
5  *
6  * See the IPFILTER.LICENCE file for details on licencing.
7  *
8  */
9 #include <stdio.h>
10 #include <netdb.h>
11 #include <ctype.h>
12 #include <signal.h>
13 #include <errno.h>
14 #ifdef __NetBSD__
15 # include <paths.h>
16 #endif
17 #include <sys/types.h>
18 #include <sys/param.h>
19 #include <sys/mbuf.h>
20 #include <sys/time.h>
21 #include <sys/timeb.h>
22 #include <sys/socket.h>
23 #include <sys/file.h>
24 #include <sys/ioctl.h>
25 #if BSD < 199103
26 #include <sys/fcntlcom.h>
27 #endif
28 #include <sys/dir.h>
29 #include <net/bpf.h>
30 
31 #include <net/if.h>
32 #include <netinet/in.h>
33 #include <netinet/in_systm.h>
34 #include <netinet/ip.h>
35 #include <netinet/if_ether.h>
36 #include <netinet/ip_var.h>
37 #include <netinet/udp.h>
38 #include <netinet/udp_var.h>
39 #include <netinet/tcp.h>
40 #include <netinet/tcpip.h>
41 #include "ip_compat.h"
42 
43 #ifndef   lint
44 static    char      sbpf[] = "@(#)sbpf.c          1.2 12/3/95 (C)1995 Darren Reed";
45 #endif
46 
47 /*
48 (000) ldh      [12]
49 (001) jeq      #0x800            jt 2   jf 5
50 (002) ldb      [23]
51 (003) jeq      #0x6      jt 4 jf 5
52 (004) ret      #68
53 (005) ret      #0
54 */
55 struct    bpf_insn filter[] = {
56 /* 0. */  { BPF_LD|BPF_H|BPF_ABS,                 0, 0, 12 },
57 /* 1. */  { BPF_JMP|BPF_JEQ,            0, 3, 0x0800 },
58 /* 2. */  { BPF_LD|BPF_B|BPF_ABS,                 0, 0, 23 },
59 /* 3. */  { BPF_JMP|BPF_JEQ,            0, 1, 0x06 },
60 /* 4. */  { BPF_RET,                              0, 0, 68 },
61 /* 5. */  { BPF_RET,                              0, 0, 0 }
62 };
63 /*
64  * the code herein is dervied from libpcap.
65  */
66 static    u_char    *buf = NULL;
67 static    u_int     bufsize = 32768, timeout = 1;
68 
69 
ack_recv(ep)70 int       ack_recv(ep)
71           char      *ep;
72 {
73           struct    tcpiphdr  tip;
74           tcphdr_t  *tcp;
75           ip_t      *ip;
76 
77           ip = (ip_t *)&tip;
78           tcp = (tcphdr_t *)(ip + 1);
79           bcopy(ep + 14, (char *)ip, sizeof(*ip));
80           bcopy(ep + 14 + (ip->ip_hl << 2), (char *)tcp, sizeof(*tcp));
81           if (ip->ip_p != IPPROTO_TCP && ip->ip_p != IPPROTO_UDP)
82                     return -1;
83           if (ip->ip_p & 0x1fff != 0)
84                     return 0;
85           if (0 == detect(ip, tcp))
86                     return 1;
87           return 0;
88 }
89 
90 
readloop(fd,port,dst)91 int       readloop(fd, port, dst)
92           int       fd, port;
93           struct    in_addr dst;
94 {
95           register u_char     *bp, *cp, *bufend;
96           register struct     bpf_hdr   *bh;
97           register int        cc;
98           time_t    in = time(NULL);
99           int       done = 0;
100 
101           while ((cc = read(fd, buf, bufsize)) >= 0) {
102                     if (!cc && (time(NULL) - in) > timeout)
103                               return done;
104                     bp = buf;
105                     bufend = buf + cc;
106                     /*
107                      * loop through each snapshot in the chunk
108                      */
109                     while (bp < bufend) {
110                               bh = (struct bpf_hdr *)bp;
111                               cp = bp + bh->bh_hdrlen;
112                               done += ack_recv(cp);
113                               bp += BPF_WORDALIGN(bh->bh_caplen + bh->bh_hdrlen);
114                     }
115                     return done;
116           }
117           perror("read");
118           exit(-1);
119 }
120 
initdevice(device,tout)121 int       initdevice(device, tout)
122           char      *device;
123           int       tout;
124 {
125           struct    bpf_program prog;
126           struct    bpf_version bv;
127           struct    timeval to;
128           struct    ifreq ifr;
129 #ifdef _PATH_BPF
130           char      *bpfname = _PATH_BPF;
131           int       fd;
132 
133           if ((fd = open(bpfname, O_RDWR)) < 0)
134               {
135                     fprintf(stderr, "no bpf devices available as /dev/bpfxx\n");
136                     return -1;
137               }
138 #else
139           char      bpfname[16];
140           int       fd = -1, i;
141 
142           for (i = 0; i < 16; i++)
143               {
144                     (void) sprintf(bpfname, "/dev/bpf%d", i);
145                     if ((fd = open(bpfname, O_RDWR)) >= 0)
146                               break;
147               }
148           if (i == 16)
149               {
150                     fprintf(stderr, "no bpf devices available as /dev/bpfxx\n");
151                     return -1;
152               }
153 #endif
154 
155           if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0)
156               {
157                     perror("BIOCVERSION");
158                     return -1;
159               }
160           if (bv.bv_major != BPF_MAJOR_VERSION ||
161               bv.bv_minor < BPF_MINOR_VERSION)
162               {
163                     fprintf(stderr, "kernel bpf (v%d.%d) filter out of date:\n",
164                               bv.bv_major, bv.bv_minor);
165                     fprintf(stderr, "current version: %d.%d\n",
166                               BPF_MAJOR_VERSION, BPF_MINOR_VERSION);
167                     return -1;
168               }
169 
170           (void) strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
171           if (ioctl(fd, BIOCSETIF, &ifr) == -1)
172               {
173                     fprintf(stderr, "%s(%d):", ifr.ifr_name, fd);
174                     perror("BIOCSETIF");
175                     exit(1);
176               }
177           /*
178            * set the timeout
179            */
180           timeout = tout;
181           to.tv_sec = 1;
182           to.tv_usec = 0;
183           if (ioctl(fd, BIOCSRTIMEOUT, (caddr_t)&to) == -1)
184               {
185                     perror("BIOCSRTIMEOUT");
186                     exit(-1);
187               }
188           /*
189            * get kernel buffer size
190            */
191           if (ioctl(fd, BIOCSBLEN, &bufsize) == -1)
192                     perror("BIOCSBLEN");
193           if (ioctl(fd, BIOCGBLEN, &bufsize) == -1)
194               {
195                     perror("BIOCGBLEN");
196                     exit(-1);
197               }
198           printf("BPF buffer size: %d\n", bufsize);
199           buf = (u_char*)malloc(bufsize);
200 
201           prog.bf_len = sizeof(filter) / sizeof(struct bpf_insn);
202           prog.bf_insns = filter;
203           if (ioctl(fd, BIOCSETF, (caddr_t)&prog) == -1)
204               {
205                     perror("BIOCSETF");
206                     exit(-1);
207               }
208           (void) ioctl(fd, BIOCFLUSH, 0);
209           return fd;
210 }
211