From 83043906d8f7c639d3fecb55801bf3f68a800501 Mon Sep 17 00:00:00 2001 From: guido Date: Wed, 16 Aug 2006 11:51:32 +0000 Subject: [PATCH] Import IP Filter 4.1.13 --- sys/contrib/ipfilter/netinet/IPFILTER.LICENCE | 57 ++--- sys/contrib/ipfilter/netinet/fil.c | 222 +++++++++--------- sys/contrib/ipfilter/netinet/ip_auth.c | 58 +++-- sys/contrib/ipfilter/netinet/ip_auth.h | 4 +- sys/contrib/ipfilter/netinet/ip_compat.h | 14 +- sys/contrib/ipfilter/netinet/ip_fil.h | 20 +- sys/contrib/ipfilter/netinet/ip_fil_freebsd.c | 47 ++-- sys/contrib/ipfilter/netinet/ip_frag.c | 12 +- sys/contrib/ipfilter/netinet/ip_ftp_pxy.c | 19 +- sys/contrib/ipfilter/netinet/ip_h323_pxy.c | 4 +- sys/contrib/ipfilter/netinet/ip_log.c | 26 +- sys/contrib/ipfilter/netinet/ip_nat.c | 215 ++++++++--------- sys/contrib/ipfilter/netinet/ip_pptp_pxy.c | 18 +- sys/contrib/ipfilter/netinet/ip_proxy.c | 25 +- sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c | 4 +- sys/contrib/ipfilter/netinet/ip_scan.c | 11 +- sys/contrib/ipfilter/netinet/ip_state.c | 120 ++++++---- sys/contrib/ipfilter/netinet/ip_sync.c | 23 +- sys/contrib/ipfilter/netinet/ip_sync.h | 4 +- sys/contrib/ipfilter/netinet/ipl.h | 6 +- sys/contrib/ipfilter/netinet/mlfk_ipl.c | 62 ++++- 21 files changed, 563 insertions(+), 408 deletions(-) diff --git a/sys/contrib/ipfilter/netinet/IPFILTER.LICENCE b/sys/contrib/ipfilter/netinet/IPFILTER.LICENCE index 2b4b67e86fd9..41c151ccdedb 100644 --- a/sys/contrib/ipfilter/netinet/IPFILTER.LICENCE +++ b/sys/contrib/ipfilter/netinet/IPFILTER.LICENCE @@ -1,28 +1,29 @@ -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. - -Redistribution and use, with or without modification, in source and binary -forms, are permitted provided that this notice is preserved in its entirety -and due credit is given to the original author and the contributors. - -The licence and distribution terms for any publically available version or -derivative of this code cannot be changed. i.e. this code cannot simply be -copied, in part or in whole, and put under another distribution licence -[including the GNU Public Licence.] - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. - -I hate legalese, don't you ? - +/* + * Copyright (C) 1993-2001 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. + * + * Redistribution and use, with or without modification, in source and binary + * forms, are permitted provided that this notice is preserved in its entirety + * and due credit is given to the original author and the contributors. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied, in part or in whole, and put under another distribution licence + * [including the GNU Public Licence.] + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * I hate legalese, don't you ? + */ diff --git a/sys/contrib/ipfilter/netinet/fil.c b/sys/contrib/ipfilter/netinet/fil.c index c8c1b55074f4..8f911e6043c2 100644 --- a/sys/contrib/ipfilter/netinet/fil.c +++ b/sys/contrib/ipfilter/netinet/fil.c @@ -137,7 +137,7 @@ struct file; #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.243.2.70 2005/12/07 08:15:16 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: fil.c,v 2.243.2.78 2006/03/29 11:19:54 darrenr Exp $"; #endif #ifndef _KERNEL @@ -145,12 +145,6 @@ static const char rcsid[] = "@(#)$Id: fil.c,v 2.243.2.70 2005/12/07 08:15:16 dar # include "ipt.h" # include "bpf-ipf.h" extern int opts; - -# define FR_VERBOSE(verb_pr) verbose verb_pr -# define FR_DEBUG(verb_pr) debug verb_pr -#else /* #ifndef _KERNEL */ -# define FR_VERBOSE(verb_pr) -# define FR_DEBUG(verb_pr) #endif /* _KERNEL */ @@ -1972,24 +1966,23 @@ u_32_t pass; * it, except for increasing the hit counter. */ if ((passt & FR_CALLNOW) != 0) { + frentry_t *frs; + ATOMIC_INC64(fr->fr_hits); if ((fr->fr_func != NULL) && - (fr->fr_func != (ipfunc_t)-1)) { - frentry_t *frs; + (fr->fr_func == (ipfunc_t)-1)) + continue; - frs = fin->fin_fr; - fin->fin_fr = fr; - fr = (*fr->fr_func)(fin, &passt); - if (fr == NULL) { - fin->fin_fr = frs; - continue; - } - passt = fr->fr_flags; - fin->fin_fr = fr; - } - } else { + frs = fin->fin_fr; fin->fin_fr = fr; + fr = (*fr->fr_func)(fin, &passt); + if (fr == NULL) { + fin->fin_fr = frs; + continue; + } + passt = fr->fr_flags; } + fin->fin_fr = fr; #ifdef IPFILTER_LOG /* @@ -2021,18 +2014,20 @@ u_32_t pass; (void) strncpy(fin->fin_group, fr->fr_group, FR_GROUPLEN); if (fr->fr_grp != NULL) { fin->fin_fr = *fr->fr_grp; - pass = fr_scanlist(fin, pass); + passt = fr_scanlist(fin, pass); if (fin->fin_fr == NULL) { fin->fin_rule = rulen; (void) strncpy(fin->fin_group, fr->fr_group, FR_GROUPLEN); fin->fin_fr = fr; + passt = pass; } if (fin->fin_flx & FI_DONTCACHE) logged = 1; + pass = passt; } - if (pass & FR_QUICK) { + if (passt & FR_QUICK) { /* * Finally, if we've asked to track state for this * packet, set it up. Add state for "quick" rules @@ -2044,6 +2039,7 @@ u_32_t pass; !(fin->fin_flx & FI_STATE)) { int out = fin->fin_out; + fin->fin_fr = fr; if (fr_addstate(fin, NULL, 0) != NULL) { ATOMIC_INCL(frstats[out].fr_ads); } else { @@ -2193,7 +2189,8 @@ u_32_t *passp; if (FR_ISAUTH(pass)) { if (fr_newauth(fin->fin_m, fin) != 0) { #ifdef _KERNEL - fin->fin_m = *fin->fin_mp = NULL; + if ((pass & FR_RETMASK) == 0) + fin->fin_m = *fin->fin_mp = NULL; #else ; #endif @@ -2233,21 +2230,6 @@ u_32_t *passp; } } - /* - * Finally, if we've asked to track state for this packet, set it up. - */ - if ((pass & FR_KEEPSTATE) && !(fin->fin_flx & FI_STATE)) { - if (fr_addstate(fin, NULL, 0) != NULL) { - ATOMIC_INCL(frstats[out].fr_ads); - } else { - ATOMIC_INCL(frstats[out].fr_bads); - if (FR_ISPASS(pass)) { - pass &= ~FR_CMDMASK; - pass |= FR_BLOCK; - } - } - } - fr = fin->fin_fr; if (passp != NULL) @@ -2313,8 +2295,6 @@ int out; #ifdef USE_INET6 ip6_t *ip6; #endif - SPL_INT(s); - /* * The first part of fr_check() deals with making sure that what goes * into the filtering engine makes some sense. Information about the @@ -2328,6 +2308,8 @@ int out; if ((u_int)ip & 0x3) return 2; +# else + SPL_INT(s); # endif READ_ENTER(&ipf_global); @@ -2493,6 +2475,23 @@ int out; if ((pass & FR_NOMATCH) || (fr == NULL)) fr = fr_firewall(fin, &pass); + /* + * If we've asked to track state for this packet, set it up. + * Here rather than fr_firewall because fr_checkauth may decide + * to return a packet for "keep state" + */ + if ((pass & FR_KEEPSTATE) && !(fin->fin_flx & FI_STATE)) { + if (fr_addstate(fin, NULL, 0) != NULL) { + ATOMIC_INCL(frstats[out].fr_ads); + } else { + ATOMIC_INCL(frstats[out].fr_bads); + if (FR_ISPASS(pass)) { + pass &= ~FR_CMDMASK; + pass |= FR_BLOCK; + } + } + } + fin->fin_fr = fr; /* @@ -2547,7 +2546,7 @@ int out; RWLOCK_EXIT(&ipf_mutex); - if (pass & (FR_RETRST|FR_RETICMP)) { + if ((pass & FR_RETMASK) != 0) { /* * Should we return an ICMP packet to indicate error * status passing through the packet filter ? @@ -2573,6 +2572,14 @@ int out; ATOMIC_INCL(frstats[1].fr_ret); } } + + /* + * When using return-* with auth rules, the auth code + * takes over disposing of this packet. + */ + if (FR_ISAUTH(pass) && (fin->fin_m != NULL)) { + fin->fin_m = *fin->fin_mp = NULL; + } } else { if (pass & FR_RETRST) fin->fin_error = ECONNRESET; @@ -2786,10 +2793,10 @@ int len; /* */ /* Expects ip_len to be in host byte order when called. */ /* ------------------------------------------------------------------------ */ -u_short fr_cksum(m, ip, l4proto, l4hdr) +u_short fr_cksum(m, ip, l4proto, l4hdr, l3len) mb_t *m; ip_t *ip; -int l4proto; +int l4proto, l3len; void *l4hdr; { u_short *sp, slen, sumsave, l4hlen, *csump; @@ -2814,7 +2821,7 @@ void *l4hdr; if (IP_V(ip) == 4) { #endif hlen = IP_HL(ip) << 2; - slen = ip->ip_len - hlen; + slen = l3len - hlen; sum = htons((u_short)l4proto); sum += htons(slen); sp = (u_short *)&ip->ip_src; @@ -2826,9 +2833,9 @@ void *l4hdr; } else if (IP_V(ip) == 6) { ip6 = (ip6_t *)ip; hlen = sizeof(*ip6); - slen = ntohs(ip6->ip6_plen); + slen = ntohs(l3len); sum = htons((u_short)l4proto); - sum += htons(slen); + sum += slen; sp = (u_short *)&ip6->ip6_src; sum += *sp++; /* ip6_src */ sum += *sp++; @@ -3059,7 +3066,7 @@ void *l4hdr; * SUCH DAMAGE. * * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 - * $Id: fil.c,v 2.243.2.70 2005/12/07 08:15:16 darrenr Exp $ + * $Id: fil.c,v 2.243.2.78 2006/03/29 11:19:54 darrenr Exp $ */ /* * Copy data from an mbuf chain starting "off" bytes from the beginning, @@ -3472,7 +3479,7 @@ int proto, flags; char *memstr(src, dst, slen, dlen) const char *src; char *dst; -int slen, dlen; +size_t slen, dlen; { char *s = NULL; @@ -3760,13 +3767,7 @@ size_t size; caddr_t ca; int err; -# if SOLARIS - err = COPYIN(dst, (caddr_t)&ca, sizeof(ca)); - if (err != 0) - return err; -# else bcopy(dst, (caddr_t)&ca, sizeof(ca)); -# endif err = COPYOUT(src, ca, size); return err; } @@ -4886,7 +4887,7 @@ ipftq_t *ifq; ifq->ifq_next->ifq_pnext = ifq->ifq_pnext; MUTEX_DESTROY(&ifq->ifq_lock); - fr_userifqs--; + ATOMIC_DEC(fr_userifqs); KFREE(ifq); } @@ -4908,8 +4909,6 @@ ipftqent_t *tqe; ipftq_t *ifq; ifq = tqe->tqe_ifq; - if (ifq == NULL) - return; MUTEX_ENTER(&ifq->ifq_lock); @@ -4981,24 +4980,21 @@ ipftqent_t *tqe; tqe->tqe_die = fr_ticks + ifq->ifq_ttl; MUTEX_ENTER(&ifq->ifq_lock); - if (tqe->tqe_next == NULL) { /* at the end already ? */ - MUTEX_EXIT(&ifq->ifq_lock); - return; + if (tqe->tqe_next != NULL) { /* at the end already ? */ + /* + * Remove from list + */ + *tqe->tqe_pnext = tqe->tqe_next; + tqe->tqe_next->tqe_pnext = tqe->tqe_pnext; + + /* + * Make it the last entry. + */ + tqe->tqe_next = NULL; + tqe->tqe_pnext = ifq->ifq_tail; + *ifq->ifq_tail = tqe; + ifq->ifq_tail = &tqe->tqe_next; } - - /* - * Remove from list - */ - *tqe->tqe_pnext = tqe->tqe_next; - tqe->tqe_next->tqe_pnext = tqe->tqe_pnext; - - /* - * Make it the last entry. - */ - tqe->tqe_next = NULL; - tqe->tqe_pnext = ifq->ifq_tail; - *ifq->ifq_tail = tqe; - ifq->ifq_tail = &tqe->tqe_next; MUTEX_EXIT(&ifq->ifq_lock); } @@ -5050,46 +5046,44 @@ ipftq_t *oifq, *nifq; * Is the operation here going to be a no-op ? */ MUTEX_ENTER(&oifq->ifq_lock); - if (oifq == nifq && *oifq->ifq_tail == tqe) { - MUTEX_EXIT(&oifq->ifq_lock); - return; + if ((oifq != nifq) || (*oifq->ifq_tail != tqe)) { + /* + * Remove from the old queue + */ + *tqe->tqe_pnext = tqe->tqe_next; + if (tqe->tqe_next) + tqe->tqe_next->tqe_pnext = tqe->tqe_pnext; + else + oifq->ifq_tail = tqe->tqe_pnext; + tqe->tqe_next = NULL; + + /* + * If we're moving from one queue to another, release the + * lock on the old queue and get a lock on the new queue. + * For user defined queues, if we're moving off it, call + * delete in case it can now be freed. + */ + if (oifq != nifq) { + tqe->tqe_ifq = NULL; + + (void) fr_deletetimeoutqueue(oifq); + + MUTEX_EXIT(&oifq->ifq_lock); + + MUTEX_ENTER(&nifq->ifq_lock); + + tqe->tqe_ifq = nifq; + nifq->ifq_ref++; + } + + /* + * Add to the bottom of the new queue + */ + tqe->tqe_die = fr_ticks + nifq->ifq_ttl; + tqe->tqe_pnext = nifq->ifq_tail; + *nifq->ifq_tail = tqe; + nifq->ifq_tail = &tqe->tqe_next; } - - /* - * Remove from the old queue - */ - *tqe->tqe_pnext = tqe->tqe_next; - if (tqe->tqe_next) - tqe->tqe_next->tqe_pnext = tqe->tqe_pnext; - else - oifq->ifq_tail = tqe->tqe_pnext; - tqe->tqe_next = NULL; - - /* - * If we're moving from one queue to another, release the lock on the - * old queue and get a lock on the new queue. For user defined queues, - * if we're moving off it, call delete in case it can now be freed. - */ - if (oifq != nifq) { - tqe->tqe_ifq = NULL; - - (void) fr_deletetimeoutqueue(oifq); - - MUTEX_EXIT(&oifq->ifq_lock); - - MUTEX_ENTER(&nifq->ifq_lock); - - tqe->tqe_ifq = nifq; - nifq->ifq_ref++; - } - - /* - * Add to the bottom of the new queue - */ - tqe->tqe_die = fr_ticks + nifq->ifq_ttl; - tqe->tqe_pnext = nifq->ifq_tail; - *nifq->ifq_tail = tqe; - nifq->ifq_tail = &tqe->tqe_next; MUTEX_EXIT(&nifq->ifq_lock); } @@ -5573,7 +5567,7 @@ fr_info_t *fin; if (dosum) sum = fr_cksum(fin->fin_m, fin->fin_ip, - fin->fin_p, fin->fin_dp); + fin->fin_p, fin->fin_dp, fin->fin_plen); #if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) && defined(ICK_VALID) } #endif diff --git a/sys/contrib/ipfilter/netinet/ip_auth.c b/sys/contrib/ipfilter/netinet/ip_auth.c index b6f0844354bf..0f0c2ff8007d 100644 --- a/sys/contrib/ipfilter/netinet/ip_auth.c +++ b/sys/contrib/ipfilter/netinet/ip_auth.c @@ -117,12 +117,13 @@ extern struct ifqueue ipintrq; /* ip packet input queue */ /* END OF INCLUDES */ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_auth.c,v 2.73.2.5 2005/06/12 07:18:14 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_auth.c,v 2.73.2.13 2006/03/29 11:19:55 darrenr Exp $"; #endif -#if SOLARIS +#if SOLARIS && defined(_KERNEL) extern kcondvar_t ipfauthwait; +extern struct pollhead iplpollhead[IPL_LOGSIZE]; #endif /* SOLARIS */ #if defined(linux) && defined(_KERNEL) wait_queue_head_t fr_authnext_linux; @@ -317,7 +318,7 @@ fr_info_t *fin; fra = fr_auth + i; fra->fra_index = i; - fra->fra_pass = 0; + fra->fra_pass = fin->fin_fr->fr_flags; fra->fra_age = fr_defaultauthage; bcopy((char *)fin, (char *)&fra->fra_info, sizeof(*fin)); #if !defined(sparc) && !defined(m68k) @@ -339,17 +340,15 @@ fr_info_t *fin; } #endif #if SOLARIS && defined(_KERNEL) + COPYIFNAME(fin->fin_ifp, fra->fra_info.fin_ifname); m->b_rptr -= qpi->qpi_off; fr_authpkts[i] = *(mblk_t **)fin->fin_mp; fra->fra_q = qpi->qpi_q; /* The queue can disappear! */ + fra->fra_m = *fin->fin_mp; + fra->fra_info.fin_mp = &fra->fra_m; cv_signal(&ipfauthwait); + pollwakeup(&iplpollhead[IPL_LOGAUTH], POLLIN|POLLRDNORM); #else -# if defined(BSD) && !defined(sparc) && (BSD >= 199306) - if (!fin->fin_out) { - ip->ip_len = htons(ip->ip_len); - ip->ip_off = htons(ip->ip_off); - } -# endif fr_authpkts[i] = m; WAKEUP(&fr_authnext,0); #endif @@ -362,15 +361,15 @@ caddr_t data; ioctlcmd_t cmd; int mode; { + frauth_t auth, *au = &auth, *fra; + int i, error = 0, len; + char *t; mb_t *m; #if defined(_KERNEL) && !defined(MENTAT) && !defined(linux) && \ (!defined(__FreeBSD_version) || (__FreeBSD_version < 501000)) struct ifqueue *ifq; SPL_INT(s); #endif - frauth_t auth, *au = &auth, *fra; - int i, error = 0, len; - char *t; switch (cmd) { @@ -399,10 +398,14 @@ int mode; case SIOCAUTHW: fr_authioctlloop: error = fr_inobj(data, au, IPFOBJ_FRAUTH); + if (error != 0) + break; READ_ENTER(&ipf_auth); if ((fr_authnext != fr_authend) && fr_authpkts[fr_authnext]) { error = fr_outobj(data, &fr_auth[fr_authnext], IPFOBJ_FRAUTH); + if (error != 0) + break; if (auth.fra_len != 0 && auth.fra_buf != NULL) { /* * Copy packet contents out to user space if @@ -416,11 +419,12 @@ int mode; for (t = auth.fra_buf; m && (len > 0); ) { i = MIN(M_LEN(m), len); error = copyoutptr(MTOD(m, char *), - t, i); + &t, i); len -= i; t += i; if (error != 0) break; + m = m->m_next; } } RWLOCK_EXIT(&ipf_auth); @@ -473,10 +477,8 @@ int mode; #endif MUTEX_EXIT(&ipf_authmx); READ_ENTER(&ipf_global); - if (error == 0) { - READ_ENTER(&ipf_auth); + if (error == 0) goto fr_authioctlloop; - } break; case SIOCAUTHR: @@ -487,6 +489,7 @@ int mode; WRITE_ENTER(&ipf_auth); i = au->fra_index; fra = fr_auth + i; + error = 0; if ((i < 0) || (i >= fr_authsize) || (fra->fra_info.fin_id != au->fra_info.fin_id)) { RWLOCK_EXIT(&ipf_auth); @@ -501,7 +504,11 @@ int mode; #ifdef _KERNEL if ((m != NULL) && (au->fra_info.fin_out != 0)) { # ifdef MENTAT - error = !putq(fra->fra_q, m); + error = ipf_inject(&fra->fra_info); + if (error != 0) { + FREE_MB_T(m); + error = ENOBUFS; + } # else /* MENTAT */ # if defined(linux) || defined(AIX) # else @@ -521,7 +528,11 @@ int mode; fr_authstats.fas_sendok++; } else if (m) { # ifdef MENTAT - error = !putq(fra->fra_q, m); + error = ipf_inject(&fra->fra_info); + if (error != 0) { + FREE_MB_T(m); + error = ENOBUFS; + } # else /* MENTAT */ # if defined(linux) || defined(AIX) # else @@ -552,10 +563,6 @@ int mode; fr_authstats.fas_queok++; } else error = EINVAL; -# ifdef MENTAT - if (error != 0) - error = EINVAL; -# else /* MENTAT */ /* * If we experience an error which will result in the packet * not being processed, make sure we advance to the next one. @@ -579,7 +586,6 @@ int mode; } } } -# endif /* MENTAT */ #endif /* _KERNEL */ SPL_X(s); break; @@ -794,3 +800,9 @@ int fr_authflush() return num_flushed; } + + +int fr_auth_waiting() +{ + return (fr_authnext != fr_authend) && fr_authpkts[fr_authnext]; +} diff --git a/sys/contrib/ipfilter/netinet/ip_auth.h b/sys/contrib/ipfilter/netinet/ip_auth.h index 389277827009..22c69b77c684 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.16 2003/07/25 12:29:56 darrenr Exp $ + * $Id: ip_auth.h,v 2.16.2.2 2006/03/16 06:45:49 darrenr Exp $ * */ #ifndef __IP_AUTH_H__ @@ -20,6 +20,7 @@ typedef struct frauth { char *fra_buf; #ifdef MENTAT queue_t *fra_q; + mb_t *fra_m; #endif } frauth_t; @@ -60,5 +61,6 @@ extern mb_t **fr_authpkts; extern int fr_newauth __P((mb_t *, fr_info_t *)); extern int fr_preauthcmd __P((ioctlcmd_t, frentry_t *, frentry_t **)); extern int fr_auth_ioctl __P((caddr_t, ioctlcmd_t, int)); +extern int fr_auth_waiting __P((void)); #endif /* __IP_AUTH_H__ */ diff --git a/sys/contrib/ipfilter/netinet/ip_compat.h b/sys/contrib/ipfilter/netinet/ip_compat.h index f48a98dbfda3..0a294cff58d8 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.142.2.33 2005/12/04 23:40:17 darrenr Exp $ + * $Id: ip_compat.h,v 2.142.2.36 2006/03/26 05:50:29 darrenr Exp $ */ #ifndef __IP_COMPAT_H__ @@ -441,6 +441,7 @@ extern void *get_unit __P((char *, int)); wakeup(id + x); \ spinunlock(_l); \ } +# define POLLWAKEUP(x) ; # define KMALLOC(a, b) MALLOC((a), b, sizeof(*(a)), M_IOSYS, M_NOWAIT) # define KMALLOCS(a, b, c) MALLOC((a), b, (c), M_IOSYS, M_NOWAIT) # define KFREE(x) kmem_free((char *)(x), sizeof(*(x))) @@ -578,6 +579,7 @@ typedef struct { # define UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,c,d) # define SLEEP(id, n) sleep((id), PZERO+1) # define WAKEUP(id,x) wakeup(id+x) +# define POLLWAKEUP(x) ; # define KFREE(x) kmem_free((char *)(x), sizeof(*(x))) # define KFREES(x,s) kmem_free((char *)(x), (s)) # define GETIFP(n,v) ifunit(n) @@ -659,6 +661,7 @@ typedef struct mbuf mb_t; # define GETIFP(n, v) ifunit(n) # define GET_MINOR getminor # define WAKEUP(id,x) wakeup(id + x) +# define POLLWAKEUP(x) ; # define COPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c)) # define COPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c)) # define BCOPYIN(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) @@ -1029,6 +1032,7 @@ typedef u_int32_t u_32_t; # define KFREES(x,s) kmem_free((char *)(x), (s)) # define SLEEP(id, n) sleep((id), PZERO+1) # define WAKEUP(id,x) wakeup(id + x) +# define POLLWAKEUP(x) ; # define UIOMOVE(a,b,c,d) uiomove((caddr_t)a,b,c,d) # define IPF_PANIC(x,y) if (x) { printf y; panic("ipf_panic"); } @@ -1074,6 +1078,7 @@ struct ip6_ext { # define FREE_MB_T(m) kfree_skb(m) # define GETKTIME(x) do_gettimeofday((struct timeval *)x) # define SLEEP(x,s) 0, interruptible_sleep_on(x##_linux) +# define POLLWAKEUP(x) ; # define WAKEUP(x,y) wake_up(x##_linux + y) # define UIOMOVE(a,b,c,d) uiomove(a,b,c,d) # define USE_MUTEXES @@ -1265,6 +1270,7 @@ extern void* getifp __P((char *, int)); # define GET_MINOR minor # define SLEEP(id, n) sleepx((id), PZERO+1, 0) # define WAKEUP(id,x) wakeup(id) +# define POLLWAKEUP(x) ; # define COPYIN(a,b,c) copyin((caddr_t)(a), (caddr_t)(b), (c)) # define COPYOUT(a,b,c) copyout((caddr_t)(a), (caddr_t)(b), (c)) # define BCOPYIN(a,b,c) bcopy((caddr_t)(a), (caddr_t)(b), (c)) @@ -1429,6 +1435,7 @@ typedef struct mb_s { # define FREE_MB_T(x) # define SLEEP(x,y) 1; # define WAKEUP(x,y) ; +# define POLLWAKEUP(y) ; # define IPF_PANIC(x,y) ; # define PANIC(x,y) ; # define SPL_NET(x) ; @@ -1451,6 +1458,7 @@ typedef struct mb_s { # 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 *)); +extern int bcopywrap __P((void *, void *, size_t)); # ifndef CACHE_HASH # define CACHE_HASH(x) ((IFNAME(fin->fin_ifp)[0] + \ ((struct ifnet *)fin->fin_ifp)->if_unit) & 7) @@ -1529,6 +1537,9 @@ typedef struct ip6_hdr ip6_t; #endif #if defined(_KERNEL) +# ifdef BSD +extern struct selinfo ipfselwait[]; +# endif # ifdef MENTAT # define COPYDATA mb_copydata # define COPYBACK mb_copyback @@ -1578,6 +1589,7 @@ MALLOC_DECLARE(M_IPFILTER); # define UIOMOVE(a,b,c,d) uiomove(a,b,d) # define SLEEP(id, n) tsleep((id), PPAUSE|PCATCH, n, 0) # define WAKEUP(id,x) wakeup(id+x) +# define POLLWAKEUP(x) selwakeup(ipfselwait+x) # define GETIFP(n, v) ifunit(n) # endif /* (Free)BSD */ diff --git a/sys/contrib/ipfilter/netinet/ip_fil.h b/sys/contrib/ipfilter/netinet/ip_fil.h index 45d5bb4734c8..5a13993d4168 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.170.2.23 2005/12/04 23:39:28 darrenr Exp $ + * $Id: ip_fil.h,v 2.170.2.29 2006/03/29 11:19:55 darrenr Exp $ */ #ifndef __IP_FIL_H__ @@ -305,6 +305,7 @@ typedef struct fr_info { #ifdef MENTAT mb_t *fin_qfm; /* pointer to mblk where pkt starts */ void *fin_qpi; + char fin_ifname[LIFNAMSIZ]; #endif #ifdef __sgi void *fin_hbuf; @@ -1133,6 +1134,17 @@ typedef struct ipftune { # endif #endif +#ifdef _KERNEL +# define FR_VERBOSE(verb_pr) +# define FR_DEBUG(verb_pr) +#else +extern void debug __P((char *, ...)); +extern void verbose __P((char *, ...)); +# define FR_VERBOSE(verb_pr) verbose verb_pr +# define FR_DEBUG(verb_pr) debug verb_pr +#endif + + #ifndef _KERNEL extern int fr_check __P((struct ip *, int, void *, int, mb_t **)); extern int (*fr_checkp) __P((ip_t *, int, void *, int, mb_t **)); @@ -1148,6 +1160,7 @@ extern int iplioctl __P((int, ioctlcmd_t, caddr_t, int)); extern int iplopen __P((dev_t, int)); extern int iplclose __P((dev_t, int)); extern void m_freem __P((mb_t *)); +extern int bcopywrap __P((void *, void *, size_t)); #else /* #ifndef _KERNEL */ # if defined(__NetBSD__) && defined(PFIL_HOOKS) extern void ipfilterattach __P((int)); @@ -1259,7 +1272,7 @@ extern ipfrwlock_t ipf_mutex, ipf_global, ip_poolrw, ipf_ipidfrag; extern ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth; extern ipfrwlock_t ipf_frcache; -extern char *memstr __P((const char *, char *, int, int)); +extern char *memstr __P((const char *, char *, size_t, size_t)); extern int count4bits __P((u_32_t)); extern int frrequest __P((int, ioctlcmd_t, caddr_t, int, int)); extern char *getifname __P((struct ifnet *)); @@ -1316,6 +1329,7 @@ extern void fr_delgroup __P((char *, minor_t, int)); extern frgroup_t *fr_findgroup __P((char *, minor_t, int, frgroup_t ***)); extern int fr_loginit __P((void)); +extern int ipflog_canread __P((int)); extern int ipflog_clear __P((minor_t)); extern int ipflog_read __P((minor_t, uio_t *)); extern int ipflog __P((fr_info_t *, u_int)); @@ -1324,7 +1338,7 @@ extern void fr_logunload __P((void)); extern frentry_t *fr_acctpkt __P((fr_info_t *, u_32_t *)); extern int fr_copytolog __P((int, char *, int)); -extern u_short fr_cksum __P((mb_t *, ip_t *, int, void *)); +extern u_short fr_cksum __P((mb_t *, ip_t *, int, void *, int)); extern void fr_deinitialise __P((void)); extern frentry_t *fr_dolog __P((fr_info_t *, u_32_t *)); extern frentry_t *fr_dstgrpmap __P((fr_info_t *, u_32_t *)); diff --git a/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c b/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c index 760122e393b3..d361beaa5710 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c +++ b/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c @@ -5,7 +5,7 @@ */ #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_freebsd.c,v 2.53.2.27 2005/08/20 13:48:19 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_fil_freebsd.c,v 2.53.2.32 2006/03/25 13:03:01 darrenr Exp $"; #endif #if defined(KERNEL) || defined(_KERNEL) @@ -55,6 +55,7 @@ static const char rcsid[] = "@(#)$Id: ip_fil_freebsd.c,v 2.53.2.27 2005/08/20 13 #endif #include #include +#include #include #if __FreeBSD_version >= 300000 @@ -131,6 +132,7 @@ int ipf_locks_done = 0; #if (__FreeBSD_version >= 300000) struct callout_handle fr_slowtimer_ch; #endif +struct selinfo ipfselwait[IPL_LOGSIZE]; #if (__FreeBSD_version >= 500011) # include @@ -300,6 +302,7 @@ int iplattach() fr_checkp = fr_check; } + bzero((char *)ipfselwait, sizeof(ipfselwait)); bzero((char *)frcache, sizeof(frcache)); fr_running = 1; @@ -476,9 +479,11 @@ int mode; } SPL_NET(s); + READ_ENTER(&ipf_global); error = fr_ioctlswitch(unit, data, cmd, mode); if (error != -1) { + RWLOCK_EXIT(&ipf_global); SPL_X(s); return error; } @@ -619,7 +624,10 @@ int mode; error = EINVAL; break; } + + RWLOCK_EXIT(&ipf_global); SPL_X(s); + return error; } @@ -742,14 +750,18 @@ dev_t dev; #endif register struct uio *uio; { + u_int xmin = GET_MINOR(dev); + + if (xmin < 0) + return ENXIO; # ifdef IPFILTER_SYNC - if (GET_MINOR(dev) == IPL_LOGSYNC) + if (xmin == IPL_LOGSYNC) return ipfsync_read(uio); # endif #ifdef IPFILTER_LOG - return ipflog_read(GET_MINOR(dev), uio); + return ipflog_read(xmin, uio); #else return ENXIO; #endif @@ -1155,6 +1167,8 @@ frdest_t *fdp; u_short ip_off; frentry_t *fr; + ro = NULL; + #ifdef M_WRITABLE /* * HOT FIX/KLUDGE: @@ -1168,15 +1182,15 @@ frdest_t *fdp; * problem. */ if (M_WRITABLE(m) == 0) { - if ((m0 = m_dup(m, M_DONTWAIT)) != 0) { + m0 = m_dup(m, M_DONTWAIT); + if (m0 != 0) { FREE_MB_T(m); m = m0; *mpp = m; } else { error = ENOBUFS; FREE_MB_T(m); - *mpp = NULL; - fr_frouteok[1]++; + goto done; } } #endif @@ -1218,18 +1232,8 @@ frdest_t *fdp; goto bad; } - /* - * In case we're here due to "to " being used with "keep state", - * check that we're going in the correct direction. - */ - if ((fr != NULL) && (fin->fin_rev != 0)) { - if ((ifp != NULL) && (fdp == &fr->fr_tif)) - return -1; - } - if (fdp != NULL) { - if (fdp->fd_ip.s_addr != 0) - dst->sin_addr = fdp->fd_ip; - } + if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0)) + dst->sin_addr = fdp->fd_ip; dst->sin_len = sizeof(*dst); rtalloc(ro); @@ -1346,6 +1350,7 @@ frdest_t *fdp; else mhip->ip_off |= IP_MF; mhip->ip_len = htons((u_short)(len + mhlen)); + *mnext = m; m->m_next = m_copy(m0, off, len); if (m->m_next == 0) { error = ENOBUFS; /* ??? */ @@ -1356,7 +1361,6 @@ frdest_t *fdp; mhip->ip_off = htons((u_short)mhip->ip_off); mhip->ip_sum = 0; mhip->ip_sum = in_cksum(m, mhlen); - *mnext = m; mnext = &m->m_act; } /* @@ -1385,7 +1389,7 @@ frdest_t *fdp; else fr_frouteok[1]++; - if (ro->ro_rt) { + if ((ro != NULL) && (ro->ro_rt != NULL)) { RTFREE(ro->ro_rt); } *mpp = NULL; @@ -1488,6 +1492,9 @@ struct in_addr *inp, *inpmask; else if (atype == FRI_PEERADDR) sock = ifa->ifa_dstaddr; + if (sock == NULL) + return -1; + #ifdef USE_INET6 if (v == 6) { return fr_ifpfillv6addr(atype, (struct sockaddr_in6 *)sock, diff --git a/sys/contrib/ipfilter/netinet/ip_frag.c b/sys/contrib/ipfilter/netinet/ip_frag.c index db1a0afbd8db..18360cee09c6 100644 --- a/sys/contrib/ipfilter/netinet/ip_frag.c +++ b/sys/contrib/ipfilter/netinet/ip_frag.c @@ -100,7 +100,7 @@ extern struct timeout fr_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.77.2.4 2005/08/20 13:48:21 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_frag.c,v 2.77.2.5 2006/02/26 08:26:54 darrenr Exp $"; #endif @@ -224,6 +224,7 @@ ipfr_t *table[]; { ipfr_t *fra, frag; u_int idx, off; + frentry_t *fr; ip_t *ip; if (ipfr_inuse >= IPFT_SIZE) @@ -275,12 +276,9 @@ ipfr_t *table[]; return NULL; } - fra->ipfr_rule = fin->fin_fr; - if (fra->ipfr_rule != NULL) { - - frentry_t *fr; - - fr = fin->fin_fr; + fr = fin->fin_fr; + fra->ipfr_rule = fr; + if (fr != NULL) { MUTEX_ENTER(&fr->fr_lock); fr->fr_ref++; MUTEX_EXIT(&fr->fr_lock); diff --git a/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c b/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c index 860d75ecb80d..e72d6fec2280 100644 --- a/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c +++ b/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c @@ -6,7 +6,7 @@ * Simple FTP transparent proxy for in-kernel use. For use with the NAT * code. * - * $Id: ip_ftp_pxy.c,v 2.88.2.16 2005/12/04 23:39:27 darrenr Exp $ + * $Id: ip_ftp_pxy.c,v 2.88.2.19 2006/04/01 10:14:53 darrenr Exp $ */ #define IPF_FTP_PROXY @@ -366,7 +366,7 @@ int dlen; fi.fin_fi.fi_daddr = nat->nat_inip.s_addr; ip->ip_dst = nat->nat_inip; } - (void) fr_addstate(&fi, &nat2->nat_state, SI_W_DPORT); + (void) fr_addstate(&fi, NULL, SI_W_DPORT); if (fi.fin_state != NULL) fr_statederef(&fi, (ipstate_t **)&fi.fin_state); } @@ -728,7 +728,7 @@ u_int data_ip; fi.fin_fi.fi_daddr = nat->nat_inip.s_addr; ip->ip_dst = nat->nat_inip; } - (void) fr_addstate(&fi, &nat2->nat_state, sflags); + (void) fr_addstate(&fi, NULL, sflags); if (fi.fin_state != NULL) fr_statederef(&fi, (ipstate_t **)&fi.fin_state); } @@ -1027,13 +1027,14 @@ int rv; if (ippr_ftp_debug > 4) printf("ippr_ftp_process: mlen %d\n", mlen); - if (mlen <= 0) { - if ((tcp->th_flags & TH_OPENING) == TH_OPENING) { - f->ftps_seq[0] = thseq + 1; - t->ftps_seq[0] = thack; - } + if ((mlen == 0) && ((tcp->th_flags & TH_OPENING) == TH_OPENING)) { + f->ftps_seq[0] = thseq + 1; + t->ftps_seq[0] = thack; + return 0; + } else if (mlen < 0) { return 0; } + aps = nat->nat_aps; sel = aps->aps_sel[1 - rv]; @@ -1423,7 +1424,7 @@ int dlen; ap += *s++ - '0'; } - if (!s) + if (!*s) return 0; if (*s == '|') diff --git a/sys/contrib/ipfilter/netinet/ip_h323_pxy.c b/sys/contrib/ipfilter/netinet/ip_h323_pxy.c index 1933203e05cd..7fc62276c597 100644 --- a/sys/contrib/ipfilter/netinet/ip_h323_pxy.c +++ b/sys/contrib/ipfilter/netinet/ip_h323_pxy.c @@ -1,5 +1,3 @@ -/* $FreeBSD$ */ - /* * Copyright 2001, QNX Software Systems Ltd. All Rights Reserved * @@ -248,7 +246,7 @@ nat_t *nat; tcp = (tcphdr_t *)fin->fin_dp; ipaddr = nat->nat_inip.s_addr; data = (caddr_t)tcp + (TCP_OFF(tcp) << 2); - datlen = ip->ip_len - fin->fin_hlen - (TCP_OFF(tcp) << 2); + datlen = fin->fin_dlen - (TCP_OFF(tcp) << 2); if (find_port(ipaddr, data, datlen, &off, &port) == 0) { fr_info_t fi; nat_t *nat2; diff --git a/sys/contrib/ipfilter/netinet/ip_log.c b/sys/contrib/ipfilter/netinet/ip_log.c index 6618c6d6d841..550855709d02 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.75.2.7 2005/06/11 07:47:44 darrenr Exp $ + * $Id: ip_log.c,v 2.75.2.11 2006/03/26 13:50:47 darrenr Exp $ */ #include #if defined(KERNEL) || defined(_KERNEL) @@ -65,6 +65,10 @@ struct file; # include # endif # include +# include +# if __FreeBSD_version >= 500000 +# include +# endif #else # if !defined(__hpux) && defined(_KERNEL) # include @@ -145,6 +149,7 @@ wait_queue_head_t iplh_linux[IPL_LOGSIZE]; # endif # if SOLARIS extern kcondvar_t iplwait; +extern struct pollhead iplpollhead[IPL_LOGSIZE]; # endif iplog_t **iplh[IPL_LOGSIZE], *iplt[IPL_LOGSIZE], *ipll[IPL_LOGSIZE]; @@ -503,9 +508,11 @@ int *types, cnt; # if SOLARIS && defined(_KERNEL) cv_signal(&iplwait); MUTEX_EXIT(&ipl_mutex); + pollwakeup(&iplpollhead[dev], POLLRDNORM); # else MUTEX_EXIT(&ipl_mutex); - WAKEUP(iplh,dev); + WAKEUP(iplh, dev); + POLLWAKEUP(dev); # endif SPL_X(s); # ifdef IPL_SELECT @@ -663,4 +670,19 @@ minor_t unit; SPL_X(s); return used; } + + +/* ------------------------------------------------------------------------ */ +/* Function: ipflog_canread */ +/* Returns: int - 0 == no data to read, 1 = data present */ +/* Parameters: unit(I) - device we are reading from */ +/* */ +/* Returns an indication of whether or not there is data present in the */ +/* current buffer for the selected ipf device. */ +/* ------------------------------------------------------------------------ */ +int ipflog_canread(unit) +int unit; +{ + return iplt[unit] != NULL; +} #endif /* IPFILTER_LOG */ diff --git a/sys/contrib/ipfilter/netinet/ip_nat.c b/sys/contrib/ipfilter/netinet/ip_nat.c index 30bba0787643..af73ebf03643 100644 --- a/sys/contrib/ipfilter/netinet/ip_nat.c +++ b/sys/contrib/ipfilter/netinet/ip_nat.c @@ -107,7 +107,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.195.2.47 2005/11/14 17:13:35 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_nat.c,v 2.195.2.56 2006/04/01 10:15:34 darrenr Exp $"; #endif @@ -191,7 +191,7 @@ static int nat_siocaddnat __P((ipnat_t *, ipnat_t **, int)); static void nat_siocdelnat __P((ipnat_t *, ipnat_t **, int)); static int nat_finalise __P((fr_info_t *, nat_t *, natinfo_t *, tcphdr_t *, nat_t **, int)); -static void nat_resolverule __P((ipnat_t *)); +static int nat_resolverule __P((ipnat_t *)); static nat_t *fr_natclone __P((fr_info_t *, nat_t *)); static void nat_mssclamp __P((tcphdr_t *, u_32_t, fr_info_t *, u_short *)); static int nat_wildok __P((nat_t *, int, int, int, int)); @@ -865,11 +865,8 @@ int getlock; { int error = 0, i, j; - nat_resolverule(n); - if (n->in_plabel[0] != '\0') { - if (n->in_apr == NULL) - return ENOENT; - } + if (nat_resolverule(n) != 0) + return ENOENT; if ((n->in_age[0] == 0) && (n->in_age[1] != 0)) return EINVAL; @@ -994,7 +991,7 @@ int getlock; /* from information passed to the kernel, then add it to the appropriate */ /* NAT rule table(s). */ /* ------------------------------------------------------------------------ */ -static void nat_resolverule(n) +static int nat_resolverule(n) ipnat_t *n; { n->in_ifnames[0][LIFNAMSIZ - 1] = '\0'; @@ -1005,12 +1002,15 @@ ipnat_t *n; (void) strncpy(n->in_ifnames[1], n->in_ifnames[0], LIFNAMSIZ); n->in_ifps[1] = n->in_ifps[0]; } else { - n->in_ifps[1] = fr_resolvenic(n->in_ifnames[0], 4); + n->in_ifps[1] = fr_resolvenic(n->in_ifnames[1], 4); } if (n->in_plabel[0] != '\0') { n->in_apr = appr_lookup(n->in_p, n->in_plabel); + if (n->in_apr == NULL) + return -1; } + return 0; } @@ -1338,23 +1338,31 @@ int getlock; ATOMIC_INC(nat_stats.ns_rules); - nat_resolverule(in); + if (nat_resolverule(in) != 0) { + error = ESRCH; + goto junkput; + } } /* * Check that the NAT entry doesn't already exist in the kernel. + * + * For NAT_OUTBOUND, we're lookup for a duplicate MAP entry. To do + * this, we check to see if the inbound combination of addresses and + * ports is already known. Similar logic is applied for NAT_INBOUND. + * */ bzero((char *)&fin, sizeof(fin)); fin.fin_p = nat->nat_p; + fin.fin_ifp = nat->nat_ifps[0]; if (nat->nat_dir == NAT_OUTBOUND) { fin.fin_data[0] = ntohs(nat->nat_oport); fin.fin_data[1] = ntohs(nat->nat_outport); - fin.fin_ifp = nat->nat_ifps[1]; if (getlock) { READ_ENTER(&ipf_nat); } - n = nat_inlookup(&fin, 0, fin.fin_p, nat->nat_oip, - nat->nat_inip); + n = nat_inlookup(&fin, nat->nat_flags, fin.fin_p, + nat->nat_oip, nat->nat_inip); if (getlock) { RWLOCK_EXIT(&ipf_nat); } @@ -1365,12 +1373,11 @@ int getlock; } else if (nat->nat_dir == NAT_INBOUND) { fin.fin_data[0] = ntohs(nat->nat_outport); fin.fin_data[1] = ntohs(nat->nat_oport); - fin.fin_ifp = nat->nat_ifps[0]; if (getlock) { READ_ENTER(&ipf_nat); } - n = nat_outlookup(&fin, 0, fin.fin_p, nat->nat_outip, - nat->nat_oip); + n = nat_outlookup(&fin, nat->nat_flags, fin.fin_p, + nat->nat_outip, nat->nat_oip); if (getlock) { RWLOCK_EXIT(&ipf_nat); } @@ -1435,6 +1442,12 @@ int getlock; fr->fr_ref = 1; (void) fr_outobj(data, ipnn, IPFOBJ_NATSAVE); bcopy((char *)&ipnn->ipn_fr, (char *)fr, sizeof(*fr)); + + fr->fr_ref = 1; + fr->fr_dsize = 0; + fr->fr_data = NULL; + fr->fr_type = FR_T_NONE; + MUTEX_NUKE(&fr->fr_lock); MUTEX_INIT(&fr->fr_lock, "nat-filter rule lock"); } else { @@ -1574,6 +1587,9 @@ int logtype; MUTEX_EXIT(&ipf_nat_new); return; } + /* + * At this point, nat_ref can be either 0 or -1 + */ #ifdef IPFILTER_SYNC if (nat->nat_sync) @@ -2152,6 +2168,9 @@ natinfo_t *ni; /* structure for a "MAP" rule (outgoing NAT translation); (2) deal with */ /* creating a new NAT structure for a "RDR" rule (incoming NAT translation) */ /* and (3) building that structure and putting it into the NAT table(s). */ +/* */ +/* NOTE: natsave should NOT be used top point back to an ipstate_t struct */ +/* as it can result in memory being corrupted. */ /* ------------------------------------------------------------------------ */ nat_t *nat_new(fin, np, natsave, flags, direction) fr_info_t *fin; @@ -2245,6 +2264,7 @@ int direction; natl = nat_outlookup(fin, nflags, (u_int)fin->fin_p, fin->fin_src, fin->fin_dst); if (natl != NULL) { + KFREE(nat); nat = natl; goto done; } @@ -2262,6 +2282,7 @@ int direction; natl = nat_inlookup(fin, nflags, (u_int)fin->fin_p, fin->fin_src, fin->fin_dst); if (natl != NULL) { + KFREE(nat); nat = natl; goto done; } @@ -2375,7 +2396,12 @@ int direction; np = ni->nai_np; - COPYIFNAME(fin->fin_ifp, nat->nat_ifnames[0]); + if (np->in_ifps[0] != NULL) { + COPYIFNAME(np->in_ifps[0], nat->nat_ifnames[0]); + } + if (np->in_ifps[1] != NULL) { + COPYIFNAME(np->in_ifps[1], nat->nat_ifnames[1]); + } #ifdef IPFILTER_SYNC if ((nat->nat_flags & SI_CLONE) == 0) nat->nat_sync = ipfsync_new(SMC_NAT, fin, nat); @@ -2383,7 +2409,8 @@ int direction; nat->nat_me = natsave; nat->nat_dir = direction; - nat->nat_ifps[0] = fin->fin_ifp; + nat->nat_ifps[0] = np->in_ifps[0]; + nat->nat_ifps[1] = np->in_ifps[1]; nat->nat_ptr = np; nat->nat_p = fin->fin_p; nat->nat_mssclamp = np->in_mssclamp; @@ -2470,7 +2497,7 @@ int rev; nat->nat_ifnames[0][LIFNAMSIZ - 1] = '\0'; nat->nat_ifps[0] = fr_resolvenic(nat->nat_ifnames[0], 4); - if (nat->nat_ifnames[1][0] !='\0') { + if (nat->nat_ifnames[1][0] != '\0') { nat->nat_ifnames[1][LIFNAMSIZ - 1] = '\0'; nat->nat_ifps[1] = fr_resolvenic(nat->nat_ifnames[1], 4); } else { @@ -2818,8 +2845,9 @@ int dir; * * Since the port fields are part of the TCP/UDP checksum * of the offending IP packet, you need to adjust that checksum - * as well... but, if you change, you must change the icmp - * checksum *again*, to reflect that change. + * as well... except that the change in the port numbers should + * be offset by the checksum change, so we only need to change + * the ICMP checksum if we only change the ports. * * To further complicate: the TCP checksum is not in the first * 8 bytes of the offending ip packet, so it most likely is not @@ -2854,21 +2882,14 @@ int dir; * The UDP checksum is optional, only adjust it if * it has been set. */ - if ((oip->ip_p == IPPROTO_UDP) && - (dlen >= 8) && (*csump != 0)) { + if (oip->ip_p == IPPROTO_UDP) { sumd = sum1 - sum2; - sumd2 += sumd; - sum1 = ntohs(*csump); - fix_datacksum(csump, sumd); - sum2 = ntohs(*csump); - - /* - * Fix ICMP checksum to compenstate - * UDP checksum adjustment. - */ - CALC_SUMD(sum1, sum2, sumd); - sumd2 += sumd; + if ((dlen >= 8) && (*csump != 0)) { + fix_datacksum(csump, sumd); + } else { + sumd2 += sumd; + } } /* @@ -2877,20 +2898,10 @@ int dir; * the other direction compared to the ICMP message. */ if (oip->ip_p == IPPROTO_TCP) { + sumd = sum1 - sum2; + if (dlen >= 18) { - sumd = sum1 - sum2; - sumd2 += sumd; - - sum1 = ntohs(*csump); fix_datacksum(csump, sumd); - sum2 = ntohs(*csump); - - /* - * Fix ICMP checksum to compensate - * TCP checksum adjustment. - */ - CALC_SUMD(sum1, sum2, sumd); - sumd2 += sumd; } else { sumd = sum2 - sum1 + 1; sumd2 += sumd; @@ -2910,21 +2921,14 @@ int dir; * The UDP checksum is optional, only adjust * it if it has been set. */ - if ((oip->ip_p == IPPROTO_UDP) && - (dlen >= 8) && (*csump != 0)) { + if (oip->ip_p == IPPROTO_UDP) { sumd = sum1 - sum2; - sumd2 += sumd; - sum1 = ntohs(*csump); - fix_datacksum(csump, sumd); - sum2 = ntohs(*csump); - - /* - * Fix ICMP checksum to compensate - * UDP checksum adjustment. - */ - CALC_SUMD(sum1, sum2, sumd); - sumd2 += sumd; + if ((dlen >= 8) && (*csump != 0)) { + fix_datacksum(csump, sumd); + } else { + sumd2 += sumd; + } } /* @@ -2933,20 +2937,10 @@ int dir; * the other direction compared to the ICMP message. */ if (oip->ip_p == IPPROTO_TCP) { + sumd = sum1 - sum2; + if (dlen >= 18) { - sumd = sum1 - sum2; - sumd2 += sumd; - - sum1 = ntohs(*csump); fix_datacksum(csump, sumd); - sum2 = ntohs(*csump); - - /* - * Fix ICMP checksum to compensate - * TCP checksum adjustment. - */ - CALC_SUMD(sum1, sum2, sumd); - sumd2 += sumd; } else { if (nat->nat_dir == NAT_INBOUND) sumd = sum2 - sum1; @@ -3039,10 +3033,7 @@ struct in_addr src , mapdst; void *ifp; u_int hv; - if (fin != NULL) - ifp = fin->fin_ifp; - else - ifp = NULL; + ifp = fin->fin_ifp; sport = 0; dport = 0; gre = NULL; @@ -3074,17 +3065,13 @@ struct in_addr src , mapdst; hv = NAT_HASH_FN(src.s_addr, hv + sport, ipf_nattable_sz); nat = nat_table[1][hv]; for (; nat; nat = nat->nat_hnext[1]) { - nflags = nat->nat_flags; + if (nat->nat_ifps[0] != NULL) { + if ((ifp != NULL) && (ifp != nat->nat_ifps[0])) + continue; + } else if (ifp != NULL) + nat->nat_ifps[0] = ifp; - if (ifp != NULL) { - if (nat->nat_dir == NAT_REDIRECT) { - if (ifp != nat->nat_ifps[0]) - continue; - } else { - if (ifp != nat->nat_ifps[1]) - continue; - } - } + nflags = nat->nat_flags; if (nat->nat_oip.s_addr == src.s_addr && nat->nat_outip.s_addr == dst && @@ -3149,15 +3136,11 @@ struct in_addr src , mapdst; nat = nat_table[1][hv]; for (; nat; nat = nat->nat_hnext[1]) { - if (ifp != NULL) { - if (nat->nat_dir == NAT_REDIRECT) { - if (ifp != nat->nat_ifps[0]) - continue; - } else { - if (ifp != nat->nat_ifps[1]) - continue; - } - } + if (nat->nat_ifps[0] != NULL) { + if ((ifp != NULL) && (ifp != nat->nat_ifps[0])) + continue; + } else if (ifp != NULL) + nat->nat_ifps[0] = ifp; if (nat->nat_p != fin->fin_p) continue; @@ -3324,17 +3307,13 @@ struct in_addr src , dst; hv = NAT_HASH_FN(dst.s_addr, hv + dport, ipf_nattable_sz); nat = nat_table[0][hv]; for (; nat; nat = nat->nat_hnext[0]) { - nflags = nat->nat_flags; + if (nat->nat_ifps[1] != NULL) { + if ((ifp != NULL) && (ifp != nat->nat_ifps[1])) + continue; + } else if (ifp != NULL) + nat->nat_ifps[1] = ifp; - if (ifp != NULL) { - if (nat->nat_dir == NAT_REDIRECT) { - if (ifp != nat->nat_ifps[1]) - continue; - } else { - if (ifp != nat->nat_ifps[0]) - continue; - } - } + nflags = nat->nat_flags; if (nat->nat_inip.s_addr == srcip && nat->nat_oip.s_addr == dst.s_addr && @@ -3389,15 +3368,11 @@ struct in_addr src , dst; nat = nat_table[0][hv]; for (; nat; nat = nat->nat_hnext[0]) { - if (ifp != NULL) { - if (nat->nat_dir == NAT_REDIRECT) { - if (ifp != nat->nat_ifps[1]) - continue; - } else { - if (ifp != nat->nat_ifps[0]) - continue; - } - } + if (nat->nat_ifps[1] != NULL) { + if ((ifp != NULL) && (ifp != nat->nat_ifps[1])) + continue; + } else if (ifp != NULL) + nat->nat_ifps[1] = ifp; if (nat->nat_p != fin->fin_p) continue; @@ -3446,6 +3421,16 @@ struct in_addr src , dst; /* entry for. */ /* */ /* Lookup the NAT tables to search for a matching redirect */ +/* The contents of natlookup_t should imitate those found in a packet that */ +/* would be translated - ie a packet coming in for RDR or going out for MAP.*/ +/* We can do the lookup in one of two ways, imitating an inbound or */ +/* outbound packet. By default we assume outbound, unless IPN_IN is set. */ +/* For IN, the fields are set as follows: */ +/* nl_real* = source information */ +/* nl_out* = destination information (translated) */ +/* For an out packet, the fields are set like this: */ +/* nl_in* = source information (untranslated) */ +/* nl_out* = destination information (translated) */ /* ------------------------------------------------------------------------ */ nat_t *nat_lookupredir(np) natlookup_t *np; @@ -3707,7 +3692,7 @@ u_32_t *passp; hv = NAT_HASH_FN(iph, 0, ipf_natrules_sz); for (np = nat_rules[hv]; np; np = np->in_mnext) { - if ((np->in_ifps[0] && (np->in_ifps[0] != ifp))) + if ((np->in_ifps[1] && (np->in_ifps[1] != ifp))) continue; if (np->in_v != fin->fin_v) continue; @@ -4346,8 +4331,8 @@ void fr_natexpire() { ipftq_t *ifq, *ifqnext; ipftqent_t *tqe, *tqn; - SPL_INT(s); int i; + SPL_INT(s); SPL_NET(s); WRITE_ENTER(&ipf_nat); diff --git a/sys/contrib/ipfilter/netinet/ip_pptp_pxy.c b/sys/contrib/ipfilter/netinet/ip_pptp_pxy.c index 0047e1032acf..2ef2e17dc5dc 100644 --- a/sys/contrib/ipfilter/netinet/ip_pptp_pxy.c +++ b/sys/contrib/ipfilter/netinet/ip_pptp_pxy.c @@ -4,7 +4,7 @@ * Simple PPTP transparent proxy for in-kernel use. For use with the NAT * code. * - * $Id: ip_pptp_pxy.c,v 2.10.2.11 2005/12/04 23:39:27 darrenr Exp $ + * $Id: ip_pptp_pxy.c,v 2.10.2.13 2006/03/17 10:40:05 darrenr Exp $ * */ #define IPF_PPTP_PROXY @@ -93,7 +93,8 @@ nat_t *nat; if (nat_outlookup(fin, 0, IPPROTO_GRE, nat->nat_inip, ip->ip_dst) != NULL) { if (ippr_pptp_debug > 0) - printf("ippr_pptp_new: GRE session already exists\n"); + printf("ippr_pptp_new: GRE session %s\n", + "already exists"); return -1; } @@ -101,7 +102,8 @@ nat_t *nat; KMALLOCS(aps->aps_data, pptp_pxy_t *, sizeof(*pptp)); if (aps->aps_data == NULL) { if (ippr_pptp_debug > 0) - printf("ippr_pptp_new: malloc for aps_data failed\n"); + printf("ippr_pptp_new: malloc for aps_data %s\n", + "failed"); return -1; } @@ -208,10 +210,12 @@ pptp_pxy_t *pptp; RWLOCK_EXIT(&ipf_state); } else { RWLOCK_EXIT(&ipf_state); - if (nat->nat_dir == NAT_INBOUND) - fi.fin_fi.fi_daddr = nat2->nat_inip.s_addr; - else - fi.fin_fi.fi_saddr = nat2->nat_inip.s_addr; + if (nat2 != NULL) { + if (nat->nat_dir == NAT_INBOUND) + fi.fin_fi.fi_daddr = nat2->nat_inip.s_addr; + else + fi.fin_fi.fi_saddr = nat2->nat_inip.s_addr; + } fi.fin_ifp = NULL; pptp->pptp_state = fr_addstate(&fi, &pptp->pptp_state, 0); diff --git a/sys/contrib/ipfilter/netinet/ip_proxy.c b/sys/contrib/ipfilter/netinet/ip_proxy.c index 60b6ac04af21..8fdd98cc3984 100644 --- a/sys/contrib/ipfilter/netinet/ip_proxy.c +++ b/sys/contrib/ipfilter/netinet/ip_proxy.c @@ -103,7 +103,7 @@ struct file; /* END OF INCLUDES */ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_proxy.c,v 2.62.2.14 2005/06/18 02:41:33 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_proxy.c,v 2.62.2.16 2006/03/29 11:19:56 darrenr Exp $"; #endif static int appr_fixseqack __P((fr_info_t *, ip_t *, ap_session_t *, int )); @@ -323,8 +323,7 @@ int mode; if (error == 0) error = appr_ctl(&ctl); - if ((ctl.apc_dsize > 0) && (ptr != NULL) && - (ctl.apc_data == ptr)) { + if (ptr != NULL) { KFREES(ptr, ctl.apc_dsize); } break; @@ -563,8 +562,8 @@ nat_t *nat; if (err != 0) { short adjlen = err & 0xffff; - s1 = LONG_SUM(ip->ip_len - adjlen); - s2 = LONG_SUM(ip->ip_len); + s1 = LONG_SUM(fin->fin_plen - adjlen); + s2 = LONG_SUM(fin->fin_plen); CALC_SUMD(s1, s2, sd); fix_outcksum(fin, &ip->ip_sum, sd); } @@ -584,19 +583,23 @@ nat_t *nat; #if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) if (dosum) tcp->th_sum = fr_cksum(fin->fin_qfm, ip, - IPPROTO_TCP, tcp); + IPPROTO_TCP, tcp, + fin->fin_plen); #else tcp->th_sum = fr_cksum(fin->fin_m, ip, - IPPROTO_TCP, tcp); + IPPROTO_TCP, tcp, + fin->fin_plen); #endif } else if ((udp != NULL) && (udp->uh_sum != 0)) { #if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) if (dosum) udp->uh_sum = fr_cksum(fin->fin_qfm, ip, - IPPROTO_UDP, udp); + IPPROTO_UDP, udp, + fin->fin_plen); #else udp->uh_sum = fr_cksum(fin->fin_m, ip, - IPPROTO_UDP, udp); + IPPROTO_UDP, udp, + fin->fin_plen); #endif } aps->aps_bytes += fin->fin_plen; @@ -687,9 +690,9 @@ int inc; tcp = (tcphdr_t *)fin->fin_dp; out = fin->fin_out; /* - * ip_len has already been adjusted by 'inc'. + * fin->fin_plen has already been adjusted by 'inc'. */ - nlen = ip->ip_len; + nlen = fin->fin_plen; nlen -= (IP_HL(ip) << 2) + (TCP_OFF(tcp) << 2); inc2 = inc; diff --git a/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c b/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c index 1782064ed0a2..c93207e006e1 100644 --- a/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c +++ b/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ip_rcmd_pxy.c,v 1.41.2.5 2005/10/02 04:20:07 darrenr Exp $ + * $Id: ip_rcmd_pxy.c,v 1.41.2.6 2006/04/01 10:14:54 darrenr Exp $ * * Simple RCMD transparent proxy for in-kernel use. For use with the NAT * code. @@ -202,7 +202,7 @@ nat_t *nat; fi.fin_fi.fi_daddr = nat->nat_inip.s_addr; ip->ip_dst = nat->nat_inip; } - (void) fr_addstate(&fi, &nat2->nat_state, SI_W_DPORT); + (void) fr_addstate(&fi, NULL, SI_W_DPORT); if (fi.fin_state != NULL) fr_statederef(&fi, (ipstate_t **)&fi.fin_state); } diff --git a/sys/contrib/ipfilter/netinet/ip_scan.c b/sys/contrib/ipfilter/netinet/ip_scan.c index 73977c7d224e..13a5a60210e1 100644 --- a/sys/contrib/ipfilter/netinet/ip_scan.c +++ b/sys/contrib/ipfilter/netinet/ip_scan.c @@ -58,7 +58,7 @@ struct file; #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_scan.c,v 2.40.2.4 2005/08/20 13:48:24 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_scan.c,v 2.40.2.6 2006/03/26 23:06:49 darrenr Exp $"; #endif #ifdef IPFILTER_SCAN /* endif at bottom of file */ @@ -84,18 +84,23 @@ int ipsc_matchstr __P((sinfo_t *, char *, int)); int ipsc_matchisc __P((ipscan_t *, ipstate_t *, int, int, int *)); int ipsc_match __P((ipstate_t *)); +static int ipsc_inited = 0; int ipsc_init() { RWLOCK_INIT(&ipsc_rwlock, "ip scan rwlock"); + ipsc_inited = 1; return 0; } void fr_scanunload() { - RW_DESTROY(&ipsc_rwlock); + if (ipsc_inited == 1) { + RW_DESTROY(&ipsc_rwlock); + ipsc_inited = 0; + } } @@ -431,6 +436,8 @@ ipstate_t *is; } if (k == 1) isc = lm; + if (isc == NULL) + return 0; /* * No matches or partial matches, so reset the respective diff --git a/sys/contrib/ipfilter/netinet/ip_state.c b/sys/contrib/ipfilter/netinet/ip_state.c index b0bf74245f2a..32aa80591ded 100644 --- a/sys/contrib/ipfilter/netinet/ip_state.c +++ b/sys/contrib/ipfilter/netinet/ip_state.c @@ -107,7 +107,7 @@ struct file; #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.186.2.36 2005/12/04 22:25:36 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_state.c,v 2.186.2.41 2006/04/01 10:16:28 darrenr Exp $"; #endif static ipstate_t **ips_table = NULL; @@ -668,6 +668,7 @@ caddr_t data; fr->fr_ref = 0; fr->fr_dsize = 0; fr->fr_data = NULL; + fr->fr_type = FR_T_NONE; fr_resolvedest(&fr->fr_tif, fr->fr_v); fr_resolvedest(&fr->fr_dif, fr->fr_v); @@ -801,6 +802,11 @@ int rev; /* Inserts it into the state table and appends to the bottom of the active */ /* list. If the capacity of the table has reached the maximum allowed then */ /* the call will fail and a flush is scheduled for the next timeout call. */ +/* */ +/* NOTE: The use of stsave to point to nat_state will result in memory */ +/* corruption. It should only be used to point to objects that will */ +/* either outlive this (not expired) or will deref the ip_state_t */ +/* when they are deleted. */ /* ------------------------------------------------------------------------ */ ipstate_t *fr_addstate(fin, stsave, flags) fr_info_t *fin; @@ -823,28 +829,30 @@ u_int flags; if ((fin->fin_flx & FI_OOW) && !(fin->fin_tcpf & TH_SYN)) return NULL; - fr = fin->fin_fr; - if ((fr->fr_statemax == 0) && (ips_num == fr_statemax)) { - ATOMIC_INCL(ips_stats.iss_max); - fr_state_doflush = 1; - return NULL; - } - /* * If a "keep state" rule has reached the maximum number of references * to it, then schedule an automatic flush in case we can clear out - * some "dead old wood". + * some "dead old wood". Note that because the lock isn't held on + * fr it is possible that we could overflow. The cost of overflowing + * is being ignored here as the number by which it can overflow is + * a product of the number of simultaneous threads that could be + * executing in here, so a limit of 100 won't result in 200, but could + * result in 101 or 102. */ - MUTEX_ENTER(&fr->fr_lock); - if ((fr != NULL) && (fr->fr_statemax != 0) && - (fr->fr_statecnt >= fr->fr_statemax)) { - MUTEX_EXIT(&fr->fr_lock); - ATOMIC_INCL(ips_stats.iss_maxref); - fr_state_doflush = 1; - return NULL; + fr = fin->fin_fr; + if (fr != NULL) { + if ((ips_num == fr_statemax) && (fr->fr_statemax == 0)) { + ATOMIC_INCL(ips_stats.iss_max); + fr_state_doflush = 1; + return NULL; + } + if ((fr->fr_statemax != 0) && + (fr->fr_statecnt >= fr->fr_statemax)) { + ATOMIC_INCL(ips_stats.iss_maxref); + fr_state_doflush = 1; + return NULL; + } } - fr->fr_statecnt++; - MUTEX_EXIT(&fr->fr_lock); pass = (fr == NULL) ? 0 : fr->fr_flags; @@ -1046,16 +1054,16 @@ u_int flags; break; } if (is != NULL) - goto cantaddstate; + return NULL; if (ips_stats.iss_bucketlen[hv] >= fr_state_maxbucket) { ATOMIC_INCL(ips_stats.iss_bucketfull); - goto cantaddstate; + return NULL; } KMALLOC(is, ipstate_t *); if (is == NULL) { ATOMIC_INCL(ips_stats.iss_nomem); - goto cantaddstate; + return NULL; } bcopy((char *)&ips, (char *)is, sizeof(*is)); /* @@ -1140,6 +1148,7 @@ u_int flags; is->is_optmsk[0] &= ~0x8; is->is_optmsk[1] &= ~0x8; } + is->is_me = stsave; is->is_sec = fin->fin_secmsk; is->is_secmsk = 0xffff; is->is_auth = fin->fin_auth; @@ -1154,7 +1163,6 @@ u_int flags; is->is_pass &= ~(FR_LOGFIRST|FR_LOG); READ_ENTER(&ipf_state); - is->is_me = stsave; fr_stinsert(is, fin->fin_rev); @@ -1188,14 +1196,6 @@ u_int flags; (void) fr_newfrag(fin, pass ^ FR_KEEPSTATE); return is; - -cantaddstate: - if (fr != NULL) { - MUTEX_ENTER(&fr->fr_lock); - fr->fr_statecnt--; - MUTEX_EXIT(&fr->fr_lock); - } - return NULL; } @@ -1455,18 +1455,6 @@ int flags; win = ntohs(tcp->th_win); else win = ntohs(tcp->th_win) << fdata->td_winscale; -#if 0 - /* - * XXX - This is a kludge is here because IPFilter doesn't track SACK - * options in TCP packets. This is not a trivial to do if one is to - * consider the performance impact of it. So instead, if the - * receiver has said SACK is ok, double the allowed window size. - * This is disabled for testing of another workaround for a problem - * with Microsoft Windows - see below. - */ - if ((tdata->td_winflags & TCP_SACK_PERMIT) != 0) - win *= 2; -#endif /* * A window of 0 produces undesirable behaviour from this function. @@ -1553,6 +1541,39 @@ int flags; (fdata->td_winflags & TCP_SACK_PERMIT) && (tdata->td_winflags & TCP_SACK_PERMIT)) { inseq = 1; + /* + * Sometimes a TCP RST will be generated with only the ACK field + * set to non-zero. + */ + } else if ((seq == 0) && (tcpflags == (TH_RST|TH_ACK)) && + (ackskew >= -1) && (ackskew <= 1)) { + inseq = 1; + } else if (!(flags & IS_TCPFSM)) { + int i; + + i = (fin->fin_rev << 1) + fin->fin_out; + +#if 0 + if (is_pkts[i]0 == 0) { + /* + * Picking up a connection in the middle, the "next" + * packet seen from a direction that is new should be + * accepted, even if it appears out of sequence. + */ + inseq = 1; + } else +#endif + if (!(fdata->td_winflags & + (TCP_WSCALE_SEEN|TCP_WSCALE_FIRST))) { + /* + * No TCPFSM and no window scaling, so make some + * extra guesses. + */ + if ((seq == fdata->td_maxend) && (ackskew == 0)) + inseq = 1; + else if (SEQ_GE(seq + maxwin, fdata->td_end - maxwin)) + inseq = 1; + } } if (inseq) { @@ -2339,7 +2360,8 @@ ipftq_t **ifqp; if ((is->is_p != pr) || (is->is_v != v)) continue; is = fr_matchsrcdst(fin, is, &src, &dst, NULL, FI_CMP); - if (is != NULL && + if ((is != NULL) && + (ic->icmp_id == is->is_icmp.ici_id) && fr_matchicmpqueryreply(v, &is->is_icmp, ic, fin->fin_rev)) { if (fin->fin_rev) @@ -2432,11 +2454,13 @@ ipftq_t **ifqp; break; } - if ((is != NULL) && ((is->is_sti.tqe_flags & TQE_RULEBASED) != 0) && - (is->is_tqehead[fin->fin_rev] != NULL)) - ifq = is->is_tqehead[fin->fin_rev]; - if (ifq != NULL && ifqp != NULL) - *ifqp = ifq; + if (is != NULL) { + if (((is->is_sti.tqe_flags & TQE_RULEBASED) != 0) && + (is->is_tqehead[fin->fin_rev] != NULL)) + ifq = is->is_tqehead[fin->fin_rev]; + if (ifq != NULL && ifqp != NULL) + *ifqp = ifq; + } return is; } diff --git a/sys/contrib/ipfilter/netinet/ip_sync.c b/sys/contrib/ipfilter/netinet/ip_sync.c index 768d1c538e60..b5b811b7619c 100644 --- a/sys/contrib/ipfilter/netinet/ip_sync.c +++ b/sys/contrib/ipfilter/netinet/ip_sync.c @@ -96,7 +96,7 @@ struct file; /* END OF INCLUDES */ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_sync.c,v 2.40.2.5 2005/09/04 12:51:12 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_sync.c,v 2.40.2.7 2006/03/19 14:59:39 darrenr Exp $"; #endif #define SYNC_STATETABSZ 256 @@ -702,7 +702,6 @@ int ipfsync_nat(sp, data) synchdr_t *sp; void *data; { - synclogent_t sle; syncupdent_t su; nat_t *n, *nat; synclist_t *sl; @@ -714,8 +713,6 @@ void *data; switch (sp->sm_cmd) { case SMC_CREATE : - bcopy(data, &sle, sizeof(sle)); - KMALLOC(n, nat_t *); if (n == NULL) { err = ENOMEM; @@ -729,9 +726,7 @@ void *data; break; } - WRITE_ENTER(&ipf_nat); - - nat = &sle.sle_un.sleu_ipn; + nat = (nat_t *)data; bzero((char *)n, offsetof(nat_t, nat_age)); bcopy((char *)&nat->nat_age, (char *)&n->nat_age, sizeof(*n) - offsetof(nat_t, nat_age)); @@ -741,6 +736,8 @@ void *data; sl->sl_idx = -1; sl->sl_ipn = n; sl->sl_num = ntohl(sp->sm_num); + + WRITE_ENTER(&ipf_nat); sl->sl_pnext = syncstatetab + hv; sl->sl_next = syncstatetab[hv]; if (syncstatetab[hv] != NULL) @@ -1005,4 +1002,16 @@ int mode; { return EINVAL; } + + +int ipfsync_canread() +{ + return !((sl_tail == sl_idx) && (su_tail == su_idx)); +} + + +int ipfsync_canwrite() +{ + return 1; +} #endif /* IPFILTER_SYNC */ diff --git a/sys/contrib/ipfilter/netinet/ip_sync.h b/sys/contrib/ipfilter/netinet/ip_sync.h index 8a62192dbfb0..76862f7534a1 100644 --- a/sys/contrib/ipfilter/netinet/ip_sync.h +++ b/sys/contrib/ipfilter/netinet/ip_sync.h @@ -4,7 +4,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_fil.h 1.35 6/5/96 - * $Id: ip_sync.h,v 2.11.2.2 2004/11/04 19:29:07 darrenr Exp $ + * $Id: ip_sync.h,v 2.11.2.3 2006/03/19 14:59:39 darrenr Exp $ */ #ifndef __IP_SYNC_H__ @@ -111,5 +111,7 @@ extern int ipfsync_nat __P((synchdr_t *sp, void *data)); extern int ipfsync_state __P((synchdr_t *sp, void *data)); extern int ipfsync_read __P((struct uio *uio)); extern int ipfsync_write __P((struct uio *uio)); +extern int ipfsync_canread __P((void)); +extern int ipfsync_canwrite __P((void)); #endif /* IP_SYNC */ diff --git a/sys/contrib/ipfilter/netinet/ipl.h b/sys/contrib/ipfilter/netinet/ipl.h index ee9a9550b884..28b9e0cfdfe3 100644 --- a/sys/contrib/ipfilter/netinet/ipl.h +++ b/sys/contrib/ipfilter/netinet/ipl.h @@ -4,14 +4,14 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ipl.h 1.21 6/5/96 - * $Id: ipl.h,v 2.52.2.11 2005/12/04 22:37:24 darrenr Exp $ + * $Id: ipl.h,v 2.52.2.14 2006/04/01 20:09:42 darrenr Exp $ */ #ifndef __IPL_H__ #define __IPL_H__ -#define IPL_VERSION "IP Filter: v4.1.10" +#define IPL_VERSION "IP Filter: v4.1.13" -#define IPFILTER_VERSION 4011000 +#define IPFILTER_VERSION 4011300 #endif diff --git a/sys/contrib/ipfilter/netinet/mlfk_ipl.c b/sys/contrib/ipfilter/netinet/mlfk_ipl.c index 26a51aa69feb..e4c5ccb9e146 100644 --- a/sys/contrib/ipfilter/netinet/mlfk_ipl.c +++ b/sys/contrib/ipfilter/netinet/mlfk_ipl.c @@ -12,6 +12,10 @@ #include #include #include +#include +#if __FreeBSD_version >= 500000 +# include +#endif #include #include #include @@ -24,6 +28,9 @@ #include #include #include +#include + +extern struct selinfo ipfselwait[IPL_LOGSIZE]; #if __FreeBSD_version >= 502116 static struct cdev *ipf_devs[IPL_LOGSIZE]; @@ -92,6 +99,10 @@ SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &fr_minttl, 0, ""); #define CDEV_MAJOR 79 #if __FreeBSD_version >= 501000 +# include +# include +static int iplpoll(struct cdev *dev, int events, struct thread *td); + static struct cdevsw ipl_cdevsw = { # if __FreeBSD_version >= 502103 .d_version = D_VERSION, @@ -103,6 +114,7 @@ static struct cdevsw ipl_cdevsw = { .d_write = iplwrite, .d_ioctl = iplioctl, .d_name = "ipl", + .d_poll = iplpoll, # if __FreeBSD_version < 600000 .d_maj = CDEV_MAJOR, # endif @@ -114,7 +126,7 @@ static struct cdevsw ipl_cdevsw = { /* read */ iplread, /* write */ iplwrite, /* ioctl */ iplioctl, - /* poll */ nopoll, + /* poll */ iplpoll, /* mmap */ nommap, /* strategy */ nostrategy, /* name */ "ipl", @@ -270,3 +282,51 @@ sysctl_ipf_int ( SYSCTL_HANDLER_ARGS ) return (error); } #endif + + +#if __FreeBSD_version >= 501000 +static int +iplpoll(struct cdev *dev, int events, struct thread *td) +{ + u_int xmin = GET_MINOR(dev); + int revents; + + if (xmin < 0 || xmin > IPL_LOGMAX) + return 0; + + revents = 0; + + switch (xmin) + { + case IPL_LOGIPF : + case IPL_LOGNAT : + case IPL_LOGSTATE : +#ifdef IPFILTER_LOG + if ((events & (POLLIN | POLLRDNORM)) && ipflog_canread(xmin)) + revents |= events & (POLLIN | POLLRDNORM); +#endif + break; + case IPL_LOGAUTH : + if ((events & (POLLIN | POLLRDNORM)) && fr_auth_waiting()) + revents |= events & (POLLIN | POLLRDNORM); + break; + case IPL_LOGSYNC : +#ifdef IPFILTER_SYNC + if ((events & (POLLIN | POLLRDNORM)) && ipfsync_canread()) + revents |= events & (POLLIN | POLLRDNORM); + if ((events & (POLLOUT | POLLWRNORM)) && ipfsync_canwrite()) + revents |= events & (POLLOUT | POLLWRNORM); +#endif + break; + case IPL_LOGSCAN : + case IPL_LOGLOOKUP : + default : + break; + } + + if ((revents == 0) && ((events & (POLLIN|POLLRDNORM)) != 0)) + selrecord(td, &ipfselwait[xmin]); + + return revents; +} +#endif