sbpf.c revision 145519
1145519Sdarrenr/* $FreeBSD: head/contrib/ipfilter/ipsd/sbpf.c 145519 2005-04-25 18:20:15Z darrenr $ */ 2145510Sdarrenr 322514Sdarrenr/* 453024Sguido * (C)opyright 1995-1998 Darren Reed. (from tcplog) 522514Sdarrenr * 680486Sdarrenr * See the IPFILTER.LICENCE file for details on licencing. 722514Sdarrenr * 822514Sdarrenr */ 922514Sdarrenr#include <stdio.h> 1022514Sdarrenr#include <netdb.h> 1122514Sdarrenr#include <ctype.h> 1222514Sdarrenr#include <signal.h> 1322514Sdarrenr#include <errno.h> 1422514Sdarrenr#include <sys/types.h> 1522514Sdarrenr#include <sys/param.h> 1622514Sdarrenr#include <sys/mbuf.h> 1722514Sdarrenr#include <sys/time.h> 1822514Sdarrenr#include <sys/timeb.h> 1922514Sdarrenr#include <sys/socket.h> 2022514Sdarrenr#include <sys/file.h> 2122514Sdarrenr#include <sys/ioctl.h> 2222514Sdarrenr#if BSD < 199103 2322514Sdarrenr#include <sys/fcntlcom.h> 2422514Sdarrenr#endif 2522514Sdarrenr#include <sys/dir.h> 2622514Sdarrenr#include <net/bpf.h> 2722514Sdarrenr 2822514Sdarrenr#include <net/if.h> 2922514Sdarrenr#include <netinet/in.h> 3022514Sdarrenr#include <netinet/in_systm.h> 3122514Sdarrenr#include <netinet/ip.h> 3222514Sdarrenr#include <netinet/if_ether.h> 3322514Sdarrenr#include <netinet/ip_var.h> 3422514Sdarrenr#include <netinet/udp.h> 3522514Sdarrenr#include <netinet/udp_var.h> 3622514Sdarrenr#include <netinet/tcp.h> 3722514Sdarrenr#include <netinet/tcpip.h> 3822514Sdarrenr#include "ip_compat.h" 3922514Sdarrenr 4022514Sdarrenr#ifndef lint 4122514Sdarrenrstatic char sbpf[] = "@(#)sbpf.c 1.2 12/3/95 (C)1995 Darren Reed"; 4222514Sdarrenr#endif 4322514Sdarrenr 4422514Sdarrenr/* 4522514Sdarrenr(000) ldh [12] 4622514Sdarrenr(001) jeq #0x800 jt 2 jf 5 4722514Sdarrenr(002) ldb [23] 4822514Sdarrenr(003) jeq #0x6 jt 4 jf 5 4922514Sdarrenr(004) ret #68 5022514Sdarrenr(005) ret #0 5122514Sdarrenr*/ 5222514Sdarrenrstruct bpf_insn filter[] = { 5322514Sdarrenr/* 0. */ { BPF_LD|BPF_H|BPF_ABS, 0, 0, 12 }, 5422514Sdarrenr/* 1. */ { BPF_JMP|BPF_JEQ, 0, 3, 0x0800 }, 5522514Sdarrenr/* 2. */ { BPF_LD|BPF_B|BPF_ABS, 0, 0, 23 }, 5622514Sdarrenr/* 3. */ { BPF_JMP|BPF_JEQ, 0, 1, 0x06 }, 5722514Sdarrenr/* 4. */ { BPF_RET, 0, 0, 68 }, 5822514Sdarrenr/* 5. */ { BPF_RET, 0, 0, 0 } 5922514Sdarrenr}; 6022514Sdarrenr/* 6122514Sdarrenr * the code herein is dervied from libpcap. 6222514Sdarrenr */ 6322514Sdarrenrstatic u_char *buf = NULL; 6422514Sdarrenrstatic u_int bufsize = 32768, timeout = 1; 6522514Sdarrenr 6622514Sdarrenr 6722514Sdarrenrint ack_recv(ep) 6822514Sdarrenrchar *ep; 6922514Sdarrenr{ 7022514Sdarrenr struct tcpiphdr tip; 7122514Sdarrenr tcphdr_t *tcp; 7222514Sdarrenr ip_t *ip; 7322514Sdarrenr 7422514Sdarrenr ip = (ip_t *)&tip; 7522514Sdarrenr tcp = (tcphdr_t *)(ip + 1); 7622514Sdarrenr bcopy(ep + 14, (char *)ip, sizeof(*ip)); 7722514Sdarrenr bcopy(ep + 14 + (ip->ip_hl << 2), (char *)tcp, sizeof(*tcp)); 7822514Sdarrenr if (ip->ip_p != IPPROTO_TCP && ip->ip_p != IPPROTO_UDP) 7922514Sdarrenr return -1; 8022514Sdarrenr if (ip->ip_p & 0x1fff != 0) 8122514Sdarrenr return 0; 8222514Sdarrenr if (0 == detect(ip, tcp)) 8322514Sdarrenr return 1; 8422514Sdarrenr return 0; 8522514Sdarrenr} 8622514Sdarrenr 8722514Sdarrenr 8822514Sdarrenrint readloop(fd, port, dst) 8922514Sdarrenrint fd, port; 9022514Sdarrenrstruct in_addr dst; 9122514Sdarrenr{ 9222514Sdarrenr register u_char *bp, *cp, *bufend; 9322514Sdarrenr register struct bpf_hdr *bh; 9422514Sdarrenr register int cc; 9522514Sdarrenr time_t in = time(NULL); 9622514Sdarrenr int done = 0; 9722514Sdarrenr 9822514Sdarrenr while ((cc = read(fd, buf, bufsize)) >= 0) { 9922514Sdarrenr if (!cc && (time(NULL) - in) > timeout) 10022514Sdarrenr return done; 10122514Sdarrenr bp = buf; 10222514Sdarrenr bufend = buf + cc; 10322514Sdarrenr /* 10422514Sdarrenr * loop through each snapshot in the chunk 10522514Sdarrenr */ 10622514Sdarrenr while (bp < bufend) { 10722514Sdarrenr bh = (struct bpf_hdr *)bp; 10822514Sdarrenr cp = bp + bh->bh_hdrlen; 10922514Sdarrenr done += ack_recv(cp); 11022514Sdarrenr bp += BPF_WORDALIGN(bh->bh_caplen + bh->bh_hdrlen); 11122514Sdarrenr } 11222514Sdarrenr return done; 11322514Sdarrenr } 11422514Sdarrenr perror("read"); 11522514Sdarrenr exit(-1); 11622514Sdarrenr} 11722514Sdarrenr 11822514Sdarrenrint initdevice(device, tout) 11922514Sdarrenrchar *device; 12022514Sdarrenrint tout; 12122514Sdarrenr{ 12222514Sdarrenr struct bpf_program prog; 12322514Sdarrenr struct bpf_version bv; 12422514Sdarrenr struct timeval to; 12522514Sdarrenr struct ifreq ifr; 12622514Sdarrenr char bpfname[16]; 12722514Sdarrenr int fd, i; 12822514Sdarrenr 12922514Sdarrenr for (i = 0; i < 16; i++) 13022514Sdarrenr { 13122514Sdarrenr (void) sprintf(bpfname, "/dev/bpf%d", i); 13222514Sdarrenr if ((fd = open(bpfname, O_RDWR)) >= 0) 13322514Sdarrenr break; 13422514Sdarrenr } 13522514Sdarrenr if (i == 16) 13622514Sdarrenr { 13722514Sdarrenr fprintf(stderr, "no bpf devices available as /dev/bpfxx\n"); 13822514Sdarrenr return -1; 13922514Sdarrenr } 14022514Sdarrenr 14122514Sdarrenr if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) 14222514Sdarrenr { 14322514Sdarrenr perror("BIOCVERSION"); 14422514Sdarrenr return -1; 14522514Sdarrenr } 14622514Sdarrenr if (bv.bv_major != BPF_MAJOR_VERSION || 14722514Sdarrenr bv.bv_minor < BPF_MINOR_VERSION) 14822514Sdarrenr { 14922514Sdarrenr fprintf(stderr, "kernel bpf (v%d.%d) filter out of date:\n", 15022514Sdarrenr bv.bv_major, bv.bv_minor); 15122514Sdarrenr fprintf(stderr, "current version: %d.%d\n", 15222514Sdarrenr BPF_MAJOR_VERSION, BPF_MINOR_VERSION); 15322514Sdarrenr return -1; 15422514Sdarrenr } 15522514Sdarrenr 15622514Sdarrenr (void) strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 15722514Sdarrenr if (ioctl(fd, BIOCSETIF, &ifr) == -1) 15822514Sdarrenr { 15922514Sdarrenr fprintf(stderr, "%s(%d):", ifr.ifr_name, fd); 16022514Sdarrenr perror("BIOCSETIF"); 16122514Sdarrenr exit(1); 16222514Sdarrenr } 16322514Sdarrenr /* 16422514Sdarrenr * set the timeout 16522514Sdarrenr */ 16622514Sdarrenr timeout = tout; 16722514Sdarrenr to.tv_sec = 1; 16822514Sdarrenr to.tv_usec = 0; 16922514Sdarrenr if (ioctl(fd, BIOCSRTIMEOUT, (caddr_t)&to) == -1) 17022514Sdarrenr { 17122514Sdarrenr perror("BIOCSRTIMEOUT"); 17222514Sdarrenr exit(-1); 17322514Sdarrenr } 17422514Sdarrenr /* 17522514Sdarrenr * get kernel buffer size 17622514Sdarrenr */ 17722514Sdarrenr if (ioctl(fd, BIOCSBLEN, &bufsize) == -1) 17822514Sdarrenr perror("BIOCSBLEN"); 17922514Sdarrenr if (ioctl(fd, BIOCGBLEN, &bufsize) == -1) 18022514Sdarrenr { 18122514Sdarrenr perror("BIOCGBLEN"); 18222514Sdarrenr exit(-1); 18322514Sdarrenr } 18422514Sdarrenr printf("BPF buffer size: %d\n", bufsize); 18522514Sdarrenr buf = (u_char*)malloc(bufsize); 18622514Sdarrenr 18722514Sdarrenr prog.bf_len = sizeof(filter) / sizeof(struct bpf_insn); 18822514Sdarrenr prog.bf_insns = filter; 18922514Sdarrenr if (ioctl(fd, BIOCSETF, (caddr_t)&prog) == -1) 19022514Sdarrenr { 19122514Sdarrenr perror("BIOCSETF"); 19222514Sdarrenr exit(-1); 19322514Sdarrenr } 19422514Sdarrenr (void) ioctl(fd, BIOCFLUSH, 0); 19522514Sdarrenr return fd; 19622514Sdarrenr} 197