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