141edb306SCy Schubert
241edb306SCy Schubert /*
341edb306SCy Schubert * (C)opyright 1992-1998 Darren Reed. (from tcplog)
441edb306SCy Schubert *
541edb306SCy Schubert * See the IPFILTER.LICENCE file for details on licencing.
641edb306SCy Schubert *
741edb306SCy Schubert */
841edb306SCy Schubert
941edb306SCy Schubert #include <stdio.h>
1041edb306SCy Schubert #include <netdb.h>
1141edb306SCy Schubert #include <ctype.h>
1241edb306SCy Schubert #include <signal.h>
1341edb306SCy Schubert #include <errno.h>
1441edb306SCy Schubert #include <sys/types.h>
1541edb306SCy Schubert #include <sys/time.h>
1641edb306SCy Schubert #include <sys/timeb.h>
1741edb306SCy Schubert #include <sys/socket.h>
1841edb306SCy Schubert #include <sys/file.h>
1941edb306SCy Schubert #include <sys/ioctl.h>
2041edb306SCy Schubert #include <net/nit.h>
2141edb306SCy Schubert #include <sys/fcntlcom.h>
2241edb306SCy Schubert #include <sys/dir.h>
2341edb306SCy Schubert #include <net/nit_if.h>
2441edb306SCy Schubert #include <net/nit_pf.h>
2541edb306SCy Schubert #include <net/nit_buf.h>
2641edb306SCy Schubert #include <net/packetfilt.h>
2741edb306SCy Schubert #include <sys/stropts.h>
2841edb306SCy Schubert
2941edb306SCy Schubert #include <net/if.h>
3041edb306SCy Schubert #include <netinet/in.h>
3141edb306SCy Schubert #include <netinet/in_systm.h>
3241edb306SCy Schubert #include <netinet/ip.h>
3341edb306SCy Schubert #include <netinet/if_ether.h>
3441edb306SCy Schubert #include <netinet/ip_var.h>
3541edb306SCy Schubert #include <netinet/udp.h>
3641edb306SCy Schubert #include <netinet/udp_var.h>
3741edb306SCy Schubert #include <netinet/tcp.h>
3841edb306SCy Schubert
3941edb306SCy Schubert #include "ipsend.h"
4041edb306SCy Schubert
4141edb306SCy Schubert
4241edb306SCy Schubert #define CHUNKSIZE 8192
4341edb306SCy Schubert #define BUFSPACE (4*CHUNKSIZE)
4441edb306SCy Schubert
4541edb306SCy Schubert /*
4641edb306SCy Schubert * Be careful to only include those defined in the flags option for the
4741edb306SCy Schubert * interface are included in the header size.
4841edb306SCy Schubert */
4941edb306SCy Schubert #define BUFHDR_SIZE (sizeof(struct nit_bufhdr))
5041edb306SCy Schubert #define NIT_HDRSIZE (BUFHDR_SIZE)
5141edb306SCy Schubert
5241edb306SCy Schubert static int timeout;
5341edb306SCy Schubert
5441edb306SCy Schubert
55efeb8bffSCy Schubert int
initdevice(char * device,int tout)56efeb8bffSCy Schubert initdevice(char *device, int tout)
5741edb306SCy Schubert {
5841edb306SCy Schubert struct strioctl si;
5941edb306SCy Schubert struct timeval to;
6041edb306SCy Schubert struct ifreq ifr;
6141edb306SCy Schubert int fd;
6241edb306SCy Schubert
6341edb306SCy Schubert if ((fd = open("/dev/nit", O_RDWR)) < 0)
6441edb306SCy Schubert {
6541edb306SCy Schubert perror("/dev/nit");
6641edb306SCy Schubert exit(-1);
6741edb306SCy Schubert }
6841edb306SCy Schubert
6941edb306SCy Schubert /*
7041edb306SCy Schubert * arrange to get messages from the NIT STREAM and use NIT_BUF option
7141edb306SCy Schubert */
7241edb306SCy Schubert ioctl(fd, I_SRDOPT, (char*)RMSGD);
7341edb306SCy Schubert ioctl(fd, I_PUSH, "nbuf");
7441edb306SCy Schubert
7541edb306SCy Schubert /*
7641edb306SCy Schubert * set the timeout
7741edb306SCy Schubert */
7841edb306SCy Schubert timeout = tout;
7941edb306SCy Schubert si.ic_timout = 1;
8041edb306SCy Schubert to.tv_sec = 1;
8141edb306SCy Schubert to.tv_usec = 0;
8241edb306SCy Schubert si.ic_cmd = NIOCSTIME;
8341edb306SCy Schubert si.ic_len = sizeof(to);
8441edb306SCy Schubert si.ic_dp = (char*)&to;
8541edb306SCy Schubert if (ioctl(fd, I_STR, (char*)&si) == -1)
8641edb306SCy Schubert {
8741edb306SCy Schubert perror("ioctl: NIT timeout");
8841edb306SCy Schubert exit(-1);
8941edb306SCy Schubert }
9041edb306SCy Schubert
9141edb306SCy Schubert /*
9241edb306SCy Schubert * request the interface
9341edb306SCy Schubert */
9441edb306SCy Schubert strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
9541edb306SCy Schubert ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = ' ';
9641edb306SCy Schubert si.ic_cmd = NIOCBIND;
9741edb306SCy Schubert si.ic_len = sizeof(ifr);
9841edb306SCy Schubert si.ic_dp = (char*)𝔦
9941edb306SCy Schubert if (ioctl(fd, I_STR, (char*)&si) == -1)
10041edb306SCy Schubert {
10141edb306SCy Schubert perror(ifr.ifr_name);
10241edb306SCy Schubert exit(1);
10341edb306SCy Schubert }
104*2582ae57SCy Schubert return (fd);
10541edb306SCy Schubert }
10641edb306SCy Schubert
10741edb306SCy Schubert
10841edb306SCy Schubert /*
10941edb306SCy Schubert * output an IP packet onto a fd opened for /dev/nit
11041edb306SCy Schubert */
111efeb8bffSCy Schubert int
112efeb8bffSCy Schubert sendip(int fd, char *pkt, int len)
11341edb306SCy Schubert int fd, len;
11441edb306SCy Schubert char *pkt;
11541edb306SCy Schubert {
11641edb306SCy Schubert struct sockaddr sk, *sa = &sk;
11741edb306SCy Schubert struct strbuf cbuf, *cp = &cbuf, dbuf, *dp = &dbuf;
11841edb306SCy Schubert
11941edb306SCy Schubert /*
12041edb306SCy Schubert * For ethernet, need at least 802.3 header and IP header.
12141edb306SCy Schubert */
12241edb306SCy Schubert if (len < (sizeof(sa->sa_data) + sizeof(struct ip)))
123*2582ae57SCy Schubert return (-1);
12441edb306SCy Schubert /*
12541edb306SCy Schubert * to avoid any output processing for IP, say we're not.
12641edb306SCy Schubert */
12741edb306SCy Schubert sa->sa_family = AF_UNSPEC;
12841edb306SCy Schubert bcopy(pkt, sa->sa_data, sizeof(sa->sa_data));
12941edb306SCy Schubert pkt += sizeof(sa->sa_data);
13041edb306SCy Schubert len -= sizeof(sa->sa_data);
13141edb306SCy Schubert
13241edb306SCy Schubert /*
13341edb306SCy Schubert * construct NIT STREAMS messages, first control then data.
13441edb306SCy Schubert */
13541edb306SCy Schubert cp->len = sizeof(*sa);
13641edb306SCy Schubert cp->maxlen = sizeof(*sa);
13741edb306SCy Schubert cp->buf = (char *)sa;
13841edb306SCy Schubert
13941edb306SCy Schubert dp->buf = pkt;
14041edb306SCy Schubert dp->len = len;
14141edb306SCy Schubert dp->maxlen = dp->len;
14241edb306SCy Schubert
14341edb306SCy Schubert if (putmsg(fd, cp, dp, 0) == -1)
14441edb306SCy Schubert {
14541edb306SCy Schubert perror("putmsg");
146*2582ae57SCy Schubert return (-1);
14741edb306SCy Schubert }
14841edb306SCy Schubert
14941edb306SCy Schubert if (ioctl(fd, I_FLUSH, FLUSHW) == -1)
15041edb306SCy Schubert {
15141edb306SCy Schubert perror("I_FLUSH");
152*2582ae57SCy Schubert return (-1);
15341edb306SCy Schubert }
154*2582ae57SCy Schubert return (len);
15541edb306SCy Schubert }
156