From 76531d9f8d54be5c8da482dd6dc247802c602ae9 Mon Sep 17 00:00:00 2001 From: Darren Reed Date: Tue, 19 Mar 2002 11:30:23 +0000 Subject: [PATCH 1/3] Import IPFilter 3.4.25 (last version 3.4.20) --- sys/contrib/ipfilter/netinet/fil.c | 202 +++--- sys/contrib/ipfilter/netinet/ip_auth.c | 18 +- sys/contrib/ipfilter/netinet/ip_auth.h | 5 +- sys/contrib/ipfilter/netinet/ip_compat.h | 466 ++++++++++++-- sys/contrib/ipfilter/netinet/ip_fil.c | 584 +++++++++++++---- sys/contrib/ipfilter/netinet/ip_fil.h | 89 +-- sys/contrib/ipfilter/netinet/ip_frag.c | 21 +- sys/contrib/ipfilter/netinet/ip_frag.h | 18 +- sys/contrib/ipfilter/netinet/ip_ftp_pxy.c | 156 +++-- sys/contrib/ipfilter/netinet/ip_log.c | 76 +-- sys/contrib/ipfilter/netinet/ip_nat.c | 468 ++++++++------ sys/contrib/ipfilter/netinet/ip_nat.h | 22 +- sys/contrib/ipfilter/netinet/ip_proxy.c | 143 ++++- sys/contrib/ipfilter/netinet/ip_proxy.h | 24 +- sys/contrib/ipfilter/netinet/ip_raudio_pxy.c | 17 +- sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c | 24 +- sys/contrib/ipfilter/netinet/ip_state.c | 619 +++++++++++++------ sys/contrib/ipfilter/netinet/ip_state.h | 18 +- sys/contrib/ipfilter/netinet/ipl.h | 6 +- sys/contrib/ipfilter/netinet/mlfk_ipl.c | 6 +- 20 files changed, 2095 insertions(+), 887 deletions(-) diff --git a/sys/contrib/ipfilter/netinet/fil.c b/sys/contrib/ipfilter/netinet/fil.c index c4cd2e041168..06623c357ebb 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 @@ -95,7 +97,7 @@ #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[] = "@(#)$Id: fil.c,v 2.35.2.58 2002/03/13 02:23:13 darrenr Exp $"; #endif #ifndef _KERNEL @@ -105,7 +107,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) @@ -260,7 +262,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) @@ -280,7 +282,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 : @@ -380,6 +382,19 @@ fr_info_t *fin; 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; } @@ -545,8 +560,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; @@ -554,20 +569,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; } @@ -578,25 +594,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; @@ -618,22 +637,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; @@ -642,23 +658,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; @@ -667,14 +679,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; } @@ -701,17 +711,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) @@ -722,32 +745,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; } @@ -803,7 +827,7 @@ int out; /* * disable delayed checksums. */ - if (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; } @@ -844,6 +868,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 : /* @@ -906,20 +933,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) { @@ -1010,6 +1043,7 @@ int out; FI_COPYSIZE); if (pass & FR_NOMATCH) { ATOMIC_INCL(frstats[out].fr_nom); + fin->fin_fr = NULL; } } } else @@ -1023,11 +1057,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; @@ -1057,7 +1087,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); @@ -1086,11 +1116,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; @@ -1134,10 +1172,10 @@ int out; # 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 @@ -1154,7 +1192,6 @@ int out; * some operating systems. */ if (!out) { -#ifdef _KERNEL if (pass & FR_RETICMP) { int dst; @@ -1170,19 +1207,6 @@ int out; 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; @@ -1207,8 +1231,10 @@ int out; 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); @@ -1243,6 +1269,12 @@ int out; 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 */ } @@ -1464,7 +1496,7 @@ tcphdr_t *tcp; * 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 b22d470b6095..e4ad347280c7 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 @@ -102,7 +104,7 @@ extern struct ifqueue ipintrq; /* ip packet input queue */ #endif #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_auth.c,v 2.11.2.12 2001/07/18 14:57:08 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_auth.c,v 2.11.2.17 2002/03/06 09:44:10 darrenr Exp $"; #endif @@ -305,7 +307,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; @@ -377,9 +379,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; @@ -453,7 +453,7 @@ frentry_t *fr, **frptr; 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 @@ -478,7 +478,9 @@ frentry_t *fr, **frptr; error = ENOBUFS; } else { IF_ENQUEUE(ifq, m); +# if IRIX < 605 schednetisr(NETISR_IP); +# endif } # endif /* SOLARIS */ if (error) @@ -526,7 +528,6 @@ frentry_t *fr, **frptr; } -#ifdef _KERNEL /* * Free all network buffer memory used to keep saved packets. */ @@ -587,7 +588,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 +627,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 7d3e46316d10..cb168c4ca959 100644 --- a/sys/contrib/ipfilter/netinet/ip_auth.h +++ b/sys/contrib/ipfilter/netinet/ip_auth.h @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ip_auth.h,v 2.3.2.4 2001/07/18 14:57:08 darrenr Exp $ + * $Id: ip_auth.h,v 2.3.2.5 2001/11/04 13:15:51 darrenr Exp $ * */ #ifndef __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 a7d0db4f07a8..4eab541231a6 100644 --- a/sys/contrib/ipfilter/netinet/ip_compat.h +++ b/sys/contrib/ipfilter/netinet/ip_compat.h @@ -4,7 +4,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_compat.h 1.8 1/14/96 - * $Id: ip_compat.h,v 2.26.2.17 2001/07/23 04:22:48 darrenr Exp $ + * $Id: ip_compat.h,v 2.26.2.39 2002/03/13 03:54:34 darrenr Exp $ */ #ifndef __IP_COMPAT_H__ @@ -25,13 +25,20 @@ #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__) @@ -62,6 +69,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 @@ -76,12 +95,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 @@ -137,12 +181,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) @@ -210,6 +256,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; @@ -225,6 +272,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)) @@ -325,6 +380,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 @@ -506,11 +576,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) */ @@ -542,7 +620,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)++ @@ -564,40 +642,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 @@ -606,39 +662,153 @@ 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_TSTAMP -# define ICMP_TSTAMP ICMP_TIMESTAMP -#endif -#ifndef ICMP_TSTAMPREPLY -# define ICMP_TSTAMPREPLY ICMP_TIMESTAMPREPLY -#endif -#ifndef ICMP_IREQ -# define ICMP_IREQ ICMP_INFO_REQUEST -#endif -#ifndef ICMP_IREQREPLY -# define ICMP_IREQREPLY ICMP_INFO_REPLY -#endif -#ifndef ICMP_MASKREQ -# define ICMP_MASKREQ ICMP_ADDRESS -#endif -#ifndef ICMP_MASKREPLY -# define ICMP_MASKREPLY ICMP_ADDRESSREPLY +#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 13 +#endif +#ifndef ICMP_TSTAMPREPLY +# define ICMP_TSTAMPREPLY 14 +#endif +#ifndef ICMP_IREQ +# define ICMP_IREQ 15 +#endif +#ifndef ICMP_IREQREPLY +# define ICMP_IREQREPLY 16 +#endif +#ifndef ICMP_MASKREQ +# define ICMP_MASKREQ 17 +#endif +#ifndef ICMP_MASKREPLY +# define ICMP_MASKREPLY 18 +#endif +#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 #endif @@ -726,6 +896,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 @@ -997,6 +1176,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 @@ -1016,9 +1199,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 e15ff67b6534..1cac072015e6 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil.c +++ b/sys/contrib/ipfilter/netinet/ip_fil.c @@ -16,7 +16,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) @@ -24,6 +24,9 @@ # include # endif #endif +#ifdef __sgi +# include +#endif #ifndef _KERNEL # include # include @@ -44,7 +47,6 @@ #ifdef _KERNEL # include #endif -#include #if !SOLARIS # if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000) # include @@ -93,12 +95,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 @@ -113,7 +119,7 @@ extern int ip_optcopy __P((struct ip *, struct ip *)); #if !defined(lint) static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.42.2.34 2001/07/23 13:49:57 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.42.2.53 2002/03/13 02:29:08 darrenr Exp $"; #endif @@ -144,15 +150,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 *, @@ -208,6 +217,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) @@ -228,19 +308,32 @@ 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; # if defined(__sgi) || (defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000)) 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)) { @@ -267,8 +360,24 @@ int iplattach() # ifdef NETBSD_PF # if __NetBSD_Version__ >= 104200000 +# 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; @@ -284,11 +393,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(); @@ -355,11 +475,21 @@ int iplattach() * 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) 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 @@ -397,8 +527,16 @@ int ipldetach() # ifdef NETBSD_PF # if __NetBSD_Version__ >= 104200000 +# 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; @@ -407,8 +545,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; @@ -530,7 +676,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; @@ -542,9 +688,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; } @@ -711,11 +865,11 @@ caddr_t data; { register frentry_t *fp, *f, **fprev; register frentry_t **ftail; + frgroup_t *fg = NULL; + int error = 0, in, i; + u_int *p, *pp; frentry_t frd; frdest_t *fdp; - frgroup_t *fg = NULL; - u_int *p, *pp; - int error = 0, in; u_int group; fp = &frd; @@ -764,18 +918,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; + 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; + } } -#if BSD >= 199306 - if (*fp->fr_oifname) { - fp->fr_oifa = GETUNIT(fp->fr_oifname, fp->fr_v); - if (!fp->fr_oifa) - fp->fr_oifa = (void *)-1; - } -#endif fdp = &fp->fr_dif; fp->fr_flags &= ~FR_DUP; @@ -854,6 +1007,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); } @@ -1002,7 +1156,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); @@ -1044,7 +1198,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; @@ -1053,17 +1207,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; @@ -1079,20 +1241,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; } @@ -1266,7 +1430,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) @@ -1279,7 +1443,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)); @@ -1291,21 +1456,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 } @@ -1323,6 +1502,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: @@ -1336,13 +1533,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 @@ -1354,35 +1552,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", @@ -1391,13 +1580,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 @@ -1418,26 +1603,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)) { @@ -1447,44 +1642,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) { - ip->ip_id = ntohs(ip->ip_id); - 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 @@ -1554,9 +1744,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; @@ -1576,7 +1764,7 @@ frdest_t *fdp; 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 @@ -1593,13 +1781,13 @@ frdest_t *fdp; 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; @@ -1613,6 +1801,10 @@ frdest_t *fdp; } +/* + * 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; @@ -1622,6 +1814,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__) && \ @@ -1651,10 +1846,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 @@ -1667,7 +1930,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 @@ -1702,26 +1965,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; - } -# else - char ifname[32], *s; for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) { - (void) sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit); - if (!strcmp(name, ifname)) +# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ + (defined(OpenBSD) && (OpenBSD >= 199603)) + if (!strncmp(ifname, ifp->if_xname, sizeof(ifp->if_xname))) +# else + char fullname[LIFNAMSIZ]; + + 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); @@ -1754,20 +2030,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; @@ -1807,27 +2082,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; } @@ -1836,4 +2106,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 6d51ced5e0ae..96a8f4bb8c6e 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil.h +++ b/sys/contrib/ipfilter/netinet/ip_fil.h @@ -1,10 +1,10 @@ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 1993-2002 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_fil.h 1.35 6/5/96 - * $Id: ip_fil.h,v 2.29.2.10 2001/07/15 13:51:42 darrenr Exp $ + * $Id: ip_fil.h,v 2.29.2.29 2002/03/13 03:56:46 darrenr Exp $ */ #ifndef __IP_FIL_H__ @@ -34,6 +34,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 *) @@ -51,8 +55,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 *) @@ -76,8 +80,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 *) @@ -123,7 +127,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' */ @@ -135,10 +141,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 */ @@ -146,19 +154,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 @@ -167,13 +177,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 >< */ @@ -198,10 +211,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 @@ -218,6 +228,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 */ @@ -227,10 +238,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 */ @@ -252,10 +260,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)) /* @@ -268,8 +277,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 */ @@ -283,8 +292,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 */ @@ -406,15 +415,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 */ @@ -422,7 +432,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; @@ -485,10 +496,11 @@ typedef struct ipflog { #ifndef _KERNEL +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__) || \ @@ -506,11 +518,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 @@ -593,6 +600,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 b0e63a9f7551..abc0faa8d72a 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" @@ -89,7 +90,7 @@ extern struct timeout ipfr_slowtimer_ch; #if !defined(lint) static const char sccsid[] = "@(#)ip_frag.c 1.11 3/24/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_frag.c,v 2.10.2.14 2001/07/15 22:06:15 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_frag.c,v 2.10.2.20 2002/03/06 09:44:11 darrenr Exp $"; #endif @@ -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 446510f0e965..03f41f8d04cd 100644 --- a/sys/contrib/ipfilter/netinet/ip_frag.h +++ b/sys/contrib/ipfilter/netinet/ip_frag.h @@ -4,7 +4,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_frag.h 1.5 3/24/96 - * $Id: ip_frag.h,v 2.4.2.5 2001/06/26 10:43:13 darrenr Exp $ + * $Id: ip_frag.h,v 2.4.2.6 2002/01/01 15:09:38 darrenr Exp $ */ #ifndef __IP_FRAG_H__ @@ -56,14 +56,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 830a4f66c9ec..0968b1055dc9 100644 --- a/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c +++ b/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c @@ -2,7 +2,7 @@ * Simple FTP transparent proxy for in-kernel use. For use with the NAT * code. * - * $Id: ip_ftp_pxy.c,v 2.7.2.26 2001/07/15 13:50:54 darrenr Exp $ + * $Id: ip_ftp_pxy.c,v 2.7.2.33 2002/02/15 14:48:38 darrenr Exp $ */ #if SOLARIS && defined(_KERNEL) extern kmutex_t ipf_rw; @@ -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,22 +620,7 @@ size_t len; c = *s++; i--; - if (isdigit(c)) { - c = *s++; - i--; - if (isdigit(c)) { - c = *s++; - i--; - if (isdigit(c)) { - c = *s++; - i--; - if ((c != '-') && (c != ' ')) - return 1; - } else - return 1; - } else - return 1; - } else if (isalpha(c)) { + if (isalpha(c)) { c = *s++; i--; if (isalpha(c)) { @@ -660,6 +651,60 @@ size_t len; } +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 (isdigit(c)) { + c = *s++; + i--; + if (isdigit(c)) { + c = *s++; + i--; + if ((c != '-') && (c != ' ')) + return 1; + } else + return 1; + } else + return 1; + } else + return 1; + for (; i; i--) { + c = *s++; + if (c == '\n') + return 0; + } + return 2; +} + + +int ippr_ftp_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 5968f46ad4b0..e56c60262460 100644 --- a/sys/contrib/ipfilter/netinet/ip_log.c +++ b/sys/contrib/ipfilter/netinet/ip_log.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ip_log.c,v 2.5.2.5 2001/06/26 10:43:14 darrenr Exp $ + * $Id: ip_log.c,v 2.5.2.17 2002/03/13 03:57:05 darrenr Exp $ */ #include #if defined(KERNEL) && !defined(_KERNEL) @@ -52,7 +52,6 @@ # if defined(_KERNEL) # include # endif -# include # if !SOLARIS # if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000) # include @@ -63,13 +62,14 @@ # else # include # include -# include -# include -# include # include -# include -# include -# include +# ifdef _KERNEL +# include +# include +# include +# include +# include +# endif # endif # include # include @@ -104,11 +104,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 @@ -116,6 +111,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) @@ -168,7 +167,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; @@ -215,9 +214,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)) || \ @@ -225,10 +226,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 @@ -241,10 +240,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 ? */ @@ -289,20 +289,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]; /* @@ -330,23 +330,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); @@ -358,12 +363,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; } @@ -388,7 +393,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; /* @@ -430,15 +435,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; @@ -467,7 +471,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 eb6e133bfc0f..5c10bc4ba3f3 100644 --- a/sys/contrib/ipfilter/netinet/ip_nat.c +++ b/sys/contrib/ipfilter/netinet/ip_nat.c @@ -9,6 +9,9 @@ #define _KERNEL #endif +#ifdef __sgi +# include +#endif #include #include #include @@ -30,7 +33,6 @@ # include #endif #include -#include #ifndef linux # include #endif @@ -92,10 +94,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 @@ -107,7 +109,7 @@ extern struct ifnet vpnif; #if !defined(lint) static const char sccsid[] = "@(#)ip_nat.c 1.11 6/5/96 (C) 1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_nat.c,v 2.37.2.44 2001/07/21 07:17:22 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_nat.c,v 2.37.2.63 2002/03/06 09:44:11 darrenr Exp $"; #endif nat_t **nat_table[2] = { NULL, NULL }, @@ -133,7 +135,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 *)); @@ -142,7 +143,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)); @@ -501,7 +502,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; @@ -900,7 +901,9 @@ caddr_t data; nat->nat_aps = NULL; in = nat->nat_ptr; 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 @@ -922,7 +925,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); } } @@ -1015,6 +1018,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); @@ -1054,6 +1059,7 @@ struct nat *natd; /* * nat_flushtable - clear the NAT table of all mapping entries. + * (this is for the dynamic mappings) */ static int nat_flushtable() { @@ -1086,8 +1092,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; @@ -1118,22 +1125,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 @@ -1141,8 +1151,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 */ @@ -1182,7 +1192,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)) { @@ -1206,7 +1216,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; @@ -1239,7 +1249,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))) @@ -1261,7 +1271,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); @@ -1301,9 +1311,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 @@ -1320,14 +1336,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) { @@ -1367,27 +1383,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) { @@ -1405,8 +1420,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); @@ -1416,9 +1431,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); @@ -1429,15 +1444,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; @@ -1451,6 +1464,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); @@ -1465,6 +1485,10 @@ int direction; } +/* + * 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; { @@ -1492,10 +1516,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]; @@ -1581,25 +1605,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); } @@ -1619,7 +1654,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; @@ -1628,6 +1663,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; @@ -1917,23 +1954,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); @@ -1943,19 +1989,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); } @@ -1964,8 +2025,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 || @@ -1973,7 +2032,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; } } @@ -1989,21 +2048,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 @@ -2045,23 +2101,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); @@ -2072,19 +2134,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); } @@ -2093,8 +2170,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) || @@ -2102,7 +2177,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; } } @@ -2119,16 +2194,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; } @@ -2146,7 +2224,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))) @@ -2196,6 +2274,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; @@ -2203,15 +2282,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; @@ -2220,27 +2301,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); @@ -2249,13 +2331,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); @@ -2271,22 +2355,13 @@ fr_info_t *fin; 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)) { @@ -2308,7 +2383,14 @@ fr_info_t *fin; 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); @@ -2320,16 +2402,16 @@ fr_info_t *fin; 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); @@ -2337,16 +2419,19 @@ fr_info_t *fin; 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, @@ -2366,25 +2451,24 @@ fr_info_t *fin; 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) @@ -2393,9 +2477,11 @@ fr_info_t *fin; 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; } @@ -2423,37 +2509,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); @@ -2462,19 +2547,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) { @@ -2482,11 +2569,10 @@ fr_info_t *fin; 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; @@ -2512,8 +2598,8 @@ fr_info_t *fin; 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); @@ -2522,9 +2608,14 @@ fr_info_t *fin; } 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); @@ -2535,7 +2626,7 @@ fr_info_t *fin; * 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 @@ -2543,12 +2634,12 @@ fr_info_t *fin; #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, @@ -2568,21 +2659,20 @@ fr_info_t *fin; 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]); @@ -2757,3 +2847,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 f712dfcd9c5e..4b2acc485283 100644 --- a/sys/contrib/ipfilter/netinet/ip_nat.h +++ b/sys/contrib/ipfilter/netinet/ip_nat.h @@ -4,7 +4,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_nat.h 1.5 2/4/96 - * $Id: ip_nat.h,v 2.17.2.20 2001/06/26 10:43:15 darrenr Exp $ + * $Id: ip_nat.h,v 2.17.2.25 2002/01/01 15:10:49 darrenr Exp $ */ #ifndef __IP_NAT_H__ @@ -88,6 +88,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]; @@ -118,6 +119,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 */ @@ -286,23 +288,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 325f36259ec2..a4ce80a5da97 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. */ @@ -7,6 +7,9 @@ # define _KERNEL #endif +#ifdef __sgi +# include +#endif #include #include #include @@ -16,7 +19,6 @@ # include #endif #include -#include #if !defined(_KERNEL) && !defined(KERNEL) # include # include @@ -65,34 +67,38 @@ #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 #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_proxy.c,v 2.9.2.6 2001/07/15 22:06:15 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_proxy.c,v 2.9.2.21 2002/03/06 09:44:14 darrenr Exp $"; #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; @@ -100,20 +106,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 - { NULL, "", '\0', 0, 0, NULL, NULL } +#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 +#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; { @@ -125,7 +150,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))) @@ -136,6 +161,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; { @@ -143,15 +173,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; @@ -160,34 +194,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; @@ -195,13 +259,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; } @@ -225,9 +294,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) { @@ -263,8 +329,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)); @@ -283,7 +354,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; { @@ -317,6 +391,7 @@ void aps_free(aps) ap_session_t *aps; { ap_session_t *a, **ap; + aproxy_t *apr; if (!aps) return; @@ -327,6 +402,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); @@ -432,6 +511,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; @@ -446,6 +529,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 b8c8eb086cae..0f1ab8469b2d 100644 --- a/sys/contrib/ipfilter/netinet/ip_proxy.h +++ b/sys/contrib/ipfilter/netinet/ip_proxy.h @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ip_proxy.h,v 2.8.2.7 2001/06/26 10:43:16 darrenr Exp $ + * $Id: ip_proxy.h,v 2.8.2.12 2002/01/01 13:41:43 darrenr Exp $ */ #ifndef __IP_PROXY_H__ @@ -74,10 +74,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 @@ -96,6 +98,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; @@ -108,7 +111,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; @@ -136,6 +139,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; @@ -147,9 +163,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 476e15949f35..ddd5ea3014b4 100644 --- a/sys/contrib/ipfilter/netinet/ip_raudio_pxy.c +++ b/sys/contrib/ipfilter/netinet/ip_raudio_pxy.c @@ -1,5 +1,5 @@ /* - * $Id: ip_raudio_pxy.c,v 1.7.2.6 2001/07/23 04:17:56 darrenr Exp $ + * $Id: ip_raudio_pxy.c,v 1.7.2.8 2002/01/13 04:58:29 darrenr Exp $ */ #if SOLARIS && defined(_KERNEL) extern kmutex_t ipf_rw; @@ -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 d017cf94c1d6..641d303c023e 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 @@ -82,10 +82,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 @@ -103,7 +103,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; @@ -128,33 +128,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 649ad939ddf8..255bdad61f75 100644 --- a/sys/contrib/ipfilter/netinet/ip_state.c +++ b/sys/contrib/ipfilter/netinet/ip_state.c @@ -1,8 +1,11 @@ /* - * 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 @@ -35,7 +38,6 @@ # include #endif #include -#include #ifndef linux # include #endif @@ -77,7 +79,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 @@ -92,7 +93,7 @@ #if !defined(lint) static const char sccsid[] = "@(#)ip_state.c 1.8 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_state.c,v 2.30.2.38 2001/07/23 13:49:46 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_state.c,v 2.30.2.61 2002/03/06 14:07:36 darrenr Exp $"; #endif #ifndef MIN @@ -102,7 +103,6 @@ static const char rcsid[] = "@(#)$Id: ip_state.c,v 2.30.2.38 2001/07/23 13:49:46 #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; @@ -145,8 +145,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() { @@ -165,6 +169,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; } @@ -184,15 +198,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); ) { @@ -204,6 +221,7 @@ int which; delete = 1; break; case 1 : + case 2 : if (is->is_p != IPPROTO_TCP) break; if ((is->is_state[0] != TCPS_ESTABLISHED) || @@ -225,6 +243,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; } @@ -337,19 +389,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)); + error = IRCOPYPTR(data, (caddr_t)&ips, sizeof(ips)); if (error) - return EFAULT; - error = IRCOPY((caddr_t)ipsp, (caddr_t)&ips, sizeof(ips)); - if (error) - return EFAULT; + return error; isn = ips.ips_next; if (!isn) { @@ -376,7 +428,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; @@ -387,16 +439,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)); + error = IRCOPYPTR(data, (caddr_t)&ips, sizeof(ips)); if (error) - return EFAULT; - error = IRCOPY((caddr_t)ipsp, (caddr_t)&ips, sizeof(ips)); - if (error) - return EFAULT; + return error; KMALLOC(isn, ipstate_t *); if (isn == NULL) @@ -415,24 +465,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); @@ -453,22 +513,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. */ @@ -491,16 +563,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)) @@ -514,8 +589,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... */ @@ -526,14 +599,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 @@ -541,30 +621,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 : @@ -579,9 +664,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) @@ -590,11 +673,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) + @@ -613,23 +696,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 *); @@ -644,19 +726,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; @@ -668,20 +778,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); @@ -801,19 +905,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; @@ -825,44 +935,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)))) { @@ -885,6 +979,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) { @@ -911,30 +1025,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; @@ -951,20 +1049,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; @@ -996,6 +1098,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; /* @@ -1049,8 +1152,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)); /* @@ -1096,15 +1202,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; @@ -1156,15 +1264,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; @@ -1211,6 +1322,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; @@ -1227,42 +1339,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; } } -#endif - case IPPROTO_ICMP : - if (v == 4) { - hv += ic->icmp_id; - hv += ic->icmp_seq; - } - hv %= fr_statesize; READ_ENTER(&ipf_state); - for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_hnext) { +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)) { - 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) { + 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; + } + hvm = hv % fr_statesize; + READ_ENTER(&ipf_state); + 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) break; RWLOCK_EXIT(&ipf_state); @@ -1270,28 +1453,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; @@ -1303,12 +1479,15 @@ fr_info_t *fin; 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; @@ -1336,47 +1515,74 @@ fr_info_t *fin; 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; -#ifndef _KERNEL - if (tcp->th_flags & TCP_CLOSE) - fr_delstate(is); -#endif RWLOCK_EXIT(&ipf_state); if ((fin->fin_fl & FI_FRAG) && (pass & FR_KEEPFRAG)) ipfr_newfrag(ip, fin, pass ^ FR_KEEPSTATE); +#ifndef _KERNEL + if ((tcp != NULL) && (tcp->th_flags & TCP_CLOSE)) + fr_delstate(is); +#endif 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); @@ -1401,6 +1607,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) { @@ -1462,7 +1670,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); @@ -1546,8 +1754,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 @@ -1736,9 +1947,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 { + } else if (ipsl.isl_p == IPPROTO_ICMPV6) { + ipsl.isl_itype = is->is_icmp.ics_type; + } else { ipsl.isl_ps.isl_filler[0] = 0; ipsl.isl_ps.isl_filler[1] = 0; } @@ -1891,10 +2104,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 b940d774ade6..fe6a505fe66d 100644 --- a/sys/contrib/ipfilter/netinet/ip_state.h +++ b/sys/contrib/ipfilter/netinet/ip_state.h @@ -4,7 +4,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_state.h 1.3 1/12/96 (C) 1995 Darren Reed - * $Id: ip_state.h,v 2.13.2.4 2001/06/26 10:43:17 darrenr Exp $ + * $Id: ip_state.h,v 2.13.2.10 2002/03/06 14:07:38 darrenr Exp $ */ #ifndef __IP_STATE_H__ #define __IP_STATE_H__ @@ -57,17 +57,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 */ @@ -80,7 +83,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 @@ -103,7 +106,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) /* @@ -177,12 +180,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 472bcce2f4f0..75f9d67efaf2 100644 --- a/sys/contrib/ipfilter/netinet/ipl.h +++ b/sys/contrib/ipfilter/netinet/ipl.h @@ -1,15 +1,15 @@ /* - * Copyright (C) 1993-2001 by Darren Reed. + * Copyright (C) 1993-2002 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ipl.h 1.21 6/5/96 - * $Id: ipl.h,v 2.15.2.23 2001/07/23 13:52:10 darrenr Exp $ + * $Id: ipl.h,v 2.15.2.31 2002/03/13 03:57:42 darrenr Exp $ */ #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 0dc4ff202723..f33de37f30ab 100644 --- a/sys/contrib/ipfilter/netinet/mlfk_ipl.c +++ b/sys/contrib/ipfilter/netinet/mlfk_ipl.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: mlfk_ipl.c,v 2.1.2.6 2000/11/18 03:58:29 darrenr Exp $ + * $Id: mlfk_ipl.c,v 2.1.2.7 2001/08/27 21:14:04 darrenr Exp $ */ @@ -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, From 13114a18aca46dd02874c48e043dd8c043b5b8fa Mon Sep 17 00:00:00 2001 From: Darren Reed Date: Thu, 25 Apr 2002 03:23:52 +0000 Subject: [PATCH 2/3] Import IPFilter 3.4.26 kernel sources, including H.323 proxy. Include the licence file for both IPFilter and the H.323 proxy (from QNX), for convienence. --- sys/contrib/ipfilter/netinet/IPFILTER.LICENCE | 5 +- sys/contrib/ipfilter/netinet/fil.c | 9 +- sys/contrib/ipfilter/netinet/ip_auth.c | 8 +- sys/contrib/ipfilter/netinet/ip_compat.h | 82 ++++--- sys/contrib/ipfilter/netinet/ip_fil.c | 11 +- sys/contrib/ipfilter/netinet/ip_fil.h | 27 ++- sys/contrib/ipfilter/netinet/ip_frag.c | 4 +- sys/contrib/ipfilter/netinet/ip_h323_pxy.c | 40 +++- sys/contrib/ipfilter/netinet/ip_log.c | 3 +- sys/contrib/ipfilter/netinet/ip_nat.c | 122 +++++++--- sys/contrib/ipfilter/netinet/ip_nat.h | 4 +- sys/contrib/ipfilter/netinet/ip_state.c | 218 +++++++++++++----- sys/contrib/ipfilter/netinet/ip_state.h | 29 ++- sys/contrib/ipfilter/netinet/ipl.h | 4 +- 14 files changed, 379 insertions(+), 187 deletions(-) diff --git a/sys/contrib/ipfilter/netinet/IPFILTER.LICENCE b/sys/contrib/ipfilter/netinet/IPFILTER.LICENCE index dfb199c5f962..2b4b67e86fd9 100644 --- a/sys/contrib/ipfilter/netinet/IPFILTER.LICENCE +++ b/sys/contrib/ipfilter/netinet/IPFILTER.LICENCE @@ -1,6 +1,4 @@ -Copyright (C) 1993-2001 by Darren Reed. - -$FreeBSD$ +Copyright (C) 1993-2002 by Darren Reed. The author accepts no responsibility for the use of this software and provides it on an ``as is'' basis without express or implied warranty. @@ -27,3 +25,4 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. I hate legalese, don't you ? + diff --git a/sys/contrib/ipfilter/netinet/fil.c b/sys/contrib/ipfilter/netinet/fil.c index 06623c357ebb..3ce8131413cd 100644 --- a/sys/contrib/ipfilter/netinet/fil.c +++ b/sys/contrib/ipfilter/netinet/fil.c @@ -97,7 +97,7 @@ #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.58 2002/03/13 02:23:13 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: fil.c,v 2.35.2.59 2002/03/25 11:07:37 darrenr Exp $"; #endif #ifndef _KERNEL @@ -211,9 +211,7 @@ fr_info_t *fin; fin->fin_data[1] = 0; fin->fin_rule = -1; fin->fin_group = -1; -#ifdef _KERNEL fin->fin_icode = ipl_unreach; -#endif v = fin->fin_v; fi->fi_v = v; fin->fin_hlen = hlen; @@ -263,6 +261,7 @@ fr_info_t *fin; fin->fin_off = off; fin->fin_plen = plen; fin->fin_dp = (char *)tcp; + fin->fin_misc = 0; off <<= 3; switch (p) @@ -295,7 +294,7 @@ fr_info_t *fin; } } - if (!(plen >= hlen + minicmpsz)) + if (!(plen >= minicmpsz)) fi->fi_fl |= FI_SHORT; break; @@ -1496,7 +1495,7 @@ tcphdr_t *tcp; * SUCH DAMAGE. * * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 - * $Id: fil.c,v 2.35.2.58 2002/03/13 02:23:13 darrenr Exp $ + * $Id: fil.c,v 2.35.2.59 2002/03/25 11:07:37 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 e4ad347280c7..2a73079d2cb0 100644 --- a/sys/contrib/ipfilter/netinet/ip_auth.c +++ b/sys/contrib/ipfilter/netinet/ip_auth.c @@ -104,7 +104,7 @@ extern struct ifqueue ipintrq; /* ip packet input queue */ #endif #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_auth.c,v 2.11.2.17 2002/03/06 09:44:10 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_auth.c,v 2.11.2.19 2002/04/23 14:57:27 darrenr Exp $"; #endif @@ -405,6 +405,7 @@ frentry_t *fr, **frptr; RWLOCK_EXIT(&ipf_auth); return 0; } + RWLOCK_EXIT(&ipf_auth); #ifdef _KERNEL # if SOLARIS mutex_enter(&ipf_authmx); @@ -417,7 +418,6 @@ frentry_t *fr, **frptr; error = SLEEP(&fr_authnext, "fr_authnext"); # endif #endif - RWLOCK_EXIT(&ipf_auth); if (!error) goto fr_authioctlloop; break; @@ -447,7 +447,7 @@ frentry_t *fr, **frptr; #ifdef _KERNEL if (m && au->fra_info.fin_out) { # if SOLARIS - error = fr_qout(fra->fra_q, m); + error = (fr_qout(fra->fra_q, m) == 0) ? EINVAL : 0; # else /* SOLARIS */ struct route ro; @@ -469,7 +469,7 @@ frentry_t *fr, **frptr; fr_authstats.fas_sendok++; } else if (m) { # if SOLARIS - error = fr_qin(fra->fra_q, m); + error = (fr_qin(fra->fra_q, m) == 0) ? EINVAL : 0; # else /* SOLARIS */ ifq = &ipintrq; if (IF_QFULL(ifq)) { diff --git a/sys/contrib/ipfilter/netinet/ip_compat.h b/sys/contrib/ipfilter/netinet/ip_compat.h index 4eab541231a6..d0dc859aae47 100644 --- a/sys/contrib/ipfilter/netinet/ip_compat.h +++ b/sys/contrib/ipfilter/netinet/ip_compat.h @@ -4,7 +4,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_compat.h 1.8 1/14/96 - * $Id: ip_compat.h,v 2.26.2.39 2002/03/13 03:54:34 darrenr Exp $ + * $Id: ip_compat.h,v 2.26.2.43 2002/04/23 16:08:50 darrenr Exp $ */ #ifndef __IP_COMPAT_H__ @@ -103,7 +103,6 @@ struct ether_addr { # include #endif - /* * This is a workaround for troubles on FreeBSD and OpenBSD. */ @@ -197,10 +196,6 @@ typedef int minor_t; #endif /* SOLARIS */ #define IPMINLEN(i, h) ((i)->ip_len >= ((i)->ip_hl * 4 + sizeof(struct h))) -#if defined(__FreeBSD__) && (__FreeBSD__ >= 5) && defined(_KERNEL) -# include -#endif - #ifndef IP_OFFMASK #define IP_OFFMASK 0x1fff #endif @@ -215,6 +210,30 @@ typedef int minor_t; #endif /* BSD > 199306 */ +#if defined(__FreeBSD__) && (defined(KERNEL) || defined(_KERNEL)) +# include +# ifndef __FreeBSD_version +# include +# endif +# ifdef IPFILTER_LKM +# define ACTUALLY_LKM_NOT_KERNEL +# endif +# if defined(__FreeBSD_version) && (__FreeBSD_version < 300000) +# include +# else +# if (__FreeBSD_version >= 300000) && (__FreeBSD_version < 400000) +# if defined(IPFILTER_LKM) && !defined(ACTUALLY_LKM_NOT_KERNEL) +# define ACTUALLY_LKM_NOT_KERNEL +# endif +# endif +# endif +#endif /* __FreeBSD__ && KERNEL */ + +#if defined(__FreeBSD_version) && (__FreeBSD_version >= 500000) && \ + defined(_KERNEL) +# include +#endif + /* * These operating systems already take care of the problem for us. */ @@ -230,6 +249,13 @@ typedef u_int32_t u_32_t; # include "opt_inet6.h" # endif # ifdef INET6 +# define USE_INET6 +# endif +# endif +# if !defined(_KERNEL) && !defined(IPFILTER_LKM) +# if (defined(__FreeBSD_version) && (__FreeBSD_version >= 400000)) || \ + (defined(OpenBSD) && (OpenBSD >= 200111)) || \ + (defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105000000)) # define USE_INET6 # endif # endif @@ -341,40 +367,9 @@ union i6addr { #define IPOPT_EIP 145 /* EIP */ #define IPOPT_FINN 205 /* FINN */ - -#if defined(__FreeBSD__) && (defined(KERNEL) || defined(_KERNEL)) -# ifdef IPFILTER_LKM -# ifndef __FreeBSD_cc_version -# include -# else -# if __FreeBSD_cc_version < 430000 -# include -# else -# include -# endif -# endif -# define ACTUALLY_LKM_NOT_KERNEL -# else -# ifndef __FreeBSD_cc_version -# include -# else -# if __FreeBSD_cc_version < 430000 -# include -# else -# include -# endif -# endif -# endif -# if __FreeBSD__ < 3 -# include -# else -# if __FreeBSD__ == 3 -# if defined(IPFILTER_LKM) && !defined(ACTUALLY_LKM_NOT_KERNEL) -# define ACTUALLY_LKM_NOT_KERNEL -# endif -# endif -# endif -#endif /* __FreeBSD__ && KERNEL */ +#ifndef TCPOPT_WSCALE +# define TCPOPT_WSCALE 3 +#endif /* * Build some macros and #defines to enable the same code to compile anywhere @@ -580,7 +575,8 @@ extern void m_copyback __P((struct mbuf *, int, int, caddr_t)); defined(__FreeBSD__) || defined(__OpenBSD__) || defined(_BSDI_VERSION) # include # endif -# if !defined(__FreeBSD__) || (defined (__FreeBSD__) && __FreeBSD__>=3) +# if !defined(__FreeBSD__) || (defined (__FreeBSD_version) && \ + (__FreeBSD_version >= 300000)) # if (defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105180000)) || \ (defined(OpenBSD) && (OpenBSD >= 200111)) # include @@ -589,9 +585,9 @@ extern void m_copyback __P((struct mbuf *, int, int, caddr_t)); extern vm_map_t kmem_map; # endif # include -# else /* !__FreeBSD__ || (__FreeBSD__ && __FreeBSD__>=3) */ +# else /* !__FreeBSD__ || (__FreeBSD__ && __FreeBSD_version >= 300000) */ # include -# endif /* !__FreeBSD__ || (__FreeBSD__ && __FreeBSD__>=3) */ +# endif /* !__FreeBSD__ || (__FreeBSD__ && __FreeBSD_version >= 300000) */ # ifdef M_PFIL # define KMALLOC(a, b) MALLOC((a), b, sizeof(*(a)), M_PFIL, M_NOWAIT) # define KMALLOCS(a, b, c) MALLOC((a), b, (c), M_PFIL, M_NOWAIT) diff --git a/sys/contrib/ipfilter/netinet/ip_fil.c b/sys/contrib/ipfilter/netinet/ip_fil.c index 1cac072015e6..2aeeaf878115 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil.c +++ b/sys/contrib/ipfilter/netinet/ip_fil.c @@ -25,6 +25,7 @@ # endif #endif #ifdef __sgi +# define _KMEMUSER # include #endif #ifndef _KERNEL @@ -119,7 +120,7 @@ extern int ip_optcopy __P((struct ip *, struct ip *)); #if !defined(lint) static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.42.2.53 2002/03/13 02:29:08 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.42.2.55 2002/03/26 15:54:39 darrenr Exp $"; #endif @@ -359,7 +360,7 @@ int iplattach() } # ifdef NETBSD_PF -# if __NetBSD_Version__ >= 104200000 +# if (__NetBSD_Version__ >= 104200000) || (__FreeBSD_version >= 500011) # if __NetBSD_Version__ >= 105110000 if ( !(ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET)) @@ -526,7 +527,7 @@ int ipldetach() fr_running = 0; # ifdef NETBSD_PF -# if __NetBSD_Version__ >= 104200000 +# if ((__NetBSD_Version__ >= 104200000) || (__FreeBSD_version >= 500011)) # if __NetBSD_Version__ >= 105110000 if (ph_inet != NULL) error = pfil_remove_hook((void *)fr_check_wrapper, NULL, @@ -2136,8 +2137,8 @@ struct uio *uio; num = io->iov_len; if (num > left) num = left; - start = io->iov_base + offset; - if (start > io->iov_base + io->iov_len) { + start = (char *)io->iov_base + offset; + if (start > (char *)io->iov_base + io->iov_len) { offset -= io->iov_len; ioc++; continue; diff --git a/sys/contrib/ipfilter/netinet/ip_fil.h b/sys/contrib/ipfilter/netinet/ip_fil.h index 96a8f4bb8c6e..82deef5f2cd7 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil.h +++ b/sys/contrib/ipfilter/netinet/ip_fil.h @@ -4,7 +4,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_fil.h 1.35 6/5/96 - * $Id: ip_fil.h,v 2.29.2.29 2002/03/13 03:56:46 darrenr Exp $ + * $Id: ip_fil.h,v 2.29.2.32 2002/04/10 04:57:14 darrenr Exp $ */ #ifndef __IP_FIL_H__ @@ -55,8 +55,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 frauth_t *) -# define SIOCAUTHR _IOWR('r', 77, struct frauth_t *) +# define SIOCAUTHW _IOWR('r', 76, struct frauth *) +# define SIOCAUTHR _IOWR('r', 77, struct frauth *) # define SIOCATHST _IOWR('r', 78, struct fr_authstat *) # define SIOCSTLCK _IOWR('r', 79, u_int) # define SIOCSTPUT _IOWR('r', 80, struct ipstate_save *) @@ -80,8 +80,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 frauth_t *) -# define SIOCAUTHR _IOWR(r, 77, struct frauth_t *) +# define SIOCAUTHW _IOWR(r, 76, struct frauth *) +# define SIOCAUTHR _IOWR(r, 77, struct frauth *) # define SIOCATHST _IOWR(r, 78, struct fr_authstat *) # define SIOCSTLCK _IOWR(r, 79, u_int) # define SIOCSTPUT _IOWR(r, 80, struct ipstate_save *) @@ -135,12 +135,11 @@ typedef struct fr_info { void *fin_ifp; /* interface packet is `on' */ struct fr_ip fin_fi; /* IP Packet summary */ u_short fin_data[2]; /* TCP/UDP ports, ICMP code/type */ - u_char fin_out; /* in or out ? 1 == out, 0 == in */ - u_char fin_rev; /* state only: 1 = reverse */ + u_int fin_out; /* in or out ? 1 == out, 0 == in */ u_short fin_hlen; /* length of IP header in bytes */ + u_char fin_rev; /* state only: 1 = reverse */ 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_int fin_icode; /* ICMP error to return */ 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 */ @@ -149,6 +148,7 @@ typedef struct fr_info { u_short fin_off; u_short fin_dlen; /* length of data portion of packet */ u_short fin_id; /* IP packet id field */ + u_int fin_misc; void *fin_mp; /* pointer to pointer to mbuf */ #if SOLARIS void *fin_qfm; /* pointer to mblk where pkt starts */ @@ -170,6 +170,11 @@ typedef struct fr_info { #define FI_CSIZE offsetof(fr_info_t, fin_icode) #define FI_LCSIZE offsetof(fr_info_t, fin_dp) +/* + * For fin_misc + */ +#define FM_BADSTATE 0x00000001 + /* * Size for copying cache fr_info structure */ @@ -421,10 +426,10 @@ typedef struct iplog { typedef struct ipflog { #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ (defined(OpenBSD) && (OpenBSD >= 199603)) - u_char fl_ifname[LIFNAMSIZ]; + char fl_ifname[LIFNAMSIZ]; #else u_int fl_unit; - u_char fl_ifname[LIFNAMSIZ]; + char fl_ifname[LIFNAMSIZ]; #endif u_char fl_plen; /* extra data after hlen */ u_char fl_hlen; /* length of IP headers saved */ diff --git a/sys/contrib/ipfilter/netinet/ip_frag.c b/sys/contrib/ipfilter/netinet/ip_frag.c index abc0faa8d72a..f240cd9da4e0 100644 --- a/sys/contrib/ipfilter/netinet/ip_frag.c +++ b/sys/contrib/ipfilter/netinet/ip_frag.c @@ -90,7 +90,7 @@ extern struct timeout ipfr_slowtimer_ch; #if !defined(lint) static const char sccsid[] = "@(#)ip_frag.c 1.11 3/24/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_frag.c,v 2.10.2.20 2002/03/06 09:44:11 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_frag.c,v 2.10.2.21 2002/04/10 04:56:10 darrenr Exp $"; #endif @@ -584,9 +584,9 @@ void ipfr_slowtimer() if (fr_running <= 0) return; + READ_ENTER(&ipf_solaris); #endif - READ_ENTER(&ipf_solaris); #if defined(__sgi) && defined(_KERNEL) ipfilter_sgi_intfsync(); #endif diff --git a/sys/contrib/ipfilter/netinet/ip_h323_pxy.c b/sys/contrib/ipfilter/netinet/ip_h323_pxy.c index 14aa47b7d4b3..a61b0402e907 100644 --- a/sys/contrib/ipfilter/netinet/ip_h323_pxy.c +++ b/sys/contrib/ipfilter/netinet/ip_h323_pxy.c @@ -52,18 +52,27 @@ unsigned char *data; int datlen, *off; unsigned short *port; { + u_32_t addr; + u_char *dp; + int offset; + if (datlen < 6) return -1; *port = 0; - for (*off = 0; *off <= datlen - 6; *off = *off + 1) { - if (ipaddr == *(int *)(data + *off)) + offset = *off; + dp = (u_char *)data; + + for (offset = 0; offset <= datlen - 6; offset++, dp++) { + addr = (dp[0] << 24) | (dp[1] << 16) | (dp[2] << 8) | dp[3]; + if (ipaddr == addr) { - *port = (*(data + *off + 4) << 8) + *(data + *off +5); + *port = (*(dp + 4) << 8) | *(dp + 5); break; } } - return (*off > datlen - 6) ? -1 : 0; + *off = offset; + return (offset > datlen - 6) ? -1 : 0; } /* @@ -109,11 +118,15 @@ ap_session_t *aps; * We are lucky here because this function is not * called with ipf_nat locked. */ - if (nat_ioctl((caddr_t)ipn, SIOCRMNAT, FWRITE) == -1) { + if (nat_ioctl((caddr_t)ipn, SIOCRMNAT, NAT_SYSSPACE| + NAT_LOCKHELD|FWRITE) == -1) { /* log the error */ } } KFREES(aps->aps_data, aps->aps_psiz); + /* avoid double free */ + aps->aps_data = NULL; + aps->aps_psiz = 0; } return; } @@ -144,7 +157,7 @@ nat_t *nat; ipaddr = ip->ip_src.s_addr; data = (unsigned char *)tcp + (tcp->th_off << 2); - datlen = ip->ip_len - (ip->ip_hl << 2) - (tcp->th_off << 2); + datlen = fin->fin_dlen - (tcp->th_off << 2); if (find_port(ipaddr, data, datlen, &off, &port) == 0) { ipnat_t *ipn; char *newarray; @@ -177,13 +190,16 @@ nat_t *nat; * of calling nat_ioctl(), we add the nat rule ourself. */ RWLOCK_EXIT(&ipf_nat); - if (nat_ioctl((caddr_t)ipn, SIOCADNAT, FWRITE) == -1) { + if (nat_ioctl((caddr_t)ipn, SIOCADNAT, + NAT_SYSSPACE|FWRITE) == -1) { READ_ENTER(&ipf_nat); return -1; } READ_ENTER(&ipf_nat); - bcopy(aps->aps_data, newarray, aps->aps_psiz); - KFREES(aps->aps_data, aps->aps_psiz); + if (aps->aps_data != NULL && aps->aps_psiz > 0) { + bcopy(aps->aps_data, newarray, aps->aps_psiz); + KFREES(aps->aps_data, aps->aps_psiz); + } aps->aps_data = newarray; aps->aps_psiz += sizeof(*ipn); } @@ -256,8 +272,10 @@ nat_t *nat; #ifdef IPFILTER_LOG nat_log(ipn, (u_int)(nat->nat_ptr->in_redir)); #endif - *(int *)(data + off) = ip->ip_src.s_addr; - *(short *)(data + off + 4) = ipn->nat_outport; + bcopy((u_char*)&ip->ip_src.s_addr, + data + off, 4); + bcopy((u_char*)&ipn->nat_outport, + data + off + 4, 2); } } } diff --git a/sys/contrib/ipfilter/netinet/ip_log.c b/sys/contrib/ipfilter/netinet/ip_log.c index e56c60262460..45bc74c7114c 100644 --- a/sys/contrib/ipfilter/netinet/ip_log.c +++ b/sys/contrib/ipfilter/netinet/ip_log.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ip_log.c,v 2.5.2.17 2002/03/13 03:57:05 darrenr Exp $ + * $Id: ip_log.c,v 2.5.2.18 2002/03/26 15:54:40 darrenr Exp $ */ #include #if defined(KERNEL) && !defined(_KERNEL) @@ -84,6 +84,7 @@ # include # include # ifdef __sgi +# define _KMEMUSER # include # ifdef IFF_DRVRLOCK /* IRIX6 */ # include diff --git a/sys/contrib/ipfilter/netinet/ip_nat.c b/sys/contrib/ipfilter/netinet/ip_nat.c index 5c10bc4ba3f3..e0d595193460 100644 --- a/sys/contrib/ipfilter/netinet/ip_nat.c +++ b/sys/contrib/ipfilter/netinet/ip_nat.c @@ -109,7 +109,7 @@ extern struct ifnet vpnif; #if !defined(lint) static const char sccsid[] = "@(#)ip_nat.c 1.11 6/5/96 (C) 1995 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_nat.c,v 2.37.2.63 2002/03/06 09:44:11 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_nat.c,v 2.37.2.66 2002/04/23 14:58:27 darrenr Exp $"; #endif nat_t **nat_table[2] = { NULL, NULL }, @@ -425,7 +425,7 @@ caddr_t data; int mode; { register ipnat_t *nat, *nt, *n = NULL, **np = NULL; - int error = 0, ret, arg; + int error = 0, ret, arg, getlock; ipnat_t natd; u_32_t i, j; @@ -436,9 +436,15 @@ int mode; nat = NULL; /* XXX gcc -Wuninitialized */ KMALLOC(nt, ipnat_t *); - if ((cmd == SIOCADNAT) || (cmd == SIOCRMNAT)) - error = IRCOPYPTR(data, (char *)&natd, sizeof(natd)); - else if (cmd == SIOCIPFFL) { /* SIOCFLNAT & SIOCCNATL */ + getlock = (mode & NAT_LOCKHELD) ? 0 : 1; + if ((cmd == SIOCADNAT) || (cmd == SIOCRMNAT)) { + if (mode & NAT_SYSSPACE) { + bcopy(data, (char *)&natd, sizeof(natd)); + error = 0; + } else { + error = IRCOPYPTR(data, (char *)&natd, sizeof(natd)); + } + } else if (cmd == SIOCIPFFL) { /* SIOCFLNAT & SIOCCNATL */ error = IRCOPY(data, (char *)&arg, sizeof(arg)); if (error) error = EFAULT; @@ -450,7 +456,8 @@ int mode; /* * For add/delete, look to see if the NAT entry is already present */ - WRITE_ENTER(&ipf_nat); + if (getlock == 1) + WRITE_ENTER(&ipf_nat); if ((cmd == SIOCADNAT) || (cmd == SIOCRMNAT)) { nat = &natd; nat->in_flags &= IPN_USERFLAGS; @@ -715,7 +722,8 @@ int mode; error = EINVAL; break; } - RWLOCK_EXIT(&ipf_nat); /* READ/WRITE */ + if (getlock == 1) + RWLOCK_EXIT(&ipf_nat); /* READ/WRITE */ done: if (nt) KFREE(nt); @@ -831,7 +839,7 @@ caddr_t data; return ENOMEM; bcopy((char *)&ipn, (char *)ipnn, sizeof(ipn)); - bcopy((char *)aps, ipnn->ipn_data, sizeof(*aps)); + bcopy((char *)aps, (char *)ipnn->ipn_data, sizeof(*aps)); if (aps->aps_data) { bcopy(aps->aps_data, ipnn->ipn_data + sizeof(*aps), aps->aps_psiz); @@ -1650,11 +1658,12 @@ int dir; { u_32_t sum1, sum2, sumd, sumd2 = 0; struct in_addr in; + int flags, dlen; icmphdr_t *icmp; udphdr_t *udp; + tcphdr_t *tcp; nat_t *nat; ip_t *oip; - int flags; if ((fin->fin_fl & FI_SHORT) || (fin->fin_off != 0)) return NULL; @@ -1673,6 +1682,13 @@ int dir; else if (oip->ip_p == IPPROTO_UDP) flags = IPN_UDP; udp = (udphdr_t *)((((char *)oip) + (oip->ip_hl << 2))); + dlen = ip->ip_len - ((char *)udp - (char *)ip); + /* + * XXX - what if this is bogus hl and we go off the end ? + * In this case, nat_icmplookup() will have returned NULL. + */ + tcp = (tcphdr_t *)udp; + /* * Need to adjust ICMP header to include the real IP#'s and * port #'s. Only apply a checksum change relative to the @@ -1695,8 +1711,6 @@ int dir; * change in the UDP and TCP checksums require yet another * adjustment of the ICMP checksum of the ICMP error message. * - * For the moment we forget about TCP, because that checksum is not - * in the first 8 bytes, so it will not be available in most cases. */ if (oip->ip_dst.s_addr == nat->nat_oip.s_addr) { @@ -1754,15 +1768,25 @@ int dir; sumd2 = sumd; } -#if 0 +#if 1 /* * Fix TCP pseudo header checksum to compensate for the * IP address change. Before we can do the change, we * must make sure that oip is sufficient large to hold * the TCP checksum (normally it does not!). */ - if (oip->ip_p == IPPROTO_TCP) { + if (oip->ip_p == IPPROTO_TCP && dlen >= 18) { + sum1 = ntohs(tcp->th_sum); + fix_datacksum(&tcp->th_sum, sumd); + sum2 = ntohs(tcp->th_sum); + + /* + * Fix ICMP checksum to compensate the TCP + * checksum adjustment. + */ + CALC_SUMD(sum1, sum2, sumd); + sumd2 = sumd; } #endif } else { @@ -1813,15 +1837,25 @@ int dir; sumd2 = sumd; } -#if 0 +#if 1 /* * Fix TCP pseudo header checksum to compensate for the * IP address change. Before we can do the change, we * must make sure that oip is sufficient large to hold * the TCP checksum (normally it does not!). */ - if (oip->ip_p == IPPROTO_TCP) { + if (oip->ip_p == IPPROTO_TCP && dlen >= 18) { + sum1 = ntohs(tcp->th_sum); + fix_datacksum(&tcp->th_sum, sumd); + sum2 = ntohs(tcp->th_sum); + + /* + * Fix ICMP checksum to compensate the TCP + * checksum adjustment. + */ + CALC_SUMD(sum1, sum2, sumd); + sumd2 = sumd; }; #endif @@ -1829,14 +1863,6 @@ int dir; } if ((flags & IPN_TCPUDP) != 0) { - tcphdr_t *tcp; - - /* - * XXX - what if this is bogus hl and we go off the end ? - * In this case, nat_icmpinlookup() will have returned NULL. - */ - tcp = (tcphdr_t *)udp; - /* * Step 2 : * For offending TCP/UDP IP packets, translate the ports as @@ -1852,8 +1878,9 @@ int dir; * * To further complicate: the TCP checksum is not in the first * 8 bytes of the offending ip packet, so it most likely is not - * available (we might have to fix that if the encounter a - * device that returns more than 8 data bytes on icmp error) + * available. Some OSses like Solaris return enough bytes to + * include the TCP checksum. So we have to check if the + * ip->ip_len actually holds the TCP checksum of the oip! */ if (nat->nat_oport == tcp->th_dport) { @@ -1891,6 +1918,27 @@ int dir; CALC_SUMD(sum1, sum2, sumd); sumd2 += sumd; } + + /* + * Fix tcp checksum (if present) to compensate + * port adjustment. NOTE : the offending IP + * packet flows the other direction compared to + * the ICMP message. + */ + if (oip->ip_p == IPPROTO_TCP && dlen >= 18) { + + sum1 = ntohs(tcp->th_sum); + fix_datacksum(&tcp->th_sum, sumd); + sum2 = ntohs(tcp->th_sum); + + /* + * Fix ICMP checksum to + * compensate TCP checksum + * adjustment. + */ + CALC_SUMD(sum1, sum2, sumd); + sumd2 += sumd; + } } } else { if (tcp->th_dport != nat->nat_outport) { @@ -1926,6 +1974,26 @@ int dir; CALC_SUMD(sum1, sum2, sumd); sumd2 += sumd; } + + /* + * Fix tcp checksum (if present) to compensate + * port adjustment. NOTE : the offending IP + * packet flows the other direction compared to + * the ICMP message. + */ + if (oip->ip_p == IPPROTO_TCP && dlen >= 18) { + + sum1 = ntohs(tcp->th_sum); + fix_datacksum(&tcp->th_sum, sumd); + sum2 = ntohs(tcp->th_sum); + + /* + * Fix ICMP checksum to compensate + * UDP checksum adjustment. + */ + CALC_SUMD(sum1, sum2, sumd); + sumd2 += sumd; + } } } if (sumd2) { @@ -2435,7 +2503,7 @@ fr_info_t *fin; csump = &tcp->th_sum; MUTEX_ENTER(&nat->nat_lock); fr_tcp_age(&nat->nat_age, - nat->nat_tcpstate, fin, 1); + nat->nat_tcpstate, fin, 1, 0); if (nat->nat_age < fr_defnaticmpage) nat->nat_age = fr_defnaticmpage; #ifdef LARGE_NAT @@ -2643,7 +2711,7 @@ fr_info_t *fin; csump = &tcp->th_sum; MUTEX_ENTER(&nat->nat_lock); fr_tcp_age(&nat->nat_age, - nat->nat_tcpstate, fin, 0); + nat->nat_tcpstate, fin, 0, 0); if (nat->nat_age < fr_defnaticmpage) nat->nat_age = fr_defnaticmpage; #ifdef LARGE_NAT diff --git a/sys/contrib/ipfilter/netinet/ip_nat.h b/sys/contrib/ipfilter/netinet/ip_nat.h index 4b2acc485283..b3b0b27723f9 100644 --- a/sys/contrib/ipfilter/netinet/ip_nat.h +++ b/sys/contrib/ipfilter/netinet/ip_nat.h @@ -4,7 +4,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_nat.h 1.5 2/4/96 - * $Id: ip_nat.h,v 2.17.2.25 2002/01/01 15:10:49 darrenr Exp $ + * $Id: ip_nat.h,v 2.17.2.26 2002/04/20 16:42:05 darrenr Exp $ */ #ifndef __IP_NAT_H__ @@ -276,6 +276,8 @@ typedef struct natlog { (sd) = (s2) - (s1); \ (sd) = ((sd) & 0xffff) + ((sd) >> 16); } +#define NAT_SYSSPACE 0x80000000 +#define NAT_LOCKHELD 0x40000000 extern u_int ipf_nattable_sz; extern u_int ipf_natrules_sz; diff --git a/sys/contrib/ipfilter/netinet/ip_state.c b/sys/contrib/ipfilter/netinet/ip_state.c index 255bdad61f75..2e8b8f3f7e1b 100644 --- a/sys/contrib/ipfilter/netinet/ip_state.c +++ b/sys/contrib/ipfilter/netinet/ip_state.c @@ -93,7 +93,7 @@ #if !defined(lint) static const char sccsid[] = "@(#)ip_state.c 1.8 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_state.c,v 2.30.2.61 2002/03/06 14:07:36 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_state.c,v 2.30.2.66 2002/04/15 12:14:03 darrenr Exp $"; #endif #ifndef MIN @@ -123,6 +123,7 @@ static ips_stat_t *fr_statetstats __P((void)); static void fr_delstate __P((ipstate_t *)); static int fr_state_remove __P((caddr_t)); static void fr_ipsmove __P((ipstate_t **, ipstate_t *, u_int)); +static int fr_tcpoptions __P((tcphdr_t *)); int fr_stputent __P((caddr_t)); int fr_stgetent __P((caddr_t)); void fr_stinsert __P((ipstate_t *)); @@ -298,7 +299,7 @@ caddr_t data; if ((sp->is_p == st.is_p) && (sp->is_v == st.is_v) && !bcmp((char *)&sp->is_src, (char *)&st.is_src, sizeof(st.is_src)) && - !bcmp((char *)&sp->is_dst, (char *)&st.is_src, + !bcmp((char *)&sp->is_dst, (char *)&st.is_dst, sizeof(st.is_dst)) && !bcmp((char *)&sp->is_ps, (char *)&st.is_ps, sizeof(st.is_ps))) { @@ -578,7 +579,8 @@ u_int flags; void *ifp; int out; - if (fr_state_lock || (fin->fin_off != 0) || (fin->fin_fl & FI_SHORT)) + if (fr_state_lock || (fin->fin_off != 0) || (fin->fin_fl & FI_SHORT) || + (fin->fin_misc & FM_BADSTATE)) return NULL; if (ips_num == fr_statemax) { ips_stats.iss_max++; @@ -619,6 +621,8 @@ u_int flags; switch (is->is_p) { + int off; + #ifdef USE_INET6 case IPPROTO_ICMPV6 : ic = (struct icmp *)fin->fin_dp; @@ -680,15 +684,22 @@ u_int flags; hv += is->is_dport; } is->is_send = ntohl(tcp->th_seq) + fin->fin_dlen - - (tcp->th_off << 2) + + (off = (tcp->th_off << 2)) + ((tcp->th_flags & TH_SYN) ? 1 : 0) + ((tcp->th_flags & TH_FIN) ? 1 : 0); is->is_maxsend = is->is_send; - is->is_dend = 0; is->is_maxdwin = 1; is->is_maxswin = ntohs(tcp->th_win); if (is->is_maxswin == 0) is->is_maxswin = 1; + + if ((tcp->th_flags & TH_OPENING) == TH_SYN) + is->is_fsm = 1; + + if ((tcp->th_flags & TH_SYN) && + ((tcp->th_off << 2) >= (sizeof(*tcp) + 4))) + is->is_swscale = fr_tcpoptions(tcp); + /* * If we're creating state for a starting connection, start the * timer on it as we'll never see an error if it fails to @@ -785,7 +796,7 @@ u_int flags; is->is_me = stsave; if (is->is_p == IPPROTO_TCP) { fr_tcp_age(&is->is_age, is->is_state, fin, - 0); /* 0 = packet from the source */ + 0, is->is_fsm); /* 0 = packet from the source */ } #ifdef IPFILTER_LOG ipstate_log(is, ISL_NEW); @@ -798,6 +809,46 @@ u_int flags; } +static int fr_tcpoptions(tcp) +tcphdr_t *tcp; +{ + u_char *opt, *last; + int wscale; + + opt = (u_char *) (tcp + 1); + last = ((u_char *)tcp) + (tcp->th_off << 2); + + /* If we don't find wscale here, we need to clear it */ + wscale = -2; + + /* Termination condition picked such that opt[0 .. 2] exist */ + while ((opt < last - 2) && (*opt != TCPOPT_EOL)) { + switch (*opt) { + case TCPOPT_NOP: + opt++; + continue; + case TCPOPT_WSCALE: + /* Proper length ? */ + if (opt[1] == 3) { + if (opt[2] > 14) + wscale = 14; + else + wscale = opt[2]; + } + break; + default: + /* Unknown options must be two bytes+ */ + if (opt[1] < 2) + break; + opt += opt[1]; + continue; + } + break; + } + return wscale; +} + + /* * check to see if a packet with TCP headers fits within the TCP window. @@ -813,9 +864,10 @@ tcphdr_t *tcp; register tcp_seq seq, ack, end; register int ackskew; tcpdata_t *fdata, *tdata; - u_short win, maxwin; - int ret = 0; + u_32_t win, maxwin; + int ret = 0, off; int source; + int wscale; /* * Find difference between last checked packet and this packet. @@ -825,15 +877,29 @@ tcphdr_t *tcp; source = 0; fdata = &is->is_tcp.ts_data[!source]; tdata = &is->is_tcp.ts_data[source]; + off = tcp->th_off << 2; seq = ntohl(tcp->th_seq); ack = ntohl(tcp->th_ack); win = ntohs(tcp->th_win); - end = seq + fin->fin_dlen - (tcp->th_off << 2) + + end = seq + fin->fin_dlen - off + ((tcp->th_flags & TH_SYN) ? 1 : 0) + ((tcp->th_flags & TH_FIN) ? 1 : 0); + + if ((tcp->th_flags & TH_SYN) && (off >= sizeof(*tcp) + 4)) + wscale = fr_tcpoptions(tcp); + else + wscale = -1; + MUTEX_ENTER(&is->is_lock); - if (fdata->td_end == 0) { + + if (wscale >= 0) + fdata->td_wscale = wscale; + else if (wscale == -2) + fdata->td_wscale = tdata->td_wscale = 0; + + if ((fdata->td_end == 0) && + (!is->is_fsm || ((tcp->th_flags & TH_OPENING) == TH_OPENING))) { /* * Must be a (outgoing) SYN-ACK in reply to a SYN. */ @@ -853,6 +919,7 @@ tcphdr_t *tcp; if (seq == end) seq = end = fdata->td_end; + win <<= fdata->td_wscale; maxwin = tdata->td_maxwin; ackskew = tdata->td_end - ack; @@ -878,29 +945,33 @@ tcphdr_t *tcp; * Thus, when ackskew is negative but still seems to belong * to this session, we bump up the destinations end value. */ - if (ackskew < 0) - tdata->td_end = ack; - - /* update max window seen */ - if (fdata->td_maxwin < win) - fdata->td_maxwin = win; - if (SEQ_GT(end, fdata->td_end)) - fdata->td_end = end; - if (SEQ_GE(ack + win, tdata->td_maxend)) { - tdata->td_maxend = ack + win; - if (win == 0) - tdata->td_maxend++; - } - - ATOMIC_INCL(ips_stats.iss_hits); /* * Nearing end of connection, start timeout. */ /* source ? 0 : 1 -> !source */ - fr_tcp_age(&is->is_age, is->is_state, fin, !source); - ret = 1; + if (fr_tcp_age(&is->is_age, is->is_state, fin, !source, + (int)is->is_fsm) == 0) { + if (ackskew < 0) + tdata->td_end = ack; + + /* update max window seen */ + if (fdata->td_maxwin < win) + fdata->td_maxwin = win; + if (SEQ_GT(end, fdata->td_end)) + fdata->td_end = end; + if (SEQ_GE(ack + win, tdata->td_maxend)) { + tdata->td_maxend = ack + win; + if (win == 0) + tdata->td_maxend++; + } + + ATOMIC_INCL(ips_stats.iss_hits); + ret = 1; + } } MUTEX_EXIT(&is->is_lock); + if ((ret == 0) && (tcp->th_flags != TH_SYN)) + fin->fin_misc |= FM_BADSTATE; return ret; } @@ -1079,9 +1150,9 @@ fr_info_t *fin; register ipstate_t *is, **isp; register u_short sport, dport; register u_char pr; + u_short savelen, ohlen; union i6addr dst, src; struct icmp *ic; - u_short savelen; icmphdr_t *icmp; fr_info_t ofin; int type, len; @@ -1110,14 +1181,15 @@ fr_info_t *fin; return NULL; oip = (ip_t *)((char *)ic + ICMPERR_ICMPHLEN); - if (fin->fin_plen < ICMPERR_MAXPKTLEN + ((oip->ip_hl - 5) << 2)) + ohlen = oip->ip_hl << 2; + if (fin->fin_plen < ICMPERR_MAXPKTLEN + ohlen - sizeof(*oip)) return NULL; /* * Sanity checks. */ len = fin->fin_dlen - ICMPERR_ICMPHLEN; - if ((len <= 0) || ((oip->ip_hl << 2) > len)) + if ((len <= 0) || (ohlen > len)) return NULL; /* @@ -1157,7 +1229,7 @@ fr_info_t *fin; switch (oip->ip_p) { case IPPROTO_ICMP : - icmp = (icmphdr_t *)((char *)oip + (oip->ip_hl << 2)); + icmp = (icmphdr_t *)((char *)oip + ohlen); /* * a ICMP error can only be generated as a result of an @@ -1187,7 +1259,7 @@ fr_info_t *fin; savelen = oip->ip_len; oip->ip_len = len; ofin.fin_v = 4; - fr_makefrip(oip->ip_hl << 2, oip, &ofin); + fr_makefrip(ohlen, oip, &ofin); oip->ip_len = savelen; ofin.fin_ifp = fin->fin_ifp; ofin.fin_out = !fin->fin_out; @@ -1209,12 +1281,14 @@ fr_info_t *fin; case IPPROTO_TCP : case IPPROTO_UDP : + if (fin->fin_plen < ICMPERR_MAXPKTLEN) + return NULL; break; default : return NULL; } - tcp = (tcphdr_t *)((char *)oip + (oip->ip_hl << 2)); + tcp = (tcphdr_t *)((char *)oip + ohlen); dport = tcp->th_dport; sport = tcp->th_sport; @@ -1239,7 +1313,7 @@ fr_info_t *fin; savelen = oip->ip_len; oip->ip_len = len; ofin.fin_v = 4; - fr_makefrip(oip->ip_hl << 2, oip, &ofin); + fr_makefrip(ohlen, oip, &ofin); oip->ip_len = savelen; ofin.fin_ifp = fin->fin_ifp; ofin.fin_out = !fin->fin_out; @@ -1481,9 +1555,8 @@ fr_info_t *fin; fr_matchsrcdst(is, src, dst, fin, tcp)) { rev = fin->fin_rev; if ((pr == IPPROTO_TCP)) { - if (!fr_tcpstate(is, fin, ip, tcp)) { - continue; - } + if (!fr_tcpstate(is, fin, ip, tcp)) + is = NULL; } else if ((pr == IPPROTO_UDP)) { if (is->is_frage[rev] != 0) is->is_age = is->is_frage[rev]; @@ -1504,6 +1577,7 @@ fr_info_t *fin; } break; } + RWLOCK_EXIT(&ipf_state); if (!tryagain && ips_wild) { hv -= dport; @@ -1703,15 +1777,16 @@ void fr_timeoutstate() * dir == 1 : a packet from dest to source * */ -void fr_tcp_age(age, state, fin, dir) +int fr_tcp_age(age, state, fin, dir, fsm) u_long *age; u_char *state; fr_info_t *fin; -int dir; +int dir, fsm; { tcphdr_t *tcp = (tcphdr_t *)fin->fin_dp; u_char flags = tcp->th_flags; int dlen, ostate; + u_long newage; ostate = state[1 - dir]; @@ -1725,10 +1800,10 @@ int dir; *age = fr_tcpclosewait; state[dir] = TCPS_CLOSE_WAIT; } - return; + return 0; } - *age = fr_tcptimeout; /* default 4 mins */ + newage = 0; switch(state[dir]) { @@ -1739,11 +1814,11 @@ int dir; * CLOSED -> SYN_RECEIVED */ state[dir] = TCPS_SYN_RECEIVED; - *age = fr_tcptimeout; - } else if ((flags & (TH_SYN|TH_ACK)) == TH_SYN) { + newage = fr_tcptimeout; + } else if ((flags & TH_OPENING) == TH_SYN) { /* 'dir' sent S, CLOSED -> SYN_SENT */ state[dir] = TCPS_SYN_SENT; - *age = fr_tcptimeout; + newage = fr_tcptimeout; } /* * The next piece of code makes it possible to get @@ -1752,12 +1827,12 @@ int dir; * does not work when a strict 'flags S keep state' is * used for tcp connections of course */ - if ((flags & (TH_FIN|TH_SYN|TH_RST|TH_ACK)) == TH_ACK) { + if (!fsm && (flags & (TH_FIN|TH_SYN|TH_RST|TH_ACK)) == TH_ACK) { /* we saw an A, guess 'dir' is in ESTABLISHED mode */ if (state[1 - dir] == TCPS_CLOSED || state[1 - dir] == TCPS_ESTABLISHED) { state[dir] = TCPS_ESTABLISHED; - *age = fr_tcpidletimeout; + newage = fr_tcpidletimeout; } } /* @@ -1772,14 +1847,24 @@ int dir; break; case TCPS_SYN_SENT: /* 2 */ - if ((flags & (TH_SYN|TH_FIN|TH_ACK)) == TH_ACK) { + if (flags == TH_SYN) { + /* + * A retransmitted SYN packet. We do not reset the + * timeout here to fr_tcptimeout because a connection + * connect timeout does not renew after every packet + * that is sent. We need to set newage to something + * to indicate the packet has passed the check for its + * flags being valid in the TCP FSM. + */ + newage = *age; + } else if ((flags & (TH_SYN|TH_FIN|TH_ACK)) == TH_ACK) { /* * We see an A from 'dir' which is in SYN_SENT * state: 'dir' sent an A in response to an SA * which it received, SYN_SENT -> ESTABLISHED */ state[dir] = TCPS_ESTABLISHED; - *age = fr_tcpidletimeout; + newage = fr_tcpidletimeout; } else if (flags & TH_FIN) { /* * We see an F from 'dir' which is in SYN_SENT @@ -1787,7 +1872,7 @@ int dir; * connection; SYN_SENT -> FIN_WAIT_1 */ state[dir] = TCPS_FIN_WAIT_1; - *age = fr_tcpidletimeout; /* or fr_tcptimeout? */ + newage = fr_tcpidletimeout; /* or fr_tcptimeout? */ } else if ((flags & TH_OPENING) == TH_OPENING) { /* * We see an SA from 'dir' which is already in @@ -1795,7 +1880,7 @@ int dir; * simultaneous open; SYN_SENT -> SYN_RECEIVED */ state[dir] = TCPS_SYN_RECEIVED; - *age = fr_tcptimeout; + newage = fr_tcptimeout; } break; @@ -1807,7 +1892,7 @@ int dir; * SYN_RECEIVED -> ESTABLISHED */ state[dir] = TCPS_ESTABLISHED; - *age = fr_tcpidletimeout; + newage = fr_tcpidletimeout; } else if (flags & TH_FIN) { /* * We see an F from 'dir' which is in SYN_RECEIVED @@ -1815,7 +1900,7 @@ int dir; * SYN_RECEIVED -> FIN_WAIT_1 */ state[dir] = TCPS_FIN_WAIT_1; - *age = fr_tcpidletimeout; + newage = fr_tcpidletimeout; } break; @@ -1827,7 +1912,7 @@ int dir; * ESTABLISHED -> FIN_WAIT_1 */ state[dir] = TCPS_FIN_WAIT_1; - *age = fr_tcphalfclosed; + newage = fr_tcphalfclosed; } else if (flags & TH_ACK) { /* an ACK, should we exclude other flags here? */ if (ostate == TCPS_FIN_WAIT_1) { @@ -1839,13 +1924,13 @@ int dir; * a half-closed connection */ state[dir] = TCPS_CLOSE_WAIT; - *age = fr_tcphalfclosed; + newage = fr_tcphalfclosed; } else if (ostate < TCPS_CLOSE_WAIT) /* * Still a fully established connection, * reset timeout */ - *age = fr_tcpidletimeout; + newage = fr_tcpidletimeout; } break; @@ -1855,7 +1940,7 @@ int dir; * Application closed and 'dir' sent a FIN, we're now * going into LAST_ACK state */ - *age = fr_tcplastack; + newage = fr_tcplastack; state[dir] = TCPS_LAST_ACK; } else { /* @@ -1863,7 +1948,7 @@ int dir; * closed already and we did not close our side yet; * reset timeout */ - *age = fr_tcphalfclosed; + newage = fr_tcphalfclosed; } break; @@ -1880,14 +1965,14 @@ int dir; * packet here? does the window code guarantee that? */ state[dir] = TCPS_TIME_WAIT; - *age = fr_tcptimeout; + newage = fr_tcptimeout; } else /* * We closed our side of the connection already but the * other side is still active (ESTABLISHED/CLOSE_WAIT); * continue with this half-closed connection */ - *age = fr_tcphalfclosed; + newage = fr_tcphalfclosed; break; case TCPS_CLOSING: /* 7 */ @@ -1901,7 +1986,7 @@ int dir; * There is still data to be delivered, reset * timeout */ - *age = fr_tcplastack; + newage = fr_tcplastack; } /* * We cannot detect when we go out of LAST_ACK state to CLOSED @@ -1916,9 +2001,16 @@ int dir; break; case TCPS_TIME_WAIT: /* 10 */ + newage = fr_tcptimeout; /* default 4 mins */ /* we're in 2MSL timeout now */ break; } + + if (newage != 0) { + *age = newage; + return 0; + } + return -1; } @@ -2068,8 +2160,14 @@ fr_info_t *fin; hv = (pr = oip->ip6_nxt); src.in6 = oip->ip6_src; hv += src.in4.s_addr; + hv += src.i6[1]; + hv += src.i6[2]; + hv += src.i6[3]; dst.in6 = oip->ip6_dst; hv += dst.in4.s_addr; + hv += dst.i6[1]; + hv += dst.i6[2]; + hv += dst.i6[3]; hv += dport; hv += sport; hv %= fr_statesize; diff --git a/sys/contrib/ipfilter/netinet/ip_state.h b/sys/contrib/ipfilter/netinet/ip_state.h index fe6a505fe66d..01b12561a7a9 100644 --- a/sys/contrib/ipfilter/netinet/ip_state.h +++ b/sys/contrib/ipfilter/netinet/ip_state.h @@ -4,7 +4,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_state.h 1.3 1/12/96 (C) 1995 Darren Reed - * $Id: ip_state.h,v 2.13.2.10 2002/03/06 14:07:38 darrenr Exp $ + * $Id: ip_state.h,v 2.13.2.12 2002/03/25 11:14:55 darrenr Exp $ */ #ifndef __IP_STATE_H__ #define __IP_STATE_H__ @@ -42,7 +42,8 @@ typedef struct icmpstate { typedef struct tcpdata { u_32_t td_end; u_32_t td_maxend; - u_short td_maxwin; + u_32_t td_maxwin; + u_char td_wscale; } tcpdata_t; typedef struct tcpstate { @@ -58,20 +59,22 @@ typedef struct ipstate { struct ipstate *is_hnext; struct ipstate **is_phnext; struct ipstate **is_me; + frentry_t *is_rule; + U_QUAD_T is_pkts; + U_QUAD_T is_bytes; + union i6addr is_src; + union i6addr is_dst; + void *is_ifp[4]; 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[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_char is_v; /* IP version */ + u_char is_fsm; /* 1 = following FSM, 0 = not */ + u_char is_xxx; /* pad */ + u_int is_hv; /* hash value for this in the table */ u_32_t is_rulen; /* rule number */ - u_32_t is_flags; + u_32_t is_flags; /* flags for this structure */ u_32_t is_opt; /* packet options set */ u_32_t is_optmsk; /* " " mask */ u_short is_sec; /* security options set */ @@ -100,6 +103,8 @@ typedef struct ipstate { #define is_dend is_tcp.ts_data[1].td_end #define is_maxswin is_tcp.ts_data[0].td_maxwin #define is_maxdwin is_tcp.ts_data[1].td_maxwin +#define is_swscale is_tcp.ts_data[0].td_wscale +#define is_dwscale is_tcp.ts_data[1].td_wscale #define is_maxsend is_tcp.ts_data[0].td_maxend #define is_maxdend is_tcp.ts_data[1].td_maxend #define is_sport is_tcp.ts_sport @@ -191,7 +196,7 @@ 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)); +extern int fr_tcp_age __P((u_long *, u_char *, fr_info_t *, int, int)); extern void fr_stateunload __P((void)); extern void ipstate_log __P((struct ipstate *, u_int)); #if defined(__NetBSD__) || defined(__OpenBSD__) diff --git a/sys/contrib/ipfilter/netinet/ipl.h b/sys/contrib/ipfilter/netinet/ipl.h index 75f9d67efaf2..2e99b65c0276 100644 --- a/sys/contrib/ipfilter/netinet/ipl.h +++ b/sys/contrib/ipfilter/netinet/ipl.h @@ -4,12 +4,12 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ipl.h 1.21 6/5/96 - * $Id: ipl.h,v 2.15.2.31 2002/03/13 03:57:42 darrenr Exp $ + * $Id: ipl.h,v 2.15.2.32 2002/04/23 14:59:13 darrenr Exp $ */ #ifndef __IPL_H__ #define __IPL_H__ -#define IPL_VERSION "IP Filter: v3.4.25" +#define IPL_VERSION "IP Filter: v3.4.26" #endif From 43ba65e60d8d4967956752a79619c4e7950a846a Mon Sep 17 00:00:00 2001 From: Darren Reed Date: Thu, 25 Apr 2002 03:23:53 +0000 Subject: [PATCH 3/3] Import IPFilter 3.4.26 kernel sources, including H.323 proxy. Include the licence file for both IPFilter and the H.323 proxy (from QNX), for convienence. --- sys/contrib/ipfilter/netinet/QNX_OCL.txt | 275 +++++++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100644 sys/contrib/ipfilter/netinet/QNX_OCL.txt diff --git a/sys/contrib/ipfilter/netinet/QNX_OCL.txt b/sys/contrib/ipfilter/netinet/QNX_OCL.txt new file mode 100644 index 000000000000..6aa33eaf6b06 --- /dev/null +++ b/sys/contrib/ipfilter/netinet/QNX_OCL.txt @@ -0,0 +1,275 @@ + End User License Certificate (EULA) End User License Certificate + (EULA) + Support Support + QNX Source Licenses QNX Source Licenses + License of the month + Confidential Source License + Version 1.0 + +QNX Open Community License Version 1.0 + + THIS QNX OPEN COMMUNITY LICENSE ( "THE OCL", OR "THIS AGREEMENT") + APPLIES TO PROGRAMS THAT QNX SOFTWARE SYSTEMS LTD. ("QSS") EXPRESSLY + ELECTS TO LICENSE UNDER THE OCL TERMS. IT ALSO APPLIES TO DERIVATIVE + WORKS CREATED UNDER THIS AGREEMENT THAT CREATORS ELECT TO LICENSE TO + OTHERS IN SOURCE CODE FORM. ANY USE, REPRODUCTION, MODIFICATION OR + DISTRIBUTION OF SUCH PROGRAMS CONSTITUTES RECIPIENT'S ACCEPTANCE OF + THE OCL. THE LICENSE RIGHTS GRANTED BELOW ARE CONDITIONAL UPON + RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT AND THE FORMATION OF A + BINDING CONTRACT. NOTHING ELSE GRANTS PERMISSION TO USE, REPRODUCE, + MODIFY OR DISTRIBUTE SUCH PROGRAMS OR THEIR DERIVATIVE WORKS. THESE + ACTIONS ARE OTHERWISE PROHIBITED. CONTACT QSS IF OTHER STEPS ARE + REQUIRED LOCALLY TO CREATE A BINDING CONTRACT. + + The OCL is intended to promote the development, use and distribution + of derivative works created from QSS source code. This includes + commercial distribution of object code versions under the terms of + Recipient's own license agreement and, at Recipient's option, sharing + of source code modifications within the QNX developer's community. The + license granted under the OCL is royalty free. Recipient is entitled + to charge royalties for object code versions of derivative works that + originate with Recipient. If Recipient elects to license source code + for its derivative works to others, then it must be licensed under the + OCL. The terms of the OCL are as follows: + +1. DEFINITIONS + + "Contribution" means: + + a. in the case of QSS: (i) the Original Program, where the Original + Program originates from QSS, (ii) changes and/or additions to + Unrestricted Open Source, where the Original Program originates + from Unrestricted Open Source and where such changes and/or + additions originate from QSS, and (iii) changes and/or additions + to the Program where such changes and/or additions originate from + QSS. + b. in the case of each Contributor, changes and/or additions to the + Program, where such changes and/or additions originate from and + are distributed by that particular Contributor. + + A Contribution 'originates' from a Contributor if it was added to the + Program by such Contributor itself or anyone acting on such + Contributor's behalf. Contributions do not include additions to the + Program which: (i) are separate modules of software distributed in + conjunction with the Program under their own license agreement, and + (ii) are not derivative works of the Program. + + "Contributor" means QSS and any other entity that distributes the + Program. + + "Licensed Patents " mean patent claims licensable by Contributor to + others, which are necessarily infringed by the use or sale of its + Contribution alone or when combined with the Program. + + "Unrestricted Open Source" means published source code that is + licensed for free use and distribution under an unrestricted licensing + and distribution model, such as the Berkley Software Design ("BSD") + and "BSD-like" licenses. It specifically excludes any source code + licensed under any version of the GNU General Public License (GPL) or + the GNU Lesser/Library GPL. All "Unrestricted Open Source" license + terms appear or are clearly identified in the header of any affected + source code for the Original Program. + + "Original Program" means the original version of the software + accompanying this Agreement as released by QSS, including source code, + object code and documentation, if any. + + "Program" means the Original Program and Contributions. + + "Recipient" means anyone who receives the Program under this + Agreement, including all Contributors. + +2. GRANT OF RIGHTS + + a. Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free + copyright license to reproduce, prepare derivative works of, + publicly display, publicly perform, and directly and indirectly + sublicense and distribute the Contribution of such Contributor, if + any, and such derivative works, in source code and object code + form. + b. Subject to the terms of this Agreement, each Contributor hereby + grants Recipient a non-exclusive, worldwide, royalty-free patent + license under Licensed Patents to make, use, sell, offer to sell, + import and otherwise transfer the Contribution of such + Contributor, if any, in source code and object code form. This + patent license shall apply to the combination of the Contribution + and the Program if, at the time the Contribution is added by the + Contributor, such addition of the Contribution causes such + combination to be covered by the Licensed Patents. The patent + license shall not apply to any other combinations which include + the Contribution. + c. Recipient understands that although each Contributor grants the + licenses to its Contributions set forth herein, no assurances are + provided by any Contributor that the Program does not infringe the + patent or other intellectual property rights of any other entity. + Each Contributor disclaims any liability to Recipient for claims + brought by any other entity based on infringement of intellectual + property rights or otherwise. As a condition to exercising the + rights and licenses granted hereunder, each Recipient hereby + assumes sole responsibility to secure any other intellectual + property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to distribute the + Program, it is Recipient's responsibility to acquire that license + before distributing the Program. + d. Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to grant + the copyright license set forth in this Agreement. + + 3. REQUIREMENTS + + A Contributor may choose to distribute the Program in object code form + under its own license agreement, provided that: + + a. it complies with the terms and conditions of this Agreement; and + b. its license agreement: + i. effectively disclaims on behalf of all Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and + fitness for a particular purpose; + ii. effectively excludes on behalf of all Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + and + iii. states that any provisions which differ from this Agreement + are offered by that Contributor alone and not by any other + party. + + If the Program is made available in source code form: + + a. it must be made available under this Agreement; and + b. a copy of this Agreement must be included with each copy of the + Program. Each Contributor must include the following in a + conspicuous location in the Program along with any other copyright + or attribution statements required by the terms of any applicable + Unrestricted Open Source license: + Copyright {date here}, QNX Software Systems Ltd. and others. All + Rights Reserved. + + In addition, each Contributor must identify itself as the originator + of its Contribution, if any, in a manner that reasonably allows + subsequent Recipients to identify the originator of the Contribution. + + 4. COMMERCIAL DISTRIBUTION + + Commercial distributors of software may accept certain + responsibilities with respect to end users, business partners and the + like. While this license is intended to facilitate the commercial use + of the Program, the Contributor who includes the Program in a + commercial product offering should do so in a manner which does not + create potential liability for other Contributors. Therefore, if a + Contributor includes the Program in a commercial product offering, + such Contributor ("Commercial Contributor") hereby agrees to defend + and indemnify every other Contributor ("Indemnified Contributor") + against any losses, damages and costs (collectively "Losses") arising + from claims, lawsuits and other legal actions brought by a third party + against the Indemnified Contributor to the extent caused by the acts + or omissions of such Commercial Contributor in connection with its + distribution of the Program in a commercial product offering. The + obligations in this section do not apply to any claims or Losses + relating to any actual or alleged intellectual property infringement. + In order to qualify, an Indemnified Contributor must: a) promptly + notify the Commercial Contributor in writing of such claim, and b) + allow the Commercial Contributor to control, and cooperate with the + Commercial Contributor in, the defense and any related settlement + negotiations. The Indemnified Contributor may participate in any such + claim at its own expense. + + For example, a Contributor might include the Program in a commercial + product offering, Product X. That Contributor is then a Commercial + Contributor. If that Commercial Contributor then makes performance + claims, or offers warranties related to Product X, those performance + claims and warranties are such Commercial Contributor's responsibility + alone. Under this section, the Commercial Contributor would have to + defend claims against the other Contributors related to those + performance claims and warranties, and if a court requires any other + Contributor to pay any damages as a result, the Commercial Contributor + must pay those damages. + + 5. NO WARRANTY + + Recipient acknowledges that there may be errors or bugs in the Program + and that it is imperative that Recipient conduct thorough testing to + identify and correct any problems prior to the productive use or + commercial release of any products that use the Program, and prior to + the release of any modifications, updates or enhancements thereto. + + EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS + PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY + WARRANTIES OR CONDITIONS OF TITLE, NON- INFRINGEMENT, MERCHANTABILITY + OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely + responsible for determining the appropriateness of using and + distributing the Program and assumes all risks associated with its + exercise of rights under this Agreement, including but not limited to + the risks and costs of program errors, compliance with applicable + laws, damage to or loss of data, programs or equipment, and + unavailability or interruption of operations. + + 6. DISCLAIMER OF LIABILITY + + EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR + ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING + WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR + DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED + HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + 7. GENERAL + + If any provision of this Agreement is invalid or unenforceable under + applicable law, it shall not affect the validity or enforceability of + the remainder of the terms of this Agreement, and without further + action by the parties hereto, such provision shall be reformed to the + minimum extent necessary to make such provision valid and enforceable. + + If Recipient institutes patent litigation against a Contributor with + respect to a patent applicable to software (including a cross-claim or + counterclaim in a lawsuit), then any patent licenses granted by that + Contributor to such recipient under this Agreement shall terminate as + of the date such litigation is filed. In addition, If Recipient + institutes patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Program + itself (excluding combinations of the Program with other software or + hardware) infringes such Recipient's patent(s), then such Recipient's + rights granted under Section 2(b) shall terminate as of the date such + litigation is filed. + + All Recipient's rights under this Agreement shall terminate if it + fails to comply with any of the material terms or conditions of this + Agreement and does not cure such failure in a reasonable period of + time after becoming aware of such noncompliance. If all Recipient's + rights under this Agreement terminate, Recipient agrees to cease use + and distribution of the Program as soon as reasonably practicable. + However, Recipient's obligations under this Agreement and any licenses + granted by Recipient relating to the Program shall continue and + survive. + + QSS may publish new versions (including revisions) of this Agreement + from time to time. Each new version of the Agreement will be given a + distinguishing version number. The Program (including Contributions) + may always be distributed subject to the version of the Agreement + under which it was received. In addition, after a new version of the + Agreement is published, Contributor may elect to distribute the + Program (including its Contributions) under the new version. No one + other than QSS has the right to modify this Agreement. Except as + expressly stated in Sections 2(a) and 2(b) above, Recipient receives + no rights or licenses to the intellectual property of any Contributor + under this Agreement, whether expressly, by implication, estoppel or + otherwise. All rights in the Program not expressly granted under this + Agreement are reserved. + + This Agreement is governed by the laws in force in the Province of + Ontario, Canada without regard to the conflict of law provisions + therein. The parties expressly disclaim the provisions of the United + Nations Convention on Contracts for the International Sale of Goods. + No party to this Agreement will bring a legal action under this + Agreement more than one year after the cause of action arose. Each + party waives its rights to a jury trial in any resulting litigation. + + * QNX is a registered trademark of QNX Software Systems Ltd. + + Document Version: ocl1_00