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