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