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