diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2001-05-30 02:12:57 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2001-05-30 02:12:57 +0000 |
commit | b15a5a165339d99f4dd696f22eb53227671e1b7c (patch) | |
tree | df0e361f461c1f4de76c81e5b9dc791ba6768ec8 /sys/netinet | |
parent | d818215253f2f1d16376a6482ac14c27f16520a1 (diff) |
Remove ipf. Darren Reed has interpreted his (old, new, whichever)
licence in a way that makes ipf not free according to the rules we
established over 5 years ago, at www.openbsd.org/goals.html (and those
same basic rules govern the other *BSD projects too). Specifically,
Darren says that modified versions are not permitted. But software
which OpenBSD uses and redistributes must be free to all (be they
people or companies), for any purpose they wish to use it, including
modification, use, peeing on, or even integration into baby mulching
machines or atomic bombs to be dropped on Australia. Furthermore, we
know of a number of companies using ipf with modification like us, who
are now in the same situation, and we hope that some of them will work
with us to fill this gap that now exists in OpenBSD (temporarily, we
hope).
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/fil.c | 2131 | ||||
-rw-r--r-- | sys/netinet/in_proto.c | 7 | ||||
-rw-r--r-- | sys/netinet/ip_auth.c | 550 | ||||
-rw-r--r-- | sys/netinet/ip_fil.c | 1802 | ||||
-rw-r--r-- | sys/netinet/ip_fil.h | 633 | ||||
-rw-r--r-- | sys/netinet/ip_fil_compat.h | 1014 | ||||
-rw-r--r-- | sys/netinet/ip_frag.c | 585 | ||||
-rw-r--r-- | sys/netinet/ip_frag.h | 70 | ||||
-rw-r--r-- | sys/netinet/ip_ftp_pxy.c | 789 | ||||
-rw-r--r-- | sys/netinet/ip_input.c | 23 | ||||
-rw-r--r-- | sys/netinet/ip_log.c | 472 | ||||
-rw-r--r-- | sys/netinet/ip_nat.c | 2736 | ||||
-rw-r--r-- | sys/netinet/ip_nat.h | 312 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 45 | ||||
-rw-r--r-- | sys/netinet/ip_proxy.c | 453 | ||||
-rw-r--r-- | sys/netinet/ip_proxy.h | 158 | ||||
-rw-r--r-- | sys/netinet/ip_raudio_pxy.c | 312 | ||||
-rw-r--r-- | sys/netinet/ip_rcmd_pxy.c | 175 | ||||
-rw-r--r-- | sys/netinet/ip_state.c | 1913 | ||||
-rw-r--r-- | sys/netinet/ip_state.h | 202 | ||||
-rw-r--r-- | sys/netinet/ipl.h | 19 |
21 files changed, 3 insertions, 14398 deletions
diff --git a/sys/netinet/fil.c b/sys/netinet/fil.c deleted file mode 100644 index 5d6a67fb890..00000000000 --- a/sys/netinet/fil.c +++ /dev/null @@ -1,2131 +0,0 @@ -/* $OpenBSD: fil.c,v 1.30 2001/05/11 17:20:11 aaron Exp $ */ - -/* - * 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[] = "@(#)$IPFilter: fil.c,v 2.35.2.31 2001/04/03 15:46:41 dar renr Exp $"; -#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_fil_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) + sizeof(*ip6); - 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[128]; -# 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); - if (!len) - return -1; /* potential jumbo gram */ - len += sizeof(ip6_t); - p = ((ip6_t *)ip)->ip6_nxt; - } else -# endif - { - p = ip->ip_p; - len = ip->ip_len; - } - - if ((p == IPPROTO_TCP || p == IPPROTO_UDP || - (v == 4 && 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)) == NULL) { - 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|FR_AUTH)) ? 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 - * $IPFilter: fil.c,v 2.35.2.31 2001/04/03 15:46:41 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/sys/netinet/in_proto.c b/sys/netinet/in_proto.c index ed39157dddc..b10fd0fc85f 100644 --- a/sys/netinet/in_proto.c +++ b/sys/netinet/in_proto.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in_proto.c,v 1.26 2001/05/25 22:08:23 itojun Exp $ */ +/* $OpenBSD: in_proto.c,v 1.27 2001/05/30 02:12:27 deraadt Exp $ */ /* $NetBSD: in_proto.c,v 1.14 1996/02/18 18:58:32 christos Exp $ */ /* @@ -143,11 +143,6 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. #include <netinet/ip_mroute.h> #endif /* MROUTING */ -#ifdef IPFILTER -void iplinit __P((void)); -#define ip_init iplinit -#endif - #ifdef INET6 #include <netinet6/ip6_var.h> #endif /* INET6 */ diff --git a/sys/netinet/ip_auth.c b/sys/netinet/ip_auth.c deleted file mode 100644 index 72dc2799324..00000000000 --- a/sys/netinet/ip_auth.c +++ /dev/null @@ -1,550 +0,0 @@ -/* $OpenBSD: ip_auth.c,v 1.18 2001/05/08 19:58:01 fgsch Exp $ */ - -/* - * Copyright (C) 1998-2001 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[] = "@(#)$IPFilter: ip_auth.c,v 2.11.2.8 2001/04/03 15:48:12 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_fil_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 SOLARIS && defined(_KERNEL) -# if !defined(sparc) - /* - * No need to copyback here as we want to undo the changes, not keep - * them. - */ - if ((ip == (ip_t *)m->b_rptr) && (ip->ip_v == 4)) - { - register u_short bo; - - bo = ip->ip_len; - ip->ip_len = htons(bo); - bo = ip->ip_off; - ip->ip_off = htons(bo); - } -# endif - 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; - WAKEUP(&fr_authnext); -#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 (!fr || !frptr) - error = EINVAL; - else if (!fae) - error = ESRCH; - else { - WRITE_ENTER(&ipf_auth); - *faep = fae->fae_next; - *frptr = fr->fr_next; - RWLOCK_EXIT(&ipf_auth); - KFREE(fae); - } - } else if (fr && frptr) { - 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; - } else - error = EINVAL; - 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 */ - struct route ro; - - bzero((char *)&ro, sizeof(ro)); -# if ((_BSDI_VERSION >= 199802) && (_BSDI_VERSION < 200005)) || \ - defined(__OpenBSD__) - error = ip_output(m, NULL, &ro, IP_FORWARDING, NULL, - NULL); -# else - error = ip_output(m, NULL, &ro, IP_FORWARDING, NULL); -# endif - if (ro.ro_rt) - RTFREE(ro.ro_rt); -# 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/sys/netinet/ip_fil.c b/sys/netinet/ip_fil.c deleted file mode 100644 index 72e16b3b758..00000000000 --- a/sys/netinet/ip_fil.c +++ /dev/null @@ -1,1802 +0,0 @@ -/* $OpenBSD: ip_fil.c,v 1.46 2001/05/08 20:13:15 fgsch Exp $ */ - -/* - * Copyright (C) 1993-2001 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[] = "@(#)$IPFilter: ip_fil.c,v 2.42.2.19 2001/04/03 14:13:37 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_fil_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(__OpenBSD__) -# include <sys/timeout.h> -struct timeout 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) { - SPL_X(s); - return EIO; - } - if (fr_stateinit() == -1) { - SPL_X(s); - return EIO; - } - if (appr_init() == -1) { - SPL_X(s); - return EIO; - } - -# 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 - SPL_X(s); - 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: - SPL_X(s); - 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"; - -#if !defined(__OpenBSD__) - printf("%s initialized. Default = %s all, Logging = %s\n", - ipfilter_version, defpass, -# ifdef IPFILTER_LOG - "enabled"); -# else - "disabled"); -# endif -#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 defined(__OpenBSD__) - timeout_set(&ipfr_slowtimer_ch, ipfr_slowtimer, NULL); - timeout_add(&ipfr_slowtimer_ch, hz / 2); -# 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 -#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 defined(__OpenBSD__) - timeout_del(&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 /* OpenBSD */ -# 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) { - SPL_X(s); - 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) { - SPL_X(s); - 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) - error = fr_auth_ioctl(data, cmd, NULL, NULL); - else - error = EIO; - 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) - error = 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) - error = 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) { - if (fdp->fd_ip.s_addr) { - dst->sin_addr = fdp->fd_ip; - ip->ip_dst = fdp->fd_ip; - } else - dst->sin_addr = 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 - ip->ip_id = htons(ip->ip_id); - ip->ip_len = htons(ip->ip_len); - ip->ip_off = htons(ip->ip_off); - 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 - mhip->ip_off = htons((u_short)mhip->ip_off); - 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]; - FILE *fp; - -# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603)) -# if defined __OpenBSD__ - sprintf(fname, "/var/run/%s", ifp->if_xname); -# else - sprintf(fname, "/tmp/%s", ifp->if_xname); -# endif -# else - sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); -# endif - /* - * XXX - * This is still raceable, if the attacker gains the ability to - * erase the existing file in /tmp - */ - if ((fp = fopen(fname, "a"))) { - fwrite((char *)ip, ntohs(ip->ip_len), 1, fp); - fclose(fp); - } - return 0; -} - - -struct ifnet *get_unit(name, v) -char *name; -int v; -{ - struct ifnet *ifp, **ifa, **nifneta; -# 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++; - nifneta = (struct ifnet **)realloc(ifneta, - (nifs + 1) * sizeof(*ifa)); - if (!nifneta) { - nifs = 0; - free(ifneta); - return NULL; - } - ifneta = nifneta; - 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; -# if defined(__OpenBSD__) - sprintf(fname, "/var/run/%s", ifp->if_xname); -# else - sprintf(fname, "/tmp/%s", ifp->if_xname); -# endif - 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/sys/netinet/ip_fil.h b/sys/netinet/ip_fil.h deleted file mode 100644 index c7989940004..00000000000 --- a/sys/netinet/ip_fil.h +++ /dev/null @@ -1,633 +0,0 @@ -/* $OpenBSD: ip_fil.h,v 1.24 2001/05/08 19:58:01 fgsch Exp $ */ - -/* - * 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 - * $IPFilter: ip_fil.h,v 2.29.2.5 2001/03/20 13:18:05 darrenr Exp $ - */ - -#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/sys/netinet/ip_fil_compat.h b/sys/netinet/ip_fil_compat.h deleted file mode 100644 index c8be3b22056..00000000000 --- a/sys/netinet/ip_fil_compat.h +++ /dev/null @@ -1,1014 +0,0 @@ -/* $OpenBSD: ip_fil_compat.h,v 1.21 2001/05/08 19:58:01 fgsch Exp $ */ - -/* - * Copyright (C) 1993-2001 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 - * $IPFilter: ip_compat.h,v 2.26.2.11 2001/04/03 14:13:35 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/sys/netinet/ip_frag.c b/sys/netinet/ip_frag.c deleted file mode 100644 index e86ad0175cd..00000000000 --- a/sys/netinet/ip_frag.c +++ /dev/null @@ -1,585 +0,0 @@ -/* $OpenBSD: ip_frag.c,v 1.22 2001/04/07 01:06:27 fgsch Exp $ */ - -/* - * 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[] = "@(#)$IPFilter: ip_frag.c,v 2.10.2.8 2001/04/06 12:31:20 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_fil_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; -#elif defined(__OpenBSD__) -# include <sys/timeout.h> -extern struct timeout 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, off; - - if (ipfr_inuse >= IPFT_SIZE) - return NULL; - - if (!(fin->fin_fi.fi_fl & FI_FRAG)) - 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. - */ - off = ip->ip_off & IP_OFFMASK; - if (!off) - fra->ipfr_seen0 = 1; - fra->ipfr_off = off + (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; - - if (!(fin->fin_fi.fi_fl & FI_FRAG)) - return NULL; - - /* - * 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; - - /* - * XXX - We really need to be guarding against the - * retransmission of (src,dst,id,offset-range) here - * because a fragmented packet is never resent with - * the same IP ID#. - */ - off = ip->ip_off & IP_OFFMASK; - if (f->ipfr_seen0) { - if (!off || (fin->fin_fi.fi_fl & FI_SHORT)) - continue; - } else if (!off) - f->ipfr_seen0 = 1; - - 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; - } - 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 defined(__OpenBSD__) - timeout_add(&ipfr_slowtimer_ch, hz/2); -# 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 /* OpenBSD */ -# endif /* NetBSD */ -# endif /* SOLARIS */ -} -#endif /* defined(_KERNEL) */ diff --git a/sys/netinet/ip_frag.h b/sys/netinet/ip_frag.h deleted file mode 100644 index 9da45ae0a68..00000000000 --- a/sys/netinet/ip_frag.h +++ /dev/null @@ -1,70 +0,0 @@ -/* $OpenBSD: ip_frag.h,v 1.15 2001/04/08 20:30:05 smart Exp $ */ - -/* - * 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 - * $IPFilter: ip_frag.h,v 2.4.2.3 2001/04/06 12:31:20 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_char ipfr_ttl; - u_char ipfr_seen0; - 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 (offsetof(ipfr_t, ipfr_off) - \ - offsetof(ipfr_t, ipfr_src)) - -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_FRAG_H__ */ diff --git a/sys/netinet/ip_ftp_pxy.c b/sys/netinet/ip_ftp_pxy.c deleted file mode 100644 index a82544da0f2..00000000000 --- a/sys/netinet/ip_ftp_pxy.c +++ /dev/null @@ -1,789 +0,0 @@ -/* $OpenBSD: ip_ftp_pxy.c,v 1.14 2001/05/08 19:58:01 fgsch Exp $ */ - -/* - * Simple FTP transparent proxy for in-kernel use. For use with the NAT - * code. - * - * $IPFilter: ip_ftp_pxy.c,v 2.7.2.21 2001/01/17 13:30:52 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) || (ftp->ftp_passok == 1)) && - !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/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 5915a5ca322..6806fb4cecc 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_input.c,v 1.72 2001/05/27 00:39:26 angelos Exp $ */ +/* $OpenBSD: ip_input.c,v 1.73 2001/05/30 02:12:31 deraadt Exp $ */ /* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */ /* @@ -148,10 +148,6 @@ u_char ip_protox[IPPROTO_MAX]; int ipqmaxlen = IFQ_MAXLEN; struct in_ifaddrhead in_ifaddr; struct ifqueue ipintrq; -#if defined(IPFILTER) || defined(IPFILTER_LKM) -int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, - struct mbuf **)); -#endif int ipq_locked; static __inline int ipq_lock_try __P((void)); @@ -377,23 +373,6 @@ ipv4_input(m) m_adj(m, ip->ip_len - m->m_pkthdr.len); } -#if defined(IPFILTER) || defined(IPFILTER_LKM) - /* - * Check if we want to allow this packet to be processed. - * Consider it to be bad if not. - */ - { - struct mbuf *m0 = m; - if (fr_checkp && (*fr_checkp)(ip, hlen, m->m_pkthdr.rcvif, 0, &m0)) { - return; - } - if (m0 == 0) { /* in case of 'fastroute' */ - return; - } - ip = mtod(m = m0, struct ip *); - } -#endif - /* * Process options and, if not destined for us, * ship it on. ip_dooptions returns 1 when an diff --git a/sys/netinet/ip_log.c b/sys/netinet/ip_log.c deleted file mode 100644 index 88ce0faee8d..00000000000 --- a/sys/netinet/ip_log.c +++ /dev/null @@ -1,472 +0,0 @@ -/* $OpenBSD: ip_log.c,v 1.12 2001/05/08 19:58:01 fgsch Exp $ */ - -/* - * Copyright (C) 1997-2001 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. - * - * $IPFilter: ip_log.c,v 2.5.2.3 2001/04/03 15:45:49 darrenr Exp $ - */ -#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) -# 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> -# 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 -# 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> -# 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(__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> -# include <netinet/ip_var.h> -# ifndef _KERNEL -# include <syslog.h> -# endif -# include <netinet/ip_fil_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]; - - -/* - * 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 - ipfl.fl_unit = (u_char)ifp->if_unit; - 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) - 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); - wakeup(&iplh[dev]); -# 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)) - 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 - MUTEX_EXIT(&ipl_mutex); - error = SLEEP(&iplh[unit], "ipl sleep"); - if (error) { - SPL_X(s); - return error; - } - MUTEX_ENTER(&ipl_mutex); -# 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. - */ - 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); - break; - } - SPL_NET(s); - MUTEX_ENTER(&ipl_mutex); - iplused[unit] -= dlen; - iplt[unit] = ipl->ipl_next; - KFREES((caddr_t)ipl, dlen); - } - if (!iplt[unit]) { - iplused[unit] = 0; - iplh[unit] = &iplt[unit]; - ipll[unit] = NULL; - } - - MUTEX_EXIT(&ipl_mutex); - SPL_X(s); - return error; -} - - -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/sys/netinet/ip_nat.c b/sys/netinet/ip_nat.c deleted file mode 100644 index 412fb9fb6a2..00000000000 --- a/sys/netinet/ip_nat.c +++ /dev/null @@ -1,2736 +0,0 @@ -/* $OpenBSD: ip_nat.c,v 1.40 2001/05/08 19:58:01 fgsch Exp $ */ - -/* - * Copyright (C) 1995-2001 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[] = "@(#)$IPFilter: ip_nat.c,v 2.37.2.35 2001/04/06 14:07:40 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_fil_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 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 - sum1 = (~ntohs(*sp)) & 0xffff; - 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. - */ -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) && - np && (np->in_flags & IPN_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) && - np && (np->in_flags & IPN_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/sys/netinet/ip_nat.h b/sys/netinet/ip_nat.h deleted file mode 100644 index c0cab691185..00000000000 --- a/sys/netinet/ip_nat.h +++ /dev/null @@ -1,312 +0,0 @@ -/* $OpenBSD: ip_nat.h,v 1.19 2001/05/08 19:58:02 fgsch Exp $ */ - -/* - * 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 - * $IPFilter: ip_nat.h,v 2.17.2.15 2001/04/06 13:47:35 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 -#define IPN_FRAG 0x200000 - - -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 nat_clearlist __P((void)); - -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/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 7ff5629d4d0..68d2648757c 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_output.c,v 1.97 2001/05/29 01:09:14 angelos Exp $ */ +/* $OpenBSD: ip_output.c,v 1.98 2001/05/30 02:12:34 deraadt Exp $ */ /* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */ /* @@ -90,9 +90,6 @@ extern int ipsec_esp_network_default_level; static struct mbuf *ip_insertoptions __P((struct mbuf *, struct mbuf *, int *)); static void ip_mloopback __P((struct ifnet *, struct mbuf *, struct sockaddr_in *)); -#if defined(IPFILTER) || defined(IPFILTER_LKM) -int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); -#endif /* * IP output. The packet in mbuf chain m contains a skeletal IP @@ -558,29 +555,6 @@ sendit: if (sproto != 0) { s = splnet(); -#if defined(IPFILTER) || defined(IPFILTER_LKM) - if (fr_checkp) { - /* - * Ok, it's time for a simple round-trip to the IPF/NAT - * code with the enc0 interface. - */ - struct mbuf *m0 = m; - void *ifp = (void *)&encif[0].sc_if; - if ((*fr_checkp)(ip, hlen, ifp, 1, &m0)) { - error = EHOSTUNREACH; - splx(s); - goto done; - } - if (m0 == 0) { /* in case of 'fastroute' */ - error = 0; - splx(s); - goto done; - } - ip = mtod(m = m0, struct ip *); - hlen = ip->ip_hl << 2; - } -#endif /* IPFILTER */ - tdb = gettdb(sspi, &sdst, sproto); if (tdb == NULL) { error = EHOSTUNREACH; @@ -624,23 +598,6 @@ sendit: } #endif /* IPSEC */ -#if defined(IPFILTER) || defined(IPFILTER_LKM) - /* - * looks like most checking has been done now...do a filter check - */ - { - struct mbuf *m0 = m; - if (fr_checkp && (*fr_checkp)(ip, hlen, ifp, 1, &m0)) { - error = EHOSTUNREACH; - goto done; - } - if (m0 == 0) { /* in case of 'fastroute' */ - error = 0; - goto done; - } - ip = mtod(m = m0, struct ip *); - } -#endif /* * If small enough for interface, can just send directly. */ diff --git a/sys/netinet/ip_proxy.c b/sys/netinet/ip_proxy.c deleted file mode 100644 index 467b4f86eee..00000000000 --- a/sys/netinet/ip_proxy.c +++ /dev/null @@ -1,453 +0,0 @@ -/* $OpenBSD: ip_proxy.c,v 1.13 2001/01/30 04:23:56 kjell Exp $ */ - -/* - * 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[] = "@(#)$IPFilter: 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_fil_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/sys/netinet/ip_proxy.h b/sys/netinet/ip_proxy.h deleted file mode 100644 index 59a94412063..00000000000 --- a/sys/netinet/ip_proxy.h +++ /dev/null @@ -1,158 +0,0 @@ -/* $OpenBSD: ip_proxy.h,v 1.9 2001/01/17 04:47:15 fgsch Exp $ */ - -/* - * 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. - * - * $IPFilter: 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/sys/netinet/ip_raudio_pxy.c b/sys/netinet/ip_raudio_pxy.c deleted file mode 100644 index 2c15281ffa6..00000000000 --- a/sys/netinet/ip_raudio_pxy.c +++ /dev/null @@ -1,312 +0,0 @@ -/* $OpenBSD: ip_raudio_pxy.c,v 1.9 2001/05/08 19:58:02 fgsch Exp $ */ - -/* - * $IPFilter: ip_raudio_pxy.c,v 1.7.2.4 2001/04/03 15:45:15 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; - int off, dlen; - tcphdr_t *tcp; - 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; - dlen = MIN(sizeof(membuf), dlen); - copyout_mblk(m, off, dlen, (char *)membuf); -#else - m = *(mb_t **)fin->fin_mp; - - dlen = mbufchainlen(m) - off; - if (dlen <= 0) - return 0; - dlen = MIN(sizeof(membuf), dlen); - m_copydata(m, off, 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/sys/netinet/ip_rcmd_pxy.c b/sys/netinet/ip_rcmd_pxy.c deleted file mode 100644 index b3113f563a1..00000000000 --- a/sys/netinet/ip_rcmd_pxy.c +++ /dev/null @@ -1,175 +0,0 @@ -/* $OpenBSD: ip_rcmd_pxy.c,v 1.5 2001/01/17 04:47:16 fgsch Exp $ */ - -/* - * $IPFilter: 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/sys/netinet/ip_state.c b/sys/netinet/ip_state.c deleted file mode 100644 index 6a3f5954138..00000000000 --- a/sys/netinet/ip_state.c +++ /dev/null @@ -1,1913 +0,0 @@ -/* $OpenBSD: ip_state.c,v 1.27 2001/04/07 01:06:28 fgsch Exp $ */ - -/* - * Copyright (C) 1995-2001 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[] = "@(#)$IPFilter: ip_state.c,v 2.30.2.30 2001/04/06 12:31:21 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_fil_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_udpacktimeout = 24, - fr_icmptimeout = 120, - fr_icmpacktimeout = 12; -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) && (pass & FR_KEEPFRAG)) - 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)) { - if (fin->fin_rev) - is->is_age = fr_icmpacktimeout; - else - 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; - } - } if ((pr == IPPROTO_UDP)) { - if (fin->fin_rev) - is->is_age = fr_udpacktimeout; - else - is->is_age = fr_udptimeout; - } - 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) && (pass & FR_KEEPFRAG)) - 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/sys/netinet/ip_state.h b/sys/netinet/ip_state.h deleted file mode 100644 index f025ef00cff..00000000000 --- a/sys/netinet/ip_state.h +++ /dev/null @@ -1,202 +0,0 @@ -/* $OpenBSD: ip_state.h,v 1.18 2001/02/06 17:29:31 fgsch Exp $ */ - -/* - * 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 - * $IPFilter: 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 - -#ifndef IPSTATE_SIZE -# define IPSTATE_SIZE 5737 -#endif - -#ifndef IPSTATE_MAX -# define IPSTATE_MAX 4013 /* Maximum number of states held */ -#endif - -#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/sys/netinet/ipl.h b/sys/netinet/ipl.h deleted file mode 100644 index 9baf5e3b5e8..00000000000 --- a/sys/netinet/ipl.h +++ /dev/null @@ -1,19 +0,0 @@ -/* $OpenBSD: ipl.h,v 1.15 2001/05/08 19:58:02 fgsch Exp $ */ - -/* - * Copyright (C) 1993-2001 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 - * $IPFilter: ipl.h,v 2.15.2.19 2001/04/06 12:21:28 darrenr Exp $ - */ - -#ifndef __IPL_H__ -#define __IPL_H__ - -#define IPL_VERSION "IP Filter: v3.4.17" - -#endif |