1145519Sdarrenr/*	$FreeBSD$	*/
2145510Sdarrenr
322514Sdarrenr/*
453024Sguido * (C)opyright 1992-1998 Darren Reed. (from tcplog)
522514Sdarrenr *
680486Sdarrenr * See the IPFILTER.LICENCE file for details on licencing.
7145510Sdarrenr *
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
4024583Sdarrenr#include "ipsend.h"
4124583Sdarrenr
4231183Speter#if !defined(lint)
4331183Speterstatic const char sccsid[] = "@(#)snit.c	1.5 1/11/96 (C)1995 Darren Reed";
44153881Sguidostatic const char rcsid[] = "@(#)$Id: snit.c,v 2.3 2001/06/09 17:09:26 darrenr Exp $";
4522514Sdarrenr#endif
4622514Sdarrenr
4722514Sdarrenr#define	CHUNKSIZE	8192
4822514Sdarrenr#define BUFSPACE	(4*CHUNKSIZE)
4922514Sdarrenr
5022514Sdarrenr/*
5122514Sdarrenr * Be careful to only include those defined in the flags option for the
5222514Sdarrenr * interface are included in the header size.
5322514Sdarrenr */
5422514Sdarrenr#define BUFHDR_SIZE  (sizeof(struct nit_bufhdr))
5522514Sdarrenr#define NIT_HDRSIZE  (BUFHDR_SIZE)
5622514Sdarrenr
5722514Sdarrenrstatic	int	timeout;
5822514Sdarrenr
5922514Sdarrenr
60145510Sdarrenrint	initdevice(device, tout)
6122514Sdarrenrchar	*device;
62145510Sdarrenrint	tout;
6322514Sdarrenr{
6422514Sdarrenr	struct	strioctl si;
6522514Sdarrenr	struct	timeval to;
6622514Sdarrenr	struct	ifreq ifr;
6722514Sdarrenr	int	fd;
6822514Sdarrenr
6922514Sdarrenr	if ((fd = open("/dev/nit", O_RDWR)) < 0)
7022514Sdarrenr	    {
7122514Sdarrenr		perror("/dev/nit");
7222514Sdarrenr		exit(-1);
7322514Sdarrenr	    }
7422514Sdarrenr
7522514Sdarrenr	/*
7622514Sdarrenr	 * arrange to get messages from the NIT STREAM and use NIT_BUF option
7722514Sdarrenr	 */
7822514Sdarrenr	ioctl(fd, I_SRDOPT, (char*)RMSGD);
7922514Sdarrenr	ioctl(fd, I_PUSH, "nbuf");
8022514Sdarrenr
8122514Sdarrenr	/*
8222514Sdarrenr	 * set the timeout
8322514Sdarrenr	 */
8422514Sdarrenr	timeout = tout;
8522514Sdarrenr	si.ic_timout = 1;
8622514Sdarrenr	to.tv_sec = 1;
8722514Sdarrenr	to.tv_usec = 0;
8822514Sdarrenr	si.ic_cmd = NIOCSTIME;
8922514Sdarrenr	si.ic_len = sizeof(to);
9022514Sdarrenr	si.ic_dp = (char*)&to;
9122514Sdarrenr	if (ioctl(fd, I_STR, (char*)&si) == -1)
9222514Sdarrenr	    {
9322514Sdarrenr		perror("ioctl: NIT timeout");
9422514Sdarrenr		exit(-1);
9522514Sdarrenr	    }
9622514Sdarrenr
9722514Sdarrenr	/*
9822514Sdarrenr	 * request the interface
9922514Sdarrenr	 */
10022514Sdarrenr	strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
10122514Sdarrenr	ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = ' ';
10222514Sdarrenr	si.ic_cmd = NIOCBIND;
10322514Sdarrenr	si.ic_len = sizeof(ifr);
10422514Sdarrenr	si.ic_dp = (char*)&ifr;
10522514Sdarrenr	if (ioctl(fd, I_STR, (char*)&si) == -1)
10622514Sdarrenr	    {
10722514Sdarrenr		perror(ifr.ifr_name);
10822514Sdarrenr		exit(1);
10922514Sdarrenr	    }
11022514Sdarrenr	return fd;
11122514Sdarrenr}
11222514Sdarrenr
11322514Sdarrenr
11422514Sdarrenr/*
11522514Sdarrenr * output an IP packet onto a fd opened for /dev/nit
11622514Sdarrenr */
11722514Sdarrenrint	sendip(fd, pkt, len)
11822514Sdarrenrint	fd, len;
11922514Sdarrenrchar	*pkt;
12022514Sdarrenr{
12122514Sdarrenr	struct	sockaddr sk, *sa = &sk;
12222514Sdarrenr	struct	strbuf	cbuf, *cp = &cbuf, dbuf, *dp = &dbuf;
12322514Sdarrenr
12422514Sdarrenr	/*
12522514Sdarrenr	 * For ethernet, need at least 802.3 header and IP header.
12622514Sdarrenr	 */
12722514Sdarrenr	if (len < (sizeof(sa->sa_data) + sizeof(struct ip)))
12822514Sdarrenr		return -1;
12922514Sdarrenr	/*
13022514Sdarrenr	 * to avoid any output processing for IP, say we're not.
13122514Sdarrenr	 */
13222514Sdarrenr	sa->sa_family = AF_UNSPEC;
13322514Sdarrenr	bcopy(pkt, sa->sa_data, sizeof(sa->sa_data));
13422514Sdarrenr	pkt += sizeof(sa->sa_data);
13522514Sdarrenr	len -= sizeof(sa->sa_data);
13622514Sdarrenr
13722514Sdarrenr	/*
13822514Sdarrenr	 * construct NIT STREAMS messages, first control then data.
13922514Sdarrenr	 */
14022514Sdarrenr	cp->len = sizeof(*sa);
14122514Sdarrenr	cp->maxlen = sizeof(*sa);
14222514Sdarrenr	cp->buf = (char *)sa;
14322514Sdarrenr
14422514Sdarrenr	dp->buf = pkt;
14522514Sdarrenr	dp->len = len;
14622514Sdarrenr	dp->maxlen = dp->len;
14722514Sdarrenr
14822514Sdarrenr	if (putmsg(fd, cp, dp, 0) == -1)
14922514Sdarrenr	    {
15022514Sdarrenr		perror("putmsg");
15122514Sdarrenr		return -1;
15222514Sdarrenr	    }
15322514Sdarrenr
15422514Sdarrenr	if (ioctl(fd, I_FLUSH, FLUSHW) == -1)
15522514Sdarrenr	    {
15622514Sdarrenr		perror("I_FLUSH");
15722514Sdarrenr		return -1;
15822514Sdarrenr	    }
15922514Sdarrenr	return len;
16022514Sdarrenr}
161