snit.c revision 302408
160484Sobrien/* $FreeBSD: stable/11/contrib/ipfilter/ipsd/snit.c 255332 2013-09-06 23:11:19Z cy $ */ 2218822Sdim 3218822Sdim/* 477298Sobrien * (C)opyright 1992-1998 Darren Reed. (from tcplog) 560484Sobrien * 660484Sobrien * See the IPFILTER.LICENCE file for details on licencing. 789857Sobrien * 8130561Sobrien */ 9130561Sobrien 1060484Sobrien#include <stdio.h> 1160484Sobrien#include <netdb.h> 1260484Sobrien#include <ctype.h> 1360484Sobrien#include <signal.h> 1460484Sobrien#include <errno.h> 1560484Sobrien#include <sys/types.h> 1660484Sobrien#include <sys/time.h> 1760484Sobrien#include <sys/timeb.h> 1860484Sobrien#include <sys/socket.h> 1960484Sobrien#include <sys/file.h> 20218822Sdim#include <sys/ioctl.h> 2160484Sobrien#include <net/nit.h> 2260484Sobrien#include <sys/fcntlcom.h> 2360484Sobrien#include <sys/dir.h> 2460484Sobrien#include <net/nit_if.h> 25218822Sdim#include <net/nit_pf.h> 26218822Sdim#include <net/nit_buf.h> 2760484Sobrien#include <net/packetfilt.h> 28218822Sdim#include <sys/stropts.h> 29218822Sdim 30218822Sdim#include <net/if.h> 3160484Sobrien#include <netinet/in.h> 3289857Sobrien#include <netinet/in_systm.h> 3360484Sobrien#include <netinet/ip.h> 3460484Sobrien#include <netinet/if_ether.h> 3560484Sobrien#include <netinet/ip_var.h> 36218822Sdim#include <netinet/udp.h> 37218822Sdim#include <netinet/udp_var.h> 3860484Sobrien#include <netinet/tcp.h> 3960484Sobrien#include <netinet/tcpip.h> 40218822Sdim 4160484Sobrien#ifndef lint 4260484Sobrienstatic char snitid[] = "@(#)snit.c 1.2 12/3/95 (C)1995 Darren Reed"; 43218822Sdim#endif 4460484Sobrien 45218822Sdim#define BUFSPACE 32768 4660484Sobrien 47218822Sdim/* 48218822Sdim * Be careful to only include those defined in the flags option for the 49218822Sdim * interface are included in the header size. 5060484Sobrien */ 51218822Sdim#define BUFHDR_SIZE (sizeof(struct nit_bufhdr)) 5289857Sobrien#define NIT_HDRSIZE (BUFHDR_SIZE) 53218822Sdim 54218822Sdimstatic int timeout; 55218822Sdim 56218822Sdim 57218822Sdimint ack_recv(ep) 58218822Sdim char *ep; 59218822Sdim{ 60218822Sdim struct tcpiphdr tip; 61218822Sdim struct tcphdr *tcp; 62218822Sdim struct ip *ip; 63218822Sdim 64218822Sdim ip = (struct ip *)&tip; 65218822Sdim tcp = (struct tcphdr *)(ip + 1); 66218822Sdim bcopy(ep + 14, (char *)ip, sizeof(*ip)); 67218822Sdim bcopy(ep + 14 + (ip->ip_hl << 2), (char *)tcp, sizeof(*tcp)); 68218822Sdim if (ip->ip_off & 0x1fff != 0) 69218822Sdim return 0; 70218822Sdim if (0 == detect(ip, tcp)) 71218822Sdim return 1; 72218822Sdim return 0; 73218822Sdim} 74218822Sdim 75218822Sdim 76218822Sdimint readloop(fd, dst) 77218822Sdim int fd; 78218822Sdim struct in_addr dst; 79218822Sdim{ 80218822Sdim static u_char buf[BUFSPACE]; 8189857Sobrien register u_char *bp, *cp, *bufend; 82218822Sdim register struct nit_bufhdr *hp; 83218822Sdim register int cc; 84218822Sdim time_t now = time(NULL); 85218822Sdim int done = 0; 8660484Sobrien 87218822Sdim while ((cc = read(fd, buf, BUFSPACE-1)) >= 0) { 8860484Sobrien if (!cc) 89218822Sdim if ((time(NULL) - now) > timeout) 9060484Sobrien return done; 91218822Sdim else 92218822Sdim continue; 93218822Sdim bp = buf; 94218822Sdim bufend = buf + cc; 95218822Sdim /* 96218822Sdim * loop through each snapshot in the chunk 9789857Sobrien */ 98130561Sobrien while (bp < bufend) { 99130561Sobrien cp = (u_char *)((char *)bp + NIT_HDRSIZE); 100130561Sobrien /* 101130561Sobrien * get past NIT buffer 102130561Sobrien */ 103130561Sobrien hp = (struct nit_bufhdr *)bp; 104130561Sobrien /* 105218822Sdim * next snapshot 10660484Sobrien */ 10777298Sobrien bp += hp->nhb_totlen; 108218822Sdim done += ack_recv(cp); 10977298Sobrien } 11060484Sobrien return done; 111218822Sdim } 11260484Sobrien perror("read"); 11360484Sobrien exit(-1); 11477298Sobrien} 11560484Sobrien 11660484Sobrienint initdevice(device, tout) 117218822Sdim char *device; 118218822Sdim int tout; 119218822Sdim{ 120218822Sdim struct strioctl si; 121218822Sdim struct timeval to; 122218822Sdim struct ifreq ifr; 123218822Sdim struct packetfilt pfil; 124218822Sdim u_long if_flags; 125218822Sdim u_short *fwp = pfil.Pf_Filter; 126218822Sdim int ret, offset, fd, snaplen= 76, chunksize = BUFSPACE; 127218822Sdim 128218822Sdim if ((fd = open("/dev/nit", O_RDWR)) < 0) 129218822Sdim { 130218822Sdim perror("/dev/nit"); 131218822Sdim exit(-1); 132218822Sdim } 13360484Sobrien 134218822Sdim /* 13560484Sobrien * Create some filter rules for our TCP watcher. We only want ethernet 136218822Sdim * pacets which are IP protocol and only the TCP packets from IP. 137218822Sdim */ 138218822Sdim offset = 6; 13960484Sobrien *fwp++ = ENF_PUSHWORD + offset; 14077298Sobrien *fwp++ = ENF_PUSHLIT | ENF_CAND; 141218822Sdim *fwp++ = htons(ETHERTYPE_IP); 142218822Sdim *fwp++ = ENF_PUSHWORD + sizeof(struct ether_header)/sizeof(short)+4; 143130561Sobrien *fwp++ = ENF_PUSHLIT | ENF_AND; 144130561Sobrien *fwp++ = htons(0x00ff); 145218822Sdim *fwp++ = ENF_PUSHLIT | ENF_COR; 14660484Sobrien *fwp++ = htons(IPPROTO_TCP); 14789857Sobrien *fwp++ = ENF_PUSHWORD + sizeof(struct ether_header)/sizeof(short)+4; 14889857Sobrien *fwp++ = ENF_PUSHLIT | ENF_AND; 14989857Sobrien *fwp++ = htons(0x00ff); 150218822Sdim *fwp++ = ENF_PUSHLIT | ENF_CAND; 151218822Sdim *fwp++ = htons(IPPROTO_UDP); 15289857Sobrien pfil.Pf_FilterLen = fwp - &pfil.Pf_Filter[0]; 153218822Sdim /* 154218822Sdim * put filter in place. 155218822Sdim */ 156218822Sdim if (ioctl(fd, I_PUSH, "pf") == -1) 157218822Sdim { 158218822Sdim perror("ioctl: I_PUSH pf"); 15989857Sobrien exit(1); 160218822Sdim } 161218822Sdim if (ioctl(fd, NIOCSETF, &pfil) == -1) 162218822Sdim { 163218822Sdim perror("ioctl: NIOCSETF"); 164218822Sdim exit(1); 165218822Sdim } 166218822Sdim /* 167218822Sdim * arrange to get messages from the NIT STREAM and use NIT_BUF option 168218822Sdim */ 169218822Sdim ioctl(fd, I_SRDOPT, (char*)RMSGD); 17060484Sobrien ioctl(fd, I_PUSH, "nbuf"); 171218822Sdim /* 172218822Sdim * set the timeout 173218822Sdim */ 17460484Sobrien timeout = tout; 175218822Sdim si.ic_timout = 1; 176218822Sdim to.tv_sec = 1; 177218822Sdim to.tv_usec = 0; 178218822Sdim si.ic_cmd = NIOCSTIME; 179218822Sdim si.ic_len = sizeof(to); 180218822Sdim si.ic_dp = (char*)&to; 181218822Sdim if (ioctl(fd, I_STR, (char*)&si) == -1) 182218822Sdim { 183218822Sdim perror("ioctl: NIT timeout"); 184218822Sdim exit(-1); 185218822Sdim } 186218822Sdim /* 187218822Sdim * set the chunksize 188218822Sdim */ 189218822Sdim si.ic_cmd = NIOCSCHUNK; 190218822Sdim si.ic_len = sizeof(chunksize); 191218822Sdim si.ic_dp = (char*)&chunksize; 192218822Sdim if (ioctl(fd, I_STR, (char*)&si) == -1) 193218822Sdim perror("ioctl: NIT chunksize"); 194218822Sdim if (ioctl(fd, NIOCGCHUNK, (char*)&chunksize) == -1) 195218822Sdim { 196218822Sdim perror("ioctl: NIT chunksize"); 197218822Sdim exit(-1); 198218822Sdim } 19960484Sobrien printf("NIT buffer size: %d\n", chunksize); 200218822Sdim 201218822Sdim /* 202218822Sdim * request the interface 203218822Sdim */ 20460484Sobrien strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 205218822Sdim ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = ' '; 206218822Sdim si.ic_cmd = NIOCBIND; 207218822Sdim si.ic_len = sizeof(ifr); 208218822Sdim si.ic_dp = (char*)𝔦 209218822Sdim if (ioctl(fd, I_STR, (char*)&si) == -1) 210218822Sdim { 211218822Sdim perror(ifr.ifr_name); 212218822Sdim exit(1); 213218822Sdim } 214218822Sdim 215218822Sdim /* 216218822Sdim * set the snapshot length 217218822Sdim */ 218218822Sdim si.ic_cmd = NIOCSSNAP; 219218822Sdim si.ic_len = sizeof(snaplen); 220218822Sdim si.ic_dp = (char*)&snaplen; 221218822Sdim if (ioctl(fd, I_STR, (char*)&si) == -1) 222218822Sdim { 22360484Sobrien perror("ioctl: NIT snaplen"); 224218822Sdim exit(1); 225218822Sdim } 226218822Sdim (void) ioctl(fd, I_FLUSH, (char*)FLUSHR); 227218822Sdim return fd; 228218822Sdim} 229218822Sdim