diff options
author | ru <ru@FreeBSD.org> | 2001-06-18 15:54:04 +0000 |
---|---|---|
committer | ru <ru@FreeBSD.org> | 2001-06-18 15:54:04 +0000 |
commit | 227ce6056bd3de96b51fd863a66296fc54c951b4 (patch) | |
tree | e8fc4082f747ca16466b1b6882edd1603261c931 | |
parent | 9d7cdee0caf49f464694398c5b692df5cb6eb3b1 (diff) | |
download | FreeBSD-src-227ce6056bd3de96b51fd863a66296fc54c951b4.zip FreeBSD-src-227ce6056bd3de96b51fd863a66296fc54c951b4.tar.gz |
Removed duplicate copies of files already present in sys/contrib/ipfilter.
Not objected to by: -arch
-rw-r--r-- | contrib/ipfilter/fil.c | 2125 | ||||
-rw-r--r-- | contrib/ipfilter/ip_auth.c | 550 | ||||
-rw-r--r-- | contrib/ipfilter/ip_auth.h | 62 | ||||
-rw-r--r-- | contrib/ipfilter/ip_compat.h | 1012 | ||||
-rw-r--r-- | contrib/ipfilter/ip_fil.c | 1758 | ||||
-rw-r--r-- | contrib/ipfilter/ip_fil.h | 631 | ||||
-rw-r--r-- | contrib/ipfilter/ip_frag.c | 555 | ||||
-rw-r--r-- | contrib/ipfilter/ip_frag.h | 66 | ||||
-rw-r--r-- | contrib/ipfilter/ip_ftp_pxy.c | 786 | ||||
-rw-r--r-- | contrib/ipfilter/ip_log.c | 502 | ||||
-rw-r--r-- | contrib/ipfilter/ip_nat.c | 2737 | ||||
-rw-r--r-- | contrib/ipfilter/ip_nat.h | 307 | ||||
-rw-r--r-- | contrib/ipfilter/ip_proxy.c | 451 | ||||
-rw-r--r-- | contrib/ipfilter/ip_proxy.h | 156 | ||||
-rw-r--r-- | contrib/ipfilter/ip_raudio_pxy.c | 308 | ||||
-rw-r--r-- | contrib/ipfilter/ip_rcmd_pxy.c | 173 | ||||
-rw-r--r-- | contrib/ipfilter/ip_state.c | 1901 | ||||
-rw-r--r-- | contrib/ipfilter/ip_state.h | 195 | ||||
-rw-r--r-- | contrib/ipfilter/ipl.h | 17 | ||||
-rw-r--r-- | contrib/ipfilter/mlfk_ipl.c | 197 |
20 files changed, 0 insertions, 14489 deletions
diff --git a/contrib/ipfilter/fil.c b/contrib/ipfilter/fil.c deleted file mode 100644 index 2315a93..0000000 --- a/contrib/ipfilter/fil.c +++ /dev/null @@ -1,2125 +0,0 @@ -/* - * Copyright (C) 1993-2000 by Darren Reed. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - */ -#if !defined(lint) -static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$FreeBSD$"; -#endif - -#include <sys/errno.h> -#include <sys/types.h> -#include <sys/param.h> -#include <sys/time.h> -#include <sys/file.h> -#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \ - defined(_KERNEL) -# include "opt_ipfilter_log.h" -#endif -#if (defined(KERNEL) || defined(_KERNEL)) && defined(__FreeBSD_version) && \ - (__FreeBSD_version >= 220000) -# if (__FreeBSD_version >= 400000) -# ifndef KLD_MODULE -# include "opt_inet6.h" -# endif -# if (__FreeBSD_version == 400019) -# define CSUM_DELAY_DATA -# endif -# endif -# include <sys/filio.h> -# include <sys/fcntl.h> -#else -# include <sys/ioctl.h> -#endif -#if (defined(_KERNEL) || defined(KERNEL)) && !defined(linux) -# include <sys/systm.h> -#else -# include <stdio.h> -# include <string.h> -# include <stdlib.h> -#endif -#include <sys/uio.h> -#if !defined(__SVR4) && !defined(__svr4__) -# ifndef linux -# include <sys/mbuf.h> -# endif -#else -# include <sys/byteorder.h> -# if SOLARIS2 < 5 -# include <sys/dditypes.h> -# endif -# include <sys/stream.h> -#endif -#ifndef linux -# include <sys/protosw.h> -# include <sys/socket.h> -#endif -#include <net/if.h> -#ifdef sun -# include <net/af.h> -#endif -#include <net/route.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#ifndef linux -# include <netinet/ip_var.h> -#endif -#if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */ -# include <sys/hashing.h> -# include <netinet/in_var.h> -#endif -#include <netinet/tcp.h> -#include <netinet/udp.h> -#include <netinet/ip_icmp.h> -#include "netinet/ip_compat.h" -#ifdef USE_INET6 -# include <netinet/icmp6.h> -# if !SOLARIS && defined(_KERNEL) -# include <netinet6/in6_var.h> -# endif -#endif -#include <netinet/tcpip.h> -#include "netinet/ip_fil.h" -#include "netinet/ip_proxy.h" -#include "netinet/ip_nat.h" -#include "netinet/ip_frag.h" -#include "netinet/ip_state.h" -#include "netinet/ip_auth.h" -# if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) -# include <sys/malloc.h> -# if defined(_KERNEL) && !defined(IPFILTER_LKM) -# include "opt_ipfilter.h" -# endif -# endif -#ifndef MIN -# define MIN(a,b) (((a)<(b))?(a):(b)) -#endif -#include "netinet/ipl.h" - -#ifndef _KERNEL -# include "ipf.h" -# include "ipt.h" -extern int opts; - -# define FR_VERBOSE(verb_pr) verbose verb_pr -# define FR_DEBUG(verb_pr) debug verb_pr -# define IPLLOG(a, c, d, e) ipllog() -#else /* #ifndef _KERNEL */ -# define FR_VERBOSE(verb_pr) -# define FR_DEBUG(verb_pr) -# define IPLLOG(a, c, d, e) ipflog(a, c, d, e) -# if SOLARIS || defined(__sgi) -extern KRWLOCK_T ipf_mutex, ipf_auth, ipf_nat; -extern kmutex_t ipf_rw; -# endif -# if SOLARIS -# define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, \ - ip, qif) -# else /* SOLARIS */ -# define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, ip) -# endif /* SOLARIS || __sgi */ -#endif /* _KERNEL */ - - -struct filterstats frstats[2] = {{0,0,0,0,0},{0,0,0,0,0}}; -struct frentry *ipfilter[2][2] = { { NULL, NULL }, { NULL, NULL } }, -#ifdef USE_INET6 - *ipfilter6[2][2] = { { NULL, NULL }, { NULL, NULL } }, - *ipacct6[2][2] = { { NULL, NULL }, { NULL, NULL } }, -#endif - *ipacct[2][2] = { { NULL, NULL }, { NULL, NULL } }; -struct frgroup *ipfgroups[3][2]; -int fr_flags = IPF_LOGGING; -int fr_active = 0; -int fr_chksrc = 0; -int fr_minttl = 3; -int fr_minttllog = 1; -#if defined(IPFILTER_DEFAULT_BLOCK) -int fr_pass = FR_NOMATCH|FR_BLOCK; -#else -int fr_pass = (IPF_DEFAULT_PASS|FR_NOMATCH); -#endif -char ipfilter_version[] = IPL_VERSION; - -fr_info_t frcache[2]; - -static int frflushlist __P((int, minor_t, int *, frentry_t **)); -#ifdef _KERNEL -static void frsynclist __P((frentry_t *)); -#endif - - -/* - * bit values for identifying presence of individual IP options - */ -struct optlist ipopts[20] = { - { IPOPT_NOP, 0x000001 }, - { IPOPT_RR, 0x000002 }, - { IPOPT_ZSU, 0x000004 }, - { IPOPT_MTUP, 0x000008 }, - { IPOPT_MTUR, 0x000010 }, - { IPOPT_ENCODE, 0x000020 }, - { IPOPT_TS, 0x000040 }, - { IPOPT_TR, 0x000080 }, - { IPOPT_SECURITY, 0x000100 }, - { IPOPT_LSRR, 0x000200 }, - { IPOPT_E_SEC, 0x000400 }, - { IPOPT_CIPSO, 0x000800 }, - { IPOPT_SATID, 0x001000 }, - { IPOPT_SSRR, 0x002000 }, - { IPOPT_ADDEXT, 0x004000 }, - { IPOPT_VISA, 0x008000 }, - { IPOPT_IMITD, 0x010000 }, - { IPOPT_EIP, 0x020000 }, - { IPOPT_FINN, 0x040000 }, - { 0, 0x000000 } -}; - -/* - * bit values for identifying presence of individual IP security options - */ -struct optlist secopt[8] = { - { IPSO_CLASS_RES4, 0x01 }, - { IPSO_CLASS_TOPS, 0x02 }, - { IPSO_CLASS_SECR, 0x04 }, - { IPSO_CLASS_RES3, 0x08 }, - { IPSO_CLASS_CONF, 0x10 }, - { IPSO_CLASS_UNCL, 0x20 }, - { IPSO_CLASS_RES2, 0x40 }, - { IPSO_CLASS_RES1, 0x80 } -}; - - -/* - * compact the IP header into a structure which contains just the info. - * which is useful for comparing IP headers with. - */ -void fr_makefrip(hlen, ip, fin) -int hlen; -ip_t *ip; -fr_info_t *fin; -{ - u_short optmsk = 0, secmsk = 0, auth = 0; - int i, mv, ol, off, p, plen, v; - fr_ip_t *fi = &fin->fin_fi; - struct optlist *op; - u_char *s, opt; - tcphdr_t *tcp; - - fin->fin_rev = 0; - fin->fin_fr = NULL; - fin->fin_tcpf = 0; - fin->fin_data[0] = 0; - fin->fin_data[1] = 0; - fin->fin_rule = -1; - fin->fin_group = -1; -#ifdef _KERNEL - fin->fin_icode = ipl_unreach; -#endif - v = fin->fin_v; - fi->fi_v = v; - fin->fin_hlen = hlen; - if (v == 4) { - fin->fin_id = ip->ip_id; - fi->fi_tos = ip->ip_tos; - off = (ip->ip_off & IP_OFFMASK) << 3; - tcp = (tcphdr_t *)((char *)ip + hlen); - (*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4)); - fi->fi_src.i6[1] = 0; - fi->fi_src.i6[2] = 0; - fi->fi_src.i6[3] = 0; - fi->fi_dst.i6[1] = 0; - fi->fi_dst.i6[2] = 0; - fi->fi_dst.i6[3] = 0; - fi->fi_saddr = ip->ip_src.s_addr; - fi->fi_daddr = ip->ip_dst.s_addr; - p = ip->ip_p; - fi->fi_fl = (hlen > sizeof(ip_t)) ? FI_OPTIONS : 0; - if (ip->ip_off & 0x3fff) - fi->fi_fl |= FI_FRAG; - plen = ip->ip_len; - fin->fin_dlen = plen - hlen; - } -#ifdef USE_INET6 - else if (v == 6) { - ip6_t *ip6 = (ip6_t *)ip; - - off = 0; - p = ip6->ip6_nxt; - fi->fi_p = p; - fi->fi_ttl = ip6->ip6_hlim; - tcp = (tcphdr_t *)(ip6 + 1); - fi->fi_src.in6 = ip6->ip6_src; - fi->fi_dst.in6 = ip6->ip6_dst; - fin->fin_id = (u_short)(ip6->ip6_flow & 0xffff); - fi->fi_tos = 0; - fi->fi_fl = 0; - plen = ntohs(ip6->ip6_plen); - fin->fin_dlen = plen; - } -#endif - else - return; - - fin->fin_off = off; - fin->fin_plen = plen; - fin->fin_dp = (void *)tcp; - - switch (p) - { -#ifdef USE_INET6 - case IPPROTO_ICMPV6 : - { - int minicmpsz = sizeof(struct icmp6_hdr); - struct icmp6_hdr *icmp6; - - if (fin->fin_dlen > 1) { - fin->fin_data[0] = *(u_short *)tcp; - - icmp6 = (struct icmp6_hdr *)tcp; - - switch (icmp6->icmp6_type) - { - case ICMP6_ECHO_REPLY : - case ICMP6_ECHO_REQUEST : - minicmpsz = ICMP6ERR_MINPKTLEN; - break; - case ICMP6_DST_UNREACH : - case ICMP6_PACKET_TOO_BIG : - case ICMP6_TIME_EXCEEDED : - case ICMP6_PARAM_PROB : - minicmpsz = ICMP6ERR_IPICMPHLEN; - break; - default : - break; - } - } - - if (!(plen >= hlen + minicmpsz)) - fi->fi_fl |= FI_SHORT; - - break; - } -#endif - case IPPROTO_ICMP : - { - int minicmpsz = sizeof(struct icmp); - icmphdr_t *icmp; - - if (!off && (fin->fin_dlen > 1)) { - fin->fin_data[0] = *(u_short *)tcp; - - icmp = (icmphdr_t *)tcp; - - if (icmp->icmp_type == ICMP_ECHOREPLY || - icmp->icmp_type == ICMP_ECHO) - minicmpsz = ICMP_MINLEN; - - /* - * type(1) + code(1) + cksum(2) + id(2) seq(2) + - * 3*timestamp(3*4) - */ - else if (icmp->icmp_type == ICMP_TSTAMP || - icmp->icmp_type == ICMP_TSTAMPREPLY) - minicmpsz = 20; - - /* - * type(1) + code(1) + cksum(2) + id(2) seq(2) + - * mask(4) - */ - else if (icmp->icmp_type == ICMP_MASKREQ || - icmp->icmp_type == ICMP_MASKREPLY) - minicmpsz = 12; - } - - if ((!(plen >= hlen + minicmpsz) && !off) || - (off && off < sizeof(struct icmp))) - fi->fi_fl |= FI_SHORT; - - break; - } - case IPPROTO_TCP : - fi->fi_fl |= FI_TCPUDP; -#ifdef USE_INET6 - if (v == 6) { - if (plen < sizeof(struct tcphdr)) - fi->fi_fl |= FI_SHORT; - } else -#endif - if (v == 4) { - if ((!IPMINLEN(ip, tcphdr) && !off) || - (off && off < sizeof(struct tcphdr))) - fi->fi_fl |= FI_SHORT; - } - if (!(fi->fi_fl & FI_SHORT) && !off) - fin->fin_tcpf = tcp->th_flags; - goto getports; - case IPPROTO_UDP : - fi->fi_fl |= FI_TCPUDP; -#ifdef USE_INET6 - if (v == 6) { - if (plen < sizeof(struct udphdr)) - fi->fi_fl |= FI_SHORT; - } else -#endif - if (v == 4) { - if ((!IPMINLEN(ip, udphdr) && !off) || - (off && off < sizeof(struct udphdr))) - fi->fi_fl |= FI_SHORT; - } -getports: - if (!off && (fin->fin_dlen > 3)) { - fin->fin_data[0] = ntohs(tcp->th_sport); - fin->fin_data[1] = ntohs(tcp->th_dport); - } - break; - default : - break; - } - -#ifdef USE_INET6 - if (v == 6) { - fi->fi_optmsk = 0; - fi->fi_secmsk = 0; - fi->fi_auth = 0; - return; - } -#endif - - for (s = (u_char *)(ip + 1), hlen -= (int)sizeof(*ip); hlen > 0; ) { - opt = *s; - if (opt == '\0') - break; - else if (opt == IPOPT_NOP) - ol = 1; - else { - if (hlen < 2) - break; - ol = (int)*(s + 1); - if (ol < 2 || ol > hlen) - break; - } - for (i = 9, mv = 4; mv >= 0; ) { - op = ipopts + i; - if (opt == (u_char)op->ol_val) { - optmsk |= op->ol_bit; - if (opt == IPOPT_SECURITY) { - struct optlist *sp; - u_char sec; - int j, m; - - sec = *(s + 2); /* classification */ - for (j = 3, m = 2; m >= 0; ) { - sp = secopt + j; - if (sec == sp->ol_val) { - secmsk |= sp->ol_bit; - auth = *(s + 3); - auth *= 256; - auth += *(s + 4); - break; - } - if (sec < sp->ol_val) - j -= m--; - else - j += m--; - } - } - break; - } - if (opt < op->ol_val) - i -= mv--; - else - i += mv--; - } - hlen -= ol; - s += ol; - } - if (auth && !(auth & 0x0100)) - auth &= 0xff00; - fi->fi_optmsk = optmsk; - fi->fi_secmsk = secmsk; - fi->fi_auth = auth; -} - - -/* - * check an IP packet for TCP/UDP characteristics such as ports and flags. - */ -int fr_tcpudpchk(ft, fin) -frtuc_t *ft; -fr_info_t *fin; -{ - register u_short po, tup; - register char i; - register int err = 1; - - /* - * Both ports should *always* be in the first fragment. - * So far, I cannot find any cases where they can not be. - * - * compare destination ports - */ - if ((i = (int)ft->ftu_dcmp)) { - po = ft->ftu_dport; - tup = fin->fin_data[1]; - /* - * Do opposite test to that required and - * continue if that succeeds. - */ - if (!--i && tup != po) /* EQUAL */ - err = 0; - else if (!--i && tup == po) /* NOTEQUAL */ - err = 0; - else if (!--i && tup >= po) /* LESSTHAN */ - err = 0; - else if (!--i && tup <= po) /* GREATERTHAN */ - err = 0; - else if (!--i && tup > po) /* LT or EQ */ - err = 0; - else if (!--i && tup < po) /* GT or EQ */ - err = 0; - else if (!--i && /* Out of range */ - (tup >= po && tup <= ft->ftu_dtop)) - err = 0; - else if (!--i && /* In range */ - (tup <= po || tup >= ft->ftu_dtop)) - err = 0; - } - /* - * compare source ports - */ - if (err && (i = (int)ft->ftu_scmp)) { - po = ft->ftu_sport; - tup = fin->fin_data[0]; - if (!--i && tup != po) - err = 0; - else if (!--i && tup == po) - err = 0; - else if (!--i && tup >= po) - err = 0; - else if (!--i && tup <= po) - err = 0; - else if (!--i && tup > po) - err = 0; - else if (!--i && tup < po) - err = 0; - else if (!--i && /* Out of range */ - (tup >= po && tup <= ft->ftu_stop)) - err = 0; - else if (!--i && /* In range */ - (tup <= po || tup >= ft->ftu_stop)) - err = 0; - } - - /* - * If we don't have all the TCP/UDP header, then how can we - * expect to do any sort of match on it ? If we were looking for - * TCP flags, then NO match. If not, then match (which should - * satisfy the "short" class too). - */ - if (err && (fin->fin_fi.fi_p == IPPROTO_TCP)) { - if (fin->fin_fi.fi_fl & FI_SHORT) - return !(ft->ftu_tcpf | ft->ftu_tcpfm); - /* - * Match the flags ? If not, abort this match. - */ - if (ft->ftu_tcpfm && - ft->ftu_tcpf != (fin->fin_tcpf & ft->ftu_tcpfm)) { - FR_DEBUG(("f. %#x & %#x != %#x\n", fin->fin_tcpf, - ft->ftu_tcpfm, ft->ftu_tcpf)); - err = 0; - } - } - return err; -} - -/* - * Check the input/output list of rules for a match and result. - * Could be per interface, but this gets real nasty when you don't have - * kernel sauce. - */ -int fr_scanlist(pass, ip, fin, m) -u_32_t pass; -ip_t *ip; -register fr_info_t *fin; -void *m; -{ - register struct frentry *fr; - register fr_ip_t *fi = &fin->fin_fi; - int rulen, portcmp = 0, off, skip = 0, logged = 0; - u_32_t passt; - - fr = fin->fin_fr; - fin->fin_fr = NULL; - fin->fin_rule = 0; - fin->fin_group = 0; - if (fin->fin_v == 4) - off = ip->ip_off & IP_OFFMASK; - else - off = 0; - pass |= (fi->fi_fl << 24); - - if ((fi->fi_fl & FI_TCPUDP) && (fin->fin_dlen > 3) && !off) - portcmp = 1; - - for (rulen = 0; fr; fr = fr->fr_next, rulen++) { - if (skip) { - skip--; - continue; - } - /* - * In all checks below, a null (zero) value in the - * filter struture is taken to mean a wildcard. - * - * check that we are working for the right interface - */ -#ifdef _KERNEL -# if BSD >= 199306 - if (fin->fin_out != 0) { - if ((fr->fr_oifa && - fr->fr_oifa != ((mb_t *)m)->m_pkthdr.rcvif) || - (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp)) - continue; - } else -# endif - if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp) - continue; -#else - if (opts & (OPT_VERBOSE|OPT_DEBUG)) - printf("\n"); - FR_VERBOSE(("%c", (pass & FR_PASS) ? 'p' : - (pass & FR_AUTH) ? 'a' : 'b')); - if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp) - continue; - FR_VERBOSE((":i")); -#endif - { - register u_32_t *ld, *lm, *lip; - register int i; - - lip = (u_32_t *)fi; - lm = (u_32_t *)&fr->fr_mip; - ld = (u_32_t *)&fr->fr_ip; - i = ((*lip & *lm) != *ld); - FR_DEBUG(("0. %#08x & %#08x != %#08x\n", - *lip, *lm, *ld)); - if (i) - continue; - /* - * We now know whether the packet version and the - * rule version match, along with protocol, ttl and - * tos. - */ - lip++, lm++, ld++; - /* - * Unrolled loops (4 each, for 32 bits). - */ - i |= ((*lip & *lm) != *ld) << 19; - FR_DEBUG(("1a. %#08x & %#08x != %#08x\n", - *lip, *lm, *ld)); - if (fi->fi_v == 6) { - lip++, lm++, ld++; - i |= ((*lip & *lm) != *ld) << 19; - FR_DEBUG(("1b. %#08x & %#08x != %#08x\n", - *lip, *lm, *ld)); - lip++, lm++, ld++; - i |= ((*lip & *lm) != *ld) << 19; - FR_DEBUG(("1c. %#08x & %#08x != %#08x\n", - *lip, *lm, *ld)); - lip++, lm++, ld++; - i |= ((*lip & *lm) != *ld) << 19; - FR_DEBUG(("1d. %#08x & %#08x != %#08x\n", - *lip, *lm, *ld)); - } else { - lip += 3; - lm += 3; - ld += 3; - } - i ^= (fr->fr_flags & FR_NOTSRCIP); - if (i) - continue; - lip++, lm++, ld++; - i |= ((*lip & *lm) != *ld) << 20; - FR_DEBUG(("2a. %#08x & %#08x != %#08x\n", - *lip, *lm, *ld)); - if (fi->fi_v == 6) { - lip++, lm++, ld++; - i |= ((*lip & *lm) != *ld) << 20; - FR_DEBUG(("2b. %#08x & %#08x != %#08x\n", - *lip, *lm, *ld)); - lip++, lm++, ld++; - i |= ((*lip & *lm) != *ld) << 20; - FR_DEBUG(("2c. %#08x & %#08x != %#08x\n", - *lip, *lm, *ld)); - lip++, lm++, ld++; - i |= ((*lip & *lm) != *ld) << 20; - FR_DEBUG(("2d. %#08x & %#08x != %#08x\n", - *lip, *lm, *ld)); - } else { - lip += 3; - lm += 3; - ld += 3; - } - i ^= (fr->fr_flags & FR_NOTDSTIP); - if (i) - continue; - lip++, lm++, ld++; - i |= ((*lip & *lm) != *ld); - FR_DEBUG(("3. %#08x & %#08x != %#08x\n", - *lip, *lm, *ld)); - lip++, lm++, ld++; - i |= ((*lip & *lm) != *ld); - FR_DEBUG(("4. %#08x & %#08x != %#08x\n", - *lip, *lm, *ld)); - if (i) - continue; - } - - /* - * If a fragment, then only the first has what we're looking - * for here... - */ - if (!portcmp && (fr->fr_dcmp || fr->fr_scmp || fr->fr_tcpf || - fr->fr_tcpfm)) - continue; - if (fi->fi_fl & FI_TCPUDP) { - if (!fr_tcpudpchk(&fr->fr_tuc, fin)) - continue; - } else if (fr->fr_icmpm || fr->fr_icmp) { - if ((fi->fi_p != IPPROTO_ICMP) || off || - (fin->fin_dlen < 2)) - continue; - if ((fin->fin_data[0] & fr->fr_icmpm) != fr->fr_icmp) { - FR_DEBUG(("i. %#x & %#x != %#x\n", - fin->fin_data[0], fr->fr_icmpm, - fr->fr_icmp)); - continue; - } - } - FR_VERBOSE(("*")); - /* - * Just log this packet... - */ - passt = fr->fr_flags; -#if (BSD >= 199306) && (defined(_KERNEL) || defined(KERNEL)) - if (securelevel <= 0) -#endif - if ((passt & FR_CALLNOW) && fr->fr_func) - passt = (*fr->fr_func)(passt, ip, fin); - fin->fin_fr = fr; -#ifdef IPFILTER_LOG - if ((passt & FR_LOGMASK) == FR_LOG) { - if (!IPLLOG(passt, ip, fin, m)) { - if (passt & FR_LOGORBLOCK) - passt |= FR_BLOCK|FR_QUICK; - ATOMIC_INCL(frstats[fin->fin_out].fr_skip); - } - ATOMIC_INCL(frstats[fin->fin_out].fr_pkl); - logged = 1; - } -#endif /* IPFILTER_LOG */ - if (!(skip = fr->fr_skip) && (passt & FR_LOGMASK) != FR_LOG) - pass = passt; - FR_DEBUG(("pass %#x\n", pass)); - ATOMIC_INCL(fr->fr_hits); - if (pass & FR_ACCOUNT) - fr->fr_bytes += (U_QUAD_T)ip->ip_len; - else - fin->fin_icode = fr->fr_icode; - fin->fin_rule = rulen; - fin->fin_group = fr->fr_group; - if (fr->fr_grp) { - fin->fin_fr = fr->fr_grp; - pass = fr_scanlist(pass, ip, fin, m); - if (fin->fin_fr == NULL) { - fin->fin_rule = rulen; - fin->fin_group = fr->fr_group; - fin->fin_fr = fr; - } - if (pass & FR_DONTCACHE) - logged = 1; - } - if (pass & FR_QUICK) - break; - } - if (logged) - pass |= FR_DONTCACHE; - return pass; -} - - -/* - * frcheck - filter check - * check using source and destination addresses/ports in a packet whether - * or not to pass it on or not. - */ -int fr_check(ip, hlen, ifp, out -#if defined(_KERNEL) && SOLARIS -, qif, mp) -qif_t *qif; -#else -, mp) -#endif -mb_t **mp; -ip_t *ip; -int hlen; -void *ifp; -int out; -{ - /* - * The above really sucks, but short of writing a diff - */ - fr_info_t frinfo, *fc; - register fr_info_t *fin = &frinfo; - int changed, error = EHOSTUNREACH, v = ip->ip_v; - frentry_t *fr = NULL, *list; - u_32_t pass, apass; -#if !SOLARIS || !defined(_KERNEL) - register mb_t *m = *mp; -#endif - -#ifdef _KERNEL - int p, len, drop = 0, logit = 0; - mb_t *mc = NULL; -# if !defined(__SVR4) && !defined(__svr4__) -# ifdef __sgi - char hbuf[(0xf << 2) + sizeof(struct icmp) + sizeof(ip_t) + 8]; -# endif - int up; - -# ifdef M_CANFASTFWD - /* - * XXX For now, IP Filter and fast-forwarding of cached flows - * XXX are mutually exclusive. Eventually, IP Filter should - * XXX get a "can-fast-forward" filter rule. - */ - m->m_flags &= ~M_CANFASTFWD; -# endif /* M_CANFASTFWD */ -# ifdef CSUM_DELAY_DATA - /* - * disable delayed checksums. - */ - if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { - in_delayed_cksum(m); - m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; - } -# endif /* CSUM_DELAY_DATA */ - -# ifdef USE_INET6 - if (v == 6) { - len = ntohs(((ip6_t*)ip)->ip6_plen); - p = ((ip6_t *)ip)->ip6_nxt; - } else -# endif - { - p = ip->ip_p; - len = ip->ip_len; - } - - if ((p == IPPROTO_TCP || p == IPPROTO_UDP || p == IPPROTO_ICMP -# ifdef USE_INET6 - || (v == 6 && p == IPPROTO_ICMPV6) -# endif - )) { - int plen = 0; - - if ((v == 6) || (ip->ip_off & IP_OFFMASK) == 0) - switch(p) - { - case IPPROTO_TCP: - plen = sizeof(tcphdr_t); - break; - case IPPROTO_UDP: - plen = sizeof(udphdr_t); - break; - /* 96 - enough for complete ICMP error IP header */ - case IPPROTO_ICMP: - plen = ICMPERR_MAXPKTLEN - sizeof(ip_t); - break; -# ifdef USE_INET6 - case IPPROTO_ICMPV6 : - /* - * XXX does not take intermediate header - * into account - */ - plen = ICMP6ERR_MINPKTLEN + 8 - sizeof(ip6_t); - break; -# endif - } - up = MIN(hlen + plen, len); - - if (up > m->m_len) { -# ifdef __sgi - /* Under IRIX, avoid m_pullup as it makes ping <hostname> panic */ - if ((up > sizeof(hbuf)) || (m_length(m) < up)) { - ATOMIC_INCL(frstats[out].fr_pull[1]); - return -1; - } - m_copydata(m, 0, up, hbuf); - ATOMIC_INCL(frstats[out].fr_pull[0]); - ip = (ip_t *)hbuf; -# else /* __ sgi */ -# ifndef linux - if ((*mp = m_pullup(m, up)) == 0) { - ATOMIC_INCL(frstats[out].fr_pull[1]); - return -1; - } else { - ATOMIC_INCL(frstats[out].fr_pull[0]); - m = *mp; - ip = mtod(m, ip_t *); - } -# endif /* !linux */ -# endif /* __sgi */ - } else - up = 0; - } else - up = 0; -# endif /* !defined(__SVR4) && !defined(__svr4__) */ -# if SOLARIS - mb_t *m = qif->qf_m; - - if ((u_int)ip & 0x3) - return 2; - fin->fin_qfm = m; - fin->fin_qif = qif; -# endif -#endif /* _KERNEL */ - - /* - * Be careful here: ip_id is in network byte order when called - * from ip_output() - */ - if ((out) && (v == 4)) - ip->ip_id = ntohs(ip->ip_id); - - changed = 0; - fin->fin_ifp = ifp; - fin->fin_v = v; - fin->fin_out = out; - fin->fin_mp = mp; - fr_makefrip(hlen, ip, fin); - -#ifdef _KERNEL -# ifdef USE_INET6 - if (v == 6) { - ATOMIC_INCL(frstats[0].fr_ipv6[out]); - if (((ip6_t *)ip)->ip6_hlim < fr_minttl) { - ATOMIC_INCL(frstats[0].fr_badttl); - if (fr_minttllog) - logit = -2; - } - } else -# endif - if (!out) { - if (fr_chksrc && !fr_verifysrc(ip->ip_src, ifp)) { - ATOMIC_INCL(frstats[0].fr_badsrc); - if (fr_chksrc == 2) - logit = -2; - } else if (ip->ip_ttl < fr_minttl) { - ATOMIC_INCL(frstats[0].fr_badttl); - if (fr_minttllog) - logit = -3; - } - } - if (drop) { -# ifdef IPFILTER_LOG - if (logit) { - fin->fin_group = logit; - pass = FR_INQUE|FR_NOMATCH|FR_LOGB; - (void) IPLLOG(pass, ip, fin, m); - } -# endif -# if !SOLARIS - m_freem(m); -# endif - return error; - } -#endif - pass = fr_pass; - if (fin->fin_fi.fi_fl & FI_SHORT) { - ATOMIC_INCL(frstats[out].fr_short); - } - - READ_ENTER(&ipf_mutex); - - if (fin->fin_fi.fi_fl & FI_SHORT) - ATOMIC_INCL(frstats[out].fr_short); - - /* - * Check auth now. This, combined with the check below to see if apass - * is 0 is to ensure that we don't count the packet twice, which can - * otherwise occur when we reprocess it. As it is, we only count it - * after it has no auth. table matchup. This also stops NAT from - * occuring until after the packet has been auth'd. - */ - apass = fr_checkauth(ip, fin); - - if (!out) { -#ifdef USE_INET6 - if (v == 6) - list = ipacct6[0][fr_active]; - else -#endif - list = ipacct[0][fr_active]; - changed = ip_natin(ip, fin); - if (!apass && (fin->fin_fr = list) && - (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) { - ATOMIC_INCL(frstats[0].fr_acct); - } - } - - if (apass || (!(fr = ipfr_knownfrag(ip, fin)) && - !(fr = fr_checkstate(ip, fin)))) { - /* - * If a packet is found in the auth table, then skip checking - * the access lists for permission but we do need to consider - * the result as if it were from the ACL's. - */ - if (!apass) { - fc = frcache + out; - if (!bcmp((char *)fin, (char *)fc, FI_CSIZE)) { - /* - * copy cached data so we can unlock the mutex - * earlier. - */ - bcopy((char *)fc, (char *)fin, FI_COPYSIZE); - ATOMIC_INCL(frstats[out].fr_chit); - if ((fr = fin->fin_fr)) { - ATOMIC_INCL(fr->fr_hits); - pass = fr->fr_flags; - } - } else { -#ifdef USE_INET6 - if (v == 6) - list = ipfilter6[out][fr_active]; - else -#endif - list = ipfilter[out][fr_active]; - if ((fin->fin_fr = list)) - pass = fr_scanlist(fr_pass, ip, fin, m); - if (!(pass & (FR_KEEPSTATE|FR_DONTCACHE))) - bcopy((char *)fin, (char *)fc, - FI_COPYSIZE); - if (pass & FR_NOMATCH) { - ATOMIC_INCL(frstats[out].fr_nom); - } - } - fr = fin->fin_fr; - } else - pass = apass; - - /* - * If we fail to add a packet to the authorization queue, - * then we drop the packet later. However, if it was added - * then pretend we've dropped it already. - */ - if ((pass & FR_AUTH)) - if (fr_newauth((mb_t *)m, fin, ip) != 0) -#ifdef _KERNEL - m = *mp = NULL; -#else - ; -#endif - - if (pass & FR_PREAUTH) { - READ_ENTER(&ipf_auth); - if ((fin->fin_fr = ipauth) && - (pass = fr_scanlist(0, ip, fin, m))) { - ATOMIC_INCL(fr_authstats.fas_hits); - } else { - ATOMIC_INCL(fr_authstats.fas_miss); - } - RWLOCK_EXIT(&ipf_auth); - } - - fin->fin_fr = fr; - if ((pass & (FR_KEEPFRAG|FR_KEEPSTATE)) == FR_KEEPFRAG) { - if (fin->fin_fi.fi_fl & FI_FRAG) { - if (ipfr_newfrag(ip, fin, pass) == -1) { - ATOMIC_INCL(frstats[out].fr_bnfr); - } else { - ATOMIC_INCL(frstats[out].fr_nfr); - } - } else { - ATOMIC_INCL(frstats[out].fr_cfr); - } - } - if (pass & FR_KEEPSTATE) { - if (fr_addstate(ip, fin, 0) == NULL) { - ATOMIC_INCL(frstats[out].fr_bads); - } else { - ATOMIC_INCL(frstats[out].fr_ads); - } - } - } else if (fr != NULL) { - pass = fr->fr_flags; - if (pass & FR_LOGFIRST) - pass &= ~(FR_LOGFIRST|FR_LOG); - } - -#if (BSD >= 199306) && (defined(_KERNEL) || defined(KERNEL)) - if (securelevel <= 0) -#endif - if (fr && fr->fr_func && !(pass & FR_CALLNOW)) - pass = (*fr->fr_func)(pass, ip, fin); - - /* - * Only count/translate packets which will be passed on, out the - * interface. - */ - if (out && (pass & FR_PASS)) { -#ifdef USE_INET6 - if (v == 6) - list = ipacct6[1][fr_active]; - else -#endif - list = ipacct[1][fr_active]; - if ((fin->fin_fr = list) && - (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) { - ATOMIC_INCL(frstats[1].fr_acct); - } - fin->fin_fr = fr; - changed = ip_natout(ip, fin); - } else - fin->fin_fr = fr; - RWLOCK_EXIT(&ipf_mutex); - -#ifdef IPFILTER_LOG - if ((fr_flags & FF_LOGGING) || (pass & FR_LOGMASK)) { - if ((fr_flags & FF_LOGNOMATCH) && (pass & FR_NOMATCH)) { - pass |= FF_LOGNOMATCH; - ATOMIC_INCL(frstats[out].fr_npkl); - goto logit; - } else if (((pass & FR_LOGMASK) == FR_LOGP) || - ((pass & FR_PASS) && (fr_flags & FF_LOGPASS))) { - if ((pass & FR_LOGMASK) != FR_LOGP) - pass |= FF_LOGPASS; - ATOMIC_INCL(frstats[out].fr_ppkl); - goto logit; - } else if (((pass & FR_LOGMASK) == FR_LOGB) || - ((pass & FR_BLOCK) && (fr_flags & FF_LOGBLOCK))) { - if ((pass & FR_LOGMASK) != FR_LOGB) - pass |= FF_LOGBLOCK; - ATOMIC_INCL(frstats[out].fr_bpkl); -logit: - if (!IPLLOG(pass, ip, fin, m)) { - ATOMIC_INCL(frstats[out].fr_skip); - if ((pass & (FR_PASS|FR_LOGORBLOCK)) == - (FR_PASS|FR_LOGORBLOCK)) - pass ^= FR_PASS|FR_BLOCK; - } - } - } -#endif /* IPFILTER_LOG */ - - if ((out) && (v == 4)) - ip->ip_id = htons(ip->ip_id); - -#ifdef _KERNEL - /* - * Only allow FR_DUP to work if a rule matched - it makes no sense to - * set FR_DUP as a "default" as there are no instructions about where - * to send the packet. - */ - if (fr && (pass & FR_DUP)) -# if SOLARIS - mc = dupmsg(m); -# else -# ifndef linux - mc = m_copy(m, 0, M_COPYALL); -# else - ; -# endif -# endif -#endif - if (pass & FR_PASS) { - ATOMIC_INCL(frstats[out].fr_pass); - } else if (pass & FR_BLOCK) { - ATOMIC_INCL(frstats[out].fr_block); - /* - * Should we return an ICMP packet to indicate error - * status passing through the packet filter ? - * WARNING: ICMP error packets AND TCP RST packets should - * ONLY be sent in repsonse to incoming packets. Sending them - * in response to outbound packets can result in a panic on - * some operating systems. - */ - if (!out) { -#ifdef _KERNEL - if (pass & FR_RETICMP) { - int dst; - - if ((pass & FR_RETMASK) == FR_FAKEICMP) - dst = 1; - else - dst = 0; - send_icmp_err(ip, ICMP_UNREACH, fin, dst); - ATOMIC_INCL(frstats[0].fr_ret); - } else if (((pass & FR_RETMASK) == FR_RETRST) && - !(fin->fin_fi.fi_fl & FI_SHORT)) { - if (send_reset(ip, fin) == 0) { - ATOMIC_INCL(frstats[1].fr_ret); - } - } -#else - if ((pass & FR_RETMASK) == FR_RETICMP) { - verbose("- ICMP unreachable sent\n"); - ATOMIC_INCL(frstats[0].fr_ret); - } else if ((pass & FR_RETMASK) == FR_FAKEICMP) { - verbose("- forged ICMP unreachable sent\n"); - ATOMIC_INCL(frstats[0].fr_ret); - } else if (((pass & FR_RETMASK) == FR_RETRST) && - !(fin->fin_fi.fi_fl & FI_SHORT)) { - verbose("- TCP RST sent\n"); - ATOMIC_INCL(frstats[1].fr_ret); - } -#endif - } else { - if (pass & FR_RETRST) - error = ECONNRESET; - } - } - - /* - * If we didn't drop off the bottom of the list of rules (and thus - * the 'current' rule fr is not NULL), then we may have some extra - * instructions about what to do with a packet. - * Once we're finished return to our caller, freeing the packet if - * we are dropping it (* BSD ONLY *). - */ - if ((changed == -1) && (pass & FR_PASS)) { - pass &= ~FR_PASS; - pass |= FR_BLOCK; - } -#if defined(_KERNEL) -# if !SOLARIS -# if !defined(linux) - if (fr) { - frdest_t *fdp = &fr->fr_tif; - - if (((pass & FR_FASTROUTE) && !out) || - (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) { - if (ipfr_fastroute(m, fin, fdp) == 0) - m = *mp = NULL; - } - if (mc) - ipfr_fastroute(mc, fin, &fr->fr_dif); - } - if (!(pass & FR_PASS) && m) - m_freem(m); -# ifdef __sgi - else if (changed && up && m) - m_copyback(m, 0, up, hbuf); -# endif -# endif /* !linux */ -# else /* !SOLARIS */ - if (fr) { - frdest_t *fdp = &fr->fr_tif; - - if (((pass & FR_FASTROUTE) && !out) || - (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) { - if (ipfr_fastroute(ip, m, mp, fin, fdp) == 0) - m = *mp = NULL; - } - if (mc) - ipfr_fastroute(ip, mc, mp, fin, &fr->fr_dif); - } -# endif /* !SOLARIS */ - return (pass & FR_PASS) ? 0 : error; -#else /* _KERNEL */ - if (pass & FR_NOMATCH) - return 1; - if (pass & FR_PASS) - return 0; - if (pass & FR_AUTH) - return -2; - return -1; -#endif /* _KERNEL */ -} - - -/* - * ipf_cksum - * addr should be 16bit aligned and len is in bytes. - * length is in bytes - */ -u_short ipf_cksum(addr, len) -register u_short *addr; -register int len; -{ - register u_32_t sum = 0; - - for (sum = 0; len > 1; len -= 2) - sum += *addr++; - - /* mop up an odd byte, if necessary */ - if (len == 1) - sum += *(u_char *)addr; - - /* - * add back carry outs from top 16 bits to low 16 bits - */ - sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ - sum += (sum >> 16); /* add carry */ - return (u_short)(~sum); -} - - -/* - * NB: This function assumes we've pullup'd enough for all of the IP header - * and the TCP header. We also assume that data blocks aren't allocated in - * odd sizes. - */ -u_short fr_tcpsum(m, ip, tcp) -mb_t *m; -ip_t *ip; -tcphdr_t *tcp; -{ - u_short *sp, slen, ts; - u_int sum, sum2; - int hlen; - - /* - * Add up IP Header portion - */ - hlen = ip->ip_hl << 2; - slen = ip->ip_len - hlen; - sum = htons((u_short)ip->ip_p); - sum += htons(slen); - sp = (u_short *)&ip->ip_src; - sum += *sp++; /* ip_src */ - sum += *sp++; - sum += *sp++; /* ip_dst */ - sum += *sp++; - ts = tcp->th_sum; - tcp->th_sum = 0; -#ifdef KERNEL -# if SOLARIS - sum2 = ip_cksum(m, hlen, sum); /* hlen == offset */ - sum2 = (sum2 & 0xffff) + (sum2 >> 16); - sum2 = ~sum2 & 0xffff; -# else /* SOLARIS */ -# if defined(BSD) || defined(sun) -# if BSD >= 199306 - m->m_data += hlen; -# else - m->m_off += hlen; -# endif - m->m_len -= hlen; - sum2 = in_cksum(m, slen); - m->m_len += hlen; -# if BSD >= 199306 - m->m_data -= hlen; -# else - m->m_off -= hlen; -# endif - /* - * Both sum and sum2 are partial sums, so combine them together. - */ - sum = (sum & 0xffff) + (sum >> 16); - sum = ~sum & 0xffff; - sum2 += sum; - sum2 = (sum2 & 0xffff) + (sum2 >> 16); -# else /* defined(BSD) || defined(sun) */ -{ - union { - u_char c[2]; - u_short s; - } bytes; - u_short len = ip->ip_len; -# if defined(__sgi) - int add; -# endif - - /* - * Add up IP Header portion - */ - sp = (u_short *)&ip->ip_src; - len -= (ip->ip_hl << 2); - sum = ntohs(IPPROTO_TCP); - sum += htons(len); - sum += *sp++; /* ip_src */ - sum += *sp++; - sum += *sp++; /* ip_dst */ - sum += *sp++; - if (sp != (u_short *)tcp) - sp = (u_short *)tcp; - sum += *sp++; /* sport */ - sum += *sp++; /* dport */ - sum += *sp++; /* seq */ - sum += *sp++; - sum += *sp++; /* ack */ - sum += *sp++; - sum += *sp++; /* off */ - sum += *sp++; /* win */ - sum += *sp++; /* Skip over checksum */ - sum += *sp++; /* urp */ - -# ifdef __sgi - /* - * In case we had to copy the IP & TCP header out of mbufs, - * skip over the mbuf bits which are the header - */ - if ((caddr_t)ip != mtod(m, caddr_t)) { - hlen = (caddr_t)sp - (caddr_t)ip; - while (hlen) { - add = MIN(hlen, m->m_len); - sp = (u_short *)(mtod(m, caddr_t) + add); - hlen -= add; - if (add == m->m_len) { - m = m->m_next; - if (!hlen) { - if (!m) - break; - sp = mtod(m, u_short *); - } - PANIC((!m),("fr_tcpsum(1): not enough data")); - } - } - } -# endif - - if (!(len -= sizeof(*tcp))) - goto nodata; - while (len > 1) { - if (((caddr_t)sp - mtod(m, caddr_t)) >= m->m_len) { - m = m->m_next; - PANIC((!m),("fr_tcpsum(2): not enough data")); - sp = mtod(m, u_short *); - } - if (((caddr_t)(sp + 1) - mtod(m, caddr_t)) > m->m_len) { - bytes.c[0] = *(u_char *)sp; - m = m->m_next; - PANIC((!m),("fr_tcpsum(3): not enough data")); - sp = mtod(m, u_short *); - bytes.c[1] = *(u_char *)sp; - sum += bytes.s; - sp = (u_short *)((u_char *)sp + 1); - } - if ((u_long)sp & 1) { - bcopy((char *)sp++, (char *)&bytes.s, sizeof(bytes.s)); - sum += bytes.s; - } else - sum += *sp++; - len -= 2; - } - if (len) - sum += ntohs(*(u_char *)sp << 8); -nodata: - while (sum > 0xffff) - sum = (sum & 0xffff) + (sum >> 16); - sum2 = (u_short)(~sum & 0xffff); -} -# endif /* defined(BSD) || defined(sun) */ -# endif /* SOLARIS */ -#else /* KERNEL */ - sum2 = 0; -#endif /* KERNEL */ - tcp->th_sum = ts; - return sum2; -} - - -#if defined(_KERNEL) && ( ((BSD < 199306) && !SOLARIS) || defined(__sgi) ) -/* - * Copyright (c) 1982, 1986, 1988, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 - * $Id: fil.c,v 2.35.2.30 2000/12/17 05:49:22 darrenr Exp $ - */ -/* - * Copy data from an mbuf chain starting "off" bytes from the beginning, - * continuing for "len" bytes, into the indicated buffer. - */ -void -m_copydata(m, off, len, cp) - register mb_t *m; - register int off; - register int len; - caddr_t cp; -{ - register unsigned count; - - if (off < 0 || len < 0) - panic("m_copydata"); - while (off > 0) { - if (m == 0) - panic("m_copydata"); - if (off < m->m_len) - break; - off -= m->m_len; - m = m->m_next; - } - while (len > 0) { - if (m == 0) - panic("m_copydata"); - count = MIN(m->m_len - off, len); - bcopy(mtod(m, caddr_t) + off, cp, count); - len -= count; - cp += count; - off = 0; - m = m->m_next; - } -} - - -# ifndef linux -/* - * Copy data from a buffer back into the indicated mbuf chain, - * starting "off" bytes from the beginning, extending the mbuf - * chain if necessary. - */ -void -m_copyback(m0, off, len, cp) - struct mbuf *m0; - register int off; - register int len; - caddr_t cp; -{ - register int mlen; - register struct mbuf *m = m0, *n; - int totlen = 0; - - if (m0 == 0) - return; - while (off > (mlen = m->m_len)) { - off -= mlen; - totlen += mlen; - if (m->m_next == 0) { - n = m_getclr(M_DONTWAIT, m->m_type); - if (n == 0) - goto out; - n->m_len = min(MLEN, len + off); - m->m_next = n; - } - m = m->m_next; - } - while (len > 0) { - mlen = min (m->m_len - off, len); - bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen); - cp += mlen; - len -= mlen; - mlen += off; - off = 0; - totlen += mlen; - if (len == 0) - break; - if (m->m_next == 0) { - n = m_get(M_DONTWAIT, m->m_type); - if (n == 0) - break; - n->m_len = min(MLEN, len); - m->m_next = n; - } - m = m->m_next; - } -out: -#if 0 - if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen)) - m->m_pkthdr.len = totlen; -#endif - return; -} -# endif /* linux */ -#endif /* (_KERNEL) && ( ((BSD < 199306) && !SOLARIS) || __sgi) */ - - -frgroup_t *fr_findgroup(num, flags, which, set, fgpp) -u_32_t num, flags; -minor_t which; -int set; -frgroup_t ***fgpp; -{ - frgroup_t *fg, **fgp; - - if (which == IPL_LOGAUTH) - fgp = &ipfgroups[2][set]; - else if (flags & FR_ACCOUNT) - fgp = &ipfgroups[1][set]; - else if (flags & (FR_OUTQUE|FR_INQUE)) - fgp = &ipfgroups[0][set]; - else - return NULL; - num &= 0xffff; - - while ((fg = *fgp)) - if (fg->fg_num == num) - break; - else - fgp = &fg->fg_next; - if (fgpp) - *fgpp = fgp; - return fg; -} - - -frgroup_t *fr_addgroup(num, fp, which, set) -u_32_t num; -frentry_t *fp; -minor_t which; -int set; -{ - frgroup_t *fg, **fgp; - - if ((fg = fr_findgroup(num, fp->fr_flags, which, set, &fgp))) - return fg; - - KMALLOC(fg, frgroup_t *); - if (fg) { - fg->fg_num = num; - fg->fg_next = *fgp; - fg->fg_head = fp; - fg->fg_start = &fp->fr_grp; - *fgp = fg; - } - return fg; -} - - -void fr_delgroup(num, flags, which, set) -u_32_t num, flags; -minor_t which; -int set; -{ - frgroup_t *fg, **fgp; - - if (!(fg = fr_findgroup(num, flags, which, set, &fgp))) - return; - - *fgp = fg->fg_next; - KFREE(fg); -} - - - -/* - * recursively flush rules from the list, descending groups as they are - * encountered. if a rule is the head of a group and it has lost all its - * group members, then also delete the group reference. - */ -static int frflushlist(set, unit, nfreedp, listp) -int set; -minor_t unit; -int *nfreedp; -frentry_t **listp; -{ - register int freed = 0, i; - register frentry_t *fp; - - while ((fp = *listp)) { - *listp = fp->fr_next; - if (fp->fr_grp) { - i = frflushlist(set, unit, nfreedp, &fp->fr_grp); - MUTEX_ENTER(&ipf_rw); - fp->fr_ref -= i; - MUTEX_EXIT(&ipf_rw); - } - - ATOMIC_DEC32(fp->fr_ref); - if (fp->fr_grhead) { - fr_delgroup(fp->fr_grhead, fp->fr_flags, - unit, set); - fp->fr_grhead = 0; - } - if (fp->fr_ref == 0) { - KFREE(fp); - freed++; - } else - fp->fr_next = NULL; - } - *nfreedp += freed; - return freed; -} - - -int frflush(unit, flags) -minor_t unit; -int flags; -{ - int flushed = 0, set; - - if (unit != IPL_LOGIPF) - return 0; - WRITE_ENTER(&ipf_mutex); - bzero((char *)frcache, sizeof(frcache[0]) * 2); - - set = fr_active; - if (flags & FR_INACTIVE) - set = 1 - set; - - if (flags & FR_OUTQUE) { -#ifdef USE_INET6 - (void) frflushlist(set, unit, &flushed, &ipfilter6[1][set]); - (void) frflushlist(set, unit, &flushed, &ipacct6[1][set]); -#endif - (void) frflushlist(set, unit, &flushed, &ipfilter[1][set]); - (void) frflushlist(set, unit, &flushed, &ipacct[1][set]); - } - if (flags & FR_INQUE) { -#ifdef USE_INET6 - (void) frflushlist(set, unit, &flushed, &ipfilter6[0][set]); - (void) frflushlist(set, unit, &flushed, &ipacct6[0][set]); -#endif - (void) frflushlist(set, unit, &flushed, &ipfilter[0][set]); - (void) frflushlist(set, unit, &flushed, &ipacct[0][set]); - } - RWLOCK_EXIT(&ipf_mutex); - return flushed; -} - - -char *memstr(src, dst, slen, dlen) -char *src, *dst; -int slen, dlen; -{ - char *s = NULL; - - while (dlen >= slen) { - if (bcmp(src, dst, slen) == 0) { - s = dst; - break; - } - dst++; - dlen--; - } - return s; -} - - -void fixskip(listp, rp, addremove) -frentry_t **listp, *rp; -int addremove; -{ - frentry_t *fp; - int rules = 0, rn = 0; - - for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rules++) - ; - - if (!fp) - return; - - for (fp = *listp; fp && (fp != rp); fp = fp->fr_next, rn++) - if (fp->fr_skip && (rn + fp->fr_skip >= rules)) - fp->fr_skip += addremove; -} - - -#ifdef _KERNEL -/* - * count consecutive 1's in bit mask. If the mask generated by counting - * consecutive 1's is different to that passed, return -1, else return # - * of bits. - */ -int countbits(ip) -u_32_t ip; -{ - u_32_t ipn; - int cnt = 0, i, j; - - ip = ipn = ntohl(ip); - for (i = 32; i; i--, ipn *= 2) - if (ipn & 0x80000000) - cnt++; - else - break; - ipn = 0; - for (i = 32, j = cnt; i; i--, j--) { - ipn *= 2; - if (j > 0) - ipn++; - } - if (ipn == ip) - return cnt; - return -1; -} - - -/* - * return the first IP Address associated with an interface - */ -int fr_ifpaddr(v, ifptr, inp) -int v; -void *ifptr; -struct in_addr *inp; -{ -# ifdef USE_INET6 - struct in6_addr *inp6 = NULL; -# endif -# if SOLARIS - ill_t *ill = ifptr; -# else - struct ifnet *ifp = ifptr; -# endif - struct in_addr in; - -# if SOLARIS -# ifdef USE_INET6 - if (v == 6) { - struct in6_addr in6; - - /* - * First is always link local. - */ - if (ill->ill_ipif->ipif_next) - in6 = ill->ill_ipif->ipif_next->ipif_v6lcl_addr; - else - bzero((char *)&in6, sizeof(in6)); - bcopy((char *)&in6, (char *)inp, sizeof(in6)); - } else -# endif - { - in.s_addr = ill->ill_ipif->ipif_local_addr; - *inp = in; - } -# else /* SOLARIS */ -# if linux - ; -# else /* linux */ - struct sockaddr_in *sin; - struct ifaddr *ifa; - -# if (__FreeBSD_version >= 300000) - ifa = TAILQ_FIRST(&ifp->if_addrhead); -# else -# if defined(__NetBSD__) || defined(__OpenBSD__) - ifa = ifp->if_addrlist.tqh_first; -# else -# if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */ - ifa = &((struct in_ifaddr *)ifp->in_ifaddr)->ia_ifa; -# else - ifa = ifp->if_addrlist; -# endif -# endif /* __NetBSD__ || __OpenBSD__ */ -# endif /* __FreeBSD_version >= 300000 */ -# if (BSD < 199306) && !(/*IRIX6*/defined(__sgi) && defined(IFF_DRVRLOCK)) - sin = (struct sockaddr_in *)&ifa->ifa_addr; -# else - sin = (struct sockaddr_in *)ifa->ifa_addr; - while (sin && ifa) { - if ((v == 4) && (sin->sin_family == AF_INET)) - break; -# ifdef USE_INET6 - if ((v == 6) && (sin->sin_family == AF_INET6)) { - inp6 = &((struct sockaddr_in6 *)sin)->sin6_addr; - if (!IN6_IS_ADDR_LINKLOCAL(inp6) && - !IN6_IS_ADDR_LOOPBACK(inp6)) - break; - } -# endif -# if (__FreeBSD_version >= 300000) - ifa = TAILQ_NEXT(ifa, ifa_link); -# else -# if defined(__NetBSD__) || defined(__OpenBSD__) - ifa = ifa->ifa_list.tqe_next; -# else - ifa = ifa->ifa_next; -# endif -# endif /* __FreeBSD_version >= 300000 */ - if (ifa) - sin = (struct sockaddr_in *)ifa->ifa_addr; - } - if (ifa == NULL) - sin = NULL; - if (sin == NULL) - return -1; -# endif /* (BSD < 199306) && (!__sgi && IFF_DRVLOCK) */ -# ifdef USE_INET6 - if (v == 6) - bcopy((char *)inp6, (char *)inp, sizeof(*inp6)); - else -# endif - { - in = sin->sin_addr; - *inp = in; - } -# endif /* linux */ -# endif /* SOLARIS */ - return 0; -} - - -static void frsynclist(fr) -register frentry_t *fr; -{ - for (; fr; fr = fr->fr_next) { - if (fr->fr_ifa != NULL) { - fr->fr_ifa = GETUNIT(fr->fr_ifname, fr->fr_ip.fi_v); - if (fr->fr_ifa == NULL) - fr->fr_ifa = (void *)-1; - } - if (fr->fr_grp) - frsynclist(fr->fr_grp); - } -} - - -void frsync() -{ -# if !SOLARIS - register struct ifnet *ifp; - -# if defined(__OpenBSD__) || ((NetBSD >= 199511) && (NetBSD < 1991011)) || \ - (defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)) -# if (NetBSD >= 199905) || defined(__OpenBSD__) - for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) -# else - for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) -# endif -# else - for (ifp = ifnet; ifp; ifp = ifp->if_next) -# endif - { - ip_natsync(ifp); - ip_statesync(ifp); - } - ip_natsync((struct ifnet *)-1); -# endif - - WRITE_ENTER(&ipf_mutex); - frsynclist(ipacct[0][fr_active]); - frsynclist(ipacct[1][fr_active]); - frsynclist(ipfilter[0][fr_active]); - frsynclist(ipfilter[1][fr_active]); -#ifdef USE_INET6 - frsynclist(ipacct6[0][fr_active]); - frsynclist(ipacct6[1][fr_active]); - frsynclist(ipfilter6[0][fr_active]); - frsynclist(ipfilter6[1][fr_active]); -#endif - RWLOCK_EXIT(&ipf_mutex); -} - - -/* - * In the functions below, bcopy() is called because the pointer being - * copied _from_ in this instance is a pointer to a char buf (which could - * end up being unaligned) and on the kernel's local stack. - */ -int ircopyptr(a, b, c) -void *a, *b; -size_t c; -{ - caddr_t ca; - int err; - -#if SOLARIS - if (copyin(a, (char *)&ca, sizeof(ca))) - return EFAULT; -#else - bcopy(a, &ca, sizeof(ca)); -#endif - err = copyin(ca, b, c); - if (err) - err = EFAULT; - return err; -} - - -int iwcopyptr(a, b, c) -void *a, *b; -size_t c; -{ - caddr_t ca; - int err; - -#if SOLARIS - if (copyin(b, (char *)&ca, sizeof(ca))) - return EFAULT; -#else - bcopy(b, &ca, sizeof(ca)); -#endif - err = copyout(a, ca, c); - if (err) - err = EFAULT; - return err; -} - -#else /* _KERNEL */ - - -/* - * return the first IP Address associated with an interface - */ -int fr_ifpaddr(v, ifptr, inp) -int v; -void *ifptr; -struct in_addr *inp; -{ - return 0; -} - - -int ircopyptr(a, b, c) -void *a, *b; -size_t c; -{ - caddr_t ca; - - bcopy(a, &ca, sizeof(ca)); - bcopy(ca, b, c); - return 0; -} - - -int iwcopyptr(a, b, c) -void *a, *b; -size_t c; -{ - caddr_t ca; - - bcopy(b, &ca, sizeof(ca)); - bcopy(a, ca, c); - return 0; -} - - -#endif - - -int fr_lock(data, lockp) -caddr_t data; -int *lockp; -{ - int arg, error; - - error = IRCOPY(data, (caddr_t)&arg, sizeof(arg)); - if (!error) { - error = IWCOPY((caddr_t)lockp, data, sizeof(*lockp)); - if (!error) - *lockp = arg; - } - return error; -} - - -void fr_getstat(fiop) -friostat_t *fiop; -{ - bcopy((char *)frstats, (char *)fiop->f_st, sizeof(filterstats_t) * 2); - fiop->f_locks[0] = fr_state_lock; - fiop->f_locks[1] = fr_nat_lock; - fiop->f_locks[2] = fr_frag_lock; - fiop->f_locks[3] = fr_auth_lock; - fiop->f_fin[0] = ipfilter[0][0]; - fiop->f_fin[1] = ipfilter[0][1]; - fiop->f_fout[0] = ipfilter[1][0]; - fiop->f_fout[1] = ipfilter[1][1]; - fiop->f_acctin[0] = ipacct[0][0]; - fiop->f_acctin[1] = ipacct[0][1]; - fiop->f_acctout[0] = ipacct[1][0]; - fiop->f_acctout[1] = ipacct[1][1]; -#ifdef USE_INET6 - fiop->f_fin6[0] = ipfilter6[0][0]; - fiop->f_fin6[1] = ipfilter6[0][1]; - fiop->f_fout6[0] = ipfilter6[1][0]; - fiop->f_fout6[1] = ipfilter6[1][1]; - fiop->f_acctin6[0] = ipacct6[0][0]; - fiop->f_acctin6[1] = ipacct6[0][1]; - fiop->f_acctout6[0] = ipacct6[1][0]; - fiop->f_acctout6[1] = ipacct6[1][1]; -#else - fiop->f_fin6[0] = NULL; - fiop->f_fin6[1] = NULL; - fiop->f_fout6[0] = NULL; - fiop->f_fout6[1] = NULL; - fiop->f_acctin6[0] = NULL; - fiop->f_acctin6[1] = NULL; - fiop->f_acctout6[0] = NULL; - fiop->f_acctout6[1] = NULL; -#endif - fiop->f_active = fr_active; - fiop->f_froute[0] = ipl_frouteok[0]; - fiop->f_froute[1] = ipl_frouteok[1]; - - fiop->f_running = fr_running; - fiop->f_groups[0][0] = ipfgroups[0][0]; - fiop->f_groups[0][1] = ipfgroups[0][1]; - fiop->f_groups[1][0] = ipfgroups[1][0]; - fiop->f_groups[1][1] = ipfgroups[1][1]; - fiop->f_groups[2][0] = ipfgroups[2][0]; - fiop->f_groups[2][1] = ipfgroups[2][1]; -#ifdef IPFILTER_LOG - fiop->f_logging = 1; -#else - fiop->f_logging = 0; -#endif - fiop->f_defpass = fr_pass; - strncpy(fiop->f_version, ipfilter_version, sizeof(fiop->f_version)); -} - - -#ifdef USE_INET6 -int icmptoicmp6types[ICMP_MAXTYPE+1] = { - ICMP6_ECHO_REPLY, /* 0: ICMP_ECHOREPLY */ - -1, /* 1: UNUSED */ - -1, /* 2: UNUSED */ - ICMP6_DST_UNREACH, /* 3: ICMP_UNREACH */ - -1, /* 4: ICMP_SOURCEQUENCH */ - ND_REDIRECT, /* 5: ICMP_REDIRECT */ - -1, /* 6: UNUSED */ - -1, /* 7: UNUSED */ - ICMP6_ECHO_REQUEST, /* 8: ICMP_ECHO */ - -1, /* 9: UNUSED */ - -1, /* 10: UNUSED */ - ICMP6_TIME_EXCEEDED, /* 11: ICMP_TIMXCEED */ - ICMP6_PARAM_PROB, /* 12: ICMP_PARAMPROB */ - -1, /* 13: ICMP_TSTAMP */ - -1, /* 14: ICMP_TSTAMPREPLY */ - -1, /* 15: ICMP_IREQ */ - -1, /* 16: ICMP_IREQREPLY */ - -1, /* 17: ICMP_MASKREQ */ - -1, /* 18: ICMP_MASKREPLY */ -}; - - -int icmptoicmp6unreach[ICMP_MAX_UNREACH] = { - ICMP6_DST_UNREACH_ADDR, /* 0: ICMP_UNREACH_NET */ - ICMP6_DST_UNREACH_ADDR, /* 1: ICMP_UNREACH_HOST */ - -1, /* 2: ICMP_UNREACH_PROTOCOL */ - ICMP6_DST_UNREACH_NOPORT, /* 3: ICMP_UNREACH_PORT */ - -1, /* 4: ICMP_UNREACH_NEEDFRAG */ - ICMP6_DST_UNREACH_NOTNEIGHBOR, /* 5: ICMP_UNREACH_SRCFAIL */ - ICMP6_DST_UNREACH_ADDR, /* 6: ICMP_UNREACH_NET_UNKNOWN */ - ICMP6_DST_UNREACH_ADDR, /* 7: ICMP_UNREACH_HOST_UNKNOWN */ - -1, /* 8: ICMP_UNREACH_ISOLATED */ - ICMP6_DST_UNREACH_ADMIN, /* 9: ICMP_UNREACH_NET_PROHIB */ - ICMP6_DST_UNREACH_ADMIN, /* 10: ICMP_UNREACH_HOST_PROHIB */ - -1, /* 11: ICMP_UNREACH_TOSNET */ - -1, /* 12: ICMP_UNREACH_TOSHOST */ - ICMP6_DST_UNREACH_ADMIN, /* 13: ICMP_UNREACH_ADMIN_PROHIBIT */ -}; -#endif diff --git a/contrib/ipfilter/ip_auth.c b/contrib/ipfilter/ip_auth.c deleted file mode 100644 index a453610..0000000 --- a/contrib/ipfilter/ip_auth.c +++ /dev/null @@ -1,550 +0,0 @@ -/* - * Copyright (C) 1998-2000 by Darren Reed & Guido van Rooij. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - */ -#if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_auth.c,v 2.11.2.5 2001/01/10 06:18:35 darrenr Exp $"; -#endif - -#include <sys/errno.h> -#include <sys/types.h> -#include <sys/param.h> -#include <sys/time.h> -#include <sys/file.h> -#if !defined(_KERNEL) && !defined(KERNEL) -# include <stdio.h> -# include <stdlib.h> -# include <string.h> -#endif -#if (defined(KERNEL) || defined(_KERNEL)) && (__FreeBSD_version >= 220000) -# include <sys/filio.h> -# include <sys/fcntl.h> -#else -# include <sys/ioctl.h> -#endif -#include <sys/uio.h> -#ifndef linux -# include <sys/protosw.h> -#endif -#include <sys/socket.h> -#if (defined(_KERNEL) || defined(KERNEL)) && !defined(linux) -# include <sys/systm.h> -#endif -#if !defined(__SVR4) && !defined(__svr4__) -# ifndef linux -# include <sys/mbuf.h> -# endif -#else -# include <sys/filio.h> -# include <sys/byteorder.h> -# ifdef _KERNEL -# include <sys/dditypes.h> -# endif -# include <sys/stream.h> -# include <sys/kmem.h> -#endif -#if (_BSDI_VERSION >= 199802) || (__FreeBSD_version >= 400000) -# include <sys/queue.h> -#endif -#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(bsdi) -# include <machine/cpu.h> -#endif -#include <net/if.h> -#ifdef sun -# include <net/af.h> -#endif -#include <net/route.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#ifndef KERNEL -# define KERNEL -# define NOT_KERNEL -#endif -#ifndef linux -# include <netinet/ip_var.h> -#endif -#ifdef NOT_KERNEL -# undef KERNEL -#endif -#ifdef __sgi -# ifdef IFF_DRVRLOCK /* IRIX6 */ -# include <sys/hashing.h> -# endif -#endif -#include <netinet/tcp.h> -#if defined(__sgi) && !defined(IFF_DRVRLOCK) /* IRIX < 6 */ -extern struct ifqueue ipintrq; /* ip packet input queue */ -#else -# ifndef linux -# if __FreeBSD_version >= 300000 -# include <net/if_var.h> -# endif -# include <netinet/in_var.h> -# include <netinet/tcp_fsm.h> -# endif -#endif -#include <netinet/udp.h> -#include <netinet/ip_icmp.h> -#include "netinet/ip_compat.h" -#include <netinet/tcpip.h> -#include "netinet/ip_fil.h" -#include "netinet/ip_auth.h" -#if !SOLARIS && !defined(linux) -# include <net/netisr.h> -# ifdef __FreeBSD__ -# include <machine/cpufunc.h> -# endif -#endif -#if (__FreeBSD_version >= 300000) -# include <sys/malloc.h> -# if (defined(_KERNEL) || defined(KERNEL)) && !defined(IPFILTER_LKM) -# include <sys/libkern.h> -# include <sys/systm.h> -# endif -#endif - - - -#if (SOLARIS || defined(__sgi)) && defined(_KERNEL) -extern KRWLOCK_T ipf_auth; -extern kmutex_t ipf_authmx; -# if SOLARIS -extern kcondvar_t ipfauthwait; -# endif -#endif -#ifdef linux -static struct wait_queue *ipfauthwait = NULL; -#endif - -int fr_authsize = FR_NUMAUTH; -int fr_authused = 0; -int fr_defaultauthage = 600; -int fr_auth_lock = 0; -fr_authstat_t fr_authstats; -static frauth_t fr_auth[FR_NUMAUTH]; -mb_t *fr_authpkts[FR_NUMAUTH]; -static int fr_authstart = 0, fr_authend = 0, fr_authnext = 0; -static frauthent_t *fae_list = NULL; -frentry_t *ipauth = NULL; - - -/* - * Check if a packet has authorization. If the packet is found to match an - * authorization result and that would result in a feedback loop (i.e. it - * will end up returning FR_AUTH) then return FR_BLOCK instead. - */ -u_32_t fr_checkauth(ip, fin) -ip_t *ip; -fr_info_t *fin; -{ - u_short id = ip->ip_id; - u_32_t pass; - int i; - - if (fr_auth_lock) - return 0; - - READ_ENTER(&ipf_auth); - for (i = fr_authstart; i != fr_authend; ) { - /* - * index becomes -2 only after an SIOCAUTHW. Check this in - * case the same packet gets sent again and it hasn't yet been - * auth'd. - */ - if ((fr_auth[i].fra_index == -2) && - (id == fr_auth[i].fra_info.fin_id) && - !bcmp((char *)fin,(char *)&fr_auth[i].fra_info,FI_CSIZE)) { - /* - * Avoid feedback loop. - */ - if (!(pass = fr_auth[i].fra_pass) || (pass & FR_AUTH)) - pass = FR_BLOCK; - RWLOCK_EXIT(&ipf_auth); - WRITE_ENTER(&ipf_auth); - fr_authstats.fas_hits++; - fr_auth[i].fra_index = -1; - fr_authused--; - if (i == fr_authstart) { - while (fr_auth[i].fra_index == -1) { - i++; - if (i == FR_NUMAUTH) - i = 0; - fr_authstart = i; - if (i == fr_authend) - break; - } - if (fr_authstart == fr_authend) { - fr_authnext = 0; - fr_authstart = fr_authend = 0; - } - } - RWLOCK_EXIT(&ipf_auth); - return pass; - } - i++; - if (i == FR_NUMAUTH) - i = 0; - } - fr_authstats.fas_miss++; - RWLOCK_EXIT(&ipf_auth); - return 0; -} - - -/* - * Check if we have room in the auth array to hold details for another packet. - * If we do, store it and wake up any user programs which are waiting to - * hear about these events. - */ -int fr_newauth(m, fin, ip) -mb_t *m; -fr_info_t *fin; -ip_t *ip; -{ -#if defined(_KERNEL) && SOLARIS - qif_t *qif = fin->fin_qif; -#endif - int i; - - if (fr_auth_lock) - return 0; - - WRITE_ENTER(&ipf_auth); - if (fr_authstart > fr_authend) { - fr_authstats.fas_nospace++; - RWLOCK_EXIT(&ipf_auth); - return 0; - } else { - if ((fr_authstart == 0) && (fr_authend == FR_NUMAUTH - 1)) { - fr_authstats.fas_nospace++; - RWLOCK_EXIT(&ipf_auth); - return 0; - } - } - - fr_authstats.fas_added++; - fr_authused++; - i = fr_authend++; - if (fr_authend == FR_NUMAUTH) - fr_authend = 0; - RWLOCK_EXIT(&ipf_auth); - fr_auth[i].fra_index = i; - fr_auth[i].fra_pass = 0; - fr_auth[i].fra_age = fr_defaultauthage; - bcopy((char *)fin, (char *)&fr_auth[i].fra_info, sizeof(*fin)); -#if !defined(sparc) && !defined(m68k) - /* - * No need to copyback here as we want to undo the changes, not keep - * them. - */ -# if SOLARIS && defined(_KERNEL) - if ((ip == (ip_t *)m->b_rptr) && (ip->ip_v == 4)) -# endif - { - register u_short bo; - - bo = ip->ip_len; - ip->ip_len = htons(bo); -# if !SOLARIS && !defined(__NetBSD__) - /* 4.4BSD converts this ip_input.c, but I don't in solaris.c */ - bo = ip->ip_id; - ip->ip_id = htons(bo); -# endif - bo = ip->ip_off; - ip->ip_off = htons(bo); - } -#endif -#if SOLARIS && defined(_KERNEL) - m->b_rptr -= qif->qf_off; - fr_authpkts[i] = *(mblk_t **)fin->fin_mp; - fr_auth[i].fra_q = qif->qf_q; - cv_signal(&ipfauthwait); -#else - fr_authpkts[i] = m; -# if defined(linux) && defined(_KERNEL) - wake_up_interruptible(&ipfauthwait); -# else - WAKEUP(&fr_authnext); -# endif -#endif - return 1; -} - - -int fr_auth_ioctl(data, cmd, fr, frptr) -caddr_t data; -#if defined(__NetBSD__) || defined(__OpenBSD__) || (FreeBSD_version >= 300003) -u_long cmd; -#else -int cmd; -#endif -frentry_t *fr, **frptr; -{ - mb_t *m; -#if defined(_KERNEL) && !SOLARIS - struct ifqueue *ifq; -#endif - frauth_t auth, *au = &auth; - frauthent_t *fae, **faep; - int i, error = 0; - - switch (cmd) - { - case SIOCSTLCK : - error = fr_lock(data, &fr_auth_lock); - break; - case SIOCINIFR : - case SIOCRMIFR : - case SIOCADIFR : - error = EINVAL; - break; - case SIOCINAFR : - error = EINVAL; - break; - case SIOCRMAFR : - case SIOCADAFR : - for (faep = &fae_list; (fae = *faep); ) - if (&fae->fae_fr == fr) - break; - else - faep = &fae->fae_next; - if (cmd == SIOCRMAFR) { - if (!fae) - error = ESRCH; - else { - WRITE_ENTER(&ipf_auth); - *faep = fae->fae_next; - *frptr = fr->fr_next; - RWLOCK_EXIT(&ipf_auth); - KFREE(fae); - } - } else { - KMALLOC(fae, frauthent_t *); - if (fae != NULL) { - bcopy((char *)fr, (char *)&fae->fae_fr, - sizeof(*fr)); - WRITE_ENTER(&ipf_auth); - fae->fae_age = fr_defaultauthage; - fae->fae_fr.fr_hits = 0; - fae->fae_fr.fr_next = *frptr; - *frptr = &fae->fae_fr; - fae->fae_next = *faep; - *faep = fae; - ipauth = &fae_list->fae_fr; - RWLOCK_EXIT(&ipf_auth); - } else - error = ENOMEM; - } - break; - case SIOCATHST: - READ_ENTER(&ipf_auth); - fr_authstats.fas_faelist = fae_list; - RWLOCK_EXIT(&ipf_auth); - error = IWCOPYPTR((char *)&fr_authstats, data, - sizeof(fr_authstats)); - break; - case SIOCAUTHW: -fr_authioctlloop: - READ_ENTER(&ipf_auth); - if ((fr_authnext != fr_authend) && fr_authpkts[fr_authnext]) { - error = IWCOPYPTR((char *)&fr_auth[fr_authnext], data, - sizeof(frauth_t)); - RWLOCK_EXIT(&ipf_auth); - if (error) - break; - WRITE_ENTER(&ipf_auth); - fr_authnext++; - if (fr_authnext == FR_NUMAUTH) - fr_authnext = 0; - RWLOCK_EXIT(&ipf_auth); - return 0; - } -#ifdef _KERNEL -# if SOLARIS - mutex_enter(&ipf_authmx); - if (!cv_wait_sig(&ipfauthwait, &ipf_authmx)) { - mutex_exit(&ipf_authmx); - return EINTR; - } - mutex_exit(&ipf_authmx); -# else -# ifdef linux - interruptible_sleep_on(&ipfauthwait); - if (current->signal & ~current->blocked) - error = -EINTR; -# else - error = SLEEP(&fr_authnext, "fr_authnext"); -# endif -# endif -#endif - RWLOCK_EXIT(&ipf_auth); - if (!error) - goto fr_authioctlloop; - break; - case SIOCAUTHR: - error = IRCOPYPTR(data, (caddr_t)&auth, sizeof(auth)); - if (error) - return error; - WRITE_ENTER(&ipf_auth); - i = au->fra_index; - if ((i < 0) || (i > FR_NUMAUTH) || - (fr_auth[i].fra_info.fin_id != au->fra_info.fin_id)) { - RWLOCK_EXIT(&ipf_auth); - return EINVAL; - } - m = fr_authpkts[i]; - fr_auth[i].fra_index = -2; - fr_auth[i].fra_pass = au->fra_pass; - fr_authpkts[i] = NULL; -#ifdef _KERNEL - RWLOCK_EXIT(&ipf_auth); -# ifndef linux - if (m && au->fra_info.fin_out) { -# if SOLARIS - error = fr_qout(fr_auth[i].fra_q, m); -# else /* SOLARIS */ -# if (_BSDI_VERSION >= 199802) || defined(__OpenBSD__) - error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL, - NULL); -# else - error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL); -# endif -# endif /* SOLARIS */ - if (error) - fr_authstats.fas_sendfail++; - else - fr_authstats.fas_sendok++; - } else if (m) { -# if SOLARIS - error = fr_qin(fr_auth[i].fra_q, m); -# else /* SOLARIS */ - ifq = &ipintrq; - if (IF_QFULL(ifq)) { - IF_DROP(ifq); - m_freem(m); - error = ENOBUFS; - } else { - IF_ENQUEUE(ifq, m); - schednetisr(NETISR_IP); - } -# endif /* SOLARIS */ - if (error) - fr_authstats.fas_quefail++; - else - fr_authstats.fas_queok++; - } else - error = EINVAL; -# endif -# if SOLARIS - if (error) - error = EINVAL; -# else - /* - * If we experience an error which will result in the packet - * not being processed, make sure we advance to the next one. - */ - if (error == ENOBUFS) { - fr_authused--; - fr_auth[i].fra_index = -1; - fr_auth[i].fra_pass = 0; - if (i == fr_authstart) { - while (fr_auth[i].fra_index == -1) { - i++; - if (i == FR_NUMAUTH) - i = 0; - fr_authstart = i; - if (i == fr_authend) - break; - } - if (fr_authstart == fr_authend) { - fr_authnext = 0; - fr_authstart = fr_authend = 0; - } - } - } -# endif -#endif /* _KERNEL */ - break; - default : - error = EINVAL; - break; - } - return error; -} - - -#ifdef _KERNEL -/* - * Free all network buffer memory used to keep saved packets. - */ -void fr_authunload() -{ - register int i; - register frauthent_t *fae, **faep; - mb_t *m; - - WRITE_ENTER(&ipf_auth); - for (i = 0; i < FR_NUMAUTH; i++) { - if ((m = fr_authpkts[i])) { - FREE_MB_T(m); - fr_authpkts[i] = NULL; - fr_auth[i].fra_index = -1; - } - } - - - for (faep = &fae_list; (fae = *faep); ) { - *faep = fae->fae_next; - KFREE(fae); - } - ipauth = NULL; - RWLOCK_EXIT(&ipf_auth); -} - - -/* - * Slowly expire held auth records. Timeouts are set - * in expectation of this being called twice per second. - */ -void fr_authexpire() -{ - register int i; - register frauth_t *fra; - register frauthent_t *fae, **faep; - mb_t *m; -#if !SOLARIS - int s; -#endif - - if (fr_auth_lock) - return; - - SPL_NET(s); - WRITE_ENTER(&ipf_auth); - for (i = 0, fra = fr_auth; i < FR_NUMAUTH; i++, fra++) { - if ((!--fra->fra_age) && (m = fr_authpkts[i])) { - FREE_MB_T(m); - fr_authpkts[i] = NULL; - fr_auth[i].fra_index = -1; - fr_authstats.fas_expire++; - fr_authused--; - } - } - - for (faep = &fae_list; (fae = *faep); ) { - if (!--fae->fae_age) { - *faep = fae->fae_next; - KFREE(fae); - fr_authstats.fas_expire++; - } else - faep = &fae->fae_next; - } - ipauth = &fae_list->fae_fr; - RWLOCK_EXIT(&ipf_auth); - SPL_X(s); -} -#endif diff --git a/contrib/ipfilter/ip_auth.h b/contrib/ipfilter/ip_auth.h deleted file mode 100644 index 681a6e5..0000000 --- a/contrib/ipfilter/ip_auth.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 1997-2000 by Darren Reed & Guido Van Rooij. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - * - * $Id: ip_auth.h,v 2.3.2.2 2000/10/19 15:38:44 darrenr Exp $ - * - */ -#ifndef __IP_AUTH_H__ -#define __IP_AUTH_H__ - -#define FR_NUMAUTH 32 - -typedef struct frauth { - int fra_age; - int fra_index; - u_32_t fra_pass; - fr_info_t fra_info; -#if SOLARIS - queue_t *fra_q; -#endif -} frauth_t; - -typedef struct frauthent { - struct frentry fae_fr; - struct frauthent *fae_next; - u_long fae_age; -} frauthent_t; - -typedef struct fr_authstat { - U_QUAD_T fas_hits; - U_QUAD_T fas_miss; - u_long fas_nospace; - u_long fas_added; - u_long fas_sendfail; - u_long fas_sendok; - u_long fas_queok; - u_long fas_quefail; - u_long fas_expire; - frauthent_t *fas_faelist; -} fr_authstat_t; - - -extern frentry_t *ipauth; -extern struct fr_authstat fr_authstats; -extern int fr_defaultauthage; -extern int fr_authsize; -extern int fr_authused; -extern int fr_auth_lock; -extern u_32_t fr_checkauth __P((ip_t *, fr_info_t *)); -extern void fr_authexpire __P((void)); -extern void fr_authunload __P((void)); -extern mb_t *fr_authpkts[]; -extern int fr_newauth __P((mb_t *, fr_info_t *, ip_t *)); -#if defined(__NetBSD__) || defined(__OpenBSD__) -extern int fr_auth_ioctl __P((caddr_t, u_long, frentry_t *, frentry_t **)); -#else -extern int fr_auth_ioctl __P((caddr_t, int, frentry_t *, frentry_t **)); -#endif -#endif /* __IP_AUTH_H__ */ diff --git a/contrib/ipfilter/ip_compat.h b/contrib/ipfilter/ip_compat.h deleted file mode 100644 index ed71f36..0000000 --- a/contrib/ipfilter/ip_compat.h +++ /dev/null @@ -1,1012 +0,0 @@ -/* - * Copyright (C) 1993-2000 by Darren Reed. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - * - * @(#)ip_compat.h 1.8 1/14/96 - * $Id: ip_compat.h,v 2.26.2.9 2001/01/14 14:58:01 darrenr Exp $ - */ - -#ifndef __IP_COMPAT_H__ -#define __IP_COMPAT_H__ - -#ifndef __P -# ifdef __STDC__ -# define __P(x) x -# else -# define __P(x) () -# endif -#endif -#ifndef __STDC__ -# undef const -# define const -#endif - -#ifndef SOLARIS -#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) -#endif -#if SOLARIS2 >= 8 -# ifndef USE_INET6 -# define USE_INET6 -# endif -#endif - -#if defined(_KERNEL) || defined(KERNEL) || defined(__KERNEL__) -# undef KERNEL -# undef _KERNEL -# undef __KERNEL__ -# define KERNEL -# define _KERNEL -# define __KERNEL__ -#endif - -#if defined(__SVR4) || defined(__svr4__) || defined(__sgi) -#define index strchr -# if !defined(KERNEL) -# define bzero(a,b) memset(a,0,b) -# define bcmp memcmp -# define bcopy(a,b,c) memmove(b,a,c) -# endif -#endif - -#ifndef offsetof -#define offsetof(t,m) (int)((&((t *)0L)->m)) -#endif - -#if defined(__sgi) || defined(bsdi) -struct ether_addr { - u_char ether_addr_octet[6]; -}; -#endif - -#if defined(__sgi) && !defined(IPFILTER_LKM) -# ifdef __STDC__ -# define IPL_EXTERN(ep) ipfilter##ep -# else -# define IPL_EXTERN(ep) ipfilter/**/ep -# endif -#else -# ifdef __STDC__ -# define IPL_EXTERN(ep) ipl##ep -# else -# define IPL_EXTERN(ep) ipl/**/ep -# endif -#endif - -#ifdef linux -# include <sys/sysmacros.h> -#endif -#if SOLARIS -# define MTYPE(m) ((m)->b_datap->db_type) -# include <sys/isa_defs.h> -# include <sys/ioccom.h> -# include <sys/sysmacros.h> -# include <sys/kmem.h> -/* - * because Solaris 2 defines these in two places :-/ - */ -# undef IPOPT_EOL -# undef IPOPT_NOP -# undef IPOPT_LSRR -# undef IPOPT_RR -# undef IPOPT_SSRR -# ifndef KERNEL -# define _KERNEL -# undef RES_INIT -# if SOLARIS2 >= 8 -# include <netinet/ip6.h> -# endif -# include <inet/common.h> -# include <inet/ip.h> -# include <inet/ip_ire.h> -# undef _KERNEL -# else /* _KERNEL */ -# if SOLARIS2 >= 8 -# include <netinet/ip6.h> -# endif -# include <inet/common.h> -# include <inet/ip.h> -# include <inet/ip_ire.h> -# endif /* _KERNEL */ -# if SOLARIS2 >= 8 -# include <inet/ip_if.h> -# include <netinet/ip6.h> -# define ipif_local_addr ipif_lcl_addr -/* Only defined in private include file */ -# ifndef V4_PART_OF_V6 -# define V4_PART_OF_V6(v6) v6.s6_addr32[3] -# endif -# endif -#else -# if !defined(__sgi) -typedef int minor_t; -#endif -#endif /* SOLARIS */ -#define IPMINLEN(i, h) ((i)->ip_len >= ((i)->ip_hl * 4 + sizeof(struct h))) - -#if defined(__FreeBSD__) && (__FreeBSD__ >= 5) && defined(_KERNEL) -# include <machine/in_cksum.h> -#endif - -#ifndef IP_OFFMASK -#define IP_OFFMASK 0x1fff -#endif - -#if BSD > 199306 -# define USE_QUAD_T -# define U_QUAD_T u_quad_t -# define QUAD_T quad_t -#else /* BSD > 199306 */ -# define U_QUAD_T u_long -# define QUAD_T long -#endif /* BSD > 199306 */ - - -/* - * These operating systems already take care of the problem for us. - */ -#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || \ - defined(__sgi) -typedef u_int32_t u_32_t; -# if defined(_KERNEL) && !defined(IPFILTER_LKM) -# if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 104110000) -# include "opt_inet.h" -# endif -# if defined(__FreeBSD_version) && (__FreeBSD_version >= 400000) && \ - !defined(KLD_MODULE) -# include "opt_inet6.h" -# endif -# ifdef INET6 -# define USE_INET6 -# endif -# endif -#else -/* - * Really, any arch where sizeof(long) != sizeof(int). - */ -# if defined(__alpha__) || defined(__alpha) || defined(_LP64) -typedef unsigned int u_32_t; -# else -# if SOLARIS2 >= 6 -typedef uint32_t u_32_t; -# else -typedef unsigned int u_32_t; -# endif -# endif -#endif /* __NetBSD__ || __OpenBSD__ || __FreeBSD__ || __sgi */ - -#ifdef USE_INET6 -# if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) -# include <netinet/ip6.h> -# ifdef _KERNEL -# include <netinet6/ip6_var.h> -# endif -typedef struct ip6_hdr ip6_t; -# endif -union i6addr { - u_32_t i6[4]; - struct in_addr in4; - struct in6_addr in6; -}; -#else -union i6addr { - u_32_t i6[4]; - struct in_addr in4; -}; -#endif - -#define IP6CMP(a,b) bcmp((char *)&(a), (char *)&(b), sizeof(a)) -#define IP6EQ(a,b) (bcmp((char *)&(a), (char *)&(b), sizeof(a)) == 0) -#define IP6NEQ(a,b) (bcmp((char *)&(a), (char *)&(b), sizeof(a)) != 0) - -#ifndef MAX -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) -#endif - -/* - * Security Options for Intenet Protocol (IPSO) as defined in RFC 1108. - * - * Basic Option - * - * 00000001 - (Reserved 4) - * 00111101 - Top Secret - * 01011010 - Secret - * 10010110 - Confidential - * 01100110 - (Reserved 3) - * 11001100 - (Reserved 2) - * 10101011 - Unclassified - * 11110001 - (Reserved 1) - */ -#define IPSO_CLASS_RES4 0x01 -#define IPSO_CLASS_TOPS 0x3d -#define IPSO_CLASS_SECR 0x5a -#define IPSO_CLASS_CONF 0x96 -#define IPSO_CLASS_RES3 0x66 -#define IPSO_CLASS_RES2 0xcc -#define IPSO_CLASS_UNCL 0xab -#define IPSO_CLASS_RES1 0xf1 - -#define IPSO_AUTH_GENSER 0x80 -#define IPSO_AUTH_ESI 0x40 -#define IPSO_AUTH_SCI 0x20 -#define IPSO_AUTH_NSA 0x10 -#define IPSO_AUTH_DOE 0x08 -#define IPSO_AUTH_UN 0x06 -#define IPSO_AUTH_FTE 0x01 - -/* - * IP option #defines - */ -/*#define IPOPT_RR 7 */ -#define IPOPT_ZSU 10 /* ZSU */ -#define IPOPT_MTUP 11 /* MTUP */ -#define IPOPT_MTUR 12 /* MTUR */ -#define IPOPT_ENCODE 15 /* ENCODE */ -/*#define IPOPT_TS 68 */ -#define IPOPT_TR 82 /* TR */ -/*#define IPOPT_SECURITY 130 */ -/*#define IPOPT_LSRR 131 */ -#define IPOPT_E_SEC 133 /* E-SEC */ -#define IPOPT_CIPSO 134 /* CIPSO */ -/*#define IPOPT_SATID 136 */ -#ifndef IPOPT_SID -# define IPOPT_SID IPOPT_SATID -#endif -/*#define IPOPT_SSRR 137 */ -#define IPOPT_ADDEXT 147 /* ADDEXT */ -#define IPOPT_VISA 142 /* VISA */ -#define IPOPT_IMITD 144 /* IMITD */ -#define IPOPT_EIP 145 /* EIP */ -#define IPOPT_FINN 205 /* FINN */ - - -#if defined(__FreeBSD__) && (defined(KERNEL) || defined(_KERNEL)) -# ifdef IPFILTER_LKM -# include <osreldate.h> -# define ACTUALLY_LKM_NOT_KERNEL -# else -# include <sys/osreldate.h> -# endif -# if __FreeBSD__ < 3 -# include <machine/spl.h> -# else -# if __FreeBSD__ == 3 -# if defined(IPFILTER_LKM) && !defined(ACTUALLY_LKM_NOT_KERNEL) -# define ACTUALLY_LKM_NOT_KERNEL -# endif -# endif -# endif -#endif /* __FreeBSD__ && KERNEL */ - -/* - * Build some macros and #defines to enable the same code to compile anywhere - * Well, that's the idea, anyway :-) - */ -#if !SOLARIS || (SOLARIS2 < 6) || !defined(KERNEL) -# define ATOMIC_INCL ATOMIC_INC -# define ATOMIC_INC64 ATOMIC_INC -# define ATOMIC_INC32 ATOMIC_INC -# define ATOMIC_INC16 ATOMIC_INC -# define ATOMIC_DECL ATOMIC_DEC -# define ATOMIC_DEC64 ATOMIC_DEC -# define ATOMIC_DEC32 ATOMIC_DEC -# define ATOMIC_DEC16 ATOMIC_DEC -#endif -#ifdef __sgi -# define hz HZ -# include <sys/ksynch.h> -# define IPF_LOCK_PL plhi -# include <sys/sema.h> -#undef kmutex_t -typedef struct { - lock_t *l; - int pl; -} kmutex_t; -# undef MUTEX_INIT -# undef MUTEX_DESTROY -#endif -#ifdef KERNEL -# if SOLARIS -# if SOLARIS2 >= 6 -# include <sys/atomic.h> -# if SOLARIS2 == 6 -# define ATOMIC_INCL(x) atomic_add_long((uint32_t*)&(x), 1) -# define ATOMIC_DECL(x) atomic_add_long((uint32_t*)&(x), -1) -# else -# define ATOMIC_INCL(x) atomic_add_long(&(x), 1) -# define ATOMIC_DECL(x) atomic_add_long(&(x), -1) -# endif -# define ATOMIC_INC64(x) atomic_add_64((uint64_t*)&(x), 1) -# define ATOMIC_INC32(x) atomic_add_32((uint32_t*)&(x), 1) -# define ATOMIC_INC16(x) atomic_add_16((uint16_t*)&(x), 1) -# define ATOMIC_DEC64(x) atomic_add_64((uint64_t*)&(x), -1) -# define ATOMIC_DEC32(x) atomic_add_32((uint32_t*)&(x), -1) -# define ATOMIC_DEC16(x) atomic_add_16((uint16_t*)&(x), -1) -# else -# define ATOMIC_INC(x) { mutex_enter(&ipf_rw); (x)++; \ - mutex_exit(&ipf_rw); } -# define ATOMIC_DEC(x) { mutex_enter(&ipf_rw); (x)--; \ - mutex_exit(&ipf_rw); } -# endif -# define MUTEX_ENTER(x) mutex_enter(x) -# if 1 -# define KRWLOCK_T krwlock_t -# define READ_ENTER(x) rw_enter(x, RW_READER) -# define WRITE_ENTER(x) rw_enter(x, RW_WRITER) -# define RW_UPGRADE(x) { if (rw_tryupgrade(x) == 0) { \ - rw_exit(x); \ - rw_enter(x, RW_WRITER); } \ - } -# define MUTEX_DOWNGRADE(x) rw_downgrade(x) -# define RWLOCK_INIT(x, y, z) rw_init((x), (y), RW_DRIVER, (z)) -# define RWLOCK_EXIT(x) rw_exit(x) -# define RW_DESTROY(x) rw_destroy(x) -# else -# define KRWLOCK_T kmutex_t -# define READ_ENTER(x) mutex_enter(x) -# define WRITE_ENTER(x) mutex_enter(x) -# define MUTEX_DOWNGRADE(x) ; -# define RWLOCK_INIT(x, y, z) mutex_init((x), (y), MUTEX_DRIVER, (z)) -# define RWLOCK_EXIT(x) mutex_exit(x) -# define RW_DESTROY(x) mutex_destroy(x) -# endif -# define MUTEX_INIT(x, y, z) mutex_init((x), (y), MUTEX_DRIVER, (z)) -# define MUTEX_DESTROY(x) mutex_destroy(x) -# define MUTEX_EXIT(x) mutex_exit(x) -# define MTOD(m,t) (t)((m)->b_rptr) -# define IRCOPY(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c)) -# define IWCOPY(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c)) -# define IRCOPYPTR ircopyptr -# define IWCOPYPTR iwcopyptr -# define FREE_MB_T(m) freemsg(m) -# define SPL_NET(x) ; -# define SPL_IMP(x) ; -# undef SPL_X -# define SPL_X(x) ; -# ifdef sparc -# define ntohs(x) (x) -# define ntohl(x) (x) -# define htons(x) (x) -# define htonl(x) (x) -# endif /* sparc */ -# define KMALLOC(a,b) (a) = (b)kmem_alloc(sizeof(*(a)), KM_NOSLEEP) -# define KMALLOCS(a,b,c) (a) = (b)kmem_alloc((c), KM_NOSLEEP) -# define GET_MINOR(x) getminor(x) -typedef struct qif { - struct qif *qf_next; - ill_t *qf_ill; - kmutex_t qf_lock; - void *qf_iptr; - void *qf_optr; - queue_t *qf_in; - queue_t *qf_out; - struct qinit *qf_wqinfo; - struct qinit *qf_rqinfo; - struct qinit qf_wqinit; - struct qinit qf_rqinit; - mblk_t *qf_m; /* These three fields are for passing data up from */ - queue_t *qf_q; /* fr_qin and fr_qout to the packet processing. */ - size_t qf_off; - size_t qf_len; /* this field is used for in ipfr_fastroute */ - char qf_name[8]; - /* - * in case the ILL has disappeared... - */ - size_t qf_hl; /* header length */ - int qf_sap; -} qif_t; -extern ill_t *get_unit __P((char *, int)); -# define GETUNIT(n, v) get_unit(n, v) -# define IFNAME(x) ((ill_t *)x)->ill_name -# else /* SOLARIS */ -# if defined(__sgi) -# define ATOMIC_INC(x) { MUTEX_ENTER(&ipf_rw); \ - (x)++; MUTEX_EXIT(&ipf_rw); } -# define ATOMIC_DEC(x) { MUTEX_ENTER(&ipf_rw); \ - (x)--; MUTEX_EXIT(&ipf_rw); } -# define MUTEX_ENTER(x) (x)->pl = LOCK((x)->l, IPF_LOCK_PL); -# define KRWLOCK_T kmutex_t -# define READ_ENTER(x) MUTEX_ENTER(x) -# define WRITE_ENTER(x) MUTEX_ENTER(x) -# define RW_UPGRADE(x) ; -# define MUTEX_DOWNGRADE(x) ; -# define RWLOCK_EXIT(x) MUTEX_EXIT(x) -# define MUTEX_EXIT(x) UNLOCK((x)->l, (x)->pl); -# define MUTEX_INIT(x,y,z) (x)->l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP) -# define MUTEX_DESTROY(x) LOCK_DEALLOC((x)->l) -# else /* __sgi */ -# define ATOMIC_INC(x) (x)++ -# define ATOMIC_DEC(x) (x)-- -# define MUTEX_ENTER(x) ; -# define READ_ENTER(x) ; -# define WRITE_ENTER(x) ; -# define RW_UPGRADE(x) ; -# define MUTEX_DOWNGRADE(x) ; -# define RWLOCK_EXIT(x) ; -# define MUTEX_EXIT(x) ; -# define MUTEX_INIT(x,y,z) ; -# define MUTEX_DESTROY(x) ; -# endif /* __sgi */ -# ifndef linux -# define FREE_MB_T(m) m_freem(m) -# define MTOD(m,t) mtod(m,t) -# define IRCOPY(a,b,c) (bcopy((a), (b), (c)), 0) -# define IWCOPY(a,b,c) (bcopy((a), (b), (c)), 0) -# define IRCOPYPTR ircopyptr -# define IWCOPYPTR iwcopyptr -# endif /* !linux */ -# endif /* SOLARIS */ - -# ifdef sun -# if !SOLARIS -# include <sys/kmem_alloc.h> -# define GETUNIT(n, v) ifunit(n, IFNAMSIZ) -# define IFNAME(x) ((struct ifnet *)x)->if_name -# endif -# else -# ifndef linux -# define GETUNIT(n, v) ifunit(n) -# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603)) -# define IFNAME(x) ((struct ifnet *)x)->if_xname -# else -# define IFNAME(x) ((struct ifnet *)x)->if_name -# endif -# endif -# endif /* sun */ - -# if defined(sun) && !defined(linux) || defined(__sgi) -# define UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,c,d) -# define SLEEP(id, n) sleep((id), PZERO+1) -# define WAKEUP(id) wakeup(id) -# define KFREE(x) kmem_free((char *)(x), sizeof(*(x))) -# define KFREES(x,s) kmem_free((char *)(x), (s)) -# if !SOLARIS -extern void m_copydata __P((struct mbuf *, int, int, caddr_t)); -extern void m_copyback __P((struct mbuf *, int, int, caddr_t)); -# endif -# ifdef __sgi -# include <sys/kmem.h> -# include <sys/ddi.h> -# define KMALLOC(a,b) (a) = (b)kmem_alloc(sizeof(*(a)), KM_NOSLEEP) -# define KMALLOCS(a,b,c) (a) = (b)kmem_alloc((c), KM_NOSLEEP) -# define GET_MINOR(x) getminor(x) -# else -# if !SOLARIS -# define KMALLOC(a,b) (a) = (b)new_kmem_alloc(sizeof(*(a)), \ - KMEM_NOSLEEP) -# define KMALLOCS(a,b,c) (a) = (b)new_kmem_alloc((c), KMEM_NOSLEEP) -# endif /* SOLARIS */ -# endif /* __sgi */ -# endif /* sun && !linux */ -# ifndef GET_MINOR -# define GET_MINOR(x) minor(x) -# endif -# if (BSD >= 199306) || defined(__FreeBSD__) -# include <vm/vm.h> -# if !defined(__FreeBSD__) || (defined (__FreeBSD__) && __FreeBSD__>=3) -# include <vm/vm_extern.h> -# include <sys/proc.h> -extern vm_map_t kmem_map; -# else /* !__FreeBSD__ || (__FreeBSD__ && __FreeBSD__>=3) */ -# include <vm/vm_kern.h> -# endif /* !__FreeBSD__ || (__FreeBSD__ && __FreeBSD__>=3) */ -# ifdef M_PFIL -# define KMALLOC(a, b) MALLOC((a), b, sizeof(*(a)), M_PFIL, M_NOWAIT) -# define KMALLOCS(a, b, c) MALLOC((a), b, (c), M_PFIL, M_NOWAIT) -# define KFREE(x) FREE((x), M_PFIL) -# define KFREES(x,s) FREE((x), M_PFIL) -# else -# define KMALLOC(a, b) MALLOC((a), b, sizeof(*(a)), M_TEMP, M_NOWAIT) -# define KMALLOCS(a, b, c) MALLOC((a), b, (c), M_TEMP, M_NOWAIT) -# define KFREE(x) FREE((x), M_TEMP) -# define KFREES(x,s) FREE((x), M_TEMP) -# endif /* M_PFIL */ -# define UIOMOVE(a,b,c,d) uiomove(a,b,d) -# define SLEEP(id, n) tsleep((id), PPAUSE|PCATCH, n, 0) -# define WAKEUP(id) wakeup(id) -# endif /* BSD */ -# if defined(NetBSD) && NetBSD <= 1991011 && NetBSD >= 199407 -# define SPL_NET(x) x = splsoftnet() -# define SPL_X(x) (void) splx(x) -# else -# if !SOLARIS && !defined(linux) -# define SPL_IMP(x) x = splimp() -# define SPL_NET(x) x = splnet() -# define SPL_X(x) (void) splx(x) -# endif -# endif /* NetBSD && NetBSD <= 1991011 && NetBSD >= 199407 */ -# define PANIC(x,y) if (x) panic y -#else /* KERNEL */ -# define SLEEP(x,y) ; -# define WAKEUP(x) ; -# define PANIC(x,y) ; -# define ATOMIC_INC(x) (x)++ -# define ATOMIC_DEC(x) (x)-- -# define MUTEX_ENTER(x) ; -# define READ_ENTER(x) ; -# define MUTEX_INIT(x,y,z) ; -# define MUTEX_DESTROY(x) ; -# define WRITE_ENTER(x) ; -# define RW_UPGRADE(x) ; -# define MUTEX_DOWNGRADE(x) ; -# define RWLOCK_EXIT(x) ; -# define MUTEX_EXIT(x) ; -# define SPL_NET(x) ; -# define SPL_IMP(x) ; -# undef SPL_X -# define SPL_X(x) ; -# define KMALLOC(a,b) (a) = (b)malloc(sizeof(*a)) -# define KMALLOCS(a,b,c) (a) = (b)malloc(c) -# define KFREE(x) free(x) -# define KFREES(x,s) free(x) -# define GETUNIT(x, v) get_unit(x,v) -# define IRCOPY(a,b,c) (bcopy((a), (b), (c)), 0) -# define IWCOPY(a,b,c) (bcopy((a), (b), (c)), 0) -# define IRCOPYPTR ircopyptr -# define IWCOPYPTR iwcopyptr -#endif /* KERNEL */ - -#if SOLARIS -typedef mblk_t mb_t; -# if SOLARIS2 >= 7 -# ifdef lint -# define ALIGN32(ptr) (ptr ? 0L : 0L) -# define ALIGN16(ptr) (ptr ? 0L : 0L) -# else -# define ALIGN32(ptr) (ptr) -# define ALIGN16(ptr) (ptr) -# endif -# endif -#else -# ifdef linux -# ifndef kernel -typedef struct mb { - struct mb *next; - u_int len; - u_char *data; -} mb_t; -# else -typedef struct sk_buff mb_t; -# endif -# else -typedef struct mbuf mb_t; -# endif -#endif /* SOLARIS */ - -#if defined(linux) || defined(__sgi) -/* - * These #ifdef's are here mainly for linux, but who knows, they may - * not be in other places or maybe one day linux will grow up and some - * of these will turn up there too. - */ -#ifndef ICMP_MINLEN -# define ICMP_MINLEN 8 -#endif -#ifndef ICMP_UNREACH -# define ICMP_UNREACH ICMP_DEST_UNREACH -#endif -#ifndef ICMP_SOURCEQUENCH -# define ICMP_SOURCEQUENCH ICMP_SOURCE_QUENCH -#endif -#ifndef ICMP_TIMXCEED -# define ICMP_TIMXCEED ICMP_TIME_EXCEEDED -#endif -#ifndef ICMP_PARAMPROB -# define ICMP_PARAMPROB ICMP_PARAMETERPROB -#endif -#ifndef ICMP_TSTAMP -# define ICMP_TSTAMP ICMP_TIMESTAMP -#endif -#ifndef ICMP_TSTAMPREPLY -# define ICMP_TSTAMPREPLY ICMP_TIMESTAMPREPLY -#endif -#ifndef ICMP_IREQ -# define ICMP_IREQ ICMP_INFO_REQUEST -#endif -#ifndef ICMP_IREQREPLY -# define ICMP_IREQREPLY ICMP_INFO_REPLY -#endif -#ifndef ICMP_MASKREQ -# define ICMP_MASKREQ ICMP_ADDRESS -#endif -#ifndef ICMP_MASKREPLY -# define ICMP_MASKREPLY ICMP_ADDRESSREPLY -#endif -#ifndef IPVERSION -# define IPVERSION 4 -#endif -#ifndef IPOPT_MINOFF -# define IPOPT_MINOFF 4 -#endif -#ifndef IPOPT_COPIED -# define IPOPT_COPIED(x) ((x)&0x80) -#endif -#ifndef IPOPT_EOL -# define IPOPT_EOL 0 -#endif -#ifndef IPOPT_NOP -# define IPOPT_NOP 1 -#endif -#ifndef IP_MF -# define IP_MF ((u_short)0x2000) -#endif -#ifndef ETHERTYPE_IP -# define ETHERTYPE_IP ((u_short)0x0800) -#endif -#ifndef TH_FIN -# define TH_FIN 0x01 -#endif -#ifndef TH_SYN -# define TH_SYN 0x02 -#endif -#ifndef TH_RST -# define TH_RST 0x04 -#endif -#ifndef TH_PUSH -# define TH_PUSH 0x08 -#endif -#ifndef TH_ACK -# define TH_ACK 0x10 -#endif -#ifndef TH_URG -# define TH_URG 0x20 -#endif -#ifndef IPOPT_EOL -# define IPOPT_EOL 0 -#endif -#ifndef IPOPT_NOP -# define IPOPT_NOP 1 -#endif -#ifndef IPOPT_RR -# define IPOPT_RR 7 -#endif -#ifndef IPOPT_TS -# define IPOPT_TS 68 -#endif -#ifndef IPOPT_SECURITY -# define IPOPT_SECURITY 130 -#endif -#ifndef IPOPT_LSRR -# define IPOPT_LSRR 131 -#endif -#ifndef IPOPT_SATID -# define IPOPT_SATID 136 -#endif -#ifndef IPOPT_SSRR -# define IPOPT_SSRR 137 -#endif -#ifndef IPOPT_SECUR_UNCLASS -# define IPOPT_SECUR_UNCLASS ((u_short)0x0000) -#endif -#ifndef IPOPT_SECUR_CONFID -# define IPOPT_SECUR_CONFID ((u_short)0xf135) -#endif -#ifndef IPOPT_SECUR_EFTO -# define IPOPT_SECUR_EFTO ((u_short)0x789a) -#endif -#ifndef IPOPT_SECUR_MMMM -# define IPOPT_SECUR_MMMM ((u_short)0xbc4d) -#endif -#ifndef IPOPT_SECUR_RESTR -# define IPOPT_SECUR_RESTR ((u_short)0xaf13) -#endif -#ifndef IPOPT_SECUR_SECRET -# define IPOPT_SECUR_SECRET ((u_short)0xd788) -#endif -#ifndef IPOPT_SECUR_TOPSECRET -# define IPOPT_SECUR_TOPSECRET ((u_short)0x6bc5) -#endif -#ifndef IPOPT_OLEN -# define IPOPT_OLEN 1 -#endif -#endif /* linux || __sgi */ - -#ifdef linux -#include <linux/in_systm.h> -/* - * TCP States - */ -#define TCPS_CLOSED 0 /* closed */ -#define TCPS_LISTEN 1 /* listening for connection */ -#define TCPS_SYN_SENT 2 /* active, have sent syn */ -#define TCPS_SYN_RECEIVED 3 /* have send and received syn */ -/* states < TCPS_ESTABLISHED are those where connections not established */ -#define TCPS_ESTABLISHED 4 /* established */ -#define TCPS_CLOSE_WAIT 5 /* rcvd fin, waiting for close */ -/* states > TCPS_CLOSE_WAIT are those where user has closed */ -#define TCPS_FIN_WAIT_1 6 /* have closed, sent fin */ -#define TCPS_CLOSING 7 /* closed xchd FIN; await FIN ACK */ -#define TCPS_LAST_ACK 8 /* had fin and close; await FIN ACK */ -/* states > TCPS_CLOSE_WAIT && < TCPS_FIN_WAIT_2 await ACK of FIN */ -#define TCPS_FIN_WAIT_2 9 /* have closed, fin is acked */ -#define TCPS_TIME_WAIT 10 /* in 2*msl quiet wait after close */ - -/* - * file flags. - */ -#ifdef WRITE -#define FWRITE WRITE -#define FREAD READ -#else -#define FWRITE _IOC_WRITE -#define FREAD _IOC_READ -#endif -/* - * mbuf related problems. - */ -#define mtod(m,t) (t)((m)->data) -#define m_len len -#define m_next next - -#ifdef IP_DF -#undef IP_DF -#endif -#define IP_DF 0x4000 - -typedef struct { - __u16 th_sport; - __u16 th_dport; - __u32 th_seq; - __u32 th_ack; -# if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\ - defined(vax) - __u8 th_res:4; - __u8 th_off:4; -#else - __u8 th_off:4; - __u8 th_res:4; -#endif - __u8 th_flags; - __u16 th_win; - __u16 th_sum; - __u16 th_urp; -} tcphdr_t; - -typedef struct { - __u16 uh_sport; - __u16 uh_dport; - __u16 uh_ulen; - __u16 uh_sum; -} udphdr_t; - -typedef struct { -# if defined(__i386__) || defined(__MIPSEL__) || defined(__alpha__) ||\ - defined(vax) - __u8 ip_hl:4; - __u8 ip_v:4; -# else - __u8 ip_v:4; - __u8 ip_hl:4; -# endif - __u8 ip_tos; - __u16 ip_len; - __u16 ip_id; - __u16 ip_off; - __u8 ip_ttl; - __u8 ip_p; - __u16 ip_sum; - struct in_addr ip_src; - struct in_addr ip_dst; -} ip_t; - -/* - * Structure of an icmp header. - */ -typedef struct icmp { - __u8 icmp_type; /* type of message, see below */ - __u8 icmp_code; /* type sub code */ - __u16 icmp_cksum; /* ones complement cksum of struct */ - union { - __u8 ih_pptr; /* ICMP_PARAMPROB */ - struct in_addr ih_gwaddr; /* ICMP_REDIRECT */ - struct ih_idseq { - __u16 icd_id; - __u16 icd_seq; - } ih_idseq; - int ih_void; - } icmp_hun; -# define icmp_pptr icmp_hun.ih_pptr -# define icmp_gwaddr icmp_hun.ih_gwaddr -# define icmp_id icmp_hun.ih_idseq.icd_id -# define icmp_seq icmp_hun.ih_idseq.icd_seq -# define icmp_void icmp_hun.ih_void - union { - struct id_ts { - n_time its_otime; - n_time its_rtime; - n_time its_ttime; - } id_ts; - struct id_ip { - ip_t idi_ip; - /* options and then 64 bits of data */ - } id_ip; - u_long id_mask; - char id_data[1]; - } icmp_dun; -# define icmp_otime icmp_dun.id_ts.its_otime -# define icmp_rtime icmp_dun.id_ts.its_rtime -# define icmp_ttime icmp_dun.id_ts.its_ttime -# define icmp_ip icmp_dun.id_ip.idi_ip -# define icmp_mask icmp_dun.id_mask -# define icmp_data icmp_dun.id_data -} icmphdr_t; - -# ifndef LINUX_IPOVLY -# define LINUX_IPOVLY -struct ipovly { - caddr_t ih_next, ih_prev; /* for protocol sequence q's */ - u_char ih_x1; /* (unused) */ - u_char ih_pr; /* protocol */ - short ih_len; /* protocol length */ - struct in_addr ih_src; /* source internet address */ - struct in_addr ih_dst; /* destination internet address */ -}; -# endif - -typedef struct { - __u8 ether_dhost[6]; - __u8 ether_shost[6]; - __u16 ether_type; -} ether_header_t; - -typedef struct uio { - int uio_resid; - int uio_rw; - caddr_t uio_buf; -} uio_t; - -# define UIO_READ 0 -# define UIO_WRITE 1 -# define UIOMOVE(a, b, c, d) uiomove(a,b,c,d) - -/* - * For masking struct ifnet onto struct device - */ -# define if_name name - -# ifdef KERNEL -# define GETUNIT(x, v) dev_get(x) -# define FREE_MB_T(m) kfree_skb(m, FREE_WRITE) -# define uniqtime do_gettimeofday -# undef INT_MAX -# undef UINT_MAX -# undef LONG_MAX -# undef ULONG_MAX -# include <linux/netdevice.h> -# define SPL_X(x) -# define SPL_NET(x) -# define SPL_IMP(x) - -# define bcmp(a,b,c) memcmp(a,b,c) -# define bcopy(a,b,c) memcpy(b,a,c) -# define bzero(a,c) memset(a,0,c) - -# define UNITNAME(n) dev_get((n)) - -# define KMALLOC(a,b) (a) = (b)kmalloc(sizeof(*(a)), GFP_ATOMIC) -# define KMALLOCS(a,b,c) (a) = (b)kmalloc((c), GFP_ATOMIC) -# define KFREE(x) kfree_s((x), sizeof(*(x))) -# define KFREES(x,s) kfree_s((x), (s)) -#define IRCOPY(const void *a, void *b, size_t c) { \ - int error; \ - - error = verify_area(VERIFY_READ, a ,c); \ - if (!error) \ - memcpy_fromfs(b, a, c); \ - return error; \ -} -static inline int IWCOPY(const void *a, void *b, size_t c) -{ - int error; - - error = verify_area(VERIFY_WRITE, b, c); - if (!error) - memcpy_tofs(b, a, c); - return error; -} -static inline int IRCOPYPTR(const void *a, void *b, size_t c) { - caddr_t ca; - int error; - - error = verify_area(VERIFY_READ, a ,sizeof(ca)); - if (!error) { - memcpy_fromfs(ca, a, sizeof(ca)); - error = verify_area(VERIFY_READ, ca , c); - if (!error) - memcpy_fromfs(b, ca, c); - } - return error; -} -static inline int IWCOPYPTR(const void *a, void *b, size_t c) { - caddr_t ca; - int error; - - - error = verify_area(VERIFY_READ, b ,sizeof(ca)); - if (!error) { - memcpy_fromfs(ca, b, sizeof(ca)); - error = verify_area(VERIFY_WRITE, ca, c); - if (!error) - memcpy_tofs(ca, a, c); - } - return error; -} -# else -# define __KERNEL__ -# undef INT_MAX -# undef UINT_MAX -# undef LONG_MAX -# undef ULONG_MAX -# define s8 __s8 -# define u8 __u8 -# define s16 __s16 -# define u16 __u16 -# define s32 __s32 -# define u32 __u32 -# include <linux/netdevice.h> -# undef __KERNEL__ -# endif -# define ifnet device -#else -typedef struct tcphdr tcphdr_t; -typedef struct udphdr udphdr_t; -typedef struct icmp icmphdr_t; -typedef struct ip ip_t; -typedef struct ether_header ether_header_t; -#endif /* linux */ -typedef struct tcpiphdr tcpiphdr_t; - -#if defined(hpux) || defined(linux) -struct ether_addr { - char ether_addr_octet[6]; -}; -#endif - -/* - * XXX - This is one of those *awful* hacks which nobody likes - */ -#ifdef ultrix -#define A_A -#else -#define A_A & -#endif - -#ifndef ICMP_ROUTERADVERT -# define ICMP_ROUTERADVERT 9 -#endif -#ifndef ICMP_ROUTERSOLICIT -# define ICMP_ROUTERSOLICIT 10 -#endif -#undef ICMP_MAX_UNREACH -#define ICMP_MAX_UNREACH 14 -#undef ICMP_MAXTYPE -#define ICMP_MAXTYPE 18 -/* - * ICMP error replies have an IP header (20 bytes), 8 bytes of ICMP data, - * another IP header and then 64 bits of data, totalling 56. Of course, - * the last 64 bits is dependant on that being available. - */ -#define ICMPERR_ICMPHLEN 8 -#define ICMPERR_IPICMPHLEN (20 + 8) -#define ICMPERR_MINPKTLEN (20 + 8 + 20) -#define ICMPERR_MAXPKTLEN (20 + 8 + 20 + 8) -#define ICMP6ERR_MINPKTLEN (40 + 8) -#define ICMP6ERR_IPICMPHLEN (40 + 8 + 40) - -/* - * ECN is a new addition to TCP - RFC 2481 - */ -#ifndef TH_ECN -# define TH_ECN 0x40 -#endif -#ifndef TH_CWR -# define TH_CWR 0x80 -#endif -#define TH_ECNALL (TH_ECN|TH_CWR) - -#define TCPF_ALL (TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG|TH_ECN|TH_CWR) - -#endif /* __IP_COMPAT_H__ */ diff --git a/contrib/ipfilter/ip_fil.c b/contrib/ipfilter/ip_fil.c deleted file mode 100644 index 9253775..0000000 --- a/contrib/ipfilter/ip_fil.c +++ /dev/null @@ -1,1758 +0,0 @@ -/* - * Copyright (C) 1993-2000 by Darren Reed. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - */ -#if !defined(lint) -static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.42.2.17 2000/10/19 15:39:42 darrenr Exp $"; -#endif - -#ifndef SOLARIS -#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) -#endif - -#if defined(KERNEL) && !defined(_KERNEL) -# define _KERNEL -#endif -#if defined(_KERNEL) && defined(__FreeBSD_version) && \ - (__FreeBSD_version >= 400000) && !defined(KLD_MODULE) -#include "opt_inet6.h" -#endif -#include <sys/param.h> -#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \ - defined(_KERNEL) -# include "opt_ipfilter_log.h" -#endif -#if defined(__FreeBSD__) && !defined(__FreeBSD_version) -# if !defined(_KERNEL) || defined(IPFILTER_LKM) -# include <osreldate.h> -# endif -#endif -#ifndef _KERNEL -# include <stdio.h> -# include <string.h> -# include <stdlib.h> -# include <ctype.h> -# include <fcntl.h> -#endif -#include <sys/errno.h> -#include <sys/types.h> -#include <sys/file.h> -#if __FreeBSD_version >= 220000 && defined(_KERNEL) -# include <sys/fcntl.h> -# include <sys/filio.h> -#else -# include <sys/ioctl.h> -#endif -#include <sys/time.h> -#ifdef _KERNEL -# include <sys/systm.h> -#endif -#include <sys/uio.h> -#if !SOLARIS -# if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000) -# include <sys/dirent.h> -# else -# include <sys/dir.h> -# endif -# include <sys/mbuf.h> -#else -# include <sys/filio.h> -#endif -#include <sys/protosw.h> -#include <sys/socket.h> - -#include <net/if.h> -#ifdef sun -# include <net/af.h> -#endif -#if __FreeBSD_version >= 300000 -# include <net/if_var.h> -# if defined(_KERNEL) && !defined(IPFILTER_LKM) -# include "opt_ipfilter.h" -# endif -#endif -#ifdef __sgi -#include <sys/debug.h> -# ifdef IFF_DRVRLOCK /* IRIX6 */ -#include <sys/hashing.h> -# endif -#endif -#include <net/route.h> -#include <netinet/in.h> -#if !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /* IRIX < 6 */ -# include <netinet/in_var.h> -#endif -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/ip_var.h> -#include <netinet/tcp.h> -#include <netinet/udp.h> -#include <netinet/tcpip.h> -#include <netinet/ip_icmp.h> -#ifndef _KERNEL -# include <unistd.h> -# include <syslog.h> -#endif -#include "netinet/ip_compat.h" -#ifdef USE_INET6 -# include <netinet/icmp6.h> -#endif -#include "netinet/ip_fil.h" -#include "netinet/ip_proxy.h" -#include "netinet/ip_nat.h" -#include "netinet/ip_frag.h" -#include "netinet/ip_state.h" -#include "netinet/ip_auth.h" -#if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) -# include <sys/malloc.h> -#endif -#ifndef MIN -# define MIN(a,b) (((a)<(b))?(a):(b)) -#endif -#if !SOLARIS && defined(_KERNEL) && !defined(__sgi) -# include <sys/kernel.h> -extern int ip_optcopy __P((struct ip *, struct ip *)); -#endif - - -extern struct protosw inetsw[]; - -#ifndef _KERNEL -# include "ipt.h" -static struct ifnet **ifneta = NULL; -static int nifs = 0; -#else -# if (BSD < 199306) || defined(__sgi) -extern int tcp_ttl; -# endif -#endif - -int ipl_unreach = ICMP_UNREACH_FILTER; -u_long ipl_frouteok[2] = {0, 0}; - -static int frzerostats __P((caddr_t)); -#if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003) -static int frrequest __P((int, u_long, caddr_t, int)); -#else -static int frrequest __P((int, int, caddr_t, int)); -#endif -#ifdef _KERNEL -static int (*fr_savep) __P((ip_t *, int, void *, int, struct mbuf **)); -static int send_ip __P((ip_t *, fr_info_t *, struct mbuf *)); -# ifdef __sgi -extern kmutex_t ipf_rw; -extern KRWLOCK_T ipf_mutex; -# endif -#else -int ipllog __P((void)); -void init_ifp __P((void)); -# ifdef __sgi -static int no_output __P((struct ifnet *, struct mbuf *, - struct sockaddr *)); -static int write_output __P((struct ifnet *, struct mbuf *, - struct sockaddr *)); -# else -static int no_output __P((struct ifnet *, struct mbuf *, - struct sockaddr *, struct rtentry *)); -static int write_output __P((struct ifnet *, struct mbuf *, - struct sockaddr *, struct rtentry *)); -# endif -#endif -int fr_running = 0; - -#if (__FreeBSD_version >= 300000) && defined(_KERNEL) -struct callout_handle ipfr_slowtimer_ch; -#endif -#if defined(__NetBSD__) && (__NetBSD_Version__ >= 104230000) -# include <sys/callout.h> -struct callout ipfr_slowtimer_ch; -#endif -#if defined(__sgi) && defined(_KERNEL) -toid_t ipfr_slowtimer_ch; -#endif - -#if (_BSDI_VERSION >= 199510) && defined(_KERNEL) -# include <sys/device.h> -# include <sys/conf.h> - -struct cfdriver iplcd = { - NULL, "ipl", NULL, NULL, DV_DULL, 0 -}; - -struct devsw iplsw = { - &iplcd, - iplopen, iplclose, iplread, nowrite, iplioctl, noselect, nommap, - nostrat, nodump, nopsize, 0, - nostop -}; -#endif /* _BSDI_VERSION >= 199510 && _KERNEL */ - -#if defined(__NetBSD__) || defined(__OpenBSD__) || (_BSDI_VERSION >= 199701) -# include <sys/conf.h> -# if defined(NETBSD_PF) -# include <net/pfil.h> -/* - * We provide the fr_checkp name just to minimize changes later. - */ -int (*fr_checkp) __P((ip_t *ip, int hlen, void *ifp, int out, mb_t **mp)); -# endif /* NETBSD_PF */ -#endif /* __NetBSD__ */ - -#ifdef _KERNEL -# if defined(IPFILTER_LKM) && !defined(__sgi) -int iplidentify(s) -char *s; -{ - if (strcmp(s, "ipl") == 0) - return 1; - return 0; -} -# endif /* IPFILTER_LKM */ - - -/* - * Try to detect the case when compiling for NetBSD with pseudo-device - */ -# if defined(__NetBSD__) && defined(PFIL_HOOKS) -void -ipfilterattach(count) -int count; -{ - if (iplattach() != 0) - printf("IP Filter failed to attach\n"); -} -# endif - - -int iplattach() -{ - char *defpass; - int s; -# if defined(__sgi) || (defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000)) - int error = 0; -# endif - - SPL_NET(s); - if (fr_running || (fr_checkp == fr_check)) { - printf("IP Filter: already initialized\n"); - SPL_X(s); - return EBUSY; - } - -# ifdef IPFILTER_LOG - ipflog_init(); -# endif - if (nat_init() == -1) - return -1; - if (fr_stateinit() == -1) - return -1; - if (appr_init() == -1) - return -1; - -# ifdef NETBSD_PF -# if __NetBSD_Version__ >= 104200000 - error = pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT, - &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); - if (error) { -# ifdef USE_INET6 - goto pfil_error; -# else - appr_unload(); - ip_natunload(); - fr_stateunload(); - return error; -# endif - } -# else - pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT); -# endif -# ifdef USE_INET6 - error = pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT, - &inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh); - if (error) { - pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT, - &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); -pfil_error: - appr_unload(); - ip_natunload(); - fr_stateunload(); - return error; - } -# endif -# endif - -# ifdef __sgi - error = ipfilter_sgi_attach(); - if (error) { - SPL_X(s); - appr_unload(); - ip_natunload(); - fr_stateunload(); - return error; - } -# endif - - bzero((char *)frcache, sizeof(frcache)); - fr_savep = fr_checkp; - fr_checkp = fr_check; - fr_running = 1; - - SPL_X(s); - if (fr_pass & FR_PASS) - defpass = "pass"; - else if (fr_pass & FR_BLOCK) - defpass = "block"; - else - defpass = "no-match -> block"; - - printf("%s initialized. Default = %s all, Logging = %s\n", - ipfilter_version, defpass, -# ifdef IPFILTER_LOG - "enabled"); -# else - "disabled"); -# endif -#ifdef _KERNEL -# if defined(__NetBSD__) && (__NetBSD_Version__ >= 104230000) - callout_init(&ipfr_slowtimer_ch); - callout_reset(&ipfr_slowtimer_ch, hz / 2, ipfr_slowtimer, NULL); -# else -# if (__FreeBSD_version >= 300000) || defined(__sgi) - ipfr_slowtimer_ch = timeout(ipfr_slowtimer, NULL, hz/2); -# else - timeout(ipfr_slowtimer, NULL, hz/2); -# endif -# endif -#endif - return 0; -} - - -/* - * Disable the filter by removing the hooks from the IP input/output - * stream. - */ -int ipldetach() -{ - int s, i = FR_INQUE|FR_OUTQUE; -#if defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000) - int error = 0; -#endif - -#ifdef _KERNEL -# if defined(__NetBSD__) && (__NetBSD_Version__ >= 104230000) - callout_stop(&ipfr_slowtimer_ch); -# else -# if (__FreeBSD_version >= 300000) - untimeout(ipfr_slowtimer, NULL, ipfr_slowtimer_ch); -# else -# ifdef __sgi - untimeout(ipfr_slowtimer_ch); -# else - untimeout(ipfr_slowtimer, NULL); -# endif -# endif /* FreeBSD */ -# endif /* NetBSD */ -#endif - SPL_NET(s); - if (!fr_running) - { - printf("IP Filter: not initialized\n"); - SPL_X(s); - return 0; - } - - printf("%s unloaded\n", ipfilter_version); - - fr_checkp = fr_savep; - i = frflush(IPL_LOGIPF, i); - fr_running = 0; - -# ifdef NETBSD_PF -# if __NetBSD_Version__ >= 104200000 - error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT, - &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); - if (error) - return error; -# else - pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT); -# endif -# ifdef USE_INET6 - error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT, - &inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh); - if (error) - return error; -# endif -# endif - -# ifdef __sgi - ipfilter_sgi_detach(); -# endif - - appr_unload(); - ipfr_unload(); - ip_natunload(); - fr_stateunload(); - fr_authunload(); - - SPL_X(s); - return 0; -} -#endif /* _KERNEL */ - - -static int frzerostats(data) -caddr_t data; -{ - friostat_t fio; - int error; - - fr_getstat(&fio); - error = IWCOPYPTR((caddr_t)&fio, data, sizeof(fio)); - if (error) - return EFAULT; - - bzero((char *)frstats, sizeof(*frstats) * 2); - - return 0; -} - - -/* - * Filter ioctl interface. - */ -#ifdef __sgi -int IPL_EXTERN(ioctl)(dev_t dev, int cmd, caddr_t data, int mode -# ifdef _KERNEL - , cred_t *cp, int *rp -# endif -) -#else -int IPL_EXTERN(ioctl)(dev, cmd, data, mode -# if (defined(_KERNEL) && ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || \ - (NetBSD >= 199511) || (__FreeBSD_version >= 220000) || \ - defined(__OpenBSD__))) -, p) -struct proc *p; -# else -) -# endif -dev_t dev; -# if defined(__NetBSD__) || defined(__OpenBSD__) || \ - (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) -u_long cmd; -# else -int cmd; -# endif -caddr_t data; -int mode; -#endif /* __sgi */ -{ -#if defined(_KERNEL) && !SOLARIS - int s; -#endif - int error = 0, unit = 0, tmp; - -#if (BSD >= 199306) && defined(_KERNEL) - if ((securelevel >= 2) && (mode & FWRITE)) - return EPERM; -#endif -#ifdef _KERNEL - unit = GET_MINOR(dev); - if ((IPL_LOGMAX < unit) || (unit < 0)) - return ENXIO; -#else - unit = dev; -#endif - - SPL_NET(s); - - if (unit == IPL_LOGNAT) { - if (fr_running) - error = nat_ioctl(data, cmd, mode); - else - error = EIO; - SPL_X(s); - return error; - } - if (unit == IPL_LOGSTATE) { - if (fr_running) - error = fr_state_ioctl(data, cmd, mode); - else - error = EIO; - SPL_X(s); - return error; - } - if (unit == IPL_LOGAUTH) { - if (!fr_running) - return EIO; - error = fr_auth_ioctl(data, cmd, NULL, NULL); - SPL_X(s); - return error; - } - - switch (cmd) { - case FIONREAD : -#ifdef IPFILTER_LOG - error = IWCOPY((caddr_t)&iplused[IPL_LOGIPF], (caddr_t)data, - sizeof(iplused[IPL_LOGIPF])); -#endif - break; -#if !defined(IPFILTER_LKM) && defined(_KERNEL) - case SIOCFRENB : - { - u_int enable; - - if (!(mode & FWRITE)) - error = EPERM; - else { - error = IRCOPY(data, (caddr_t)&enable, sizeof(enable)); - if (error) - break; - if (enable) - error = iplattach(); - else - error = ipldetach(); - } - break; - } -#endif - case SIOCSETFF : - if (!(mode & FWRITE)) - error = EPERM; - else - error = IRCOPY(data, (caddr_t)&fr_flags, - sizeof(fr_flags)); - break; - case SIOCGETFF : - error = IWCOPY((caddr_t)&fr_flags, data, sizeof(fr_flags)); - break; - case SIOCINAFR : - case SIOCRMAFR : - case SIOCADAFR : - case SIOCZRLST : - if (!(mode & FWRITE)) - error = EPERM; - else - error = frrequest(unit, cmd, data, fr_active); - break; - case SIOCINIFR : - case SIOCRMIFR : - case SIOCADIFR : - if (!(mode & FWRITE)) - error = EPERM; - else - error = frrequest(unit, cmd, data, 1 - fr_active); - break; - case SIOCSWAPA : - if (!(mode & FWRITE)) - error = EPERM; - else { - bzero((char *)frcache, sizeof(frcache[0]) * 2); - *(u_int *)data = fr_active; - fr_active = 1 - fr_active; - } - break; - case SIOCGETFS : - { - friostat_t fio; - - fr_getstat(&fio); - error = IWCOPYPTR((caddr_t)&fio, data, sizeof(fio)); - if (error) - return EFAULT; - break; - } - case SIOCFRZST : - if (!(mode & FWRITE)) - error = EPERM; - else - error = frzerostats(data); - break; - case SIOCIPFFL : - if (!(mode & FWRITE)) - error = EPERM; - else { - error = IRCOPY(data, (caddr_t)&tmp, sizeof(tmp)); - if (!error) { - tmp = frflush(unit, tmp); - error = IWCOPY((caddr_t)&tmp, data, - sizeof(tmp)); - } - } - break; - case SIOCSTLCK : - error = IRCOPY(data, (caddr_t)&tmp, sizeof(tmp)); - if (!error) { - fr_state_lock = tmp; - fr_nat_lock = tmp; - fr_frag_lock = tmp; - fr_auth_lock = tmp; - } else - error = EFAULT; - break; -#ifdef IPFILTER_LOG - case SIOCIPFFB : - if (!(mode & FWRITE)) - error = EPERM; - else - *(int *)data = ipflog_clear(unit); - break; -#endif /* IPFILTER_LOG */ - case SIOCGFRST : - error = IWCOPYPTR((caddr_t)ipfr_fragstats(), data, - sizeof(ipfrstat_t)); - if (error) - return EFAULT; - break; - case SIOCAUTHW : - case SIOCAUTHR : - if (!(mode & FWRITE)) { - error = EPERM; - break; - } - case SIOCFRSYN : - if (!(mode & FWRITE)) - error = EPERM; - else { -#if defined(_KERNEL) && defined(__sgi) - ipfsync(); -#endif - frsync(); - } - break; - default : - error = EINVAL; - break; - } - SPL_X(s); - return error; -} - - -void fr_forgetifp(ifp) -void *ifp; -{ - register frentry_t *f; - - WRITE_ENTER(&ipf_mutex); - for (f = ipacct[0][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; - for (f = ipacct[1][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; - for (f = ipfilter[0][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; - for (f = ipfilter[1][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; -#ifdef USE_INET6 - for (f = ipacct6[0][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; - for (f = ipacct6[1][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; - for (f = ipfilter6[0][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; - for (f = ipfilter6[1][fr_active]; (f != NULL); f = f->fr_next) - if (f->fr_ifa == ifp) - f->fr_ifa = (void *)-1; -#endif - RWLOCK_EXIT(&ipf_mutex); - ip_natsync(ifp); -} - - -static int frrequest(unit, req, data, set) -int unit; -#if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003) -u_long req; -#else -int req; -#endif -int set; -caddr_t data; -{ - register frentry_t *fp, *f, **fprev; - register frentry_t **ftail; - frentry_t frd; - frdest_t *fdp; - frgroup_t *fg = NULL; - u_int *p, *pp; - int error = 0, in; - u_int group; - - fp = &frd; - error = IRCOPYPTR(data, (caddr_t)fp, sizeof(*fp)); - if (error) - return EFAULT; - fp->fr_ref = 0; -#if (BSD >= 199306) && defined(_KERNEL) - if ((securelevel > 0) && (fp->fr_func != NULL)) - return EPERM; -#endif - - /* - * Check that the group number does exist and that if a head group - * has been specified, doesn't exist. - */ - if ((req != SIOCZRLST) && fp->fr_grhead && - fr_findgroup((u_int)fp->fr_grhead, fp->fr_flags, unit, set, NULL)) - return EEXIST; - if ((req != SIOCZRLST) && fp->fr_group && - !fr_findgroup((u_int)fp->fr_group, fp->fr_flags, unit, set, NULL)) - return ESRCH; - - in = (fp->fr_flags & FR_INQUE) ? 0 : 1; - - if (unit == IPL_LOGAUTH) - ftail = fprev = &ipauth; - else if ((fp->fr_flags & FR_ACCOUNT) && (fp->fr_v == 4)) - ftail = fprev = &ipacct[in][set]; - else if ((fp->fr_flags & (FR_OUTQUE|FR_INQUE)) && (fp->fr_v == 4)) - ftail = fprev = &ipfilter[in][set]; -#ifdef USE_INET6 - else if ((fp->fr_flags & FR_ACCOUNT) && (fp->fr_v == 6)) - ftail = fprev = &ipacct6[in][set]; - else if ((fp->fr_flags & (FR_OUTQUE|FR_INQUE)) && (fp->fr_v == 6)) - ftail = fprev = &ipfilter6[in][set]; -#endif - else - return ESRCH; - - if ((group = fp->fr_group)) { - if (!(fg = fr_findgroup(group, fp->fr_flags, unit, set, NULL))) - return ESRCH; - ftail = fprev = fg->fg_start; - } - - bzero((char *)frcache, sizeof(frcache[0]) * 2); - - if (*fp->fr_ifname) { - fp->fr_ifa = GETUNIT(fp->fr_ifname, fp->fr_v); - if (!fp->fr_ifa) - fp->fr_ifa = (void *)-1; - } -#if BSD >= 199306 - if (*fp->fr_oifname) { - fp->fr_oifa = GETUNIT(fp->fr_oifname, fp->fr_v); - if (!fp->fr_oifa) - fp->fr_oifa = (void *)-1; - } -#endif - - fdp = &fp->fr_dif; - fp->fr_flags &= ~FR_DUP; - if (*fdp->fd_ifname) { - fdp->fd_ifp = GETUNIT(fdp->fd_ifname, fp->fr_v); - if (!fdp->fd_ifp) - fdp->fd_ifp = (struct ifnet *)-1; - else - fp->fr_flags |= FR_DUP; - } - - fdp = &fp->fr_tif; - if (*fdp->fd_ifname) { - fdp->fd_ifp = GETUNIT(fdp->fd_ifname, fp->fr_v); - if (!fdp->fd_ifp) - fdp->fd_ifp = (struct ifnet *)-1; - } - - /* - * Look for a matching filter rule, but don't include the next or - * interface pointer in the comparison (fr_next, fr_ifa). - */ - for (fp->fr_cksum = 0, p = (u_int *)&fp->fr_ip, pp = &fp->fr_cksum; - p < pp; p++) - fp->fr_cksum += *p; - - for (; (f = *ftail); ftail = &f->fr_next) - if ((fp->fr_cksum == f->fr_cksum) && - !bcmp((char *)&f->fr_ip, (char *)&fp->fr_ip, FR_CMPSIZ)) - break; - - /* - * If zero'ing statistics, copy current to caller and zero. - */ - if (req == SIOCZRLST) { - if (!f) - return ESRCH; - error = IWCOPYPTR((caddr_t)f, data, sizeof(*f)); - if (error) - return EFAULT; - f->fr_hits = 0; - f->fr_bytes = 0; - return 0; - } - - if (!f) { - if (req != SIOCINAFR && req != SIOCINIFR) - while ((f = *ftail)) - ftail = &f->fr_next; - else { - if (fp->fr_hits) { - ftail = fprev; - while (--fp->fr_hits && (f = *ftail)) - ftail = &f->fr_next; - } - f = NULL; - } - } - - if (req == SIOCRMAFR || req == SIOCRMIFR) { - if (!f) - error = ESRCH; - else { - /* - * Only return EBUSY if there is a group list, else - * it's probably just state information referencing - * the rule. - */ - if ((f->fr_ref > 1) && f->fr_grp) - return EBUSY; - if (fg && fg->fg_head) - fg->fg_head->fr_ref--; - if (unit == IPL_LOGAUTH) - return fr_auth_ioctl(data, req, f, ftail); - if (f->fr_grhead) - fr_delgroup((u_int)f->fr_grhead, fp->fr_flags, - unit, set); - fixskip(fprev, f, -1); - *ftail = f->fr_next; - f->fr_next = NULL; - if (f->fr_ref == 0) - KFREE(f); - } - } else { - if (f) - error = EEXIST; - else { - if (unit == IPL_LOGAUTH) - return fr_auth_ioctl(data, req, fp, ftail); - KMALLOC(f, frentry_t *); - if (f != NULL) { - if (fg && fg->fg_head) - fg->fg_head->fr_ref++; - bcopy((char *)fp, (char *)f, sizeof(*f)); - f->fr_ref = 1; - f->fr_hits = 0; - f->fr_next = *ftail; - *ftail = f; - if (req == SIOCINIFR || req == SIOCINAFR) - fixskip(fprev, f, 1); - f->fr_grp = NULL; - if ((group = f->fr_grhead)) - fg = fr_addgroup(group, f, unit, set); - } else - error = ENOMEM; - } - } - return (error); -} - - -#ifdef _KERNEL -/* - * routines below for saving IP headers to buffer - */ -# ifdef __sgi -# ifdef _KERNEL -int IPL_EXTERN(open)(dev_t *pdev, int flags, int devtype, cred_t *cp) -# else -int IPL_EXTERN(open)(dev_t dev, int flags) -# endif -# else -int IPL_EXTERN(open)(dev, flags -# if ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \ - (__FreeBSD_version >= 220000) || defined(__OpenBSD__)) && defined(_KERNEL) -, devtype, p) -int devtype; -struct proc *p; -# else -) -# endif -dev_t dev; -int flags; -# endif /* __sgi */ -{ -# if defined(__sgi) && defined(_KERNEL) - u_int min = geteminor(*pdev); -# else - u_int min = GET_MINOR(dev); -# endif - - if (IPL_LOGMAX < min) - min = ENXIO; - else - min = 0; - return min; -} - - -# ifdef __sgi -int IPL_EXTERN(close)(dev_t dev, int flags, int devtype, cred_t *cp) -#else -int IPL_EXTERN(close)(dev, flags -# if ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \ - (__FreeBSD_version >= 220000) || defined(__OpenBSD__)) && defined(_KERNEL) -, devtype, p) -int devtype; -struct proc *p; -# else -) -# endif -dev_t dev; -int flags; -# endif /* __sgi */ -{ - u_int min = GET_MINOR(dev); - - if (IPL_LOGMAX < min) - min = ENXIO; - else - min = 0; - return min; -} - -/* - * iplread/ipllog - * both of these must operate with at least splnet() lest they be - * called during packet processing and cause an inconsistancy to appear in - * the filter lists. - */ -# ifdef __sgi -int IPL_EXTERN(read)(dev_t dev, uio_t *uio, cred_t *crp) -# else -# if BSD >= 199306 -int IPL_EXTERN(read)(dev, uio, ioflag) -int ioflag; -# else -int IPL_EXTERN(read)(dev, uio) -# endif -dev_t dev; -register struct uio *uio; -# endif /* __sgi */ -{ -# ifdef IPFILTER_LOG - return ipflog_read(GET_MINOR(dev), uio); -# else - return ENXIO; -# endif -} - - -/* - * send_reset - this could conceivably be a call to tcp_respond(), but that - * requires a large amount of setting up and isn't any more efficient. - */ -int send_reset(oip, fin) -struct ip *oip; -fr_info_t *fin; -{ - struct tcphdr *tcp, *tcp2; - int tlen = 0, hlen; - struct mbuf *m; -#ifdef USE_INET6 - ip6_t *ip6, *oip6 = (ip6_t *)oip; -#endif - ip_t *ip; - - tcp = (struct tcphdr *)fin->fin_dp; - if (tcp->th_flags & TH_RST) - return -1; /* feedback loop */ -# if (BSD < 199306) || defined(__sgi) - m = m_get(M_DONTWAIT, MT_HEADER); -# else - m = m_gethdr(M_DONTWAIT, MT_HEADER); -# endif - if (m == NULL) - return ENOBUFS; - if (m == NULL) - return -1; - - tlen = oip->ip_len - fin->fin_hlen - (tcp->th_off << 2) + - ((tcp->th_flags & TH_SYN) ? 1 : 0) + - ((tcp->th_flags & TH_FIN) ? 1 : 0); - -#ifdef USE_INET6 - hlen = (fin->fin_v == 6) ? sizeof(ip6_t) : sizeof(ip_t); -#else - hlen = sizeof(ip_t); -#endif - m->m_len = sizeof(*tcp2) + hlen; -# if BSD >= 199306 - m->m_data += max_linkhdr; - m->m_pkthdr.len = m->m_len; - m->m_pkthdr.rcvif = (struct ifnet *)0; -# endif - ip = mtod(m, struct ip *); -# ifdef USE_INET6 - ip6 = (ip6_t *)ip; -# endif - bzero((char *)ip, sizeof(*tcp2) + hlen); - tcp2 = (struct tcphdr *)((char *)ip + hlen); - - tcp2->th_sport = tcp->th_dport; - tcp2->th_dport = tcp->th_sport; - if (tcp->th_flags & TH_ACK) { - tcp2->th_seq = tcp->th_ack; - tcp2->th_flags = TH_RST; - } else { - tcp2->th_ack = ntohl(tcp->th_seq); - tcp2->th_ack += tlen; - tcp2->th_ack = htonl(tcp2->th_ack); - tcp2->th_flags = TH_RST|TH_ACK; - } - tcp2->th_off = sizeof(*tcp2) >> 2; -# ifdef USE_INET6 - if (fin->fin_v == 6) { - ip6->ip6_plen = htons(sizeof(struct tcphdr)); - ip6->ip6_nxt = IPPROTO_TCP; - ip6->ip6_src = oip6->ip6_dst; - ip6->ip6_dst = oip6->ip6_src; - tcp2->th_sum = in6_cksum(m, IPPROTO_TCP, - sizeof(*ip6), sizeof(*tcp2)); - return send_ip(oip, fin, m); - } -# endif - ip->ip_p = IPPROTO_TCP; - ip->ip_len = htons(sizeof(struct tcphdr)); - ip->ip_src.s_addr = oip->ip_dst.s_addr; - ip->ip_dst.s_addr = oip->ip_src.s_addr; - tcp2->th_sum = in_cksum(m, hlen + sizeof(*tcp2)); - ip->ip_len = hlen + sizeof(*tcp2); - return send_ip(oip, fin, m); -} - - -static int send_ip(oip, fin, m) -ip_t *oip; -fr_info_t *fin; -struct mbuf *m; -{ - ip_t *ip; - - ip = mtod(m, ip_t *); - - ip->ip_v = fin->fin_v; - if (ip->ip_v == 4) { - ip->ip_hl = (sizeof(*oip) >> 2); - ip->ip_v = IPVERSION; - ip->ip_tos = oip->ip_tos; - ip->ip_id = oip->ip_id; - ip->ip_off = 0; -# if (BSD < 199306) || defined(__sgi) - ip->ip_ttl = tcp_ttl; -# else - ip->ip_ttl = ip_defttl; -# endif - ip->ip_sum = 0; - } -# ifdef USE_INET6 - else if (ip->ip_v == 6) { - ip6_t *ip6 = (ip6_t *)ip; - - ip6->ip6_hlim = 127; - - return ip6_output(m, NULL, NULL, 0, NULL, NULL); - } -# endif -# ifdef IPSEC - m->m_pkthdr.rcvif = NULL; -# endif - return ipfr_fastroute(m, fin, NULL); -} - - -int send_icmp_err(oip, type, fin, dst) -ip_t *oip; -int type; -fr_info_t *fin; -int dst; -{ - int err, hlen = 0, xtra = 0, iclen, ohlen = 0, avail, code; - struct in_addr dst4; - struct icmp *icmp; - struct mbuf *m; - void *ifp; -#ifdef USE_INET6 - ip6_t *ip6, *oip6 = (ip6_t *)oip; - struct in6_addr dst6; -#endif - ip_t *ip; - - if ((type < 0) || (type > ICMP_MAXTYPE)) - return -1; - - code = fin->fin_icode; -#ifdef USE_INET6 - if ((code < 0) || (code > sizeof(icmptoicmp6unreach)/sizeof(int))) - return -1; -#endif - - avail = 0; - m = NULL; - ifp = fin->fin_ifp; - if (fin->fin_v == 4) { - if ((oip->ip_p == IPPROTO_ICMP) && - !(fin->fin_fi.fi_fl & FI_SHORT)) - switch (ntohs(fin->fin_data[0]) >> 8) - { - case ICMP_ECHO : - case ICMP_TSTAMP : - case ICMP_IREQ : - case ICMP_MASKREQ : - break; - default : - return 0; - } - -# if (BSD < 199306) || defined(__sgi) - avail = MLEN; - m = m_get(M_DONTWAIT, MT_HEADER); -# else - avail = MHLEN; - m = m_gethdr(M_DONTWAIT, MT_HEADER); -# endif - if (m == NULL) - return ENOBUFS; - - if (dst == 0) { - if (fr_ifpaddr(4, ifp, &dst4) == -1) - return -1; - } else - dst4.s_addr = oip->ip_dst.s_addr; - - hlen = sizeof(ip_t); - ohlen = oip->ip_hl << 2; - xtra = 8; - } - -#ifdef USE_INET6 - else if (fin->fin_v == 6) { - hlen = sizeof(ip6_t); - ohlen = sizeof(ip6_t); - type = icmptoicmp6types[type]; - if (type == ICMP6_DST_UNREACH) - code = icmptoicmp6unreach[code]; - - MGETHDR(m, M_DONTWAIT, MT_HEADER); - if (!m) - return ENOBUFS; - - MCLGET(m, M_DONTWAIT); - if ((m->m_flags & M_EXT) == 0) { - m_freem(m); - return ENOBUFS; - } -# ifdef M_TRAILINGSPACE - m->m_len = 0; - avail = M_TRAILINGSPACE(m); -# else - avail = (m->m_flags & M_EXT) ? MCLBYTES : MHLEN; -# endif - xtra = MIN(ntohs(oip6->ip6_plen) + sizeof(ip6_t), - avail - hlen - sizeof(*icmp) - max_linkhdr); - if (dst == 0) { - if (fr_ifpaddr(6, ifp, (struct in_addr *)&dst6) == -1) - return -1; - } else - dst6 = oip6->ip6_dst; - } -#endif - - iclen = hlen + sizeof(*icmp); -# if BSD >= 199306 - avail -= (max_linkhdr + iclen); - m->m_data += max_linkhdr; - m->m_pkthdr.rcvif = (struct ifnet *)0; - if (xtra > avail) - xtra = avail; - iclen += xtra; - m->m_pkthdr.len = iclen; -#else - avail -= (m->m_off + iclen); - if (xtra > avail) - xtra = avail; - iclen += xtra; -#endif - m->m_len = iclen; - ip = mtod(m, ip_t *); - icmp = (struct icmp *)((char *)ip + hlen); - bzero((char *)ip, iclen); - - icmp->icmp_type = type; - icmp->icmp_code = fin->fin_icode; - icmp->icmp_cksum = 0; -#ifdef icmp_nextmtu - if (type == ICMP_UNREACH && - fin->fin_icode == ICMP_UNREACH_NEEDFRAG && ifp) - icmp->icmp_nextmtu = htons(((struct ifnet *) ifp)->if_mtu); -#endif - - if (avail) { - bcopy((char *)oip, (char *)&icmp->icmp_ip, MIN(ohlen, avail)); - avail -= MIN(ohlen, avail); - } - -#ifdef USE_INET6 - ip6 = (ip6_t *)ip; - if (fin->fin_v == 6) { - ip6->ip6_flow = 0; - ip6->ip6_plen = htons(iclen - hlen); - ip6->ip6_nxt = IPPROTO_ICMPV6; - ip6->ip6_hlim = 0; - ip6->ip6_src = dst6; - ip6->ip6_dst = oip6->ip6_src; - if (avail) - bcopy((char *)oip + ohlen, - (char *)&icmp->icmp_ip + ohlen, avail); - icmp->icmp_cksum = in6_cksum(m, IPPROTO_ICMPV6, - sizeof(*ip6), iclen - hlen); - } else -#endif - { - ip->ip_src.s_addr = dst4.s_addr; - ip->ip_dst.s_addr = oip->ip_src.s_addr; - - if (avail > 8) - avail = 8; - if (avail) - bcopy((char *)oip + ohlen, - (char *)&icmp->icmp_ip + ohlen, avail); - icmp->icmp_cksum = ipf_cksum((u_short *)icmp, - sizeof(*icmp) + 8); - ip->ip_len = iclen; - ip->ip_p = IPPROTO_ICMP; - } - err = send_ip(oip, fin, m); - return err; -} - - -# if !defined(IPFILTER_LKM) && (__FreeBSD_version < 300000) && !defined(__sgi) -# if (BSD < 199306) -int iplinit __P((void)); - -int -# else -void iplinit __P((void)); - -void -# endif -iplinit() -{ - if (iplattach() != 0) - printf("IP Filter failed to attach\n"); - ip_init(); -} -# endif /* ! __NetBSD__ */ - - -size_t mbufchainlen(m0) -register struct mbuf *m0; -{ - register size_t len = 0; - - for (; m0; m0 = m0->m_next) - len += m0->m_len; - return len; -} - - -int ipfr_fastroute(m0, fin, fdp) -struct mbuf *m0; -fr_info_t *fin; -frdest_t *fdp; -{ - register struct ip *ip, *mhip; - register struct mbuf *m = m0; - register struct route *ro; - int len, off, error = 0, hlen, code; - struct ifnet *ifp, *sifp; - struct sockaddr_in *dst; - struct route iproute; - frentry_t *fr; - - hlen = fin->fin_hlen; - ip = mtod(m0, struct ip *); - -#ifdef USE_INET6 - if (ip->ip_v == 6) { - /* - * currently "to <if>" and "to <if>:ip#" are not supported - * for IPv6 - */ - return ip6_output(m0, NULL, NULL, 0, NULL, NULL); - } -#endif - /* - * Route packet. - */ - ro = &iproute; - bzero((caddr_t)ro, sizeof (*ro)); - dst = (struct sockaddr_in *)&ro->ro_dst; - dst->sin_family = AF_INET; - - fr = fin->fin_fr; - if (fdp) - ifp = fdp->fd_ifp; - else { - ifp = fin->fin_ifp; - dst->sin_addr = ip->ip_dst; - } - - /* - * In case we're here due to "to <if>" being used with "keep state", - * check that we're going in the correct direction. - */ - if ((fr != NULL) && (fin->fin_rev != 0)) { - if ((ifp != NULL) && (fdp == &fr->fr_tif)) - return -1; - dst->sin_addr = ip->ip_dst; - } else if (fdp) - dst->sin_addr = fdp->fd_ip.s_addr ? fdp->fd_ip : ip->ip_dst; - -# if BSD >= 199306 - dst->sin_len = sizeof(*dst); -# endif -# if (BSD >= 199306) && !defined(__NetBSD__) && !defined(__bsdi__) && \ - !defined(__OpenBSD__) -# ifdef RTF_CLONING - rtalloc_ign(ro, RTF_CLONING); -# else - rtalloc_ign(ro, RTF_PRCLONING); -# endif -# else - rtalloc(ro); -# endif - if (!ifp) { - if (!fr || !(fr->fr_flags & FR_FASTROUTE)) { - error = -2; - goto bad; - } - if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) { - if (in_localaddr(ip->ip_dst)) - error = EHOSTUNREACH; - else - error = ENETUNREACH; - goto bad; - } - if (ro->ro_rt->rt_flags & RTF_GATEWAY) - dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway; - } - if (ro->ro_rt) - ro->ro_rt->rt_use++; - - /* - * For input packets which are being "fastrouted", they won't - * go back through output filtering and miss their chance to get - * NAT'd and counted. - */ - fin->fin_ifp = ifp; - if (fin->fin_out == 0) { - fin->fin_out = 1; - if ((fin->fin_fr = ipacct[1][fr_active]) && - (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) { - ATOMIC_INCL(frstats[1].fr_acct); - } - fin->fin_fr = NULL; - if (!fr || !(fr->fr_flags & FR_RETMASK)) - (void) fr_checkstate(ip, fin); - (void) ip_natout(ip, fin); - } else - ip->ip_sum = 0; - /* - * If small enough for interface, can just send directly. - */ - if (ip->ip_len <= ifp->if_mtu) { -# if BSD >= 199306 - int i = 0; - -# ifdef MCLISREFERENCED - if ((m->m_flags & M_EXT) && MCLISREFERENCED(m)) -# else - if (m->m_flags & M_EXT) -# endif - i = 1; -# endif -# ifndef sparc - ip->ip_id = htons(ip->ip_id); - ip->ip_len = htons(ip->ip_len); - ip->ip_off = htons(ip->ip_off); -# endif - if (!ip->ip_sum) - ip->ip_sum = in_cksum(m, hlen); -# if BSD >= 199306 - error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, - ro->ro_rt); - if (i) { - ip->ip_id = ntohs(ip->ip_id); - ip->ip_len = ntohs(ip->ip_len); - ip->ip_off = ntohs(ip->ip_off); - } -# else - error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst); -# endif - goto done; - } - /* - * Too large for interface; fragment if possible. - * Must be able to put at least 8 bytes per fragment. - */ - if (ip->ip_off & IP_DF) { - error = EMSGSIZE; - goto bad; - } - len = (ifp->if_mtu - hlen) &~ 7; - if (len < 8) { - error = EMSGSIZE; - goto bad; - } - - { - int mhlen, firstlen = len; - struct mbuf **mnext = &m->m_act; - - /* - * Loop through length of segment after first fragment, - * make new header and copy data of each part and link onto chain. - */ - m0 = m; - mhlen = sizeof (struct ip); - for (off = hlen + len; off < ip->ip_len; off += len) { -# ifdef MGETHDR - MGETHDR(m, M_DONTWAIT, MT_HEADER); -# else - MGET(m, M_DONTWAIT, MT_HEADER); -# endif - if (m == 0) { - error = ENOBUFS; - goto bad; - } -# if BSD >= 199306 - m->m_data += max_linkhdr; -# else - m->m_off = MMAXOFF - hlen; -# endif - mhip = mtod(m, struct ip *); - bcopy((char *)ip, (char *)mhip, sizeof(*ip)); - if (hlen > sizeof (struct ip)) { - mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); - mhip->ip_hl = mhlen >> 2; - } - m->m_len = mhlen; - mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF); - if (ip->ip_off & IP_MF) - mhip->ip_off |= IP_MF; - if (off + len >= ip->ip_len) - len = ip->ip_len - off; - else - mhip->ip_off |= IP_MF; - mhip->ip_len = htons((u_short)(len + mhlen)); - m->m_next = m_copy(m0, off, len); - if (m->m_next == 0) { - error = ENOBUFS; /* ??? */ - goto sendorfree; - } -# if BSD >= 199306 - m->m_pkthdr.len = mhlen + len; - m->m_pkthdr.rcvif = NULL; -# endif -# ifndef sparc - mhip->ip_off = htons((u_short)mhip->ip_off); -# endif - mhip->ip_sum = 0; - mhip->ip_sum = in_cksum(m, mhlen); - *mnext = m; - mnext = &m->m_act; - } - /* - * Update first fragment by trimming what's been copied out - * and updating header, then send each fragment (in order). - */ - m_adj(m0, hlen + firstlen - ip->ip_len); - ip->ip_len = htons((u_short)(hlen + firstlen)); - ip->ip_off = htons((u_short)(ip->ip_off | IP_MF)); - ip->ip_sum = 0; - ip->ip_sum = in_cksum(m0, hlen); -sendorfree: - for (m = m0; m; m = m0) { - m0 = m->m_act; - m->m_act = 0; - if (error == 0) -# if BSD >= 199306 - error = (*ifp->if_output)(ifp, m, - (struct sockaddr *)dst, ro->ro_rt); -# else - error = (*ifp->if_output)(ifp, m, - (struct sockaddr *)dst); -# endif - else - m_freem(m); - } - } -done: - if (!error) - ipl_frouteok[0]++; - else - ipl_frouteok[1]++; - - if (ro->ro_rt) - RTFREE(ro->ro_rt); - return 0; -bad: - if (error == EMSGSIZE) { - sifp = fin->fin_ifp; - code = fin->fin_icode; - fin->fin_icode = ICMP_UNREACH_NEEDFRAG; - fin->fin_ifp = ifp; - (void) send_icmp_err(ip, ICMP_UNREACH, fin, 1); - fin->fin_ifp = sifp; - fin->fin_icode = code; - } - m_freem(m); - goto done; -} - - -int fr_verifysrc(ipa, ifp) -struct in_addr ipa; -void *ifp; -{ - struct sockaddr_in *dst; - struct route iproute; - - bzero((char *)&iproute, sizeof(iproute)); - dst = (struct sockaddr_in *)&iproute.ro_dst; - dst->sin_family = AF_INET; - dst->sin_addr = ipa; -# if (BSD >= 199306) && !defined(__NetBSD__) && !defined(__bsdi__) && \ - !defined(__OpenBSD__) -# ifdef RTF_CLONING - rtalloc_ign(&iproute, RTF_CLONING); -# else - rtalloc_ign(&iproute, RTF_PRCLONING); -# endif -# else - rtalloc(&iproute); -# endif - if (iproute.ro_rt == NULL) - return 0; - return (ifp == iproute.ro_rt->rt_ifp); -} - -#else /* #ifdef _KERNEL */ - - -# ifdef __sgi -static int no_output __P((struct ifnet *ifp, struct mbuf *m, - struct sockaddr *s)) -# else -static int no_output __P((struct ifnet *ifp, struct mbuf *m, - struct sockaddr *s, struct rtentry *rt)) -# endif -{ - return 0; -} - - -# ifdef __STDC__ -# ifdef __sgi -static int write_output __P((struct ifnet *ifp, struct mbuf *m, - struct sockaddr *s)) -# else -static int write_output __P((struct ifnet *ifp, struct mbuf *m, - struct sockaddr *s, struct rtentry *rt)) -# endif -{ - ip_t *ip = (ip_t *)m; -# else -static int write_output(ifp, ip) -struct ifnet *ifp; -ip_t *ip; -{ -# endif - char fname[32]; - int fd; - -# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603)) - sprintf(fname, "/tmp/%s", ifp->if_xname); -# else - sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); -# endif - fd = open(fname, O_WRONLY|O_APPEND); - if (fd == -1) { - perror("open"); - return -1; - } - write(fd, (char *)ip, ntohs(ip->ip_len)); - close(fd); - return 0; -} - - -struct ifnet *get_unit(name, v) -char *name; -int v; -{ - struct ifnet *ifp, **ifa; -# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603)) - for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) { - if (!strcmp(name, ifp->if_xname)) - return ifp; - } -# else - char ifname[32], *s; - - for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) { - (void) sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit); - if (!strcmp(name, ifname)) - return ifp; - } -# endif - - if (!ifneta) { - ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2); - if (!ifneta) - return NULL; - ifneta[1] = NULL; - ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp)); - if (!ifneta[0]) { - free(ifneta); - return NULL; - } - nifs = 1; - } else { - nifs++; - ifneta = (struct ifnet **)realloc(ifneta, - (nifs + 1) * sizeof(*ifa)); - if (!ifneta) { - nifs = 0; - return NULL; - } - ifneta[nifs] = NULL; - ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp)); - if (!ifneta[nifs - 1]) { - nifs--; - return NULL; - } - } - ifp = ifneta[nifs - 1]; - -# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603)) - strncpy(ifp->if_xname, name, sizeof(ifp->if_xname)); -# else - for (s = name; *s && !isdigit(*s); s++) - ; - if (*s && isdigit(*s)) { - ifp->if_unit = atoi(s); - ifp->if_name = (char *)malloc(s - name + 1); - strncpy(ifp->if_name, name, s - name); - ifp->if_name[s - name] = '\0'; - } else { - ifp->if_name = strdup(name); - ifp->if_unit = -1; - } -# endif - ifp->if_output = no_output; - return ifp; -} - - - -void init_ifp() -{ - struct ifnet *ifp, **ifa; - char fname[32]; - int fd; - -# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603)) - for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) { - ifp->if_output = write_output; - sprintf(fname, "/tmp/%s", ifp->if_xname); - fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); - if (fd == -1) - perror("open"); - else - close(fd); - } -# else - - for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) { - ifp->if_output = write_output; - sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); - fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); - if (fd == -1) - perror("open"); - else - close(fd); - } -# endif -} - - -int ipfr_fastroute(ip, fin, fdp) -ip_t *ip; -fr_info_t *fin; -frdest_t *fdp; -{ - struct ifnet *ifp = fdp->fd_ifp; - - if (!ifp) - return 0; /* no routing table out here */ - - ip->ip_len = htons((u_short)ip->ip_len); - ip->ip_off = htons((u_short)(ip->ip_off | IP_MF)); - ip->ip_sum = 0; -#ifdef __sgi - (*ifp->if_output)(ifp, (void *)ip, NULL); -#else - (*ifp->if_output)(ifp, (void *)ip, NULL, 0); -#endif - return 0; -} - - -int ipllog __P((void)) -{ - verbose("l"); - return 0; -} - - -int send_reset(ip, ifp) -ip_t *ip; -struct ifnet *ifp; -{ - verbose("- TCP RST sent\n"); - return 0; -} - - -int icmp_error(ip, ifp) -ip_t *ip; -struct ifnet *ifp; -{ - verbose("- TCP RST sent\n"); - return 0; -} - - -void frsync() -{ - return; -} -#endif /* _KERNEL */ diff --git a/contrib/ipfilter/ip_fil.h b/contrib/ipfilter/ip_fil.h deleted file mode 100644 index 9dd75f0..0000000 --- a/contrib/ipfilter/ip_fil.h +++ /dev/null @@ -1,631 +0,0 @@ -/* - * Copyright (C) 1993-2000 by Darren Reed. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - * - * @(#)ip_fil.h 1.35 6/5/96 - * $FreeBSD$ - */ - -#ifndef __IP_FIL_H__ -#define __IP_FIL_H__ - -/* - * Pathnames for various IP Filter control devices. Used by LKM - * and userland, so defined here. - */ -#define IPNAT_NAME "/dev/ipnat" -#define IPSTATE_NAME "/dev/ipstate" -#define IPAUTH_NAME "/dev/ipauth" - -#ifndef SOLARIS -# define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) -#endif - -#if defined(KERNEL) && !defined(_KERNEL) -# define _KERNEL -#endif - -#ifndef __P -# ifdef __STDC__ -# define __P(x) x -# else -# define __P(x) () -# endif -#endif - -#if defined(__STDC__) || defined(__GNUC__) -# define SIOCADAFR _IOW('r', 60, struct frentry *) -# define SIOCRMAFR _IOW('r', 61, struct frentry *) -# define SIOCSETFF _IOW('r', 62, u_int) -# define SIOCGETFF _IOR('r', 63, u_int) -# define SIOCGETFS _IOWR('r', 64, struct friostat *) -# define SIOCIPFFL _IOWR('r', 65, int) -# define SIOCIPFFB _IOR('r', 66, int) -# define SIOCADIFR _IOW('r', 67, struct frentry *) -# define SIOCRMIFR _IOW('r', 68, struct frentry *) -# define SIOCSWAPA _IOR('r', 69, u_int) -# define SIOCINAFR _IOW('r', 70, struct frentry *) -# define SIOCINIFR _IOW('r', 71, struct frentry *) -# define SIOCFRENB _IOW('r', 72, u_int) -# define SIOCFRSYN _IOW('r', 73, u_int) -# define SIOCFRZST _IOWR('r', 74, struct friostat *) -# define SIOCZRLST _IOWR('r', 75, struct frentry *) -# define SIOCAUTHW _IOWR('r', 76, struct fr_info *) -# define SIOCAUTHR _IOWR('r', 77, struct fr_info *) -# define SIOCATHST _IOWR('r', 78, struct fr_authstat *) -# define SIOCSTLCK _IOWR('r', 79, u_int) -# define SIOCSTPUT _IOWR('r', 80, struct ipstate_save *) -# define SIOCSTGET _IOWR('r', 81, struct ipstate_save *) -# define SIOCSTGSZ _IOWR('r', 82, struct natget *) -# define SIOCGFRST _IOWR('r', 83, struct ipfrstat *) -#else -# define SIOCADAFR _IOW(r, 60, struct frentry *) -# define SIOCRMAFR _IOW(r, 61, struct frentry *) -# define SIOCSETFF _IOW(r, 62, u_int) -# define SIOCGETFF _IOR(r, 63, u_int) -# define SIOCGETFS _IOWR(r, 64, struct friostat *) -# define SIOCIPFFL _IOWR(r, 65, int) -# define SIOCIPFFB _IOR(r, 66, int) -# define SIOCADIFR _IOW(r, 67, struct frentry *) -# define SIOCRMIFR _IOW(r, 68, struct frentry *) -# define SIOCSWAPA _IOR(r, 69, u_int) -# define SIOCINAFR _IOW(r, 70, struct frentry *) -# define SIOCINIFR _IOW(r, 71, struct frentry *) -# define SIOCFRENB _IOW(r, 72, u_int) -# define SIOCFRSYN _IOW(r, 73, u_int) -# define SIOCFRZST _IOWR(r, 74, struct friostat *) -# define SIOCZRLST _IOWR(r, 75, struct frentry *) -# define SIOCAUTHW _IOWR(r, 76, struct fr_info *) -# define SIOCAUTHR _IOWR(r, 77, struct fr_info *) -# define SIOCATHST _IOWR(r, 78, struct fr_authstat *) -# define SIOCSTLCK _IOWR(r, 79, u_int) -# define SIOCSTPUT _IOWR(r, 80, struct ipstate_save *) -# define SIOCSTGET _IOWR(r, 81, struct ipstate_save *) -# define SIOCSTGSZ _IOWR(r, 82, struct natget *) -# define SIOCGFRST _IOWR(r, 83, struct ipfrstat *) -#endif -#define SIOCADDFR SIOCADAFR -#define SIOCDELFR SIOCRMAFR -#define SIOCINSFR SIOCINAFR - - -typedef struct fr_ip { - u_32_t fi_v:4; /* IP version */ - u_32_t fi_fl:4; /* packet flags */ - u_32_t fi_tos:8; /* IP packet TOS */ - u_32_t fi_ttl:8; /* IP packet TTL */ - u_32_t fi_p:8; /* IP packet protocol */ - union i6addr fi_src; /* source address from packet */ - union i6addr fi_dst; /* destination address from packet */ - u_32_t fi_optmsk; /* bitmask composed from IP options */ - u_short fi_secmsk; /* bitmask composed from IP security options */ - u_short fi_auth; /* authentication code from IP sec. options */ -} fr_ip_t; - -#define FI_OPTIONS (FF_OPTIONS >> 24) -#define FI_TCPUDP (FF_TCPUDP >> 24) /* TCP/UCP implied comparison*/ -#define FI_FRAG (FF_FRAG >> 24) -#define FI_SHORT (FF_SHORT >> 24) -#define FI_CMP (FI_OPTIONS|FI_TCPUDP|FI_SHORT) - -#define fi_saddr fi_src.in4.s_addr -#define fi_daddr fi_dst.in4.s_addr - - -/* - * These are both used by the state and NAT code to indicate that one port or - * the other should be treated as a wildcard. - */ -#define FI_W_SPORT 0x00000100 -#define FI_W_DPORT 0x00000200 -#define FI_WILDP (FI_W_SPORT|FI_W_DPORT) -#define FI_W_SADDR 0x00000400 -#define FI_W_DADDR 0x00000800 -#define FI_WILDA (FI_W_SADDR|FI_W_DADDR) -#define FI_NEWFR 0x00001000 - -typedef struct fr_info { - void *fin_ifp; /* interface packet is `on' */ - struct fr_ip fin_fi; /* IP Packet summary */ - u_short fin_data[2]; /* TCP/UDP ports, ICMP code/type */ - u_char fin_out; /* in or out ? 1 == out, 0 == in */ - u_char fin_rev; /* state only: 1 = reverse */ - u_short fin_hlen; /* length of IP header in bytes */ - u_char fin_tcpf; /* TCP header flags (SYN, ACK, etc) */ - /* From here on is packet specific */ - u_char fin_icode; /* ICMP error to return */ - u_short fin_rule; /* rule # last matched */ - u_32_t fin_group; /* group number, -1 for none */ - struct frentry *fin_fr; /* last matching rule */ - char *fin_dp; /* start of data past IP header */ - u_short fin_dlen; /* length of data portion of packet */ - u_short fin_id; /* IP packet id field */ - void *fin_mp; /* pointer to pointer to mbuf */ -#if SOLARIS - void *fin_qfm; /* pointer to mblk where pkt starts */ - void *fin_qif; -#endif - u_short fin_plen; - u_short fin_off; -} fr_info_t; - -#define fin_v fin_fi.fi_v - -/* - * Size for compares on fr_info structures - */ -#define FI_CSIZE offsetof(fr_info_t, fin_icode) - -/* - * Size for copying cache fr_info structure - */ -#define FI_COPYSIZE offsetof(fr_info_t, fin_dp) - -typedef struct frdest { - void *fd_ifp; - struct in_addr fd_ip; - char fd_ifname[IFNAMSIZ]; -} frdest_t; - -typedef struct frpcmp { - int frp_cmp; /* data for port comparisons */ - u_short frp_port; /* top port for <> and >< */ - u_short frp_top; /* top port for <> and >< */ -} frpcmp_t; - -typedef struct frtuc { - u_char ftu_tcpfm; /* tcp flags mask */ - u_char ftu_tcpf; /* tcp flags */ - frpcmp_t ftu_src; - frpcmp_t ftu_dst; -} frtuc_t; - -#define ftu_scmp ftu_src.frp_cmp -#define ftu_dcmp ftu_dst.frp_cmp -#define ftu_sport ftu_src.frp_port -#define ftu_dport ftu_dst.frp_port -#define ftu_stop ftu_src.frp_top -#define ftu_dtop ftu_dst.frp_top - -typedef struct frentry { - struct frentry *fr_next; - u_32_t fr_group; /* group to which this rule belongs */ - u_32_t fr_grhead; /* group # which this rule starts */ - struct frentry *fr_grp; - int fr_ref; /* reference count - for grouping */ - void *fr_ifa; -#if BSD >= 199306 - void *fr_oifa; -#endif - /* - * These are only incremented when a packet matches this rule and - * it is the last match - */ - U_QUAD_T fr_hits; - U_QUAD_T fr_bytes; - /* - * Fields after this may not change whilst in the kernel. - */ - struct fr_ip fr_ip; - struct fr_ip fr_mip; /* mask structure */ - - - u_short fr_icmpm; /* data for ICMP packets (mask) */ - u_short fr_icmp; - - frtuc_t fr_tuc; - u_32_t fr_flags; /* per-rule flags && options (see below) */ - u_int fr_skip; /* # of rules to skip */ - u_int fr_loglevel; /* syslog log facility + priority */ - int (*fr_func) __P((int, ip_t *, fr_info_t *)); /* call this function */ - int fr_sap; /* For solaris only */ - u_char fr_icode; /* return ICMP code */ - char fr_ifname[IFNAMSIZ]; -#if BSD >= 199306 - char fr_oifname[IFNAMSIZ]; -#endif - struct frdest fr_tif; /* "to" interface */ - struct frdest fr_dif; /* duplicate packet interfaces */ - u_int fr_cksum; /* checksum on filter rules for performance */ -} frentry_t; - -#define fr_v fr_ip.fi_v -#define fr_proto fr_ip.fi_p -#define fr_ttl fr_ip.fi_ttl -#define fr_tos fr_ip.fi_tos -#define fr_tcpfm fr_tuc.ftu_tcpfm -#define fr_tcpf fr_tuc.ftu_tcpf -#define fr_scmp fr_tuc.ftu_scmp -#define fr_dcmp fr_tuc.ftu_dcmp -#define fr_dport fr_tuc.ftu_dport -#define fr_sport fr_tuc.ftu_sport -#define fr_stop fr_tuc.ftu_stop -#define fr_dtop fr_tuc.ftu_dtop -#define fr_dst fr_ip.fi_dst.in4 -#define fr_src fr_ip.fi_src.in4 -#define fr_dmsk fr_mip.fi_dst.in4 -#define fr_smsk fr_mip.fi_src.in4 - -#ifndef offsetof -#define offsetof(t,m) (int)((&((t *)0L)->m)) -#endif -#define FR_CMPSIZ (sizeof(struct frentry) - offsetof(frentry_t, fr_ip)) - -/* - * fr_flags - */ -#define FR_BLOCK 0x00001 /* do not allow packet to pass */ -#define FR_PASS 0x00002 /* allow packet to pass */ -#define FR_OUTQUE 0x00004 /* outgoing packets */ -#define FR_INQUE 0x00008 /* ingoing packets */ -#define FR_LOG 0x00010 /* Log */ -#define FR_LOGB 0x00011 /* Log-fail */ -#define FR_LOGP 0x00012 /* Log-pass */ -#define FR_LOGBODY 0x00020 /* Log the body */ -#define FR_LOGFIRST 0x00040 /* Log the first byte if state held */ -#define FR_RETRST 0x00080 /* Return TCP RST packet - reset connection */ -#define FR_RETICMP 0x00100 /* Return ICMP unreachable packet */ -#define FR_FAKEICMP 0x00180 /* Return ICMP unreachable with fake source */ -#define FR_NOMATCH 0x00200 /* no match occured */ -#define FR_ACCOUNT 0x00400 /* count packet bytes */ -#define FR_KEEPFRAG 0x00800 /* keep fragment information */ -#define FR_KEEPSTATE 0x01000 /* keep `connection' state information */ -#define FR_INACTIVE 0x02000 -#define FR_QUICK 0x04000 /* match & stop processing list */ -#define FR_FASTROUTE 0x08000 /* bypass normal routing */ -#define FR_CALLNOW 0x10000 /* call another function (fr_func) if matches */ -#define FR_DUP 0x20000 /* duplicate packet */ -#define FR_LOGORBLOCK 0x40000 /* block the packet if it can't be logged */ -#define FR_NOTSRCIP 0x80000 /* not the src IP# */ -#define FR_NOTDSTIP 0x100000 /* not the dst IP# */ -#define FR_AUTH 0x200000 /* use authentication */ -#define FR_PREAUTH 0x400000 /* require preauthentication */ -#define FR_DONTCACHE 0x800000 /* don't cache the result */ - -#define FR_LOGMASK (FR_LOG|FR_LOGP|FR_LOGB) -#define FR_RETMASK (FR_RETICMP|FR_RETRST|FR_FAKEICMP) - -/* - * These correspond to #define's for FI_* and are stored in fr_flags - */ -#define FF_OPTIONS 0x01000000 -#define FF_TCPUDP 0x02000000 -#define FF_FRAG 0x04000000 -#define FF_SHORT 0x08000000 -/* - * recognized flags for SIOCGETFF and SIOCSETFF, and get put in fr_flags - */ -#define FF_LOGPASS 0x10000000 -#define FF_LOGBLOCK 0x20000000 -#define FF_LOGNOMATCH 0x40000000 -#define FF_LOGGING (FF_LOGPASS|FF_LOGBLOCK|FF_LOGNOMATCH) -#define FF_BLOCKNONIP 0x80000000 /* Solaris2 Only */ - -#define FR_NONE 0 -#define FR_EQUAL 1 -#define FR_NEQUAL 2 -#define FR_LESST 3 -#define FR_GREATERT 4 -#define FR_LESSTE 5 -#define FR_GREATERTE 6 -#define FR_OUTRANGE 7 -#define FR_INRANGE 8 - -typedef struct filterstats { - u_long fr_pass; /* packets allowed */ - u_long fr_block; /* packets denied */ - u_long fr_nom; /* packets which don't match any rule */ - u_long fr_short; /* packets which are short */ - u_long fr_ppkl; /* packets allowed and logged */ - u_long fr_bpkl; /* packets denied and logged */ - u_long fr_npkl; /* packets unmatched and logged */ - u_long fr_pkl; /* packets logged */ - u_long fr_skip; /* packets to be logged but buffer full */ - u_long fr_ret; /* packets for which a return is sent */ - u_long fr_acct; /* packets for which counting was performed */ - u_long fr_bnfr; /* bad attempts to allocate fragment state */ - u_long fr_nfr; /* new fragment state kept */ - u_long fr_cfr; /* add new fragment state but complete pkt */ - u_long fr_bads; /* bad attempts to allocate packet state */ - u_long fr_ads; /* new packet state kept */ - u_long fr_chit; /* cached hit */ - u_long fr_tcpbad; /* TCP checksum check failures */ - u_long fr_pull[2]; /* good and bad pullup attempts */ - u_long fr_badsrc; /* source received doesn't match route */ - u_long fr_badttl; /* TTL in packet doesn't reach minimum */ -#if SOLARIS - u_long fr_notdata; /* PROTO/PCPROTO that have no data */ - u_long fr_nodata; /* mblks that have no data */ - u_long fr_bad; /* bad IP packets to the filter */ - u_long fr_notip; /* packets passed through no on ip queue */ - u_long fr_drop; /* packets dropped - no info for them! */ - u_long fr_copy; /* messages copied due to db_ref > 1 */ -#endif - u_long fr_ipv6[2]; /* IPv6 packets in/out */ -} filterstats_t; - -/* - * For SIOCGETFS - */ -typedef struct friostat { - struct filterstats f_st[2]; - struct frentry *f_fin[2]; - struct frentry *f_fout[2]; - struct frentry *f_acctin[2]; - struct frentry *f_acctout[2]; - struct frentry *f_fin6[2]; - struct frentry *f_fout6[2]; - struct frentry *f_acctin6[2]; - struct frentry *f_acctout6[2]; - struct frentry *f_auth; - struct frgroup *f_groups[3][2]; - u_long f_froute[2]; - int f_defpass; /* default pass - from fr_pass */ - char f_active; /* 1 or 0 - active rule set */ - char f_running; /* 1 if running, else 0 */ - char f_logging; /* 1 if enabled, else 0 */ - char f_version[32]; /* version string */ - int f_locks[4]; -} friostat_t; - -typedef struct optlist { - u_short ol_val; - int ol_bit; -} optlist_t; - - -/* - * Group list structure. - */ -typedef struct frgroup { - u_32_t fg_num; - struct frgroup *fg_next; - struct frentry *fg_head; - struct frentry **fg_start; -} frgroup_t; - - -/* - * Log structure. Each packet header logged is prepended by one of these. - * Following this in the log records read from the device will be an ipflog - * structure which is then followed by any packet data. - */ -typedef struct iplog { - u_32_t ipl_magic; - u_int ipl_count; - u_long ipl_sec; - u_long ipl_usec; - size_t ipl_dsize; - struct iplog *ipl_next; -} iplog_t; - -#define IPL_MAGIC 0x49504c4d /* 'IPLM' */ - -typedef struct ipflog { -#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603)) - u_char fl_ifname[IFNAMSIZ]; -#else - u_int fl_unit; - u_char fl_ifname[4]; -#endif - u_char fl_plen; /* extra data after hlen */ - u_char fl_hlen; /* length of IP headers saved */ - u_short fl_loglevel; /* syslog log level */ - u_32_t fl_rule; - u_32_t fl_group; - u_32_t fl_flags; - u_32_t fl_lflags; -} ipflog_t; - - -#ifndef ICMP_UNREACH_FILTER -# define ICMP_UNREACH_FILTER 13 -#endif - -#ifndef IPF_LOGGING -# define IPF_LOGGING 0 -#endif -#ifndef IPF_DEFAULT_PASS -# define IPF_DEFAULT_PASS FR_PASS -#endif - -#define IPMINLEN(i, h) ((i)->ip_len >= ((i)->ip_hl * 4 + sizeof(struct h))) -#define IPLLOGSIZE 8192 - -/* - * Device filenames for reading log information. Use ipf on Solaris2 because - * ipl is already a name used by something else. - */ -#ifndef IPL_NAME -# if SOLARIS -# define IPL_NAME "/dev/ipf" -# else -# define IPL_NAME "/dev/ipl" -# endif -#endif -#define IPL_NAT IPNAT_NAME -#define IPL_STATE IPSTATE_NAME -#define IPL_AUTH IPAUTH_NAME - -#define IPL_LOGIPF 0 /* Minor device #'s for accessing logs */ -#define IPL_LOGNAT 1 -#define IPL_LOGSTATE 2 -#define IPL_LOGAUTH 3 -#define IPL_LOGMAX 3 - -#if !defined(CDEV_MAJOR) && defined (__FreeBSD_version) && \ - (__FreeBSD_version >= 220000) -# define CDEV_MAJOR 79 -#endif - -/* - * Post NetBSD 1.2 has the PFIL interface for packet filters. This turns - * on those hooks. We don't need any special mods in non-IP Filter code - * with this! - */ -#if (defined(NetBSD) && (NetBSD > 199609) && (NetBSD <= 1991011)) || \ - (defined(NetBSD1_2) && NetBSD1_2 > 1) -# if (NetBSD >= 199905) -# define PFIL_HOOKS -# endif -# ifdef PFIL_HOOKS -# define NETBSD_PF -# endif -#endif - - -#ifndef _KERNEL -extern int fr_check __P((ip_t *, int, void *, int, mb_t **)); -extern int (*fr_checkp) __P((ip_t *, int, void *, int, mb_t **)); -extern int send_reset __P((ip_t *, struct ifnet *)); -extern int icmp_error __P((ip_t *, struct ifnet *)); -extern int ipf_log __P((void)); -extern int ipfr_fastroute __P((ip_t *, fr_info_t *, frdest_t *)); -extern struct ifnet *get_unit __P((char *, int)); -# if defined(__NetBSD__) || defined(__OpenBSD__) || \ - (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) -extern int iplioctl __P((dev_t, u_long, caddr_t, int)); -# else -extern int iplioctl __P((dev_t, int, caddr_t, int)); -# endif -extern int iplopen __P((dev_t, int)); -extern int iplclose __P((dev_t, int)); -#else /* #ifndef _KERNEL */ -# if defined(__NetBSD__) && defined(PFIL_HOOKS) -extern void ipfilterattach __P((int)); -# endif -extern int iplattach __P((void)); -extern int ipl_enable __P((void)); -extern int ipl_disable __P((void)); -extern void ipflog_init __P((void)); -extern int ipflog_clear __P((minor_t)); -extern int ipflog_read __P((minor_t, struct uio *)); -extern int ipflog __P((u_int, ip_t *, fr_info_t *, mb_t *)); -extern int ipllog __P((int, fr_info_t *, void **, size_t *, int *, int)); -extern int send_icmp_err __P((ip_t *, int, fr_info_t *, int)); -extern int send_reset __P((ip_t *, fr_info_t *)); -# if SOLARIS -extern int fr_check __P((ip_t *, int, void *, int, qif_t *, mb_t **)); -extern int (*fr_checkp) __P((ip_t *, int, void *, - int, qif_t *, mb_t **)); -# if SOLARIS2 >= 7 -extern int iplioctl __P((dev_t, int, intptr_t, int, cred_t *, int *)); -# else -extern int iplioctl __P((dev_t, int, int *, int, cred_t *, int *)); -# endif -extern int iplopen __P((dev_t *, int, int, cred_t *)); -extern int iplclose __P((dev_t, int, int, cred_t *)); -extern int ipfsync __P((void)); -extern int ipfr_fastroute __P((ip_t *, mblk_t *, mblk_t **, - fr_info_t *, frdest_t *)); -extern void copyin_mblk __P((mblk_t *, size_t, size_t, char *)); -extern void copyout_mblk __P((mblk_t *, size_t, size_t, char *)); -extern int fr_qin __P((queue_t *, mblk_t *)); -extern int fr_qout __P((queue_t *, mblk_t *)); -extern int iplread __P((dev_t, struct uio *, cred_t *)); -# else /* SOLARIS */ -extern int fr_check __P((ip_t *, int, void *, int, mb_t **)); -extern int (*fr_checkp) __P((ip_t *, int, void *, int, mb_t **)); -extern int ipfr_fastroute __P((mb_t *, fr_info_t *, frdest_t *)); -extern size_t mbufchainlen __P((mb_t *)); -# ifdef __sgi -# include <sys/cred.h> -extern int iplioctl __P((dev_t, int, caddr_t, int, cred_t *, int *)); -extern int iplopen __P((dev_t *, int, int, cred_t *)); -extern int iplclose __P((dev_t, int, int, cred_t *)); -extern int iplread __P((dev_t, struct uio *, cred_t *)); -extern int ipfsync __P((void)); -extern int ipfilter_sgi_attach __P((void)); -extern void ipfilter_sgi_detach __P((void)); -extern void ipfilter_sgi_intfsync __P((void)); -# else -# ifdef IPFILTER_LKM -extern int iplidentify __P((char *)); -# endif -# if (_BSDI_VERSION >= 199510) || (__FreeBSD_version >= 220000) || \ - (NetBSD >= 199511) || defined(__OpenBSD__) -# if defined(__NetBSD__) || (_BSDI_VERSION >= 199701) || \ - defined(__OpenBSD__) || (__FreeBSD_version >= 300000) -extern int iplioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); -# else -extern int iplioctl __P((dev_t, int, caddr_t, int, struct proc *)); -# endif -extern int iplopen __P((dev_t, int, int, struct proc *)); -extern int iplclose __P((dev_t, int, int, struct proc *)); -# else -# ifndef linux -extern int iplopen __P((dev_t, int)); -extern int iplclose __P((dev_t, int)); -extern int iplioctl __P((dev_t, int, caddr_t, int)); -# else -extern int iplioctl(struct inode *, struct file *, u_int, u_long); -extern int iplopen __P((struct inode *, struct file *)); -extern void iplclose __P((struct inode *, struct file *)); -# endif /* !linux */ -# endif /* (_BSDI_VERSION >= 199510) */ -# if BSD >= 199306 -extern int iplread __P((dev_t, struct uio *, int)); -# else -# ifndef linux -extern int iplread __P((dev_t, struct uio *)); -# else -extern int iplread(struct inode *, struct file *, char *, int); -# endif /* !linux */ -# endif /* BSD >= 199306 */ -# endif /* __ sgi */ -# endif /* SOLARIS */ -#endif /* #ifndef _KERNEL */ - -extern char *memstr __P((char *, char *, int, int)); -extern void fixskip __P((frentry_t **, frentry_t *, int)); -extern int countbits __P((u_32_t)); -extern int ipldetach __P((void)); -extern u_short ipf_cksum __P((u_short *, int)); -extern int ircopyptr __P((void *, void *, size_t)); -extern int iwcopyptr __P((void *, void *, size_t)); - -extern int frflush __P((minor_t, int)); -extern void frsync __P((void)); -extern frgroup_t *fr_addgroup __P((u_32_t, frentry_t *, minor_t, int)); -extern void fr_delgroup __P((u_32_t, u_32_t, minor_t, int)); -extern frgroup_t *fr_findgroup __P((u_32_t, u_32_t, minor_t, int, - frgroup_t ***)); - -extern int fr_copytolog __P((int, char *, int)); -extern void fr_forgetifp __P((void *)); -extern void fr_getstat __P((struct friostat *)); -extern int fr_ifpaddr __P((int, void *, struct in_addr *)); -extern int fr_lock __P((caddr_t, int *)); -extern void fr_makefrip __P((int, ip_t *, fr_info_t *)); -extern u_short fr_tcpsum __P((mb_t *, ip_t *, tcphdr_t *)); -extern int fr_scanlist __P((u_32_t, ip_t *, fr_info_t *, void *)); -extern int fr_tcpudpchk __P((frtuc_t *, fr_info_t *)); -extern int fr_verifysrc __P((struct in_addr, void *)); - -extern int ipl_unreach; -extern int fr_running; -extern u_long ipl_frouteok[2]; -extern int fr_pass; -extern int fr_flags; -extern int fr_active; -extern int fr_chksrc; -extern int fr_minttl; -extern int fr_minttllog; -extern fr_info_t frcache[2]; -extern char ipfilter_version[]; -extern iplog_t **iplh[IPL_LOGMAX+1], *iplt[IPL_LOGMAX+1]; -extern size_t iplused[IPL_LOGMAX + 1]; -extern struct frentry *ipfilter[2][2], *ipacct[2][2]; -#ifdef USE_INET6 -extern struct frentry *ipfilter6[2][2], *ipacct6[2][2]; -extern int icmptoicmp6types[ICMP_MAXTYPE+1]; -extern int icmptoicmp6unreach[ICMP_MAX_UNREACH]; -#endif -extern struct frgroup *ipfgroups[3][2]; -extern struct filterstats frstats[]; - -#endif /* __IP_FIL_H__ */ diff --git a/contrib/ipfilter/ip_frag.c b/contrib/ipfilter/ip_frag.c deleted file mode 100644 index 556478d..0000000 --- a/contrib/ipfilter/ip_frag.c +++ /dev/null @@ -1,555 +0,0 @@ -/* - * Copyright (C) 1993-2000 by Darren Reed. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - */ -#if !defined(lint) -static const char sccsid[] = "@(#)ip_frag.c 1.11 3/24/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_frag.c,v 2.10.2.7 2000/11/27 10:26:56 darrenr Exp $"; -#endif - -#if defined(KERNEL) && !defined(_KERNEL) -# define _KERNEL -#endif - -#include <sys/errno.h> -#include <sys/types.h> -#include <sys/param.h> -#include <sys/time.h> -#include <sys/file.h> -#if !defined(_KERNEL) && !defined(KERNEL) -# include <stdio.h> -# include <string.h> -# include <stdlib.h> -#endif -#if (defined(KERNEL) || defined(_KERNEL)) && (__FreeBSD_version >= 220000) -# include <sys/filio.h> -# include <sys/fcntl.h> -#else -# include <sys/ioctl.h> -#endif -#include <sys/uio.h> -#ifndef linux -# include <sys/protosw.h> -#endif -#include <sys/socket.h> -#if defined(_KERNEL) && !defined(linux) -# include <sys/systm.h> -#endif -#if !defined(__SVR4) && !defined(__svr4__) -# if defined(_KERNEL) && !defined(__sgi) -# include <sys/kernel.h> -# endif -# ifndef linux -# include <sys/mbuf.h> -# endif -#else -# include <sys/byteorder.h> -# ifdef _KERNEL -# include <sys/dditypes.h> -# endif -# include <sys/stream.h> -# include <sys/kmem.h> -#endif -#include <net/if.h> -#ifdef sun -# include <net/af.h> -#endif -#include <net/route.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#ifndef linux -# include <netinet/ip_var.h> -#endif -#include <netinet/tcp.h> -#include <netinet/udp.h> -#include <netinet/ip_icmp.h> -#include "netinet/ip_compat.h" -#include <netinet/tcpip.h> -#include "netinet/ip_fil.h" -#include "netinet/ip_proxy.h" -#include "netinet/ip_nat.h" -#include "netinet/ip_frag.h" -#include "netinet/ip_state.h" -#include "netinet/ip_auth.h" -#if (__FreeBSD_version >= 300000) -# include <sys/malloc.h> -# if (defined(KERNEL) || defined(_KERNEL)) -# ifndef IPFILTER_LKM -# include <sys/libkern.h> -# include <sys/systm.h> -# endif -extern struct callout_handle ipfr_slowtimer_ch; -# endif -#endif -#if defined(__NetBSD__) && (__NetBSD_Version__ >= 104230000) -# include <sys/callout.h> -extern struct callout ipfr_slowtimer_ch; -#endif - - -static ipfr_t *ipfr_heads[IPFT_SIZE]; -static ipfr_t *ipfr_nattab[IPFT_SIZE]; -static ipfrstat_t ipfr_stats; -static int ipfr_inuse = 0; - -int fr_ipfrttl = 120; /* 60 seconds */ -int fr_frag_lock = 0; - -#ifdef _KERNEL -# if SOLARIS2 >= 7 -extern timeout_id_t ipfr_timer_id; -# else -extern int ipfr_timer_id; -# endif -#endif -#if (SOLARIS || defined(__sgi)) && defined(_KERNEL) -extern KRWLOCK_T ipf_frag, ipf_natfrag, ipf_nat, ipf_mutex; -# if SOLARIS -extern KRWLOCK_T ipf_solaris; -# else -KRWLOCK_T ipf_solaris; -# endif -extern kmutex_t ipf_rw; -#endif - - -static ipfr_t *ipfr_new __P((ip_t *, fr_info_t *, u_int, ipfr_t **)); -static ipfr_t *ipfr_lookup __P((ip_t *, fr_info_t *, ipfr_t **)); -static void ipfr_delete __P((ipfr_t *)); - - -ipfrstat_t *ipfr_fragstats() -{ - ipfr_stats.ifs_table = ipfr_heads; - ipfr_stats.ifs_nattab = ipfr_nattab; - ipfr_stats.ifs_inuse = ipfr_inuse; - return &ipfr_stats; -} - - -/* - * add a new entry to the fragment cache, registering it as having come - * through this box, with the result of the filter operation. - */ -static ipfr_t *ipfr_new(ip, fin, pass, table) -ip_t *ip; -fr_info_t *fin; -u_int pass; -ipfr_t *table[]; -{ - ipfr_t **fp, *fra, frag; - u_int idx; - - if (ipfr_inuse >= IPFT_SIZE) - return NULL; - - frag.ipfr_p = ip->ip_p; - idx = ip->ip_p; - frag.ipfr_id = ip->ip_id; - idx += ip->ip_id; - frag.ipfr_tos = ip->ip_tos; - frag.ipfr_src.s_addr = ip->ip_src.s_addr; - idx += ip->ip_src.s_addr; - frag.ipfr_dst.s_addr = ip->ip_dst.s_addr; - idx += ip->ip_dst.s_addr; - frag.ipfr_ifp = fin->fin_ifp; - idx *= 127; - idx %= IPFT_SIZE; - - /* - * first, make sure it isn't already there... - */ - for (fp = &table[idx]; (fra = *fp); fp = &fra->ipfr_next) - if (!bcmp((char *)&frag.ipfr_src, (char *)&fra->ipfr_src, - IPFR_CMPSZ)) { - ATOMIC_INCL(ipfr_stats.ifs_exists); - return NULL; - } - - /* - * allocate some memory, if possible, if not, just record that we - * failed to do so. - */ - KMALLOC(fra, ipfr_t *); - if (fra == NULL) { - ATOMIC_INCL(ipfr_stats.ifs_nomem); - return NULL; - } - - if ((fra->ipfr_rule = fin->fin_fr) != NULL) { - ATOMIC_INC32(fin->fin_fr->fr_ref); - } - - - /* - * Instert the fragment into the fragment table, copy the struct used - * in the search using bcopy rather than reassign each field. - * Set the ttl to the default and mask out logging from "pass" - */ - if ((fra->ipfr_next = table[idx])) - table[idx]->ipfr_prev = fra; - fra->ipfr_prev = NULL; - fra->ipfr_data = NULL; - table[idx] = fra; - bcopy((char *)&frag.ipfr_src, (char *)&fra->ipfr_src, IPFR_CMPSZ); - fra->ipfr_ttl = fr_ipfrttl; - /* - * Compute the offset of the expected start of the next packet. - */ - fra->ipfr_off = (ip->ip_off & IP_OFFMASK) + (fin->fin_dlen >> 3); - ATOMIC_INCL(ipfr_stats.ifs_new); - ATOMIC_INC32(ipfr_inuse); - return fra; -} - - -int ipfr_newfrag(ip, fin, pass) -ip_t *ip; -fr_info_t *fin; -u_int pass; -{ - ipfr_t *ipf; - - if ((ip->ip_v != 4) || (fr_frag_lock)) - return -1; - WRITE_ENTER(&ipf_frag); - ipf = ipfr_new(ip, fin, pass, ipfr_heads); - RWLOCK_EXIT(&ipf_frag); - return ipf ? 0 : -1; -} - - -int ipfr_nat_newfrag(ip, fin, pass, nat) -ip_t *ip; -fr_info_t *fin; -u_int pass; -nat_t *nat; -{ - ipfr_t *ipf; - - if ((ip->ip_v != 4) || (fr_frag_lock)) - return -1; - WRITE_ENTER(&ipf_natfrag); - ipf = ipfr_new(ip, fin, pass, ipfr_nattab); - if (ipf != NULL) { - ipf->ipfr_data = nat; - nat->nat_data = ipf; - } - RWLOCK_EXIT(&ipf_natfrag); - return ipf ? 0 : -1; -} - - -/* - * check the fragment cache to see if there is already a record of this packet - * with its filter result known. - */ -static ipfr_t *ipfr_lookup(ip, fin, table) -ip_t *ip; -fr_info_t *fin; -ipfr_t *table[]; -{ - ipfr_t *f, frag; - u_int idx; - - /* - * For fragments, we record protocol, packet id, TOS and both IP#'s - * (these should all be the same for all fragments of a packet). - * - * build up a hash value to index the table with. - */ - frag.ipfr_p = ip->ip_p; - idx = ip->ip_p; - frag.ipfr_id = ip->ip_id; - idx += ip->ip_id; - frag.ipfr_tos = ip->ip_tos; - frag.ipfr_src.s_addr = ip->ip_src.s_addr; - idx += ip->ip_src.s_addr; - frag.ipfr_dst.s_addr = ip->ip_dst.s_addr; - idx += ip->ip_dst.s_addr; - frag.ipfr_ifp = fin->fin_ifp; - idx *= 127; - idx %= IPFT_SIZE; - - /* - * check the table, careful to only compare the right amount of data - */ - for (f = table[idx]; f; f = f->ipfr_next) - if (!bcmp((char *)&frag.ipfr_src, (char *)&f->ipfr_src, - IPFR_CMPSZ)) { - u_short atoff, off; - - if (f != table[idx]) { - /* - * move fragment info. to the top of the list - * to speed up searches. - */ - if ((f->ipfr_prev->ipfr_next = f->ipfr_next)) - f->ipfr_next->ipfr_prev = f->ipfr_prev; - f->ipfr_next = table[idx]; - table[idx]->ipfr_prev = f; - f->ipfr_prev = NULL; - table[idx] = f; - } - off = ip->ip_off & IP_OFFMASK; - atoff = off + (fin->fin_dlen >> 3); - /* - * If we've follwed the fragments, and this is the - * last (in order), shrink expiration time. - */ - if (off == f->ipfr_off) { - if (!(ip->ip_off & IP_MF)) - f->ipfr_ttl = 1; - else - f->ipfr_off = atoff; - } - ATOMIC_INCL(ipfr_stats.ifs_hits); - return f; - } - return NULL; -} - - -/* - * functional interface for NAT lookups of the NAT fragment cache - */ -nat_t *ipfr_nat_knownfrag(ip, fin) -ip_t *ip; -fr_info_t *fin; -{ - nat_t *nat; - ipfr_t *ipf; - - if ((ip->ip_v != 4) || (fr_frag_lock)) - return NULL; - READ_ENTER(&ipf_natfrag); - ipf = ipfr_lookup(ip, fin, ipfr_nattab); - if (ipf != NULL) { - nat = ipf->ipfr_data; - /* - * This is the last fragment for this packet. - */ - if ((ipf->ipfr_ttl == 1) && (nat != NULL)) { - nat->nat_data = NULL; - ipf->ipfr_data = NULL; - } - } else - nat = NULL; - RWLOCK_EXIT(&ipf_natfrag); - return nat; -} - - -/* - * functional interface for normal lookups of the fragment cache - */ -frentry_t *ipfr_knownfrag(ip, fin) -ip_t *ip; -fr_info_t *fin; -{ - frentry_t *fr = NULL; - ipfr_t *fra; - - if ((ip->ip_v != 4) || (fr_frag_lock)) - return NULL; - READ_ENTER(&ipf_frag); - fra = ipfr_lookup(ip, fin, ipfr_heads); - if (fra != NULL) - fr = fra->ipfr_rule; - RWLOCK_EXIT(&ipf_frag); - return fr; -} - - -/* - * forget any references to this external object. - */ -void ipfr_forget(nat) -void *nat; -{ - ipfr_t *fr; - int idx; - - WRITE_ENTER(&ipf_natfrag); - for (idx = IPFT_SIZE - 1; idx >= 0; idx--) - for (fr = ipfr_heads[idx]; fr; fr = fr->ipfr_next) - if (fr->ipfr_data == nat) - fr->ipfr_data = NULL; - - RWLOCK_EXIT(&ipf_natfrag); -} - - -static void ipfr_delete(fra) -ipfr_t *fra; -{ - frentry_t *fr; - - fr = fra->ipfr_rule; - if (fr != NULL) { - ATOMIC_DEC32(fr->fr_ref); - if (fr->fr_ref == 0) - KFREE(fr); - } - if (fra->ipfr_prev) - fra->ipfr_prev->ipfr_next = fra->ipfr_next; - if (fra->ipfr_next) - fra->ipfr_next->ipfr_prev = fra->ipfr_prev; - KFREE(fra); -} - - -/* - * Free memory in use by fragment state info. kept. - */ -void ipfr_unload() -{ - ipfr_t **fp, *fra; - nat_t *nat; - int idx; - - WRITE_ENTER(&ipf_frag); - for (idx = IPFT_SIZE - 1; idx >= 0; idx--) - for (fp = &ipfr_heads[idx]; (fra = *fp); ) { - *fp = fra->ipfr_next; - ipfr_delete(fra); - } - RWLOCK_EXIT(&ipf_frag); - - WRITE_ENTER(&ipf_nat); - WRITE_ENTER(&ipf_natfrag); - for (idx = IPFT_SIZE - 1; idx >= 0; idx--) - for (fp = &ipfr_nattab[idx]; (fra = *fp); ) { - *fp = fra->ipfr_next; - nat = fra->ipfr_data; - if (nat != NULL) { - if (nat->nat_data == fra) - nat->nat_data = NULL; - } - ipfr_delete(fra); - } - RWLOCK_EXIT(&ipf_natfrag); - RWLOCK_EXIT(&ipf_nat); -} - - -#ifdef _KERNEL -void ipfr_fragexpire() -{ - ipfr_t **fp, *fra; - nat_t *nat; - int idx; -#if defined(_KERNEL) -# if !SOLARIS - int s; -# endif -#endif - - if (fr_frag_lock) - return; - - SPL_NET(s); - WRITE_ENTER(&ipf_frag); - - /* - * Go through the entire table, looking for entries to expire, - * decreasing the ttl by one for each entry. If it reaches 0, - * remove it from the chain and free it. - */ - for (idx = IPFT_SIZE - 1; idx >= 0; idx--) - for (fp = &ipfr_heads[idx]; (fra = *fp); ) { - --fra->ipfr_ttl; - if (fra->ipfr_ttl == 0) { - *fp = fra->ipfr_next; - ipfr_delete(fra); - ATOMIC_INCL(ipfr_stats.ifs_expire); - ATOMIC_DEC32(ipfr_inuse); - } else - fp = &fra->ipfr_next; - } - RWLOCK_EXIT(&ipf_frag); - - /* - * Same again for the NAT table, except that if the structure also - * still points to a NAT structure, and the NAT structure points back - * at the one to be free'd, NULL the reference from the NAT struct. - * NOTE: We need to grab both mutex's early, and in this order so as - * to prevent a deadlock if both try to expire at the same time. - */ - WRITE_ENTER(&ipf_nat); - WRITE_ENTER(&ipf_natfrag); - for (idx = IPFT_SIZE - 1; idx >= 0; idx--) - for (fp = &ipfr_nattab[idx]; (fra = *fp); ) { - --fra->ipfr_ttl; - if (fra->ipfr_ttl == 0) { - ATOMIC_INCL(ipfr_stats.ifs_expire); - ATOMIC_DEC32(ipfr_inuse); - nat = fra->ipfr_data; - if (nat != NULL) { - if (nat->nat_data == fra) - nat->nat_data = NULL; - } - *fp = fra->ipfr_next; - ipfr_delete(fra); - } else - fp = &fra->ipfr_next; - } - RWLOCK_EXIT(&ipf_natfrag); - RWLOCK_EXIT(&ipf_nat); - SPL_X(s); -} - - -/* - * Slowly expire held state for fragments. Timeouts are set * in expectation - * of this being called twice per second. - */ -# if (BSD >= 199306) || SOLARIS || defined(__sgi) -# if defined(SOLARIS2) && (SOLARIS2 < 7) -void ipfr_slowtimer() -# else -void ipfr_slowtimer __P((void *ptr)) -# endif -# else -int ipfr_slowtimer() -# endif -{ -#if defined(_KERNEL) && SOLARIS - extern int fr_running; - - if (fr_running <= 0) - return; -#endif - - READ_ENTER(&ipf_solaris); -#ifdef __sgi - ipfilter_sgi_intfsync(); -#endif - - ipfr_fragexpire(); - fr_timeoutstate(); - ip_natexpire(); - fr_authexpire(); -# if SOLARIS - ipfr_timer_id = timeout(ipfr_slowtimer, NULL, drv_usectohz(500000)); - RWLOCK_EXIT(&ipf_solaris); -# else -# if defined(__NetBSD__) && (__NetBSD_Version__ >= 104240000) - callout_reset(&ipfr_slowtimer_ch, hz / 2, ipfr_slowtimer, NULL); -# else -# if (__FreeBSD_version >= 300000) - ipfr_slowtimer_ch = timeout(ipfr_slowtimer, NULL, hz/2); -# else - timeout(ipfr_slowtimer, NULL, hz/2); -# endif -# if (BSD < 199306) && !defined(__sgi) - return 0; -# endif /* FreeBSD */ -# endif /* NetBSD */ -# endif /* SOLARIS */ -} -#endif /* defined(_KERNEL) */ diff --git a/contrib/ipfilter/ip_frag.h b/contrib/ipfilter/ip_frag.h deleted file mode 100644 index 362bcdd..0000000 --- a/contrib/ipfilter/ip_frag.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 1993-2000 by Darren Reed. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - * - * @(#)ip_frag.h 1.5 3/24/96 - * $Id: ip_frag.h,v 2.4.2.2 2000/11/10 13:10:54 darrenr Exp $ - */ - -#ifndef __IP_FRAG_H__ -#define __IP_FRAG_H__ - -#define IPFT_SIZE 257 - -typedef struct ipfr { - struct ipfr *ipfr_next, *ipfr_prev; - void *ipfr_data; - struct in_addr ipfr_src; - struct in_addr ipfr_dst; - void *ipfr_ifp; - u_short ipfr_id; - u_char ipfr_p; - u_char ipfr_tos; - u_short ipfr_off; - u_short ipfr_ttl; - frentry_t *ipfr_rule; -} ipfr_t; - - -typedef struct ipfrstat { - u_long ifs_exists; /* add & already exists */ - u_long ifs_nomem; - u_long ifs_new; - u_long ifs_hits; - u_long ifs_expire; - u_long ifs_inuse; - struct ipfr **ifs_table; - struct ipfr **ifs_nattab; -} ipfrstat_t; - -#define IPFR_CMPSZ (4 + 4 + 2 + 1 + 1) - -extern int fr_ipfrttl; -extern int fr_frag_lock; -extern ipfrstat_t *ipfr_fragstats __P((void)); -extern int ipfr_newfrag __P((ip_t *, fr_info_t *, u_int)); -extern int ipfr_nat_newfrag __P((ip_t *, fr_info_t *, u_int, struct nat *)); -extern nat_t *ipfr_nat_knownfrag __P((ip_t *, fr_info_t *)); -extern frentry_t *ipfr_knownfrag __P((ip_t *, fr_info_t *)); -extern void ipfr_forget __P((void *)); -extern void ipfr_unload __P((void)); -extern void ipfr_fragexpire __P((void)); - -#if (BSD >= 199306) || SOLARIS || defined(__sgi) -# if defined(SOLARIS2) && (SOLARIS2 < 7) -extern void ipfr_slowtimer __P((void)); -# else -extern void ipfr_slowtimer __P((void *)); -# endif -#else -extern int ipfr_slowtimer __P((void)); -#endif /* (BSD >= 199306) || SOLARIS */ - -#endif /* __IP_FIL_H__ */ diff --git a/contrib/ipfilter/ip_ftp_pxy.c b/contrib/ipfilter/ip_ftp_pxy.c deleted file mode 100644 index ddca889..0000000 --- a/contrib/ipfilter/ip_ftp_pxy.c +++ /dev/null @@ -1,786 +0,0 @@ -/* - * Simple FTP transparent proxy for in-kernel use. For use with the NAT - * code. - * - * $Id: ip_ftp_pxy.c,v 2.7.2.20 2000/12/02 00:15:06 darrenr Exp $ - */ -#if SOLARIS && defined(_KERNEL) -extern kmutex_t ipf_rw; -#endif - -#define isdigit(x) ((x) >= '0' && (x) <= '9') -#define isupper(x) (((unsigned)(x) >= 'A') && ((unsigned)(x) <= 'Z')) -#define islower(x) (((unsigned)(x) >= 'a') && ((unsigned)(x) <= 'z')) -#define isalpha(x) (isupper(x) || islower(x)) -#define toupper(x) (isupper(x) ? (x) : (x) - 'a' + 'A') - -#define IPF_FTP_PROXY - -#define IPF_MINPORTLEN 18 -#define IPF_MAXPORTLEN 30 -#define IPF_MIN227LEN 39 -#define IPF_MAX227LEN 51 -#define IPF_FTPBUFSZ 96 /* This *MUST* be >= 53! */ - - -int ippr_ftp_client __P((fr_info_t *, ip_t *, nat_t *, ftpinfo_t *, int)); -int ippr_ftp_complete __P((char *, size_t)); -int ippr_ftp_in __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *)); -int ippr_ftp_init __P((void)); -int ippr_ftp_new __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *)); -int ippr_ftp_out __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *)); -int ippr_ftp_pasv __P((fr_info_t *, ip_t *, nat_t *, ftpside_t *, int)); -int ippr_ftp_port __P((fr_info_t *, ip_t *, nat_t *, ftpside_t *, int)); -int ippr_ftp_process __P((fr_info_t *, ip_t *, nat_t *, ftpinfo_t *, int)); -int ippr_ftp_server __P((fr_info_t *, ip_t *, nat_t *, ftpinfo_t *, int)); -int ippr_ftp_valid __P((char *, size_t)); -u_short ippr_ftp_atoi __P((char **)); - -static frentry_t natfr; -int ippr_ftp_pasvonly = 0; -int ippr_ftp_insecure = 0; - - -/* - * Initialize local structures. - */ -int ippr_ftp_init() -{ - bzero((char *)&natfr, sizeof(natfr)); - natfr.fr_ref = 1; - natfr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE; - return 0; -} - - -int ippr_ftp_new(fin, ip, aps, nat) -fr_info_t *fin; -ip_t *ip; -ap_session_t *aps; -nat_t *nat; -{ - ftpinfo_t *ftp; - ftpside_t *f; - - KMALLOC(ftp, ftpinfo_t *); - if (ftp == NULL) - return -1; - aps->aps_data = ftp; - aps->aps_psiz = sizeof(ftpinfo_t); - - bzero((char *)ftp, sizeof(*ftp)); - f = &ftp->ftp_side[0]; - f->ftps_rptr = f->ftps_buf; - f->ftps_wptr = f->ftps_buf; - f = &ftp->ftp_side[1]; - f->ftps_rptr = f->ftps_buf; - f->ftps_wptr = f->ftps_buf; - return 0; -} - - -int ippr_ftp_port(fin, ip, nat, f, dlen) -fr_info_t *fin; -ip_t *ip; -nat_t *nat; -ftpside_t *f; -int dlen; -{ - tcphdr_t *tcp, tcph, *tcp2 = &tcph; - char newbuf[IPF_FTPBUFSZ], *s; - u_short a5, a6, sp, dp; - u_int a1, a2, a3, a4; - struct in_addr swip; - size_t nlen, olen; - fr_info_t fi; - int inc, off; - nat_t *ipn; - mb_t *m; -#if SOLARIS - mb_t *m1; -#endif - - tcp = (tcphdr_t *)fin->fin_dp; - /* - * Check for client sending out PORT message. - */ - if (dlen < IPF_MINPORTLEN) - return 0; - off = fin->fin_hlen + (tcp->th_off << 2); - /* - * Skip the PORT command + space - */ - s = f->ftps_rptr + 5; - /* - * Pick out the address components, two at a time. - */ - a1 = ippr_ftp_atoi(&s); - if (!s) - return 0; - a2 = ippr_ftp_atoi(&s); - if (!s) - return 0; - /* - * check that IP address in the PORT/PASV reply is the same as the - * sender of the command - prevents using PORT for port scanning. - */ - a1 <<= 16; - a1 |= a2; - if (a1 != ntohl(nat->nat_inip.s_addr)) - return 0; - - a5 = ippr_ftp_atoi(&s); - if (!s) - return 0; - if (*s == ')') - s++; - - /* - * check for CR-LF at the end. - */ - if (*s == '\n') - s--; - if ((*s == '\r') && (*(s + 1) == '\n')) { - s += 2; - a6 = a5 & 0xff; - } else - return 0; - a5 >>= 8; - a5 &= 0xff; - /* - * Calculate new address parts for PORT command - */ - a1 = ntohl(ip->ip_src.s_addr); - a2 = (a1 >> 16) & 0xff; - a3 = (a1 >> 8) & 0xff; - a4 = a1 & 0xff; - a1 >>= 24; - olen = s - f->ftps_rptr; - /* DO NOT change this to sprintf! */ - (void) sprintf(newbuf, "%s %u,%u,%u,%u,%u,%u\r\n", - "PORT", a1, a2, a3, a4, a5, a6); - - nlen = strlen(newbuf); - inc = nlen - olen; - if ((inc + ip->ip_len) > 65535) - return 0; - -#if SOLARIS - m = fin->fin_qfm; - for (m1 = m; m1->b_cont; m1 = m1->b_cont) - ; - if ((inc > 0) && (m1->b_datap->db_lim - m1->b_wptr < inc)) { - mblk_t *nm; - - /* alloc enough to keep same trailer space for lower driver */ - nm = allocb(nlen, BPRI_MED); - PANIC((!nm),("ippr_ftp_out: allocb failed")); - - nm->b_band = m1->b_band; - nm->b_wptr += nlen; - - m1->b_wptr -= olen; - PANIC((m1->b_wptr < m1->b_rptr), - ("ippr_ftp_out: cannot handle fragmented data block")); - - linkb(m1, nm); - } else { - if (m1->b_datap->db_struiolim == m1->b_wptr) - m1->b_datap->db_struiolim += inc; - m1->b_datap->db_struioflag &= ~STRUIO_IP; - m1->b_wptr += inc; - } - copyin_mblk(m, off, nlen, newbuf); -#else - m = *((mb_t **)fin->fin_mp); - if (inc < 0) - m_adj(m, inc); - /* the mbuf chain will be extended if necessary by m_copyback() */ - m_copyback(m, off, nlen, newbuf); -# ifdef M_PKTHDR - if (!(m->m_flags & M_PKTHDR)) - m->m_pkthdr.len += inc; -# endif -#endif - if (inc != 0) { -#if SOLARIS || defined(__sgi) - register u_32_t sum1, sum2; - - sum1 = ip->ip_len; - sum2 = ip->ip_len + inc; - - /* Because ~1 == -2, We really need ~1 == -1 */ - if (sum1 > sum2) - sum2--; - sum2 -= sum1; - sum2 = (sum2 & 0xffff) + (sum2 >> 16); - - fix_outcksum(&ip->ip_sum, sum2); -#endif - ip->ip_len += inc; - } - - /* - * Add skeleton NAT entry for connection which will come back the - * other way. - */ - sp = htons(a5 << 8 | a6); - /* - * Don't allow the PORT command to specify a port < 1024 due to - * security crap. - */ - if (ntohs(sp) < 1024) - return 0; - /* - * The server may not make the connection back from port 20, but - * it is the most likely so use it here to check for a conflicting - * mapping. - */ - dp = htons(fin->fin_data[1] - 1); - ipn = nat_outlookup(fin->fin_ifp, IPN_TCP, nat->nat_p, nat->nat_inip, - ip->ip_dst, (dp << 16) | sp, 0); - if (ipn == NULL) { - int slen; - - slen = ip->ip_len; - ip->ip_len = fin->fin_hlen + sizeof(*tcp2); - bcopy((char *)fin, (char *)&fi, sizeof(fi)); - bzero((char *)tcp2, sizeof(*tcp2)); - tcp2->th_win = htons(8192); - tcp2->th_sport = sp; - tcp2->th_off = 5; - tcp2->th_dport = 0; /* XXX - don't specify remote port */ - fi.fin_data[0] = ntohs(sp); - fi.fin_data[1] = 0; - fi.fin_dlen = sizeof(*tcp2); - fi.fin_dp = (char *)tcp2; - fi.fin_fr = &natfr; - swip = ip->ip_src; - fi.fin_fi.fi_saddr = nat->nat_inip.s_addr; - ip->ip_src = nat->nat_inip; - ipn = nat_new(nat->nat_ptr, ip, &fi, IPN_TCP|FI_W_DPORT, - NAT_OUTBOUND); - if (ipn != NULL) { - ipn->nat_age = fr_defnatage; - (void) fr_addstate(ip, &fi, FI_W_DPORT); - } - ip->ip_len = slen; - ip->ip_src = swip; - } - return APR_INC(inc); -} - - -int ippr_ftp_client(fin, ip, nat, ftp, dlen) -fr_info_t *fin; -nat_t *nat; -ftpinfo_t *ftp; -ip_t *ip; -int dlen; -{ - char *rptr, *wptr, cmd[6], c; - ftpside_t *f; - int inc, i; - - inc = 0; - f = &ftp->ftp_side[0]; - rptr = f->ftps_rptr; - wptr = f->ftps_wptr; - - for (i = 0; (i < 5) && (i < dlen); i++) { - c = rptr[i]; - if (isalpha(c)) { - cmd[i] = toupper(c); - } else { - cmd[i] = c; - } - } - cmd[i] = '\0'; - - if ((ftp->ftp_passok == 0) && !strncmp(cmd, "USER ", 5)) - ftp->ftp_passok = 1; - else if ((ftp->ftp_passok == 2) && !strncmp(cmd, "PASS ", 5)) - ftp->ftp_passok = 3; - else if ((ftp->ftp_passok == 4) && !ippr_ftp_pasvonly && - !strncmp(cmd, "PORT ", 5)) { - inc = ippr_ftp_port(fin, ip, nat, f, dlen); - } else if (ippr_ftp_insecure && !ippr_ftp_pasvonly && - !strncmp(cmd, "PORT ", 5)) { - inc = ippr_ftp_port(fin, ip, nat, f, dlen); - } - - while ((*rptr++ != '\n') && (rptr < wptr)) - ; - f->ftps_rptr = rptr; - return inc; -} - - -int ippr_ftp_pasv(fin, ip, nat, f, dlen) -fr_info_t *fin; -ip_t *ip; -nat_t *nat; -ftpside_t *f; -int dlen; -{ - tcphdr_t *tcp, tcph, *tcp2 = &tcph; - struct in_addr swip, swip2; - u_short a5, a6, sp, dp; - u_int a1, a2, a3, a4; - fr_info_t fi; - nat_t *ipn; - int inc; - char *s; - - /* - * Check for PASV reply message. - */ - if (dlen < IPF_MIN227LEN) - return 0; - else if (strncmp(f->ftps_rptr, "227 Entering Passive Mode", 25)) - return 0; - - tcp = (tcphdr_t *)fin->fin_dp; - - /* - * Skip the PORT command + space - */ - s = f->ftps_rptr + 25; - while (*s && !isdigit(*s)) - s++; - /* - * Pick out the address components, two at a time. - */ - a1 = ippr_ftp_atoi(&s); - if (!s) - return 0; - a2 = ippr_ftp_atoi(&s); - if (!s) - return 0; - - /* - * check that IP address in the PORT/PASV reply is the same as the - * sender of the command - prevents using PORT for port scanning. - */ - a1 <<= 16; - a1 |= a2; - if (a1 != ntohl(nat->nat_oip.s_addr)) - return 0; - - a5 = ippr_ftp_atoi(&s); - if (!s) - return 0; - - if (*s == ')') - s++; - if (*s == '\n') - s--; - /* - * check for CR-LF at the end. - */ - if ((*s == '\r') && (*(s + 1) == '\n')) { - s += 2; - a6 = a5 & 0xff; - } else - return 0; - a5 >>= 8; - /* - * Calculate new address parts for 227 reply - */ - a1 = ntohl(ip->ip_src.s_addr); - a2 = (a1 >> 16) & 0xff; - a3 = (a1 >> 8) & 0xff; - a4 = a1 & 0xff; - a1 >>= 24; - inc = 0; -#if 0 - olen = s - f->ftps_rptr; - (void) sprintf(newbuf, "%s %u,%u,%u,%u,%u,%u\r\n", - "227 Entering Passive Mode", a1, a2, a3, a4, a5, a6); - nlen = strlen(newbuf); - inc = nlen - olen; - if ((inc + ip->ip_len) > 65535) - return 0; - -#if SOLARIS - m = fin->fin_qfm; - for (m1 = m; m1->b_cont; m1 = m1->b_cont) - ; - if ((inc > 0) && (m1->b_datap->db_lim - m1->b_wptr < inc)) { - mblk_t *nm; - - /* alloc enough to keep same trailer space for lower driver */ - nm = allocb(nlen, BPRI_MED); - PANIC((!nm),("ippr_ftp_out: allocb failed")); - - nm->b_band = m1->b_band; - nm->b_wptr += nlen; - - m1->b_wptr -= olen; - PANIC((m1->b_wptr < m1->b_rptr), - ("ippr_ftp_out: cannot handle fragmented data block")); - - linkb(m1, nm); - } else { - m1->b_wptr += inc; - } - /*copyin_mblk(m, off, nlen, newbuf);*/ -#else /* SOLARIS */ - m = *((mb_t **)fin->fin_mp); - if (inc < 0) - m_adj(m, inc); - /* the mbuf chain will be extended if necessary by m_copyback() */ - /*m_copyback(m, off, nlen, newbuf);*/ -#endif /* SOLARIS */ - if (inc != 0) { -#if SOLARIS || defined(__sgi) - register u_32_t sum1, sum2; - - sum1 = ip->ip_len; - sum2 = ip->ip_len + inc; - - /* Because ~1 == -2, We really need ~1 == -1 */ - if (sum1 > sum2) - sum2--; - sum2 -= sum1; - sum2 = (sum2 & 0xffff) + (sum2 >> 16); - - fix_outcksum(&ip->ip_sum, sum2); -#endif /* SOLARIS || defined(__sgi) */ - ip->ip_len += inc; - } -#endif /* 0 */ - - /* - * Add skeleton NAT entry for connection which will come back the - * other way. - */ - sp = 0; - dp = htons(fin->fin_data[1] - 1); - ipn = nat_outlookup(fin->fin_ifp, IPN_TCP, nat->nat_p, nat->nat_inip, - ip->ip_dst, (dp << 16) | sp, 0); - if (ipn == NULL) { - int slen; - - slen = ip->ip_len; - ip->ip_len = fin->fin_hlen + sizeof(*tcp2); - bcopy((char *)fin, (char *)&fi, sizeof(fi)); - bzero((char *)tcp2, sizeof(*tcp2)); - tcp2->th_win = htons(8192); - tcp2->th_sport = 0; /* XXX - fake it for nat_new */ - tcp2->th_off = 5; - fi.fin_data[1] = a5 << 8 | a6; - fi.fin_dlen = sizeof(*tcp2); - tcp2->th_dport = htons(fi.fin_data[1]); - fi.fin_data[0] = 0; - fi.fin_dp = (char *)tcp2; - fi.fin_fr = &natfr; - swip = ip->ip_src; - swip2 = ip->ip_dst; - fi.fin_fi.fi_daddr = ip->ip_src.s_addr; - fi.fin_fi.fi_saddr = nat->nat_inip.s_addr; - ip->ip_dst = ip->ip_src; - ip->ip_src = nat->nat_inip; - ipn = nat_new(nat->nat_ptr, ip, &fi, IPN_TCP|FI_W_SPORT, - NAT_OUTBOUND); - if (ipn != NULL) { - ipn->nat_age = fr_defnatage; - (void) fr_addstate(ip, &fi, FI_W_SPORT); - } - ip->ip_len = slen; - ip->ip_src = swip; - ip->ip_dst = swip2; - } - return inc; -} - - -int ippr_ftp_server(fin, ip, nat, ftp, dlen) -fr_info_t *fin; -ip_t *ip; -nat_t *nat; -ftpinfo_t *ftp; -int dlen; -{ - char *rptr, *wptr; - ftpside_t *f; - int inc; - - inc = 0; - f = &ftp->ftp_side[1]; - rptr = f->ftps_rptr; - wptr = f->ftps_wptr; - - if ((ftp->ftp_passok == 1) && !strncmp(rptr, "331", 3)) - ftp->ftp_passok = 2; - else if ((ftp->ftp_passok == 3) && !strncmp(rptr, "230", 3)) - ftp->ftp_passok = 4; - else if ((ftp->ftp_passok == 3) && !strncmp(rptr, "530", 3)) - ftp->ftp_passok = 0; - else if ((ftp->ftp_passok == 4) && !strncmp(rptr, "227 ", 4)) { - inc = ippr_ftp_pasv(fin, ip, nat, f, dlen); - } else if (ippr_ftp_insecure && !strncmp(rptr, "227 ", 4)) { - inc = ippr_ftp_pasv(fin, ip, nat, f, dlen); - } - while ((*rptr++ != '\n') && (rptr < wptr)) - ; - f->ftps_rptr = rptr; - return inc; -} - - -/* - * Look to see if the buffer starts with something which we recognise as - * being the correct syntax for the FTP protocol. - */ -int ippr_ftp_valid(buf, len) -char *buf; -size_t len; -{ - register char *s, c; - register size_t i = len; - - if (i < 5) - return 2; - s = buf; - c = *s++; - i--; - - if (isdigit(c)) { - c = *s++; - i--; - if (isdigit(c)) { - c = *s++; - i--; - if (isdigit(c)) { - c = *s++; - i--; - if ((c != '-') && (c != ' ')) - return 1; - } else - return 1; - } else - return 1; - } else if (isalpha(c)) { - c = *s++; - i--; - if (isalpha(c)) { - c = *s++; - i--; - if (isalpha(c)) { - c = *s++; - i--; - if (isalpha(c)) { - c = *s++; - i--; - if ((c != ' ') && (c != '\r')) - return 1; - } else if ((c != ' ') && (c != '\r')) - return 1; - } else - return 1; - } else - return 1; - } else - return 1; - for (; i; i--) { - c = *s++; - if (c == '\n') - return 0; - } - return 2; -} - - -int ippr_ftp_process(fin, ip, nat, ftp, rv) -fr_info_t *fin; -ip_t *ip; -nat_t *nat; -ftpinfo_t *ftp; -int rv; -{ - int mlen, len, off, inc, i, sel; - char *rptr, *wptr; - ftpside_t *f, *t; - tcphdr_t *tcp; - mb_t *m; - - tcp = (tcphdr_t *)fin->fin_dp; - off = fin->fin_hlen + (tcp->th_off << 2); - -#if SOLARIS - m = fin->fin_qfm; -#else - m = *((mb_t **)fin->fin_mp); -#endif - -#if SOLARIS - mlen = msgdsize(m) - off; -#else - mlen = mbufchainlen(m) - off; -#endif - - t = &ftp->ftp_side[1 - rv]; - f = &ftp->ftp_side[rv]; - if (!mlen) { - if (!t->ftps_seq || - (int)ntohl(tcp->th_ack) - (int)t->ftps_seq > 0) - t->ftps_seq = ntohl(tcp->th_ack); - f->ftps_len = 0; - return 0; - } - - inc = 0; - rptr = f->ftps_rptr; - wptr = f->ftps_wptr; - - sel = nat->nat_aps->aps_sel[1 - rv]; - if (rv) - i = nat->nat_aps->aps_ackoff[sel]; - else - i = nat->nat_aps->aps_seqoff[sel]; - /* - * XXX - Ideally, this packet should get dropped because we now know - * that it is out of order (and there is no real danger in doing so - * apart from causing packets to go through here ordered). - */ - if (f->ftps_len + f->ftps_seq == ntohl(tcp->th_seq)) - f->ftps_seq = ntohl(tcp->th_seq); - else if (ntohl(tcp->th_seq) + i != f->ftps_seq) { - return APR_ERR(-1); - } - f->ftps_len = mlen; - - while (mlen > 0) { - len = MIN(mlen, FTP_BUFSZ / 2); - -#if SOLARIS - copyout_mblk(m, off, len, wptr); -#else - m_copydata(m, off, len, wptr); -#endif - mlen -= len; - off += len; - wptr += len; - f->ftps_wptr = wptr; - if (f->ftps_junk == 2) - f->ftps_junk = ippr_ftp_valid(rptr, wptr - rptr); - - while ((f->ftps_junk == 0) && (wptr > rptr)) { - f->ftps_junk = ippr_ftp_valid(rptr, wptr - rptr); - if (f->ftps_junk == 0) { - len = wptr - rptr; - f->ftps_rptr = rptr; - if (rv) - inc += ippr_ftp_server(fin, ip, nat, - ftp, len); - else - inc += ippr_ftp_client(fin, ip, nat, - ftp, len); - rptr = f->ftps_rptr; - } - } - - while ((f->ftps_junk == 1) && (rptr < wptr)) { - while ((rptr < wptr) && (*rptr != '\r')) - rptr++; - - if (*rptr == '\r') { - if (rptr + 1 < wptr) { - if (*(rptr + 1) == '\n') { - rptr += 2; - f->ftps_junk = 0; - } else - rptr++; - } else - break; - } - } - f->ftps_rptr = rptr; - - if (rptr == wptr) { - rptr = wptr = f->ftps_buf; - } else { - if ((wptr > f->ftps_buf + FTP_BUFSZ / 2)) { - i = wptr - rptr; - if ((rptr == f->ftps_buf) || - (wptr - rptr > FTP_BUFSZ / 2)) { - f->ftps_junk = 1; - rptr = wptr = f->ftps_buf; - } else { - bcopy(rptr, f->ftps_buf, i); - wptr = f->ftps_buf + i; - rptr = f->ftps_buf; - } - } - f->ftps_rptr = rptr; - f->ftps_wptr = wptr; - } - } - - t->ftps_seq = ntohl(tcp->th_ack); - f->ftps_rptr = rptr; - f->ftps_wptr = wptr; - return APR_INC(inc); -} - - -int ippr_ftp_out(fin, ip, aps, nat) -fr_info_t *fin; -ip_t *ip; -ap_session_t *aps; -nat_t *nat; -{ - ftpinfo_t *ftp; - - ftp = aps->aps_data; - if (ftp == NULL) - return 0; - return ippr_ftp_process(fin, ip, nat, ftp, 0); -} - - -int ippr_ftp_in(fin, ip, aps, nat) -fr_info_t *fin; -ip_t *ip; -ap_session_t *aps; -nat_t *nat; -{ - ftpinfo_t *ftp; - - ftp = aps->aps_data; - if (ftp == NULL) - return 0; - return ippr_ftp_process(fin, ip, nat, ftp, 1); -} - - -/* - * ippr_ftp_atoi - implement a version of atoi which processes numbers in - * pairs separated by commas (which are expected to be in the range 0 - 255), - * returning a 16 bit number combining either side of the , as the MSB and - * LSB. - */ -u_short ippr_ftp_atoi(ptr) -char **ptr; -{ - register char *s = *ptr, c; - register u_char i = 0, j = 0; - - while ((c = *s++) && isdigit(c)) { - i *= 10; - i += c - '0'; - } - if (c != ',') { - *ptr = NULL; - return 0; - } - while ((c = *s++) && isdigit(c)) { - j *= 10; - j += c - '0'; - } - *ptr = s; - i &= 0xff; - j &= 0xff; - return (i << 8) | j; -} diff --git a/contrib/ipfilter/ip_log.c b/contrib/ipfilter/ip_log.c deleted file mode 100644 index a7d1529..0000000 --- a/contrib/ipfilter/ip_log.c +++ /dev/null @@ -1,502 +0,0 @@ -/* - * Copyright (C) 1997-2000 by Darren Reed. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - * - * $Id: ip_log.c,v 2.1.2.2 1999/09/21 11:55:44 darrenr Exp $ - * $FreeBSD$ - */ -#include <sys/param.h> -#if defined(KERNEL) && !defined(_KERNEL) -# define _KERNEL -#endif -#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) -# include "opt_ipfilter_log.h" -#endif -#ifdef __FreeBSD__ -# if defined(_KERNEL) && !defined(IPFILTER_LKM) -# if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) -# include "opt_ipfilter.h" -# endif -# else -# ifdef KLD_MODULE -# include <osreldate.h> -# endif -# endif -#endif -#ifdef IPFILTER_LOG -# ifndef SOLARIS -# define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) -# endif -# ifndef _KERNEL -# include <stdio.h> -# include <string.h> -# include <stdlib.h> -# include <ctype.h> -# endif -# include <sys/errno.h> -# include <sys/types.h> -# include <sys/file.h> -# if __FreeBSD_version >= 220000 && defined(_KERNEL) -# include <sys/fcntl.h> -# include <sys/filio.h> -# else -# include <sys/ioctl.h> -# endif -# include <sys/time.h> -# if defined(_KERNEL) && !defined(linux) -# include <sys/systm.h> -# endif -# include <sys/uio.h> -# if !SOLARIS -# if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000) -# include <sys/dirent.h> -# else -# include <sys/dir.h> -# endif -# ifndef linux -# include <sys/mbuf.h> -# endif -# else -# include <sys/filio.h> -# include <sys/cred.h> -# include <sys/ddi.h> -# include <sys/sunddi.h> -# include <sys/ksynch.h> -# include <sys/kmem.h> -# include <sys/mkdev.h> -# include <sys/dditypes.h> -# include <sys/cmn_err.h> -# endif -# ifndef linux -# include <sys/protosw.h> -# endif -# include <sys/socket.h> - -# include <net/if.h> -# ifdef sun -# include <net/af.h> -# endif -# if __FreeBSD_version >= 300000 -# include <net/if_var.h> -# endif -# include <net/route.h> -# include <netinet/in.h> -# ifdef __sgi -# include <sys/ddi.h> -# ifdef IFF_DRVRLOCK /* IRIX6 */ -# include <sys/hashing.h> -# endif -# endif -# if !defined(linux) && !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /*IRIX<6*/ -# include <netinet/in_var.h> -# endif -# include <netinet/in_systm.h> -# include <netinet/ip.h> -# include <netinet/tcp.h> -# include <netinet/udp.h> -# include <netinet/ip_icmp.h> -# ifndef linux -# include <netinet/ip_var.h> -# endif -# ifndef _KERNEL -# include <syslog.h> -# endif -# include "netinet/ip_compat.h" -# include <netinet/tcpip.h> -# include "netinet/ip_fil.h" -# include "netinet/ip_proxy.h" -# include "netinet/ip_nat.h" -# include "netinet/ip_frag.h" -# include "netinet/ip_state.h" -# include "netinet/ip_auth.h" -# if (__FreeBSD_version >= 300000) -# include <sys/malloc.h> -# endif - -# ifndef MIN -# define MIN(a,b) (((a)<(b))?(a):(b)) -# endif - - -# if SOLARIS || defined(__sgi) -extern kmutex_t ipl_mutex; -# if SOLARIS -extern kcondvar_t iplwait; -# endif -# endif - -iplog_t **iplh[IPL_LOGMAX+1], *iplt[IPL_LOGMAX+1], *ipll[IPL_LOGMAX+1]; -size_t iplused[IPL_LOGMAX+1]; -static fr_info_t iplcrc[IPL_LOGMAX+1]; -# ifdef linux -static struct wait_queue *iplwait[IPL_LOGMAX+1]; -# endif - - -/* - * Initialise log buffers & pointers. Also iniialised the CRC to a local - * secret for use in calculating the "last log checksum". - */ -void ipflog_init() -{ - int i; - - for (i = IPL_LOGMAX; i >= 0; i--) { - iplt[i] = NULL; - ipll[i] = NULL; - iplh[i] = &iplt[i]; - iplused[i] = 0; - bzero((char *)&iplcrc[i], sizeof(iplcrc[i])); - } -} - - -/* - * ipflog - * Create a log record for a packet given that it has been triggered by a - * rule (or the default setting). Calculate the transport protocol header - * size using predetermined size of a couple of popular protocols and thus - * how much data to copy into the log, including part of the data body if - * requested. - */ -int ipflog(flags, ip, fin, m) -u_int flags; -ip_t *ip; -fr_info_t *fin; -mb_t *m; -{ - ipflog_t ipfl; - register size_t mlen, hlen; - size_t sizes[2]; - void *ptrs[2]; - int types[2]; - u_char p; -# if SOLARIS - ill_t *ifp = fin->fin_ifp; -# else - struct ifnet *ifp = fin->fin_ifp; -# endif - - /* - * calculate header size. - */ - hlen = fin->fin_hlen; - if (fin->fin_off == 0) { - p = fin->fin_fi.fi_p; - if (p == IPPROTO_TCP) - hlen += MIN(sizeof(tcphdr_t), fin->fin_dlen); - else if (p == IPPROTO_UDP) - hlen += MIN(sizeof(udphdr_t), fin->fin_dlen); - else if (p == IPPROTO_ICMP) { - struct icmp *icmp; - - icmp = (struct icmp *)fin->fin_dp; - - /* - * For ICMP, if the packet is an error packet, also - * include the information about the packet which - * caused the error. - */ - switch (icmp->icmp_type) - { - case ICMP_UNREACH : - case ICMP_SOURCEQUENCH : - case ICMP_REDIRECT : - case ICMP_TIMXCEED : - case ICMP_PARAMPROB : - hlen += MIN(sizeof(struct icmp) + 8, - fin->fin_dlen); - break; - default : - hlen += MIN(sizeof(struct icmp), - fin->fin_dlen); - break; - } - } - } - /* - * Get the interface number and name to which this packet is - * currently associated. - */ -# if SOLARIS - ipfl.fl_unit = (u_char)ifp->ill_ppa; - bcopy(ifp->ill_name, ipfl.fl_ifname, MIN(ifp->ill_name_length, 4)); - mlen = (flags & FR_LOGBODY) ? MIN(msgdsize(m) - hlen, 128) : 0; -# else -# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603)) - strncpy(ipfl.fl_ifname, ifp->if_xname, IFNAMSIZ); -# else -# ifndef linux - ipfl.fl_unit = (u_char)ifp->if_unit; -# endif - if ((ipfl.fl_ifname[0] = ifp->if_name[0])) - if ((ipfl.fl_ifname[1] = ifp->if_name[1])) - if ((ipfl.fl_ifname[2] = ifp->if_name[2])) - ipfl.fl_ifname[3] = ifp->if_name[3]; -# endif - mlen = (flags & FR_LOGBODY) ? MIN(fin->fin_plen - hlen, 128) : 0; -# endif - ipfl.fl_plen = (u_char)mlen; - ipfl.fl_hlen = (u_char)hlen; - ipfl.fl_rule = fin->fin_rule; - ipfl.fl_group = fin->fin_group; - if (fin->fin_fr != NULL) - ipfl.fl_loglevel = fin->fin_fr->fr_loglevel; - else - ipfl.fl_loglevel = 0xffff; - ipfl.fl_flags = flags; - ptrs[0] = (void *)&ipfl; - sizes[0] = sizeof(ipfl); - types[0] = 0; -# if SOLARIS - /* - * Are we copied from the mblk or an aligned array ? - */ - if (ip == (ip_t *)m->b_rptr) { - ptrs[1] = m; - sizes[1] = hlen + mlen; - types[1] = 1; - } else { - ptrs[1] = ip; - sizes[1] = hlen + mlen; - types[1] = 0; - } -# else - ptrs[1] = m; - sizes[1] = hlen + mlen; - types[1] = 1; -# endif - return ipllog(IPL_LOGIPF, fin, ptrs, sizes, types, 2); -} - - -/* - * ipllog - */ -int ipllog(dev, fin, items, itemsz, types, cnt) -int dev; -fr_info_t *fin; -void **items; -size_t *itemsz; -int *types, cnt; -{ - caddr_t buf, s; - iplog_t *ipl; - size_t len; - int i; - - /* - * Check to see if this log record has a CRC which matches the last - * record logged. If it does, just up the count on the previous one - * rather than create a new one. - */ - MUTEX_ENTER(&ipl_mutex); - if (fin != NULL) { - if ((ipll[dev] != NULL) && - bcmp((char *)fin, (char *)&iplcrc[dev], FI_CSIZE) == 0) { - ipll[dev]->ipl_count++; - MUTEX_EXIT(&ipl_mutex); - return 1; - } - bcopy((char *)fin, (char *)&iplcrc[dev], FI_CSIZE); - } else - bzero((char *)&iplcrc[dev], FI_CSIZE); - MUTEX_EXIT(&ipl_mutex); - - /* - * Get the total amount of data to be logged. - */ - for (i = 0, len = sizeof(iplog_t); i < cnt; i++) - len += itemsz[i]; - - /* - * check that we have space to record this information and can - * allocate that much. - */ - KMALLOCS(buf, caddr_t, len); - if (!buf) - return 0; - MUTEX_ENTER(&ipl_mutex); - if ((iplused[dev] + len) > IPLLOGSIZE) { - MUTEX_EXIT(&ipl_mutex); - KFREES(buf, len); - return 0; - } - iplused[dev] += len; - MUTEX_EXIT(&ipl_mutex); - - /* - * advance the log pointer to the next empty record and deduct the - * amount of space we're going to use. - */ - ipl = (iplog_t *)buf; - ipl->ipl_magic = IPL_MAGIC; - ipl->ipl_count = 1; - ipl->ipl_next = NULL; - ipl->ipl_dsize = len; -# if SOLARIS || defined(sun) || defined(linux) - uniqtime((struct timeval *)&ipl->ipl_sec); -# else -# if BSD >= 199306 || defined(__FreeBSD__) || defined(__sgi) - microtime((struct timeval *)&ipl->ipl_sec); -# endif -# endif - - /* - * Loop through all the items to be logged, copying each one to the - * buffer. Use bcopy for normal data or the mb_t copyout routine. - */ - for (i = 0, s = buf + sizeof(*ipl); i < cnt; i++) { - if (types[i] == 0) - bcopy(items[i], s, itemsz[i]); - else if (types[i] == 1) { -# if SOLARIS - copyout_mblk(items[i], 0, itemsz[i], s); -# else - m_copydata(items[i], 0, itemsz[i], s); -# endif - } - s += itemsz[i]; - } - MUTEX_ENTER(&ipl_mutex); - ipll[dev] = ipl; - *iplh[dev] = ipl; - iplh[dev] = &ipl->ipl_next; -# if SOLARIS - cv_signal(&iplwait); - mutex_exit(&ipl_mutex); -# else - MUTEX_EXIT(&ipl_mutex); -# ifdef linux - wake_up_interruptible(&iplwait[dev]); -# else - wakeup(&iplh[dev]); -# endif -# endif - return 1; -} - - -int ipflog_read(unit, uio) -minor_t unit; -struct uio *uio; -{ - size_t dlen, copied; - int error = 0; - iplog_t *ipl; -# if defined(_KERNEL) && !SOLARIS - int s; -# endif - - /* - * Sanity checks. Make sure the minor # is valid and we're copying - * a valid chunk of data. - */ - if (IPL_LOGMAX < unit) - return ENXIO; - if (!uio->uio_resid) - return 0; - if ((uio->uio_resid < sizeof(iplog_t)) || - (uio->uio_resid > IPLLOGSIZE)) - return EINVAL; - - /* - * Lock the log so we can snapshot the variables. Wait for a signal - * if the log is empty. - */ - SPL_NET(s); - MUTEX_ENTER(&ipl_mutex); - - while (!iplused[unit] || !iplt[unit]) { -# if SOLARIS && defined(_KERNEL) - if (!cv_wait_sig(&iplwait, &ipl_mutex)) { - MUTEX_EXIT(&ipl_mutex); - return EINTR; - } -# else -# ifdef linux - interruptible_sleep_on(&iplwait[unit]); - if (current->signal & ~current->blocked) - return -EINTR; -# else - MUTEX_EXIT(&ipl_mutex); - SPL_X(s); - error = SLEEP(&iplh[unit], "ipl sleep"); - if (error) - return error; - SPL_NET(s); - MUTEX_ENTER(&ipl_mutex); -# endif /* linux */ -# endif /* SOLARIS */ - } - -# if BSD >= 199306 || defined(__FreeBSD__) - uio->uio_rw = UIO_READ; -# endif - - for (copied = 0; (ipl = iplt[unit]); copied += dlen) { - dlen = ipl->ipl_dsize; - if (dlen > uio->uio_resid) - break; - /* - * Don't hold the mutex over the uiomove call. - */ - iplt[unit] = ipl->ipl_next; - iplused[unit] -= dlen; - MUTEX_EXIT(&ipl_mutex); - SPL_X(s); - error = UIOMOVE((caddr_t)ipl, dlen, UIO_READ, uio); - if (error) { - SPL_NET(s); - MUTEX_ENTER(&ipl_mutex); - ipl->ipl_next = iplt[unit]; - iplt[unit] = ipl; - iplused[unit] += dlen; - break; - } - KFREES((caddr_t)ipl, dlen); - SPL_NET(s); - MUTEX_ENTER(&ipl_mutex); - } - if (!iplt[unit]) { - iplused[unit] = 0; - iplh[unit] = &iplt[unit]; - ipll[unit] = NULL; - } - - MUTEX_EXIT(&ipl_mutex); - SPL_X(s); -# ifdef linux - if (!error) - return (int)copied; - return -error; -# else - return error; -# endif -} - - -int ipflog_clear(unit) -minor_t unit; -{ - iplog_t *ipl; - int used; - - MUTEX_ENTER(&ipl_mutex); - while ((ipl = iplt[unit])) { - iplt[unit] = ipl->ipl_next; - KFREES((caddr_t)ipl, ipl->ipl_dsize); - } - iplh[unit] = &iplt[unit]; - ipll[unit] = NULL; - used = iplused[unit]; - iplused[unit] = 0; - bzero((char *)&iplcrc[unit], FI_CSIZE); - MUTEX_EXIT(&ipl_mutex); - return used; -} -#endif /* IPFILTER_LOG */ diff --git a/contrib/ipfilter/ip_nat.c b/contrib/ipfilter/ip_nat.c deleted file mode 100644 index e7e121a..0000000 --- a/contrib/ipfilter/ip_nat.c +++ /dev/null @@ -1,2737 +0,0 @@ -/* - * Copyright (C) 1995-2000 by Darren Reed. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - * - * Added redirect stuff and a LOT of bug fixes. (mcn@EnGarde.com) - */ -#if !defined(lint) -static const char sccsid[] = "@(#)ip_nat.c 1.11 6/5/96 (C) 1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_nat.c,v 2.37.2.32 2001/01/10 06:19:11 darrenr Exp $"; -#endif - -#if defined(__FreeBSD__) && defined(KERNEL) && !defined(_KERNEL) -#define _KERNEL -#endif - -#include <sys/errno.h> -#include <sys/types.h> -#include <sys/param.h> -#include <sys/time.h> -#include <sys/file.h> -#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \ - defined(_KERNEL) -# include "opt_ipfilter_log.h" -#endif -#if !defined(_KERNEL) && !defined(KERNEL) -# include <stdio.h> -# include <string.h> -# include <stdlib.h> -#endif -#if (defined(KERNEL) || defined(_KERNEL)) && (__FreeBSD_version >= 220000) -# include <sys/filio.h> -# include <sys/fcntl.h> -#else -# include <sys/ioctl.h> -#endif -#include <sys/fcntl.h> -#include <sys/uio.h> -#ifndef linux -# include <sys/protosw.h> -#endif -#include <sys/socket.h> -#if defined(_KERNEL) && !defined(linux) -# include <sys/systm.h> -#endif -#if !defined(__SVR4) && !defined(__svr4__) -# ifndef linux -# include <sys/mbuf.h> -# endif -#else -# include <sys/filio.h> -# include <sys/byteorder.h> -# ifdef _KERNEL -# include <sys/dditypes.h> -# endif -# include <sys/stream.h> -# include <sys/kmem.h> -#endif -#if __FreeBSD_version >= 300000 -# include <sys/queue.h> -#endif -#include <net/if.h> -#if __FreeBSD_version >= 300000 -# include <net/if_var.h> -# if defined(_KERNEL) && !defined(IPFILTER_LKM) -# include "opt_ipfilter.h" -# endif -#endif -#ifdef sun -# include <net/af.h> -#endif -#include <net/route.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> - -#ifdef __sgi -# ifdef IFF_DRVRLOCK /* IRIX6 */ -#include <sys/hashing.h> -#include <netinet/in_var.h> -# endif -#endif - -#ifdef RFC1825 -# include <vpn/md5.h> -# include <vpn/ipsec.h> -extern struct ifnet vpnif; -#endif - -#ifndef linux -# include <netinet/ip_var.h> -#endif -#include <netinet/tcp.h> -#include <netinet/udp.h> -#include <netinet/ip_icmp.h> -#include "netinet/ip_compat.h" -#include <netinet/tcpip.h> -#include "netinet/ip_fil.h" -#include "netinet/ip_proxy.h" -#include "netinet/ip_nat.h" -#include "netinet/ip_frag.h" -#include "netinet/ip_state.h" -#if (__FreeBSD_version >= 300000) -# include <sys/malloc.h> -#endif -#ifndef MIN -# define MIN(a,b) (((a)<(b))?(a):(b)) -#endif -#undef SOCKADDR_IN -#define SOCKADDR_IN struct sockaddr_in - -nat_t **nat_table[2] = { NULL, NULL }, - *nat_instances = NULL; -ipnat_t *nat_list = NULL; -u_int ipf_nattable_sz = NAT_TABLE_SZ; -u_int ipf_natrules_sz = NAT_SIZE; -u_int ipf_rdrrules_sz = RDR_SIZE; -u_int ipf_hostmap_sz = HOSTMAP_SIZE; -u_32_t nat_masks = 0; -u_32_t rdr_masks = 0; -ipnat_t **nat_rules = NULL; -ipnat_t **rdr_rules = NULL; -hostmap_t **maptable = NULL; - -u_long fr_defnatage = DEF_NAT_AGE, - fr_defnaticmpage = 6; /* 3 seconds */ -natstat_t nat_stats; -int fr_nat_lock = 0; -#if (SOLARIS || defined(__sgi)) && defined(_KERNEL) -extern kmutex_t ipf_rw; -extern KRWLOCK_T ipf_nat; -#endif - -static int nat_flushtable __P((void)); -static int nat_clearlist __P((void)); -static void nat_addnat __P((struct ipnat *)); -static void nat_addrdr __P((struct ipnat *)); -static void nat_delete __P((struct nat *)); -static void nat_delrdr __P((struct ipnat *)); -static void nat_delnat __P((struct ipnat *)); -static int fr_natgetent __P((caddr_t)); -static int fr_natgetsz __P((caddr_t)); -static int fr_natputent __P((caddr_t)); -static void nat_tabmove __P((nat_t *, u_32_t)); -static int nat_match __P((fr_info_t *, ipnat_t *, ip_t *)); -static hostmap_t *nat_hostmap __P((ipnat_t *, struct in_addr, - struct in_addr)); -static void nat_hostmapdel __P((struct hostmap *)); - - -int nat_init() -{ - KMALLOCS(nat_table[0], nat_t **, sizeof(nat_t *) * ipf_nattable_sz); - if (nat_table[0] != NULL) - bzero((char *)nat_table[0], ipf_nattable_sz * sizeof(nat_t *)); - else - return -1; - - KMALLOCS(nat_table[1], nat_t **, sizeof(nat_t *) * ipf_nattable_sz); - if (nat_table[1] != NULL) - bzero((char *)nat_table[1], ipf_nattable_sz * sizeof(nat_t *)); - else - return -1; - - KMALLOCS(nat_rules, ipnat_t **, sizeof(ipnat_t *) * ipf_natrules_sz); - if (nat_rules != NULL) - bzero((char *)nat_rules, ipf_natrules_sz * sizeof(ipnat_t *)); - else - return -1; - - KMALLOCS(rdr_rules, ipnat_t **, sizeof(ipnat_t *) * ipf_rdrrules_sz); - if (rdr_rules != NULL) - bzero((char *)rdr_rules, ipf_rdrrules_sz * sizeof(ipnat_t *)); - else - return -1; - - KMALLOCS(maptable, hostmap_t **, sizeof(hostmap_t *) * ipf_hostmap_sz); - if (maptable != NULL) - bzero((char *)maptable, sizeof(hostmap_t *) * ipf_hostmap_sz); - else - return -1; - return 0; -} - - -static void nat_addrdr(n) -ipnat_t *n; -{ - ipnat_t **np; - u_32_t j; - u_int hv; - int k; - - k = countbits(n->in_outmsk); - if ((k >= 0) && (k != 32)) - rdr_masks |= 1 << k; - j = (n->in_outip & n->in_outmsk); - hv = NAT_HASH_FN(j, 0, ipf_rdrrules_sz); - np = rdr_rules + hv; - while (*np != NULL) - np = &(*np)->in_rnext; - n->in_rnext = NULL; - n->in_prnext = np; - *np = n; -} - - -static void nat_addnat(n) -ipnat_t *n; -{ - ipnat_t **np; - u_32_t j; - u_int hv; - int k; - - k = countbits(n->in_inmsk); - if ((k >= 0) && (k != 32)) - nat_masks |= 1 << k; - j = (n->in_inip & n->in_inmsk); - hv = NAT_HASH_FN(j, 0, ipf_natrules_sz); - np = nat_rules + hv; - while (*np != NULL) - np = &(*np)->in_mnext; - n->in_mnext = NULL; - n->in_pmnext = np; - *np = n; -} - - -static void nat_delrdr(n) -ipnat_t *n; -{ - if (n->in_rnext) - n->in_rnext->in_prnext = n->in_prnext; - *n->in_prnext = n->in_rnext; -} - - -static void nat_delnat(n) -ipnat_t *n; -{ - if (n->in_mnext) - n->in_mnext->in_pmnext = n->in_pmnext; - *n->in_pmnext = n->in_mnext; -} - - -/* - * check if an ip address has already been allocated for a given mapping that - * is not doing port based translation. - * - * Must be called with ipf_nat held as a write lock. - */ -static struct hostmap *nat_hostmap(np, real, map) -ipnat_t *np; -struct in_addr real; -struct in_addr map; -{ - hostmap_t *hm; - u_int hv; - - hv = real.s_addr % HOSTMAP_SIZE; - for (hm = maptable[hv]; hm; hm = hm->hm_next) - if ((hm->hm_realip.s_addr == real.s_addr) && - (np == hm->hm_ipnat)) { - hm->hm_ref++; - return hm; - } - - KMALLOC(hm, hostmap_t *); - if (hm) { - hm->hm_next = maptable[hv]; - hm->hm_pnext = maptable + hv; - if (maptable[hv]) - maptable[hv]->hm_pnext = &hm->hm_next; - maptable[hv] = hm; - hm->hm_ipnat = np; - hm->hm_realip = real; - hm->hm_mapip = map; - hm->hm_ref = 1; - } - return hm; -} - - -/* - * Must be called with ipf_nat held as a write lock. - */ -static void nat_hostmapdel(hm) -struct hostmap *hm; -{ - ATOMIC_DEC32(hm->hm_ref); - if (hm->hm_ref == 0) { - if (hm->hm_next) - hm->hm_next->hm_pnext = hm->hm_pnext; - *hm->hm_pnext = hm->hm_next; - KFREE(hm); - } -} - - -void fix_outcksum(sp, n) -u_short *sp; -u_32_t n; -{ - register u_short sumshort; - register u_32_t sum1; - - if (!n) - return; -#if SOLARIS2 >= 6 - else if (n & NAT_HW_CKSUM) { - *sp = n & 0xffff; - return; - } -#endif - sum1 = (~ntohs(*sp)) & 0xffff; - sum1 += (n); - sum1 = (sum1 >> 16) + (sum1 & 0xffff); - /* Again */ - sum1 = (sum1 >> 16) + (sum1 & 0xffff); - sumshort = ~(u_short)sum1; - *(sp) = htons(sumshort); -} - - -void fix_incksum(sp, n) -u_short *sp; -u_32_t n; -{ - register u_short sumshort; - register u_32_t sum1; - - if (!n) - return; -#if SOLARIS2 >= 6 - else if (n & NAT_HW_CKSUM) { - *sp = n & 0xffff; - return; - } -#endif -#ifdef sparc - sum1 = (~(*sp)) & 0xffff; -#else - sum1 = (~ntohs(*sp)) & 0xffff; -#endif - sum1 += ~(n) & 0xffff; - sum1 = (sum1 >> 16) + (sum1 & 0xffff); - /* Again */ - sum1 = (sum1 >> 16) + (sum1 & 0xffff); - sumshort = ~(u_short)sum1; - *(sp) = htons(sumshort); -} - - -/* - * fix_datacksum is used *only* for the adjustments of checksums in the data - * section of an IP packet. - * - * The only situation in which you need to do this is when NAT'ing an - * ICMP error message. Such a message, contains in its body the IP header - * of the original IP packet, that causes the error. - * - * You can't use fix_incksum or fix_outcksum in that case, because for the - * kernel the data section of the ICMP error is just data, and no special - * processing like hardware cksum or ntohs processing have been done by the - * kernel on the data section. - */ -void fix_datacksum(sp, n) -u_short *sp; -u_32_t n; -{ - register u_short sumshort; - register u_32_t sum1; - - if (!n) - return; - - sum1 = (~ntohs(*sp)) & 0xffff; - sum1 += (n); - sum1 = (sum1 >> 16) + (sum1 & 0xffff); - /* Again */ - sum1 = (sum1 >> 16) + (sum1 & 0xffff); - sumshort = ~(u_short)sum1; - *(sp) = htons(sumshort); -} - -/* - * How the NAT is organised and works. - * - * Inside (interface y) NAT Outside (interface x) - * -------------------- -+- ------------------------------------- - * Packet going | out, processsed by ip_natout() for x - * ------------> | ------------> - * src=10.1.1.1 | src=192.1.1.1 - * | - * | in, processed by ip_natin() for x - * <------------ | <------------ - * dst=10.1.1.1 | dst=192.1.1.1 - * -------------------- -+- ------------------------------------- - * ip_natout() - changes ip_src and if required, sport - * - creates a new mapping, if required. - * ip_natin() - changes ip_dst and if required, dport - * - * In the NAT table, internal source is recorded as "in" and externally - * seen as "out". - */ - -/* - * Handle ioctls which manipulate the NAT. - */ -int nat_ioctl(data, cmd, mode) -#if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003) -u_long cmd; -#else -int cmd; -#endif -caddr_t data; -int mode; -{ - register ipnat_t *nat, *nt, *n = NULL, **np = NULL; - int error = 0, ret, arg; - ipnat_t natd; - u_32_t i, j; - -#if (BSD >= 199306) && defined(_KERNEL) - if ((securelevel >= 2) && (mode & FWRITE)) - return EPERM; -#endif - - nat = NULL; /* XXX gcc -Wuninitialized */ - KMALLOC(nt, ipnat_t *); - if ((cmd == SIOCADNAT) || (cmd == SIOCRMNAT)) - error = IRCOPYPTR(data, (char *)&natd, sizeof(natd)); - else if (cmd == SIOCIPFFL) { /* SIOCFLNAT & SIOCCNATL */ - error = IRCOPY(data, (char *)&arg, sizeof(arg)); - if (error) - error = EFAULT; - } - - if (error) - goto done; - - /* - * For add/delete, look to see if the NAT entry is already present - */ - WRITE_ENTER(&ipf_nat); - if ((cmd == SIOCADNAT) || (cmd == SIOCRMNAT)) { - nat = &natd; - nat->in_flags &= IPN_USERFLAGS; - if ((nat->in_redir & NAT_MAPBLK) == 0) { - if ((nat->in_flags & IPN_SPLIT) == 0) - nat->in_inip &= nat->in_inmsk; - if ((nat->in_flags & IPN_IPRANGE) == 0) - nat->in_outip &= nat->in_outmsk; - } - for (np = &nat_list; (n = *np); np = &n->in_next) - if (!bcmp((char *)&nat->in_flags, (char *)&n->in_flags, - IPN_CMPSIZ)) - break; - } - - switch (cmd) - { -#ifdef IPFILTER_LOG - case SIOCIPFFB : - { - int tmp; - - if (!(mode & FWRITE)) - error = EPERM; - else { - tmp = ipflog_clear(IPL_LOGNAT); - IWCOPY((char *)&tmp, (char *)data, sizeof(tmp)); - } - break; - } -#endif - case SIOCADNAT : - if (!(mode & FWRITE)) { - error = EPERM; - break; - } - if (n) { - error = EEXIST; - break; - } - if (nt == NULL) { - error = ENOMEM; - break; - } - n = nt; - nt = NULL; - bcopy((char *)nat, (char *)n, sizeof(*n)); - n->in_ifp = (void *)GETUNIT(n->in_ifname, 4); - if (!n->in_ifp) - n->in_ifp = (void *)-1; - if (n->in_plabel[0] != '\0') { - n->in_apr = appr_match(n->in_p, n->in_plabel); - if (!n->in_apr) { - error = ENOENT; - break; - } - } - n->in_next = NULL; - *np = n; - - if (n->in_redir & NAT_REDIRECT) { - n->in_flags &= ~IPN_NOTDST; - nat_addrdr(n); - } - if (n->in_redir & (NAT_MAP|NAT_MAPBLK)) { - n->in_flags &= ~IPN_NOTSRC; - nat_addnat(n); - } - - n->in_use = 0; - if (n->in_redir & NAT_MAPBLK) - n->in_space = USABLE_PORTS * ~ntohl(n->in_outmsk); - else if (n->in_flags & IPN_AUTOPORTMAP) - n->in_space = USABLE_PORTS * ~ntohl(n->in_inmsk); - else if (n->in_flags & IPN_IPRANGE) - n->in_space = ntohl(n->in_outmsk) - ntohl(n->in_outip); - else if (n->in_flags & IPN_SPLIT) - n->in_space = 2; - else - n->in_space = ~ntohl(n->in_outmsk); - /* - * Calculate the number of valid IP addresses in the output - * mapping range. In all cases, the range is inclusive of - * the start and ending IP addresses. - * If to a CIDR address, lose 2: broadcast + network address - * (so subtract 1) - * If to a range, add one. - * If to a single IP address, set to 1. - */ - if (n->in_space) { - if ((n->in_flags & IPN_IPRANGE) != 0) - n->in_space += 1; - else - n->in_space -= 1; - } else - n->in_space = 1; - if ((n->in_outmsk != 0xffffffff) && (n->in_outmsk != 0) && - ((n->in_flags & (IPN_IPRANGE|IPN_SPLIT)) == 0)) - n->in_nip = ntohl(n->in_outip) + 1; - else if ((n->in_flags & IPN_SPLIT) && - (n->in_redir & NAT_REDIRECT)) - n->in_nip = ntohl(n->in_inip); - else - n->in_nip = ntohl(n->in_outip); - if (n->in_redir & NAT_MAP) { - n->in_pnext = ntohs(n->in_pmin); - /* - * Multiply by the number of ports made available. - */ - if (ntohs(n->in_pmax) >= ntohs(n->in_pmin)) { - n->in_space *= (ntohs(n->in_pmax) - - ntohs(n->in_pmin) + 1); - /* - * Because two different sources can map to - * different destinations but use the same - * local IP#/port #. - * If the result is smaller than in_space, then - * we may have wrapped around 32bits. - */ - i = n->in_inmsk; - if ((i != 0) && (i != 0xffffffff)) { - j = n->in_space * (~ntohl(i) + 1); - if (j >= n->in_space) - n->in_space = j; - else - n->in_space = 0xffffffff; - } - } - /* - * If no protocol is specified, multiple by 256. - */ - if ((n->in_flags & IPN_TCPUDP) == 0) { - j = n->in_space * 256; - if (j >= n->in_space) - n->in_space = j; - else - n->in_space = 0xffffffff; - } - } - /* Otherwise, these fields are preset */ - n = NULL; - nat_stats.ns_rules++; - break; - case SIOCRMNAT : - if (!(mode & FWRITE)) { - error = EPERM; - n = NULL; - break; - } - if (!n) { - error = ESRCH; - break; - } - if (n->in_redir & NAT_REDIRECT) - nat_delrdr(n); - if (n->in_redir & (NAT_MAPBLK|NAT_MAP)) - nat_delnat(n); - if (nat_list == NULL) { - nat_masks = 0; - rdr_masks = 0; - } - *np = n->in_next; - if (!n->in_use) { - if (n->in_apr) - appr_free(n->in_apr); - KFREE(n); - nat_stats.ns_rules--; - } else { - n->in_flags |= IPN_DELETE; - n->in_next = NULL; - } - n = NULL; - break; - case SIOCGNATS : - MUTEX_DOWNGRADE(&ipf_nat); - nat_stats.ns_table[0] = nat_table[0]; - nat_stats.ns_table[1] = nat_table[1]; - nat_stats.ns_list = nat_list; - nat_stats.ns_nattab_sz = ipf_nattable_sz; - nat_stats.ns_rultab_sz = ipf_natrules_sz; - nat_stats.ns_rdrtab_sz = ipf_rdrrules_sz; - nat_stats.ns_instances = nat_instances; - nat_stats.ns_apslist = ap_sess_list; - error = IWCOPYPTR((char *)&nat_stats, (char *)data, - sizeof(nat_stats)); - break; - case SIOCGNATL : - { - natlookup_t nl; - - MUTEX_DOWNGRADE(&ipf_nat); - error = IRCOPYPTR((char *)data, (char *)&nl, sizeof(nl)); - if (error) - break; - - if (nat_lookupredir(&nl)) { - error = IWCOPYPTR((char *)&nl, (char *)data, - sizeof(nl)); - } else - error = ESRCH; - break; - } - case SIOCIPFFL : /* old SIOCFLNAT & SIOCCNATL */ - if (!(mode & FWRITE)) { - error = EPERM; - break; - } - error = 0; - if (arg == 0) - ret = nat_flushtable(); - else if (arg == 1) - ret = nat_clearlist(); - else - error = EINVAL; - MUTEX_DOWNGRADE(&ipf_nat); - if (!error) { - error = IWCOPY((caddr_t)&ret, data, sizeof(ret)); - if (error) - error = EFAULT; - } - break; - case SIOCSTLCK : - error = IRCOPY(data, (caddr_t)&arg, sizeof(arg)); - if (!error) { - error = IWCOPY((caddr_t)&fr_nat_lock, data, - sizeof(fr_nat_lock)); - if (!error) - fr_nat_lock = arg; - } else - error = EFAULT; - break; - case SIOCSTPUT : - if (fr_nat_lock) - error = fr_natputent(data); - else - error = EACCES; - break; - case SIOCSTGSZ : - if (fr_nat_lock) - error = fr_natgetsz(data); - else - error = EACCES; - break; - case SIOCSTGET : - if (fr_nat_lock) - error = fr_natgetent(data); - else - error = EACCES; - break; - case FIONREAD : -#ifdef IPFILTER_LOG - arg = (int)iplused[IPL_LOGNAT]; - MUTEX_DOWNGRADE(&ipf_nat); - error = IWCOPY((caddr_t)&arg, (caddr_t)data, sizeof(arg)); - if (error) - error = EFAULT; -#endif - break; - default : - error = EINVAL; - break; - } - RWLOCK_EXIT(&ipf_nat); /* READ/WRITE */ -done: - if (nt) - KFREE(nt); - return error; -} - - -static int fr_natgetsz(data) -caddr_t data; -{ - ap_session_t *aps; - nat_t *nat, *n; - int error = 0; - natget_t ng; - - error = IRCOPY(data, (caddr_t)&ng, sizeof(ng)); - if (error) - return EFAULT; - - nat = ng.ng_ptr; - if (!nat) { - nat = nat_instances; - ng.ng_sz = 0; - if (nat == NULL) { - error = IWCOPY((caddr_t)&ng, data, sizeof(ng)); - if (error) - error = EFAULT; - return error; - } - } else { - /* - * Make sure the pointer we're copying from exists in the - * current list of entries. Security precaution to prevent - * copying of random kernel data. - */ - for (n = nat_instances; n; n = n->nat_next) - if (n == nat) - break; - if (!n) - return ESRCH; - } - - ng.ng_sz = sizeof(nat_save_t); - aps = nat->nat_aps; - if ((aps != NULL) && (aps->aps_data != 0)) { - ng.ng_sz += sizeof(ap_session_t); - ng.ng_sz += aps->aps_psiz; - } - - error = IWCOPY((caddr_t)&ng, data, sizeof(ng)); - if (error) - error = EFAULT; - return error; -} - - -static int fr_natgetent(data) -caddr_t data; -{ - nat_save_t ipn, *ipnp, *ipnn = NULL; - register nat_t *n, *nat; - ap_session_t *aps; - int error; - - error = IRCOPY(data, (caddr_t)&ipnp, sizeof(ipnp)); - if (error) - return EFAULT; - error = IRCOPY((caddr_t)ipnp, (caddr_t)&ipn, sizeof(ipn)); - if (error) - return EFAULT; - - nat = ipn.ipn_next; - if (!nat) { - nat = nat_instances; - if (nat == NULL) { - if (nat_instances == NULL) - return ENOENT; - return 0; - } - } else { - /* - * Make sure the pointer we're copying from exists in the - * current list of entries. Security precaution to prevent - * copying of random kernel data. - */ - for (n = nat_instances; n; n = n->nat_next) - if (n == nat) - break; - if (!n) - return ESRCH; - } - - ipn.ipn_next = nat->nat_next; - ipn.ipn_dsize = 0; - bcopy((char *)nat, (char *)&ipn.ipn_nat, sizeof(ipn.ipn_nat)); - ipn.ipn_nat.nat_data = NULL; - - if (nat->nat_ptr) { - bcopy((char *)nat->nat_ptr, (char *)&ipn.ipn_ipnat, - sizeof(ipn.ipn_ipnat)); - } - - if (nat->nat_fr) - bcopy((char *)nat->nat_fr, (char *)&ipn.ipn_rule, - sizeof(ipn.ipn_rule)); - - if ((aps = nat->nat_aps)) { - ipn.ipn_dsize = sizeof(*aps); - if (aps->aps_data) - ipn.ipn_dsize += aps->aps_psiz; - KMALLOCS(ipnn, nat_save_t *, sizeof(*ipnn) + ipn.ipn_dsize); - if (ipnn == NULL) - return ENOMEM; - bcopy((char *)&ipn, (char *)ipnn, sizeof(ipn)); - - bcopy((char *)aps, ipnn->ipn_data, sizeof(*aps)); - if (aps->aps_data) { - bcopy(aps->aps_data, ipnn->ipn_data + sizeof(*aps), - aps->aps_psiz); - ipnn->ipn_dsize += aps->aps_psiz; - } - error = IWCOPY((caddr_t)ipnn, ipnp, - sizeof(ipn) + ipn.ipn_dsize); - if (error) - error = EFAULT; - KFREES(ipnn, sizeof(*ipnn) + ipn.ipn_dsize); - } else { - error = IWCOPY((caddr_t)&ipn, ipnp, sizeof(ipn)); - if (error) - error = EFAULT; - } - return error; -} - - -static int fr_natputent(data) -caddr_t data; -{ - nat_save_t ipn, *ipnp, *ipnn = NULL; - register nat_t *n, *nat; - ap_session_t *aps; - frentry_t *fr; - ipnat_t *in; - - int error; - - error = IRCOPY(data, (caddr_t)&ipnp, sizeof(ipnp)); - if (error) - return EFAULT; - error = IRCOPY((caddr_t)ipnp, (caddr_t)&ipn, sizeof(ipn)); - if (error) - return EFAULT; - nat = NULL; - if (ipn.ipn_dsize) { - KMALLOCS(ipnn, nat_save_t *, sizeof(ipn) + ipn.ipn_dsize); - if (ipnn == NULL) - return ENOMEM; - bcopy((char *)&ipn, (char *)ipnn, sizeof(ipn)); - error = IRCOPY((caddr_t)ipnp, (caddr_t)ipn.ipn_data, - ipn.ipn_dsize); - if (error) { - error = EFAULT; - goto junkput; - } - } else - ipnn = NULL; - - KMALLOC(nat, nat_t *); - if (nat == NULL) { - error = EFAULT; - goto junkput; - } - - bcopy((char *)&ipn.ipn_nat, (char *)nat, sizeof(*nat)); - /* - * Initialize all these so that nat_delete() doesn't cause a crash. - */ - nat->nat_phnext[0] = NULL; - nat->nat_phnext[1] = NULL; - fr = nat->nat_fr; - nat->nat_fr = NULL; - aps = nat->nat_aps; - nat->nat_aps = NULL; - in = nat->nat_ptr; - nat->nat_ptr = NULL; - nat->nat_data = NULL; - - /* - * Restore the rule associated with this nat session - */ - if (in) { - KMALLOC(in, ipnat_t *); - if (in == NULL) { - error = ENOMEM; - goto junkput; - } - nat->nat_ptr = in; - bcopy((char *)&ipn.ipn_ipnat, (char *)in, sizeof(*in)); - in->in_use = 1; - in->in_flags |= IPN_DELETE; - in->in_next = NULL; - in->in_rnext = NULL; - in->in_prnext = NULL; - in->in_mnext = NULL; - in->in_pmnext = NULL; - in->in_ifp = GETUNIT(in->in_ifname, 4); - if (in->in_plabel[0] != '\0') { - in->in_apr = appr_match(in->in_p, in->in_plabel); - } - } - - /* - * Restore ap_session_t structure. Include the private data allocated - * if it was there. - */ - if (aps) { - KMALLOC(aps, ap_session_t *); - if (aps == NULL) { - error = ENOMEM; - goto junkput; - } - nat->nat_aps = aps; - aps->aps_next = ap_sess_list; - ap_sess_list = aps; - bcopy(ipnn->ipn_data, (char *)aps, sizeof(*aps)); - if (in) - aps->aps_apr = in->in_apr; - if (aps->aps_psiz) { - KMALLOCS(aps->aps_data, void *, aps->aps_psiz); - if (aps->aps_data == NULL) { - error = ENOMEM; - goto junkput; - } - bcopy(ipnn->ipn_data + sizeof(*aps), aps->aps_data, - aps->aps_psiz); - } else { - aps->aps_psiz = 0; - aps->aps_data = NULL; - } - } - - /* - * If there was a filtering rule associated with this entry then - * build up a new one. - */ - if (fr != NULL) { - if (nat->nat_flags & FI_NEWFR) { - KMALLOC(fr, frentry_t *); - nat->nat_fr = fr; - if (fr == NULL) { - error = ENOMEM; - goto junkput; - } - bcopy((char *)&ipn.ipn_fr, (char *)fr, sizeof(*fr)); - ipn.ipn_nat.nat_fr = fr; - error = IWCOPY((caddr_t)&ipn, ipnp, sizeof(ipn)); - if (error) { - error = EFAULT; - goto junkput; - } - } else { - for (n = nat_instances; n; n = n->nat_next) - if (n->nat_fr == fr) - break; - if (!n) { - error = ESRCH; - goto junkput; - } - } - } - - if (ipnn) - KFREES(ipnn, sizeof(ipn) + ipn.ipn_dsize); - nat_insert(nat); - return 0; -junkput: - if (ipnn) - KFREES(ipnn, sizeof(ipn) + ipn.ipn_dsize); - if (nat) - nat_delete(nat); - return error; -} - - -/* - * Delete a nat entry from the various lists and table. - */ -static void nat_delete(natd) -struct nat *natd; -{ - struct ipnat *ipn; - - if (natd->nat_flags & FI_WILDP) - nat_stats.ns_wilds--; - if (natd->nat_hnext[0]) - natd->nat_hnext[0]->nat_phnext[0] = natd->nat_phnext[0]; - *natd->nat_phnext[0] = natd->nat_hnext[0]; - if (natd->nat_hnext[1]) - natd->nat_hnext[1]->nat_phnext[1] = natd->nat_phnext[1]; - *natd->nat_phnext[1] = natd->nat_hnext[1]; - - if (natd->nat_fr != NULL) { - ATOMIC_DEC32(natd->nat_fr->fr_ref); - } - - if (natd->nat_hm != NULL) - nat_hostmapdel(natd->nat_hm); - - /* - * If there is an active reference from the nat entry to its parent - * rule, decrement the rule's reference count and free it too if no - * longer being used. - */ - ipn = natd->nat_ptr; - if (ipn != NULL) { - ipn->in_space++; - ipn->in_use--; - if (!ipn->in_use && (ipn->in_flags & IPN_DELETE)) { - if (ipn->in_apr) - appr_free(ipn->in_apr); - KFREE(ipn); - nat_stats.ns_rules--; - } - } - - MUTEX_DESTROY(&natd->nat_lock); - /* - * If there's a fragment table entry too for this nat entry, then - * dereference that as well. - */ - ipfr_forget((void *)natd); - aps_free(natd->nat_aps); - nat_stats.ns_inuse--; - KFREE(natd); -} - - -/* - * nat_flushtable - clear the NAT table of all mapping entries. - */ -static int nat_flushtable() -{ - register nat_t *nat, **natp; - register int j = 0; - - /* - * ALL NAT mappings deleted, so lets just make the deletions - * quicker. - */ - if (nat_table[0] != NULL) - bzero((char *)nat_table[0], - sizeof(nat_table[0]) * ipf_nattable_sz); - if (nat_table[1] != NULL) - bzero((char *)nat_table[1], - sizeof(nat_table[1]) * ipf_nattable_sz); - - for (natp = &nat_instances; (nat = *natp); ) { - *natp = nat->nat_next; -#ifdef IPFILTER_LOG - nat_log(nat, NL_FLUSH); -#endif - nat_delete(nat); - j++; - } - nat_stats.ns_inuse = 0; - return j; -} - - -/* - * nat_clearlist - delete all rules in the active NAT mapping list. - */ -static int nat_clearlist() -{ - register ipnat_t *n, **np = &nat_list; - int i = 0; - - if (nat_rules != NULL) - bzero((char *)nat_rules, sizeof(*nat_rules) * ipf_natrules_sz); - if (rdr_rules != NULL) - bzero((char *)rdr_rules, sizeof(*rdr_rules) * ipf_rdrrules_sz); - - while ((n = *np)) { - *np = n->in_next; - if (!n->in_use) { - if (n->in_apr) - appr_free(n->in_apr); - KFREE(n); - nat_stats.ns_rules--; - } else { - n->in_flags |= IPN_DELETE; - n->in_next = NULL; - } - i++; - } - nat_masks = 0; - rdr_masks = 0; - return i; -} - - -/* - * Create a new NAT table entry. - * NOTE: assumes write lock on ipf_nat has been obtained already. - */ -nat_t *nat_new(np, ip, fin, flags, direction) -ipnat_t *np; -ip_t *ip; -fr_info_t *fin; -u_int flags; -int direction; -{ - register u_32_t sum1, sum2, sumd, l; - u_short port = 0, sport = 0, dport = 0, nport = 0; - struct in_addr in, inb; - tcphdr_t *tcp = NULL; - hostmap_t *hm = NULL; - nat_t *nat, *natl; - u_short nflags; -#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) - qif_t *qf = fin->fin_qif; -#endif - - nflags = flags & np->in_flags; - if (flags & IPN_TCPUDP) { - tcp = (tcphdr_t *)fin->fin_dp; - sport = tcp->th_sport; - dport = tcp->th_dport; - } - - /* Give me a new nat */ - KMALLOC(nat, nat_t *); - if (nat == NULL) { - nat_stats.ns_memfail++; - return NULL; - } - - bzero((char *)nat, sizeof(*nat)); - nat->nat_flags = flags; - if (flags & FI_WILDP) - nat_stats.ns_wilds++; - /* - * Search the current table for a match. - */ - if (direction == NAT_OUTBOUND) { - /* - * Values at which the search for a free resouce starts. - */ - u_32_t st_ip; - u_short st_port; - - /* - * If it's an outbound packet which doesn't match any existing - * record, then create a new port - */ - l = 0; - st_ip = np->in_nip; - st_port = np->in_pnext; - - do { - port = 0; - in.s_addr = htonl(np->in_nip); - if (l == 0) { - /* - * Check to see if there is an existing NAT - * setup for this IP address pair. - */ - hm = nat_hostmap(np, ip->ip_src, in); - if (hm != NULL) - in.s_addr = hm->hm_mapip.s_addr; - } else if ((l == 1) && (hm != NULL)) { - nat_hostmapdel(hm); - hm = NULL; - } - in.s_addr = ntohl(in.s_addr); - - nat->nat_hm = hm; - - if ((np->in_outmsk == 0xffffffff) && - (np->in_pnext == 0)) { - if (l > 0) - goto badnat; - } - - if (np->in_redir & NAT_MAPBLK) { - if ((l >= np->in_ppip) || ((l > 0) && - !(flags & IPN_TCPUDP))) - goto badnat; - /* - * map-block - Calculate destination address. - */ - in.s_addr = ntohl(ip->ip_src.s_addr); - in.s_addr &= ntohl(~np->in_inmsk); - inb.s_addr = in.s_addr; - in.s_addr /= np->in_ippip; - in.s_addr &= ntohl(~np->in_outmsk); - in.s_addr += ntohl(np->in_outip); - /* - * Calculate destination port. - */ - if ((flags & IPN_TCPUDP) && - (np->in_ppip != 0)) { - port = ntohs(sport) + l; - port %= np->in_ppip; - port += np->in_ppip * - (inb.s_addr % np->in_ippip); - port += MAPBLK_MINPORT; - port = htons(port); - } - } else if (!np->in_outip && - (np->in_outmsk == 0xffffffff)) { - /* - * 0/32 - use the interface's IP address. - */ - if ((l > 0) || - fr_ifpaddr(4, fin->fin_ifp, &in) == -1) - goto badnat; - in.s_addr = ntohl(in.s_addr); - } else if (!np->in_outip && !np->in_outmsk) { - /* - * 0/0 - use the original source address/port. - */ - if (l > 0) - goto badnat; - in.s_addr = ntohl(ip->ip_src.s_addr); - } else if ((np->in_outmsk != 0xffffffff) && - (np->in_pnext == 0) && - ((l > 0) || (hm == NULL))) - np->in_nip++; - natl = NULL; - - if ((nflags & IPN_TCPUDP) && - ((np->in_redir & NAT_MAPBLK) == 0) && - (np->in_flags & IPN_AUTOPORTMAP)) { - if ((l > 0) && (l % np->in_ppip == 0)) { - if (l > np->in_space) { - goto badnat; - } else if ((l > np->in_ppip) && - np->in_outmsk != 0xffffffff) - np->in_nip++; - } - if (np->in_ppip != 0) { - port = ntohs(sport); - port += (l % np->in_ppip); - port %= np->in_ppip; - port += np->in_ppip * - (ntohl(ip->ip_src.s_addr) % - np->in_ippip); - port += MAPBLK_MINPORT; - port = htons(port); - } - } else if (((np->in_redir & NAT_MAPBLK) == 0) && - (nflags & IPN_TCPUDP) && - (np->in_pnext != 0)) { - port = htons(np->in_pnext++); - if (np->in_pnext > ntohs(np->in_pmax)) { - np->in_pnext = ntohs(np->in_pmin); - if (np->in_outmsk != 0xffffffff) - np->in_nip++; - } - } - - if (np->in_flags & IPN_IPRANGE) { - if (np->in_nip > ntohl(np->in_outmsk)) - np->in_nip = ntohl(np->in_outip); - } else { - if ((np->in_outmsk != 0xffffffff) && - ((np->in_nip + 1) & ntohl(np->in_outmsk)) > - ntohl(np->in_outip)) - np->in_nip = ntohl(np->in_outip) + 1; - } - - if (!port && (flags & IPN_TCPUDP)) - port = sport; - - /* - * Here we do a lookup of the connection as seen from - * the outside. If an IP# pair already exists, try - * again. So if you have A->B becomes C->B, you can - * also have D->E become C->E but not D->B causing - * another C->B. Also take protocol and ports into - * account when determining whether a pre-existing - * NAT setup will cause an external conflict where - * this is appropriate. - */ - inb.s_addr = htonl(in.s_addr); - natl = nat_inlookup(fin->fin_ifp, flags & ~FI_WILDP, - (u_int)ip->ip_p, ip->ip_dst, inb, - (port << 16) | dport, 1); - - /* - * Has the search wrapped around and come back to the - * start ? - */ - if ((natl != NULL) && - (np->in_pnext != 0) && (st_port == np->in_pnext) && - (np->in_nip != 0) && (st_ip == np->in_nip)) - goto badnat; - l++; - } while (natl != NULL); - - if (np->in_space > 0) - np->in_space--; - - /* Setup the NAT table */ - nat->nat_inip = ip->ip_src; - nat->nat_outip.s_addr = htonl(in.s_addr); - nat->nat_oip = ip->ip_dst; - if (nat->nat_hm == NULL) - nat->nat_hm = nat_hostmap(np, ip->ip_src, - nat->nat_outip); - - sum1 = LONG_SUM(ntohl(ip->ip_src.s_addr)) + ntohs(sport); - sum2 = LONG_SUM(in.s_addr) + ntohs(port); - - if (flags & IPN_TCPUDP) { - nat->nat_inport = sport; - nat->nat_outport = port; /* sport */ - nat->nat_oport = dport; - } - } else { - /* - * Otherwise, it's an inbound packet. Most likely, we don't - * want to rewrite source ports and source addresses. Instead, - * we want to rewrite to a fixed internal address and fixed - * internal port. - */ - if (np->in_flags & IPN_SPLIT) { - in.s_addr = np->in_nip; - if (np->in_inip == htonl(in.s_addr)) - np->in_nip = ntohl(np->in_inmsk); - else { - np->in_nip = ntohl(np->in_inip); - if (np->in_flags & IPN_ROUNDR) { - nat_delrdr(np); - nat_addrdr(np); - } - } - } else { - in.s_addr = ntohl(np->in_inip); - if (np->in_flags & IPN_ROUNDR) { - nat_delrdr(np); - nat_addrdr(np); - } - } - if (!np->in_pnext) - nport = dport; - else { - /* - * Whilst not optimized for the case where - * pmin == pmax, the gain is not significant. - */ - nport = ntohs(dport) - ntohs(np->in_pmin) + - ntohs(np->in_pnext); - nport = htons(nport); - } - - /* - * When the redirect-to address is set to 0.0.0.0, just - * assume a blank `forwarding' of the packet. We don't - * setup any translation for this either. - */ - if (in.s_addr == 0) { - if (nport == dport) - goto badnat; - in.s_addr = ntohl(ip->ip_dst.s_addr); - } - - nat->nat_inip.s_addr = htonl(in.s_addr); - nat->nat_outip = ip->ip_dst; - nat->nat_oip = ip->ip_src; - - sum1 = LONG_SUM(ntohl(ip->ip_dst.s_addr)) + ntohs(dport); - sum2 = LONG_SUM(in.s_addr) + ntohs(nport); - - if (flags & IPN_TCPUDP) { - nat->nat_inport = nport; - nat->nat_outport = dport; - nat->nat_oport = sport; - } - } - - CALC_SUMD(sum1, sum2, sumd); - nat->nat_sumd[0] = (sumd & 0xffff) + (sumd >> 16); -#if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) - if ((flags == IPN_TCP) && dohwcksum && - (qf->qf_ill->ill_ick.ick_magic == ICK_M_CTL_MAGIC)) { - if (direction == NAT_OUTBOUND) - sum1 = LONG_SUM(ntohl(in.s_addr)); - else - sum1 = LONG_SUM(ntohl(ip->ip_src.s_addr)); - sum1 += LONG_SUM(ntohl(ip->ip_dst.s_addr)); - sum1 += 30; - sum1 = (sum1 & 0xffff) + (sum1 >> 16); - nat->nat_sumd[1] = NAT_HW_CKSUM|(sum1 & 0xffff); - } else -#endif - nat->nat_sumd[1] = nat->nat_sumd[0]; - - if ((flags & IPN_TCPUDP) && ((sport != port) || (dport != nport))) { - if (direction == NAT_OUTBOUND) - sum1 = LONG_SUM(ntohl(ip->ip_src.s_addr)); - else - sum1 = LONG_SUM(ntohl(ip->ip_dst.s_addr)); - - sum2 = LONG_SUM(in.s_addr); - - CALC_SUMD(sum1, sum2, sumd); - nat->nat_ipsumd = (sumd & 0xffff) + (sumd >> 16); - } else - nat->nat_ipsumd = nat->nat_sumd[0]; - - in.s_addr = htonl(in.s_addr); - -#ifdef _KERNEL - strncpy(nat->nat_ifname, IFNAME(fin->fin_ifp), IFNAMSIZ); -#endif - nat_insert(nat); - - nat->nat_dir = direction; - nat->nat_ifp = fin->fin_ifp; - nat->nat_ptr = np; - nat->nat_p = ip->ip_p; - nat->nat_bytes = 0; - nat->nat_pkts = 0; - nat->nat_fr = fin->fin_fr; - if (nat->nat_fr != NULL) { - ATOMIC_INC32(nat->nat_fr->fr_ref); - } - if (direction == NAT_OUTBOUND) { - if (flags & IPN_TCPUDP) - tcp->th_sport = port; - } else { - if (flags & IPN_TCPUDP) - tcp->th_dport = nport; - } - np->in_use++; -#ifdef IPFILTER_LOG - nat_log(nat, (u_int)np->in_redir); -#endif - return nat; -badnat: - nat_stats.ns_badnat++; - if ((hm = nat->nat_hm) != NULL) - nat_hostmapdel(hm); - KFREE(nat); - return NULL; -} - - -void nat_insert(nat) -nat_t *nat; -{ - nat_t **natp; - u_int hv; - - MUTEX_INIT(&nat->nat_lock, "nat entry lock", NULL); - - nat->nat_age = fr_defnatage; - nat->nat_ifname[sizeof(nat->nat_ifname) - 1] = '\0'; - if (nat->nat_ifname[0] !='\0') { - nat->nat_ifp = GETUNIT(nat->nat_ifname, 4); - } - - nat->nat_next = nat_instances; - nat_instances = nat; - - hv = NAT_HASH_FN(nat->nat_inip.s_addr, nat->nat_inport, - ipf_nattable_sz); - natp = &nat_table[0][hv]; - if (*natp) - (*natp)->nat_phnext[0] = &nat->nat_hnext[0]; - nat->nat_phnext[0] = natp; - nat->nat_hnext[0] = *natp; - *natp = nat; - - hv = NAT_HASH_FN(nat->nat_outip.s_addr, nat->nat_outport, - ipf_nattable_sz); - natp = &nat_table[1][hv]; - if (*natp) - (*natp)->nat_phnext[1] = &nat->nat_hnext[1]; - nat->nat_phnext[1] = natp; - nat->nat_hnext[1] = *natp; - *natp = nat; - - nat_stats.ns_added++; - nat_stats.ns_inuse++; -} - - -nat_t *nat_icmplookup(ip, fin, dir) -ip_t *ip; -fr_info_t *fin; -int dir; -{ - icmphdr_t *icmp; - tcphdr_t *tcp = NULL; - ip_t *oip; - int flags = 0, type, minlen; - - icmp = (icmphdr_t *)fin->fin_dp; - /* - * Does it at least have the return (basic) IP header ? - * Only a basic IP header (no options) should be with an ICMP error - * header. - */ - if ((ip->ip_hl != 5) || (ip->ip_len < ICMPERR_MINPKTLEN)) - return NULL; - type = icmp->icmp_type; - /* - * If it's not an error type, then return. - */ - if ((type != ICMP_UNREACH) && (type != ICMP_SOURCEQUENCH) && - (type != ICMP_REDIRECT) && (type != ICMP_TIMXCEED) && - (type != ICMP_PARAMPROB)) - return NULL; - - oip = (ip_t *)((char *)fin->fin_dp + 8); - minlen = (oip->ip_hl << 2); - if (minlen < sizeof(ip_t)) - return NULL; - if (ip->ip_len < ICMPERR_IPICMPHLEN + minlen) - return NULL; - /* - * Is the buffer big enough for all of it ? It's the size of the IP - * header claimed in the encapsulated part which is of concern. It - * may be too big to be in this buffer but not so big that it's - * outside the ICMP packet, leading to TCP deref's causing problems. - * This is possible because we don't know how big oip_hl is when we - * do the pullup early in fr_check() and thus can't gaurantee it is - * all here now. - */ -#ifdef _KERNEL - { - mb_t *m; - -# if SOLARIS - m = fin->fin_qfm; - if ((char *)oip + fin->fin_dlen - ICMPERR_ICMPHLEN > (char *)m->b_wptr) - return NULL; -# else - m = *(mb_t **)fin->fin_mp; - if ((char *)oip + fin->fin_dlen - ICMPERR_ICMPHLEN > - (char *)ip + m->m_len) - return NULL; -# endif - } -#endif - - if (oip->ip_p == IPPROTO_TCP) - flags = IPN_TCP; - else if (oip->ip_p == IPPROTO_UDP) - flags = IPN_UDP; - if (flags & IPN_TCPUDP) { - minlen += 8; /* + 64bits of data to get ports */ - if (ip->ip_len < ICMPERR_IPICMPHLEN + minlen) - return NULL; - tcp = (tcphdr_t *)((char *)oip + (oip->ip_hl << 2)); - if (dir == NAT_INBOUND) - return nat_inlookup(fin->fin_ifp, flags, - (u_int)oip->ip_p, oip->ip_dst, oip->ip_src, - (tcp->th_sport << 16) | tcp->th_dport, 0); - else - return nat_outlookup(fin->fin_ifp, flags, - (u_int)oip->ip_p, oip->ip_dst, oip->ip_src, - (tcp->th_sport << 16) | tcp->th_dport, 0); - } - if (dir == NAT_INBOUND) - return nat_inlookup(fin->fin_ifp, 0, (u_int)oip->ip_p, - oip->ip_dst, oip->ip_src, 0, 0); - else - return nat_outlookup(fin->fin_ifp, 0, (u_int)oip->ip_p, - oip->ip_dst, oip->ip_src, 0, 0); -} - - -/* - * This should *ONLY* be used for incoming packets to make sure a NAT'd ICMP - * packet gets correctly recognised. - */ -nat_t *nat_icmp(ip, fin, nflags, dir) -ip_t *ip; -fr_info_t *fin; -u_int *nflags; -int dir; -{ - u_32_t sum1, sum2, sumd, sumd2 = 0; - struct in_addr in; - icmphdr_t *icmp; - udphdr_t *udp; - nat_t *nat; - ip_t *oip; - int flags = 0; - - if ((fin->fin_fi.fi_fl & FI_SHORT) || (ip->ip_off & IP_OFFMASK)) - return NULL; - /* - * nat_icmplookup() will return NULL for `defective' packets. - */ - if ((ip->ip_v != 4) || !(nat = nat_icmplookup(ip, fin, dir))) - return NULL; - *nflags = IPN_ICMPERR; - icmp = (icmphdr_t *)fin->fin_dp; - oip = (ip_t *)&icmp->icmp_ip; - if (oip->ip_p == IPPROTO_TCP) - flags = IPN_TCP; - else if (oip->ip_p == IPPROTO_UDP) - flags = IPN_UDP; - udp = (udphdr_t *)((((char *)oip) + (oip->ip_hl << 2))); - /* - * Need to adjust ICMP header to include the real IP#'s and - * port #'s. Only apply a checksum change relative to the - * IP address change as it will be modified again in ip_natout - * for both address and port. Two checksum changes are - * necessary for the two header address changes. Be careful - * to only modify the checksum once for the port # and twice - * for the IP#. - */ - - /* - * Step 1 - * Fix the IP addresses in the offending IP packet. You also need - * to adjust the IP header checksum of that offending IP packet - * and the ICMP checksum of the ICMP error message itself. - * - * Unfortunately, for UDP and TCP, the IP addresses are also contained - * in the pseudo header that is used to compute the UDP resp. TCP - * checksum. So, we must compensate that as well. Even worse, the - * change in the UDP and TCP checksums require yet another - * adjustment of the ICMP checksum of the ICMP error message. - * - * For the moment we forget about TCP, because that checksum is not - * in the first 8 bytes, so it will not be available in most cases. - */ - - if (oip->ip_dst.s_addr == nat->nat_oip.s_addr) { - sum1 = LONG_SUM(ntohl(oip->ip_src.s_addr)); - in = nat->nat_inip; - oip->ip_src = in; - } else { - sum1 = LONG_SUM(ntohl(oip->ip_dst.s_addr)); - in = nat->nat_outip; - oip->ip_dst = in; - } - - sum2 = LONG_SUM(ntohl(in.s_addr)); - - CALC_SUMD(sum1, sum2, sumd); - - if (nat->nat_dir == NAT_OUTBOUND) { - /* - * Fix IP checksum of the offending IP packet to adjust for - * the change in the IP address. - * - * Normally, you would expect that the ICMP checksum of the - * ICMP error message needs to be adjusted as well for the - * IP address change in oip. - * However, this is a NOP, because the ICMP checksum is - * calculated over the complete ICMP packet, which includes the - * changed oip IP addresses and oip->ip_sum. However, these - * two changes cancel each other out (if the delta for - * the IP address is x, then the delta for ip_sum is minus x), - * so no change in the icmp_cksum is necessary. - * - * Be careful that nat_dir refers to the direction of the - * offending IP packet (oip), not to its ICMP response (icmp) - */ - fix_datacksum(&oip->ip_sum, sumd); - - /* - * Fix UDP pseudo header checksum to compensate for the - * IP address change. - */ - if (oip->ip_p == IPPROTO_UDP && udp->uh_sum) { - /* - * The UDP checksum is optional, only adjust it - * if it has been set. - */ - sum1 = ntohs(udp->uh_sum); - fix_datacksum(&udp->uh_sum, sumd); - sum2 = ntohs(udp->uh_sum); - - /* - * Fix ICMP checksum to compensate the UDP - * checksum adjustment. - */ - CALC_SUMD(sum1, sum2, sumd); - sumd2 = sumd; - } - -#if 0 - /* - * Fix TCP pseudo header checksum to compensate for the - * IP address change. Before we can do the change, we - * must make sure that oip is sufficient large to hold - * the TCP checksum (normally it does not!). - */ - if (oip->ip_p == IPPROTO_TCP) { - - } -#endif - } else { - - /* - * Fix IP checksum of the offending IP packet to adjust for - * the change in the IP address. - * - * Normally, you would expect that the ICMP checksum of the - * ICMP error message needs to be adjusted as well for the - * IP address change in oip. - * However, this is a NOP, because the ICMP checksum is - * calculated over the complete ICMP packet, which includes the - * changed oip IP addresses and oip->ip_sum. However, these - * two changes cancel each other out (if the delta for - * the IP address is x, then the delta for ip_sum is minus x), - * so no change in the icmp_cksum is necessary. - * - * Be careful that nat_dir refers to the direction of the - * offending IP packet (oip), not to its ICMP response (icmp) - */ - fix_datacksum(&oip->ip_sum, sumd); - -/* XXX FV : without having looked at Solaris source code, it seems unlikely - * that SOLARIS would compensate this in the kernel (a body of an IP packet - * in the data section of an ICMP packet). I have the feeling that this should - * be unconditional, but I'm not in a position to check. - */ -#if !SOLARIS && !defined(__sgi) - /* - * Fix UDP pseudo header checksum to compensate for the - * IP address change. - */ - if (oip->ip_p == IPPROTO_UDP && udp->uh_sum) { - /* - * The UDP checksum is optional, only adjust it - * if it has been set - */ - sum1 = ntohs(udp->uh_sum); - fix_datacksum(&udp->uh_sum, sumd); - sum2 = ntohs(udp->uh_sum); - - /* - * Fix ICMP checksum to compensate the UDP - * checksum adjustment. - */ - CALC_SUMD(sum1, sum2, sumd); - sumd2 = sumd; - } - -#if 0 - /* - * Fix TCP pseudo header checksum to compensate for the - * IP address change. Before we can do the change, we - * must make sure that oip is sufficient large to hold - * the TCP checksum (normally it does not!). - */ - if (oip->ip_p == IPPROTO_TCP) { - - }; -#endif - -#endif - } - - if ((flags & IPN_TCPUDP) != 0) { - tcphdr_t *tcp; - - /* - * XXX - what if this is bogus hl and we go off the end ? - * In this case, nat_icmpinlookup() will have returned NULL. - */ - tcp = (tcphdr_t *)udp; - - /* - * Step 2 : - * For offending TCP/UDP IP packets, translate the ports as - * well, based on the NAT specification. Of course such - * a change must be reflected in the ICMP checksum as well. - * - * Advance notice : Now it becomes complicated :-) - * - * Since the port fields are part of the TCP/UDP checksum - * of the offending IP packet, you need to adjust that checksum - * as well... but, if you change, you must change the icmp - * checksum *again*, to reflect that change. - * - * To further complicate: the TCP checksum is not in the first - * 8 bytes of the offending ip packet, so it most likely is not - * available (we might have to fix that if the encounter a - * device that returns more than 8 data bytes on icmp error) - */ - - if (nat->nat_oport == tcp->th_dport) { - if (tcp->th_sport != nat->nat_inport) { - /* - * Fix ICMP checksum to compensate port - * adjustment. - */ - sum1 = ntohs(tcp->th_sport); - sum2 = ntohs(nat->nat_inport); - CALC_SUMD(sum1, sum2, sumd); - sumd2 += sumd; - tcp->th_sport = nat->nat_inport; - - /* - * Fix udp checksum to compensate port - * adjustment. NOTE : the offending IP packet - * flows the other direction compared to the - * ICMP message. - * - * The UDP checksum is optional, only adjust - * it if it has been set. - */ - if (oip->ip_p == IPPROTO_UDP && udp->uh_sum) { - - sum1 = ntohs(udp->uh_sum); - fix_datacksum(&udp->uh_sum, sumd); - sum2 = ntohs(udp->uh_sum); - - /* - * Fix ICMP checksum to - * compensate UDP checksum - * adjustment. - */ - CALC_SUMD(sum1, sum2, sumd); - sumd2 += sumd; - } - } - } else { - if (tcp->th_dport != nat->nat_outport) { - /* - * Fix ICMP checksum to compensate port - * adjustment. - */ - sum1 = ntohs(tcp->th_dport); - sum2 = ntohs(nat->nat_outport); - CALC_SUMD(sum1, sum2, sumd); - sumd2 += sumd; - tcp->th_dport = nat->nat_outport; - - /* - * Fix udp checksum to compensate port - * adjustment. NOTE : the offending IP - * packet flows the other direction compared - * to the ICMP message. - * - * The UDP checksum is optional, only adjust - * it if it has been set. - */ - if (oip->ip_p == IPPROTO_UDP && udp->uh_sum) { - - sum1 = ntohs(udp->uh_sum); - fix_datacksum(&udp->uh_sum, sumd); - sum2 = ntohs(udp->uh_sum); - - /* - * Fix ICMP checksum to compensate - * UDP checksum adjustment. - */ - CALC_SUMD(sum1, sum2, sumd); - sumd2 += sumd; - } - } - } - if (sumd2) { - sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16); - sumd2 = (sumd2 & 0xffff) + (sumd2 >> 16); - if (nat->nat_dir == NAT_OUTBOUND) { - fix_outcksum(&icmp->icmp_cksum, sumd2); - } else { - fix_incksum(&icmp->icmp_cksum, sumd2); - } - } - } - nat->nat_age = fr_defnaticmpage; - return nat; -} - - -/* - * NB: these lookups don't lock access to the list, it assume it has already - * been done! - */ -/* - * Lookup a nat entry based on the mapped destination ip address/port and - * real source address/port. We use this lookup when receiving a packet, - * we're looking for a table entry, based on the destination address. - * NOTE: THE PACKET BEING CHECKED (IF FOUND) HAS A MAPPING ALREADY. - */ -nat_t *nat_inlookup(ifp, flags, p, src, mapdst, ports, rw) -void *ifp; -register u_int flags, p; -struct in_addr src , mapdst; -u_32_t ports; -int rw; -{ - register u_short sport, dport; - register nat_t *nat; - register int nflags; - register u_32_t dst; - u_int hv; - - dst = mapdst.s_addr; - dport = ports >> 16; - sport = ports & 0xffff; - flags &= IPN_TCPUDP; - - hv = NAT_HASH_FN(dst, dport, ipf_nattable_sz); - nat = nat_table[1][hv]; - for (; nat; nat = nat->nat_hnext[1]) { - nflags = nat->nat_flags; - if ((!ifp || ifp == nat->nat_ifp) && - nat->nat_oip.s_addr == src.s_addr && - nat->nat_outip.s_addr == dst && - (((p == 0) && (flags == (nat->nat_flags & IPN_TCPUDP))) - || (p == nat->nat_p)) && (!flags || - (((nat->nat_oport == sport) || (nflags & FI_W_DPORT)) && - ((nat->nat_outport == dport) || (nflags & FI_W_SPORT))))) - return nat; - } - if (!nat_stats.ns_wilds || !(flags & IPN_TCPUDP)) - return NULL; - if (!rw) { - RWLOCK_EXIT(&ipf_nat); - } - hv = NAT_HASH_FN(dst, 0, ipf_nattable_sz); - if (!rw) { - WRITE_ENTER(&ipf_nat); - } - nat = nat_table[1][hv]; - for (; nat; nat = nat->nat_hnext[1]) { - nflags = nat->nat_flags; - if (ifp && ifp != nat->nat_ifp) - continue; - if (!(nflags & IPN_TCPUDP)) - continue; - if (!(nflags & FI_WILDP)) - continue; - if (nat->nat_oip.s_addr != src.s_addr || - nat->nat_outip.s_addr != dst) - continue; - if (((nat->nat_oport == sport) || (nflags & FI_W_DPORT)) && - ((nat->nat_outport == dport) || (nflags & FI_W_SPORT))) { - nat_tabmove(nat, ports); - break; - } - } - if (!rw) { - MUTEX_DOWNGRADE(&ipf_nat); - } - return nat; -} - - -/* - * This function is only called for TCP/UDP NAT table entries where the - * original was placed in the table without hashing on the ports and we now - * want to include hashing on port numbers. - */ -static void nat_tabmove(nat, ports) -nat_t *nat; -u_32_t ports; -{ - register u_short sport, dport; - nat_t **natp; - u_int hv; - - dport = ports >> 16; - sport = ports & 0xffff; - - if (nat->nat_oport == dport) { - nat->nat_inport = sport; - nat->nat_outport = sport; - } - - /* - * Remove the NAT entry from the old location - */ - if (nat->nat_hnext[0]) - nat->nat_hnext[0]->nat_phnext[0] = nat->nat_phnext[0]; - *nat->nat_phnext[0] = nat->nat_hnext[0]; - - if (nat->nat_hnext[1]) - nat->nat_hnext[1]->nat_phnext[1] = nat->nat_phnext[1]; - *nat->nat_phnext[1] = nat->nat_hnext[1]; - - /* - * Add into the NAT table in the new position - */ - hv = NAT_HASH_FN(nat->nat_inip.s_addr, sport, ipf_nattable_sz); - natp = &nat_table[0][hv]; - if (*natp) - (*natp)->nat_phnext[0] = &nat->nat_hnext[0]; - nat->nat_phnext[0] = natp; - nat->nat_hnext[0] = *natp; - *natp = nat; - - hv = NAT_HASH_FN(nat->nat_outip.s_addr, sport, ipf_nattable_sz); - natp = &nat_table[1][hv]; - if (*natp) - (*natp)->nat_phnext[1] = &nat->nat_hnext[1]; - nat->nat_phnext[1] = natp; - nat->nat_hnext[1] = *natp; - *natp = nat; -} - - -/* - * Lookup a nat entry based on the source 'real' ip address/port and - * destination address/port. We use this lookup when sending a packet out, - * we're looking for a table entry, based on the source address. - * NOTE: THE PACKET BEING CHECKED (IF FOUND) HAS A MAPPING ALREADY. - */ -nat_t *nat_outlookup(ifp, flags, p, src, dst, ports, rw) -void *ifp; -register u_int flags, p; -struct in_addr src , dst; -u_32_t ports; -int rw; -{ - register u_short sport, dport; - register nat_t *nat; - register int nflags; - u_32_t srcip; - u_int hv; - - sport = ports & 0xffff; - dport = ports >> 16; - flags &= IPN_TCPUDP; - srcip = src.s_addr; - - hv = NAT_HASH_FN(srcip, sport, ipf_nattable_sz); - nat = nat_table[0][hv]; - for (; nat; nat = nat->nat_hnext[0]) { - nflags = nat->nat_flags; - - if ((!ifp || ifp == nat->nat_ifp) && - nat->nat_inip.s_addr == srcip && - nat->nat_oip.s_addr == dst.s_addr && - (((p == 0) && (flags == (nflags & IPN_TCPUDP))) - || (p == nat->nat_p)) && (!flags || - ((nat->nat_inport == sport || nflags & FI_W_SPORT) && - (nat->nat_oport == dport || nflags & FI_W_DPORT)))) - return nat; - } - if (!nat_stats.ns_wilds || !(flags & IPN_TCPUDP)) - return NULL; - if (!rw) { - RWLOCK_EXIT(&ipf_nat); - } - hv = NAT_HASH_FN(srcip, 0, ipf_nattable_sz); - if (!rw) { - WRITE_ENTER(&ipf_nat); - } - nat = nat_table[0][hv]; - for (; nat; nat = nat->nat_hnext[0]) { - nflags = nat->nat_flags; - if (ifp && ifp != nat->nat_ifp) - continue; - if (!(nflags & IPN_TCPUDP)) - continue; - if (!(nflags & FI_WILDP)) - continue; - if ((nat->nat_inip.s_addr != srcip) || - (nat->nat_oip.s_addr != dst.s_addr)) - continue; - if (((nat->nat_inport == sport) || (nflags & FI_W_SPORT)) && - ((nat->nat_oport == dport) || (nflags & FI_W_DPORT))) { - nat_tabmove(nat, ports); - break; - } - } - if (!rw) { - MUTEX_DOWNGRADE(&ipf_nat); - } - return nat; -} - - -/* - * Lookup the NAT tables to search for a matching redirect - */ -nat_t *nat_lookupredir(np) -register natlookup_t *np; -{ - u_32_t ports; - nat_t *nat; - - ports = (np->nl_outport << 16) | np->nl_inport; - /* - * If nl_inip is non null, this is a lookup based on the real - * ip address. Else, we use the fake. - */ - if ((nat = nat_outlookup(NULL, np->nl_flags, 0, np->nl_inip, - np->nl_outip, ports, 0))) { - np->nl_realip = nat->nat_outip; - np->nl_realport = nat->nat_outport; - } - return nat; -} - - -static int nat_match(fin, np, ip) -fr_info_t *fin; -ipnat_t *np; -ip_t *ip; -{ - frtuc_t *ft; - - if (ip->ip_v != 4) - return 0; - - if (np->in_p && ip->ip_p != np->in_p) - return 0; - if (fin->fin_out) { - if (!(np->in_redir & (NAT_MAP|NAT_MAPBLK))) - return 0; - if (((fin->fin_fi.fi_saddr & np->in_inmsk) != np->in_inip) - ^ ((np->in_flags & IPN_NOTSRC) != 0)) - return 0; - if (((fin->fin_fi.fi_daddr & np->in_srcmsk) != np->in_srcip) - ^ ((np->in_flags & IPN_NOTDST) != 0)) - return 0; - } else { - if (!(np->in_redir & NAT_REDIRECT)) - return 0; - if (((fin->fin_fi.fi_saddr & np->in_srcmsk) != np->in_srcip) - ^ ((np->in_flags & IPN_NOTSRC) != 0)) - return 0; - if (((fin->fin_fi.fi_daddr & np->in_outmsk) != np->in_outip) - ^ ((np->in_flags & IPN_NOTDST) != 0)) - return 0; - } - - ft = &np->in_tuc; - if (!(fin->fin_fi.fi_fl & FI_TCPUDP) || - (fin->fin_fi.fi_fl & FI_SHORT) || (ip->ip_off & IP_OFFMASK)) { - if (ft->ftu_scmp || ft->ftu_dcmp) - return 0; - return 1; - } - - return fr_tcpudpchk(ft, fin); -} - - -/* - * Packets going out on the external interface go through this. - * Here, the source address requires alteration, if anything. - */ -int ip_natout(ip, fin) -ip_t *ip; -fr_info_t *fin; -{ - register ipnat_t *np = NULL; - register u_32_t ipa; - tcphdr_t *tcp = NULL; - u_short sport = 0, dport = 0, *csump = NULL; - struct ifnet *ifp; - int natadd = 1; - frentry_t *fr; - u_int nflags = 0, hv, msk; - u_32_t iph; - nat_t *nat; - int i; - - if (nat_list == NULL || (fr_nat_lock)) - return 0; - - if ((fr = fin->fin_fr) && !(fr->fr_flags & FR_DUP) && - fr->fr_tif.fd_ifp && fr->fr_tif.fd_ifp != (void *)-1) - ifp = fr->fr_tif.fd_ifp; - else - ifp = fin->fin_ifp; - - if (!(ip->ip_off & IP_OFFMASK) && !(fin->fin_fi.fi_fl & FI_SHORT)) { - if (ip->ip_p == IPPROTO_TCP) - nflags = IPN_TCP; - else if (ip->ip_p == IPPROTO_UDP) - nflags = IPN_UDP; - if ((nflags & IPN_TCPUDP)) { - tcp = (tcphdr_t *)fin->fin_dp; - sport = tcp->th_sport; - dport = tcp->th_dport; - } - } - - ipa = ip->ip_src.s_addr; - - READ_ENTER(&ipf_nat); - - if ((ip->ip_p == IPPROTO_ICMP) && - (nat = nat_icmp(ip, fin, &nflags, NAT_OUTBOUND))) - ; - else if ((ip->ip_off & (IP_OFFMASK|IP_MF)) && - (nat = ipfr_nat_knownfrag(ip, fin))) - natadd = 0; - else if ((nat = nat_outlookup(ifp, nflags, (u_int)ip->ip_p, - ip->ip_src, ip->ip_dst, - (dport << 16) | sport, 0))) { - nflags = nat->nat_flags; - if ((nflags & (FI_W_SPORT|FI_W_DPORT)) != 0) { - if ((nflags & FI_W_SPORT) && - (nat->nat_inport != sport)) - nat->nat_inport = sport; - else if ((nflags & FI_W_DPORT) && - (nat->nat_oport != dport)) - nat->nat_oport = dport; - if (nat->nat_outport == 0) - nat->nat_outport = sport; - nat->nat_flags &= ~(FI_W_DPORT|FI_W_SPORT); - nflags = nat->nat_flags; - nat_stats.ns_wilds--; - } - } else { - RWLOCK_EXIT(&ipf_nat); - WRITE_ENTER(&ipf_nat); - /* - * If there is no current entry in the nat table for this IP#, - * create one for it (if there is a matching rule). - */ - msk = 0xffffffff; - i = 32; -maskloop: - iph = ipa & htonl(msk); - hv = NAT_HASH_FN(iph, 0, ipf_natrules_sz); - for (np = nat_rules[hv]; np; np = np->in_mnext) - { - if ((np->in_ifp && (np->in_ifp != ifp)) || - !np->in_space) - continue; - if ((np->in_flags & IPN_RF) && - !(np->in_flags & nflags)) - continue; - if (np->in_flags & IPN_FILTER) { - if (!nat_match(fin, np, ip)) - continue; - } else if ((ipa & np->in_inmsk) != np->in_inip) - continue; - if (np->in_redir & (NAT_MAP|NAT_MAPBLK)) { - if (*np->in_plabel && !appr_ok(ip, tcp, np)) - continue; - /* - * If it's a redirection, then we don't want to - * create new outgoing port stuff. - * Redirections are only for incoming - * connections. - */ - if (!(np->in_redir & (NAT_MAP|NAT_MAPBLK))) - continue; - if ((nat = nat_new(np, ip, fin, (u_int)nflags, - NAT_OUTBOUND))) { - np->in_hits++; - break; - } - } - } - if ((np == NULL) && (i > 0)) { - do { - i--; - msk <<= 1; - } while ((i >= 0) && ((nat_masks & (1 << i)) == 0)); - if (i >= 0) - goto maskloop; - } - MUTEX_DOWNGRADE(&ipf_nat); - } - - /* - * NOTE: ipf_nat must now only be held as a read lock - */ - if (nat) { - np = nat->nat_ptr; - if (natadd && fin->fin_fi.fi_fl & FI_FRAG) - ipfr_nat_newfrag(ip, fin, 0, nat); - MUTEX_ENTER(&nat->nat_lock); - nat->nat_age = fr_defnatage; - nat->nat_bytes += ip->ip_len; - nat->nat_pkts++; - MUTEX_EXIT(&nat->nat_lock); - - /* - * Fix up checksums, not by recalculating them, but - * simply computing adjustments. - */ - if (nflags == IPN_ICMPERR) { - u_32_t s1, s2, sumd; - - s1 = LONG_SUM(ntohl(ip->ip_src.s_addr)); - s2 = LONG_SUM(ntohl(nat->nat_outip.s_addr)); - CALC_SUMD(s1, s2, sumd); - - if (nat->nat_dir == NAT_OUTBOUND) - fix_incksum(&ip->ip_sum, sumd); - else - fix_outcksum(&ip->ip_sum, sumd); - } -#if SOLARIS || defined(__sgi) - else { - if (nat->nat_dir == NAT_OUTBOUND) - fix_outcksum(&ip->ip_sum, nat->nat_ipsumd); - else - fix_incksum(&ip->ip_sum, nat->nat_ipsumd); - } -#endif - ip->ip_src = nat->nat_outip; - - if (!(ip->ip_off & IP_OFFMASK) && - !(fin->fin_fi.fi_fl & FI_SHORT)) { - - if ((nat->nat_outport != 0) && (nflags & IPN_TCPUDP)) { - tcp->th_sport = nat->nat_outport; - fin->fin_data[0] = ntohs(tcp->th_sport); - } - - if (ip->ip_p == IPPROTO_TCP) { - csump = &tcp->th_sum; - MUTEX_ENTER(&nat->nat_lock); - fr_tcp_age(&nat->nat_age, - nat->nat_tcpstate, fin, 1); - if (nat->nat_age < fr_defnaticmpage) - nat->nat_age = fr_defnaticmpage; -#ifdef LARGE_NAT - else if (nat->nat_age > fr_defnatage) - nat->nat_age = fr_defnatage; -#endif - /* - * Increase this because we may have - * "keep state" following this too and - * packet storms can occur if this is - * removed too quickly. - */ - if (nat->nat_age == fr_tcpclosed) - nat->nat_age = fr_tcplastack; - MUTEX_EXIT(&nat->nat_lock); - } else if (ip->ip_p == IPPROTO_UDP) { - udphdr_t *udp = (udphdr_t *)tcp; - - if (udp->uh_sum) - csump = &udp->uh_sum; - } else if (ip->ip_p == IPPROTO_ICMP) { - nat->nat_age = fr_defnaticmpage; - } - - if (csump) { - if (nat->nat_dir == NAT_OUTBOUND) - fix_outcksum(csump, nat->nat_sumd[1]); - else - fix_incksum(csump, nat->nat_sumd[1]); - } - } - - if ((np->in_apr != NULL) && (np->in_dport == 0 || - (tcp != NULL && dport == np->in_dport))) { - i = appr_check(ip, fin, nat); - if (i == 0) - i = 1; - } else - i = 1; - ATOMIC_INCL(nat_stats.ns_mapped[1]); - RWLOCK_EXIT(&ipf_nat); /* READ */ - return i; - } - RWLOCK_EXIT(&ipf_nat); /* READ/WRITE */ - return 0; -} - - -/* - * Packets coming in from the external interface go through this. - * Here, the destination address requires alteration, if anything. - */ -int ip_natin(ip, fin) -ip_t *ip; -fr_info_t *fin; -{ - register struct in_addr src; - register struct in_addr in; - register ipnat_t *np; - u_int nflags = 0, natadd = 1, hv, msk; - struct ifnet *ifp = fin->fin_ifp; - tcphdr_t *tcp = NULL; - u_short sport = 0, dport = 0, *csump = NULL; - nat_t *nat; - u_32_t iph; - int i; - - if ((nat_list == NULL) || (ip->ip_v != 4) || (fr_nat_lock)) - return 0; - - if (!(ip->ip_off & IP_OFFMASK) && !(fin->fin_fi.fi_fl & FI_SHORT)) { - if (ip->ip_p == IPPROTO_TCP) - nflags = IPN_TCP; - else if (ip->ip_p == IPPROTO_UDP) - nflags = IPN_UDP; - if ((nflags & IPN_TCPUDP)) { - tcp = (tcphdr_t *)fin->fin_dp; - dport = tcp->th_dport; - sport = tcp->th_sport; - } - } - - in = ip->ip_dst; - /* make sure the source address is to be redirected */ - src = ip->ip_src; - - READ_ENTER(&ipf_nat); - - if ((ip->ip_p == IPPROTO_ICMP) && - (nat = nat_icmp(ip, fin, &nflags, NAT_INBOUND))) - ; - else if ((ip->ip_off & (IP_OFFMASK|IP_MF)) && - (nat = ipfr_nat_knownfrag(ip, fin))) - natadd = 0; - else if ((nat = nat_inlookup(fin->fin_ifp, nflags, (u_int)ip->ip_p, - ip->ip_src, in, (dport << 16) | sport, - 0))) { - nflags = nat->nat_flags; - if ((nflags & (FI_W_SPORT|FI_W_DPORT)) != 0) { - if ((nat->nat_oport != sport) && (nflags & FI_W_DPORT)) - nat->nat_oport = sport; - else if ((nat->nat_outport != dport) && - (nflags & FI_W_SPORT)) - nat->nat_outport = dport; - nat->nat_flags &= ~(FI_W_SPORT|FI_W_DPORT); - nflags = nat->nat_flags; - nat_stats.ns_wilds--; - } - } else { - RWLOCK_EXIT(&ipf_nat); - WRITE_ENTER(&ipf_nat); - /* - * If there is no current entry in the nat table for this IP#, - * create one for it (if there is a matching rule). - */ - msk = 0xffffffff; - i = 32; -maskloop: - iph = in.s_addr & htonl(msk); - hv = NAT_HASH_FN(iph, 0, ipf_rdrrules_sz); - for (np = rdr_rules[hv]; np; np = np->in_rnext) { - if ((np->in_ifp && (np->in_ifp != ifp)) || - (np->in_p && (np->in_p != ip->ip_p)) || - (np->in_flags && !(nflags & np->in_flags))) - continue; - if (np->in_flags & IPN_FILTER) { - if (!nat_match(fin, np, ip)) - continue; - } else if ((in.s_addr & np->in_outmsk) != np->in_outip) - continue; - if ((np->in_redir & NAT_REDIRECT) && - (!np->in_pmin || (np->in_flags & IPN_FILTER) || - ((ntohs(np->in_pmax) >= ntohs(dport)) && - (ntohs(dport) >= ntohs(np->in_pmin))))) - if ((nat = nat_new(np, ip, fin, nflags, - NAT_INBOUND))) { - np->in_hits++; - break; - } - } - - if ((np == NULL) && (i > 0)) { - do { - i--; - msk <<= 1; - } while ((i >= 0) && ((rdr_masks & (1 << i)) == 0)); - if (i >= 0) - goto maskloop; - } - MUTEX_DOWNGRADE(&ipf_nat); - } - - /* - * NOTE: ipf_nat must now only be held as a read lock - */ - if (nat) { - np = nat->nat_ptr; - fin->fin_fr = nat->nat_fr; - if (natadd && fin->fin_fi.fi_fl & FI_FRAG) - ipfr_nat_newfrag(ip, fin, 0, nat); - if ((np->in_apr != NULL) && (np->in_dport == 0 || - (tcp != NULL && sport == np->in_dport))) { - i = appr_check(ip, fin, nat); - if (i == -1) { - RWLOCK_EXIT(&ipf_nat); - return i; - } - } - - MUTEX_ENTER(&nat->nat_lock); - if (nflags != IPN_ICMPERR) - nat->nat_age = fr_defnatage; - - nat->nat_bytes += ip->ip_len; - nat->nat_pkts++; - MUTEX_EXIT(&nat->nat_lock); - ip->ip_dst = nat->nat_inip; - fin->fin_fi.fi_daddr = nat->nat_inip.s_addr; - - /* - * Fix up checksums, not by recalculating them, but - * simply computing adjustments. - */ -#if SOLARIS || defined(__sgi) - if (nat->nat_dir == NAT_OUTBOUND) - fix_incksum(&ip->ip_sum, nat->nat_ipsumd); - else - fix_outcksum(&ip->ip_sum, nat->nat_ipsumd); -#endif - if (!(ip->ip_off & IP_OFFMASK) && - !(fin->fin_fi.fi_fl & FI_SHORT)) { - - if ((nat->nat_inport != 0) && (nflags & IPN_TCPUDP)) { - tcp->th_dport = nat->nat_inport; - fin->fin_data[1] = ntohs(tcp->th_dport); - } - - if (ip->ip_p == IPPROTO_TCP) { - csump = &tcp->th_sum; - MUTEX_ENTER(&nat->nat_lock); - fr_tcp_age(&nat->nat_age, - nat->nat_tcpstate, fin, 0); - if (nat->nat_age < fr_defnaticmpage) - nat->nat_age = fr_defnaticmpage; -#ifdef LARGE_NAT - else if (nat->nat_age > fr_defnatage) - nat->nat_age = fr_defnatage; -#endif - /* - * Increase this because we may have - * "keep state" following this too and - * packet storms can occur if this is - * removed too quickly. - */ - if (nat->nat_age == fr_tcpclosed) - nat->nat_age = fr_tcplastack; - MUTEX_EXIT(&nat->nat_lock); - } else if (ip->ip_p == IPPROTO_UDP) { - udphdr_t *udp = (udphdr_t *)tcp; - - if (udp->uh_sum) - csump = &udp->uh_sum; - } else if (ip->ip_p == IPPROTO_ICMP) { - nat->nat_age = fr_defnaticmpage; - } - - if (csump) { - if (nat->nat_dir == NAT_OUTBOUND) - fix_incksum(csump, nat->nat_sumd[0]); - else - fix_outcksum(csump, nat->nat_sumd[0]); - } - } - ATOMIC_INCL(nat_stats.ns_mapped[0]); - RWLOCK_EXIT(&ipf_nat); /* READ */ - return 1; - } - RWLOCK_EXIT(&ipf_nat); /* READ/WRITE */ - return 0; -} - - -/* - * Free all memory used by NAT structures allocated at runtime. - */ -void ip_natunload() -{ - WRITE_ENTER(&ipf_nat); - (void) nat_clearlist(); - (void) nat_flushtable(); - RWLOCK_EXIT(&ipf_nat); - - if (nat_table[0] != NULL) { - KFREES(nat_table[0], sizeof(nat_t *) * ipf_nattable_sz); - nat_table[0] = NULL; - } - if (nat_table[1] != NULL) { - KFREES(nat_table[1], sizeof(nat_t *) * ipf_nattable_sz); - nat_table[1] = NULL; - } - if (nat_rules != NULL) { - KFREES(nat_rules, sizeof(ipnat_t *) * ipf_natrules_sz); - nat_rules = NULL; - } - if (rdr_rules != NULL) { - KFREES(rdr_rules, sizeof(ipnat_t *) * ipf_rdrrules_sz); - rdr_rules = NULL; - } - if (maptable != NULL) { - KFREES(maptable, sizeof(hostmap_t *) * ipf_hostmap_sz); - maptable = NULL; - } -} - - -/* - * Slowly expire held state for NAT entries. Timeouts are set in - * expectation of this being called twice per second. - */ -void ip_natexpire() -{ - register struct nat *nat, **natp; -#if defined(_KERNEL) && !SOLARIS - int s; -#endif - - SPL_NET(s); - WRITE_ENTER(&ipf_nat); - for (natp = &nat_instances; (nat = *natp); ) { - nat->nat_age--; - if (nat->nat_age) { - natp = &nat->nat_next; - continue; - } - *natp = nat->nat_next; -#ifdef IPFILTER_LOG - nat_log(nat, NL_EXPIRE); -#endif - nat_delete(nat); - nat_stats.ns_expire++; - } - RWLOCK_EXIT(&ipf_nat); - SPL_X(s); -} - - -/* - */ -void ip_natsync(ifp) -void *ifp; -{ - register ipnat_t *n; - register nat_t *nat; - register u_32_t sum1, sum2, sumd; - struct in_addr in; - ipnat_t *np; - void *ifp2; -#if defined(_KERNEL) && !SOLARIS - int s; -#endif - - /* - * Change IP addresses for NAT sessions for any protocol except TCP - * since it will break the TCP connection anyway. - */ - SPL_NET(s); - WRITE_ENTER(&ipf_nat); - for (nat = nat_instances; nat; nat = nat->nat_next) - if (((ifp == NULL) || (ifp == nat->nat_ifp)) && - !(nat->nat_flags & IPN_TCP) && (np = nat->nat_ptr) && - (np->in_outmsk == 0xffffffff) && !np->in_nip) { - ifp2 = nat->nat_ifp; - /* - * Change the map-to address to be the same as the - * new one. - */ - sum1 = nat->nat_outip.s_addr; - if (fr_ifpaddr(4, ifp2, &in) != -1) - nat->nat_outip = in; - sum2 = nat->nat_outip.s_addr; - - if (sum1 == sum2) - continue; - /* - * Readjust the checksum adjustment to take into - * account the new IP#. - */ - CALC_SUMD(sum1, sum2, sumd); - /* XXX - dont change for TCP when solaris does - * hardware checksumming. - */ - sumd += nat->nat_sumd[0]; - nat->nat_sumd[0] = (sumd & 0xffff) + (sumd >> 16); - nat->nat_sumd[1] = nat->nat_sumd[0]; - } - - for (n = nat_list; (n != NULL); n = n->in_next) - if (n->in_ifp == ifp) { - n->in_ifp = (void *)GETUNIT(n->in_ifname, 4); - if (!n->in_ifp) - n->in_ifp = (void *)-1; - } - RWLOCK_EXIT(&ipf_nat); - SPL_X(s); -} - - -#ifdef IPFILTER_LOG -void nat_log(nat, type) -struct nat *nat; -u_int type; -{ - struct ipnat *np; - struct natlog natl; - void *items[1]; - size_t sizes[1]; - int rulen, types[1]; - - natl.nl_inip = nat->nat_inip; - natl.nl_outip = nat->nat_outip; - natl.nl_origip = nat->nat_oip; - natl.nl_bytes = nat->nat_bytes; - natl.nl_pkts = nat->nat_pkts; - natl.nl_origport = nat->nat_oport; - natl.nl_inport = nat->nat_inport; - natl.nl_outport = nat->nat_outport; - natl.nl_p = nat->nat_p; - natl.nl_type = type; - natl.nl_rule = -1; -#ifndef LARGE_NAT - if (nat->nat_ptr != NULL) { - for (rulen = 0, np = nat_list; np; np = np->in_next, rulen++) - if (np == nat->nat_ptr) { - natl.nl_rule = rulen; - break; - } - } -#endif - items[0] = &natl; - sizes[0] = sizeof(natl); - types[0] = 0; - - (void) ipllog(IPL_LOGNAT, NULL, items, sizes, types, 1); -} -#endif diff --git a/contrib/ipfilter/ip_nat.h b/contrib/ipfilter/ip_nat.h deleted file mode 100644 index 22f8503..0000000 --- a/contrib/ipfilter/ip_nat.h +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright (C) 1995-2000 by Darren Reed. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - * - * @(#)ip_nat.h 1.5 2/4/96 - * $Id: ip_nat.h,v 2.17.2.14 2000/11/18 03:58:04 darrenr Exp $ - */ - -#ifndef __IP_NAT_H__ -#define __IP_NAT_H__ - -#ifndef SOLARIS -#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) -#endif - -#if defined(__STDC__) || defined(__GNUC__) -#define SIOCADNAT _IOW('r', 60, struct ipnat *) -#define SIOCRMNAT _IOW('r', 61, struct ipnat *) -#define SIOCGNATS _IOWR('r', 62, struct natstat *) -#define SIOCGNATL _IOWR('r', 63, struct natlookup *) -#else -#define SIOCADNAT _IOW(r, 60, struct ipnat *) -#define SIOCRMNAT _IOW(r, 61, struct ipnat *) -#define SIOCGNATS _IOWR(r, 62, struct natstat *) -#define SIOCGNATL _IOWR(r, 63, struct natlookup *) -#endif - -#undef LARGE_NAT /* define this if you're setting up a system to NAT - * LARGE numbers of networks/hosts - i.e. in the - * hundreds or thousands. In such a case, you should - * also change the RDR_SIZE and NAT_SIZE below to more - * appropriate sizes. The figures below were used for - * a setup with 1000-2000 networks to NAT. - */ -#define NAT_SIZE 127 -#define RDR_SIZE 127 -#define HOSTMAP_SIZE 127 -#define NAT_TABLE_SZ 127 -#ifdef LARGE_NAT -#undef NAT_SIZE -#undef RDR_SIZE -#undef NAT_TABLE_SZ -#undef HOSTMAP_SIZE 127 -#define NAT_SIZE 2047 -#define RDR_SIZE 2047 -#define NAT_TABLE_SZ 16383 -#define HOSTMAP_SIZE 8191 -#endif -#ifndef APR_LABELLEN -#define APR_LABELLEN 16 -#endif -#define NAT_HW_CKSUM 0x80000000 - -#define DEF_NAT_AGE 1200 /* 10 minutes (600 seconds) */ - -struct ap_session; - -typedef struct nat { - u_long nat_age; - int nat_flags; - u_32_t nat_sumd[2]; - u_32_t nat_ipsumd; - void *nat_data; - struct ap_session *nat_aps; /* proxy session */ - struct frentry *nat_fr; /* filter rule ptr if appropriate */ - struct in_addr nat_inip; - struct in_addr nat_outip; - struct in_addr nat_oip; /* other ip */ - U_QUAD_T nat_pkts; - U_QUAD_T nat_bytes; - u_short nat_oport; /* other port */ - u_short nat_inport; - u_short nat_outport; - u_short nat_use; - u_char nat_tcpstate[2]; - u_char nat_p; /* protocol for NAT */ - struct ipnat *nat_ptr; /* pointer back to the rule */ - struct hostmap *nat_hm; - struct nat *nat_next; - struct nat *nat_hnext[2]; - struct nat **nat_phnext[2]; - void *nat_ifp; - int nat_dir; - char nat_ifname[IFNAMSIZ]; -#if SOLARIS || defined(__sgi) - kmutex_t nat_lock; -#endif -} nat_t; - -typedef struct ipnat { - struct ipnat *in_next; - struct ipnat *in_rnext; - struct ipnat **in_prnext; - struct ipnat *in_mnext; - struct ipnat **in_pmnext; - void *in_ifp; - void *in_apr; - u_long in_space; - u_int in_use; - u_int in_hits; - struct in_addr in_nextip; - u_short in_pnext; - u_short in_ippip; /* IP #'s per IP# */ - u_32_t in_flags; /* From here to in_dport must be reflected */ - u_short in_spare; - u_short in_ppip; /* ports per IP */ - u_short in_port[2]; /* correctly in IPN_CMPSIZ */ - struct in_addr in_in[2]; - struct in_addr in_out[2]; - struct in_addr in_src[2]; - struct frtuc in_tuc; - int in_redir; /* 0 if it's a mapping, 1 if it's a hard redir */ - char in_ifname[IFNAMSIZ]; - char in_plabel[APR_LABELLEN]; /* proxy label */ - char in_p; /* protocol */ -} ipnat_t; - -#define in_pmin in_port[0] /* Also holds static redir port */ -#define in_pmax in_port[1] -#define in_nip in_nextip.s_addr -#define in_inip in_in[0].s_addr -#define in_inmsk in_in[1].s_addr -#define in_outip in_out[0].s_addr -#define in_outmsk in_out[1].s_addr -#define in_srcip in_src[0].s_addr -#define in_srcmsk in_src[1].s_addr -#define in_scmp in_tuc.ftu_scmp -#define in_dcmp in_tuc.ftu_dcmp -#define in_stop in_tuc.ftu_stop -#define in_dtop in_tuc.ftu_dtop -#define in_sport in_tuc.ftu_sport -#define in_dport in_tuc.ftu_dport - -#define NAT_OUTBOUND 0 -#define NAT_INBOUND 1 - -#define NAT_MAP 0x01 -#define NAT_REDIRECT 0x02 -#define NAT_BIMAP (NAT_MAP|NAT_REDIRECT) -#define NAT_MAPBLK 0x04 -/* 0x100 reserved for FI_W_SPORT */ -/* 0x200 reserved for FI_W_DPORT */ -/* 0x400 reserved for FI_W_SADDR */ -/* 0x800 reserved for FI_W_DADDR */ -/* 0x1000 reserved for FI_W_NEWFR */ - -#define MAPBLK_MINPORT 1024 /* don't use reserved ports for src port */ -#define USABLE_PORTS (65536 - MAPBLK_MINPORT) - -#define IPN_CMPSIZ (sizeof(ipnat_t) - offsetof(ipnat_t, in_flags)) - -typedef struct natlookup { - struct in_addr nl_inip; - struct in_addr nl_outip; - struct in_addr nl_realip; - int nl_flags; - u_short nl_inport; - u_short nl_outport; - u_short nl_realport; -} natlookup_t; - - -typedef struct nat_save { - void *ipn_next; - struct nat ipn_nat; - struct ipnat ipn_ipnat; - struct frentry ipn_fr; - int ipn_dsize; - char ipn_data[4]; -} nat_save_t; - -#define ipn_rule ipn_nat.nat_fr - -typedef struct natget { - void *ng_ptr; - int ng_sz; -} natget_t; - - -typedef struct hostmap { - struct hostmap *hm_next; - struct hostmap **hm_pnext; - struct ipnat *hm_ipnat; - struct in_addr hm_realip; - struct in_addr hm_mapip; - int hm_ref; -} hostmap_t; - - -typedef struct natstat { - u_long ns_mapped[2]; - u_long ns_rules; - u_long ns_added; - u_long ns_expire; - u_long ns_inuse; - u_long ns_logged; - u_long ns_logfail; - u_long ns_memfail; - u_long ns_badnat; - nat_t **ns_table[2]; - ipnat_t *ns_list; - void *ns_apslist; - u_int ns_nattab_sz; - u_int ns_rultab_sz; - u_int ns_rdrtab_sz; - nat_t *ns_instances; - u_int ns_wilds; -} natstat_t; - -#define IPN_ANY 0x000 -#define IPN_TCP 0x001 -#define IPN_UDP 0x002 -#define IPN_TCPUDP (IPN_TCP|IPN_UDP) -#define IPN_DELETE 0x004 -#define IPN_ICMPERR 0x008 -#define IPN_RF (IPN_TCPUDP|IPN_DELETE|IPN_ICMPERR) -#define IPN_AUTOPORTMAP 0x010 -#define IPN_IPRANGE 0x020 -#define IPN_USERFLAGS (IPN_TCPUDP|IPN_AUTOPORTMAP|IPN_IPRANGE|IPN_SPLIT|\ - IPN_ROUNDR|IPN_FILTER|IPN_NOTSRC|IPN_NOTDST) -#define IPN_FILTER 0x040 -#define IPN_SPLIT 0x080 -#define IPN_ROUNDR 0x100 -#define IPN_NOTSRC 0x080000 -#define IPN_NOTDST 0x100000 - - -typedef struct natlog { - struct in_addr nl_origip; - struct in_addr nl_outip; - struct in_addr nl_inip; - u_short nl_origport; - u_short nl_outport; - u_short nl_inport; - u_short nl_type; - int nl_rule; - U_QUAD_T nl_pkts; - U_QUAD_T nl_bytes; - u_char nl_p; -} natlog_t; - - -#define NL_NEWMAP NAT_MAP -#define NL_NEWRDR NAT_REDIRECT -#define NL_NEWBIMAP NAT_BIMAP -#define NL_NEWBLOCK NAT_MAPBLK -#define NL_FLUSH 0xfffe -#define NL_EXPIRE 0xffff - -#define NAT_HASH_FN(k,l,m) (((k) + ((k) >> 12) + l) % (m)) - -#define LONG_SUM(in) (((in) & 0xffff) + ((in) >> 16)) - -#define CALC_SUMD(s1, s2, sd) { \ - (s1) = ((s1) & 0xffff) + ((s1) >> 16); \ - (s2) = ((s2) & 0xffff) + ((s2) >> 16); \ - /* Do it twice */ \ - (s1) = ((s1) & 0xffff) + ((s1) >> 16); \ - (s2) = ((s2) & 0xffff) + ((s2) >> 16); \ - /* Because ~1 == -2, We really need ~1 == -1 */ \ - if ((s1) > (s2)) (s2)--; \ - (sd) = (s2) - (s1); \ - (sd) = ((sd) & 0xffff) + ((sd) >> 16); } - - -extern u_int ipf_nattable_sz; -extern u_int ipf_natrules_sz; -extern u_int ipf_rdrrules_sz; -extern int fr_nat_lock; -extern void ip_natsync __P((void *)); -extern u_long fr_defnatage; -extern u_long fr_defnaticmpage; -extern nat_t **nat_table[2]; -extern nat_t *nat_instances; -extern ipnat_t **nat_rules; -extern ipnat_t **rdr_rules; -extern natstat_t nat_stats; -#if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003) -extern int nat_ioctl __P((caddr_t, u_long, int)); -#else -extern int nat_ioctl __P((caddr_t, int, int)); -#endif -extern int nat_init __P((void)); -extern nat_t *nat_new __P((ipnat_t *, ip_t *, fr_info_t *, u_int, int)); -extern nat_t *nat_outlookup __P((void *, u_int, u_int, struct in_addr, - struct in_addr, u_32_t, int)); -extern nat_t *nat_inlookup __P((void *, u_int, u_int, struct in_addr, - struct in_addr, u_32_t, int)); -extern nat_t *nat_maplookup __P((void *, u_int, struct in_addr, - struct in_addr)); -extern nat_t *nat_lookupredir __P((natlookup_t *)); -extern nat_t *nat_icmplookup __P((ip_t *, fr_info_t *, int)); -extern nat_t *nat_icmp __P((ip_t *, fr_info_t *, u_int *, int)); -extern void nat_insert __P((nat_t *)); - -extern int ip_natout __P((ip_t *, fr_info_t *)); -extern int ip_natin __P((ip_t *, fr_info_t *)); -extern void ip_natunload __P((void)), ip_natexpire __P((void)); -extern void nat_log __P((struct nat *, u_int)); -extern void fix_incksum __P((u_short *, u_32_t)); -extern void fix_outcksum __P((u_short *, u_32_t)); -extern void fix_datacksum __P((u_short *, u_32_t)); - -#endif /* __IP_NAT_H__ */ diff --git a/contrib/ipfilter/ip_proxy.c b/contrib/ipfilter/ip_proxy.c deleted file mode 100644 index e1e55f1..0000000 --- a/contrib/ipfilter/ip_proxy.c +++ /dev/null @@ -1,451 +0,0 @@ -/* - * Copyright (C) 1997-2000 by Darren Reed. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - */ -#if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_proxy.c,v 2.9.2.1 2000/05/06 12:30:50 darrenr Exp $"; -#endif - -#if defined(__FreeBSD__) && defined(KERNEL) && !defined(_KERNEL) -# define _KERNEL -#endif - -#include <sys/errno.h> -#include <sys/types.h> -#include <sys/param.h> -#include <sys/time.h> -#include <sys/file.h> -#if !defined(__FreeBSD_version) -# include <sys/ioctl.h> -#endif -#include <sys/fcntl.h> -#include <sys/uio.h> -#if !defined(_KERNEL) && !defined(KERNEL) -# include <stdio.h> -# include <string.h> -# include <stdlib.h> -#endif -#ifndef linux -# include <sys/protosw.h> -#endif -#include <sys/socket.h> -#if defined(_KERNEL) -# if !defined(linux) -# include <sys/systm.h> -# else -# include <linux/string.h> -# endif -#endif -#if !defined(__SVR4) && !defined(__svr4__) -# ifndef linux -# include <sys/mbuf.h> -# endif -#else -# include <sys/byteorder.h> -# ifdef _KERNEL -# include <sys/dditypes.h> -# endif -# include <sys/stream.h> -# include <sys/kmem.h> -#endif -#if __FreeBSD__ > 2 -# include <sys/queue.h> -#endif -#include <net/if.h> -#ifdef sun -# include <net/af.h> -#endif -#include <net/route.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#ifndef linux -# include <netinet/ip_var.h> -#endif -#include <netinet/tcp.h> -#include <netinet/udp.h> -#include <netinet/ip_icmp.h> -#include "netinet/ip_compat.h" -#include <netinet/tcpip.h> -#include "netinet/ip_fil.h" -#include "netinet/ip_proxy.h" -#include "netinet/ip_nat.h" -#include "netinet/ip_state.h" -#if (__FreeBSD_version >= 300000) -# include <sys/malloc.h> -#endif - - -#ifndef MIN -#define MIN(a,b) (((a)<(b))?(a):(b)) -#endif - -static ap_session_t *appr_new_session __P((aproxy_t *, ip_t *, - fr_info_t *, nat_t *)); -static int appr_fixseqack __P((fr_info_t *, ip_t *, ap_session_t *, int )); - - -#define AP_SESS_SIZE 53 - -#if defined(_KERNEL) && !defined(linux) -#include "netinet/ip_ftp_pxy.c" -#include "netinet/ip_rcmd_pxy.c" -#include "netinet/ip_raudio_pxy.c" -#endif - -ap_session_t *ap_sess_tab[AP_SESS_SIZE]; -ap_session_t *ap_sess_list = NULL; -aproxy_t *ap_proxylist = NULL; -aproxy_t ap_proxies[] = { -#ifdef IPF_FTP_PROXY - { NULL, "ftp", (char)IPPROTO_TCP, 0, 0, ippr_ftp_init, NULL, - ippr_ftp_new, ippr_ftp_in, ippr_ftp_out }, -#endif -#ifdef IPF_RCMD_PROXY - { NULL, "rcmd", (char)IPPROTO_TCP, 0, 0, ippr_rcmd_init, NULL, - ippr_rcmd_new, NULL, ippr_rcmd_out }, -#endif -#ifdef IPF_RAUDIO_PROXY - { NULL, "raudio", (char)IPPROTO_TCP, 0, 0, ippr_raudio_init, NULL, - ippr_raudio_new, ippr_raudio_in, ippr_raudio_out }, -#endif - { NULL, "", '\0', 0, 0, NULL, NULL } -}; - - -int appr_add(ap) -aproxy_t *ap; -{ - aproxy_t *a; - - for (a = ap_proxies; a->apr_p; a++) - if ((a->apr_p == ap->apr_p) && - !strncmp(a->apr_label, ap->apr_label, - sizeof(ap->apr_label))) - return -1; - - for (a = ap_proxylist; a->apr_p; a = a->apr_next) - if ((a->apr_p == ap->apr_p) && - !strncmp(a->apr_label, ap->apr_label, - sizeof(ap->apr_label))) - return -1; - ap->apr_next = ap_proxylist; - ap_proxylist = ap; - return (*ap->apr_init)(); -} - - -int appr_del(ap) -aproxy_t *ap; -{ - aproxy_t *a, **app; - - for (app = &ap_proxylist; (a = *app); app = &a->apr_next) - if (a == ap) { - if (ap->apr_ref != 0) - return 1; - *app = a->apr_next; - return 0; - } - return -1; -} - - -int appr_ok(ip, tcp, nat) -ip_t *ip; -tcphdr_t *tcp; -ipnat_t *nat; -{ - aproxy_t *apr = nat->in_apr; - u_short dport = nat->in_dport; - - if (!apr || (apr->apr_flags & APR_DELETE) || - (ip->ip_p != apr->apr_p)) - return 0; - if ((tcp && (tcp->th_dport != dport)) || (!tcp && dport)) - return 0; - return 1; -} - - -/* - * Allocate a new application proxy structure and fill it in with the - * relevant details. call the init function once complete, prior to - * returning. - */ -static ap_session_t *appr_new_session(apr, ip, fin, nat) -aproxy_t *apr; -ip_t *ip; -fr_info_t *fin; -nat_t *nat; -{ - register ap_session_t *aps; - - if (!apr || (apr->apr_flags & APR_DELETE) || (ip->ip_p != apr->apr_p)) - return NULL; - - KMALLOC(aps, ap_session_t *); - if (!aps) - return NULL; - bzero((char *)aps, sizeof(*aps)); - aps->aps_p = ip->ip_p; - aps->aps_data = NULL; - aps->aps_apr = apr; - aps->aps_psiz = 0; - if (apr->apr_new != NULL) - if ((*apr->apr_new)(fin, ip, aps, nat) == -1) { - KFREE(aps); - return NULL; - } - aps->aps_nat = nat; - aps->aps_next = ap_sess_list; - ap_sess_list = aps; - return aps; -} - - -/* - * check to see if a packet should be passed through an active proxy routine - * if one has been setup for it. - */ -int appr_check(ip, fin, nat) -ip_t *ip; -fr_info_t *fin; -nat_t *nat; -{ - ap_session_t *aps; - aproxy_t *apr; - tcphdr_t *tcp = NULL; - u_32_t sum; - short rv; - int err; - - if (nat->nat_aps == NULL) - nat->nat_aps = appr_new_session(nat->nat_ptr->in_apr, ip, - fin, nat); - aps = nat->nat_aps; - if ((aps != NULL) && (aps->aps_p == ip->ip_p)) { - if (ip->ip_p == IPPROTO_TCP) { - tcp = (tcphdr_t *)fin->fin_dp; - /* - * verify that the checksum is correct. If not, then - * don't do anything with this packet. - */ -#if SOLARIS && defined(_KERNEL) - sum = fr_tcpsum(fin->fin_qfm, ip, tcp); -#else - sum = fr_tcpsum(*(mb_t **)fin->fin_mp, ip, tcp); -#endif - if (sum != tcp->th_sum) { - frstats[fin->fin_out].fr_tcpbad++; - return -1; - } - } - - apr = aps->aps_apr; - err = 0; - if (fin->fin_out != 0) { - if (apr->apr_outpkt != NULL) - err = (*apr->apr_outpkt)(fin, ip, aps, nat); - } else { - if (apr->apr_inpkt != NULL) - err = (*apr->apr_inpkt)(fin, ip, aps, nat); - } - - rv = APR_EXIT(err); - if (rv == -1) - return rv; - - if (tcp != NULL) { - err = appr_fixseqack(fin, ip, aps, APR_INC(err)); -#if SOLARIS && defined(_KERNEL) - tcp->th_sum = fr_tcpsum(fin->fin_qfm, ip, tcp); -#else - tcp->th_sum = fr_tcpsum(*(mb_t **)fin->fin_mp, ip, tcp); -#endif - } - aps->aps_bytes += ip->ip_len; - aps->aps_pkts++; - return 1; - } - return 0; -} - - -aproxy_t *appr_match(pr, name) -u_int pr; -char *name; -{ - aproxy_t *ap; - - for (ap = ap_proxies; ap->apr_p; ap++) - if ((ap->apr_p == pr) && - !strncmp(name, ap->apr_label, sizeof(ap->apr_label))) { - ap->apr_ref++; - return ap; - } - - for (ap = ap_proxylist; ap; ap = ap->apr_next) - if ((ap->apr_p == pr) && - !strncmp(name, ap->apr_label, sizeof(ap->apr_label))) { - ap->apr_ref++; - return ap; - } - return NULL; -} - - -void appr_free(ap) -aproxy_t *ap; -{ - ap->apr_ref--; -} - - -void aps_free(aps) -ap_session_t *aps; -{ - ap_session_t *a, **ap; - - if (!aps) - return; - - for (ap = &ap_sess_list; (a = *ap); ap = &a->aps_next) - if (a == aps) { - *ap = a->aps_next; - break; - } - - if ((aps->aps_data != NULL) && (aps->aps_psiz != 0)) - KFREES(aps->aps_data, aps->aps_psiz); - KFREE(aps); -} - - -static int appr_fixseqack(fin, ip, aps, inc) -fr_info_t *fin; -ip_t *ip; -ap_session_t *aps; -int inc; -{ - int sel, ch = 0, out, nlen; - u_32_t seq1, seq2; - tcphdr_t *tcp; - - tcp = (tcphdr_t *)fin->fin_dp; - out = fin->fin_out; - nlen = ip->ip_len; - nlen -= (ip->ip_hl << 2) + (tcp->th_off << 2); - - if (out != 0) { - seq1 = (u_32_t)ntohl(tcp->th_seq); - sel = aps->aps_sel[out]; - - /* switch to other set ? */ - if ((aps->aps_seqmin[!sel] > aps->aps_seqmin[sel]) && - (seq1 > aps->aps_seqmin[!sel])) - sel = aps->aps_sel[out] = !sel; - - if (aps->aps_seqoff[sel]) { - seq2 = aps->aps_seqmin[sel] - aps->aps_seqoff[sel]; - if (seq1 > seq2) { - seq2 = aps->aps_seqoff[sel]; - seq1 += seq2; - tcp->th_seq = htonl(seq1); - ch = 1; - } - } - - if (inc && (seq1 > aps->aps_seqmin[!sel])) { - aps->aps_seqmin[!sel] = seq1 + nlen - 1; - aps->aps_seqoff[!sel] = aps->aps_seqoff[sel] + inc; - } - - /***/ - - seq1 = ntohl(tcp->th_ack); - sel = aps->aps_sel[1 - out]; - - /* switch to other set ? */ - if ((aps->aps_ackmin[!sel] > aps->aps_ackmin[sel]) && - (seq1 > aps->aps_ackmin[!sel])) - sel = aps->aps_sel[1 - out] = !sel; - - if (aps->aps_ackoff[sel] && (seq1 > aps->aps_ackmin[sel])) { - seq2 = aps->aps_ackoff[sel]; - tcp->th_ack = htonl(seq1 - seq2); - ch = 1; - } - } else { - seq1 = ntohl(tcp->th_seq); - sel = aps->aps_sel[out]; - - /* switch to other set ? */ - if ((aps->aps_ackmin[!sel] > aps->aps_ackmin[sel]) && - (seq1 > aps->aps_ackmin[!sel])) - sel = aps->aps_sel[out] = !sel; - - if (aps->aps_ackoff[sel]) { - seq2 = aps->aps_ackmin[sel] - - aps->aps_ackoff[sel]; - if (seq1 > seq2) { - seq2 = aps->aps_ackoff[sel]; - seq1 += seq2; - tcp->th_seq = htonl(seq1); - ch = 1; - } - } - - if (inc && (seq1 > aps->aps_ackmin[!sel])) { - aps->aps_ackmin[!sel] = seq1 + nlen - 1; - aps->aps_ackoff[!sel] = aps->aps_ackoff[sel] + inc; - } - - /***/ - - seq1 = ntohl(tcp->th_ack); - sel = aps->aps_sel[1 - out]; - - /* switch to other set ? */ - if ((aps->aps_seqmin[!sel] > aps->aps_seqmin[sel]) && - (seq1 > aps->aps_seqmin[!sel])) - sel = aps->aps_sel[1 - out] = !sel; - - if (aps->aps_seqoff[sel] && (seq1 > aps->aps_seqmin[sel])) { - seq2 = aps->aps_seqoff[sel]; - tcp->th_ack = htonl(seq1 - seq2); - ch = 1; - } - } - return ch ? 2 : 0; -} - - -int appr_init() -{ - aproxy_t *ap; - int err = 0; - - for (ap = ap_proxies; ap->apr_p; ap++) { - err = (*ap->apr_init)(); - if (err != 0) - break; - } - return err; -} - - -void appr_unload() -{ - aproxy_t *ap; - - for (ap = ap_proxies; ap->apr_p; ap++) - if (ap->apr_fini) - (*ap->apr_fini)(); - for (ap = ap_proxylist; ap; ap = ap->apr_next) - if (ap->apr_fini) - (*ap->apr_fini)(); -} diff --git a/contrib/ipfilter/ip_proxy.h b/contrib/ipfilter/ip_proxy.h deleted file mode 100644 index 212900f..0000000 --- a/contrib/ipfilter/ip_proxy.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (C) 1997-2000 by Darren Reed. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - * - * $Id: ip_proxy.h,v 2.8.2.4 2000/12/02 00:15:03 darrenr Exp $ - */ - -#ifndef __IP_PROXY_H__ -#define __IP_PROXY_H__ - -#ifndef SOLARIS -#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) -#endif - -#ifndef APR_LABELLEN -#define APR_LABELLEN 16 -#endif -#define AP_SESS_SIZE 53 - -struct nat; -struct ipnat; - -typedef struct ap_tcp { - u_short apt_sport; /* source port */ - u_short apt_dport; /* destination port */ - short apt_sel[2]; /* {seq,ack}{off,min} set selector */ - short apt_seqoff[2]; /* sequence # difference */ - tcp_seq apt_seqmin[2]; /* don't change seq-off until after this */ - short apt_ackoff[2]; /* sequence # difference */ - tcp_seq apt_ackmin[2]; /* don't change seq-off until after this */ - u_char apt_state[2]; /* connection state */ -} ap_tcp_t; - -typedef struct ap_udp { - u_short apu_sport; /* source port */ - u_short apu_dport; /* destination port */ -} ap_udp_t; - -typedef struct ap_session { - struct aproxy *aps_apr; - union { - struct ap_tcp apu_tcp; - struct ap_udp apu_udp; - } aps_un; - u_int aps_flags; - U_QUAD_T aps_bytes; /* bytes sent */ - U_QUAD_T aps_pkts; /* packets sent */ - void *aps_nat; /* pointer back to nat struct */ - void *aps_data; /* private data */ - int aps_p; /* protocol */ - int aps_psiz; /* size of private data */ - struct ap_session *aps_hnext; - struct ap_session *aps_next; -} ap_session_t; - -#define aps_sport aps_un.apu_tcp.apt_sport -#define aps_dport aps_un.apu_tcp.apt_dport -#define aps_sel aps_un.apu_tcp.apt_sel -#define aps_seqoff aps_un.apu_tcp.apt_seqoff -#define aps_seqmin aps_un.apu_tcp.apt_seqmin -#define aps_state aps_un.apu_tcp.apt_state -#define aps_ackoff aps_un.apu_tcp.apt_ackoff -#define aps_ackmin aps_un.apu_tcp.apt_ackmin - - -typedef struct aproxy { - struct aproxy *apr_next; - char apr_label[APR_LABELLEN]; /* Proxy label # */ - u_char apr_p; /* protocol */ - int apr_ref; /* +1 per rule referencing it */ - int apr_flags; - int (* apr_init) __P((void)); - void (* apr_fini) __P((void)); - int (* apr_new) __P((fr_info_t *, ip_t *, - ap_session_t *, struct nat *)); - int (* apr_inpkt) __P((fr_info_t *, ip_t *, - ap_session_t *, struct nat *)); - int (* apr_outpkt) __P((fr_info_t *, ip_t *, - ap_session_t *, struct nat *)); -} aproxy_t; - -#define APR_DELETE 1 - -#define APR_ERR(x) (((x) & 0xffff) << 16) -#define APR_EXIT(x) (((x) >> 16) & 0xffff) -#define APR_INC(x) ((x) & 0xffff) - -#define FTP_BUFSZ 160 -/* - * For the ftp proxy. - */ -typedef struct ftpside { - char *ftps_rptr; - char *ftps_wptr; - u_32_t ftps_seq; - u_32_t ftps_len; - int ftps_junk; - char ftps_buf[FTP_BUFSZ]; -} ftpside_t; - -typedef struct ftpinfo { - u_int ftp_passok; - ftpside_t ftp_side[2]; -} ftpinfo_t; - -/* - * Real audio proxy structure and #defines - */ -typedef struct { - int rap_seenpna; - int rap_seenver; - int rap_version; - int rap_eos; /* End Of Startup */ - int rap_gotid; - int rap_gotlen; - int rap_mode; - int rap_sdone; - u_short rap_plport; - u_short rap_prport; - u_short rap_srport; - char rap_svr[19]; - u_32_t rap_sbf; /* flag to indicate which of the 19 bytes have - * been filled - */ - tcp_seq rap_sseq; -} raudio_t; - -#define RA_ID_END 0 -#define RA_ID_UDP 1 -#define RA_ID_ROBUST 7 - -#define RAP_M_UDP 1 -#define RAP_M_ROBUST 2 -#define RAP_M_TCP 4 -#define RAP_M_UDP_ROBUST (RAP_M_UDP|RAP_M_ROBUST) - - -extern ap_session_t *ap_sess_tab[AP_SESS_SIZE]; -extern ap_session_t *ap_sess_list; -extern aproxy_t ap_proxies[]; -extern int ippr_ftp_pasvonly; - -extern int appr_add __P((aproxy_t *)); -extern int appr_del __P((aproxy_t *)); -extern int appr_init __P((void)); -extern void appr_unload __P((void)); -extern int appr_ok __P((ip_t *, tcphdr_t *, struct ipnat *)); -extern void appr_free __P((aproxy_t *)); -extern void aps_free __P((ap_session_t *)); -extern int appr_check __P((ip_t *, fr_info_t *, struct nat *)); -extern aproxy_t *appr_match __P((u_int, char *)); - -#endif /* __IP_PROXY_H__ */ diff --git a/contrib/ipfilter/ip_raudio_pxy.c b/contrib/ipfilter/ip_raudio_pxy.c deleted file mode 100644 index 9ea437c..0000000 --- a/contrib/ipfilter/ip_raudio_pxy.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * $Id: ip_raudio_pxy.c,v 1.7.2.3 2000/10/27 22:54:04 darrenr Exp $ - */ -#if SOLARIS && defined(_KERNEL) -extern kmutex_t ipf_rw; -#endif - -#define IPF_RAUDIO_PROXY - - -int ippr_raudio_init __P((void)); -int ippr_raudio_new __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *)); -int ippr_raudio_in __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *)); -int ippr_raudio_out __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *)); - -static frentry_t raudiofr; - - -/* - * Real Audio application proxy initialization. - */ -int ippr_raudio_init() -{ - bzero((char *)&raudiofr, sizeof(raudiofr)); - raudiofr.fr_ref = 1; - raudiofr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE; - return 0; -} - - -/* - * Setup for a new proxy to handle Real Audio. - */ -int ippr_raudio_new(fin, ip, aps, nat) -fr_info_t *fin; -ip_t *ip; -ap_session_t *aps; -nat_t *nat; -{ - raudio_t *rap; - - - KMALLOCS(aps->aps_data, void *, sizeof(raudio_t)); - if (aps->aps_data == NULL) - return -1; - - bzero(aps->aps_data, sizeof(raudio_t)); - rap = aps->aps_data; - aps->aps_psiz = sizeof(raudio_t); - rap->rap_mode = RAP_M_TCP; /* default is for TCP */ - return 0; -} - - - -int ippr_raudio_out(fin, ip, aps, nat) -fr_info_t *fin; -ip_t *ip; -ap_session_t *aps; -nat_t *nat; -{ - raudio_t *rap = aps->aps_data; - unsigned char membuf[512 + 1], *s; - u_short id = 0; - tcphdr_t *tcp; - int off, dlen; - int len = 0; - mb_t *m; -#if SOLARIS - mb_t *m1; -#endif - - /* - * If we've already processed the start messages, then nothing left - * for the proxy to do. - */ - if (rap->rap_eos == 1) - return 0; - - tcp = (tcphdr_t *)fin->fin_dp; - off = (ip->ip_hl << 2) + (tcp->th_off << 2); - bzero(membuf, sizeof(membuf)); -#if SOLARIS - m = fin->fin_qfm; - - dlen = msgdsize(m) - off; - if (dlen <= 0) - return 0; - copyout_mblk(m, off, MIN(sizeof(membuf), dlen), (char *)membuf); -#else - m = *(mb_t **)fin->fin_mp; - - dlen = mbufchainlen(m) - off; - if (dlen <= 0) - return 0; - m_copydata(m, off, MIN(sizeof(membuf), dlen), (char *)membuf); -#endif - /* - * In all the startup parsing, ensure that we don't go outside - * the packet buffer boundary. - */ - /* - * Look for the start of connection "PNA" string if not seen yet. - */ - if (rap->rap_seenpna == 0) { - s = (u_char *)memstr("PNA", (char *)membuf, 3, dlen); - if (s == NULL) - return 0; - s += 3; - rap->rap_seenpna = 1; - } else - s = membuf; - - /* - * Directly after the PNA will be the version number of this - * connection. - */ - if (rap->rap_seenpna == 1 && rap->rap_seenver == 0) { - if ((s + 1) - membuf < dlen) { - rap->rap_version = (*s << 8) | *(s + 1); - s += 2; - rap->rap_seenver = 1; - } else - return 0; - } - - /* - * Now that we've been past the PNA and version number, we're into the - * startup messages block. This ends when a message with an ID of 0. - */ - while ((rap->rap_eos == 0) && ((s + 1) - membuf < dlen)) { - if (rap->rap_gotid == 0) { - id = (*s << 8) | *(s + 1); - s += 2; - rap->rap_gotid = 1; - if (id == RA_ID_END) { - rap->rap_eos = 1; - break; - } - } else if (rap->rap_gotlen == 0) { - len = (*s << 8) | *(s + 1); - s += 2; - rap->rap_gotlen = 1; - } - - if (rap->rap_gotid == 1 && rap->rap_gotlen == 1) { - if (id == RA_ID_UDP) { - rap->rap_mode &= ~RAP_M_TCP; - rap->rap_mode |= RAP_M_UDP; - rap->rap_plport = (*s << 8) | *(s + 1); - } else if (id == RA_ID_ROBUST) { - rap->rap_mode |= RAP_M_ROBUST; - rap->rap_prport = (*s << 8) | *(s + 1); - } - s += len; - rap->rap_gotlen = 0; - rap->rap_gotid = 0; - } - } - return 0; -} - - -int ippr_raudio_in(fin, ip, aps, nat) -fr_info_t *fin; -ip_t *ip; -ap_session_t *aps; -nat_t *nat; -{ - unsigned char membuf[IPF_MAXPORTLEN + 1], *s; - tcphdr_t *tcp, tcph, *tcp2 = &tcph; - raudio_t *rap = aps->aps_data; - struct in_addr swa, swb; - int off, dlen, slen; - int a1, a2, a3, a4; - u_short sp, dp; - fr_info_t fi; - tcp_seq seq; - nat_t *ipn; - u_char swp; - mb_t *m; -#if SOLARIS - mb_t *m1; -#endif - - /* - * Wait until we've seen the end of the start messages and even then - * only proceed further if we're using UDP. If they want to use TCP - * then data is sent back on the same channel that is already open. - */ - if (rap->rap_sdone != 0) - return 0; - - tcp = (tcphdr_t *)fin->fin_dp; - off = (ip->ip_hl << 2) + (tcp->th_off << 2); - m = *(mb_t **)fin->fin_mp; - -#if SOLARIS - m = fin->fin_qfm; - - dlen = msgdsize(m) - off; - if (dlen <= 0) - return 0; - bzero(membuf, sizeof(membuf)); - copyout_mblk(m, off, MIN(sizeof(membuf), dlen), (char *)membuf); -#else - dlen = mbufchainlen(m) - off; - if (dlen <= 0) - return 0; - bzero(membuf, sizeof(membuf)); - m_copydata(m, off, MIN(sizeof(membuf), dlen), (char *)membuf); -#endif - - seq = ntohl(tcp->th_seq); - /* - * Check to see if the data in this packet is of interest to us. - * We only care for the first 19 bytes coming back from the server. - */ - if (rap->rap_sseq == 0) { - s = (u_char *)memstr("PNA", (char *)membuf, 3, dlen); - if (s == NULL) - return 0; - a1 = s - membuf; - dlen -= a1; - a1 = 0; - rap->rap_sseq = seq; - a2 = MIN(dlen, sizeof(rap->rap_svr)); - } else if (seq <= rap->rap_sseq + sizeof(rap->rap_svr)) { - /* - * seq # which is the start of data and from that the offset - * into the buffer array. - */ - a1 = seq - rap->rap_sseq; - a2 = MIN(dlen, sizeof(rap->rap_svr)); - a2 -= a1; - s = membuf; - } else - return 0; - - for (a3 = a1, a4 = a2; (a4 > 0) && (a3 < 19) && (a3 >= 0); a4--,a3++) { - rap->rap_sbf |= (1 << a3); - rap->rap_svr[a3] = *s++; - } - - if ((rap->rap_sbf != 0x7ffff) || (!rap->rap_eos)) /* 19 bits */ - return 0; - rap->rap_sdone = 1; - - s = (u_char *)rap->rap_svr + 11; - if (((*s << 8) | *(s + 1)) == RA_ID_ROBUST) { - s += 2; - rap->rap_srport = (*s << 8) | *(s + 1); - } - - swp = ip->ip_p; - swa = ip->ip_src; - swb = ip->ip_dst; - - ip->ip_p = IPPROTO_UDP; - ip->ip_src = nat->nat_inip; - ip->ip_dst = nat->nat_oip; - - bcopy((char *)fin, (char *)&fi, sizeof(fi)); - bzero((char *)tcp2, sizeof(*tcp2)); - tcp2->th_off = 5; - fi.fin_dp = (char *)tcp2; - fi.fin_fr = &raudiofr; - fi.fin_dlen = sizeof(*tcp2); - tcp2->th_win = htons(8192); - slen = ip->ip_len; - ip->ip_len = fin->fin_hlen + sizeof(*tcp); - - if (((rap->rap_mode & RAP_M_UDP_ROBUST) == RAP_M_UDP_ROBUST) && - (rap->rap_srport != 0)) { - dp = rap->rap_srport; - sp = rap->rap_prport; - tcp2->th_sport = htons(sp); - tcp2->th_dport = htons(dp); - fi.fin_data[0] = dp; - fi.fin_data[1] = sp; - ipn = nat_new(nat->nat_ptr, ip, &fi, - IPN_UDP | (sp ? 0 : FI_W_SPORT), NAT_OUTBOUND); - if (ipn != NULL) { - ipn->nat_age = fr_defnatage; - (void) fr_addstate(ip, &fi, sp ? 0 : FI_W_SPORT); - } - } - - if ((rap->rap_mode & RAP_M_UDP) == RAP_M_UDP) { - sp = rap->rap_plport; - tcp2->th_sport = htons(sp); - tcp2->th_dport = 0; /* XXX - don't specify remote port */ - fi.fin_data[0] = sp; - fi.fin_data[1] = 0; - ipn = nat_new(nat->nat_ptr, ip, &fi, IPN_UDP|FI_W_DPORT, - NAT_OUTBOUND); - if (ipn != NULL) { - ipn->nat_age = fr_defnatage; - (void) fr_addstate(ip, &fi, FI_W_DPORT); - } - } - - ip->ip_p = swp; - ip->ip_len = slen; - ip->ip_src = swa; - ip->ip_dst = swb; - return 0; -} diff --git a/contrib/ipfilter/ip_rcmd_pxy.c b/contrib/ipfilter/ip_rcmd_pxy.c deleted file mode 100644 index d017cf9..0000000 --- a/contrib/ipfilter/ip_rcmd_pxy.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * $Id: ip_rcmd_pxy.c,v 1.4.2.4 2000/11/01 14:34:20 darrenr Exp $ - */ -/* - * Simple RCMD transparent proxy for in-kernel use. For use with the NAT - * code. - */ -#if SOLARIS && defined(_KERNEL) -extern kmutex_t ipf_rw; -#endif - -#define isdigit(x) ((x) >= '0' && (x) <= '9') - -#define IPF_RCMD_PROXY - - -int ippr_rcmd_init __P((void)); -int ippr_rcmd_new __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *)); -int ippr_rcmd_out __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *)); -u_short ipf_rcmd_atoi __P((char *)); -int ippr_rcmd_portmsg __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *)); - -static frentry_t rcmdfr; - - -/* - * RCMD application proxy initialization. - */ -int ippr_rcmd_init() -{ - bzero((char *)&rcmdfr, sizeof(rcmdfr)); - rcmdfr.fr_ref = 1; - rcmdfr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE; - return 0; -} - - -/* - * Setup for a new RCMD proxy. - */ -int ippr_rcmd_new(fin, ip, aps, nat) -fr_info_t *fin; -ip_t *ip; -ap_session_t *aps; -nat_t *nat; -{ - tcphdr_t *tcp = (tcphdr_t *)fin->fin_dp; - - aps->aps_psiz = sizeof(u_32_t); - KMALLOCS(aps->aps_data, u_32_t *, sizeof(u_32_t)); - if (aps->aps_data == NULL) - return -1; - *(u_32_t *)aps->aps_data = 0; - aps->aps_sport = tcp->th_sport; - aps->aps_dport = tcp->th_dport; - return 0; -} - - -/* - * ipf_rcmd_atoi - implement a simple version of atoi - */ -u_short ipf_rcmd_atoi(ptr) -char *ptr; -{ - register char *s = ptr, c; - register u_short i = 0; - - while ((c = *s++) && isdigit(c)) { - i *= 10; - i += c - '0'; - } - return i; -} - - -int ippr_rcmd_portmsg(fin, ip, aps, nat) -fr_info_t *fin; -ip_t *ip; -ap_session_t *aps; -nat_t *nat; -{ - char portbuf[8], *s; - struct in_addr swip; - u_short sp, dp; - int off, dlen; - tcphdr_t *tcp, tcph, *tcp2 = &tcph; - fr_info_t fi; - nat_t *ipn; - mb_t *m; -#if SOLARIS - mb_t *m1; -#endif - - tcp = (tcphdr_t *)fin->fin_dp; - - if (tcp->th_flags & TH_SYN) { - *(u_32_t *)aps->aps_data = htonl(ntohl(tcp->th_seq) + 1); - return 0; - } - - if ((*(u_32_t *)aps->aps_data != 0) && - (tcp->th_seq != *(u_32_t *)aps->aps_data)) - return 0; - - off = (ip->ip_hl << 2) + (tcp->th_off << 2); - -#if SOLARIS - m = fin->fin_qfm; - - dlen = msgdsize(m) - off; - bzero(portbuf, sizeof(portbuf)); - copyout_mblk(m, off, MIN(sizeof(portbuf), dlen), portbuf); -#else - m = *(mb_t **)fin->fin_mp; - dlen = mbufchainlen(m) - off; - bzero(portbuf, sizeof(portbuf)); - m_copydata(m, off, MIN(sizeof(portbuf), dlen), portbuf); -#endif - - portbuf[sizeof(portbuf) - 1] = '\0'; - s = portbuf; - sp = ipf_rcmd_atoi(s); - if (!sp) - return 0; - - /* - * Add skeleton NAT entry for connection which will come back the - * other way. - */ - sp = htons(sp); - dp = htons(fin->fin_data[1]); - ipn = nat_outlookup(fin->fin_ifp, IPN_TCP, nat->nat_p, nat->nat_inip, - ip->ip_dst, (dp << 16) | sp, 0); - if (ipn == NULL) { - int slen; - - slen = ip->ip_len; - ip->ip_len = fin->fin_hlen + sizeof(*tcp); - bcopy((char *)fin, (char *)&fi, sizeof(fi)); - bzero((char *)tcp2, sizeof(*tcp2)); - tcp2->th_win = htons(8192); - tcp2->th_sport = sp; - tcp2->th_dport = 0; /* XXX - don't specify remote port */ - tcp2->th_off = 5; - fi.fin_data[0] = ntohs(sp); - fi.fin_data[1] = 0; - fi.fin_dp = (char *)tcp2; - fi.fin_dlen = sizeof(*tcp2); - swip = ip->ip_src; - ip->ip_src = nat->nat_inip; - ipn = nat_new(nat->nat_ptr, ip, &fi, IPN_TCP|FI_W_DPORT, - NAT_OUTBOUND); - if (ipn != NULL) { - ipn->nat_age = fr_defnatage; - fi.fin_fr = &rcmdfr; - (void) fr_addstate(ip, &fi, FI_W_DPORT); - } - ip->ip_len = slen; - ip->ip_src = swip; - } - return 0; -} - - -int ippr_rcmd_out(fin, ip, aps, nat) -fr_info_t *fin; -ip_t *ip; -ap_session_t *aps; -nat_t *nat; -{ - return ippr_rcmd_portmsg(fin, ip, aps, nat); -} diff --git a/contrib/ipfilter/ip_state.c b/contrib/ipfilter/ip_state.c deleted file mode 100644 index 5d63969..0000000 --- a/contrib/ipfilter/ip_state.c +++ /dev/null @@ -1,1901 +0,0 @@ -/* - * Copyright (C) 1995-2000 by Darren Reed. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - */ -#if !defined(lint) -static const char sccsid[] = "@(#)ip_state.c 1.8 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_state.c,v 2.30.2.28 2001/01/08 14:04:46 darrenr Exp $"; -#endif - -#include <sys/errno.h> -#include <sys/types.h> -#include <sys/param.h> -#include <sys/file.h> -#if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \ - defined(_KERNEL) -# include "opt_ipfilter_log.h" -#endif -#if defined(_KERNEL) && defined(__FreeBSD_version) && \ - (__FreeBSD_version >= 400000) && !defined(KLD_MODULE) -#include "opt_inet6.h" -#endif -#if !defined(_KERNEL) && !defined(KERNEL) && !defined(__KERNEL__) -# include <stdio.h> -# include <stdlib.h> -# include <string.h> -#else -# ifdef linux -# include <linux/kernel.h> -# include <linux/module.h> -# endif -#endif -#if (defined(KERNEL) || defined(_KERNEL)) && (__FreeBSD_version >= 220000) -# include <sys/filio.h> -# include <sys/fcntl.h> -# if (__FreeBSD_version >= 300000) && !defined(IPFILTER_LKM) -# include "opt_ipfilter.h" -# endif -#else -# include <sys/ioctl.h> -#endif -#include <sys/time.h> -#include <sys/uio.h> -#ifndef linux -# include <sys/protosw.h> -#endif -#include <sys/socket.h> -#if (defined(_KERNEL) || defined(KERNEL)) && !defined(linux) -# include <sys/systm.h> -#endif -#if !defined(__SVR4) && !defined(__svr4__) -# ifndef linux -# include <sys/mbuf.h> -# endif -#else -# include <sys/filio.h> -# include <sys/byteorder.h> -# ifdef _KERNEL -# include <sys/dditypes.h> -# endif -# include <sys/stream.h> -# include <sys/kmem.h> -#endif - -#include <net/if.h> -#ifdef sun -# include <net/af.h> -#endif -#include <net/route.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/tcp.h> -#ifndef linux -# include <netinet/ip_var.h> -# include <netinet/tcp_fsm.h> -#endif -#include <netinet/udp.h> -#include <netinet/ip_icmp.h> -#include "netinet/ip_compat.h" -#include <netinet/tcpip.h> -#include "netinet/ip_fil.h" -#include "netinet/ip_nat.h" -#include "netinet/ip_frag.h" -#include "netinet/ip_proxy.h" -#include "netinet/ip_state.h" -#ifdef USE_INET6 -#include <netinet/icmp6.h> -#endif -#if (__FreeBSD_version >= 300000) -# include <sys/malloc.h> -# if (defined(_KERNEL) || defined(KERNEL)) && !defined(IPFILTER_LKM) -# include <sys/libkern.h> -# include <sys/systm.h> -# endif -#endif - -#ifndef MIN -# define MIN(a,b) (((a)<(b))?(a):(b)) -#endif - -#define TCP_CLOSE (TH_FIN|TH_RST) - -static ipstate_t **ips_table = NULL; -static ipstate_t *ips_list = NULL; -static int ips_num = 0; -static int ips_wild = 0; -static ips_stat_t ips_stats; -#if (SOLARIS || defined(__sgi)) && defined(_KERNEL) -extern KRWLOCK_T ipf_state, ipf_mutex; -extern kmutex_t ipf_rw; -#endif - -#ifdef USE_INET6 -static frentry_t *fr_checkicmp6matchingstate __P((ip6_t *, fr_info_t *)); -#endif -static int fr_matchsrcdst __P((ipstate_t *, union i6addr, union i6addr, - fr_info_t *, tcphdr_t *)); -static frentry_t *fr_checkicmpmatchingstate __P((ip_t *, fr_info_t *)); -static int fr_matchicmpqueryreply __P((int, ipstate_t *, icmphdr_t *)); -static int fr_state_flush __P((int)); -static ips_stat_t *fr_statetstats __P((void)); -static void fr_delstate __P((ipstate_t *)); -static int fr_state_remove __P((caddr_t)); -static void fr_ipsmove __P((ipstate_t **, ipstate_t *, u_int)); -int fr_stputent __P((caddr_t)); -int fr_stgetent __P((caddr_t)); -void fr_stinsert __P((ipstate_t *)); - - -#define FIVE_DAYS (2 * 5 * 86400) /* 5 days: half closed session */ - -#define TCP_MSL 240 /* 2 minutes */ -u_long fr_tcpidletimeout = FIVE_DAYS, - fr_tcpclosewait = 2 * TCP_MSL, - fr_tcplastack = 2 * TCP_MSL, - fr_tcptimeout = 2 * TCP_MSL, - fr_tcpclosed = 120, - fr_tcphalfclosed = 2 * 2 * 3600, /* 2 hours */ - fr_udptimeout = 240, - fr_icmptimeout = 120; -int fr_statemax = IPSTATE_MAX, - fr_statesize = IPSTATE_SIZE; -int fr_state_doflush = 0, - fr_state_lock = 0; - -static int icmpreplytype4[ICMP_MAXTYPE + 1]; - -int fr_stateinit() -{ - int i; - - KMALLOCS(ips_table, ipstate_t **, fr_statesize * sizeof(ipstate_t *)); - if (ips_table != NULL) - bzero((char *)ips_table, fr_statesize * sizeof(ipstate_t *)); - else - return -1; - - /* fill icmp reply type table */ - for (i = 0; i <= ICMP_MAXTYPE; i++) - icmpreplytype4[i] = -1; - icmpreplytype4[ICMP_ECHO] = ICMP_ECHOREPLY; - icmpreplytype4[ICMP_TSTAMP] = ICMP_TSTAMPREPLY; - icmpreplytype4[ICMP_IREQ] = ICMP_IREQREPLY; - icmpreplytype4[ICMP_MASKREQ] = ICMP_MASKREPLY; - - return 0; -} - - -static ips_stat_t *fr_statetstats() -{ - ips_stats.iss_active = ips_num; - ips_stats.iss_table = ips_table; - ips_stats.iss_list = ips_list; - return &ips_stats; -} - - -/* - * flush state tables. two actions currently defined: - * which == 0 : flush all state table entries - * which == 1 : flush TCP connections which have started to close but are - * stuck for some reason. - */ -static int fr_state_flush(which) -int which; -{ - register ipstate_t *is, **isp; -#if defined(_KERNEL) && !SOLARIS - int s; -#endif - int delete, removed = 0; - - SPL_NET(s); - for (isp = &ips_list; (is = *isp); ) { - delete = 0; - - switch (which) - { - case 0 : - delete = 1; - break; - case 1 : - if (is->is_p != IPPROTO_TCP) - break; - if ((is->is_state[0] != TCPS_ESTABLISHED) || - (is->is_state[1] != TCPS_ESTABLISHED)) - delete = 1; - break; - } - - if (delete) { - if (is->is_p == IPPROTO_TCP) - ips_stats.iss_fin++; - else - ips_stats.iss_expire++; -#ifdef IPFILTER_LOG - ipstate_log(is, ISL_FLUSH); -#endif - fr_delstate(is); - removed++; - } else - isp = &is->is_next; - } - SPL_X(s); - return removed; -} - - -static int fr_state_remove(data) -caddr_t data; -{ - ipstate_t *sp, st; - int error; - - sp = &st; - error = IRCOPYPTR(data, (caddr_t)&st, sizeof(st)); - if (error) - return EFAULT; - - for (sp = ips_list; sp; sp = sp->is_next) - if ((sp->is_p == st.is_p) && (sp->is_v == st.is_v) && - !bcmp((char *)&sp->is_src, (char *)&st.is_src, - sizeof(st.is_src)) && - !bcmp((char *)&sp->is_dst, (char *)&st.is_src, - sizeof(st.is_dst)) && - !bcmp((char *)&sp->is_ps, (char *)&st.is_ps, - sizeof(st.is_ps))) { - WRITE_ENTER(&ipf_state); -#ifdef IPFILTER_LOG - ipstate_log(sp, ISL_REMOVE); -#endif - fr_delstate(sp); - RWLOCK_EXIT(&ipf_state); - return 0; - } - return ESRCH; -} - - -int fr_state_ioctl(data, cmd, mode) -caddr_t data; -#if defined(__NetBSD__) || defined(__OpenBSD__) -u_long cmd; -#else -int cmd; -#endif -int mode; -{ - int arg, ret, error = 0; - - switch (cmd) - { - case SIOCDELST : - error = fr_state_remove(data); - break; - case SIOCIPFFL : - error = IRCOPY(data, (caddr_t)&arg, sizeof(arg)); - if (error) - break; - if (arg == 0 || arg == 1) { - WRITE_ENTER(&ipf_state); - ret = fr_state_flush(arg); - RWLOCK_EXIT(&ipf_state); - error = IWCOPY((caddr_t)&ret, data, sizeof(ret)); - } else - error = EINVAL; - break; -#ifdef IPFILTER_LOG - case SIOCIPFFB : - if (!(mode & FWRITE)) - error = EPERM; - else { - int tmp; - - tmp = ipflog_clear(IPL_LOGSTATE); - IWCOPY((char *)&tmp, data, sizeof(tmp)); - } - break; -#endif - case SIOCGETFS : - error = IWCOPYPTR((caddr_t)fr_statetstats(), data, - sizeof(ips_stat_t)); - break; - case FIONREAD : -#ifdef IPFILTER_LOG - arg = (int)iplused[IPL_LOGSTATE]; - error = IWCOPY((caddr_t)&arg, (caddr_t)data, sizeof(arg)); -#endif - break; - case SIOCSTLCK : - error = fr_lock(data, &fr_state_lock); - break; - case SIOCSTPUT : - if (!fr_state_lock) { - error = EACCES; - break; - } - error = fr_stputent(data); - break; - case SIOCSTGET : - if (!fr_state_lock) { - error = EACCES; - break; - } - error = fr_stgetent(data); - break; - default : - error = EINVAL; - break; - } - return error; -} - - -int fr_stgetent(data) -caddr_t data; -{ - register ipstate_t *is, *isn; - ipstate_save_t ips, *ipsp; - int error; - - error = IRCOPY(data, (caddr_t)&ipsp, sizeof(ipsp)); - if (error) - return EFAULT; - error = IRCOPY((caddr_t)ipsp, (caddr_t)&ips, sizeof(ips)); - if (error) - return EFAULT; - - isn = ips.ips_next; - if (!isn) { - isn = ips_list; - if (isn == NULL) { - if (ips.ips_next == NULL) - return ENOENT; - return 0; - } - } else { - /* - * Make sure the pointer we're copying from exists in the - * current list of entries. Security precaution to prevent - * copying of random kernel data. - */ - for (is = ips_list; is; is = is->is_next) - if (is == isn) - break; - if (!is) - return ESRCH; - } - ips.ips_next = isn->is_next; - bcopy((char *)isn, (char *)&ips.ips_is, sizeof(ips.ips_is)); - if (isn->is_rule) - bcopy((char *)isn->is_rule, (char *)&ips.ips_fr, - sizeof(ips.ips_fr)); - error = IWCOPY((caddr_t)&ips, ipsp, sizeof(ips)); - if (error) - error = EFAULT; - return error; -} - - -int fr_stputent(data) -caddr_t data; -{ - register ipstate_t *is, *isn; - ipstate_save_t ips, *ipsp; - int error, out; - frentry_t *fr; - - error = IRCOPY(data, (caddr_t)&ipsp, sizeof(ipsp)); - if (error) - return EFAULT; - error = IRCOPY((caddr_t)ipsp, (caddr_t)&ips, sizeof(ips)); - if (error) - return EFAULT; - - KMALLOC(isn, ipstate_t *); - if (isn == NULL) - return ENOMEM; - - bcopy((char *)&ips.ips_is, (char *)isn, sizeof(*isn)); - fr = isn->is_rule; - if (fr != NULL) { - if (isn->is_flags & FI_NEWFR) { - KMALLOC(fr, frentry_t *); - if (fr == NULL) { - KFREE(isn); - return ENOMEM; - } - bcopy((char *)&ips.ips_fr, (char *)fr, sizeof(*fr)); - out = fr->fr_flags & FR_OUTQUE ? 1 : 0; - isn->is_rule = fr; - ips.ips_is.is_rule = fr; - if (*fr->fr_ifname) { - fr->fr_ifa = GETUNIT(fr->fr_ifname, fr->fr_v); - if (fr->fr_ifa == NULL) - fr->fr_ifa = (void *)-1; -#ifdef _KERNEL - else { - strncpy(isn->is_ifname[out], - IFNAME(fr->fr_ifa), IFNAMSIZ); - isn->is_ifp[out] = fr->fr_ifa; - } -#endif - } else - fr->fr_ifa = NULL; - /* - * send a copy back to userland of what we ended up - * to allow for verification. - */ - error = IWCOPY((caddr_t)&ips, ipsp, sizeof(ips)); - if (error) { - KFREE(isn); - KFREE(fr); - return EFAULT; - } - } else { - for (is = ips_list; is; is = is->is_next) - if (is->is_rule == fr) - break; - if (!is) { - KFREE(isn); - return ESRCH; - } - } - } - fr_stinsert(isn); - return 0; -} - - -void fr_stinsert(is) -register ipstate_t *is; -{ - register u_int hv = is->is_hv; - - MUTEX_INIT(&is->is_lock, "ipf state entry", NULL); - - is->is_ifname[0][sizeof(is->is_ifname[0]) - 1] = '\0'; - if (is->is_ifname[0][0] != '\0') { - is->is_ifp[0] = GETUNIT(is->is_ifname[0], is->is_v); - } - is->is_ifname[1][sizeof(is->is_ifname[0]) - 1] = '\0'; - if (is->is_ifname[1][0] != '\0') { - is->is_ifp[1] = GETUNIT(is->is_ifname[1], is->is_v); - } - - /* - * add into list table. - */ - if (ips_list) - ips_list->is_pnext = &is->is_next; - is->is_pnext = &ips_list; - is->is_next = ips_list; - ips_list = is; - if (ips_table[hv]) - ips_table[hv]->is_phnext = &is->is_hnext; - else - ips_stats.iss_inuse++; - is->is_phnext = ips_table + hv; - is->is_hnext = ips_table[hv]; - ips_table[hv] = is; - ips_num++; -} - - -/* - * Create a new ipstate structure and hang it off the hash table. - */ -ipstate_t *fr_addstate(ip, fin, flags) -ip_t *ip; -fr_info_t *fin; -u_int flags; -{ - register tcphdr_t *tcp = NULL; - register ipstate_t *is; - register u_int hv; - ipstate_t ips; - u_int pass; - int out; - - if (fr_state_lock || (fin->fin_off & IP_OFFMASK) || - (fin->fin_fi.fi_fl & FI_SHORT)) - return NULL; - if (ips_num == fr_statemax) { - ips_stats.iss_max++; - fr_state_doflush = 1; - return NULL; - } - out = fin->fin_out; - is = &ips; - bzero((char *)is, sizeof(*is)); - ips.is_age = 1; - ips.is_state[0] = 0; - ips.is_state[1] = 0; - /* - * Copy and calculate... - */ - hv = (is->is_p = fin->fin_fi.fi_p); - is->is_src = fin->fin_fi.fi_src; - hv += is->is_saddr; - is->is_dst = fin->fin_fi.fi_dst; - hv += is->is_daddr; -#ifdef USE_INET6 - if (fin->fin_v == 6) { - if (is->is_p == IPPROTO_ICMPV6) { - if (IN6_IS_ADDR_MULTICAST(&is->is_dst.in6)) - flags |= FI_W_DADDR; - if (out) - hv -= is->is_daddr; - else - hv -= is->is_saddr; - } - } -#endif - - switch (is->is_p) - { -#ifdef USE_INET6 - case IPPROTO_ICMPV6 : -#endif - case IPPROTO_ICMP : - { - struct icmp *ic = (struct icmp *)fin->fin_dp; - -#ifdef USE_INET6 - if ((is->is_p == IPPROTO_ICMPV6) && - ((ic->icmp_type & ICMP6_INFOMSG_MASK) == 0)) - return NULL; -#endif - switch (ic->icmp_type) - { -#ifdef USE_INET6 - case ICMP6_ECHO_REQUEST : - is->is_icmp.ics_type = ICMP6_ECHO_REPLY; - hv += (is->is_icmp.ics_id = ic->icmp_id); - hv += (is->is_icmp.ics_seq = ic->icmp_seq); - break; - case ICMP6_MEMBERSHIP_QUERY : - case ND_ROUTER_SOLICIT : - case ND_NEIGHBOR_SOLICIT : - is->is_icmp.ics_type = ic->icmp_type + 1; - break; -#endif - case ICMP_ECHO : - case ICMP_TSTAMP : - case ICMP_IREQ : - case ICMP_MASKREQ : - is->is_icmp.ics_type = ic->icmp_type; - hv += (is->is_icmp.ics_id = ic->icmp_id); - hv += (is->is_icmp.ics_seq = ic->icmp_seq); - break; - default : - return NULL; - } - ATOMIC_INCL(ips_stats.iss_icmp); - is->is_age = fr_icmptimeout; - break; - } - case IPPROTO_TCP : - { - tcp = (tcphdr_t *)fin->fin_dp; - - if (tcp->th_flags & TH_RST) - return NULL; - /* - * The endian of the ports doesn't matter, but the ack and - * sequence numbers do as we do mathematics on them later. - */ - is->is_dport = tcp->th_dport; - is->is_sport = tcp->th_sport; - if ((flags & (FI_W_DPORT|FI_W_SPORT)) == 0) { - hv += tcp->th_dport; - hv += tcp->th_sport; - } - is->is_send = ntohl(tcp->th_seq) + fin->fin_dlen - - (tcp->th_off << 2) + - ((tcp->th_flags & TH_SYN) ? 1 : 0) + - ((tcp->th_flags & TH_FIN) ? 1 : 0); - is->is_maxsend = is->is_send; - is->is_dend = 0; - is->is_maxdwin = 1; - is->is_maxswin = ntohs(tcp->th_win); - if (is->is_maxswin == 0) - is->is_maxswin = 1; - /* - * If we're creating state for a starting connection, start the - * timer on it as we'll never see an error if it fails to - * connect. - */ - ATOMIC_INCL(ips_stats.iss_tcp); - break; - } - case IPPROTO_UDP : - { - tcp = (tcphdr_t *)fin->fin_dp; - - is->is_dport = tcp->th_dport; - is->is_sport = tcp->th_sport; - if ((flags & (FI_W_DPORT|FI_W_SPORT)) == 0) { - hv += tcp->th_dport; - hv += tcp->th_sport; - } - ATOMIC_INCL(ips_stats.iss_udp); - is->is_age = fr_udptimeout; - break; - } - default : - return NULL; - } - - KMALLOC(is, ipstate_t *); - if (is == NULL) { - ATOMIC_INCL(ips_stats.iss_nomem); - return NULL; - } - bcopy((char *)&ips, (char *)is, sizeof(*is)); - hv %= fr_statesize; - is->is_hv = hv; - is->is_rule = fin->fin_fr; - if (is->is_rule != NULL) { - ATOMIC_INC32(is->is_rule->fr_ref); - pass = is->is_rule->fr_flags; - } else - pass = fr_flags; - WRITE_ENTER(&ipf_state); - - is->is_pass = pass; - is->is_pkts = 1; - is->is_bytes = fin->fin_dlen + fin->fin_hlen; - /* - * We want to check everything that is a property of this packet, - * but we don't (automatically) care about it's fragment status as - * this may change. - */ - is->is_v = fin->fin_fi.fi_v; - is->is_opt = fin->fin_fi.fi_optmsk; - is->is_optmsk = 0xffffffff; - is->is_sec = fin->fin_fi.fi_secmsk; - is->is_secmsk = 0xffff; - is->is_auth = fin->fin_fi.fi_auth; - is->is_authmsk = 0xffff; - is->is_flags = fin->fin_fi.fi_fl & FI_CMP; - is->is_flags |= FI_CMP << 4; - is->is_flags |= flags & (FI_WILDP|FI_WILDA); - if (flags & (FI_WILDP|FI_WILDA)) - ips_wild++; - is->is_ifp[1 - out] = NULL; - is->is_ifp[out] = fin->fin_ifp; -#ifdef _KERNEL - strncpy(is->is_ifname[out], IFNAME(fin->fin_ifp), IFNAMSIZ); -#endif - is->is_ifname[1 - out][0] = '\0'; - if (pass & FR_LOGFIRST) - is->is_pass &= ~(FR_LOGFIRST|FR_LOG); - fr_stinsert(is); - if (is->is_p == IPPROTO_TCP) { - MUTEX_ENTER(&is->is_lock); - fr_tcp_age(&is->is_age, is->is_state, fin, - 0); /* 0 = packet from the source */ - MUTEX_EXIT(&is->is_lock); - } -#ifdef IPFILTER_LOG - ipstate_log(is, ISL_NEW); -#endif - RWLOCK_EXIT(&ipf_state); - fin->fin_rev = IP6NEQ(is->is_dst, fin->fin_fi.fi_dst); - if (fin->fin_fi.fi_fl & FI_FRAG) - ipfr_newfrag(ip, fin, pass ^ FR_KEEPSTATE); - return is; -} - - - -/* - * check to see if a packet with TCP headers fits within the TCP window. - * change timeout depending on whether new packet is a SYN-ACK returning for a - * SYN or a RST or FIN which indicate time to close up shop. - */ -int fr_tcpstate(is, fin, ip, tcp) -register ipstate_t *is; -fr_info_t *fin; -ip_t *ip; -tcphdr_t *tcp; -{ - register tcp_seq seq, ack, end; - register int ackskew; - tcpdata_t *fdata, *tdata; - u_short win, maxwin; - int ret = 0; - int source; - - /* - * Find difference between last checked packet and this packet. - */ - source = IP6EQ(fin->fin_fi.fi_src, is->is_src); - fdata = &is->is_tcp.ts_data[!source]; - tdata = &is->is_tcp.ts_data[source]; - seq = ntohl(tcp->th_seq); - ack = ntohl(tcp->th_ack); - win = ntohs(tcp->th_win); - end = seq + fin->fin_dlen - (tcp->th_off << 2) + - ((tcp->th_flags & TH_SYN) ? 1 : 0) + - ((tcp->th_flags & TH_FIN) ? 1 : 0); - - MUTEX_ENTER(&is->is_lock); - if (fdata->td_end == 0) { - /* - * Must be a (outgoing) SYN-ACK in reply to a SYN. - */ - fdata->td_end = end; - fdata->td_maxwin = 1; - fdata->td_maxend = end + 1; - } - - if (!(tcp->th_flags & TH_ACK)) { /* Pretend an ack was sent */ - ack = tdata->td_end; - } else if (((tcp->th_flags & (TH_ACK|TH_RST)) == (TH_ACK|TH_RST)) && - (ack == 0)) { - /* gross hack to get around certain broken tcp stacks */ - ack = tdata->td_end; - } - - if (seq == end) - seq = end = fdata->td_end; - - maxwin = tdata->td_maxwin; - ackskew = tdata->td_end - ack; - -#define SEQ_GE(a,b) ((int)((a) - (b)) >= 0) -#define SEQ_GT(a,b) ((int)((a) - (b)) > 0) - if ((SEQ_GE(fdata->td_maxend, end)) && - (SEQ_GE(seq, fdata->td_end - maxwin)) && -/* XXX what about big packets */ -#define MAXACKWINDOW 66000 - (ackskew >= -MAXACKWINDOW) && - (ackskew <= MAXACKWINDOW)) { - /* if ackskew < 0 then this should be due to fragented - * packets. There is no way to know the length of the - * total packet in advance. - * We do know the total length from the fragment cache though. - * Note however that there might be more sessions with - * exactly the same source and destination paramters in the - * state cache (and source and destination is the only stuff - * that is saved in the fragment cache). Note further that - * some TCP connections in the state cache are hashed with - * sport and dport as well which makes it not worthwhile to - * look for them. - * Thus, when ackskew is negative but still seems to belong - * to this session, we bump up the destinations end value. - */ - if (ackskew < 0) - tdata->td_end = ack; - - /* update max window seen */ - if (fdata->td_maxwin < win) - fdata->td_maxwin = win; - if (SEQ_GT(end, fdata->td_end)) - fdata->td_end = end; - if (SEQ_GE(ack + win, tdata->td_maxend)) { - tdata->td_maxend = ack + win; - if (win == 0) - tdata->td_maxend++; - } - - ATOMIC_INCL(ips_stats.iss_hits); - /* - * Nearing end of connection, start timeout. - */ - /* source ? 0 : 1 -> !source */ - fr_tcp_age(&is->is_age, is->is_state, fin, !source); - ret = 1; - } - MUTEX_EXIT(&is->is_lock); - return ret; -} - - -static int fr_matchsrcdst(is, src, dst, fin, tcp) -ipstate_t *is; -union i6addr src, dst; -fr_info_t *fin; -tcphdr_t *tcp; -{ - int ret = 0, rev, out, flags; - u_short sp, dp; - void *ifp; - - rev = fin->fin_rev = IP6NEQ(is->is_dst, dst); - ifp = fin->fin_ifp; - out = fin->fin_out; - - if (tcp != NULL) { - flags = is->is_flags; - sp = tcp->th_sport; - dp = tcp->th_dport; - } else { - flags = is->is_flags & FI_WILDA; - sp = 0; - dp = 0; - } - - if (rev == 0) { - if (!out) { - if (is->is_ifpin == NULL || is->is_ifpin == ifp) - ret = 1; - } else { - if (is->is_ifpout == NULL || is->is_ifpout == ifp) - ret = 1; - } - } else { - if (out) { - if (is->is_ifpin == NULL || is->is_ifpin == ifp) - ret = 1; - } else { - if (is->is_ifpout == NULL || is->is_ifpout == ifp) - ret = 1; - } - } - if (ret == 0) - return 0; - ret = 0; - - if (rev == 0) { - if ( - (IP6EQ(is->is_dst, dst) || (flags & FI_W_DADDR)) && - (IP6EQ(is->is_src, src) || (flags & FI_W_SADDR)) && - (!tcp || ((sp == is->is_sport || flags & FI_W_SPORT) && - (dp == is->is_dport || flags & FI_W_DPORT)))) { - ret = 1; - } - } else { - if ( - (IP6EQ(is->is_dst, src) || (flags & FI_W_DADDR)) && - (IP6EQ(is->is_src, dst) || (flags & FI_W_SADDR)) && - (!tcp || ((sp == is->is_dport || flags & FI_W_DPORT) && - (dp == is->is_sport || flags & FI_W_SPORT)))) { - ret = 1; - } - } - if (ret == 0) - return 0; - - /* - * Whether or not this should be here, is questionable, but the aim - * is to get this out of the main line. - */ - if (tcp == NULL) - flags = is->is_flags & (FI_CMP|(FI_CMP<<4)); - - if (((fin->fin_fi.fi_fl & (flags >> 4)) != (flags & FI_CMP)) || - ((fin->fin_fi.fi_optmsk & is->is_optmsk) != is->is_opt) || - ((fin->fin_fi.fi_secmsk & is->is_secmsk) != is->is_sec) || - ((fin->fin_fi.fi_auth & is->is_authmsk) != is->is_auth)) - return 0; - - if ((flags & (FI_W_SPORT|FI_W_DPORT))) { - if ((flags & FI_W_SPORT) != 0) { - if (rev == 0) { - is->is_sport = sp; - is->is_send = htonl(tcp->th_seq); - } else { - is->is_sport = dp; - is->is_send = htonl(tcp->th_ack); - } - is->is_maxsend = is->is_send + 1; - } else if ((flags & FI_W_DPORT) != 0) { - if (rev == 0) { - is->is_dport = dp; - is->is_dend = htonl(tcp->th_ack); - } else { - is->is_dport = sp; - is->is_dend = htonl(tcp->th_seq); - } - is->is_maxdend = is->is_dend + 1; - } - is->is_flags &= ~(FI_W_SPORT|FI_W_DPORT); - ips_wild--; - } - - ret = -1; - - if (!rev) { - if (out) { - if (!is->is_ifpout) - ret = 1; - } else { - if (!is->is_ifpin) - ret = 0; - } - } else { - if (out) { - if (!is->is_ifpin) - ret = 0; - } else { - if (!is->is_ifpout) - ret = 1; - } - } - - if (ret >= 0) { - is->is_ifp[ret] = ifp; -#ifdef _KERNEL - strncpy(is->is_ifname[out], IFNAME(fin->fin_ifp), - sizeof(is->is_ifname[1])); -#endif - } -#ifdef _KERNEL - if (ret >= 0) { - strncpy(is->is_ifname[out], IFNAME(fin->fin_ifp), - sizeof(is->is_ifname[1])); - } -#endif - return 1; -} - -static int fr_matchicmpqueryreply(v, is, icmp) -int v; -ipstate_t *is; -icmphdr_t *icmp; -{ - if (v == 4) { - /* - * If we matched its type on the way in, then when going out - * it will still be the same type. - */ - if (((icmp->icmp_type == is->is_type) || - (icmpreplytype4[is->is_type] == icmp->icmp_type)) && - (icmp->icmp_id == is->is_icmp.ics_id) && - (icmp->icmp_seq == is->is_icmp.ics_seq)) { - return 1; - }; - } -#ifdef USE_INET6 - else if (is->is_v == 6) { - if ((is->is_type == ICMP6_ECHO_REPLY) && - (icmp->icmp_type == ICMP6_ECHO_REQUEST) && - (icmp->icmp_id == is->is_icmp.ics_id) && - (icmp->icmp_seq == is->is_icmp.ics_seq)) { - return 1; - }; - } -#endif - return 0; -} - -static frentry_t *fr_checkicmpmatchingstate(ip, fin) -ip_t *ip; -fr_info_t *fin; -{ - register ipstate_t *is, **isp; - register u_short sport, dport; - register u_char pr; - union i6addr dst, src; - struct icmp *ic; - u_short savelen; - icmphdr_t *icmp; - fr_info_t ofin; - int type, len; - tcphdr_t *tcp; - frentry_t *fr; - ip_t *oip; - u_int hv; - - /* - * Does it at least have the return (basic) IP header ? - * Only a basic IP header (no options) should be with - * an ICMP error header. - */ - if (((ip->ip_v != 4) || (ip->ip_hl != 5)) || - (fin->fin_plen < ICMPERR_MINPKTLEN)) - return NULL; - ic = (struct icmp *)fin->fin_dp; - type = ic->icmp_type; - /* - * If it's not an error type, then return - */ - if ((type != ICMP_UNREACH) && (type != ICMP_SOURCEQUENCH) && - (type != ICMP_REDIRECT) && (type != ICMP_TIMXCEED) && - (type != ICMP_PARAMPROB)) - return NULL; - - oip = (ip_t *)((char *)ic + ICMPERR_ICMPHLEN); - if (fin->fin_plen < ICMPERR_MAXPKTLEN + ((oip->ip_hl - 5) << 2)) - return NULL; - - /* - * Sanity checks. - */ - len = fin->fin_dlen - ICMPERR_ICMPHLEN; - if ((len <= 0) || ((oip->ip_hl << 2) > len)) - return NULL; - - /* - * Is the buffer big enough for all of it ? It's the size of the IP - * header claimed in the encapsulated part which is of concern. It - * may be too big to be in this buffer but not so big that it's - * outside the ICMP packet, leading to TCP deref's causing problems. - * This is possible because we don't know how big oip_hl is when we - * do the pullup early in fr_check() and thus can't gaurantee it is - * all here now. - */ -#ifdef _KERNEL - { - mb_t *m; - -# if SOLARIS - m = fin->fin_qfm; - if ((char *)oip + len > (char *)m->b_wptr) - return NULL; -# else - m = *(mb_t **)fin->fin_mp; - if ((char *)oip + len > (char *)ip + m->m_len) - return NULL; -# endif - } -#endif - - /* - * in the IPv4 case we must zero the i6addr union otherwise - * the IP6EQ and IP6NEQ macros produce the wrong results because - * of the 'junk' in the unused part of the union - */ - bzero((char *)&src, sizeof(src)); - bzero((char *)&dst, sizeof(dst)); - - if (oip->ip_p == IPPROTO_ICMP) { - icmp = (icmphdr_t *)((char *)oip + (oip->ip_hl << 2)); - - /* - * a ICMP error can only be generated as a result of an - * ICMP query, not as the response on an ICMP error - * - * XXX theoretically ICMP_ECHOREP and the other reply's are - * ICMP query's as well, but adding them here seems strange XXX - */ - if ((icmp->icmp_type != ICMP_ECHO) && - (icmp->icmp_type != ICMP_TSTAMP) && - (icmp->icmp_type != ICMP_IREQ) && - (icmp->icmp_type != ICMP_MASKREQ)) - return NULL; - - /* - * perform a lookup of the ICMP packet in the state table - */ - hv = (pr = oip->ip_p); - src.in4 = oip->ip_src; - hv += src.in4.s_addr; - dst.in4 = oip->ip_dst; - hv += dst.in4.s_addr; - hv += icmp->icmp_id; - hv += icmp->icmp_seq; - hv %= fr_statesize; - - savelen = oip->ip_len; - oip->ip_len = len; - ofin.fin_v = 4; - fr_makefrip(oip->ip_hl << 2, oip, &ofin); - oip->ip_len = savelen; - ofin.fin_ifp = fin->fin_ifp; - ofin.fin_out = !fin->fin_out; - ofin.fin_mp = NULL; /* if dereferenced, panic XXX */ - - READ_ENTER(&ipf_state); - for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_hnext) - if ((is->is_p == pr) && (is->is_v == 4) && - fr_matchsrcdst(is, src, dst, &ofin, NULL) && - fr_matchicmpqueryreply(is->is_v, is, icmp)) { - ips_stats.iss_hits++; - is->is_pkts++; - is->is_bytes += ip->ip_len; - fr = is->is_rule; - RWLOCK_EXIT(&ipf_state); - return fr; - } - RWLOCK_EXIT(&ipf_state); - return NULL; - }; - - if ((oip->ip_p != IPPROTO_TCP) && (oip->ip_p != IPPROTO_UDP)) - return NULL; - - tcp = (tcphdr_t *)((char *)oip + (oip->ip_hl << 2)); - dport = tcp->th_dport; - sport = tcp->th_sport; - - hv = (pr = oip->ip_p); - src.in4 = oip->ip_src; - hv += src.in4.s_addr; - dst.in4 = oip->ip_dst; - hv += dst.in4.s_addr; - hv += dport; - hv += sport; - hv %= fr_statesize; - /* - * we make an fin entry to be able to feed it to - * matchsrcdst note that not all fields are encessary - * but this is the cleanest way. Note further we fill - * in fin_mp such that if someone uses it we'll get - * a kernel panic. fr_matchsrcdst does not use this. - * - * watch out here, as ip is in host order and oip in network - * order. Any change we make must be undone afterwards. - */ - savelen = oip->ip_len; - oip->ip_len = len; - ofin.fin_v = 4; - fr_makefrip(oip->ip_hl << 2, oip, &ofin); - oip->ip_len = savelen; - ofin.fin_ifp = fin->fin_ifp; - ofin.fin_out = !fin->fin_out; - ofin.fin_mp = NULL; /* if dereferenced, panic XXX */ - READ_ENTER(&ipf_state); - for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_hnext) { - /* - * Only allow this icmp though if the - * encapsulated packet was allowed through the - * other way around. Note that the minimal amount - * of info present does not allow for checking against - * tcp internals such as seq and ack numbers. - */ - if ((is->is_p == pr) && (is->is_v == 4) && - fr_matchsrcdst(is, src, dst, &ofin, tcp)) { - fr = is->is_rule; - ips_stats.iss_hits++; - is->is_pkts++; - is->is_bytes += fin->fin_plen; - /* - * we deliberately do not touch the timeouts - * for the accompanying state table entry. - * It remains to be seen if that is correct. XXX - */ - RWLOCK_EXIT(&ipf_state); - return fr; - } - } - RWLOCK_EXIT(&ipf_state); - return NULL; -} - - -static void fr_ipsmove(isp, is, hv) -ipstate_t **isp, *is; -u_int hv; -{ - u_int hvm; - - hvm = is->is_hv; - /* - * Remove the hash from the old location... - */ - if (is->is_hnext) - is->is_hnext->is_phnext = isp; - *isp = is->is_hnext; - if (ips_table[hvm] == NULL) - ips_stats.iss_inuse--; - - /* - * ...and put the hash in the new one. - */ - hvm = hv % fr_statesize; - is->is_hv = hvm; - isp = &ips_table[hvm]; - if (*isp) - (*isp)->is_phnext = &is->is_hnext; - else - ips_stats.iss_inuse++; - is->is_phnext = isp; - is->is_hnext = *isp; - *isp = is; -} - - -/* - * Check if a packet has a registered state. - */ -frentry_t *fr_checkstate(ip, fin) -ip_t *ip; -fr_info_t *fin; -{ - union i6addr dst, src; - register ipstate_t *is, **isp; - register u_char pr; - u_int hv, hvm, hlen, tryagain, pass, v; - struct icmp *ic; - frentry_t *fr; - tcphdr_t *tcp; - - if (fr_state_lock || (fin->fin_off & IP_OFFMASK) || - (fin->fin_fi.fi_fl & FI_SHORT)) - return NULL; - - is = NULL; - hlen = fin->fin_hlen; - tcp = (tcphdr_t *)((char *)ip + hlen); - ic = (struct icmp *)tcp; - hv = (pr = fin->fin_fi.fi_p); - src = fin->fin_fi.fi_src; - dst = fin->fin_fi.fi_dst; - hv += src.in4.s_addr; - hv += dst.in4.s_addr; - - /* - * Search the hash table for matching packet header info. - */ - v = fin->fin_fi.fi_v; - switch (fin->fin_fi.fi_p) - { -#ifdef USE_INET6 - case IPPROTO_ICMPV6 : - if (v == 6) { - if (fin->fin_out) - hv -= dst.in4.s_addr; - else - hv -= src.in4.s_addr; - if ((ic->icmp_type == ICMP6_ECHO_REQUEST) || - (ic->icmp_type == ICMP6_ECHO_REPLY)) { - hv += ic->icmp_id; - hv += ic->icmp_seq; - } - } -#endif - case IPPROTO_ICMP : - if (v == 4) { - hv += ic->icmp_id; - hv += ic->icmp_seq; - } - hv %= fr_statesize; - READ_ENTER(&ipf_state); - for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_hnext) { - if ((is->is_p == pr) && (is->is_v == v) && - fr_matchsrcdst(is, src, dst, fin, NULL) && - fr_matchicmpqueryreply(v, is, ic)) { - is->is_age = fr_icmptimeout; - break; - } - } - if (is != NULL) - break; - RWLOCK_EXIT(&ipf_state); - /* - * No matching icmp state entry. Perhaps this is a - * response to another state entry. - */ -#ifdef USE_INET6 - if (v == 6) - fr = fr_checkicmp6matchingstate((ip6_t *)ip, fin); - else -#endif - fr = fr_checkicmpmatchingstate(ip, fin); - if (fr) - return fr; - break; - case IPPROTO_TCP : - { - register u_short dport, sport; - register int i; - - i = tcp->th_flags; - /* - * Just plain ignore RST flag set with either FIN or SYN. - */ - if ((i & TH_RST) && - ((i & (TH_FIN|TH_SYN|TH_RST)) != TH_RST)) - break; - case IPPROTO_UDP : - dport = tcp->th_dport; - sport = tcp->th_sport; - tryagain = 0; - hv += dport; - hv += sport; - READ_ENTER(&ipf_state); -retry_tcpudp: - hvm = hv % fr_statesize; - for (isp = &ips_table[hvm]; (is = *isp); isp = &is->is_hnext) - if ((is->is_p == pr) && (is->is_v == v) && - fr_matchsrcdst(is, src, dst, fin, tcp)) { - if ((pr == IPPROTO_TCP)) { - if (!fr_tcpstate(is, fin, ip, tcp)) { - continue; - } - } - break; - } - if (is != NULL) { - if (tryagain && - !(is->is_flags & (FI_WILDP|FI_WILDA))) { - hv += dport; - hv += sport; - fr_ipsmove(isp, is, hv); - MUTEX_DOWNGRADE(&ipf_state); - } - break; - } - RWLOCK_EXIT(&ipf_state); - if (!tryagain && ips_wild) { - hv -= dport; - hv -= sport; - tryagain = 1; - WRITE_ENTER(&ipf_state); - goto retry_tcpudp; - } - break; - } - default : - break; - } - if (is == NULL) { - ATOMIC_INCL(ips_stats.iss_miss); - return NULL; - } - MUTEX_ENTER(&is->is_lock); - is->is_bytes += fin->fin_plen; - ips_stats.iss_hits++; - is->is_pkts++; - MUTEX_EXIT(&is->is_lock); - fr = is->is_rule; - fin->fin_fr = fr; - pass = is->is_pass; -#ifndef _KERNEL - if (tcp->th_flags & TCP_CLOSE) - fr_delstate(is); -#endif - RWLOCK_EXIT(&ipf_state); - if (fin->fin_fi.fi_fl & FI_FRAG) - ipfr_newfrag(ip, fin, pass ^ FR_KEEPSTATE); - return fr; -} - - -void ip_statesync(ifp) -void *ifp; -{ - register ipstate_t *is; - - WRITE_ENTER(&ipf_state); - for (is = ips_list; is; is = is->is_next) { - if (is->is_ifpin == ifp) { - is->is_ifpin = GETUNIT(is->is_ifname[0], is->is_v); - if (!is->is_ifpin) - is->is_ifpin = (void *)-1; - } - if (is->is_ifpout == ifp) { - is->is_ifpout = GETUNIT(is->is_ifname[1], is->is_v); - if (!is->is_ifpout) - is->is_ifpout = (void *)-1; - } - } - RWLOCK_EXIT(&ipf_state); -} - - -/* - * Must always be called with fr_ipfstate held as a write lock. - */ -static void fr_delstate(is) -ipstate_t *is; -{ - frentry_t *fr; - - if (is->is_flags & (FI_WILDP|FI_WILDA)) - ips_wild--; - if (is->is_next) - is->is_next->is_pnext = is->is_pnext; - *is->is_pnext = is->is_next; - if (is->is_hnext) - is->is_hnext->is_phnext = is->is_phnext; - *is->is_phnext = is->is_hnext; - if (ips_table[is->is_hv] == NULL) - ips_stats.iss_inuse--; - - fr = is->is_rule; - if (fr != NULL) { - fr->fr_ref--; - if (fr->fr_ref == 0) { - KFREE(fr); - } - } -#ifdef _KERNEL - MUTEX_DESTROY(&is->is_lock); -#endif - KFREE(is); - ips_num--; -} - - -/* - * Free memory in use by all state info. kept. - */ -void fr_stateunload() -{ - register ipstate_t *is; - - WRITE_ENTER(&ipf_state); - while ((is = ips_list)) - fr_delstate(is); - ips_stats.iss_inuse = 0; - ips_num = 0; - RWLOCK_EXIT(&ipf_state); - KFREES(ips_table, fr_statesize * sizeof(ipstate_t *)); - ips_table = NULL; -} - - -/* - * Slowly expire held state for thingslike UDP and ICMP. Timeouts are set - * in expectation of this being called twice per second. - */ -void fr_timeoutstate() -{ - register ipstate_t *is, **isp; -#if defined(_KERNEL) && !SOLARIS - int s; -#endif - - SPL_NET(s); - WRITE_ENTER(&ipf_state); - for (isp = &ips_list; (is = *isp); ) - if (is->is_age && !--is->is_age) { - if (is->is_p == IPPROTO_TCP) - ips_stats.iss_fin++; - else - ips_stats.iss_expire++; -#ifdef IPFILTER_LOG - ipstate_log(is, ISL_EXPIRE); -#endif - fr_delstate(is); - } else - isp = &is->is_next; - if (fr_state_doflush) { - (void) fr_state_flush(1); - fr_state_doflush = 0; - } - RWLOCK_EXIT(&ipf_state); - SPL_X(s); -} - - -/* - * Original idea freom Pradeep Krishnan for use primarily with NAT code. - * (pkrishna@netcom.com) - * - * Rewritten by Arjan de Vet <Arjan.deVet@adv.iae.nl>, 2000-07-29: - * - * - (try to) base state transitions on real evidence only, - * i.e. packets that are sent and have been received by ipfilter; - * diagram 18.12 of TCP/IP volume 1 by W. Richard Stevens was used. - * - * - deal with half-closed connections correctly; - * - * - store the state of the source in state[0] such that ipfstat - * displays the state as source/dest instead of dest/source; the calls - * to fr_tcp_age have been changed accordingly. - * - * Parameters: - * - * state[0] = state of source (host that initiated connection) - * state[1] = state of dest (host that accepted the connection) - * - * dir == 0 : a packet from source to dest - * dir == 1 : a packet from dest to source - * - */ -void fr_tcp_age(age, state, fin, dir) -u_long *age; -u_char *state; -fr_info_t *fin; -int dir; -{ - tcphdr_t *tcp = (tcphdr_t *)fin->fin_dp; - u_char flags = tcp->th_flags; - int dlen, ostate; - - ostate = state[1 - dir]; - - dlen = fin->fin_plen - fin->fin_hlen - (tcp->th_off << 2); - - if (flags & TH_RST) { - if (!(tcp->th_flags & TH_PUSH) && !dlen) { - *age = fr_tcpclosed; - state[dir] = TCPS_CLOSED; - } else { - *age = fr_tcpclosewait; - state[dir] = TCPS_CLOSE_WAIT; - } - return; - } - - *age = fr_tcptimeout; /* default 4 mins */ - - switch(state[dir]) - { - case TCPS_CLOSED: /* 0 */ - if ((flags & TH_OPENING) == TH_OPENING) { - /* - * 'dir' received an S and sends SA in response, - * CLOSED -> SYN_RECEIVED - */ - state[dir] = TCPS_SYN_RECEIVED; - *age = fr_tcptimeout; - } else if ((flags & (TH_SYN|TH_ACK)) == TH_SYN) { - /* 'dir' sent S, CLOSED -> SYN_SENT */ - state[dir] = TCPS_SYN_SENT; - *age = fr_tcptimeout; - } - /* - * The next piece of code makes it possible to get - * already established connections into the state table - * after a restart or reload of the filter rules; this - * does not work when a strict 'flags S keep state' is - * used for tcp connections of course - */ - if ((flags & (TH_FIN|TH_SYN|TH_RST|TH_ACK)) == TH_ACK) { - /* we saw an A, guess 'dir' is in ESTABLISHED mode */ - state[dir] = TCPS_ESTABLISHED; - *age = fr_tcpidletimeout; - } - /* - * TODO: besides regular ACK packets we can have other - * packets as well; it is yet to be determined how we - * should initialize the states in those cases - */ - break; - - case TCPS_LISTEN: /* 1 */ - /* NOT USED */ - break; - - case TCPS_SYN_SENT: /* 2 */ - if ((flags & (TH_SYN|TH_FIN|TH_ACK)) == TH_ACK) { - /* - * We see an A from 'dir' which is in SYN_SENT - * state: 'dir' sent an A in response to an SA - * which it received, SYN_SENT -> ESTABLISHED - */ - state[dir] = TCPS_ESTABLISHED; - *age = fr_tcpidletimeout; - } else if (flags & TH_FIN) { - /* - * We see an F from 'dir' which is in SYN_SENT - * state and wants to close its side of the - * connection; SYN_SENT -> FIN_WAIT_1 - */ - state[dir] = TCPS_FIN_WAIT_1; - *age = fr_tcpidletimeout; /* or fr_tcptimeout? */ - } else if ((flags & TH_OPENING) == TH_OPENING) { - /* - * We see an SA from 'dir' which is already in - * SYN_SENT state, this means we have a - * simultaneous open; SYN_SENT -> SYN_RECEIVED - */ - state[dir] = TCPS_SYN_RECEIVED; - *age = fr_tcptimeout; - } - break; - - case TCPS_SYN_RECEIVED: /* 3 */ - if ((flags & (TH_SYN|TH_FIN|TH_ACK)) == TH_ACK) { - /* - * We see an A from 'dir' which was in SYN_RECEIVED - * state so it must now be in established state, - * SYN_RECEIVED -> ESTABLISHED - */ - state[dir] = TCPS_ESTABLISHED; - *age = fr_tcpidletimeout; - } else if (flags & TH_FIN) { - /* - * We see an F from 'dir' which is in SYN_RECEIVED - * state and wants to close its side of the connection; - * SYN_RECEIVED -> FIN_WAIT_1 - */ - state[dir] = TCPS_FIN_WAIT_1; - *age = fr_tcpidletimeout; - } - break; - - case TCPS_ESTABLISHED: /* 4 */ - if (flags & TH_FIN) { - /* - * 'dir' closed its side of the connection; this - * gives us a half-closed connection; - * ESTABLISHED -> FIN_WAIT_1 - */ - state[dir] = TCPS_FIN_WAIT_1; - *age = fr_tcphalfclosed; - } else if (flags & TH_ACK) { - /* an ACK, should we exclude other flags here? */ - if (ostate == TCPS_FIN_WAIT_1) { - /* - * We know the other side did an active close, - * so we are ACKing the recvd FIN packet (does - * the window matching code guarantee this?) - * and go into CLOSE_WAIT state; this gives us - * a half-closed connection - */ - state[dir] = TCPS_CLOSE_WAIT; - *age = fr_tcphalfclosed; - } else if (ostate < TCPS_CLOSE_WAIT) - /* - * Still a fully established connection, - * reset timeout - */ - *age = fr_tcpidletimeout; - } - break; - - case TCPS_CLOSE_WAIT: /* 5 */ - if (flags & TH_FIN) { - /* - * Application closed and 'dir' sent a FIN, we're now - * going into LAST_ACK state - */ - *age = fr_tcplastack; - state[dir] = TCPS_LAST_ACK; - } else { - /* - * We remain in CLOSE_WAIT because the other side has - * closed already and we did not close our side yet; - * reset timeout - */ - *age = fr_tcphalfclosed; - } - break; - - case TCPS_FIN_WAIT_1: /* 6 */ - if ((flags & TH_ACK) && ostate > TCPS_CLOSE_WAIT) { - /* - * If the other side is not active anymore it has sent - * us a FIN packet that we are ack'ing now with an ACK; - * this means both sides have now closed the connection - * and we go into TIME_WAIT - */ - /* - * XXX: how do we know we really are ACKing the FIN - * packet here? does the window code guarantee that? - */ - state[dir] = TCPS_TIME_WAIT; - *age = fr_tcptimeout; - } else - /* - * We closed our side of the connection already but the - * other side is still active (ESTABLISHED/CLOSE_WAIT); - * continue with this half-closed connection - */ - *age = fr_tcphalfclosed; - break; - - case TCPS_CLOSING: /* 7 */ - /* NOT USED */ - break; - - case TCPS_LAST_ACK: /* 8 */ - if (flags & TH_ACK) { - if ((flags & TH_PUSH) || dlen) - /* - * There is still data to be delivered, reset - * timeout - */ - *age = fr_tcplastack; - } - /* - * We cannot detect when we go out of LAST_ACK state to CLOSED - * because that is based on the reception of ACK packets; - * ipfilter can only detect that a packet has been sent by a - * host - */ - break; - - case TCPS_FIN_WAIT_2: /* 9 */ - /* NOT USED */ - break; - - case TCPS_TIME_WAIT: /* 10 */ - /* we're in 2MSL timeout now */ - break; - } -} - - -#ifdef IPFILTER_LOG -void ipstate_log(is, type) -struct ipstate *is; -u_int type; -{ - struct ipslog ipsl; - void *items[1]; - size_t sizes[1]; - int types[1]; - - ipsl.isl_type = type; - ipsl.isl_pkts = is->is_pkts; - ipsl.isl_bytes = is->is_bytes; - ipsl.isl_src = is->is_src; - ipsl.isl_dst = is->is_dst; - ipsl.isl_p = is->is_p; - ipsl.isl_v = is->is_v; - ipsl.isl_flags = is->is_flags; - if (ipsl.isl_p == IPPROTO_TCP || ipsl.isl_p == IPPROTO_UDP) { - ipsl.isl_sport = is->is_sport; - ipsl.isl_dport = is->is_dport; - if (ipsl.isl_p == IPPROTO_TCP) { - ipsl.isl_state[0] = is->is_state[0]; - ipsl.isl_state[1] = is->is_state[1]; - } - } else if (ipsl.isl_p == IPPROTO_ICMP) - ipsl.isl_itype = is->is_icmp.ics_type; - else { - ipsl.isl_ps.isl_filler[0] = 0; - ipsl.isl_ps.isl_filler[1] = 0; - } - items[0] = &ipsl; - sizes[0] = sizeof(ipsl); - types[0] = 0; - - (void) ipllog(IPL_LOGSTATE, NULL, items, sizes, types, 1); -} -#endif - - -#ifdef USE_INET6 -frentry_t *fr_checkicmp6matchingstate(ip, fin) -ip6_t *ip; -fr_info_t *fin; -{ - register ipstate_t *is, **isp; - register u_short sport, dport; - register u_char pr; - struct icmp6_hdr *ic, *oic; - union i6addr dst, src; - u_short savelen; - fr_info_t ofin; - tcphdr_t *tcp; - frentry_t *fr; - ip6_t *oip; - int type; - u_int hv; - - /* - * Does it at least have the return (basic) IP header ? - * Only a basic IP header (no options) should be with - * an ICMP error header. - */ - if ((fin->fin_v != 6) || (fin->fin_plen < ICMP6ERR_MINPKTLEN)) - return NULL; - ic = (struct icmp6_hdr *)fin->fin_dp; - type = ic->icmp6_type; - /* - * If it's not an error type, then return - */ - if ((type != ICMP6_DST_UNREACH) && (type != ICMP6_PACKET_TOO_BIG) && - (type != ICMP6_TIME_EXCEEDED) && (type != ICMP6_PARAM_PROB)) - return NULL; - - oip = (ip6_t *)((char *)ic + ICMPERR_ICMPHLEN); - if (fin->fin_plen < sizeof(*oip)) - return NULL; - - if (oip->ip6_nxt == IPPROTO_ICMPV6) { - oic = (struct icmp6_hdr *)(oip + 1); - /* - * a ICMP error can only be generated as a result of an - * ICMP query, not as the response on an ICMP error - * - * XXX theoretically ICMP_ECHOREP and the other reply's are - * ICMP query's as well, but adding them here seems strange XXX - */ - if (!(oic->icmp6_type & ICMP6_INFOMSG_MASK)) - return NULL; - - /* - * perform a lookup of the ICMP packet in the state table - */ - hv = (pr = oip->ip6_nxt); - src.in6 = oip->ip6_src; - hv += src.in4.s_addr; - dst.in6 = oip->ip6_dst; - hv += dst.in4.s_addr; - hv += oic->icmp6_id; - hv += oic->icmp6_seq; - hv %= fr_statesize; - - oip->ip6_plen = ntohs(oip->ip6_plen); - ofin.fin_v = 6; - fr_makefrip(sizeof(*oip), (ip_t *)oip, &ofin); - oip->ip6_plen = htons(oip->ip6_plen); - ofin.fin_ifp = fin->fin_ifp; - ofin.fin_out = !fin->fin_out; - ofin.fin_mp = NULL; /* if dereferenced, panic XXX */ - - READ_ENTER(&ipf_state); - for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_hnext) - if ((is->is_p == pr) && - (oic->icmp6_id == is->is_icmp.ics_id) && - (oic->icmp6_seq == is->is_icmp.ics_seq) && - fr_matchsrcdst(is, src, dst, &ofin, NULL)) { - /* - * in the state table ICMP query's are stored - * with the type of the corresponding ICMP - * response. Correct here - */ - if (((is->is_type == ICMP6_ECHO_REPLY) && - (oic->icmp6_type == ICMP6_ECHO_REQUEST)) || - (is->is_type - 1 == oic->icmp6_type )) { - ips_stats.iss_hits++; - is->is_pkts++; - is->is_bytes += fin->fin_plen; - return is->is_rule; - } - } - RWLOCK_EXIT(&ipf_state); - - return NULL; - }; - - if ((oip->ip6_nxt != IPPROTO_TCP) && (oip->ip6_nxt != IPPROTO_UDP)) - return NULL; - tcp = (tcphdr_t *)(oip + 1); - dport = tcp->th_dport; - sport = tcp->th_sport; - - hv = (pr = oip->ip6_nxt); - src.in6 = oip->ip6_src; - hv += src.in4.s_addr; - dst.in6 = oip->ip6_dst; - hv += dst.in4.s_addr; - hv += dport; - hv += sport; - hv %= fr_statesize; - /* - * we make an fin entry to be able to feed it to - * matchsrcdst note that not all fields are encessary - * but this is the cleanest way. Note further we fill - * in fin_mp such that if someone uses it we'll get - * a kernel panic. fr_matchsrcdst does not use this. - * - * watch out here, as ip is in host order and oip in network - * order. Any change we make must be undone afterwards. - */ - savelen = oip->ip6_plen; - oip->ip6_plen = ip->ip6_plen - sizeof(*ip) - ICMPERR_ICMPHLEN; - ofin.fin_v = 6; - fr_makefrip(sizeof(*oip), (ip_t *)oip, &ofin); - oip->ip6_plen = savelen; - ofin.fin_ifp = fin->fin_ifp; - ofin.fin_out = !fin->fin_out; - ofin.fin_mp = NULL; /* if dereferenced, panic XXX */ - READ_ENTER(&ipf_state); - for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_hnext) { - /* - * Only allow this icmp though if the - * encapsulated packet was allowed through the - * other way around. Note that the minimal amount - * of info present does not allow for checking against - * tcp internals such as seq and ack numbers. - */ - if ((is->is_p == pr) && (is->is_v == 6) && - fr_matchsrcdst(is, src, dst, &ofin, tcp)) { - fr = is->is_rule; - ips_stats.iss_hits++; - /* - * we must swap src and dst here because the icmp - * comes the other way around - */ - is->is_pkts++; - is->is_bytes += fin->fin_plen; - /* - * we deliberately do not touch the timeouts - * for the accompanying state table entry. - * It remains to be seen if that is correct. XXX - */ - RWLOCK_EXIT(&ipf_state); - return fr; - } - } - RWLOCK_EXIT(&ipf_state); - return NULL; -} -#endif diff --git a/contrib/ipfilter/ip_state.h b/contrib/ipfilter/ip_state.h deleted file mode 100644 index 1d1bc00..0000000 --- a/contrib/ipfilter/ip_state.h +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (C) 1995-2000 by Darren Reed. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - * - * @(#)ip_state.h 1.3 1/12/96 (C) 1995 Darren Reed - * $Id: ip_state.h,v 2.13.2.2 2000/08/23 11:01:31 darrenr Exp $ - */ -#ifndef __IP_STATE_H__ -#define __IP_STATE_H__ - -#if defined(__STDC__) || defined(__GNUC__) -# define SIOCDELST _IOW('r', 61, struct ipstate *) -#else -# define SIOCDELST _IOW(r, 61, struct ipstate *) -#endif - -#define IPSTATE_SIZE 5737 -#define IPSTATE_MAX 4013 /* Maximum number of states held */ - -#define PAIRS(s1,d1,s2,d2) ((((s1) == (s2)) && ((d1) == (d2))) ||\ - (((s1) == (d2)) && ((d1) == (s2)))) -#define IPPAIR(s1,d1,s2,d2) PAIRS((s1).s_addr, (d1).s_addr, \ - (s2).s_addr, (d2).s_addr) - - -typedef struct udpstate { - u_short us_sport; - u_short us_dport; -} udpstate_t; - -typedef struct icmpstate { - u_short ics_id; - u_short ics_seq; - u_char ics_type; -} icmpstate_t; - -typedef struct tcpdata { - u_32_t td_end; - u_32_t td_maxend; - u_short td_maxwin; -} tcpdata_t; - -typedef struct tcpstate { - u_short ts_sport; - u_short ts_dport; - tcpdata_t ts_data[2]; - u_char ts_state[2]; -} tcpstate_t; - -typedef struct ipstate { - struct ipstate *is_next; - struct ipstate **is_pnext; - struct ipstate *is_hnext; - struct ipstate **is_phnext; - u_long is_age; - u_int is_pass; - U_QUAD_T is_pkts; - U_QUAD_T is_bytes; - void *is_ifp[2]; - frentry_t *is_rule; - union i6addr is_src; - union i6addr is_dst; - u_char is_p; /* Protocol */ - u_char is_v; - u_int is_hv; - u_32_t is_flags; - u_32_t is_opt; /* packet options set */ - u_32_t is_optmsk; /* " " mask */ - u_short is_sec; /* security options set */ - u_short is_secmsk; /* " " mask */ - u_short is_auth; /* authentication options set */ - u_short is_authmsk; /* " " mask */ - union { - icmpstate_t is_ics; - tcpstate_t is_ts; - udpstate_t is_us; - } is_ps; - char is_ifname[2][IFNAMSIZ]; -#if SOLARIS || defined(__sgi) - kmutex_t is_lock; -#endif -} ipstate_t; - -#define is_saddr is_src.in4.s_addr -#define is_daddr is_dst.in4.s_addr -#define is_icmp is_ps.is_ics -#define is_type is_icmp.ics_type -#define is_code is_icmp.ics_code -#define is_tcp is_ps.is_ts -#define is_udp is_ps.is_us -#define is_send is_tcp.ts_data[0].td_end -#define is_dend is_tcp.ts_data[1].td_end -#define is_maxswin is_tcp.ts_data[0].td_maxwin -#define is_maxdwin is_tcp.ts_data[1].td_maxwin -#define is_maxsend is_tcp.ts_data[0].td_maxend -#define is_maxdend is_tcp.ts_data[1].td_maxend -#define is_sport is_tcp.ts_sport -#define is_dport is_tcp.ts_dport -#define is_state is_tcp.ts_state -#define is_ifpin is_ifp[0] -#define is_ifpout is_ifp[1] - -#define TH_OPENING (TH_SYN|TH_ACK) -/* - * is_flags: - * Bits 0 - 3 are use as a mask with the current packet's bits to check for - * whether it is short, tcp/udp, a fragment or the presence of IP options. - * Bits 4 - 7 are set from the initial packet and contain what the packet - * anded with bits 0-3 must match. - * Bits 8,9 are used to indicate wildcard source/destination port matching. - */ - -typedef struct ipstate_save { - void *ips_next; - struct ipstate ips_is; - struct frentry ips_fr; -} ipstate_save_t; - -#define ips_rule ips_is.is_rule - - -typedef struct ipslog { - U_QUAD_T isl_pkts; - U_QUAD_T isl_bytes; - union i6addr isl_src; - union i6addr isl_dst; - u_short isl_type; - union { - u_short isl_filler[2]; - u_short isl_ports[2]; - u_short isl_icmp; - } isl_ps; - u_char isl_v; - u_char isl_p; - u_char isl_flags; - u_char isl_state[2]; -} ipslog_t; - -#define isl_sport isl_ps.isl_ports[0] -#define isl_dport isl_ps.isl_ports[1] -#define isl_itype isl_ps.isl_icmp - -#define ISL_NEW 0 -#define ISL_EXPIRE 0xffff -#define ISL_FLUSH 0xfffe -#define ISL_REMOVE 0xfffd - - -typedef struct ips_stat { - u_long iss_hits; - u_long iss_miss; - u_long iss_max; - u_long iss_tcp; - u_long iss_udp; - u_long iss_icmp; - u_long iss_nomem; - u_long iss_expire; - u_long iss_fin; - u_long iss_active; - u_long iss_logged; - u_long iss_logfail; - u_long iss_inuse; - ipstate_t **iss_table; - ipstate_t *iss_list; -} ips_stat_t; - - -extern u_long fr_tcpidletimeout; -extern u_long fr_tcpclosewait; -extern u_long fr_tcplastack; -extern u_long fr_tcptimeout; -extern u_long fr_tcpclosed; -extern u_long fr_tcphalfclosed; -extern u_long fr_udptimeout; -extern u_long fr_icmptimeout; -extern int fr_state_lock; -extern int fr_stateinit __P((void)); -extern int fr_tcpstate __P((ipstate_t *, fr_info_t *, ip_t *, tcphdr_t *)); -extern ipstate_t *fr_addstate __P((ip_t *, fr_info_t *, u_int)); -extern frentry_t *fr_checkstate __P((ip_t *, fr_info_t *)); -extern void ip_statesync __P((void *)); -extern void fr_timeoutstate __P((void)); -extern void fr_tcp_age __P((u_long *, u_char *, fr_info_t *, int)); -extern void fr_stateunload __P((void)); -extern void ipstate_log __P((struct ipstate *, u_int)); -#if defined(__NetBSD__) || defined(__OpenBSD__) -extern int fr_state_ioctl __P((caddr_t, u_long, int)); -#else -extern int fr_state_ioctl __P((caddr_t, int, int)); -#endif - -#endif /* __IP_STATE_H__ */ diff --git a/contrib/ipfilter/ipl.h b/contrib/ipfilter/ipl.h deleted file mode 100644 index 3529d65..0000000 --- a/contrib/ipfilter/ipl.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (C) 1993-2000 by Darren Reed. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - * - * @(#)ipl.h 1.21 6/5/96 - * $Id: ipl.h,v 2.15.2.17 2001/01/14 13:47:15 darrenr Exp $ - */ - -#ifndef __IPL_H__ -#define __IPL_H__ - -#define IPL_VERSION "IP Filter: v3.4.16" - -#endif diff --git a/contrib/ipfilter/mlfk_ipl.c b/contrib/ipfilter/mlfk_ipl.c deleted file mode 100644 index 0dc4ff2..0000000 --- a/contrib/ipfilter/mlfk_ipl.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright 1999 Guido van Rooij. All rights reserved. - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: mlfk_ipl.c,v 2.1.2.6 2000/11/18 03:58:29 darrenr Exp $ - */ - - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/conf.h> -#include <sys/socket.h> -#include <sys/sysctl.h> -#include <net/if.h> -#include <netinet/in_systm.h> -#include <netinet/in.h> -#include <netinet/ip.h> -#if (__FreeBSD_version >= 199511) -# include <net/route.h> -# include <netinet/ip_var.h> -# include <netinet/tcp.h> -# include <netinet/tcpip.h> -#endif - - -#include <netinet/ipl.h> -#include <netinet/ip_compat.h> -#include <netinet/ip_fil.h> -#include <netinet/ip_state.h> -#include <netinet/ip_nat.h> -#include <netinet/ip_auth.h> -#include <netinet/ip_frag.h> -#include <netinet/ip_proxy.h> - -static dev_t ipf_devs[IPL_LOGMAX + 1]; - -SYSCTL_DECL(_net_inet); -SYSCTL_NODE(_net_inet, OID_AUTO, ipf, CTLFLAG_RW, 0, "IPF"); -SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &fr_flags, 0, ""); -SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_pass, CTLFLAG_RW, &fr_pass, 0, ""); -SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &fr_active, 0, ""); -SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcpidletimeout, CTLFLAG_RW, - &fr_tcpidletimeout, 0, ""); -SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcpclosewait, CTLFLAG_RW, - &fr_tcpclosewait, 0, ""); -SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcplastack, CTLFLAG_RW, - &fr_tcplastack, 0, ""); -SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RW, - &fr_tcptimeout, 0, ""); -SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RW, - &fr_tcpclosed, 0, ""); -SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RW, - &fr_tcphalfclosed, 0, ""); -SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RW, - &fr_udptimeout, 0, ""); -SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RW, - &fr_icmptimeout, 0, ""); -SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_defnatage, CTLFLAG_RW, - &fr_defnatage, 0, ""); -SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_ipfrttl, CTLFLAG_RW, - &fr_ipfrttl, 0, ""); -SYSCTL_INT(_net_inet_ipf, OID_AUTO, ipl_unreach, CTLFLAG_RW, - &ipl_unreach, 0, ""); -SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_running, CTLFLAG_RD, - &fr_running, 0, ""); -SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_authsize, CTLFLAG_RD, - &fr_authsize, 0, ""); -SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_authused, CTLFLAG_RD, - &fr_authused, 0, ""); -SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_defaultauthage, CTLFLAG_RW, - &fr_defaultauthage, 0, ""); -SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &fr_chksrc, 0, ""); -SYSCTL_INT(_net_inet_ipf, OID_AUTO, ippr_ftp_pasvonly, CTLFLAG_RW, - &ippr_ftp_pasvonly, 0, ""); -SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &fr_minttl, 0, ""); -SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_minttllog, CTLFLAG_RW, - &fr_minttllog, 0, ""); - -#define CDEV_MAJOR 79 -static struct cdevsw ipl_cdevsw = { - /* open */ iplopen, - /* close */ iplclose, - /* read */ iplread, - /* write */ nowrite, - /* ioctl */ iplioctl, - /* poll */ nopoll, - /* mmap */ nommap, - /* strategy */ nostrategy, - /* name */ "ipl", - /* maj */ CDEV_MAJOR, - /* dump */ nodump, - /* psize */ nopsize, - /* flags */ 0, - /* bmaj */ -1 -}; - -static int -ipfilter_modevent(module_t mod, int type, void *unused) -{ - char *c; - int i, error = 0; - - switch (type) { - case MOD_LOAD : - - error = iplattach(); - if (error) - break; - - c = NULL; - for(i=strlen(IPL_NAME); i>0; i--) - if (IPL_NAME[i] == '/') { - c = &IPL_NAME[i+1]; - break; - } - if (!c) - c = IPL_NAME; - ipf_devs[IPL_LOGIPF] = - make_dev(&ipl_cdevsw, IPL_LOGIPF, 0, 0, 0600, c); - - c = NULL; - for(i=strlen(IPL_NAT); i>0; i--) - if (IPL_NAT[i] == '/') { - c = &IPL_NAT[i+1]; - break; - } - if (!c) - c = IPL_NAT; - ipf_devs[IPL_LOGNAT] = - make_dev(&ipl_cdevsw, IPL_LOGNAT, 0, 0, 0600, c); - - c = NULL; - for(i=strlen(IPL_STATE); i>0; i--) - if (IPL_STATE[i] == '/') { - c = &IPL_STATE[i+1]; - break; - } - if (!c) - c = IPL_STATE; - ipf_devs[IPL_LOGSTATE] = - make_dev(&ipl_cdevsw, IPL_LOGSTATE, 0, 0, 0600, c); - - c = NULL; - for(i=strlen(IPL_AUTH); i>0; i--) - if (IPL_AUTH[i] == '/') { - c = &IPL_AUTH[i+1]; - break; - } - if (!c) - c = IPL_AUTH; - ipf_devs[IPL_LOGAUTH] = - make_dev(&ipl_cdevsw, IPL_LOGAUTH, 0, 0, 0600, c); - - break; - case MOD_UNLOAD : - destroy_dev(ipf_devs[IPL_LOGIPF]); - destroy_dev(ipf_devs[IPL_LOGNAT]); - destroy_dev(ipf_devs[IPL_LOGSTATE]); - destroy_dev(ipf_devs[IPL_LOGAUTH]); - error = ipldetach(); - break; - default: - error = EINVAL; - break; - } - return error; -} - -static moduledata_t ipfiltermod = { - IPL_VERSION, - ipfilter_modevent, - 0 -}; -DECLARE_MODULE(ipfilter, ipfiltermod, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY); |