sbpf.c revision 255332
1/* $FreeBSD: head/contrib/ipfilter/ipsd/sbpf.c 255332 2013-09-06 23:11:19Z cy $ */ 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 44static 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*/ 55struct 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 */ 66static u_char *buf = NULL; 67static u_int bufsize = 32768, timeout = 1; 68 69 70int 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 91int 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 121int 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