1145519Sdarrenr/*	$FreeBSD$	*/
2145510Sdarrenr
322514Sdarrenr/*
453024Sguido * (C)opyright 1992-1998 Darren Reed. (from tcplog)
522514Sdarrenr *
680486Sdarrenr * See the IPFILTER.LICENCE file for details on licencing.
722514Sdarrenr *
822514Sdarrenr */
922514Sdarrenr
1022514Sdarrenr#include <stdio.h>
1122514Sdarrenr#include <netdb.h>
1222514Sdarrenr#include <ctype.h>
1322514Sdarrenr#include <signal.h>
1422514Sdarrenr#include <errno.h>
1522514Sdarrenr#include <sys/types.h>
1622514Sdarrenr#include <sys/time.h>
1722514Sdarrenr#include <sys/timeb.h>
1822514Sdarrenr#include <sys/socket.h>
1922514Sdarrenr#include <sys/file.h>
2022514Sdarrenr#include <sys/ioctl.h>
2122514Sdarrenr#include <net/nit.h>
2222514Sdarrenr#include <sys/fcntlcom.h>
2322514Sdarrenr#include <sys/dir.h>
2422514Sdarrenr#include <net/nit_if.h>
2522514Sdarrenr#include <net/nit_pf.h>
2622514Sdarrenr#include <net/nit_buf.h>
2722514Sdarrenr#include <net/packetfilt.h>
2822514Sdarrenr#include <sys/stropts.h>
2922514Sdarrenr
3022514Sdarrenr#include <net/if.h>
3122514Sdarrenr#include <netinet/in.h>
3222514Sdarrenr#include <netinet/in_systm.h>
3322514Sdarrenr#include <netinet/ip.h>
3422514Sdarrenr#include <netinet/if_ether.h>
3522514Sdarrenr#include <netinet/ip_var.h>
3622514Sdarrenr#include <netinet/udp.h>
3722514Sdarrenr#include <netinet/udp_var.h>
3822514Sdarrenr#include <netinet/tcp.h>
3922514Sdarrenr#include <netinet/tcpip.h>
4022514Sdarrenr
4122514Sdarrenr#ifndef	lint
4222514Sdarrenrstatic	char	snitid[] = "@(#)snit.c	1.2 12/3/95 (C)1995 Darren Reed";
4322514Sdarrenr#endif
4422514Sdarrenr
4522514Sdarrenr#define BUFSPACE	32768
4622514Sdarrenr
4722514Sdarrenr/*
4822514Sdarrenr * Be careful to only include those defined in the flags option for the
4922514Sdarrenr * interface are included in the header size.
5022514Sdarrenr */
5122514Sdarrenr#define BUFHDR_SIZE  (sizeof(struct nit_bufhdr))
5222514Sdarrenr#define NIT_HDRSIZE  (BUFHDR_SIZE)
5322514Sdarrenr
5422514Sdarrenrstatic	int	timeout;
5522514Sdarrenr
5622514Sdarrenr
5722514Sdarrenrint	ack_recv(ep)
58255332Scy	char	*ep;
5922514Sdarrenr{
6022514Sdarrenr	struct	tcpiphdr	tip;
6122514Sdarrenr	struct	tcphdr	*tcp;
6222514Sdarrenr	struct	ip	*ip;
6322514Sdarrenr
6422514Sdarrenr	ip = (struct ip *)&tip;
6522514Sdarrenr	tcp = (struct tcphdr *)(ip + 1);
6622514Sdarrenr	bcopy(ep + 14, (char *)ip, sizeof(*ip));
6722514Sdarrenr	bcopy(ep + 14 + (ip->ip_hl << 2), (char *)tcp, sizeof(*tcp));
6822514Sdarrenr	if (ip->ip_off & 0x1fff != 0)
6922514Sdarrenr		return 0;
7022514Sdarrenr	if (0 == detect(ip, tcp))
7122514Sdarrenr		return 1;
7222514Sdarrenr	return 0;
7322514Sdarrenr}
7422514Sdarrenr
7522514Sdarrenr
7622514Sdarrenrint	readloop(fd, dst)
77255332Scy	int 	fd;
78255332Scy	struct	in_addr dst;
7922514Sdarrenr{
8022514Sdarrenr	static	u_char	buf[BUFSPACE];
8122514Sdarrenr	register u_char	*bp, *cp, *bufend;
8222514Sdarrenr	register struct	nit_bufhdr	*hp;
8322514Sdarrenr	register int	cc;
8422514Sdarrenr	time_t	now = time(NULL);
8522514Sdarrenr	int	done = 0;
8622514Sdarrenr
8722514Sdarrenr	while ((cc = read(fd, buf, BUFSPACE-1)) >= 0) {
8822514Sdarrenr		if (!cc)
8922514Sdarrenr			if ((time(NULL) - now) > timeout)
9022514Sdarrenr				return done;
9122514Sdarrenr			else
9222514Sdarrenr				continue;
9322514Sdarrenr		bp = buf;
9422514Sdarrenr		bufend = buf + cc;
9522514Sdarrenr		/*
9622514Sdarrenr		 * loop through each snapshot in the chunk
9722514Sdarrenr		 */
9822514Sdarrenr		while (bp < bufend) {
9922514Sdarrenr			cp = (u_char *)((char *)bp + NIT_HDRSIZE);
10022514Sdarrenr			/*
10122514Sdarrenr			 * get past NIT buffer
10222514Sdarrenr			 */
10322514Sdarrenr			hp = (struct nit_bufhdr *)bp;
10422514Sdarrenr			/*
10522514Sdarrenr			 * next snapshot
10622514Sdarrenr			 */
10722514Sdarrenr			bp += hp->nhb_totlen;
10822514Sdarrenr			done += ack_recv(cp);
10922514Sdarrenr		}
11022514Sdarrenr		return done;
11122514Sdarrenr	}
11222514Sdarrenr	perror("read");
11322514Sdarrenr	exit(-1);
11422514Sdarrenr}
11522514Sdarrenr
11622514Sdarrenrint	initdevice(device, tout)
117255332Scy	char	*device;
118255332Scy	int	tout;
11922514Sdarrenr{
12022514Sdarrenr	struct	strioctl si;
12122514Sdarrenr	struct	timeval to;
12222514Sdarrenr	struct	ifreq ifr;
12322514Sdarrenr	struct	packetfilt pfil;
12422514Sdarrenr	u_long	if_flags;
12522514Sdarrenr	u_short	*fwp = pfil.Pf_Filter;
12622514Sdarrenr	int	ret, offset, fd, snaplen= 76, chunksize = BUFSPACE;
12722514Sdarrenr
12822514Sdarrenr	if ((fd = open("/dev/nit", O_RDWR)) < 0)
12922514Sdarrenr	    {
13022514Sdarrenr		perror("/dev/nit");
13122514Sdarrenr		exit(-1);
13222514Sdarrenr	    }
13322514Sdarrenr
13422514Sdarrenr	/*
13522514Sdarrenr	 * Create some filter rules for our TCP watcher. We only want ethernet
13622514Sdarrenr	 * pacets which are IP protocol and only the TCP packets from IP.
13722514Sdarrenr	 */
13822514Sdarrenr	offset = 6;
13922514Sdarrenr	*fwp++ = ENF_PUSHWORD + offset;
14022514Sdarrenr	*fwp++ = ENF_PUSHLIT | ENF_CAND;
14122514Sdarrenr	*fwp++ = htons(ETHERTYPE_IP);
14222514Sdarrenr	*fwp++ = ENF_PUSHWORD + sizeof(struct ether_header)/sizeof(short)+4;
14322514Sdarrenr	*fwp++ = ENF_PUSHLIT | ENF_AND;
14422514Sdarrenr	*fwp++ = htons(0x00ff);
14522514Sdarrenr	*fwp++ = ENF_PUSHLIT | ENF_COR;
14622514Sdarrenr	*fwp++ = htons(IPPROTO_TCP);
14722514Sdarrenr	*fwp++ = ENF_PUSHWORD + sizeof(struct ether_header)/sizeof(short)+4;
14822514Sdarrenr	*fwp++ = ENF_PUSHLIT | ENF_AND;
14922514Sdarrenr	*fwp++ = htons(0x00ff);
15022514Sdarrenr	*fwp++ = ENF_PUSHLIT | ENF_CAND;
15122514Sdarrenr	*fwp++ = htons(IPPROTO_UDP);
15222514Sdarrenr	pfil.Pf_FilterLen = fwp - &pfil.Pf_Filter[0];
15322514Sdarrenr	/*
15422514Sdarrenr	 * put filter in place.
15522514Sdarrenr	 */
15622514Sdarrenr	if (ioctl(fd, I_PUSH, "pf") == -1)
15722514Sdarrenr	    {
15822514Sdarrenr		perror("ioctl: I_PUSH pf");
15922514Sdarrenr		exit(1);
16022514Sdarrenr	    }
16122514Sdarrenr	if (ioctl(fd, NIOCSETF, &pfil) == -1)
16222514Sdarrenr	    {
16322514Sdarrenr		perror("ioctl: NIOCSETF");
16422514Sdarrenr		exit(1);
16522514Sdarrenr	    }
16622514Sdarrenr	/*
16722514Sdarrenr	 * arrange to get messages from the NIT STREAM and use NIT_BUF option
16822514Sdarrenr	 */
16922514Sdarrenr	ioctl(fd, I_SRDOPT, (char*)RMSGD);
17022514Sdarrenr	ioctl(fd, I_PUSH, "nbuf");
17122514Sdarrenr	/*
17222514Sdarrenr	 * set the timeout
17322514Sdarrenr	 */
17422514Sdarrenr	timeout = tout;
17522514Sdarrenr	si.ic_timout = 1;
17622514Sdarrenr	to.tv_sec = 1;
17722514Sdarrenr	to.tv_usec = 0;
17822514Sdarrenr	si.ic_cmd = NIOCSTIME;
17922514Sdarrenr	si.ic_len = sizeof(to);
18022514Sdarrenr	si.ic_dp = (char*)&to;
18122514Sdarrenr	if (ioctl(fd, I_STR, (char*)&si) == -1)
18222514Sdarrenr	    {
18322514Sdarrenr		perror("ioctl: NIT timeout");
18422514Sdarrenr		exit(-1);
18522514Sdarrenr	    }
18622514Sdarrenr	/*
18722514Sdarrenr	 * set the chunksize
18822514Sdarrenr	 */
18922514Sdarrenr	si.ic_cmd = NIOCSCHUNK;
19022514Sdarrenr	si.ic_len = sizeof(chunksize);
19122514Sdarrenr	si.ic_dp = (char*)&chunksize;
19222514Sdarrenr	if (ioctl(fd, I_STR, (char*)&si) == -1)
19322514Sdarrenr		perror("ioctl: NIT chunksize");
19422514Sdarrenr	if (ioctl(fd, NIOCGCHUNK, (char*)&chunksize) == -1)
19522514Sdarrenr	    {
19622514Sdarrenr		perror("ioctl: NIT chunksize");
19722514Sdarrenr		exit(-1);
19822514Sdarrenr	    }
19922514Sdarrenr	printf("NIT buffer size: %d\n", chunksize);
20022514Sdarrenr
20122514Sdarrenr	/*
20222514Sdarrenr	 * request the interface
20322514Sdarrenr	 */
20422514Sdarrenr	strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
20522514Sdarrenr	ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = ' ';
20622514Sdarrenr	si.ic_cmd = NIOCBIND;
20722514Sdarrenr	si.ic_len = sizeof(ifr);
20822514Sdarrenr	si.ic_dp = (char*)&ifr;
20922514Sdarrenr	if (ioctl(fd, I_STR, (char*)&si) == -1)
21022514Sdarrenr	    {
21122514Sdarrenr		perror(ifr.ifr_name);
21222514Sdarrenr		exit(1);
21322514Sdarrenr	    }
21422514Sdarrenr
21522514Sdarrenr	/*
21622514Sdarrenr	 * set the snapshot length
21722514Sdarrenr	 */
21822514Sdarrenr	si.ic_cmd = NIOCSSNAP;
21922514Sdarrenr	si.ic_len = sizeof(snaplen);
22022514Sdarrenr	si.ic_dp = (char*)&snaplen;
22122514Sdarrenr	if (ioctl(fd, I_STR, (char*)&si) == -1)
22222514Sdarrenr	    {
22322514Sdarrenr		perror("ioctl: NIT snaplen");
22422514Sdarrenr		exit(1);
22522514Sdarrenr	    }
22622514Sdarrenr	(void) ioctl(fd, I_FLUSH, (char*)FLUSHR);
22722514Sdarrenr	return fd;
22822514Sdarrenr}
229