1145519Sdarrenr/* $FreeBSD$ */ 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> 14161357Sguido#ifdef __NetBSD__ 15161357Sguido# include <paths.h> 16161357Sguido#endif 1722514Sdarrenr#include <sys/types.h> 1822514Sdarrenr#include <sys/param.h> 1922514Sdarrenr#include <sys/mbuf.h> 2022514Sdarrenr#include <sys/time.h> 2122514Sdarrenr#include <sys/timeb.h> 2222514Sdarrenr#include <sys/socket.h> 2322514Sdarrenr#include <sys/file.h> 2422514Sdarrenr#include <sys/ioctl.h> 2522514Sdarrenr#if BSD < 199103 2622514Sdarrenr#include <sys/fcntlcom.h> 2722514Sdarrenr#endif 2822514Sdarrenr#include <sys/dir.h> 2922514Sdarrenr#include <net/bpf.h> 3022514Sdarrenr 3122514Sdarrenr#include <net/if.h> 3222514Sdarrenr#include <netinet/in.h> 3322514Sdarrenr#include <netinet/in_systm.h> 3422514Sdarrenr#include <netinet/ip.h> 3522514Sdarrenr#include <netinet/if_ether.h> 3622514Sdarrenr#include <netinet/ip_var.h> 3722514Sdarrenr#include <netinet/udp.h> 3822514Sdarrenr#include <netinet/udp_var.h> 3922514Sdarrenr#include <netinet/tcp.h> 4022514Sdarrenr#include <netinet/tcpip.h> 4122514Sdarrenr#include "ip_compat.h" 4222514Sdarrenr 4322514Sdarrenr#ifndef lint 4422514Sdarrenrstatic char sbpf[] = "@(#)sbpf.c 1.2 12/3/95 (C)1995 Darren Reed"; 4522514Sdarrenr#endif 4622514Sdarrenr 4722514Sdarrenr/* 4822514Sdarrenr(000) ldh [12] 4922514Sdarrenr(001) jeq #0x800 jt 2 jf 5 5022514Sdarrenr(002) ldb [23] 5122514Sdarrenr(003) jeq #0x6 jt 4 jf 5 5222514Sdarrenr(004) ret #68 5322514Sdarrenr(005) ret #0 5422514Sdarrenr*/ 5522514Sdarrenrstruct bpf_insn filter[] = { 5622514Sdarrenr/* 0. */ { BPF_LD|BPF_H|BPF_ABS, 0, 0, 12 }, 5722514Sdarrenr/* 1. */ { BPF_JMP|BPF_JEQ, 0, 3, 0x0800 }, 5822514Sdarrenr/* 2. */ { BPF_LD|BPF_B|BPF_ABS, 0, 0, 23 }, 5922514Sdarrenr/* 3. */ { BPF_JMP|BPF_JEQ, 0, 1, 0x06 }, 6022514Sdarrenr/* 4. */ { BPF_RET, 0, 0, 68 }, 6122514Sdarrenr/* 5. */ { BPF_RET, 0, 0, 0 } 6222514Sdarrenr}; 6322514Sdarrenr/* 6422514Sdarrenr * the code herein is dervied from libpcap. 6522514Sdarrenr */ 6622514Sdarrenrstatic u_char *buf = NULL; 6722514Sdarrenrstatic u_int bufsize = 32768, timeout = 1; 6822514Sdarrenr 6922514Sdarrenr 7022514Sdarrenrint ack_recv(ep) 71255332Scy char *ep; 7222514Sdarrenr{ 7322514Sdarrenr struct tcpiphdr tip; 7422514Sdarrenr tcphdr_t *tcp; 7522514Sdarrenr ip_t *ip; 7622514Sdarrenr 7722514Sdarrenr ip = (ip_t *)&tip; 7822514Sdarrenr tcp = (tcphdr_t *)(ip + 1); 7922514Sdarrenr bcopy(ep + 14, (char *)ip, sizeof(*ip)); 8022514Sdarrenr bcopy(ep + 14 + (ip->ip_hl << 2), (char *)tcp, sizeof(*tcp)); 8122514Sdarrenr if (ip->ip_p != IPPROTO_TCP && ip->ip_p != IPPROTO_UDP) 8222514Sdarrenr return -1; 8322514Sdarrenr if (ip->ip_p & 0x1fff != 0) 8422514Sdarrenr return 0; 8522514Sdarrenr if (0 == detect(ip, tcp)) 8622514Sdarrenr return 1; 8722514Sdarrenr return 0; 8822514Sdarrenr} 8922514Sdarrenr 9022514Sdarrenr 9122514Sdarrenrint readloop(fd, port, dst) 92255332Scy int fd, port; 93255332Scy struct in_addr dst; 9422514Sdarrenr{ 9522514Sdarrenr register u_char *bp, *cp, *bufend; 9622514Sdarrenr register struct bpf_hdr *bh; 9722514Sdarrenr register int cc; 9822514Sdarrenr time_t in = time(NULL); 9922514Sdarrenr int done = 0; 10022514Sdarrenr 10122514Sdarrenr while ((cc = read(fd, buf, bufsize)) >= 0) { 10222514Sdarrenr if (!cc && (time(NULL) - in) > timeout) 10322514Sdarrenr return done; 10422514Sdarrenr bp = buf; 10522514Sdarrenr bufend = buf + cc; 10622514Sdarrenr /* 10722514Sdarrenr * loop through each snapshot in the chunk 10822514Sdarrenr */ 10922514Sdarrenr while (bp < bufend) { 11022514Sdarrenr bh = (struct bpf_hdr *)bp; 11122514Sdarrenr cp = bp + bh->bh_hdrlen; 11222514Sdarrenr done += ack_recv(cp); 11322514Sdarrenr bp += BPF_WORDALIGN(bh->bh_caplen + bh->bh_hdrlen); 11422514Sdarrenr } 11522514Sdarrenr return done; 11622514Sdarrenr } 11722514Sdarrenr perror("read"); 11822514Sdarrenr exit(-1); 11922514Sdarrenr} 12022514Sdarrenr 12122514Sdarrenrint initdevice(device, tout) 122255332Scy char *device; 123255332Scy int tout; 12422514Sdarrenr{ 12522514Sdarrenr struct bpf_program prog; 12622514Sdarrenr struct bpf_version bv; 12722514Sdarrenr struct timeval to; 12822514Sdarrenr struct ifreq ifr; 129161357Sguido#ifdef _PATH_BPF 130161357Sguido char *bpfname = _PATH_BPF; 131161357Sguido int fd; 132161357Sguido 133161357Sguido if ((fd = open(bpfname, O_RDWR)) < 0) 134161357Sguido { 135161357Sguido fprintf(stderr, "no bpf devices available as /dev/bpfxx\n"); 136161357Sguido return -1; 137161357Sguido } 138161357Sguido#else 13922514Sdarrenr char bpfname[16]; 140161357Sguido int fd = -1, i; 14122514Sdarrenr 14222514Sdarrenr for (i = 0; i < 16; i++) 14322514Sdarrenr { 14422514Sdarrenr (void) sprintf(bpfname, "/dev/bpf%d", i); 14522514Sdarrenr if ((fd = open(bpfname, O_RDWR)) >= 0) 14622514Sdarrenr break; 14722514Sdarrenr } 14822514Sdarrenr if (i == 16) 14922514Sdarrenr { 15022514Sdarrenr fprintf(stderr, "no bpf devices available as /dev/bpfxx\n"); 15122514Sdarrenr return -1; 15222514Sdarrenr } 153161357Sguido#endif 15422514Sdarrenr 15522514Sdarrenr if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) 15622514Sdarrenr { 15722514Sdarrenr perror("BIOCVERSION"); 15822514Sdarrenr return -1; 15922514Sdarrenr } 16022514Sdarrenr if (bv.bv_major != BPF_MAJOR_VERSION || 16122514Sdarrenr bv.bv_minor < BPF_MINOR_VERSION) 16222514Sdarrenr { 16322514Sdarrenr fprintf(stderr, "kernel bpf (v%d.%d) filter out of date:\n", 16422514Sdarrenr bv.bv_major, bv.bv_minor); 16522514Sdarrenr fprintf(stderr, "current version: %d.%d\n", 16622514Sdarrenr BPF_MAJOR_VERSION, BPF_MINOR_VERSION); 16722514Sdarrenr return -1; 16822514Sdarrenr } 16922514Sdarrenr 17022514Sdarrenr (void) strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 17122514Sdarrenr if (ioctl(fd, BIOCSETIF, &ifr) == -1) 17222514Sdarrenr { 17322514Sdarrenr fprintf(stderr, "%s(%d):", ifr.ifr_name, fd); 17422514Sdarrenr perror("BIOCSETIF"); 17522514Sdarrenr exit(1); 17622514Sdarrenr } 17722514Sdarrenr /* 17822514Sdarrenr * set the timeout 17922514Sdarrenr */ 18022514Sdarrenr timeout = tout; 18122514Sdarrenr to.tv_sec = 1; 18222514Sdarrenr to.tv_usec = 0; 18322514Sdarrenr if (ioctl(fd, BIOCSRTIMEOUT, (caddr_t)&to) == -1) 18422514Sdarrenr { 18522514Sdarrenr perror("BIOCSRTIMEOUT"); 18622514Sdarrenr exit(-1); 18722514Sdarrenr } 18822514Sdarrenr /* 18922514Sdarrenr * get kernel buffer size 19022514Sdarrenr */ 19122514Sdarrenr if (ioctl(fd, BIOCSBLEN, &bufsize) == -1) 19222514Sdarrenr perror("BIOCSBLEN"); 19322514Sdarrenr if (ioctl(fd, BIOCGBLEN, &bufsize) == -1) 19422514Sdarrenr { 19522514Sdarrenr perror("BIOCGBLEN"); 19622514Sdarrenr exit(-1); 19722514Sdarrenr } 19822514Sdarrenr printf("BPF buffer size: %d\n", bufsize); 19922514Sdarrenr buf = (u_char*)malloc(bufsize); 20022514Sdarrenr 20122514Sdarrenr prog.bf_len = sizeof(filter) / sizeof(struct bpf_insn); 20222514Sdarrenr prog.bf_insns = filter; 20322514Sdarrenr if (ioctl(fd, BIOCSETF, (caddr_t)&prog) == -1) 20422514Sdarrenr { 20522514Sdarrenr perror("BIOCSETF"); 20622514Sdarrenr exit(-1); 20722514Sdarrenr } 20822514Sdarrenr (void) ioctl(fd, BIOCFLUSH, 0); 20922514Sdarrenr return fd; 21022514Sdarrenr} 211