snit.c revision 145519
1/* $FreeBSD: head/contrib/ipfilter/ipsd/snit.c 145519 2005-04-25 18:20:15Z darrenr $ */ 2 3/* 4 * (C)opyright 1992-1998 Darren Reed. (from tcplog) 5 * 6 * See the IPFILTER.LICENCE file for details on licencing. 7 * 8 */ 9 10#include <stdio.h> 11#include <netdb.h> 12#include <ctype.h> 13#include <signal.h> 14#include <errno.h> 15#include <sys/types.h> 16#include <sys/time.h> 17#include <sys/timeb.h> 18#include <sys/socket.h> 19#include <sys/file.h> 20#include <sys/ioctl.h> 21#include <net/nit.h> 22#include <sys/fcntlcom.h> 23#include <sys/dir.h> 24#include <net/nit_if.h> 25#include <net/nit_pf.h> 26#include <net/nit_buf.h> 27#include <net/packetfilt.h> 28#include <sys/stropts.h> 29 30#include <net/if.h> 31#include <netinet/in.h> 32#include <netinet/in_systm.h> 33#include <netinet/ip.h> 34#include <netinet/if_ether.h> 35#include <netinet/ip_var.h> 36#include <netinet/udp.h> 37#include <netinet/udp_var.h> 38#include <netinet/tcp.h> 39#include <netinet/tcpip.h> 40 41#ifndef lint 42static char snitid[] = "@(#)snit.c 1.2 12/3/95 (C)1995 Darren Reed"; 43#endif 44 45#define BUFSPACE 32768 46 47/* 48 * Be careful to only include those defined in the flags option for the 49 * interface are included in the header size. 50 */ 51#define BUFHDR_SIZE (sizeof(struct nit_bufhdr)) 52#define NIT_HDRSIZE (BUFHDR_SIZE) 53 54static int timeout; 55 56 57int ack_recv(ep) 58char *ep; 59{ 60 struct tcpiphdr tip; 61 struct tcphdr *tcp; 62 struct ip *ip; 63 64 ip = (struct ip *)&tip; 65 tcp = (struct tcphdr *)(ip + 1); 66 bcopy(ep + 14, (char *)ip, sizeof(*ip)); 67 bcopy(ep + 14 + (ip->ip_hl << 2), (char *)tcp, sizeof(*tcp)); 68 if (ip->ip_off & 0x1fff != 0) 69 return 0; 70 if (0 == detect(ip, tcp)) 71 return 1; 72 return 0; 73} 74 75 76int readloop(fd, dst) 77int fd; 78struct in_addr dst; 79{ 80 static u_char buf[BUFSPACE]; 81 register u_char *bp, *cp, *bufend; 82 register struct nit_bufhdr *hp; 83 register int cc; 84 time_t now = time(NULL); 85 int done = 0; 86 87 while ((cc = read(fd, buf, BUFSPACE-1)) >= 0) { 88 if (!cc) 89 if ((time(NULL) - now) > timeout) 90 return done; 91 else 92 continue; 93 bp = buf; 94 bufend = buf + cc; 95 /* 96 * loop through each snapshot in the chunk 97 */ 98 while (bp < bufend) { 99 cp = (u_char *)((char *)bp + NIT_HDRSIZE); 100 /* 101 * get past NIT buffer 102 */ 103 hp = (struct nit_bufhdr *)bp; 104 /* 105 * next snapshot 106 */ 107 bp += hp->nhb_totlen; 108 done += ack_recv(cp); 109 } 110 return done; 111 } 112 perror("read"); 113 exit(-1); 114} 115 116int initdevice(device, tout) 117char *device; 118int tout; 119{ 120 struct strioctl si; 121 struct timeval to; 122 struct ifreq ifr; 123 struct packetfilt pfil; 124 u_long if_flags; 125 u_short *fwp = pfil.Pf_Filter; 126 int ret, offset, fd, snaplen= 76, chunksize = BUFSPACE; 127 128 if ((fd = open("/dev/nit", O_RDWR)) < 0) 129 { 130 perror("/dev/nit"); 131 exit(-1); 132 } 133 134 /* 135 * Create some filter rules for our TCP watcher. We only want ethernet 136 * pacets which are IP protocol and only the TCP packets from IP. 137 */ 138 offset = 6; 139 *fwp++ = ENF_PUSHWORD + offset; 140 *fwp++ = ENF_PUSHLIT | ENF_CAND; 141 *fwp++ = htons(ETHERTYPE_IP); 142 *fwp++ = ENF_PUSHWORD + sizeof(struct ether_header)/sizeof(short)+4; 143 *fwp++ = ENF_PUSHLIT | ENF_AND; 144 *fwp++ = htons(0x00ff); 145 *fwp++ = ENF_PUSHLIT | ENF_COR; 146 *fwp++ = htons(IPPROTO_TCP); 147 *fwp++ = ENF_PUSHWORD + sizeof(struct ether_header)/sizeof(short)+4; 148 *fwp++ = ENF_PUSHLIT | ENF_AND; 149 *fwp++ = htons(0x00ff); 150 *fwp++ = ENF_PUSHLIT | ENF_CAND; 151 *fwp++ = htons(IPPROTO_UDP); 152 pfil.Pf_FilterLen = fwp - &pfil.Pf_Filter[0]; 153 /* 154 * put filter in place. 155 */ 156 if (ioctl(fd, I_PUSH, "pf") == -1) 157 { 158 perror("ioctl: I_PUSH pf"); 159 exit(1); 160 } 161 if (ioctl(fd, NIOCSETF, &pfil) == -1) 162 { 163 perror("ioctl: NIOCSETF"); 164 exit(1); 165 } 166 /* 167 * arrange to get messages from the NIT STREAM and use NIT_BUF option 168 */ 169 ioctl(fd, I_SRDOPT, (char*)RMSGD); 170 ioctl(fd, I_PUSH, "nbuf"); 171 /* 172 * set the timeout 173 */ 174 timeout = tout; 175 si.ic_timout = 1; 176 to.tv_sec = 1; 177 to.tv_usec = 0; 178 si.ic_cmd = NIOCSTIME; 179 si.ic_len = sizeof(to); 180 si.ic_dp = (char*)&to; 181 if (ioctl(fd, I_STR, (char*)&si) == -1) 182 { 183 perror("ioctl: NIT timeout"); 184 exit(-1); 185 } 186 /* 187 * set the chunksize 188 */ 189 si.ic_cmd = NIOCSCHUNK; 190 si.ic_len = sizeof(chunksize); 191 si.ic_dp = (char*)&chunksize; 192 if (ioctl(fd, I_STR, (char*)&si) == -1) 193 perror("ioctl: NIT chunksize"); 194 if (ioctl(fd, NIOCGCHUNK, (char*)&chunksize) == -1) 195 { 196 perror("ioctl: NIT chunksize"); 197 exit(-1); 198 } 199 printf("NIT buffer size: %d\n", chunksize); 200 201 /* 202 * request the interface 203 */ 204 strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 205 ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = ' '; 206 si.ic_cmd = NIOCBIND; 207 si.ic_len = sizeof(ifr); 208 si.ic_dp = (char*)𝔦 209 if (ioctl(fd, I_STR, (char*)&si) == -1) 210 { 211 perror(ifr.ifr_name); 212 exit(1); 213 } 214 215 /* 216 * set the snapshot length 217 */ 218 si.ic_cmd = NIOCSSNAP; 219 si.ic_len = sizeof(snaplen); 220 si.ic_dp = (char*)&snaplen; 221 if (ioctl(fd, I_STR, (char*)&si) == -1) 222 { 223 perror("ioctl: NIT snaplen"); 224 exit(1); 225 } 226 (void) ioctl(fd, I_FLUSH, (char*)FLUSHR); 227 return fd; 228} 229