From b38f3fb061c38679370cfc86fa0126a1cdc7d848 Mon Sep 17 00:00:00 2001 From: Darren Reed Date: Tue, 19 Mar 2002 11:44:16 +0000 Subject: fix conflicts (mostly damn rcs id's) generated by import --- sys/contrib/ipfilter/netinet/fil.c | 201 +++++---- sys/contrib/ipfilter/netinet/ip_auth.c | 14 +- sys/contrib/ipfilter/netinet/ip_auth.h | 3 +- sys/contrib/ipfilter/netinet/ip_compat.h | 446 +++++++++++++++++--- sys/contrib/ipfilter/netinet/ip_fil.c | 582 +++++++++++++++++++------ sys/contrib/ipfilter/netinet/ip_fil.h | 88 ++-- sys/contrib/ipfilter/netinet/ip_frag.c | 19 +- sys/contrib/ipfilter/netinet/ip_frag.h | 16 +- sys/contrib/ipfilter/netinet/ip_ftp_pxy.c | 148 ++++--- sys/contrib/ipfilter/netinet/ip_log.c | 74 ++-- sys/contrib/ipfilter/netinet/ip_nat.c | 465 ++++++++++++-------- sys/contrib/ipfilter/netinet/ip_nat.h | 20 +- sys/contrib/ipfilter/netinet/ip_proxy.c | 141 +++++-- sys/contrib/ipfilter/netinet/ip_proxy.h | 22 +- sys/contrib/ipfilter/netinet/ip_raudio_pxy.c | 15 +- sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c | 24 +- sys/contrib/ipfilter/netinet/ip_state.c | 607 ++++++++++++++++++--------- sys/contrib/ipfilter/netinet/ip_state.h | 16 +- sys/contrib/ipfilter/netinet/ipl.h | 4 +- sys/contrib/ipfilter/netinet/mlfk_ipl.c | 4 + 20 files changed, 2055 insertions(+), 854 deletions(-) (limited to 'sys/contrib/ipfilter') diff --git a/sys/contrib/ipfilter/netinet/fil.c b/sys/contrib/ipfilter/netinet/fil.c index bd7cd1ff818e..dd5cad1e43cd 100644 --- a/sys/contrib/ipfilter/netinet/fil.c +++ b/sys/contrib/ipfilter/netinet/fil.c @@ -3,6 +3,9 @@ * * See the IPFILTER.LICENCE file for details on licencing. */ +#ifdef __sgi +# include +#endif #include #include #include @@ -34,7 +37,6 @@ # include # include #endif -#include #if !defined(__SVR4) && !defined(__svr4__) # ifndef linux # include @@ -77,10 +79,10 @@ #endif #include #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_proxy.h" #include "netinet/ip_auth.h" # if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) # include @@ -97,7 +99,6 @@ #if !defined(lint) static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-2000 Darren Reed"; -/* static const char rcsid[] = "@(#)$Id: fil.c,v 2.35.2.39 2001/07/18 13:30:32 darrenr Exp $"; */ static const char rcsid[] = "@(#)$FreeBSD$"; #endif @@ -108,7 +109,7 @@ 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() +# define IPLLOG(a, c, d, e) ipflog(a, c, d, e) #else /* #ifndef _KERNEL */ # define FR_VERBOSE(verb_pr) # define FR_DEBUG(verb_pr) @@ -263,7 +264,7 @@ fr_info_t *fin; fin->fin_off = off; fin->fin_plen = plen; - fin->fin_dp = (void *)tcp; + fin->fin_dp = (char *)tcp; off <<= 3; switch (p) @@ -283,7 +284,7 @@ fr_info_t *fin; { case ICMP6_ECHO_REPLY : case ICMP6_ECHO_REQUEST : - minicmpsz = ICMP6ERR_MINPKTLEN; + minicmpsz = ICMP6_MINLEN; break; case ICMP6_DST_UNREACH : case ICMP6_PACKET_TOO_BIG : @@ -383,6 +384,19 @@ getports: fin->fin_data[1] = ntohs(tcp->th_dport); } break; + case IPPROTO_ESP : +#ifdef USE_INET6 + if (v == 6) { + if (plen < 8) + fi->fi_fl |= FI_SHORT; + } else +#endif + if (v == 4) { + if (((ip->ip_len < hlen + 8) && !off) || + (off && off < 8)) + fi->fi_fl |= FI_SHORT; + } + break; default : break; } @@ -548,8 +562,8 @@ fr_info_t *fin; * 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; +int fr_scanlist(passin, ip, fin, m) +u_32_t passin; ip_t *ip; register fr_info_t *fin; void *m; @@ -557,20 +571,21 @@ 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; + u_32_t pass, passt, passl; + frentry_t *frl; + frl = NULL; + pass = passin; fr = fin->fin_fr; fin->fin_fr = NULL; - fin->fin_rule = 0; - fin->fin_group = 0; off = fin->fin_off; - 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) { + FR_VERBOSE(("%d (%#x)\n", skip, fr->fr_flags)); skip--; continue; } @@ -581,25 +596,28 @@ void *m; * check that we are working for the right interface */ #ifdef _KERNEL -# if BSD >= 199306 +# 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)) + (fr->fr_oifa != ((mb_t *)m)->m_pkthdr.rcvif))) 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')); +#endif + + FR_VERBOSE(("%c", fr->fr_skip ? 's' : + (pass & FR_PASS) ? 'p' : + (pass & FR_AUTH) ? 'a' : + (pass & FR_ACCOUNT) ? 'A' : + (pass & FR_NOMATCH) ? 'n' : '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; @@ -621,22 +639,19 @@ void *m; /* * Unrolled loops (4 each, for 32 bits). */ - i |= ((*lip & *lm) != *ld) << 19; FR_DEBUG(("1a. %#08x & %#08x != %#08x\n", *lip, *lm, *ld)); + i |= ((*lip++ & *lm++) != *ld++) << 5; 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; + i |= ((*lip++ & *lm++) != *ld++) << 5; FR_DEBUG(("1c. %#08x & %#08x != %#08x\n", *lip, *lm, *ld)); - lip++, lm++, ld++; - i |= ((*lip & *lm) != *ld) << 19; + i |= ((*lip++ & *lm++) != *ld++) << 5; FR_DEBUG(("1d. %#08x & %#08x != %#08x\n", *lip, *lm, *ld)); + i |= ((*lip++ & *lm++) != *ld++) << 5; } else { lip += 3; lm += 3; @@ -645,23 +660,19 @@ void *m; 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)); + i |= ((*lip++ & *lm++) != *ld++) << 6; 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; + i |= ((*lip++ & *lm++) != *ld++) << 6; FR_DEBUG(("2c. %#08x & %#08x != %#08x\n", *lip, *lm, *ld)); - lip++, lm++, ld++; - i |= ((*lip & *lm) != *ld) << 20; + i |= ((*lip++ & *lm++) != *ld++) << 6; FR_DEBUG(("2d. %#08x & %#08x != %#08x\n", *lip, *lm, *ld)); + i |= ((*lip++ & *lm++) != *ld++) << 6; } else { lip += 3; lm += 3; @@ -670,14 +681,12 @@ void *m; 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); + i |= ((*lip++ & *lm++) != *ld++); FR_DEBUG(("4. %#08x & %#08x != %#08x\n", *lip, *lm, *ld)); + i |= ((*lip & *lm) != *ld); if (i) continue; } @@ -704,17 +713,30 @@ void *m; } } FR_VERBOSE(("*")); - /* - * Just log this packet... - */ + + if (fr->fr_flags & FR_NOMATCH) { + passt = passl; + passl = passin; + fin->fin_fr = frl; + frl = NULL; + if (fr->fr_flags & FR_QUICK) + break; + continue; + } + + passl = passt; passt = fr->fr_flags; + frl = fin->fin_fr; + fin->fin_fr = fr; #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 + /* + * Just log this packet... + */ if ((passt & FR_LOGMASK) == FR_LOG) { if (!IPLLOG(passt, ip, fin, m)) { if (passt & FR_LOGORBLOCK) @@ -725,32 +747,33 @@ void *m; 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) + if (passt & 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) { + if (fr->fr_grp != NULL) { fin->fin_fr = fr->fr_grp; - pass = fr_scanlist(pass, ip, fin, m); + passt = fr_scanlist(passt, 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) + if (passt & FR_DONTCACHE) logged = 1; } - if (pass & FR_QUICK) + if (!(skip = fr->fr_skip) && (passt & FR_LOGMASK) != FR_LOG) + pass = passt; + FR_DEBUG(("pass %#x\n", pass)); + if (passt & FR_QUICK) break; } if (logged) pass |= FR_DONTCACHE; + pass |= (fi->fi_fl << 24); return pass; } @@ -806,7 +829,7 @@ int out; /* * disable delayed checksums. */ - if (out && (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA)) { + if ((out != 0) && (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA)) { in_delayed_cksum(m); m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; } @@ -847,6 +870,9 @@ int out; case IPPROTO_ICMP: plen = ICMPERR_MAXPKTLEN - sizeof(ip_t); break; + case IPPROTO_ESP: + plen = 8; + break; # ifdef USE_INET6 case IPPROTO_ICMPV6 : /* @@ -918,20 +944,26 @@ int out; 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; + if (fr_minttllog & 1) + logit = -3; + if (fr_minttllog & 2) + drop = 1; } } else # endif if (!out) { if (fr_chksrc && !fr_verifysrc(ip->ip_src, ifp)) { ATOMIC_INCL(frstats[0].fr_badsrc); - if (fr_chksrc == 2) + if (fr_chksrc & 1) + drop = 1; + if (fr_chksrc & 2) logit = -2; } else if (ip->ip_ttl < fr_minttl) { ATOMIC_INCL(frstats[0].fr_badttl); - if (fr_minttllog) + if (fr_minttllog & 1) logit = -3; + if (fr_minttllog & 2) + drop = 1; } } if (drop) { @@ -1022,6 +1054,7 @@ int out; FI_COPYSIZE); if (pass & FR_NOMATCH) { ATOMIC_INCL(frstats[out].fr_nom); + fin->fin_fr = NULL; } } } else @@ -1035,11 +1068,7 @@ int out; */ if ((pass & FR_AUTH)) { if (fr_newauth((mb_t *)m, fin, ip) != 0) { -#ifdef _KERNEL m = *mp = NULL; -#else - ; -#endif error = 0; } else error = ENOSPC; @@ -1069,7 +1098,7 @@ int out; } } if (pass & FR_KEEPSTATE) { - if (fr_addstate(ip, fin, 0) == NULL) { + if (fr_addstate(ip, fin, NULL, 0) == NULL) { ATOMIC_INCL(frstats[out].fr_bads); } else { ATOMIC_INCL(frstats[out].fr_ads); @@ -1098,11 +1127,19 @@ int out; 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); + if (list != NULL) { + u_32_t sg, sr; + + fin->fin_fr = list; + sg = fin->fin_group; + sr = fin->fin_rule; + if (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT) { + ATOMIC_INCL(frstats[1].fr_acct); + } + fin->fin_group = sg; + fin->fin_rule = sr; + fin->fin_fr = fr; } - fin->fin_fr = fr; changed = ip_natout(ip, fin); } else fin->fin_fr = fr; @@ -1151,10 +1188,10 @@ logit: # if SOLARIS mc = dupmsg(m); # else -# ifndef linux - mc = m_copy(m, 0, M_COPYALL); +# if defined(__OpenBSD__) && (OpenBSD >= 199905) + mc = m_copym2(m, 0, M_COPYALL, M_DONTWAIT); # else - ; + mc = m_copy(m, 0, M_COPYALL); # endif # endif #endif @@ -1171,7 +1208,6 @@ logit: * some operating systems. */ if (!out) { -#ifdef _KERNEL if (pass & FR_RETICMP) { int dst; @@ -1187,19 +1223,6 @@ logit: 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_fl & FI_SHORT)) { - verbose("- TCP RST sent\n"); - ATOMIC_INCL(frstats[1].fr_ret); - } -#endif } else { if (pass & FR_RETRST) error = ECONNRESET; @@ -1224,8 +1247,10 @@ logit: frdest_t *fdp = &fr->fr_tif; if (((pass & FR_FASTROUTE) && !out) || - (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) + (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) { (void) ipfr_fastroute(m, mp, fin, fdp); + m = *mp; + } if (mc != NULL) (void) ipfr_fastroute(mc, &mc, fin, &fr->fr_dif); @@ -1260,6 +1285,12 @@ logit: return 0; if (pass & FR_AUTH) return -2; + if ((pass & FR_RETMASK) == FR_RETRST) + return -3; + if ((pass & FR_RETMASK) == FR_RETICMP) + return -4; + if ((pass & FR_RETMASK) == FR_FAKEICMP) + return -5; return -1; #endif /* _KERNEL */ } @@ -1481,7 +1512,7 @@ nodata: * SUCH DAMAGE. * * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 - * $Id: fil.c,v 2.35.2.39 2001/07/18 13:30:32 darrenr Exp $ + * $Id: fil.c,v 2.35.2.58 2002/03/13 02:23:13 darrenr Exp $ */ /* * Copy data from an mbuf chain starting "off" bytes from the beginning, diff --git a/sys/contrib/ipfilter/netinet/ip_auth.c b/sys/contrib/ipfilter/netinet/ip_auth.c index a3182e262beb..ee3a7d71e16f 100644 --- a/sys/contrib/ipfilter/netinet/ip_auth.c +++ b/sys/contrib/ipfilter/netinet/ip_auth.c @@ -3,6 +3,9 @@ * * See the IPFILTER.LICENCE file for details on licencing. */ +#ifdef __sgi +# include +#endif #include #include #include @@ -19,7 +22,6 @@ #else # include #endif -#include #ifndef linux # include #endif @@ -311,7 +313,7 @@ ip_t *ip; int fr_auth_ioctl(data, mode, cmd, fr, frptr) caddr_t data; int mode; -#if defined(__NetBSD__) || defined(__OpenBSD__) || (FreeBSD_version >= 300003) +#if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003) u_long cmd; #else int cmd; @@ -382,9 +384,7 @@ frentry_t *fr, **frptr; 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; @@ -458,7 +458,7 @@ fr_authioctlloop: bzero((char *)&ro, sizeof(ro)); # if ((_BSDI_VERSION >= 199802) && (_BSDI_VERSION < 200005)) || \ - defined(__OpenBSD__) + defined(__OpenBSD__) || (defined(IRIX) && (IRIX >= 605)) error = ip_output(m, NULL, &ro, IP_FORWARDING, NULL, NULL); # else @@ -526,7 +526,6 @@ fr_authioctlloop: } -#ifdef _KERNEL /* * Free all network buffer memory used to keep saved packets. */ @@ -587,7 +586,7 @@ void fr_authexpire() register frauthent_t *fae, **faep; register frentry_t *fr, **frp; mb_t *m; -#if !SOLARIS +#if !SOLARIS && defined(_KERNEL) int s; #endif @@ -626,4 +625,3 @@ void fr_authexpire() RWLOCK_EXIT(&ipf_auth); SPL_X(s); } -#endif diff --git a/sys/contrib/ipfilter/netinet/ip_auth.h b/sys/contrib/ipfilter/netinet/ip_auth.h index 638a03db2bd5..cc2b661f4b45 100644 --- a/sys/contrib/ipfilter/netinet/ip_auth.h +++ b/sys/contrib/ipfilter/netinet/ip_auth.h @@ -52,7 +52,8 @@ extern void fr_authexpire __P((void)); extern void fr_authunload __P((void)); extern mb_t *fr_authpkts[]; extern int fr_newauth __P((mb_t *, fr_info_t *, ip_t *)); -#if defined(__NetBSD__) || defined(__OpenBSD__) +#if defined(__NetBSD__) || defined(__OpenBSD__) || \ + (__FreeBSD_version >= 300003) extern int fr_auth_ioctl __P((caddr_t, int, u_long, frentry_t *, frentry_t **)); #else extern int fr_auth_ioctl __P((caddr_t, int, int, frentry_t *, frentry_t **)); diff --git a/sys/contrib/ipfilter/netinet/ip_compat.h b/sys/contrib/ipfilter/netinet/ip_compat.h index 76dd88c02eca..d4b7bf6c5463 100644 --- a/sys/contrib/ipfilter/netinet/ip_compat.h +++ b/sys/contrib/ipfilter/netinet/ip_compat.h @@ -26,14 +26,21 @@ #ifndef SOLARIS #define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) #endif -#if SOLARIS && !defined(SOLARIS2) -# define SOLARIS2 4 /* Pick an old version */ -#endif -#if SOLARIS2 >= 8 -# ifndef USE_INET6 -# define USE_INET6 +#if SOLARIS +# if !defined(SOLARIS2) +# define SOLARIS2 3 /* Pick an old version */ +# endif +# if SOLARIS2 >= 8 +# ifndef USE_INET6 +# define USE_INET6 +# endif +# else +# undef USE_INET6 # endif #endif +#if defined(sun) && !(defined(__svr4__) || defined(__SVR4)) +# undef USE_INET6 +#endif #if defined(_KERNEL) || defined(KERNEL) || defined(__KERNEL__) # undef KERNEL @@ -63,6 +70,18 @@ struct ether_addr { }; #endif +#ifndef LIFNAMSIZ +# ifdef IF_NAMESIZE +# define LIFNAMSIZ IF_NAMESIZE +# else +# ifdef IFNAMSIZ +# define LIFNAMSIZ IFNAMSIZ +# else +# define LIFNAMSIZ 16 +# endif +# endif +#endif + #if defined(__sgi) && !defined(IPFILTER_LKM) # ifdef __STDC__ # define IPL_EXTERN(ep) ipfilter##ep @@ -77,12 +96,37 @@ struct ether_addr { # endif #endif +#ifdef __sgi +# include +#endif + #ifdef linux # include #endif + + +/* + * This is a workaround for troubles on FreeBSD and OpenBSD. + */ +#ifndef _KERNEL +# define ADD_KERNEL +# define _KERNEL +# define KERNEL +#endif +#ifdef __OpenBSD__ +struct file; +#endif +#include +#ifdef ADD_KERNEL +# undef _KERNEL +# undef KERNEL +#endif + #if SOLARIS # define MTYPE(m) ((m)->b_datap->db_type) -# include +# if SOLARIS2 >= 4 +# include +# endif # include # include # include @@ -138,12 +182,14 @@ typedef struct qif { 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]; + char qf_name[LIFNAMSIZ]; /* * in case the ILL has disappeared... */ size_t qf_hl; /* header length */ int qf_sap; + size_t qf_incnt; + size_t qf_outcnt; } qif_t; #else /* SOLARIS */ # if !defined(__sgi) @@ -211,6 +257,7 @@ typedef unsigned int u_32_t; # endif typedef struct ip6_hdr ip6_t; # endif +# include union i6addr { u_32_t i6[4]; struct in_addr in4; @@ -226,6 +273,14 @@ union i6addr { #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) +#define IP6_ISZERO(a) ((((union i6addr *)(a))->i6[0] | \ + ((union i6addr *)(a))->i6[1] | \ + ((union i6addr *)(a))->i6[2] | \ + ((union i6addr *)(a))->i6[3]) == 0) +#define IP6_NOTZERO(a) ((((union i6addr *)(a))->i6[0] | \ + ((union i6addr *)(a))->i6[1] | \ + ((union i6addr *)(a))->i6[2] | \ + ((union i6addr *)(a))->i6[3]) != 0) #ifndef MAX #define MAX(a,b) (((a) > (b)) ? (a) : (b)) @@ -326,6 +381,21 @@ union i6addr { * Build some macros and #defines to enable the same code to compile anywhere * Well, that's the idea, anyway :-) */ +#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 +typedef struct mbuf mb_t; +#endif /* SOLARIS */ + #if !SOLARIS || (SOLARIS2 < 6) || !defined(KERNEL) # define ATOMIC_INCL ATOMIC_INC # define ATOMIC_INC64 ATOMIC_INC @@ -507,11 +577,19 @@ extern void m_copyback __P((struct mbuf *, int, int, caddr_t)); # define GET_MINOR(x) minor(x) # endif # if (BSD >= 199306) || defined(__FreeBSD__) -# include +# if (defined(__NetBSD_Version__) && (__NetBSD_Version__ < 105180000)) || \ + defined(__FreeBSD__) || defined(__OpenBSD__) || defined(_BSDI_VERSION) +# include +# endif # if !defined(__FreeBSD__) || (defined (__FreeBSD__) && __FreeBSD__>=3) -# include -# include +# if (defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105180000)) || \ + (defined(OpenBSD) && (OpenBSD >= 200111)) +# include +# else +# include extern vm_map_t kmem_map; +# endif +# include # else /* !__FreeBSD__ || (__FreeBSD__ && __FreeBSD__>=3) */ # include # endif /* !__FreeBSD__ || (__FreeBSD__ && __FreeBSD__>=3) */ @@ -543,7 +621,7 @@ extern vm_map_t kmem_map; # endif /* NetBSD && (NetBSD <= 1991011) && (NetBSD >= 199407) */ # define PANIC(x,y) if (x) panic y #else /* KERNEL */ -# define SLEEP(x,y) ; +# define SLEEP(x,y) 1 # define WAKEUP(x) ; # define PANIC(x,y) ; # define ATOMIC_INC(x) (x)++ @@ -565,40 +643,18 @@ extern vm_map_t kmem_map; # define KMALLOCS(a,b,c) (a) = (b)malloc(c) # define KFREE(x) free(x) # define KFREES(x,s) free(x) +# define FREE_MB_T(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 +# define IFNAME(x) get_ifname((struct ifnet *)x) +# define UIOMOVE(a,b,c,d) ipfuiomove(a,b,c,d) +extern void m_copydata __P((mb_t *, int, int, caddr_t)); +extern int ipfuiomove __P((caddr_t, int, int, struct uio *)); #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 */ - /* * 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 @@ -607,38 +663,152 @@ typedef struct mbuf mb_t; #ifndef ICMP_MINLEN # define ICMP_MINLEN 8 #endif +#ifndef ICMP_ECHOREPLY +# define ICMP_ECHOREPLY 0 +#endif #ifndef ICMP_UNREACH -# define ICMP_UNREACH ICMP_DEST_UNREACH +# define ICMP_UNREACH 3 +#endif +#ifndef ICMP_UNREACH_NET +# define ICMP_UNREACH_NET 0 +#endif +#ifndef ICMP_UNREACH_HOST +# define ICMP_UNREACH_HOST 1 +#endif +#ifndef ICMP_UNREACH_PROTOCOL +# define ICMP_UNREACH_PROTOCOL 2 +#endif +#ifndef ICMP_UNREACH_PORT +# define ICMP_UNREACH_PORT 3 +#endif +#ifndef ICMP_UNREACH_NEEDFRAG +# define ICMP_UNREACH_NEEDFRAG 4 +#endif +#ifndef ICMP_UNREACH_SRCFAIL +# define ICMP_UNREACH_SRCFAIL 5 +#endif +#ifndef ICMP_UNREACH_NET_UNKNOWN +# define ICMP_UNREACH_NET_UNKNOWN 6 +#endif +#ifndef ICMP_UNREACH_HOST_UNKNOWN +# define ICMP_UNREACH_HOST_UNKNOWN 7 +#endif +#ifndef ICMP_UNREACH_ISOLATED +# define ICMP_UNREACH_ISOLATED 8 +#endif +#ifndef ICMP_UNREACH_NET_PROHIB +# define ICMP_UNREACH_NET_PROHIB 9 +#endif +#ifndef ICMP_UNREACH_HOST_PROHIB +# define ICMP_UNREACH_HOST_PROHIB 10 +#endif +#ifndef ICMP_UNREACH_TOSNET +# define ICMP_UNREACH_TOSNET 11 +#endif +#ifndef ICMP_UNREACH_TOSHOST +# define ICMP_UNREACH_TOSHOST 12 +#endif +#ifndef ICMP_UNREACH_ADMIN_PROHIBIT +# define ICMP_UNREACH_ADMIN_PROHIBIT 13 +#endif +#ifndef ICMP_UNREACH_HOST_PRECEDENCE +# define ICMP_UNREACH_HOST_PRECEDENCE 14 +#endif +#ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF +# define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 #endif #ifndef ICMP_SOURCEQUENCH -# define ICMP_SOURCEQUENCH ICMP_SOURCE_QUENCH +# define ICMP_SOURCEQUENCH 4 +#endif +#ifndef ICMP_REDIRECT_NET +# define ICMP_REDIRECT_NET 0 +#endif +#ifndef ICMP_REDIRECT_HOST +# define ICMP_REDIRECT_HOST 1 +#endif +#ifndef ICMP_REDIRECT_TOSNET +# define ICMP_REDIRECT_TOSNET 2 +#endif +#ifndef ICMP_REDIRECT_TOSHOST +# define ICMP_REDIRECT_TOSHOST 3 +#endif +#ifndef ICMP_ALTHOSTADDR +# define ICMP_ALTHOSTADDR 6 #endif #ifndef ICMP_TIMXCEED -# define ICMP_TIMXCEED ICMP_TIME_EXCEEDED +# define ICMP_TIMXCEED 11 +#endif +#ifndef ICMP_TIMXCEED_INTRANS +# define ICMP_TIMXCEED_INTRANS 0 +#endif +#ifndef ICMP_TIMXCEED_REASS +# define ICMP_TIMXCEED_REASS 1 #endif #ifndef ICMP_PARAMPROB -# define ICMP_PARAMPROB ICMP_PARAMETERPROB +# define ICMP_PARAMPROB 12 +#endif +#ifndef ICMP_PARAMPROB_ERRATPTR +# define ICMP_PARAMPROB_ERRATPTR 0 +#endif +#ifndef ICMP_PARAMPROB_OPTABSENT +# define ICMP_PARAMPROB_OPTABSENT 1 +#endif +#ifndef ICMP_PARAMPROB_LENGTH +# define ICMP_PARAMPROB_LENGTH 2 #endif #ifndef ICMP_TSTAMP -# define ICMP_TSTAMP ICMP_TIMESTAMP +# define ICMP_TSTAMP 13 #endif #ifndef ICMP_TSTAMPREPLY -# define ICMP_TSTAMPREPLY ICMP_TIMESTAMPREPLY +# define ICMP_TSTAMPREPLY 14 #endif #ifndef ICMP_IREQ -# define ICMP_IREQ ICMP_INFO_REQUEST +# define ICMP_IREQ 15 #endif #ifndef ICMP_IREQREPLY -# define ICMP_IREQREPLY ICMP_INFO_REPLY +# define ICMP_IREQREPLY 16 #endif #ifndef ICMP_MASKREQ -# define ICMP_MASKREQ ICMP_ADDRESS +# define ICMP_MASKREQ 17 #endif #ifndef ICMP_MASKREPLY -# define ICMP_MASKREPLY ICMP_ADDRESSREPLY +# define ICMP_MASKREPLY 18 #endif -#ifndef ICMP_PARAMPROB_OPTABSENT -# define ICMP_PARAMPROB_OPTABSENT 1 +#ifndef ICMP_TRACEROUTE +# define ICMP_TRACEROUTE 30 +#endif +#ifndef ICMP_DATACONVERR +# define ICMP_DATACONVERR 31 +#endif +#ifndef ICMP_MOBILE_REDIRECT +# define ICMP_MOBILE_REDIRECT 32 +#endif +#ifndef ICMP_IPV6_WHEREAREYOU +# define ICMP_IPV6_WHEREAREYOU 33 +#endif +#ifndef ICMP_IPV6_IAMHERE +# define ICMP_IPV6_IAMHERE 34 +#endif +#ifndef ICMP_MOBILE_REGREQUEST +# define ICMP_MOBILE_REGREQUEST 35 +#endif +#ifndef ICMP_MOBILE_REGREPLY +# define ICMP_MOBILE_REGREPLY 36 +#endif +#ifndef ICMP_SKIP +# define ICMP_SKIP 39 +#endif +#ifndef ICMP_PHOTURIS +# define ICMP_PHOTURIS 40 +#endif +#ifndef ICMP_PHOTURIS_UNKNOWN_INDEX +# define ICMP_PHOTURIS_UNKNOWN_INDEX 1 +#endif +#ifndef ICMP_PHOTURIS_AUTH_FAILED +# define ICMP_PHOTURIS_AUTH_FAILED 2 +#endif +#ifndef ICMP_PHOTURIS_DECRYPT_FAILED +# define ICMP_PHOTURIS_DECRYPT_FAILED 3 #endif #ifndef IPVERSION # define IPVERSION 4 @@ -727,6 +897,15 @@ typedef struct mbuf mb_t; #ifndef IPOPT_OLEN # define IPOPT_OLEN 1 #endif +#ifndef IPPROTO_GRE +# define IPPROTO_GRE 47 /* GRE encaps RFC 1701 */ +#endif +#ifndef IPPROTO_ESP +# define IPPROTO_ESP 50 +#endif +#ifndef IPPROTO_ICMPV6 +# define IPPROTO_ICMPV6 58 +#endif #ifdef linux #include @@ -998,6 +1177,10 @@ struct ether_addr { #define A_A & #endif +#if (BSD >= 199306) && !defined(m_act) +# define m_act m_nextpkt +#endif + #ifndef ICMP_ROUTERADVERT # define ICMP_ROUTERADVERT 9 #endif @@ -1017,9 +1200,170 @@ struct ether_addr { #define ICMPERR_IPICMPHLEN (20 + 8) #define ICMPERR_MINPKTLEN (20 + 8 + 20) #define ICMPERR_MAXPKTLEN (20 + 8 + 20 + 8) +#define ICMP6_MINLEN 8 #define ICMP6ERR_MINPKTLEN (40 + 8) #define ICMP6ERR_IPICMPHLEN (40 + 8 + 40) +#ifndef ICMP6_DST_UNREACH +# define ICMP6_DST_UNREACH 1 +#endif +#ifndef ICMP6_PACKET_TOO_BIG +# define ICMP6_PACKET_TOO_BIG 2 +#endif +#ifndef ICMP6_TIME_EXCEEDED +# define ICMP6_TIME_EXCEEDED 3 +#endif +#ifndef ICMP6_PARAM_PROB +# define ICMP6_PARAM_PROB 4 +#endif + +#ifndef ICMP6_ECHO_REQUEST +# define ICMP6_ECHO_REQUEST 128 +#endif +#ifndef ICMP6_ECHO_REPLY +# define ICMP6_ECHO_REPLY 129 +#endif +#ifndef ICMP6_MEMBERSHIP_QUERY +# define ICMP6_MEMBERSHIP_QUERY 130 +#endif +#ifndef MLD6_LISTENER_QUERY +# define MLD6_LISTENER_QUERY 130 +#endif +#ifndef ICMP6_MEMBERSHIP_REPORT +# define ICMP6_MEMBERSHIP_REPORT 131 +#endif +#ifndef MLD6_LISTENER_REPORT +# define MLD6_LISTENER_REPORT 131 +#endif +#ifndef ICMP6_MEMBERSHIP_REDUCTION +# define ICMP6_MEMBERSHIP_REDUCTION 132 +#endif +#ifndef MLD6_LISTENER_DONE +# define MLD6_LISTENER_DONE 132 +#endif +#ifndef ND_ROUTER_SOLICIT +# define ND_ROUTER_SOLICIT 133 +#endif +#ifndef ND_ROUTER_ADVERT +# define ND_ROUTER_ADVERT 134 +#endif +#ifndef ND_NEIGHBOR_SOLICIT +# define ND_NEIGHBOR_SOLICIT 135 +#endif +#ifndef ND_NEIGHBOR_ADVERT +# define ND_NEIGHBOR_ADVERT 136 +#endif +#ifndef ND_REDIRECT +# define ND_REDIRECT 137 +#endif +#ifndef ICMP6_ROUTER_RENUMBERING +# define ICMP6_ROUTER_RENUMBERING 138 +#endif +#ifndef ICMP6_WRUREQUEST +# define ICMP6_WRUREQUEST 139 +#endif +#ifndef ICMP6_WRUREPLY +# define ICMP6_WRUREPLY 140 +#endif +#ifndef ICMP6_FQDN_QUERY +# define ICMP6_FQDN_QUERY 139 +#endif +#ifndef ICMP6_FQDN_REPLY +# define ICMP6_FQDN_REPLY 140 +#endif +#ifndef ICMP6_NI_QUERY +# define ICMP6_NI_QUERY 139 +#endif +#ifndef ICMP6_NI_REPLY +# define ICMP6_NI_REPLY 140 +#endif +#ifndef MLD6_MTRACE_RESP +# define MLD6_MTRACE_RESP 200 +#endif +#ifndef MLD6_MTRACE +# define MLD6_MTRACE 201 +#endif +#ifndef ICMP6_HADISCOV_REQUEST +# define ICMP6_HADISCOV_REQUEST 202 +#endif +#ifndef ICMP6_HADISCOV_REPLY +# define ICMP6_HADISCOV_REPLY 203 +#endif +#ifndef ICMP6_MOBILEPREFIX_SOLICIT +# define ICMP6_MOBILEPREFIX_SOLICIT 204 +#endif +#ifndef ICMP6_MOBILEPREFIX_ADVERT +# define ICMP6_MOBILEPREFIX_ADVERT 205 +#endif +#ifndef ICMP6_MAXTYPE +# define ICMP6_MAXTYPE 205 +#endif + +#ifndef ICMP6_DST_UNREACH_NOROUTE +# define ICMP6_DST_UNREACH_NOROUTE 0 +#endif +#ifndef ICMP6_DST_UNREACH_ADMIN +# define ICMP6_DST_UNREACH_ADMIN 1 +#endif +#ifndef ICMP6_DST_UNREACH_NOTNEIGHBOR +# define ICMP6_DST_UNREACH_NOTNEIGHBOR 2 +#endif +#ifndef ICMP6_DST_UNREACH_BEYONDSCOPE +# define ICMP6_DST_UNREACH_BEYONDSCOPE 2 +#endif +#ifndef ICMP6_DST_UNREACH_ADDR +# define ICMP6_DST_UNREACH_ADDR 3 +#endif +#ifndef ICMP6_DST_UNREACH_NOPORT +# define ICMP6_DST_UNREACH_NOPORT 4 +#endif +#ifndef ICMP6_TIME_EXCEED_TRANSIT +# define ICMP6_TIME_EXCEED_TRANSIT 0 +#endif +#ifndef ICMP6_TIME_EXCEED_REASSEMBLY +# define ICMP6_TIME_EXCEED_REASSEMBLY 1 +#endif + +#ifndef ICMP6_NI_SUCCESS +# define ICMP6_NI_SUCCESS 0 +#endif +#ifndef ICMP6_NI_REFUSED +# define ICMP6_NI_REFUSED 1 +#endif +#ifndef ICMP6_NI_UNKNOWN +# define ICMP6_NI_UNKNOWN 2 +#endif + +#ifndef ICMP6_ROUTER_RENUMBERING_COMMAND +# define ICMP6_ROUTER_RENUMBERING_COMMAND 0 +#endif +#ifndef ICMP6_ROUTER_RENUMBERING_RESULT +# define ICMP6_ROUTER_RENUMBERING_RESULT 1 +#endif +#ifndef ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET +# define ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET 255 +#endif + +#ifndef ICMP6_PARAMPROB_HEADER +# define ICMP6_PARAMPROB_HEADER 0 +#endif +#ifndef ICMP6_PARAMPROB_NEXTHEADER +# define ICMP6_PARAMPROB_NEXTHEADER 1 +#endif +#ifndef ICMP6_PARAMPROB_OPTION +# define ICMP6_PARAMPROB_OPTION 2 +#endif + +#ifndef ICMP6_NI_SUBJ_IPV6 +# define ICMP6_NI_SUBJ_IPV6 0 +#endif +#ifndef ICMP6_NI_SUBJ_FQDN +# define ICMP6_NI_SUBJ_FQDN 1 +#endif +#ifndef ICMP6_NI_SUBJ_IPV4 +# define ICMP6_NI_SUBJ_IPV4 2 +#endif + /* * ECN is a new addition to TCP - RFC 2481 */ diff --git a/sys/contrib/ipfilter/netinet/ip_fil.c b/sys/contrib/ipfilter/netinet/ip_fil.c index 5e5bfce2c96a..643592c7b336 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil.c +++ b/sys/contrib/ipfilter/netinet/ip_fil.c @@ -17,7 +17,7 @@ #endif #include #if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \ - defined(_KERNEL) + defined(_KERNEL) && !defined(_LKM) # include "opt_ipfilter_log.h" #endif #if defined(__FreeBSD__) && !defined(__FreeBSD_version) @@ -25,6 +25,9 @@ # include # endif #endif +#ifdef __sgi +# include +#endif #ifndef _KERNEL # include # include @@ -45,7 +48,6 @@ #ifdef _KERNEL # include #endif -#include #if !SOLARIS # if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000) # include @@ -94,12 +96,16 @@ #include "netinet/ip_compat.h" #ifdef USE_INET6 # include +# if !SOLARIS +# include +# include +# endif #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_proxy.h" #include "netinet/ip_auth.h" #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) # include @@ -147,15 +153,18 @@ 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 *)); +static int send_ip __P((ip_t *, fr_info_t *, struct mbuf **)); +# ifdef USE_INET6 +static int ipfr_fastroute6 __P((struct mbuf *, struct mbuf **, + fr_info_t *, frdest_t *)); +# endif # 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 +# if defined(__sgi) && (IRIX < 605) static int no_output __P((struct ifnet *, struct mbuf *, struct sockaddr *)); static int write_output __P((struct ifnet *, struct mbuf *, @@ -212,6 +221,77 @@ int (*fr_checkp) __P((ip_t *ip, int hlen, void *ifp, int out, mb_t **mp)); # endif /* NETBSD_PF */ #endif /* __NetBSD__ */ + +#if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000) && \ + defined(_KERNEL) +# include + +static int fr_check_wrapper(void *, struct mbuf **, struct ifnet *, int ); + +static int fr_check_wrapper(arg, mp, ifp, dir) +void *arg; +struct mbuf **mp; +struct ifnet *ifp; +int dir; +{ + struct ip *ip = mtod(*mp, struct ip *); + int rv, hlen = ip->ip_hl << 2; + +#if defined(M_CSUM_TCPv4) + /* + * If the packet is out-bound, we can't delay checksums + * here. For in-bound, the checksum has already been + * validated. + */ + if (dir == PFIL_OUT) { + if ((*mp)->m_pkthdr.csum_flags & (M_CSUM_TCPv4|M_CSUM_UDPv4)) { + in_delayed_cksum(*mp); + (*mp)->m_pkthdr.csum_flags &= + ~(M_CSUM_TCPv4|M_CSUM_UDPv4); + } + } +#endif /* M_CSUM_TCPv4 */ + + /* + * We get the packet with all fields in network byte + * order. We expect ip_len and ip_off to be in host + * order. We frob them, call the filter, then frob + * them back. + * + * Note, we don't need to update the checksum, because + * it has already been verified. + */ + NTOHS(ip->ip_len); + NTOHS(ip->ip_off); + + rv = fr_check(ip, hlen, ifp, (dir == PFIL_OUT), mp); + + if (rv == 0 && *mp != NULL) { + ip = mtod(*mp, struct ip *); + HTONS(ip->ip_len); + HTONS(ip->ip_off); + } + + return (rv); +} + +# ifdef USE_INET6 +# include + +static int fr_check_wrapper6(void *, struct mbuf **, struct ifnet *, int ); + +static int fr_check_wrapper6(arg, mp, ifp, dir) +void *arg; +struct mbuf **mp; +struct ifnet *ifp; +int dir; +{ + + return (fr_check(mtod(*mp, struct ip *), sizeof(struct ip6_hdr), + ifp, (dir == PFIL_OUT), mp)); +} +# endif +#endif /* __NetBSD_Version >= 105110000 && _KERNEL */ #ifdef _KERNEL # if defined(IPFILTER_LKM) && !defined(__sgi) int iplidentify(s) @@ -232,13 +312,20 @@ void ipfilterattach(count) int count; { - if (iplattach() != 0) - printf("IP Filter failed to attach\n"); + + /* + * Do nothing here, really. The filter will be enabled + * by the SIOCFRENB ioctl. + */ } # endif +# if defined(__NetBSD__) +int ipl_enable() +# else int iplattach() +# endif { char *defpass; int s; @@ -246,6 +333,12 @@ int iplattach() ((__NetBSD_Version__ >= 104200000) || (__FreeBSD_version >= 500011))) int error = 0; # endif +#if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000) + struct pfil_head *ph_inet; +# ifdef USE_INET6 + struct pfil_head *ph_inet6; +# endif +#endif SPL_NET(s); if (fr_running || (fr_checkp == fr_check)) { @@ -272,8 +365,24 @@ int iplattach() # ifdef NETBSD_PF # if (__NetBSD_Version__ >= 104200000) || (__FreeBSD_version >= 500011) +# if __NetBSD_Version__ >= 105110000 + if ( + !(ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET)) +# ifdef USE_INET6 + && !(ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6)) +# endif + ) + return ENODEV; + + if (ph_inet != NULL) + error = pfil_add_hook((void *)fr_check_wrapper, NULL, + PFIL_IN|PFIL_OUT, ph_inet); + else + error = 0; +# else error = pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT, &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); +# endif if (error) { # ifdef USE_INET6 goto pfil_error; @@ -289,11 +398,22 @@ int iplattach() pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT); # endif # ifdef USE_INET6 +# if __NetBSD_Version__ >= 105110000 + if (ph_inet6 != NULL) + error = pfil_add_hook((void *)fr_check_wrapper6, NULL, + PFIL_IN|PFIL_OUT, ph_inet6); + else + error = 0; + if (error) { + pfil_remove_hook((void *)fr_check_wrapper6, NULL, + PFIL_IN|PFIL_OUT, ph_inet6); +# else error = pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT, - &inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh); + &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh); if (error) { pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT, &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); +# endif pfil_error: SPL_X(s); appr_unload(); @@ -360,12 +480,22 @@ pfil_error: * Disable the filter by removing the hooks from the IP input/output * stream. */ +# if defined(__NetBSD__) +int ipl_disable() +# else int ipldetach() +# endif { int s, i = FR_INQUE|FR_OUTQUE; #if defined(NETBSD_PF) && \ ((__NetBSD_Version__ >= 104200000) || (__FreeBSD_version >= 500011)) int error = 0; +# if __NetBSD_Version__ >= 105150000 + struct pfil_head *ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); +# ifdef USE_INET6 + struct pfil_head *ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); +# endif +# endif #endif #ifdef _KERNEL @@ -403,8 +533,16 @@ int ipldetach() # ifdef NETBSD_PF # if ((__NetBSD_Version__ >= 104200000) || (__FreeBSD_version >= 500011)) +# if __NetBSD_Version__ >= 105110000 + if (ph_inet != NULL) + error = pfil_remove_hook((void *)fr_check_wrapper, NULL, + PFIL_IN|PFIL_OUT, ph_inet); + else + error = 0; +# else error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT, &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); +# endif if (error) { SPL_X(s); return error; @@ -413,8 +551,16 @@ int ipldetach() pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT); # endif # ifdef USE_INET6 +# if __NetBSD_Version__ >= 105110000 + if (ph_inet6 != NULL) + error = pfil_remove_hook((void *)fr_check_wrapper6, NULL, + PFIL_IN|PFIL_OUT, ph_inet6); + else + error = 0; +# else error = pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT, - &inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh); + &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh); +# endif if (error) { SPL_X(s); return error; @@ -536,7 +682,7 @@ int mode; sizeof(iplused[IPL_LOGIPF])); #endif break; -#if !defined(IPFILTER_LKM) && defined(_KERNEL) +#if (!defined(IPFILTER_LKM) || defined(__NetBSD__)) && defined(_KERNEL) case SIOCFRENB : { u_int enable; @@ -548,9 +694,17 @@ int mode; if (error) break; if (enable) +# if defined(__NetBSD__) + error = ipl_enable(); +# else error = iplattach(); +# endif else +# if defined(__NetBSD__) + error = ipl_disable(); +# else error = ipldetach(); +# endif } break; } @@ -717,11 +871,11 @@ caddr_t data; { register frentry_t *fp, *f, **fprev; register frentry_t **ftail; - frentry_t frd; - frdest_t *fdp; frgroup_t *fg = NULL; + int error = 0, in, i; u_int *p, *pp; - int error = 0, in; + frentry_t frd; + frdest_t *fdp; u_int group; fp = &frd; @@ -770,18 +924,17 @@ caddr_t data; 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; + for (i = 0; i < 4; i++) { + if ((fp->fr_ifnames[i][1] == '\0') && + ((fp->fr_ifnames[i][0] == '-') || + (fp->fr_ifnames[i][0] == '*'))) { + fp->fr_ifas[i] = NULL; + } else if (*fp->fr_ifnames[i]) { + fp->fr_ifas[i] = GETUNIT(fp->fr_ifnames[i], fp->fr_v); + if (!fp->fr_ifas[i]) + fp->fr_ifas[i] = (void *)-1; + } } -#endif fdp = &fp->fr_dif; fp->fr_flags &= ~FR_DUP; @@ -860,6 +1013,7 @@ caddr_t data; fixskip(fprev, f, -1); *ftail = f->fr_next; f->fr_next = NULL; + f->fr_ref--; if (f->fr_ref == 0) KFREE(f); } @@ -1008,7 +1162,7 @@ fr_info_t *fin; if (m == NULL) return -1; - tlen = oip->ip_len - fin->fin_hlen - (tcp->th_off << 2) + + tlen = fin->fin_dlen - (tcp->th_off << 2) + ((tcp->th_flags & TH_SYN) ? 1 : 0) + ((tcp->th_flags & TH_FIN) ? 1 : 0); @@ -1050,7 +1204,7 @@ fr_info_t *fin; ip6->ip6_dst = oip6->ip6_src; tcp2->th_sum = in6_cksum(m, IPPROTO_TCP, sizeof(*ip6), sizeof(*tcp2)); - return send_ip(oip, fin, m); + return send_ip(oip, fin, &m); } # endif ip->ip_p = IPPROTO_TCP; @@ -1059,17 +1213,25 @@ fr_info_t *fin; 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); + return send_ip(oip, fin, &m); } -static int send_ip(oip, fin, m) +/* + * Send an IP(v4/v6) datagram out into the network + */ +static int send_ip(oip, fin, mp) ip_t *oip; fr_info_t *fin; -struct mbuf *m; +struct mbuf **mp; { + struct mbuf *m = *mp; + char *dpsave; + int error; ip_t *ip; + dpsave = fin->fin_dp; + ip = mtod(m, ip_t *); ip->ip_v = fin->fin_v; @@ -1085,20 +1247,22 @@ struct mbuf *m; ip->ip_ttl = ip_defttl; # endif ip->ip_sum = 0; + fin->fin_dp = (char *)(ip + 1); } # 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); + fin->fin_dp = (char *)(ip6 + 1); } # endif # ifdef IPSEC m->m_pkthdr.rcvif = NULL; # endif - return ipfr_fastroute(m, fin->fin_mp, fin, NULL); + error = ipfr_fastroute(m, mp, fin, NULL); + fin->fin_dp = dpsave; + return error; } @@ -1272,7 +1436,7 @@ int dst; shlen = fin->fin_hlen; fin->fin_hlen = hlen; - err = send_ip(oip, fin, m); + err = send_ip(oip, fin, &m); fin->fin_hlen = shlen; #ifdef USE_INET6 if (fin->fin_v == 4) @@ -1285,7 +1449,8 @@ int dst; } -# if !defined(IPFILTER_LKM) && (__FreeBSD_version < 300000) && !defined(__sgi) +# if !defined(IPFILTER_LKM) && !defined(__sgi) && \ + (!defined(__FreeBSD_version) || (__FreeBSD_version < 300000)) # if (BSD < 199306) int iplinit __P((void)); @@ -1297,21 +1462,35 @@ void # endif iplinit() { + +# if defined(__NetBSD__) + if (ipl_enable() != 0) +# else if (iplattach() != 0) +# endif + { printf("IP Filter failed to attach\n"); + } ip_init(); } # endif /* ! __NetBSD__ */ +/* + * Return the length of the entire mbuf. + */ size_t mbufchainlen(m0) register struct mbuf *m0; { +#if BSD >= 199306 + return m0->m_pkthdr.len; +#else register size_t len = 0; for (; m0; m0 = m0->m_next) len += m0->m_len; return len; +#endif } @@ -1329,6 +1508,24 @@ frdest_t *fdp; struct route iproute; frentry_t *fr; + ip = NULL; + ro = NULL; + ifp = NULL; + ro = &iproute; + ro->ro_rt = NULL; + +#ifdef USE_INET6 + if (fin->fin_v == 6) { + error = ipfr_fastroute6(m0, mpp, fin, fdp); + if (error != 0) + goto bad; + goto done; + } +#else + if (fin->fin_v == 6) + goto bad; +#endif + #ifdef M_WRITABLE /* * HOT FIX/KLUDGE: @@ -1342,13 +1539,14 @@ frdest_t *fdp; * problem. */ if (M_WRITABLE(m) == 0) { - if ((m0 = m_dup(m, M_DONTWAIT)) != 0) { - m_freem(m); + if ((m0 = m_dup(m, M_DONTWAIT)) != NULL) { + m_freem(*mpp); + *mpp = m0; m = m0; } else { error = ENOBUFS; - m_freem(m); - ipl_frouteok[1]++; + m_freem(*mpp); + goto done; } } #endif @@ -1360,35 +1558,26 @@ frdest_t *fdp; /* * Clear any in-bound checksum flags for this packet. */ +# if (__NetBSD_Version__ > 105009999) + m0->m_pkthdr.csum_flags = 0; +# else m0->m_pkthdr.csuminfo = 0; +# endif #endif /* __NetBSD__ && M_CSUM_IPv4 */ -#ifdef USE_INET6 - if (ip->ip_v == 6) { - /* - * currently "to " and "to :ip#" are not supported - * for IPv6 - */ - error = ip6_output(m0, NULL, NULL, 0, NULL, NULL); - *mpp = NULL; - return error; - } -#endif /* * Route packet. */ - ro = &iproute; bzero((caddr_t)ro, sizeof (*ro)); dst = (struct sockaddr_in *)&ro->ro_dst; dst->sin_family = AF_INET; + dst->sin_addr = ip->ip_dst; fr = fin->fin_fr; - if (fdp) + if (fdp != NULL) ifp = fdp->fd_ifp; - else { + else ifp = fin->fin_ifp; - dst->sin_addr = ip->ip_dst; - } /* * In case we're here due to "to " being used with "keep state", @@ -1397,13 +1586,9 @@ frdest_t *fdp; if ((fr != NULL) && (fin->fin_rev != 0)) { if ((ifp != NULL) && (fdp == &fr->fr_tif)) return 0; - dst->sin_addr = ip->ip_dst; - } else if (fdp) { - if (fdp->fd_ip.s_addr) { + } else if (fdp != NULL) { + if (fdp->fd_ip.s_addr != 0) dst->sin_addr = fdp->fd_ip; - ip->ip_dst = fdp->fd_ip; - } else - dst->sin_addr = ip->ip_dst; } # if BSD >= 199306 @@ -1424,26 +1609,36 @@ frdest_t *fdp; 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++; + + if ((ifp == NULL) && (ro->ro_rt != NULL)) + ifp = ro->ro_rt->rt_ifp; + + if ((ro->ro_rt == NULL) || (ifp == NULL)) { + if (in_localaddr(ip->ip_dst)) + error = EHOSTUNREACH; + else + error = ENETUNREACH; + goto bad; + } + + if (ro->ro_rt->rt_flags & RTF_GATEWAY) { +#if BSD >= 199306 + dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway; +#else + dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway; +#endif + } + 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) { + sifp = fin->fin_ifp; + fin->fin_ifp = ifp; fin->fin_out = 1; if ((fin->fin_fr = ipacct[1][fr_active]) && (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) { @@ -1453,46 +1648,39 @@ frdest_t *fdp; if (!fr || !(fr->fr_flags & FR_RETMASK)) (void) fr_checkstate(ip, fin); (void) ip_natout(ip, fin); + fin->fin_ifp = sifp; } else ip->ip_sum = 0; /* * If small enough for interface, can just send directly. */ if (ip->ip_len <= ifp->if_mtu) { -# if defined(MCLISREFERENCED) && !defined(sparc) - int i = 0; - - if ((m->m_flags & M_EXT) && MCLISREFERENCED(m)) - i = 1; -# endif # ifndef sparc -# if !(_BSDI_VERSION >= 199510) +# if (!defined(__FreeBSD__) && !(_BSDI_VERSION >= 199510)) ip->ip_id = htons(ip->ip_id); # endif ip->ip_len = htons(ip->ip_len); ip->ip_off = htons(ip->ip_off); # endif # if defined(__NetBSD__) && defined(M_CSUM_IPv4) +# if (__NetBSD_Version__ > 105009999) + if (ifp->if_csum_flags_tx & IFCAP_CSUM_IPv4) + m->m_pkthdr.csum_flags |= M_CSUM_IPv4; + else if (ip->ip_sum == 0) + ip->ip_sum = in_cksum(m, hlen); +# else if (ifp->if_capabilities & IFCAP_CSUM_IPv4) m->m_pkthdr.csuminfo |= M_CSUM_IPv4; else if (ip->ip_sum == 0) ip->ip_sum = in_cksum(m, hlen); +# endif # else if (!ip->ip_sum) ip->ip_sum = in_cksum(m, hlen); # endif /* __NetBSD__ && M_CSUM_IPv4 */ -# if BSD >= 199306 +# if (BSD >= 199306) || (defined(IRIX) && (IRIX >= 605)) error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, ro->ro_rt); -# if defined(MCLISREFERENCED) && !defined(sparc) - if (i) { -# ifndef __FreeBSD__ - ip->ip_id = ntohs(ip->ip_id); -# endif - ip->ip_len = ntohs(ip->ip_len); - ip->ip_off = ntohs(ip->ip_off); - } -# endif # else error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst); # endif @@ -1562,9 +1750,7 @@ frdest_t *fdp; m->m_pkthdr.len = mhlen + len; m->m_pkthdr.rcvif = NULL; # endif -# ifndef sparc mhip->ip_off = htons((u_short)mhip->ip_off); -# endif mhip->ip_sum = 0; mhip->ip_sum = in_cksum(m, mhlen); *mnext = m; @@ -1584,7 +1770,7 @@ sendorfree: m0 = m->m_act; m->m_act = 0; if (error == 0) -# if BSD >= 199306 +# if (BSD >= 199306) || (defined(IRIX) && (IRIX >= 605)) error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, ro->ro_rt); # else @@ -1601,13 +1787,13 @@ done: else ipl_frouteok[1]++; - if (ro->ro_rt) { + if (ro->ro_rt != NULL) { RTFREE(ro->ro_rt); } *mpp = NULL; return error; bad: - if (error == EMSGSIZE) { + if ((error == EMSGSIZE) && (fin->fin_v == 4)) { sifp = fin->fin_ifp; code = fin->fin_icode; fin->fin_icode = ICMP_UNREACH_NEEDFRAG; @@ -1621,6 +1807,10 @@ bad: } +/* + * Return true or false depending on whether the route to the + * given IP address uses the same interface as the one passed. + */ int fr_verifysrc(ipa, ifp) struct in_addr ipa; void *ifp; @@ -1630,6 +1820,9 @@ void *ifp; bzero((char *)&iproute, sizeof(iproute)); dst = (struct sockaddr_in *)&iproute.ro_dst; +# if (BSD >= 199306) + dst->sin_len = sizeof(*dst); +# endif dst->sin_family = AF_INET; dst->sin_addr = ipa; # if (BSD >= 199306) && !defined(__NetBSD__) && !defined(__bsdi__) && \ @@ -1659,10 +1852,78 @@ struct ifnet *ifp; return workbuf; } # endif + + +# if defined(USE_INET6) +/* + * This is the IPv6 specific fastroute code. It doesn't clean up the mbuf's + * or ensure that it is an IPv6 packet that is being forwarded, those are + * expected to be done by the called (ipfr_fastroute). + */ +static int ipfr_fastroute6(m0, mpp, fin, fdp) +struct mbuf *m0, **mpp; +fr_info_t *fin; +frdest_t *fdp; +{ + struct route_in6 ip6route; + struct sockaddr_in6 *dst6; + struct route_in6 *ro; + struct ifnet *ifp; + frentry_t *fr; + int error; + + ifp = NULL; + ro = &ip6route; + fr = fin->fin_fr; + bzero((caddr_t)ro, sizeof(*ro)); + dst6 = (struct sockaddr_in6 *)&ro->ro_dst; + dst6->sin6_family = AF_INET6; + dst6->sin6_len = sizeof(struct sockaddr_in6); + dst6->sin6_addr = fin->fin_fi.fi_src.in6; + + if (fdp != NULL) + ifp = fdp->fd_ifp; + + if ((fr != NULL) && (fin->fin_rev != 0)) { + if ((ifp != NULL) && (fdp == &fr->fr_tif)) + return 0; + } else if (fdp != NULL) { + if (IP6_NOTZERO(&fdp->fd_ip6)) + dst6->sin6_addr = fdp->fd_ip6.in6; + } + if ((ifp == NULL) && ((fr == NULL) || !(fr->fr_flags & FR_FASTROUTE))) + return -2; + + rtalloc((struct route *)ro); + + if ((ifp == NULL) && (ro->ro_rt != NULL)) + ifp = ro->ro_rt->rt_ifp; + + if ((ro->ro_rt == NULL) || (ifp == NULL) || + (ifp != ro->ro_rt->rt_ifp)) { + error = EHOSTUNREACH; + } else { + if (ro->ro_rt->rt_flags & RTF_GATEWAY) + dst6 = (struct sockaddr_in6 *)ro->ro_rt->rt_gateway; + ro->ro_rt->rt_use++; + + if (m0->m_pkthdr.len <= nd_ifinfo[ifp->if_index].linkmtu) + error = nd6_output(ifp, fin->fin_ifp, m0, dst6, + ro->ro_rt); + else + error = EMSGSIZE; + } + + if (ro->ro_rt != NULL) { + RTFREE(ro->ro_rt); + } + return error; +} +# endif #else /* #ifdef _KERNEL */ -# ifdef __sgi +# if defined(__sgi) && (IRIX < 605) static int no_output __P((struct ifnet *ifp, struct mbuf *m, struct sockaddr *s)) # else @@ -1675,7 +1936,7 @@ static int no_output __P((struct ifnet *ifp, struct mbuf *m, # ifdef __STDC__ -# ifdef __sgi +# if defined(__sgi) && (IRIX < 605) static int write_output __P((struct ifnet *ifp, struct mbuf *m, struct sockaddr *s)) # else @@ -1710,26 +1971,39 @@ ip_t *ip; } -struct ifnet *get_unit(name, v) -char *name; +char *get_ifname(ifp) +struct ifnet *ifp; +{ +# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ + (defined(OpenBSD) && (OpenBSD >= 199603)) + return ifp->if_xname; +# else + static char fullifname[LIFNAMSIZ]; + + sprintf(fullifname, "%s%d", ifp->if_name, ifp->if_unit); + return fullifname; +# endif +} + + +struct ifnet *get_unit(ifname, v) +char *ifname; int v; { struct ifnet *ifp, **ifa, **old_ifneta; -# 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; - } +# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ + (defined(OpenBSD) && (OpenBSD >= 199603)) + if (!strncmp(ifname, ifp->if_xname, sizeof(ifp->if_xname))) # else - char ifname[32], *s; + char fullname[LIFNAMSIZ]; - for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) { - (void) sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit); - if (!strcmp(name, ifname)) + sprintf(fullname, "%s%d", ifp->if_name, ifp->if_unit); + if (!strcmp(ifname, fullname)) +# endif return ifp; } -# endif if (!ifneta) { ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2); @@ -1762,20 +2036,19 @@ int v; ifp = ifneta[nifs - 1]; # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603)) - strncpy(ifp->if_xname, name, sizeof(ifp->if_xname)); + (defined(OpenBSD) && (OpenBSD >= 199603)) + strncpy(ifp->if_xname, ifname, 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_name = strdup(ifname); + + ifname = ifp->if_name; + while (*ifname && !isdigit(*ifname)) + ifname++; + if (*ifname && isdigit(*ifname)) { + ifp->if_unit = atoi(ifname); + *ifname = '\0'; + } else ifp->if_unit = -1; - } # endif ifp->if_output = no_output; return ifp; @@ -1815,27 +2088,22 @@ void init_ifp() } -int ipllog __P((void)) -{ - verbose("l"); - return 0; -} - - -int send_reset(ip, ifp) +int send_reset(ip, fin) ip_t *ip; -struct ifnet *ifp; +fr_info_t *fin; { verbose("- TCP RST sent\n"); return 0; } -int icmp_error(ip, ifp) +int send_icmp_err(ip, code, fin, dst) ip_t *ip; -struct ifnet *ifp; +int code; +fr_info_t *fin; +int dst; { - verbose("- TCP RST sent\n"); + verbose("- ICMP UNREACHABLE RST sent\n"); return 0; } @@ -1844,4 +2112,52 @@ void frsync() { return; } + +void m_copydata(m, off, len, cp) +mb_t *m; +int off, len; +caddr_t cp; +{ + bcopy((char *)m + off, cp, len); +} + + +int ipfuiomove(buf, len, rwflag, uio) +caddr_t buf; +int len, rwflag; +struct uio *uio; +{ + int left, ioc, num, offset; + struct iovec *io; + char *start; + + if (rwflag == UIO_READ) { + left = len; + ioc = 0; + + offset = uio->uio_offset; + + while ((left > 0) && (ioc < uio->uio_iovcnt)) { + io = uio->uio_iov + ioc; + num = io->iov_len; + if (num > left) + num = left; + start = io->iov_base + offset; + if (start > io->iov_base + io->iov_len) { + offset -= io->iov_len; + ioc++; + continue; + } + bcopy(buf, start, num); + uio->uio_resid -= num; + uio->uio_offset += num; + left -= num; + if (left > 0) + ioc++; + } + if (left > 0) + return EFAULT; + } + return 0; +} #endif /* _KERNEL */ diff --git a/sys/contrib/ipfilter/netinet/ip_fil.h b/sys/contrib/ipfilter/netinet/ip_fil.h index 2934f7d19c96..b63769a4a2f0 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil.h +++ b/sys/contrib/ipfilter/netinet/ip_fil.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 1993-2002 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * @@ -35,6 +35,10 @@ # endif #endif +#ifndef offsetof +# define offsetof(t,m) (int)((&((t *)0L)->m)) +#endif + #if defined(__STDC__) || defined(__GNUC__) # define SIOCADAFR _IOW('r', 60, struct frentry *) # define SIOCRMAFR _IOW('r', 61, struct frentry *) @@ -52,8 +56,8 @@ # 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 SIOCAUTHW _IOWR('r', 76, struct frauth_t *) +# define SIOCAUTHR _IOWR('r', 77, struct frauth_t *) # define SIOCATHST _IOWR('r', 78, struct fr_authstat *) # define SIOCSTLCK _IOWR('r', 79, u_int) # define SIOCSTPUT _IOWR('r', 80, struct ipstate_save *) @@ -77,8 +81,8 @@ # 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 SIOCAUTHW _IOWR(r, 76, struct frauth_t *) +# define SIOCAUTHR _IOWR(r, 77, struct frauth_t *) # define SIOCATHST _IOWR(r, 78, struct fr_authstat *) # define SIOCSTLCK _IOWR(r, 79, u_int) # define SIOCSTPUT _IOWR(r, 80, struct ipstate_save *) @@ -124,7 +128,9 @@ typedef struct fr_ip { #define FI_W_SADDR 0x00000400 #define FI_W_DADDR 0x00000800 #define FI_WILDA (FI_W_SADDR|FI_W_DADDR) -#define FI_NEWFR 0x00001000 +#define FI_NEWFR 0x00001000 /* Create a filter rule */ +#define FI_IGNOREPKT 0x00002000 /* Do not treat as a real packet */ +#define FI_NORULE 0x00004000 /* Not direct a result of a rule */ typedef struct fr_info { void *fin_ifp; /* interface packet is `on' */ @@ -136,10 +142,12 @@ typedef struct fr_info { 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_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_plen; + u_short fin_off; 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 */ @@ -147,19 +155,21 @@ typedef struct fr_info { 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 +#define fin_p fin_fi.fi_p #define fin_saddr fin_fi.fi_saddr +#define fin_src fin_fi.fi_src.in4 #define fin_daddr fin_fi.fi_daddr +#define fin_dst fin_fi.fi_dst.in4 #define fin_fl fin_fi.fi_fl /* * Size for compares on fr_info structures */ #define FI_CSIZE offsetof(fr_info_t, fin_icode) +#define FI_LCSIZE offsetof(fr_info_t, fin_dp) /* * Size for copying cache fr_info structure @@ -168,13 +178,16 @@ typedef struct fr_info { typedef struct frdest { void *fd_ifp; - struct in_addr fd_ip; - char fd_ifname[IFNAMSIZ]; + union i6addr fd_ip6; + char fd_ifname[LIFNAMSIZ]; #if SOLARIS mb_t *fd_mp; /* cache resolver for to/dup-to */ #endif } frdest_t; +#define fd_ip fd_ip6.in4 + + typedef struct frpcmp { int frp_cmp; /* data for port comparisons */ u_short frp_port; /* top port for <> and >< */ @@ -199,10 +212,7 @@ typedef struct frentry { struct frentry *fr_next; struct frentry *fr_grp; int fr_ref; /* reference count - for grouping */ - void *fr_ifa; -#if BSD >= 199306 - void *fr_oifa; -#endif + void *fr_ifas[4]; /* * These are only incremented when a packet matches this rule and * it is the last match @@ -219,6 +229,7 @@ typedef struct frentry { u_short fr_icmpm; /* data for ICMP packets (mask) */ u_short fr_icmp; + u_int fr_age[2]; /* aging for state */ frtuc_t fr_tuc; u_32_t fr_group; /* group to which this rule belongs */ u_32_t fr_grhead; /* group # which this rule starts */ @@ -228,10 +239,7 @@ typedef struct frentry { 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 + char fr_ifnames[4][LIFNAMSIZ]; struct frdest fr_tif; /* "to" interface */ struct frdest fr_dif; /* duplicate packet interfaces */ u_int fr_cksum; /* checksum on filter rules for performance */ @@ -253,10 +261,11 @@ typedef struct frentry { #define fr_src fr_ip.fi_src.in4 #define fr_dmsk fr_mip.fi_dst.in4 #define fr_smsk fr_mip.fi_src.in4 +#define fr_ifname fr_ifnames[0] +#define fr_oifname fr_ifnames[2] +#define fr_ifa fr_ifas[0] +#define fr_oifa fr_ifas[2] -#ifndef offsetof -#define offsetof(t,m) (int)((&((t *)0L)->m)) -#endif #define FR_CMPSIZ (sizeof(struct frentry) - offsetof(frentry_t, fr_ip)) /* @@ -269,8 +278,8 @@ typedef struct frentry { #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_NOTSRCIP 0x00020 /* not the src IP# */ +#define FR_NOTDSTIP 0x00040 /* not the dst IP# */ #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 */ @@ -284,8 +293,8 @@ typedef struct frentry { #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_LOGBODY 0x80000 /* Log the body */ +#define FR_LOGFIRST 0x100000 /* Log the first byte if state held */ #define FR_AUTH 0x200000 /* use authentication */ #define FR_PREAUTH 0x400000 /* require preauthentication */ #define FR_DONTCACHE 0x800000 /* don't cache the result */ @@ -407,15 +416,16 @@ typedef struct iplog { struct iplog *ipl_next; } iplog_t; -#define IPL_MAGIC 0x49504c4d /* 'IPLM' */ +#define IPL_MAGIC 0x49504c4d /* 'IPLM' */ +#define IPLOG_SIZE sizeof(iplog_t) typedef struct ipflog { #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ (defined(OpenBSD) && (OpenBSD >= 199603)) - u_char fl_ifname[IFNAMSIZ]; + u_char fl_ifname[LIFNAMSIZ]; #else u_int fl_unit; - u_char fl_ifname[4]; + u_char fl_ifname[LIFNAMSIZ]; #endif u_char fl_plen; /* extra data after hlen */ u_char fl_hlen; /* length of IP headers saved */ @@ -423,7 +433,8 @@ typedef struct ipflog { u_32_t fl_rule; u_32_t fl_group; u_32_t fl_flags; - u_32_t fl_lflags; + u_char fl_dir; + u_char fl_pad[3]; } ipflog_t; @@ -487,11 +498,11 @@ typedef struct ipflog { #ifndef _KERNEL -struct ifnet; +extern char *get_ifname __P((struct ifnet *)); 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 send_reset __P((ip_t *, fr_info_t *)); +extern int send_icmp_err __P((ip_t *, int, fr_info_t *, int)); extern int ipf_log __P((void)); extern struct ifnet *get_unit __P((char *, int)); # if defined(__NetBSD__) || defined(__OpenBSD__) || \ @@ -509,11 +520,6 @@ extern void ipfilterattach __P((int)); 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 @@ -596,6 +602,12 @@ 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 void ipflog_init __P((void)); +extern int ipflog_clear __P((minor_t)); +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 ipflog_read __P((minor_t, struct uio *)); + 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)); diff --git a/sys/contrib/ipfilter/netinet/ip_frag.c b/sys/contrib/ipfilter/netinet/ip_frag.c index 622d0cc5816d..7b7c7e5d930a 100644 --- a/sys/contrib/ipfilter/netinet/ip_frag.c +++ b/sys/contrib/ipfilter/netinet/ip_frag.c @@ -7,6 +7,9 @@ # define _KERNEL #endif +#ifdef __sgi +# include +#endif #include #include #include @@ -23,7 +26,6 @@ #else # include #endif -#include #ifndef linux # include #endif @@ -63,7 +65,6 @@ #include "netinet/ip_compat.h" #include #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" @@ -494,7 +495,6 @@ void ipfr_unload() } -#ifdef _KERNEL void ipfr_fragexpire() { ipfr_t **fp, *fra; @@ -565,6 +565,7 @@ void ipfr_fragexpire() * Slowly expire held state for fragments. Timeouts are set * in expectation * of this being called twice per second. */ +#ifdef _KERNEL # if (BSD >= 199306) || SOLARIS || defined(__sgi) # if defined(SOLARIS2) && (SOLARIS2 < 7) void ipfr_slowtimer() @@ -574,6 +575,9 @@ void ipfr_slowtimer __P((void *ptr)) # else int ipfr_slowtimer() # endif +#else +void ipfr_slowtimer() +#endif { #if defined(_KERNEL) && SOLARIS extern int fr_running; @@ -583,7 +587,7 @@ int ipfr_slowtimer() #endif READ_ENTER(&ipf_solaris); -#ifdef __sgi +#if defined(__sgi) && defined(_KERNEL) ipfilter_sgi_intfsync(); #endif @@ -591,6 +595,7 @@ int ipfr_slowtimer() fr_timeoutstate(); ip_natexpire(); fr_authexpire(); +#if defined(_KERNEL) # if SOLARIS ipfr_timer_id = timeout(ipfr_slowtimer, NULL, drv_usectohz(500000)); RWLOCK_EXIT(&ipf_solaris); @@ -601,8 +606,8 @@ int ipfr_slowtimer() # if (__FreeBSD_version >= 300000) ipfr_slowtimer_ch = timeout(ipfr_slowtimer, NULL, hz/2); # else -# if defined(__OpenBSD_) - timeout_add(&ipfr_slowtimer_ch, hz/2, ipfr_slowtimer, NULL); +# if defined(__OpenBSD__) + timeout_add(&ipfr_slowtimer_ch, hz/2); # else timeout(ipfr_slowtimer, NULL, hz/2); # endif @@ -612,5 +617,5 @@ int ipfr_slowtimer() # endif /* FreeBSD */ # endif /* NetBSD */ # endif /* SOLARIS */ -} #endif /* defined(_KERNEL) */ +} diff --git a/sys/contrib/ipfilter/netinet/ip_frag.h b/sys/contrib/ipfilter/netinet/ip_frag.h index 0aa44c154348..63df64847aa8 100644 --- a/sys/contrib/ipfilter/netinet/ip_frag.h +++ b/sys/contrib/ipfilter/netinet/ip_frag.h @@ -57,14 +57,18 @@ 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) +#ifdef _KERNEL +# if (BSD >= 199306) || SOLARIS || defined(__sgi) +# if defined(SOLARIS2) && (SOLARIS2 < 7) extern void ipfr_slowtimer __P((void)); -# else +# else extern void ipfr_slowtimer __P((void *)); -# endif -#else +# endif +# else extern int ipfr_slowtimer __P((void)); -#endif /* (BSD >= 199306) || SOLARIS */ +# endif /* (BSD >= 199306) || SOLARIS */ +#else +extern void ipfr_slowtimer __P((void)); +#endif /* _KERNEL */ #endif /* __IP_FIL_H__ */ diff --git a/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c b/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c index d5eac9c70e62..ce673d92ca00 100644 --- a/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c +++ b/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c @@ -49,10 +49,12 @@ 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)); +int ippr_ftp_valid __P((int, char *, size_t)); +int ippr_ftp_server_valid __P((char *, size_t)); +int ippr_ftp_client_valid __P((char *, size_t)); u_short ippr_ftp_atoi __P((char **)); -static frentry_t natfr; +static frentry_t ftppxyfr; int ippr_ftp_pasvonly = 0; int ippr_ftp_insecure = 0; @@ -62,9 +64,9 @@ int ippr_ftp_insecure = 0; */ int ippr_ftp_init() { - bzero((char *)&natfr, sizeof(natfr)); - natfr.fr_ref = 1; - natfr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE; + bzero((char *)&ftppxyfr, sizeof(ftppxyfr)); + ftppxyfr.fr_ref = 1; + ftppxyfr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE; return 0; } @@ -105,9 +107,9 @@ 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; + u_short a5, a6, sp; size_t nlen, olen; fr_info_t fi; int inc, off; @@ -173,7 +175,7 @@ int dlen; a4 = a1 & 0xff; a1 >>= 24; olen = s - f->ftps_rptr; - /* DO NOT change this to sprintf! */ + /* DO NOT change this to snprintf! */ (void) sprintf(newbuf, "%s %u,%u,%u,%u,%u,%u\r\n", "PORT", a1, a2, a3, a4, a5, a6); @@ -241,46 +243,47 @@ int dlen; * Add skeleton NAT entry for connection which will come back the * other way. */ - sp = htons(a5 << 8 | a6); + sp = (a5 << 8 | a6); /* * Don't allow the PORT command to specify a port < 1024 due to * security crap. */ - if (ntohs(sp) < 1024) + if (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); + bcopy((char *)fin, (char *)&fi, sizeof(fi)); + fi.fin_data[0] = sp; + fi.fin_data[1] = fin->fin_data[1] - 1; + ipn = nat_outlookup(&fi, IPN_TCP, nat->nat_p, nat->nat_inip, + ip->ip_dst, 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_sport = htons(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; + fi.fin_fr = &ftppxyfr; fi.fin_out = 1; 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, + ipn = nat_new(&fi, ip, nat->nat_ptr, NULL, IPN_TCP|FI_W_DPORT, NAT_OUTBOUND); if (ipn != NULL) { ipn->nat_age = fr_defnatage; - (void) fr_addstate(ip, &fi, FI_W_DPORT); + (void) fr_addstate(ip, &fi, NULL, + FI_W_DPORT|FI_IGNOREPKT); } ip->ip_len = slen; ip->ip_src = swip; @@ -340,7 +343,8 @@ int dlen; !strncmp(cmd, "ADAT ", 5)) { ftp->ftp_passok = FTPXY_ADAT_1; ftp->ftp_incok = 1; - } else if ((ftp->ftp_passok == FTPXY_PAOK_2) && + } else if ((ftp->ftp_passok == FTPXY_PAOK_1 || + ftp->ftp_passok == FTPXY_PAOK_2) && !strncmp(cmd, "ACCT ", 5)) { ftp->ftp_passok = FTPXY_ACCT_1; ftp->ftp_incok = 1; @@ -368,8 +372,8 @@ 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; + u_short a5, a6, dp; fr_info_t fi; nat_t *ipn; int inc; @@ -501,26 +505,27 @@ int dlen; * Add skeleton NAT entry for connection which will come back the * other way. */ - sp = 0; + bcopy((char *)fin, (char *)&fi, sizeof(fi)); + fi.fin_data[0] = 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); + fi.fin_data[1] = ntohs(dp); + ipn = nat_outlookup(&fi, IPN_TCP, nat->nat_p, nat->nat_inip, + ip->ip_dst, 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[0] = a5 << 8 | a6; + fi.fin_data[1] = a5 << 8 | a6; fi.fin_dlen = sizeof(*tcp2); - tcp2->th_dport = htons(fi.fin_data[0]); - fi.fin_data[1] = 0; + tcp2->th_dport = htons(fi.fin_data[1]); + fi.fin_data[0] = 0; fi.fin_dp = (char *)tcp2; - fi.fin_fr = &natfr; + fi.fin_fr = &ftppxyfr; fi.fin_out = 1; swip = ip->ip_src; swip2 = ip->ip_dst; @@ -528,11 +533,12 @@ int dlen; 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, + ipn = nat_new(&fi, ip, nat->nat_ptr, NULL, IPN_TCP|FI_W_SPORT, NAT_OUTBOUND); if (ipn != NULL) { ipn->nat_age = fr_defnatage; - (void) fr_addstate(ip, &fi, FI_W_SPORT); + (void) fr_addstate(ip, &fi, NULL, + FI_W_SPORT|FI_IGNOREPKT); } ip->ip_len = slen; ip->ip_src = swip; @@ -601,7 +607,7 @@ int dlen; * 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) +int ippr_ftp_client_valid(buf, len) char *buf; size_t len; { @@ -614,36 +620,60 @@ size_t len; c = *s++; i--; - if (isdigit(c)) { + if (isalpha(c)) { c = *s++; i--; - if (isdigit(c)) { + if (isalpha(c)) { c = *s++; i--; - if (isdigit(c)) { + if (isalpha(c)) { c = *s++; i--; - if ((c != '-') && (c != ' ')) + 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 if (isalpha(c)) { + } else + return 1; + for (; i; i--) { + c = *s++; + if (c == '\n') + return 0; + } + return 2; +} + + +int ippr_ftp_server_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 (isalpha(c)) { + if (isdigit(c)) { c = *s++; i--; - if (isalpha(c)) { + if (isdigit(c)) { c = *s++; i--; - if (isalpha(c)) { - c = *s++; - i--; - if ((c != ' ') && (c != '\r')) - return 1; - } else if ((c != ' ') && (c != '\r')) + if ((c != '-') && (c != ' ')) return 1; } else return 1; @@ -660,6 +690,21 @@ size_t len; } +int ippr_ftp_valid(side, buf, len) +int side; +char *buf; +size_t len; +{ + int ret; + + if (side == 0) + ret = ippr_ftp_client_valid(buf, len); + else + ret = ippr_ftp_server_valid(buf, len); + return ret; +} + + int ippr_ftp_process(fin, ip, nat, ftp, rv) fr_info_t *fin; ip_t *ip; @@ -715,7 +760,7 @@ int rv; 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); + return APR_ERR(1); } f->ftps_len = mlen; @@ -732,11 +777,12 @@ int rv; wptr += len; f->ftps_wptr = wptr; if (f->ftps_junk == 2) - f->ftps_junk = ippr_ftp_valid(rptr, wptr - rptr); + f->ftps_junk = ippr_ftp_valid(rv, rptr, wptr - rptr); while ((f->ftps_junk == 0) && (wptr > rptr)) { - f->ftps_junk = ippr_ftp_valid(rptr, wptr - rptr); + f->ftps_junk = ippr_ftp_valid(rv, rptr, wptr - rptr); if (f->ftps_junk == 0) { + f->ftps_cmds++; len = wptr - rptr; f->ftps_rptr = rptr; if (rv) @@ -746,9 +792,17 @@ int rv; inc += ippr_ftp_client(fin, ip, nat, ftp, len); rptr = f->ftps_rptr; + wptr = f->ftps_wptr; } } + /* + * Off to a bad start so lets just forget about using the + * ftp proxy for this connection. + */ + if ((f->ftps_cmds == 0) && (f->ftps_junk == 1)) + return APR_ERR(2); + while ((f->ftps_junk == 1) && (rptr < wptr)) { while ((rptr < wptr) && (*rptr != '\r')) rptr++; diff --git a/sys/contrib/ipfilter/netinet/ip_log.c b/sys/contrib/ipfilter/netinet/ip_log.c index b3f1e5606242..189e68200714 100644 --- a/sys/contrib/ipfilter/netinet/ip_log.c +++ b/sys/contrib/ipfilter/netinet/ip_log.c @@ -58,7 +58,6 @@ # if defined(_KERNEL) # include # endif -# include # if !SOLARIS # if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000) # include @@ -69,13 +68,14 @@ # else # include # include -# include -# include -# include # include -# include -# include -# include +# ifdef _KERNEL +# include +# include +# include +# include +# include +# endif # endif # include # include @@ -110,11 +110,6 @@ # include "netinet/ip_compat.h" # include # 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 # endif @@ -122,6 +117,10 @@ # ifndef MIN # define MIN(a,b) (((a)<(b))?(a):(b)) # endif +# ifdef IPFILTER_LOGSIZE +# undef IPLLOGSIZE +# define IPLLOGSIZE IPFILTER_LOGSIZE +# endif # if SOLARIS || defined(__sgi) @@ -174,7 +173,7 @@ mb_t *m; void *ptrs[2]; int types[2]; u_char p; -# if SOLARIS +# if SOLARIS && defined(_KERNEL) ill_t *ifp = fin->fin_ifp; # else struct ifnet *ifp = fin->fin_ifp; @@ -221,9 +220,11 @@ mb_t *m; * Get the interface number and name to which this packet is * currently associated. */ -# if SOLARIS + bzero((char *)ipfl.fl_ifname, sizeof(ipfl.fl_ifname)); +# if SOLARIS && defined(_KERNEL) ipfl.fl_unit = (u_char)ifp->ill_ppa; - bcopy(ifp->ill_name, ipfl.fl_ifname, MIN(ifp->ill_name_length, 4)); + bcopy(ifp->ill_name, ipfl.fl_ifname, + MIN(ifp->ill_name_length, sizeof(ipfl.fl_ifname))); mlen = (flags & FR_LOGBODY) ? MIN(msgdsize(m) - hlen, 128) : 0; # else # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ @@ -231,10 +232,8 @@ mb_t *m; 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]; + strncpy(ipfl.fl_ifname, ifp->if_name, MIN(sizeof(ipfl.fl_ifname), + sizeof(ifp->if_name))); # endif mlen = (flags & FR_LOGBODY) ? MIN(fin->fin_plen - hlen, 128) : 0; # endif @@ -247,10 +246,11 @@ mb_t *m; else ipfl.fl_loglevel = 0xffff; ipfl.fl_flags = flags; + ipfl.fl_dir = fin->fin_out; ptrs[0] = (void *)&ipfl; sizes[0] = sizeof(ipfl); types[0] = 0; -# if SOLARIS +# if SOLARIS && defined(_KERNEL) /* * Are we copied from the mblk or an aligned array ? */ @@ -295,20 +295,20 @@ int *types, cnt; MUTEX_ENTER(&ipl_mutex); if (fin != NULL) { if ((ipll[dev] != NULL) && - bcmp((char *)fin, (char *)&iplcrc[dev], FI_CSIZE) == 0) { + bcmp((char *)fin, (char *)&iplcrc[dev], FI_LCSIZE) == 0) { ipll[dev]->ipl_count++; MUTEX_EXIT(&ipl_mutex); return 1; } - bcopy((char *)fin, (char *)&iplcrc[dev], FI_CSIZE); + bcopy((char *)fin, (char *)&iplcrc[dev], FI_LCSIZE); } else - bzero((char *)&iplcrc[dev], FI_CSIZE); + bzero((char *)&iplcrc[dev], FI_LCSIZE); MUTEX_EXIT(&ipl_mutex); /* * Get the total amount of data to be logged. */ - for (i = 0, len = sizeof(iplog_t); i < cnt; i++) + for (i = 0, len = IPLOG_SIZE; i < cnt; i++) len += itemsz[i]; /* @@ -336,23 +336,28 @@ int *types, cnt; ipl->ipl_count = 1; ipl->ipl_next = NULL; ipl->ipl_dsize = len; -# if SOLARIS || defined(sun) +# ifdef _KERNEL +# if SOLARIS || defined(sun) uniqtime((struct timeval *)&ipl->ipl_sec); -# else -# if BSD >= 199306 || defined(__FreeBSD__) || defined(__sgi) +# else +# if BSD >= 199306 || defined(__FreeBSD__) || defined(__sgi) microtime((struct timeval *)&ipl->ipl_sec); +# endif # endif +# else + ipl->ipl_sec = 0; + ipl->ipl_usec = 0; # 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++) { + for (i = 0, s = buf + IPLOG_SIZE; i < cnt; i++) { if (types[i] == 0) bcopy(items[i], s, itemsz[i]); else if (types[i] == 1) { -# if SOLARIS +# if SOLARIS && defined(_KERNEL) copyout_mblk(items[i], 0, itemsz[i], s); # else m_copydata(items[i], 0, itemsz[i], s); @@ -364,12 +369,12 @@ int *types, cnt; ipll[dev] = ipl; *iplh[dev] = ipl; iplh[dev] = &ipl->ipl_next; -# if SOLARIS +# if SOLARIS && defined(_KERNEL) cv_signal(&iplwait); mutex_exit(&ipl_mutex); # else MUTEX_EXIT(&ipl_mutex); - wakeup(&iplh[dev]); + WAKEUP(&iplh[dev]); # endif return 1; } @@ -394,7 +399,7 @@ struct uio *uio; return ENXIO; if (!uio->uio_resid) return 0; - if (uio->uio_resid < sizeof(iplog_t)) + if (uio->uio_resid < IPLOG_SIZE) return EINVAL; /* @@ -436,15 +441,14 @@ struct uio *uio; iplused[unit] -= dlen; MUTEX_EXIT(&ipl_mutex); error = UIOMOVE((caddr_t)ipl, dlen, UIO_READ, uio); + MUTEX_ENTER(&ipl_mutex); if (error) { - MUTEX_ENTER(&ipl_mutex); ipl->ipl_next = iplt[unit]; iplt[unit] = ipl; iplused[unit] += dlen; break; } KFREES((caddr_t)ipl, dlen); - MUTEX_ENTER(&ipl_mutex); } if (!iplt[unit]) { iplused[unit] = 0; @@ -473,7 +477,7 @@ minor_t unit; ipll[unit] = NULL; used = iplused[unit]; iplused[unit] = 0; - bzero((char *)&iplcrc[unit], FI_CSIZE); + bzero((char *)&iplcrc[unit], FI_LCSIZE); MUTEX_EXIT(&ipl_mutex); return used; } diff --git a/sys/contrib/ipfilter/netinet/ip_nat.c b/sys/contrib/ipfilter/netinet/ip_nat.c index 363ab24cb01b..60dd7ed73c98 100644 --- a/sys/contrib/ipfilter/netinet/ip_nat.c +++ b/sys/contrib/ipfilter/netinet/ip_nat.c @@ -10,6 +10,9 @@ #define _KERNEL #endif +#ifdef __sgi +# include +#endif #include #include #include @@ -31,7 +34,6 @@ # include #endif #include -#include #ifndef linux # include #endif @@ -93,10 +95,10 @@ extern struct ifnet vpnif; #include "netinet/ip_compat.h" #include #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_proxy.h" #if (__FreeBSD_version >= 300000) # include #endif @@ -135,7 +137,6 @@ extern KRWLOCK_T ipf_nat; #endif static int nat_flushtable __P((void)); -static int nat_clearlist __P((void)); static void nat_addnat __P((struct ipnat *)); static void nat_addrdr __P((struct ipnat *)); static void nat_delete __P((struct nat *)); @@ -144,7 +145,7 @@ 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 void nat_tabmove __P((fr_info_t *, nat_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)); @@ -503,7 +504,7 @@ int mode; 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); + n->in_apr = appr_lookup(n->in_p, n->in_plabel); if (!n->in_apr) { error = ENOENT; break; @@ -904,6 +905,7 @@ caddr_t data; nat->nat_ptr = NULL; nat->nat_hm = NULL; nat->nat_data = NULL; + nat->nat_ifp = GETUNIT(nat->nat_ifname, 4); /* * Restore the rule associated with this nat session @@ -925,7 +927,7 @@ caddr_t data; 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); + in->in_apr = appr_lookup(in->in_p, in->in_plabel); } } @@ -1018,6 +1020,8 @@ struct nat *natd; 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_me != NULL) + *natd->nat_me = NULL; if (natd->nat_fr != NULL) { ATOMIC_DEC32(natd->nat_fr->fr_ref); @@ -1057,6 +1061,7 @@ struct nat *natd; /* * nat_flushtable - clear the NAT table of all mapping entries. + * (this is for the dynamic mappings) */ static int nat_flushtable() { @@ -1089,8 +1094,9 @@ static int nat_flushtable() /* * nat_clearlist - delete all rules in the active NAT mapping list. + * (this is for NAT/RDR rules) */ -static int nat_clearlist() +int nat_clearlist() { register ipnat_t *n, **np = &nat_list; int i = 0; @@ -1121,22 +1127,25 @@ static int nat_clearlist() /* * Create a new NAT table entry. - * NOTE: assumes write lock on ipf_nat has been obtained already. + * NOTE: Assumes write lock on ipf_nat has been obtained already. + * If you intend on changing this, beware: appr_new() may call nat_new() + * recursively! */ -nat_t *nat_new(np, ip, fin, flags, direction) -ipnat_t *np; -ip_t *ip; +nat_t *nat_new(fin, ip, np, natsave, flags, direction) fr_info_t *fin; +ip_t *ip; +ipnat_t *np; +nat_t **natsave; 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; + u_short nflags, sp, dp; 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 @@ -1144,8 +1153,8 @@ int direction; nflags = flags & np->in_flags; if (flags & IPN_TCPUDP) { tcp = (tcphdr_t *)fin->fin_dp; - sport = tcp->th_sport; - dport = tcp->th_dport; + sport = htons(fin->fin_data[0]); + dport = htons(fin->fin_data[1]); } /* Give me a new nat */ @@ -1185,7 +1194,7 @@ int direction; * Check to see if there is an existing NAT * setup for this IP address pair. */ - hm = nat_hostmap(np, ip->ip_src, in); + hm = nat_hostmap(np, fin->fin_src, in); if (hm != NULL) in.s_addr = hm->hm_mapip.s_addr; } else if ((l == 1) && (hm != NULL)) { @@ -1209,7 +1218,7 @@ int direction; /* * map-block - Calculate destination address. */ - in.s_addr = ntohl(ip->ip_src.s_addr); + in.s_addr = ntohl(fin->fin_saddr); in.s_addr &= ntohl(~np->in_inmsk); inb.s_addr = in.s_addr; in.s_addr /= np->in_ippip; @@ -1242,7 +1251,7 @@ int direction; */ if (l > 0) goto badnat; - in.s_addr = ntohl(ip->ip_src.s_addr); + in.s_addr = ntohl(fin->fin_saddr); } else if ((np->in_outmsk != 0xffffffff) && (np->in_pnext == 0) && ((l > 0) || (hm == NULL))) @@ -1264,7 +1273,7 @@ int direction; port += (l % np->in_ppip); port %= np->in_ppip; port += np->in_ppip * - (ntohl(ip->ip_src.s_addr) % + (ntohl(fin->fin_saddr) % np->in_ippip); port += MAPBLK_MINPORT; port = htons(port); @@ -1304,9 +1313,15 @@ int direction; * 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); + sp = fin->fin_data[0]; + dp = fin->fin_data[1]; + fin->fin_data[0] = fin->fin_data[1]; + fin->fin_data[1] = htons(port); + natl = nat_inlookup(fin, flags & ~FI_WILDP, + (u_int)fin->fin_p, fin->fin_dst, + inb, 1); + fin->fin_data[0] = sp; + fin->fin_data[1] = dp; /* * Has the search wrapped around and come back to the @@ -1323,14 +1338,14 @@ int direction; np->in_space--; /* Setup the NAT table */ - nat->nat_inip = ip->ip_src; + nat->nat_inip = fin->fin_src; nat->nat_outip.s_addr = htonl(in.s_addr); - nat->nat_oip = ip->ip_dst; + nat->nat_oip = fin->fin_dst; if (nat->nat_hm == NULL) - nat->nat_hm = nat_hostmap(np, ip->ip_src, + nat->nat_hm = nat_hostmap(np, fin->fin_src, nat->nat_outip); - sum1 = LONG_SUM(ntohl(ip->ip_src.s_addr)) + ntohs(sport); + sum1 = LONG_SUM(ntohl(fin->fin_saddr)) + ntohs(sport); sum2 = LONG_SUM(in.s_addr) + ntohs(port); if (flags & IPN_TCPUDP) { @@ -1370,27 +1385,26 @@ int direction; * 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); + if (np->in_pmin != np->in_pmax) { + nport = ntohs(dport) - ntohs(np->in_pmin) + + ntohs(np->in_pnext); + nport = ntohs(nport); + } else + nport = np->in_pnext; } /* * 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. + * assume a blank `forwarding' of the packet. */ - if (in.s_addr == 0) { - if (nport == dport) - goto badnat; - in.s_addr = ntohl(ip->ip_dst.s_addr); - } + if (in.s_addr == 0) + in.s_addr = ntohl(fin->fin_daddr); nat->nat_inip.s_addr = htonl(in.s_addr); - nat->nat_outip = ip->ip_dst; - nat->nat_oip = ip->ip_src; + nat->nat_outip = fin->fin_dst; + nat->nat_oip = fin->fin_src; - sum1 = LONG_SUM(ntohl(ip->ip_dst.s_addr)) + ntohs(dport); + sum1 = LONG_SUM(ntohl(fin->fin_daddr)) + ntohs(dport); sum2 = LONG_SUM(in.s_addr) + ntohs(nport); if (flags & IPN_TCPUDP) { @@ -1408,8 +1422,8 @@ int direction; 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 = LONG_SUM(ntohl(fin->fin_saddr)); + sum1 += LONG_SUM(ntohl(fin->fin_daddr)); sum1 += IPPROTO_TCP; sum1 = (sum1 & 0xffff) + (sum1 >> 16); nat->nat_sumd[1] = NAT_HW_CKSUM|(sum1 & 0xffff); @@ -1419,9 +1433,9 @@ int direction; if ((flags & IPN_TCPUDP) && ((sport != port) || (dport != nport))) { if (direction == NAT_OUTBOUND) - sum1 = LONG_SUM(ntohl(ip->ip_src.s_addr)); + sum1 = LONG_SUM(ntohl(fin->fin_saddr)); else - sum1 = LONG_SUM(ntohl(ip->ip_dst.s_addr)); + sum1 = LONG_SUM(ntohl(fin->fin_daddr)); sum2 = LONG_SUM(in.s_addr); @@ -1432,15 +1446,13 @@ int direction; in.s_addr = htonl(in.s_addr); -#ifdef _KERNEL strncpy(nat->nat_ifname, IFNAME(fin->fin_ifp), IFNAMSIZ); -#endif - nat_insert(nat); + nat->nat_me = natsave; nat->nat_dir = direction; nat->nat_ifp = fin->fin_ifp; nat->nat_ptr = np; - nat->nat_p = ip->ip_p; + nat->nat_p = fin->fin_p; nat->nat_bytes = 0; nat->nat_pkts = 0; nat->nat_fr = fin->fin_fr; @@ -1454,6 +1466,13 @@ int direction; if (flags & IPN_TCPUDP) tcp->th_dport = nport; } + + nat_insert(nat); + + if ((np->in_apr != NULL) && (np->in_dport == 0 || + (tcp != NULL && dport == np->in_dport))) + (void) appr_new(fin, ip, nat); + np->in_use++; #ifdef IPFILTER_LOG nat_log(nat, (u_int)np->in_redir); @@ -1468,6 +1487,10 @@ badnat: } +/* + * Insert a NAT entry into the hash tables for searching and add it to the + * list of active NAT entries. Adjust global counters when complete. + */ void nat_insert(nat) nat_t *nat; { @@ -1495,10 +1518,10 @@ nat_t *nat; hv2 = NAT_HASH_FN(nat->nat_oip.s_addr, hv2 + nat->nat_oport, ipf_nattable_sz); } else { - hv1 = NAT_HASH_FN(nat->nat_inip.s_addr, 0, 0xffffffff); - hv1 = NAT_HASH_FN(nat->nat_oip.s_addr, hv1, ipf_nattable_sz); - hv2 = NAT_HASH_FN(nat->nat_outip.s_addr, 0, 0xffffffff); - hv2 = NAT_HASH_FN(nat->nat_oip.s_addr, hv2, ipf_nattable_sz); + hv1 = NAT_HASH_FN(nat->nat_oip.s_addr, nat->nat_inip.s_addr, + ipf_nattable_sz); + hv2 = NAT_HASH_FN(nat->nat_oip.s_addr, nat->nat_outip.s_addr, + ipf_nattable_sz); } natp = &nat_table[0][hv1]; @@ -1584,25 +1607,36 @@ int dir; else if (oip->ip_p == IPPROTO_UDP) flags = IPN_UDP; if (flags & IPN_TCPUDP) { + u_short data[2]; + nat_t *nat; + minlen += 8; /* + 64bits of data to get ports */ if (ip->ip_len < ICMPERR_IPICMPHLEN + minlen) return NULL; + + data[0] = fin->fin_data[0]; + data[1] = fin->fin_data[1]; 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); + fin->fin_data[0] = ntohs(tcp->th_dport); + fin->fin_data[1] = ntohs(tcp->th_sport); + + if (dir == NAT_INBOUND) { + nat = nat_inlookup(fin, flags, (u_int)oip->ip_p, + oip->ip_dst, oip->ip_src, 0); + } else { + nat = nat_outlookup(fin, flags, (u_int)oip->ip_p, + oip->ip_dst, oip->ip_src, 0); + } + fin->fin_data[0] = data[0]; + fin->fin_data[1] = data[1]; + return nat; } if (dir == NAT_INBOUND) - return nat_inlookup(fin->fin_ifp, 0, (u_int)oip->ip_p, - oip->ip_dst, oip->ip_src, 0, 0); + return nat_inlookup(fin, 0, (u_int)oip->ip_p, + oip->ip_dst, oip->ip_src, 0); else - return nat_outlookup(fin->fin_ifp, 0, (u_int)oip->ip_p, - oip->ip_dst, oip->ip_src, 0, 0); + return nat_outlookup(fin, 0, (u_int)oip->ip_p, + oip->ip_dst, oip->ip_src, 0); } @@ -1622,7 +1656,7 @@ int dir; udphdr_t *udp; nat_t *nat; ip_t *oip; - int flags = 0; + int flags; if ((fin->fin_fl & FI_SHORT) || (fin->fin_off != 0)) return NULL; @@ -1631,6 +1665,8 @@ int dir; */ if ((ip->ip_v != 4) || !(nat = nat_icmplookup(ip, fin, dir))) return NULL; + + flags = 0; *nflags = IPN_ICMPERR; icmp = (icmphdr_t *)fin->fin_dp; oip = (ip_t *)&icmp->icmp_ip; @@ -1920,23 +1956,32 @@ int dir; * 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; +nat_t *nat_inlookup(fin, flags, p, src, mapdst, rw) +fr_info_t *fin; 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; + ipnat_t *ipn; + void *ifp; u_int hv; + if (fin != NULL) + ifp = fin->fin_ifp; + else + ifp = NULL; dst = mapdst.s_addr; - dport = ports >> 16; - sport = ports & 0xffff; - flags &= IPN_TCPUDP; + if (flags & IPN_TCPUDP) { + sport = htons(fin->fin_data[0]); + dport = htons(fin->fin_data[1]); + } else { + sport = 0; + dport = 0; + } hv = NAT_HASH_FN(dst, dport, 0xffffffff); hv = NAT_HASH_FN(src.s_addr, hv + sport, ipf_nattable_sz); @@ -1946,19 +1991,34 @@ int rw; 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))))) + ((p == 0) || (p == nat->nat_p))) { + switch (p) + { + case IPPROTO_TCP : + case IPPROTO_UDP : + if (nat->nat_oport != sport) + continue; + if (nat->nat_outport != dport) + continue; + break; + default : + break; + } + + ipn = nat->nat_ptr; + if ((ipn != NULL) && (nat->nat_aps != NULL)) + if (appr_match(fin, nat) != 0) + continue; return nat; + } } - if (!nat_stats.ns_wilds || !(flags & IPN_TCPUDP)) + if (!nat_stats.ns_wilds || !(flags & FI_WILDP)) return NULL; if (!rw) { RWLOCK_EXIT(&ipf_nat); } hv = NAT_HASH_FN(dst, 0, 0xffffffff); - hv = NAT_HASH_FN(src.s_addr, hv, ipf_nattable_sz); + hv = NAT_HASH_FN(src.s_addr, dst, ipf_nattable_sz); if (!rw) { WRITE_ENTER(&ipf_nat); } @@ -1967,8 +2027,6 @@ int rw; 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 || @@ -1976,7 +2034,7 @@ int rw; continue; if (((nat->nat_oport == sport) || (nflags & FI_W_DPORT)) && ((nat->nat_outport == dport) || (nflags & FI_W_SPORT))) { - nat_tabmove(nat, ports); + nat_tabmove(fin, nat); break; } } @@ -1992,21 +2050,18 @@ int rw; * 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) +static void nat_tabmove(fin, nat) +fr_info_t *fin; nat_t *nat; -u_32_t ports; { register u_short sport, dport; + u_int hv, nflags; nat_t **natp; - u_int hv; - dport = ports >> 16; - sport = ports & 0xffff; + nflags = nat->nat_flags; - if (nat->nat_oport == dport) { - nat->nat_inport = sport; - nat->nat_outport = sport; - } + sport = ntohs(fin->fin_data[0]); + dport = ntohs(fin->fin_data[1]); /* * Remove the NAT entry from the old location @@ -2048,23 +2103,29 @@ u_32_t ports; * 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; +nat_t *nat_outlookup(fin, flags, p, src, dst, rw) +fr_info_t *fin; 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; + ipnat_t *ipn; u_32_t srcip; + void *ifp; u_int hv; - sport = ports & 0xffff; - dport = ports >> 16; - flags &= IPN_TCPUDP; + ifp = fin->fin_ifp; srcip = src.s_addr; + if (flags & IPN_TCPUDP) { + sport = ntohs(fin->fin_data[0]); + dport = ntohs(fin->fin_data[1]); + } else { + sport = 0; + dport = 0; + } hv = NAT_HASH_FN(srcip, sport, 0xffffffff); hv = NAT_HASH_FN(dst.s_addr, hv + dport, ipf_nattable_sz); @@ -2075,19 +2136,34 @@ int rw; 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)))) + ((p == 0) || (p == nat->nat_p))) { + switch (p) + { + case IPPROTO_TCP : + case IPPROTO_UDP : + if (nat->nat_oport != dport) + continue; + if (nat->nat_inport != sport) + continue; + break; + default : + break; + } + + ipn = nat->nat_ptr; + if ((ipn != NULL) && (nat->nat_aps != NULL)) + if (appr_match(fin, nat) != 0) + continue; return nat; + } } - if (!nat_stats.ns_wilds || !(flags & IPN_TCPUDP)) + if (!nat_stats.ns_wilds || !(flags & FI_WILDP)) return NULL; if (!rw) { RWLOCK_EXIT(&ipf_nat); } - hv = NAT_HASH_FN(srcip, 0, ipf_nattable_sz); - hv = NAT_HASH_FN(dst.s_addr, hv, ipf_nattable_sz); + + hv = NAT_HASH_FN(dst.s_addr, srcip, ipf_nattable_sz); if (!rw) { WRITE_ENTER(&ipf_nat); } @@ -2096,8 +2172,6 @@ int rw; 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) || @@ -2105,7 +2179,7 @@ int rw; continue; if (((nat->nat_inport == sport) || (nflags & FI_W_SPORT)) && ((nat->nat_oport == dport) || (nflags & FI_W_DPORT))) { - nat_tabmove(nat, ports); + nat_tabmove(fin, nat); break; } } @@ -2122,16 +2196,19 @@ int rw; nat_t *nat_lookupredir(np) register natlookup_t *np; { - u_32_t ports; nat_t *nat; + fr_info_t fi; + + bzero((char *)&fi, sizeof(fi)); + fi.fin_data[0] = np->nl_inport; + fi.fin_data[1] = np->nl_outport; - 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))) { + if ((nat = nat_outlookup(&fi, np->nl_flags, 0, np->nl_inip, + np->nl_outip, 0))) { np->nl_realip = nat->nat_outip; np->nl_realport = nat->nat_outport; } @@ -2149,7 +2226,7 @@ ip_t *ip; if (ip->ip_v != 4) return 0; - if (np->in_p && ip->ip_p != np->in_p) + if (np->in_p && fin->fin_p != np->in_p) return 0; if (fin->fin_out) { if (!(np->in_redir & (NAT_MAP|NAT_MAPBLK))) @@ -2199,6 +2276,7 @@ fr_info_t *fin; u_int nflags = 0, hv, msk; struct ifnet *ifp; frentry_t *fr; + void *sifp; u_32_t iph; nat_t *nat; @@ -2206,15 +2284,17 @@ fr_info_t *fin; 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; + fr->fr_tif.fd_ifp && fr->fr_tif.fd_ifp != (void *)-1) { + sifp = fin->fin_ifp; + fin->fin_ifp = fr->fr_tif.fd_ifp; + } else + sifp = fin->fin_ifp; + ifp = fin->fin_ifp; if ((fin->fin_off == 0) && !(fin->fin_fl & FI_SHORT)) { - if (ip->ip_p == IPPROTO_TCP) + if (fin->fin_p == IPPROTO_TCP) nflags = IPN_TCP; - else if (ip->ip_p == IPPROTO_UDP) + else if (fin->fin_p == IPPROTO_UDP) nflags = IPN_UDP; if ((nflags & IPN_TCPUDP)) { tcp = (tcphdr_t *)fin->fin_dp; @@ -2223,27 +2303,28 @@ fr_info_t *fin; } } - ipa = ip->ip_src.s_addr; + ipa = fin->fin_saddr; READ_ENTER(&ipf_nat); - if ((ip->ip_p == IPPROTO_ICMP) && + if ((fin->fin_p == IPPROTO_ICMP) && (nat = nat_icmp(ip, fin, &nflags, NAT_OUTBOUND))) icmpset = 1; else if ((fin->fin_fl & FI_FRAG) && (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))) { + else if ((nat = nat_outlookup(fin, nflags|FI_WILDP|FI_WILDA, + (u_int)fin->fin_p, fin->fin_src, + fin->fin_dst, 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)) + 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); @@ -2252,13 +2333,15 @@ fr_info_t *fin; } } else { RWLOCK_EXIT(&ipf_nat); + + msk = 0xffffffff; + i = 32; + 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); @@ -2274,22 +2357,13 @@ maskloop: 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->in_plabel && !appr_ok(ip, tcp, np)) + continue; + nat = nat_new(fin, ip, np, NULL, + (u_int)nflags, NAT_OUTBOUND); + if (nat != NULL) { + np->in_hits++; + break; } } if ((np == NULL) && (i > 0)) { @@ -2311,7 +2385,14 @@ maskloop: if (natadd && (fin->fin_fl & FI_FRAG) && np) ipfr_nat_newfrag(ip, fin, 0, nat); MUTEX_ENTER(&nat->nat_lock); - nat->nat_age = fr_defnatage; + if (fin->fin_p != IPPROTO_TCP) { + if (np && np->in_age[1]) + nat->nat_age = np->in_age[1]; + else if (!icmpset && (fin->fin_p == IPPROTO_ICMP)) + nat->nat_age = fr_defnaticmpage; + else + nat->nat_age = fr_defnatage; + } nat->nat_bytes += ip->ip_len; nat->nat_pkts++; MUTEX_EXIT(&nat->nat_lock); @@ -2323,16 +2404,16 @@ maskloop: if (nflags == IPN_ICMPERR) { u_32_t s1, s2, sumd; - s1 = LONG_SUM(ntohl(ip->ip_src.s_addr)); + s1 = LONG_SUM(ntohl(fin->fin_saddr)); s2 = LONG_SUM(ntohl(nat->nat_outip.s_addr)); CALC_SUMD(s1, s2, sumd); if (nat->nat_dir == NAT_OUTBOUND) - fix_incksum(fin, &ip->ip_sum, sumd); - else fix_outcksum(fin, &ip->ip_sum, sumd); + else + fix_incksum(fin, &ip->ip_sum, sumd); } -#if SOLARIS || defined(__sgi) +#if (SOLARIS || defined(__sgi)) && defined(_KERNEL) else { if (nat->nat_dir == NAT_OUTBOUND) fix_outcksum(fin, &ip->ip_sum, nat->nat_ipsumd); @@ -2340,16 +2421,19 @@ maskloop: fix_incksum(fin, &ip->ip_sum, nat->nat_ipsumd); } #endif + /* + * Only change the packet contents, not what is filtered upon. + */ ip->ip_src = nat->nat_outip; if ((fin->fin_off == 0) && !(fin->fin_fl & FI_SHORT)) { - if ((nat->nat_outport != 0) && (nflags & IPN_TCPUDP)) { + if ((nat->nat_outport != 0) && (tcp != NULL)) { tcp->th_sport = nat->nat_outport; fin->fin_data[0] = ntohs(tcp->th_sport); } - if (ip->ip_p == IPPROTO_TCP) { + if (fin->fin_p == IPPROTO_TCP) { csump = &tcp->th_sum; MUTEX_ENTER(&nat->nat_lock); fr_tcp_age(&nat->nat_age, @@ -2369,25 +2453,24 @@ maskloop: if (nat->nat_age == fr_tcpclosed) nat->nat_age = fr_tcplastack; MUTEX_EXIT(&nat->nat_lock); - } else if (ip->ip_p == IPPROTO_UDP) { + } else if (fin->fin_p == IPPROTO_UDP) { udphdr_t *udp = (udphdr_t *)tcp; if (udp->uh_sum) csump = &udp->uh_sum; - } else if (ip->ip_p == IPPROTO_ICMP) { - if (!icmpset) - nat->nat_age = fr_defnaticmpage; } if (csump) { if (nat->nat_dir == NAT_OUTBOUND) - fix_outcksum(fin, csump, nat->nat_sumd[1]); + fix_outcksum(fin, csump, + nat->nat_sumd[1]); else - fix_incksum(fin, csump, nat->nat_sumd[1]); + fix_incksum(fin, csump, + nat->nat_sumd[1]); } } - if ((np->in_apr != NULL) && (np->in_dport == 0 || + if (np && (np->in_apr != NULL) && (np->in_dport == 0 || (tcp != NULL && dport == np->in_dport))) { i = appr_check(ip, fin, nat); if (i == 0) @@ -2396,9 +2479,11 @@ maskloop: i = 1; ATOMIC_INCL(nat_stats.ns_mapped[1]); RWLOCK_EXIT(&ipf_nat); /* READ */ + fin->fin_ifp = sifp; return i; } RWLOCK_EXIT(&ipf_nat); /* READ/WRITE */ + fin->fin_ifp = sifp; return 0; } @@ -2426,37 +2511,36 @@ fr_info_t *fin; return 0; if ((fin->fin_off == 0) && !(fin->fin_fl & FI_SHORT)) { - if (ip->ip_p == IPPROTO_TCP) + if (fin->fin_p == IPPROTO_TCP) nflags = IPN_TCP; - else if (ip->ip_p == IPPROTO_UDP) + else if (fin->fin_p == IPPROTO_UDP) nflags = IPN_UDP; if ((nflags & IPN_TCPUDP)) { tcp = (tcphdr_t *)fin->fin_dp; - dport = tcp->th_dport; sport = tcp->th_sport; + dport = tcp->th_dport; } } - in = ip->ip_dst; + in = fin->fin_dst; /* make sure the source address is to be redirected */ - src = ip->ip_src; + src = fin->fin_src; READ_ENTER(&ipf_nat); - if ((ip->ip_p == IPPROTO_ICMP) && + if ((fin->fin_p == IPPROTO_ICMP) && (nat = nat_icmp(ip, fin, &nflags, NAT_INBOUND))) icmpset = 1; else if ((fin->fin_fl & FI_FRAG) && (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))) { + else if ((nat = nat_inlookup(fin, nflags|FI_WILDP|FI_WILDA, + (u_int)fin->fin_p, fin->fin_src, in, 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) && + if ((nat->nat_outport != dport) && (nflags & FI_W_SPORT)) nat->nat_outport = dport; nat->nat_flags &= ~(FI_W_SPORT|FI_W_DPORT); @@ -2465,19 +2549,21 @@ fr_info_t *fin; } } else { RWLOCK_EXIT(&ipf_nat); + + msk = 0xffffffff; + i = 32; + 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_p && (np->in_p != fin->fin_p)) || (np->in_flags && !(nflags & np->in_flags))) continue; if (np->in_flags & IPN_FILTER) { @@ -2485,11 +2571,10 @@ maskloop: 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) || + if ((!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, + if ((nat = nat_new(fin, ip, np, NULL, nflags, NAT_INBOUND))) { np->in_hits++; break; @@ -2515,8 +2600,8 @@ maskloop: fin->fin_fr = nat->nat_fr; if (natadd && (fin->fin_fl & FI_FRAG) && np) ipfr_nat_newfrag(ip, fin, 0, nat); - if ((np->in_apr != NULL) && (np->in_dport == 0 || - (tcp != NULL && sport == np->in_dport))) { + if (np && (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); @@ -2525,9 +2610,14 @@ maskloop: } MUTEX_ENTER(&nat->nat_lock); - if (nflags != IPN_ICMPERR) - nat->nat_age = fr_defnatage; - + if (fin->fin_p != IPPROTO_TCP) { + if (np && np->in_age[0]) + nat->nat_age = np->in_age[0]; + else if (!icmpset && (fin->fin_p == IPPROTO_ICMP)) + nat->nat_age = fr_defnaticmpage; + else + nat->nat_age = fr_defnatage; + } nat->nat_bytes += ip->ip_len; nat->nat_pkts++; MUTEX_EXIT(&nat->nat_lock); @@ -2538,7 +2628,7 @@ maskloop: * Fix up checksums, not by recalculating them, but * simply computing adjustments. */ -#if SOLARIS || defined(__sgi) +#if (SOLARIS || defined(__sgi)) && defined(_KERNEL) if (nat->nat_dir == NAT_OUTBOUND) fix_incksum(fin, &ip->ip_sum, nat->nat_ipsumd); else @@ -2546,12 +2636,12 @@ maskloop: #endif if ((fin->fin_off == 0) && !(fin->fin_fl & FI_SHORT)) { - if ((nat->nat_inport != 0) && (nflags & IPN_TCPUDP)) { + if ((nat->nat_inport != 0) && (tcp != NULL)) { tcp->th_dport = nat->nat_inport; fin->fin_data[1] = ntohs(tcp->th_dport); } - if (ip->ip_p == IPPROTO_TCP) { + if (fin->fin_p == IPPROTO_TCP) { csump = &tcp->th_sum; MUTEX_ENTER(&nat->nat_lock); fr_tcp_age(&nat->nat_age, @@ -2571,21 +2661,20 @@ maskloop: if (nat->nat_age == fr_tcpclosed) nat->nat_age = fr_tcplastack; MUTEX_EXIT(&nat->nat_lock); - } else if (ip->ip_p == IPPROTO_UDP) { + } else if (fin->fin_p == IPPROTO_UDP) { udphdr_t *udp = (udphdr_t *)tcp; if (udp->uh_sum) csump = &udp->uh_sum; - } else if (ip->ip_p == IPPROTO_ICMP) { - if (!icmpset) - nat->nat_age = fr_defnaticmpage; } if (csump) { if (nat->nat_dir == NAT_OUTBOUND) - fix_incksum(fin, csump, nat->nat_sumd[0]); + fix_incksum(fin, csump, + nat->nat_sumd[0]); else - fix_outcksum(fin, csump, nat->nat_sumd[0]); + fix_outcksum(fin, csump, + nat->nat_sumd[0]); } } ATOMIC_INCL(nat_stats.ns_mapped[0]); @@ -2760,3 +2849,13 @@ u_int type; (void) ipllog(IPL_LOGNAT, NULL, items, sizes, types, 1); } #endif + + +#if defined(__OpenBSD__) +void nat_ifdetach(ifp) +void *ifp; +{ + frsync(); + return; +} +#endif diff --git a/sys/contrib/ipfilter/netinet/ip_nat.h b/sys/contrib/ipfilter/netinet/ip_nat.h index 20f7a14dd831..be0bb8307a36 100644 --- a/sys/contrib/ipfilter/netinet/ip_nat.h +++ b/sys/contrib/ipfilter/netinet/ip_nat.h @@ -89,6 +89,7 @@ typedef struct nat { struct nat *nat_next; struct nat *nat_hnext[2]; struct nat **nat_phnext[2]; + struct nat **nat_me; void *nat_ifp; int nat_dir; char nat_ifname[IFNAMSIZ]; @@ -119,6 +120,7 @@ typedef struct ipnat { struct in_addr in_out[2]; struct in_addr in_src[2]; struct frtuc in_tuc; + u_int in_age[2]; /* Aging for NAT entries. Not for TCP */ 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 */ @@ -287,23 +289,27 @@ extern nat_t **nat_table[2]; extern nat_t *nat_instances; extern ipnat_t **nat_rules; extern ipnat_t **rdr_rules; +extern ipnat_t *nat_list; extern natstat_t nat_stats; +#if defined(__OpenBSD__) +extern void nat_ifdetach __P((void *)); +#endif #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_new __P((fr_info_t *, ip_t *, ipnat_t *, nat_t **, + u_int, int)); +extern nat_t *nat_outlookup __P((fr_info_t *, u_int, u_int, struct in_addr, + struct in_addr, int)); +extern nat_t *nat_inlookup __P((fr_info_t *, u_int, u_int, struct in_addr, + struct in_addr, int)); 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 int nat_clearlist __P((void)); extern void nat_insert __P((nat_t *)); extern int ip_natout __P((ip_t *, fr_info_t *)); diff --git a/sys/contrib/ipfilter/netinet/ip_proxy.c b/sys/contrib/ipfilter/netinet/ip_proxy.c index 1fee6b720c4e..5a03319ed04d 100644 --- a/sys/contrib/ipfilter/netinet/ip_proxy.c +++ b/sys/contrib/ipfilter/netinet/ip_proxy.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1997-2001 by Darren Reed. + * Copyright (C) 1997-2002 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -8,6 +8,9 @@ # define _KERNEL #endif +#ifdef __sgi +# include +#endif #include #include #include @@ -17,7 +20,6 @@ # include #endif #include -#include #if !defined(_KERNEL) && !defined(KERNEL) # include # include @@ -66,9 +68,9 @@ #include "netinet/ip_compat.h" #include #include "netinet/ip_fil.h" -#include "netinet/ip_proxy.h" #include "netinet/ip_nat.h" #include "netinet/ip_state.h" +#include "netinet/ip_proxy.h" #if (__FreeBSD_version >= 300000) # include #endif @@ -78,23 +80,27 @@ static const char rcsid[] = "@(#)$FreeBSD$"; #endif +#if defined(_KERNEL) && (SOLARIS || defined(__sgi)) +extern KRWLOCK_T ipf_nat, ipf_state; +#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) +#if defined(_KERNEL) #include "netinet/ip_ftp_pxy.c" #include "netinet/ip_rcmd_pxy.c" #include "netinet/ip_raudio_pxy.c" +#include "netinet/ip_netbios_pxy.c" +#include "netinet/ip_h323_pxy.c" #endif +#include "netinet/ip_ipsec_pxy.c" ap_session_t *ap_sess_tab[AP_SESS_SIZE]; ap_session_t *ap_sess_list = NULL; @@ -102,20 +108,39 @@ 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 }, + ippr_ftp_new, NULL, ippr_ftp_in, ippr_ftp_out, NULL }, #endif #ifdef IPF_RCMD_PROXY { NULL, "rcmd", (char)IPPROTO_TCP, 0, 0, ippr_rcmd_init, NULL, - ippr_rcmd_new, NULL, ippr_rcmd_out }, + ippr_rcmd_new, NULL, NULL, ippr_rcmd_out, NULL }, #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 }, + ippr_raudio_new, NULL, ippr_raudio_in, ippr_raudio_out, NULL }, +#endif +#ifdef IPF_IPSEC_PROXY + { NULL, "ipsec", (char)IPPROTO_UDP, 0, 0, ippr_ipsec_init, NULL, + ippr_ipsec_new, ippr_ipsec_del, NULL, ippr_ipsec_out, + ippr_ipsec_match }, #endif - { NULL, "", '\0', 0, 0, NULL, NULL } +#ifdef IPF_NETBIOS_PROXY + { NULL, "netbios", (char)IPPROTO_TCP, 0, 0, ippr_netbios_init, NULL, + NULL, NULL, NULL, ippr_netbios_out, NULL }, +#endif +#ifdef IPF_H323_PROXY + { NULL, "h323", (char)IPPROTO_TCP, 0, 0, ippr_h323_init, NULL, + ippr_h323_new, ippr_h323_del, ippr_h323_in, ippr_h323_out, NULL }, + { NULL, "h245", (char)IPPROTO_TCP, 0, 0, ippr_h245_init, NULL, + ippr_h245_new, NULL, NULL, ippr_h245_out, NULL }, +#endif + { NULL, "", '\0', 0, 0, NULL, NULL, NULL } }; +/* + * Dynamically add a new kernel proxy. Ensure that it is unique in the + * collection compiled in and dynamically added. + */ int appr_add(ap) aproxy_t *ap; { @@ -127,7 +152,7 @@ aproxy_t *ap; sizeof(ap->apr_label))) return -1; - for (a = ap_proxylist; a->apr_p; a = a->apr_next) + for (a = ap_proxylist; a && 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))) @@ -138,6 +163,11 @@ aproxy_t *ap; } +/* + * Delete a proxy that has been added dynamically from those available. + * If it is in use, return 1 (do not destroy NOW), not in use 0 or -1 + * if it cannot be matched. + */ int appr_del(ap) aproxy_t *ap; { @@ -145,15 +175,19 @@ aproxy_t *ap; for (app = &ap_proxylist; (a = *app); app = &a->apr_next) if (a == ap) { + a->apr_flags |= APR_DELETE; + *app = a->apr_next; if (ap->apr_ref != 0) return 1; - *app = a->apr_next; return 0; } return -1; } +/* + * Return 1 if the packet is a good match against a proxy, else 0. + */ int appr_ok(ip, tcp, nat) ip_t *ip; tcphdr_t *tcp; @@ -162,34 +196,64 @@ ipnat_t *nat; aproxy_t *apr = nat->in_apr; u_short dport = nat->in_dport; - if (!apr || (apr->apr_flags & APR_DELETE) || + if ((apr == NULL) || (apr->apr_flags & APR_DELETE) || (ip->ip_p != apr->apr_p)) return 0; - if ((tcp && (tcp->th_dport != dport)) || (!tcp && dport)) + if (((tcp != NULL) && (tcp->th_dport != dport)) || (!tcp && dport)) return 0; return 1; } +/* + * If a proxy has a match function, call that to do extended packet + * matching. + */ +int appr_match(fin, nat) +fr_info_t *fin; +nat_t *nat; +{ + aproxy_t *apr; + ipnat_t *ipn; + + ipn = nat->nat_ptr; + if (ipn == NULL) + return -1; + apr = ipn->in_apr; + if ((apr == NULL) || (apr->apr_flags & APR_DELETE) || + (nat->nat_aps == NULL)) + return -1; + if (apr->apr_match != NULL) + if ((*apr->apr_match)(fin, nat->nat_aps, nat) != 0) + return -1; + return 0; +} + + /* * 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; +int appr_new(fin, ip, nat) fr_info_t *fin; +ip_t *ip; nat_t *nat; { register ap_session_t *aps; + aproxy_t *apr; + + if ((nat->nat_ptr == NULL) || (nat->nat_aps != NULL)) + return -1; + + apr = nat->nat_ptr->in_apr; if (!apr || (apr->apr_flags & APR_DELETE) || (ip->ip_p != apr->apr_p)) - return NULL; + return -1; KMALLOC(aps, ap_session_t *); if (!aps) - return NULL; + return -1; bzero((char *)aps, sizeof(*aps)); aps->aps_p = ip->ip_p; aps->aps_data = NULL; @@ -197,13 +261,18 @@ nat_t *nat; aps->aps_psiz = 0; if (apr->apr_new != NULL) if ((*apr->apr_new)(fin, ip, aps, nat) == -1) { + if ((aps->aps_data != NULL) && (aps->aps_psiz != 0)) { + KFREES(aps->aps_data, aps->aps_psiz); + } KFREE(aps); - return NULL; + return -1; } aps->aps_nat = nat; aps->aps_next = ap_sess_list; ap_sess_list = aps; - return aps; + nat->nat_aps = aps; + + return 0; } @@ -227,9 +296,6 @@ nat_t *nat; 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) { @@ -265,8 +331,13 @@ nat_t *nat; } rv = APR_EXIT(err); - if (rv == -1) - return rv; + if (rv == 1) + return -1; + if (rv == 2) { + appr_free(apr); + nat->nat_aps = NULL; + return -1; + } if (tcp != NULL) { err = appr_fixseqack(fin, ip, aps, APR_INC(err)); @@ -285,7 +356,10 @@ nat_t *nat; } -aproxy_t *appr_match(pr, name) +/* + * Search for an proxy by the protocol it is being used with and its name. + */ +aproxy_t *appr_lookup(pr, name) u_int pr; char *name; { @@ -319,6 +393,7 @@ void aps_free(aps) ap_session_t *aps; { ap_session_t *a, **ap; + aproxy_t *apr; if (!aps) return; @@ -329,6 +404,10 @@ ap_session_t *aps; break; } + apr = aps->aps_apr; + if ((apr != NULL) && (apr->apr_del != NULL)) + (*apr->apr_del)(aps); + if ((aps->aps_data != NULL) && (aps->aps_psiz != 0)) KFREES(aps->aps_data, aps->aps_psiz); KFREE(aps); @@ -434,6 +513,10 @@ int inc; } +/* + * Initialise hook for kernel application proxies. + * Call the initialise routine for all the compiled in kernel proxies. + */ int appr_init() { aproxy_t *ap; @@ -448,6 +531,10 @@ int appr_init() } +/* + * Unload hook for kernel application proxies. + * Call the finialise routine for all the compiled in kernel proxies. + */ void appr_unload() { aproxy_t *ap; diff --git a/sys/contrib/ipfilter/netinet/ip_proxy.h b/sys/contrib/ipfilter/netinet/ip_proxy.h index 9a601d77d24f..f38974ebe535 100644 --- a/sys/contrib/ipfilter/netinet/ip_proxy.h +++ b/sys/contrib/ipfilter/netinet/ip_proxy.h @@ -75,10 +75,12 @@ typedef struct aproxy { void (* apr_fini) __P((void)); int (* apr_new) __P((fr_info_t *, ip_t *, ap_session_t *, struct nat *)); + void (* apr_del) __P((ap_session_t *)); 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 *)); + int (* apr_match) __P((fr_info_t *, ap_session_t *, struct nat *)); } aproxy_t; #define APR_DELETE 1 @@ -97,6 +99,7 @@ typedef struct ftpside { u_32_t ftps_seq; u_32_t ftps_len; int ftps_junk; + int ftps_cmds; char ftps_buf[FTP_BUFSZ]; } ftpside_t; @@ -109,7 +112,7 @@ typedef struct ftpinfo { /* * Real audio proxy structure and #defines */ -typedef struct { +typedef struct raudio_s { int rap_seenpna; int rap_seenver; int rap_version; @@ -137,6 +140,19 @@ typedef struct { #define RAP_M_TCP 4 #define RAP_M_UDP_ROBUST (RAP_M_UDP|RAP_M_ROBUST) +/* + * IPSec proxy + */ +typedef u_32_t ipsec_cookie_t[2]; + +typedef struct ipsec_pxy { + ipsec_cookie_t ipsc_icookie; + ipsec_cookie_t ipsc_rcookie; + int ipsc_rckset; + ipnat_t ipsc_rule; + nat_t *ipsc_nat; + ipstate_t *ipsc_state; +} ipsec_pxy_t; extern ap_session_t *ap_sess_tab[AP_SESS_SIZE]; extern ap_session_t *ap_sess_list; @@ -148,9 +164,11 @@ 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 int appr_match __P((fr_info_t *, struct nat *)); 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 *)); +extern aproxy_t *appr_lookup __P((u_int, char *)); +extern int appr_new __P((fr_info_t *, ip_t *, struct nat *)); #endif /* __IP_PROXY_H__ */ diff --git a/sys/contrib/ipfilter/netinet/ip_raudio_pxy.c b/sys/contrib/ipfilter/netinet/ip_raudio_pxy.c index 1bd8c9252d29..5d5d9d449f5b 100644 --- a/sys/contrib/ipfilter/netinet/ip_raudio_pxy.c +++ b/sys/contrib/ipfilter/netinet/ip_raudio_pxy.c @@ -78,7 +78,7 @@ nat_t *nat; return 0; tcp = (tcphdr_t *)fin->fin_dp; - off = (ip->ip_hl << 2) + (tcp->th_off << 2); + off = fin->fin_hlen + (tcp->th_off << 2); bzero(membuf, sizeof(membuf)); #if SOLARIS m = fin->fin_qfm; @@ -194,7 +194,7 @@ nat_t *nat; return 0; tcp = (tcphdr_t *)fin->fin_dp; - off = (ip->ip_hl << 2) + (tcp->th_off << 2); + off = fin->fin_hlen + (tcp->th_off << 2); m = *(mb_t **)fin->fin_mp; #if SOLARIS @@ -283,11 +283,13 @@ nat_t *nat; fi.fin_data[0] = dp; fi.fin_data[1] = sp; fi.fin_out = 0; - ipn = nat_new(nat->nat_ptr, ip, &fi, + ipn = nat_new(&fi, ip, nat->nat_ptr, NULL, 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); + (void) fr_addstate(ip, &fi, NULL, + FI_IGNOREPKT|FI_NORULE| + (sp ? 0 : FI_W_SPORT)); } } @@ -298,11 +300,12 @@ nat_t *nat; fi.fin_data[0] = sp; fi.fin_data[1] = 0; fi.fin_out = 1; - ipn = nat_new(nat->nat_ptr, ip, &fi, IPN_UDP|FI_W_DPORT, + ipn = nat_new(&fi, ip, nat->nat_ptr, NULL, IPN_UDP|FI_W_DPORT, NAT_OUTBOUND); if (ipn != NULL) { ipn->nat_age = fr_defnatage; - (void) fr_addstate(ip, &fi, FI_W_DPORT); + (void) fr_addstate(ip, &fi, NULL, + FI_W_DPORT|FI_IGNOREPKT|FI_NORULE); } } diff --git a/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c b/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c index 0ae021087b85..1d6bc71893d6 100644 --- a/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c +++ b/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c @@ -1,5 +1,5 @@ /* - * $Id: ip_rcmd_pxy.c,v 1.4.2.4 2000/11/01 14:34:20 darrenr Exp $ + * $Id: ip_rcmd_pxy.c,v 1.4.2.5 2001/10/30 16:38:14 darrenr Exp $ */ /* * Simple RCMD transparent proxy for in-kernel use. For use with the NAT @@ -83,10 +83,10 @@ 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; + u_short sp; nat_t *ipn; mb_t *m; #if SOLARIS @@ -104,7 +104,7 @@ nat_t *nat; (tcp->th_seq != *(u_32_t *)aps->aps_data)) return 0; - off = (ip->ip_hl << 2) + (tcp->th_off << 2); + off = fin->fin_hlen + (tcp->th_off << 2); #if SOLARIS m = fin->fin_qfm; @@ -129,33 +129,33 @@ nat_t *nat; * 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); + bcopy((char *)fin, (char *)&fi, sizeof(fi)); + fi.fin_data[0] = sp; + fi.fin_data[1] = fin->fin_data[1]; + ipn = nat_outlookup(&fi, IPN_TCP, nat->nat_p, nat->nat_inip, + ip->ip_dst, 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_sport = htons(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, + ipn = nat_new(&fi, ip, nat->nat_ptr, NULL, 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); + (void) fr_addstate(ip, &fi, NULL, + FI_W_DPORT|FI_IGNOREPKT); } ip->ip_len = slen; ip->ip_src = swip; diff --git a/sys/contrib/ipfilter/netinet/ip_state.c b/sys/contrib/ipfilter/netinet/ip_state.c index 585929fd21d1..322e59f76f02 100644 --- a/sys/contrib/ipfilter/netinet/ip_state.c +++ b/sys/contrib/ipfilter/netinet/ip_state.c @@ -1,9 +1,12 @@ /* - * Copyright (C) 1995-2001 by Darren Reed. + * Copyright (C) 1995-2002 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ +#ifdef __sgi +# include +#endif #include #include #include @@ -36,7 +39,6 @@ # include #endif #include -#include #ifndef linux # include #endif @@ -78,7 +80,6 @@ #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 @@ -104,7 +105,6 @@ static const char rcsid[] = "@(#)$FreeBSD$"; #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; @@ -147,8 +147,12 @@ int fr_statemax = IPSTATE_MAX, fr_statesize = IPSTATE_SIZE; int fr_state_doflush = 0, fr_state_lock = 0; +ipstate_t *ips_list = NULL; static int icmpreplytype4[ICMP_MAXTYPE + 1]; +#ifdef USE_INET6 +static int icmpreplytype6[ICMP6_MAXTYPE + 1]; +#endif int fr_stateinit() { @@ -167,6 +171,16 @@ int fr_stateinit() icmpreplytype4[ICMP_TSTAMP] = ICMP_TSTAMPREPLY; icmpreplytype4[ICMP_IREQ] = ICMP_IREQREPLY; icmpreplytype4[ICMP_MASKREQ] = ICMP_MASKREPLY; +#ifdef USE_INET6 + /* fill icmp reply type table */ + for (i = 0; i <= ICMP6_MAXTYPE; i++) + icmpreplytype6[i] = -1; + icmpreplytype6[ICMP6_ECHO_REQUEST] = ICMP6_ECHO_REPLY; + icmpreplytype6[ICMP6_MEMBERSHIP_QUERY] = ICMP6_MEMBERSHIP_REPORT; + icmpreplytype6[ICMP6_NI_QUERY] = ICMP6_NI_REPLY; + icmpreplytype6[ND_ROUTER_SOLICIT] = ND_ROUTER_ADVERT; + icmpreplytype6[ND_NEIGHBOR_SOLICIT] = ND_NEIGHBOR_ADVERT; +#endif return 0; } @@ -186,15 +200,18 @@ static ips_stat_t *fr_statetstats() * which == 0 : flush all state table entries * which == 1 : flush TCP connections which have started to close but are * stuck for some reason. + * which == 2 : flush TCP connections which have been idle for a long time, + * starting at > 4 days idle and working back in successive half- + * days to at most 12 hours old. */ static int fr_state_flush(which) int which; { - register ipstate_t *is, **isp; + ipstate_t *is, **isp; #if defined(_KERNEL) && !SOLARIS int s; #endif - int delete, removed = 0; + int delete, removed = 0, try; SPL_NET(s); for (isp = &ips_list; (is = *isp); ) { @@ -206,6 +223,7 @@ int which; delete = 1; break; case 1 : + case 2 : if (is->is_p != IPPROTO_TCP) break; if ((is->is_state[0] != TCPS_ESTABLISHED) || @@ -227,6 +245,40 @@ int which; } else isp = &is->is_next; } + + /* + * Asked to remove inactive entries, try again if first attempt + * failed. In this case, 86400 is half a day because the counter is + * activated every half second. + */ + if ((which == 2) && (removed == 0)) { + try = 86400; /* half a day */ + for (; (try < FIVE_DAYS) && (removed == 0); try += 86400) { + for (isp = &ips_list; (is = *isp); ) { + delete = 0; + if ((is->is_p == IPPROTO_TCP) && + ((is->is_state[0] == TCPS_ESTABLISHED) || + (is->is_state[1] == TCPS_ESTABLISHED)) && + (is->is_age < try)) { + ips_stats.iss_fin++; + delete = 1; + } else if ((is->is_p != IPPROTO_TCP) && + (is->is_pkts > 1)) { + ips_stats.iss_expire++; + delete = 1; + } + if (delete) { +#ifdef IPFILTER_LOG + ipstate_log(is, ISL_FLUSH); +#endif + fr_delstate(is); + removed++; + } else + isp = &is->is_next; + } + } + } + SPL_X(s); return removed; } @@ -339,19 +391,19 @@ int mode; } +/* + * Copy out state information from the kernel to a user space process. + */ int fr_stgetent(data) caddr_t data; { register ipstate_t *is, *isn; - ipstate_save_t ips, *ipsp; + ipstate_save_t ips; int error; - error = IRCOPY(data, (caddr_t)&ipsp, sizeof(ipsp)); - if (error) - return EFAULT; - error = IRCOPY((caddr_t)ipsp, (caddr_t)&ips, sizeof(ips)); + error = IRCOPYPTR(data, (caddr_t)&ips, sizeof(ips)); if (error) - return EFAULT; + return error; isn = ips.ips_next; if (!isn) { @@ -378,7 +430,7 @@ caddr_t data; 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)); + error = IWCOPYPTR((caddr_t)&ips, data, sizeof(ips)); if (error) error = EFAULT; return error; @@ -389,16 +441,14 @@ int fr_stputent(data) caddr_t data; { register ipstate_t *is, *isn; - ipstate_save_t ips, *ipsp; - int error, out; + ipstate_save_t ips; + int error, out, i; frentry_t *fr; + char *name; - error = IRCOPY(data, (caddr_t)&ipsp, sizeof(ipsp)); - if (error) - return EFAULT; - error = IRCOPY((caddr_t)ipsp, (caddr_t)&ips, sizeof(ips)); + error = IRCOPYPTR(data, (caddr_t)&ips, sizeof(ips)); if (error) - return EFAULT; + return error; KMALLOC(isn, ipstate_t *); if (isn == NULL) @@ -417,24 +467,34 @@ caddr_t data; 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; + + /* + * Look up all the interface names in the rule. + */ + for (i = 0; i < 4; i++) { + name = fr->fr_ifnames[i]; + if ((name[1] == '\0') && + ((name[0] == '-') || (name[0] == '*'))) { + fr->fr_ifas[i] = NULL; + } else if (*name != '\0') { + fr->fr_ifas[i] = GETUNIT(name, + fr->fr_v); + if (fr->fr_ifas[i] == NULL) + fr->fr_ifas[i] = (void *)-1; + else { + strncpy(isn->is_ifname[i], + IFNAME(fr->fr_ifas[i]), + IFNAMSIZ); + } } -#endif - } else - fr->fr_ifa = NULL; + isn->is_ifp[out] = fr->fr_ifas[i]; + } + /* * send a copy back to userland of what we ended up * to allow for verification. */ - error = IWCOPY((caddr_t)&ips, ipsp, sizeof(ips)); + error = IWCOPYPTR((caddr_t)&ips, data, sizeof(ips)); if (error) { KFREE(isn); KFREE(fr); @@ -455,22 +515,34 @@ caddr_t data; } +/* + * Insert a state table entry manually. + */ void fr_stinsert(is) register ipstate_t *is; { register u_int hv = is->is_hv; + char *name; + int i; 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); + /* + * Look up all the interface names in the state entry. + */ + for (i = 0; i < 4; i++) { + name = is->is_ifname[i]; + if ((name[1] == '\0') && + ((name[0] == '-') || (name[0] == '*'))) { + is->is_ifp[0] = NULL; + } else if (*name != '\0') { + is->is_ifp[i] = GETUNIT(name, is->is_v); + if (is->is_ifp[i] == NULL) + is->is_ifp[i] = (void *)-1; + } } + /* * add into list table. */ @@ -493,16 +565,19 @@ register ipstate_t *is; /* * Create a new ipstate structure and hang it off the hash table. */ -ipstate_t *fr_addstate(ip, fin, flags) +ipstate_t *fr_addstate(ip, fin, stsave, flags) ip_t *ip; fr_info_t *fin; +ipstate_t **stsave; u_int flags; { register tcphdr_t *tcp = NULL; register ipstate_t *is; register u_int hv; + struct icmp *ic; ipstate_t ips; u_int pass; + void *ifp; int out; if (fr_state_lock || (fin->fin_off != 0) || (fin->fin_fl & FI_SHORT)) @@ -516,8 +591,6 @@ u_int flags; is = &ips; bzero((char *)is, sizeof(*is)); ips.is_age = 1; - ips.is_state[0] = 0; - ips.is_state[1] = 0; /* * Copy and calculate... */ @@ -528,14 +601,21 @@ u_int flags; 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; + if ((is->is_p == IPPROTO_ICMPV6) && + IN6_IS_ADDR_MULTICAST(&is->is_dst.in6)) { + /* + * So you can do keep state with neighbour discovery. + */ + flags |= FI_W_DADDR; + hv -= is->is_daddr; + } else { + hv += is->is_dst.i6[1]; + hv += is->is_dst.i6[2]; + hv += is->is_dst.i6[3]; } + hv += is->is_src.i6[1]; + hv += is->is_src.i6[2]; + hv += is->is_src.i6[3]; } #endif @@ -543,30 +623,35 @@ u_int flags; { #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)) + ic = (struct icmp *)fin->fin_dp; + if ((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; + 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; case ICMP6_MEMBERSHIP_QUERY : case ND_ROUTER_SOLICIT : case ND_NEIGHBOR_SOLICIT : - is->is_icmp.ics_type = ic->icmp_type + 1; + case ICMP6_NI_QUERY : + is->is_icmp.ics_type = ic->icmp_type; break; + default : + return NULL; + } + ATOMIC_INCL(ips_stats.iss_icmp); + is->is_age = fr_icmptimeout; + break; #endif + case IPPROTO_ICMP : + ic = (struct icmp *)fin->fin_dp; + + switch (ic->icmp_type) + { case ICMP_ECHO : case ICMP_TSTAMP : case ICMP_IREQ : @@ -581,9 +666,7 @@ u_int flags; 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) @@ -592,11 +675,11 @@ u_int flags; * 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; + is->is_sport = htons(fin->fin_data[0]); + is->is_dport = htons(fin->fin_data[1]); if ((flags & (FI_W_DPORT|FI_W_SPORT)) == 0) { - hv += tcp->th_dport; - hv += tcp->th_sport; + hv += is->is_sport; + hv += is->is_dport; } is->is_send = ntohl(tcp->th_seq) + fin->fin_dlen - (tcp->th_off << 2) + @@ -615,23 +698,22 @@ u_int flags; */ 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; + is->is_sport = htons(fin->fin_data[0]); + is->is_dport = htons(fin->fin_data[1]); if ((flags & (FI_W_DPORT|FI_W_SPORT)) == 0) { - hv += tcp->th_dport; - hv += tcp->th_sport; + hv += is->is_sport; + hv += is->is_dport; } ATOMIC_INCL(ips_stats.iss_udp); is->is_age = fr_udptimeout; break; - } default : - return NULL; + is->is_age = fr_udptimeout; + break; } KMALLOC(is, ipstate_t *); @@ -646,19 +728,47 @@ u_int flags; if (is->is_rule != NULL) { ATOMIC_INC32(is->is_rule->fr_ref); pass = is->is_rule->fr_flags; + is->is_frage[0] = is->is_rule->fr_age[0]; + is->is_frage[1] = is->is_rule->fr_age[1]; + if (is->is_frage[0] != 0) + is->is_age = is->is_frage[0]; + + is->is_ifp[(out << 1) + 1] = is->is_rule->fr_ifas[1]; + is->is_ifp[(1 - out) << 1] = is->is_rule->fr_ifas[2]; + is->is_ifp[((1 - out) << 1) + 1] = is->is_rule->fr_ifas[3]; + + if (((ifp = is->is_rule->fr_ifas[1]) != NULL) && + (ifp != (void *)-1)) + strncpy(is->is_ifname[(out << 1) + 1], + IFNAME(ifp), IFNAMSIZ); + if (((ifp = is->is_rule->fr_ifas[2]) != NULL) && + (ifp != (void *)-1)) + strncpy(is->is_ifname[(1 - out) << 1], + IFNAME(ifp), IFNAMSIZ); + if (((ifp = is->is_rule->fr_ifas[3]) != NULL) && + (ifp != (void *)-1)) + strncpy(is->is_ifname[((1 - out) << 1) + 1], + IFNAME(ifp), IFNAMSIZ); } else pass = fr_flags; + + is->is_ifp[out << 1] = fin->fin_ifp; + strncpy(is->is_ifname[out << 1], IFNAME(fin->fin_ifp), IFNAMSIZ); + WRITE_ENTER(&ipf_state); is->is_pass = pass; - is->is_pkts = 1; - is->is_bytes = fin->fin_dlen + fin->fin_hlen; + if ((flags & FI_IGNOREPKT) == 0) { + 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_v = fin->fin_v; + is->is_rulen = fin->fin_rule; is->is_opt = fin->fin_fi.fi_optmsk; is->is_optmsk = 0xffffffff; is->is_sec = fin->fin_fi.fi_secmsk; @@ -670,20 +780,14 @@ u_int flags; 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); + is->is_me = stsave; 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); @@ -803,19 +907,25 @@ tcphdr_t *tcp; } +/* + * Match a state table entry against an IP packet. + */ 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; + int ret = 0, rev, out, flags, idx; u_short sp, dp; void *ifp; rev = IP6NEQ(is->is_dst, dst); ifp = fin->fin_ifp; out = fin->fin_out; + flags = is->is_flags & (FI_WILDA|FI_WILDP); + sp = 0; + dp = 0; if (tcp != NULL) { flags = is->is_flags; @@ -827,44 +937,28 @@ tcphdr_t *tcp; else if (!(flags & FI_W_DPORT) && (dp != is->is_dport)) rev = 1; } - } 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; - } - } + idx = (out << 1) + rev; + + if ((is->is_ifp[idx] == NULL && + (*is->is_ifname[idx] == '\0' || *is->is_ifname[idx] == '*')) || + is->is_ifp[idx] == ifp) + ret = 1; + if (ret == 0) return 0; ret = 0; if (rev == 0) { - if ( - (IP6EQ(is->is_dst, dst) || (flags & FI_W_DADDR)) && + 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)) && + 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)))) { @@ -887,6 +981,26 @@ tcphdr_t *tcp; (fin->fin_fi.fi_auth != is->is_auth)) return 0; + flags = is->is_flags & (FI_WILDA|FI_WILDP); + if ((flags & (FI_W_SADDR|FI_W_DADDR))) { + if ((flags & FI_W_SADDR) != 0) { + if (rev == 0) { + is->is_src = fin->fin_fi.fi_src; + } else { + is->is_src = fin->fin_fi.fi_dst; + } + } else if ((flags & FI_W_DPORT) != 0) { + if (rev == 0) { + is->is_dst = fin->fin_fi.fi_dst; + } else { + is->is_dst = fin->fin_fi.fi_src; + } + } + is->is_flags &= ~(FI_W_SADDR|FI_W_DADDR); + if ((is->is_flags & (FI_WILDA|FI_WILDP)) == 0) + ips_wild--; + } + if ((flags & (FI_W_SPORT|FI_W_DPORT))) { if ((flags & FI_W_SPORT) != 0) { if (rev == 0) { @@ -913,30 +1027,14 @@ tcphdr_t *tcp; 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 (is->is_ifp[idx] == NULL && + (*is->is_ifname[idx] == '\0' || *is->is_ifname[idx] == '*')) + ret = idx; if (ret >= 0) { is->is_ifp[ret] = ifp; -#ifdef _KERNEL - strncpy(is->is_ifname[ret], IFNAME(fin->fin_ifp), + strncpy(is->is_ifname[ret], IFNAME(ifp), sizeof(is->is_ifname[ret])); -#endif } fin->fin_rev = rev; return 1; @@ -953,20 +1051,24 @@ icmphdr_t *icmp; * 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; - }; + (icmpreplytype4[is->is_type] == icmp->icmp_type))) { + if (icmp->icmp_type != ICMP_ECHOREPLY) + return 1; + if ((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; - }; + if (((icmp->icmp_type == is->is_type) || + (icmpreplytype6[is->is_type] == icmp->icmp_type))) { + if (icmp->icmp_type != ICMP6_ECHO_REPLY) + return 1; + if ((icmp->icmp_id == is->is_icmp.ics_id) && + (icmp->icmp_seq == is->is_icmp.ics_seq)) + return 1; + } } #endif return 0; @@ -998,6 +1100,7 @@ fr_info_t *fin; 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; /* @@ -1051,8 +1154,11 @@ fr_info_t *fin; */ bzero((char *)&src, sizeof(src)); bzero((char *)&dst, sizeof(dst)); + fr = NULL; - if (oip->ip_p == IPPROTO_ICMP) { + switch (oip->ip_p) + { + case IPPROTO_ICMP : icmp = (icmphdr_t *)((char *)oip + (oip->ip_hl << 2)); /* @@ -1098,15 +1204,17 @@ fr_info_t *fin; is->is_pkts++; is->is_bytes += ip->ip_len; fr = is->is_rule; - RWLOCK_EXIT(&ipf_state); - return fr; + break; } RWLOCK_EXIT(&ipf_state); + return fr; + + case IPPROTO_TCP : + case IPPROTO_UDP : + break; + default : 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; @@ -1158,15 +1266,18 @@ fr_info_t *fin; * for the accompanying state table entry. * It remains to be seen if that is correct. XXX */ - RWLOCK_EXIT(&ipf_state); - return fr; + break; } } RWLOCK_EXIT(&ipf_state); - return NULL; + return fr; } +/* + * Move a state hash table entry from its old location at is->is_hv to + * its new location, indexed by hv % fr_statesize. + */ static void fr_ipsmove(isp, is, hv) ipstate_t **isp, *is; u_int hv; @@ -1213,6 +1324,7 @@ fr_info_t *fin; struct icmp *ic; frentry_t *fr; tcphdr_t *tcp; + int rev; if (fr_state_lock || (fin->fin_off != 0) || (fin->fin_fl & FI_SHORT)) return NULL; @@ -1229,42 +1341,113 @@ fr_info_t *fin; /* * Search the hash table for matching packet header info. + * At the bottom of this switch statement, the following is expected: + * is == NULL, no lock on ipf_state is held. + * is != NULL, a lock on ipf_state is held. */ v = fin->fin_fi.fi_v; - switch (fin->fin_fi.fi_p) +#ifdef USE_INET6 + if (v == 6) { + hv += fin->fin_fi.fi_src.i6[1]; + hv += fin->fin_fi.fi_src.i6[2]; + hv += fin->fin_fi.fi_src.i6[3]; + + if ((fin->fin_p == IPPROTO_ICMPV6) && + IN6_IS_ADDR_MULTICAST(&fin->fin_fi.fi_dst.in6)) { + hv -= dst.in4.s_addr; + } else { + hv += fin->fin_fi.fi_dst.i6[1]; + hv += fin->fin_fi.fi_dst.i6[2]; + hv += fin->fin_fi.fi_dst.i6[3]; + } + } +#endif + + switch (fin->fin_p) { #ifdef USE_INET6 case IPPROTO_ICMPV6 : + tcp = NULL; + tryagain = 0; 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; } } + READ_ENTER(&ipf_state); +icmp6again: + 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, NULL) && + fr_matchicmpqueryreply(v, is, ic)) { + rev = fin->fin_rev; + if (is->is_frage[rev] != 0) + is->is_age = is->is_frage[rev]; + else if (fin->fin_rev) + is->is_age = fr_icmpacktimeout; + else + is->is_age = fr_icmptimeout; + break; + } + + if (is != NULL) { + if (tryagain && !(is->is_flags & FI_W_DADDR)) { + hv += fin->fin_fi.fi_src.i6[0]; + hv += fin->fin_fi.fi_src.i6[1]; + hv += fin->fin_fi.fi_src.i6[2]; + hv += fin->fin_fi.fi_src.i6[3]; + fr_ipsmove(isp, is, hv); + MUTEX_DOWNGRADE(&ipf_state); + } + break; + } + RWLOCK_EXIT(&ipf_state); + + /* + * No matching icmp state entry. Perhaps this is a + * response to another state entry. + */ + if ((ips_wild != 0) && (v == 6) && (tryagain == 0) && + !IN6_IS_ADDR_MULTICAST(&fin->fin_fi.fi_src.in6)) { + hv -= fin->fin_fi.fi_src.i6[0]; + hv -= fin->fin_fi.fi_src.i6[1]; + hv -= fin->fin_fi.fi_src.i6[2]; + hv -= fin->fin_fi.fi_src.i6[3]; + tryagain = 1; + WRITE_ENTER(&ipf_state); + goto icmp6again; + } + + fr = fr_checkicmp6matchingstate((ip6_t *)ip, fin); + if (fr) + return fr; + break; #endif case IPPROTO_ICMP : + tcp = NULL; if (v == 4) { hv += ic->icmp_id; hv += ic->icmp_seq; } - hv %= fr_statesize; + hvm = hv % fr_statesize; READ_ENTER(&ipf_state); - for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_hnext) { + 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, NULL) && fr_matchicmpqueryreply(v, is, ic)) { - if (fin->fin_rev) + rev = fin->fin_rev; + if (is->is_frage[rev] != 0) + is->is_age = is->is_frage[rev]; + else if (fin->fin_rev) is->is_age = fr_icmpacktimeout; else is->is_age = fr_icmptimeout; break; } - } + if (is != NULL) break; RWLOCK_EXIT(&ipf_state); @@ -1272,28 +1455,21 @@ fr_info_t *fin; * 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); + 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)) + if ((tcp->th_flags & TH_RST) && + ((tcp->th_flags & (TH_FIN|TH_SYN|TH_RST)) != TH_RST)) break; case IPPROTO_UDP : + { + register u_short dport, sport; + dport = tcp->th_dport; sport = tcp->th_sport; tryagain = 0; @@ -1305,12 +1481,15 @@ retry_tcpudp: 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)) { + rev = fin->fin_rev; if ((pr == IPPROTO_TCP)) { if (!fr_tcpstate(is, fin, ip, tcp)) { continue; } } else if ((pr == IPPROTO_UDP)) { - if (fin->fin_rev) + if (is->is_frage[rev] != 0) + is->is_age = is->is_frage[rev]; + else if (fin->fin_rev) is->is_age = fr_udpacktimeout; else is->is_age = fr_udptimeout; @@ -1338,47 +1517,74 @@ retry_tcpudp: break; } default : + tcp = NULL; + 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)) { + rev = fin->fin_rev; + if (is->is_frage[rev] != 0) + is->is_age = is->is_frage[rev]; + else + is->is_age = fr_udptimeout; + break; + } + } + if (is == NULL) { + RWLOCK_EXIT(&ipf_state); + } 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_rule = is->is_rulen; + if (fr != NULL) { + fin->fin_group = fr->fr_group; + fin->fin_icode = fr->fr_icode; + } fin->fin_fr = fr; pass = is->is_pass; + RWLOCK_EXIT(&ipf_state); + if ((fin->fin_fl & FI_FRAG) && (pass & FR_KEEPFRAG)) + ipfr_newfrag(ip, fin, pass ^ FR_KEEPSTATE); #ifndef _KERNEL - if (tcp->th_flags & TCP_CLOSE) + if ((tcp != NULL) && (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; } +/* + * Sync. state entries. If interfaces come or go or just change position, + * this is needed. + */ void ip_statesync(ifp) void *ifp; { register ipstate_t *is; + int i; 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; + for (i = 0; i < 4; i++) { + if (is->is_ifp[i] == ifp) { + is->is_ifpin = GETUNIT(is->is_ifname[i], + is->is_v); + if (!is->is_ifp[i]) + is->is_ifp[i] = (void *)-1; + } } } RWLOCK_EXIT(&ipf_state); @@ -1403,6 +1609,8 @@ ipstate_t *is; *is->is_phnext = is->is_hnext; if (ips_table[is->is_hv] == NULL) ips_stats.iss_inuse--; + if (is->is_me) + *is->is_me = NULL; fr = is->is_rule; if (fr != NULL) { @@ -1464,7 +1672,7 @@ void fr_timeoutstate() } else isp = &is->is_next; if (fr_state_doflush) { - (void) fr_state_flush(1); + (void) fr_state_flush(2); fr_state_doflush = 0; } RWLOCK_EXIT(&ipf_state); @@ -1548,8 +1756,11 @@ int dir; */ 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; + if (state[1 - dir] == TCPS_CLOSED || + state[1 - dir] == TCPS_ESTABLISHED) { + state[dir] = TCPS_ESTABLISHED; + *age = fr_tcpidletimeout; + } } /* * TODO: besides regular ACK packets we can have other @@ -1738,9 +1949,11 @@ u_int type; ipsl.isl_state[0] = is->is_state[0]; ipsl.isl_state[1] = is->is_state[1]; } - } else if (ipsl.isl_p == IPPROTO_ICMP) + } else if (ipsl.isl_p == IPPROTO_ICMP) { + ipsl.isl_itype = is->is_icmp.ics_type; + } else if (ipsl.isl_p == IPPROTO_ICMPV6) { ipsl.isl_itype = is->is_icmp.ics_type; - else { + } else { ipsl.isl_ps.isl_filler[0] = 0; ipsl.isl_ps.isl_filler[1] = 0; } @@ -1893,10 +2106,6 @@ fr_info_t *fin; 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; /* diff --git a/sys/contrib/ipfilter/netinet/ip_state.h b/sys/contrib/ipfilter/netinet/ip_state.h index c4bf0d9a677a..a645868af7d7 100644 --- a/sys/contrib/ipfilter/netinet/ip_state.h +++ b/sys/contrib/ipfilter/netinet/ip_state.h @@ -58,17 +58,20 @@ typedef struct ipstate { struct ipstate **is_pnext; struct ipstate *is_hnext; struct ipstate **is_phnext; + struct ipstate **is_me; u_long is_age; + u_int is_frage[2]; /* age from filter rule, forward & reverse */ u_int is_pass; U_QUAD_T is_pkts; U_QUAD_T is_bytes; - void *is_ifp[2]; + void *is_ifp[4]; 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_rulen; /* rule number */ u_32_t is_flags; u_32_t is_opt; /* packet options set */ u_32_t is_optmsk; /* " " mask */ @@ -81,7 +84,7 @@ typedef struct ipstate { tcpstate_t is_ts; udpstate_t is_us; } is_ps; - char is_ifname[2][IFNAMSIZ]; + char is_ifname[4][IFNAMSIZ]; #if SOLARIS || defined(__sgi) kmutex_t is_lock; #endif @@ -104,7 +107,7 @@ typedef struct ipstate { #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 is_ifpout is_ifp[2] #define TH_OPENING (TH_SYN|TH_ACK) /* @@ -178,12 +181,15 @@ extern u_long fr_tcptimeout; extern u_long fr_tcpclosed; extern u_long fr_tcphalfclosed; extern u_long fr_udptimeout; +extern u_long fr_udpacktimeout; extern u_long fr_icmptimeout; +extern u_long fr_icmpacktimeout; +extern ipstate_t *ips_list; 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 ipstate_t *fr_addstate __P((ip_t *, fr_info_t *, ipstate_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)); diff --git a/sys/contrib/ipfilter/netinet/ipl.h b/sys/contrib/ipfilter/netinet/ipl.h index bd03794c2c4e..fdb289a85591 100644 --- a/sys/contrib/ipfilter/netinet/ipl.h +++ b/sys/contrib/ipfilter/netinet/ipl.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 1993-2002 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * @@ -10,6 +10,6 @@ #ifndef __IPL_H__ #define __IPL_H__ -#define IPL_VERSION "IP Filter: v3.4.20" +#define IPL_VERSION "IP Filter: v3.4.25" #endif diff --git a/sys/contrib/ipfilter/netinet/mlfk_ipl.c b/sys/contrib/ipfilter/netinet/mlfk_ipl.c index 2a51d7dc002a..a9386c44e4e6 100644 --- a/sys/contrib/ipfilter/netinet/mlfk_ipl.c +++ b/sys/contrib/ipfilter/netinet/mlfk_ipl.c @@ -76,8 +76,12 @@ SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RW, &fr_tcphalfclosed, 0, ""); SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RW, &fr_udptimeout, 0, ""); +SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_udpacktimeout, CTLFLAG_RW, + &fr_udpacktimeout, 0, ""); SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RW, &fr_icmptimeout, 0, ""); +SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_icmpacktimeout, CTLFLAG_RW, + &fr_icmpacktimeout, 0, ""); SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_defnatage, CTLFLAG_RW, &fr_defnatage, 0, ""); SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_ipfrttl, CTLFLAG_RW, -- cgit v1.2.3