From 4160f4c64e792b95d1d413f350b59eaf9fc1b6b9 Mon Sep 17 00:00:00 2001 From: Guido van Rooij Date: Wed, 16 Aug 2006 12:06:35 +0000 Subject: [PATCH] Resolve conflicts MFC after: 2 weeks --- 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 | 10 +- 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_log.c | 27 ++- sys/contrib/ipfilter/netinet/ip_nat.c | 215 ++++++++--------- sys/contrib/ipfilter/netinet/ip_proxy.c | 25 +- sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c | 4 +- sys/contrib/ipfilter/netinet/ip_state.c | 120 ++++++---- sys/contrib/ipfilter/netinet/ip_sync.c | 23 +- sys/contrib/ipfilter/netinet/ipl.h | 6 +- sys/contrib/ipfilter/netinet/mlfk_ipl.c | 62 ++++- 16 files changed, 507 insertions(+), 367 deletions(-) diff --git a/sys/contrib/ipfilter/netinet/fil.c b/sys/contrib/ipfilter/netinet/fil.c index a13441caec8f..ee21a941c246 100644 --- a/sys/contrib/ipfilter/netinet/fil.c +++ b/sys/contrib/ipfilter/netinet/fil.c @@ -142,7 +142,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[] = "@(#)$FreeBSD$"; -/* static const char rcsid[] = "@(#)Id: fil.c,v 2.243.2.57 2005/03/28 10:47:50 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 @@ -150,12 +150,6 @@ static const char rcsid[] = "@(#)$FreeBSD$"; # 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 */ @@ -1977,24 +1971,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 /* @@ -2026,18 +2019,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 @@ -2049,6 +2044,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 { @@ -2198,7 +2194,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 @@ -2238,21 +2235,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) @@ -2318,8 +2300,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 @@ -2333,6 +2313,8 @@ int out; if ((u_int)ip & 0x3) return 2; +# else + SPL_INT(s); # endif READ_ENTER(&ipf_global); @@ -2498,6 +2480,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; /* @@ -2552,7 +2551,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 ? @@ -2578,6 +2577,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; @@ -2791,10 +2798,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; @@ -2819,7 +2826,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; @@ -2831,9 +2838,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++; @@ -3064,7 +3071,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, @@ -3477,7 +3484,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; @@ -3765,13 +3772,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; } @@ -4891,7 +4892,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); } @@ -4913,8 +4914,6 @@ ipftqent_t *tqe; ipftq_t *ifq; ifq = tqe->tqe_ifq; - if (ifq == NULL) - return; MUTEX_ENTER(&ifq->ifq_lock); @@ -4986,24 +4985,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); } @@ -5055,46 +5051,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); } @@ -5578,7 +5572,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 c4341df4be6b..3f82d2521164 100644 --- a/sys/contrib/ipfilter/netinet/ip_auth.c +++ b/sys/contrib/ipfilter/netinet/ip_auth.c @@ -121,12 +121,13 @@ extern struct ifqueue ipintrq; /* ip packet input queue */ #if !defined(lint) static const char rcsid[] = "@(#)$FreeBSD$"; -/* static const char rcsid[] = "@(#)Id: ip_auth.c,v 2.73.2.3 2004/08/26 11:25:21 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; @@ -321,7 +322,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) @@ -343,17 +344,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 @@ -366,15 +365,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) { @@ -403,10 +402,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 @@ -420,11 +423,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); @@ -477,10 +481,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: @@ -491,6 +493,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); @@ -505,7 +508,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 @@ -526,7 +533,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 @@ -557,10 +568,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. @@ -584,7 +591,6 @@ int mode; } } } -# endif /* MENTAT */ #endif /* _KERNEL */ SPL_X(s); break; @@ -799,3 +805,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 5c93610c6e64..a480c5df1b04 100644 --- a/sys/contrib/ipfilter/netinet/ip_auth.h +++ b/sys/contrib/ipfilter/netinet/ip_auth.h @@ -6,7 +6,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * $FreeBSD$ - * 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__ @@ -23,6 +23,7 @@ typedef struct frauth { char *fra_buf; #ifdef MENTAT queue_t *fra_q; + mb_t *fra_m; #endif } frauth_t; @@ -63,5 +64,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 cc69245bf098..ebf8fbe4cb3d 100644 --- a/sys/contrib/ipfilter/netinet/ip_compat.h +++ b/sys/contrib/ipfilter/netinet/ip_compat.h @@ -5,7 +5,7 @@ * * @(#)ip_compat.h 1.8 1/14/96 * $FreeBSD$ - * Id: ip_compat.h,v 2.142.2.25 2005/03/28 09:33:36 darrenr Exp + * Id: ip_compat.h,v 2.142.2.36 2006/03/26 05:50:29 darrenr Exp $ */ #ifndef __IP_COMPAT_H__ @@ -442,6 +442,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))) @@ -579,6 +580,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) @@ -660,6 +662,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)) @@ -1030,6 +1033,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"); } @@ -1075,6 +1079,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 @@ -1266,6 +1271,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)) @@ -1430,6 +1436,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) ; @@ -1580,6 +1587,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 a061edef6700..568453d2326d 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil.h +++ b/sys/contrib/ipfilter/netinet/ip_fil.h @@ -5,7 +5,7 @@ * * @(#)ip_fil.h 1.35 6/5/96 * $FreeBSD$ - * Id: ip_fil.h,v 2.170.2.18 2005/03/28 10:47:52 darrenr Exp + * Id: ip_fil.h,v 2.170.2.29 2006/03/29 11:19:55 darrenr Exp $ */ #ifndef __IP_FIL_H__ @@ -306,6 +306,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; @@ -1134,6 +1135,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 **)); @@ -1149,6 +1161,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)); @@ -1262,7 +1275,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 *)); @@ -1319,6 +1332,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)); @@ -1327,7 +1341,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 0e8125160f3f..d27878158cd0 100644 --- a/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c +++ b/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c @@ -7,7 +7,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) @@ -57,6 +57,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 @@ -133,6 +134,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 @@ -302,6 +304,7 @@ int iplattach() fr_checkp = fr_check; } + bzero((char *)ipfselwait, sizeof(ipfselwait)); bzero((char *)frcache, sizeof(frcache)); fr_running = 1; @@ -478,9 +481,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; } @@ -621,7 +626,10 @@ int mode; error = EINVAL; break; } + + RWLOCK_EXIT(&ipf_global); SPL_X(s); + return error; } @@ -744,14 +752,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 @@ -1157,6 +1169,8 @@ frdest_t *fdp; u_short ip_off; frentry_t *fr; + ro = NULL; + #ifdef M_WRITABLE /* * HOT FIX/KLUDGE: @@ -1170,15 +1184,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 @@ -1220,18 +1234,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); @@ -1348,6 +1352,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; /* ??? */ @@ -1358,7 +1363,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; } /* @@ -1387,7 +1391,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; @@ -1490,6 +1494,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 f1754cab61f8..5a932951601d 100644 --- a/sys/contrib/ipfilter/netinet/ip_frag.c +++ b/sys/contrib/ipfilter/netinet/ip_frag.c @@ -103,7 +103,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[] = "@(#)$FreeBSD$"; -/* static const char rcsid[] = "@(#)Id: ip_frag.c,v 2.77 2004/01/27 00:24:54 darrenr Exp"; */ +/* static const char rcsid[] = "@(#)$Id: ip_frag.c,v 2.77.2.5 2006/02/26 08:26:54 darrenr Exp $";*/ #endif @@ -227,6 +227,7 @@ ipfr_t *table[]; { ipfr_t *fra, frag; u_int idx, off; + frentry_t *fr; ip_t *ip; if (ipfr_inuse >= IPFT_SIZE) @@ -278,12 +279,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 9e628a692ada..6718f85625f5 100644 --- a/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c +++ b/sys/contrib/ipfilter/netinet/ip_ftp_pxy.c @@ -9,7 +9,7 @@ * code. * * $FreeBSD$ - * Id: ip_ftp_pxy.c,v 2.88.2.15 2005/03/19 19:38:10 darrenr Exp + * Id: ip_ftp_pxy.c,v 2.88.2.19 2006/04/01 10:14:53 darrenr Exp $ */ #define IPF_FTP_PROXY @@ -369,7 +369,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); } @@ -731,7 +731,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); } @@ -1030,13 +1030,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]; @@ -1426,7 +1427,7 @@ int dlen; ap += *s++ - '0'; } - if (!s) + if (!*s) return 0; if (*s == '|') diff --git a/sys/contrib/ipfilter/netinet/ip_log.c b/sys/contrib/ipfilter/netinet/ip_log.c index 36901ac679b6..83dcb70331d8 100644 --- a/sys/contrib/ipfilter/netinet/ip_log.c +++ b/sys/contrib/ipfilter/netinet/ip_log.c @@ -6,7 +6,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * $FreeBSD$ - * Id: ip_log.c,v 2.75.2.6 2004/10/16 07:59:27 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) @@ -70,6 +70,10 @@ struct file; # include # endif # include +# include +# if __FreeBSD_version >= 500000 +# include +# endif #else # if !defined(__hpux) && defined(_KERNEL) # include @@ -144,12 +148,14 @@ iplog_select_t iplog_ss[IPL_LOGMAX+1]; extern int selwait; # endif /* IPL_SELECT */ +extern struct selinfo ipfselwait[IPL_LOGSIZE]; # if defined(linux) && defined(_KERNEL) 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]; @@ -508,9 +514,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 @@ -668,4 +676,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 1b69f853077c..063f557f493e 100644 --- a/sys/contrib/ipfilter/netinet/ip_nat.c +++ b/sys/contrib/ipfilter/netinet/ip_nat.c @@ -110,7 +110,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[] = "@(#)$FreeBSD$"; -/* static const char rcsid[] = "@(#)Id: ip_nat.c,v 2.195.2.38 2005/03/28 11:09:54 darrenr Exp"; */ +/* static const char rcsid[] = "@(#)$Id: ip_nat.c,v 2.195.2.56 2006/04/01 10:15:34 darrenr Exp $";*/ #endif @@ -194,7 +194,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)); @@ -868,11 +868,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; @@ -997,7 +994,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'; @@ -1008,12 +1005,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; } @@ -1341,23 +1341,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); } @@ -1368,12 +1376,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); } @@ -1438,6 +1445,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 { @@ -1577,6 +1590,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) @@ -2155,6 +2171,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; @@ -2248,6 +2267,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; } @@ -2265,6 +2285,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; } @@ -2378,7 +2399,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); @@ -2386,7 +2412,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; @@ -2473,7 +2500,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 { @@ -2821,8 +2848,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 @@ -2857,21 +2885,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; + } } /* @@ -2880,20 +2901,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; @@ -2913,21 +2924,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; + } } /* @@ -2936,20 +2940,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; @@ -3042,10 +3036,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; @@ -3077,17 +3068,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 && @@ -3152,15 +3139,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; @@ -3327,17 +3310,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 && @@ -3392,15 +3371,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; @@ -3449,6 +3424,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; @@ -3710,7 +3695,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; @@ -4349,8 +4334,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_proxy.c b/sys/contrib/ipfilter/netinet/ip_proxy.c index 8fae312d27a9..eb84cd191ea6 100644 --- a/sys/contrib/ipfilter/netinet/ip_proxy.c +++ b/sys/contrib/ipfilter/netinet/ip_proxy.c @@ -104,7 +104,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 )); @@ -324,8 +324,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; @@ -564,8 +563,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); } @@ -585,19 +584,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; @@ -688,9 +691,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 01b2d89602e4..c0d755a1f481 100644 --- a/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c +++ b/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c @@ -5,7 +5,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. @@ -205,7 +205,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_state.c b/sys/contrib/ipfilter/netinet/ip_state.c index ab42da09c03b..5a877a616c27 100644 --- a/sys/contrib/ipfilter/netinet/ip_state.c +++ b/sys/contrib/ipfilter/netinet/ip_state.c @@ -109,7 +109,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; @@ -670,6 +670,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); @@ -803,6 +804,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; @@ -825,28 +831,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; @@ -1048,16 +1056,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)); /* @@ -1142,6 +1150,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; @@ -1156,7 +1165,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); @@ -1190,14 +1198,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; } @@ -1457,18 +1457,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. @@ -1555,6 +1543,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) { @@ -2341,7 +2362,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) @@ -2434,11 +2456,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 e96b65135f43..d41091a2e611 100644 --- a/sys/contrib/ipfilter/netinet/ip_sync.c +++ b/sys/contrib/ipfilter/netinet/ip_sync.c @@ -98,7 +98,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 @@ -704,7 +704,6 @@ int ipfsync_nat(sp, data) synchdr_t *sp; void *data; { - synclogent_t sle; syncupdent_t su; nat_t *n, *nat; synclist_t *sl; @@ -716,8 +715,6 @@ void *data; switch (sp->sm_cmd) { case SMC_CREATE : - bcopy(data, &sle, sizeof(sle)); - KMALLOC(n, nat_t *); if (n == NULL) { err = ENOMEM; @@ -731,9 +728,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)); @@ -743,6 +738,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) @@ -1007,4 +1004,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/ipl.h b/sys/contrib/ipfilter/netinet/ipl.h index 906b2ef6f47f..cdbf3d0c21dc 100644 --- a/sys/contrib/ipfilter/netinet/ipl.h +++ b/sys/contrib/ipfilter/netinet/ipl.h @@ -7,14 +7,14 @@ * * @(#)ipl.h 1.21 6/5/96 * $FreeBSD$ - * Id: ipl.h,v 2.52.2.9 2005/03/30 14:14:05 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 3c232661cada..2048df4322a4 100644 --- a/sys/contrib/ipfilter/netinet/mlfk_ipl.c +++ b/sys/contrib/ipfilter/netinet/mlfk_ipl.c @@ -15,6 +15,10 @@ #include #include #include +#include +#if __FreeBSD_version >= 500000 +# include +#endif #include #include #include @@ -27,6 +31,9 @@ #include #include #include +#include + +extern struct selinfo ipfselwait[IPL_LOGSIZE]; #if __FreeBSD_version >= 502116 static struct cdev *ipf_devs[IPL_LOGSIZE]; @@ -95,6 +102,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, @@ -106,6 +117,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 @@ -117,7 +129,7 @@ static struct cdevsw ipl_cdevsw = { /* read */ iplread, /* write */ iplwrite, /* ioctl */ iplioctl, - /* poll */ nopoll, + /* poll */ iplpoll, /* mmap */ nommap, /* strategy */ nostrategy, /* name */ "ipl", @@ -273,3 +285,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