diff options
Diffstat (limited to 'contrib/ipfilter/ip_auth.c')
-rw-r--r-- | contrib/ipfilter/ip_auth.c | 540 |
1 files changed, 339 insertions, 201 deletions
diff --git a/contrib/ipfilter/ip_auth.c b/contrib/ipfilter/ip_auth.c index 566f203..b91c2e6 100644 --- a/contrib/ipfilter/ip_auth.c +++ b/contrib/ipfilter/ip_auth.c @@ -1,39 +1,49 @@ +/* $NetBSD$ */ + /* - * Copyright (C) 1998-2001 by Darren Reed & Guido van Rooij. + * Copyright (C) 1998-2003 by Darren Reed & Guido van Rooij. * * See the IPFILTER.LICENCE file for details on licencing. */ -#if defined(__sgi) && (IRIX > 602) -# include <sys/ptimers.h> +#if defined(KERNEL) || defined(_KERNEL) +# undef KERNEL +# undef _KERNEL +# define KERNEL 1 +# define _KERNEL 1 #endif #include <sys/errno.h> #include <sys/types.h> #include <sys/param.h> #include <sys/time.h> #include <sys/file.h> -#if !defined(_KERNEL) && !defined(KERNEL) +#if !defined(_KERNEL) # include <stdio.h> # include <stdlib.h> # include <string.h> +# define _KERNEL +# ifdef __OpenBSD__ +struct file; +# endif +# include <sys/uio.h> +# undef _KERNEL #endif -#if (defined(KERNEL) || defined(_KERNEL)) && (__FreeBSD_version >= 220000) +#if defined(_KERNEL) && (__FreeBSD_version >= 220000) # include <sys/filio.h> # include <sys/fcntl.h> #else # include <sys/ioctl.h> #endif -#ifndef linux +#if !defined(linux) # include <sys/protosw.h> #endif #include <sys/socket.h> -#if (defined(_KERNEL) || defined(KERNEL)) && !defined(linux) +#if defined(_KERNEL) # include <sys/systm.h> -#endif -#if !defined(__SVR4) && !defined(__svr4__) -# ifndef linux +# if !defined(__SVR4) && !defined(__svr4__) && !defined(linux) # include <sys/mbuf.h> # endif -#else +#endif +#if defined(__SVR4) || defined(__svr4__) # include <sys/filio.h> # include <sys/byteorder.h> # ifdef _KERNEL @@ -48,6 +58,9 @@ #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(bsdi) # include <machine/cpu.h> #endif +#if defined(_KERNEL) && defined(__NetBSD__) && (__NetBSD_Version__ >= 104000000) +# include <sys/proc.h> +#endif #include <net/if.h> #ifdef sun # include <net/af.h> @@ -56,28 +69,29 @@ #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> -#ifndef KERNEL +#if !defined(_KERNEL) && !defined(__osf__) && !defined(__sgi) # define KERNEL +# define _KERNEL # define NOT_KERNEL #endif -#ifndef linux +#if !defined(linux) # include <netinet/ip_var.h> #endif #ifdef NOT_KERNEL +# undef _KERNEL # undef KERNEL #endif -#ifdef __sgi -# ifdef IFF_DRVRLOCK /* IRIX6 */ -# include <sys/hashing.h> -# endif -#endif #include <netinet/tcp.h> -#if defined(__sgi) && !defined(IFF_DRVRLOCK) /* IRIX < 6 */ +#if defined(IRIX) && (IRIX < 60516) /* IRIX < 6 */ extern struct ifqueue ipintrq; /* ip packet input queue */ #else -# ifndef linux +# if !defined(__hpux) && !defined(linux) # if __FreeBSD_version >= 300000 # include <net/if_var.h> +# if __FreeBSD_version >= 500042 +# define IF_QFULL _IF_QFULL +# define IF_DROP _IF_DROP +# endif /* __FreeBSD_version >= 500042 */ # endif # include <netinet/in_var.h> # include <netinet/tcp_fsm.h> @@ -89,7 +103,7 @@ extern struct ifqueue ipintrq; /* ip packet input queue */ #include <netinet/tcpip.h> #include "netinet/ip_fil.h" #include "netinet/ip_auth.h" -#if !SOLARIS && !defined(linux) +#if !defined(MENTAT) && !defined(linux) # include <net/netisr.h> # ifdef __FreeBSD__ # include <machine/cpufunc.h> @@ -97,58 +111,89 @@ extern struct ifqueue ipintrq; /* ip packet input queue */ #endif #if (__FreeBSD_version >= 300000) # include <sys/malloc.h> -# if (defined(_KERNEL) || defined(KERNEL)) && !defined(IPFILTER_LKM) +# if defined(_KERNEL) && !defined(IPFILTER_LKM) # include <sys/libkern.h> # include <sys/systm.h> # endif #endif +/* END OF INCLUDES */ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_auth.c,v 2.11.2.26 2003/09/22 12:37:04 darrenr Exp $"; +static const char rcsid[] = "@(#)Id: ip_auth.c,v 2.73.2.3 2004/08/26 11:25:21 darrenr Exp"; #endif -#if (SOLARIS || defined(__sgi)) && defined(_KERNEL) -extern KRWLOCK_T ipf_auth, ipf_mutex; -extern kmutex_t ipf_authmx; -# if SOLARIS +#if SOLARIS extern kcondvar_t ipfauthwait; -# endif -#endif -#ifdef linux -static struct wait_queue *ipfauthwait = NULL; +#endif /* SOLARIS */ +#if defined(linux) && defined(_KERNEL) +wait_queue_head_t fr_authnext_linux; #endif int fr_authsize = FR_NUMAUTH; int fr_authused = 0; int fr_defaultauthage = 600; int fr_auth_lock = 0; +int fr_auth_init = 0; fr_authstat_t fr_authstats; -static frauth_t fr_auth[FR_NUMAUTH]; -mb_t *fr_authpkts[FR_NUMAUTH]; -static int fr_authstart = 0, fr_authend = 0, fr_authnext = 0; -static frauthent_t *fae_list = NULL; +static frauth_t *fr_auth = NULL; +mb_t **fr_authpkts = NULL; +int fr_authstart = 0, fr_authend = 0, fr_authnext = 0; +frauthent_t *fae_list = NULL; frentry_t *ipauth = NULL, *fr_authlist = NULL; +int fr_authinit() +{ + KMALLOCS(fr_auth, frauth_t *, fr_authsize * sizeof(*fr_auth)); + if (fr_auth != NULL) + bzero((char *)fr_auth, fr_authsize * sizeof(*fr_auth)); + else + return -1; + + KMALLOCS(fr_authpkts, mb_t **, fr_authsize * sizeof(*fr_authpkts)); + if (fr_authpkts != NULL) + bzero((char *)fr_authpkts, fr_authsize * sizeof(*fr_authpkts)); + else + return -2; + + MUTEX_INIT(&ipf_authmx, "ipf auth log mutex"); + RWLOCK_INIT(&ipf_auth, "ipf IP User-Auth rwlock"); +#if SOLARIS && defined(_KERNEL) + cv_init(&ipfauthwait, "ipf auth condvar", CV_DRIVER, NULL); +#endif +#if defined(linux) && defined(_KERNEL) + init_waitqueue_head(&fr_authnext_linux); +#endif + + fr_auth_init = 1; + + return 0; +} + + /* * Check if a packet has authorization. If the packet is found to match an * authorization result and that would result in a feedback loop (i.e. it * will end up returning FR_AUTH) then return FR_BLOCK instead. */ -u_32_t fr_checkauth(ip, fin) -ip_t *ip; +frentry_t *fr_checkauth(fin, passp) fr_info_t *fin; +u_32_t *passp; { - u_short id = ip->ip_id; frentry_t *fr; frauth_t *fra; u_32_t pass; + u_short id; + ip_t *ip; int i; if (fr_auth_lock || !fr_authused) - return 0; + return NULL; + + ip = fin->fin_ip; + id = ip->ip_id; READ_ENTER(&ipf_auth); for (i = fr_authstart; i != fr_authend; ) { @@ -163,7 +208,7 @@ fr_info_t *fin; /* * Avoid feedback loop. */ - if (!(pass = fra->fra_pass) || (pass & FR_AUTH)) + if (!(pass = fra->fra_pass) || (FR_ISAUTH(pass))) pass = FR_BLOCK; /* * Create a dummy rule for the stateful checking to @@ -171,26 +216,26 @@ fr_info_t *fin; * trust from userland! */ if ((pass & FR_KEEPSTATE) || ((pass & FR_KEEPFRAG) && - (fin->fin_fi.fi_fl & FI_FRAG))) { + (fin->fin_flx & FI_FRAG))) { KMALLOC(fr, frentry_t *); if (fr) { bcopy((char *)fra->fra_info.fin_fr, - fr, sizeof(*fr)); + (char *)fr, sizeof(*fr)); fr->fr_grp = NULL; fr->fr_ifa = fin->fin_ifp; fr->fr_func = NULL; fr->fr_ref = 1; fr->fr_flags = pass; -#if BSD >= 199306 - fr->fr_oifa = NULL; -#endif + fr->fr_ifas[1] = NULL; + fr->fr_ifas[2] = NULL; + fr->fr_ifas[3] = NULL; } } else fr = fra->fra_info.fin_fr; fin->fin_fr = fr; RWLOCK_EXIT(&ipf_auth); WRITE_ENTER(&ipf_auth); - if (fr && fr != fra->fra_info.fin_fr) { + if ((fr != NULL) && (fr != fra->fra_info.fin_fr)) { fr->fr_next = fr_authlist; fr_authlist = fr; } @@ -201,7 +246,7 @@ fr_info_t *fin; while (fra->fra_index == -1) { i++; fra++; - if (i == FR_NUMAUTH) { + if (i == fr_authsize) { i = 0; fra = fr_auth; } @@ -215,15 +260,19 @@ fr_info_t *fin; } } RWLOCK_EXIT(&ipf_auth); - return pass; + if (passp != NULL) + *passp = pass; + ATOMIC_INC64(fr_authstats.fas_hits); + return fr; } i++; - if (i == FR_NUMAUTH) + if (i == fr_authsize) i = 0; } fr_authstats.fas_miss++; RWLOCK_EXIT(&ipf_auth); - return 0; + ATOMIC_INC64(fr_authstats.fas_miss); + return NULL; } @@ -232,15 +281,17 @@ fr_info_t *fin; * If we do, store it and wake up any user programs which are waiting to * hear about these events. */ -int fr_newauth(m, fin, ip) +int fr_newauth(m, fin) mb_t *m; fr_info_t *fin; -ip_t *ip; { -#if defined(_KERNEL) && SOLARIS - qif_t *qif = fin->fin_qif; +#if defined(_KERNEL) && defined(MENTAT) + qpktinfo_t *qpi = fin->fin_qpi; #endif frauth_t *fra; +#if !defined(sparc) && !defined(m68k) + ip_t *ip; +#endif int i; if (fr_auth_lock) @@ -252,7 +303,7 @@ ip_t *ip; RWLOCK_EXIT(&ipf_auth); return 0; } else { - if (fr_authused == FR_NUMAUTH) { + if (fr_authused == fr_authsize) { fr_authstats.fas_nospace++; RWLOCK_EXIT(&ipf_auth); return 0; @@ -262,21 +313,24 @@ ip_t *ip; fr_authstats.fas_added++; fr_authused++; i = fr_authend++; - if (fr_authend == FR_NUMAUTH) + if (fr_authend == fr_authsize) fr_authend = 0; RWLOCK_EXIT(&ipf_auth); + fra = fr_auth + i; fra->fra_index = i; fra->fra_pass = 0; fra->fra_age = fr_defaultauthage; bcopy((char *)fin, (char *)&fra->fra_info, sizeof(*fin)); -#if SOLARIS && defined(_KERNEL) -# if !defined(sparc) +#if !defined(sparc) && !defined(m68k) /* * No need to copyback here as we want to undo the changes, not keep * them. */ - if ((ip == (ip_t *)m->b_rptr) && (ip->ip_v == 4)) + ip = fin->fin_ip; +# if defined(MENTAT) && defined(_KERNEL) + if ((ip == (ip_t *)m->b_rptr) && (fin->fin_v == 4)) +# endif { register u_short bo; @@ -285,42 +339,42 @@ ip_t *ip; bo = ip->ip_off; ip->ip_off = htons(bo); } -# endif - m->b_rptr -= qif->qf_off; +#endif +#if SOLARIS && defined(_KERNEL) + m->b_rptr -= qpi->qpi_off; fr_authpkts[i] = *(mblk_t **)fin->fin_mp; - fra->fra_q = qif->qf_q; + fra->fra_q = qpi->qpi_q; /* The queue can disappear! */ cv_signal(&ipfauthwait); #else # if defined(BSD) && !defined(sparc) && (BSD >= 199306) - if (fin->fin_out == 0) { + 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); + WAKEUP(&fr_authnext,0); #endif return 1; } -int fr_auth_ioctl(data, mode, cmd) +int fr_auth_ioctl(data, cmd, mode) caddr_t data; +ioctlcmd_t cmd; int mode; -#if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003) -u_long cmd; -#else -int cmd; -#endif { mb_t *m; -#if defined(_KERNEL) && !SOLARIS && \ +#if defined(_KERNEL) && !defined(MENTAT) && !defined(linux) && \ (!defined(__FreeBSD_version) || (__FreeBSD_version < 501000)) struct ifqueue *ifq; +# ifdef USE_SPL int s; +# endif /* USE_SPL */ #endif frauth_t auth, *au = &auth, *fra; - int i, error = 0; + int i, error = 0, len; + char *t; switch (cmd) { @@ -329,81 +383,119 @@ int cmd; error = EPERM; break; } - error = fr_lock(data, &fr_auth_lock); - break; - case SIOCINIFR : - case SIOCRMIFR : - case SIOCADIFR : - error = EINVAL; - break; - case SIOCINAFR : - error = EINVAL; - break; - case SIOCRMAFR : - case SIOCADAFR : - /* These commands go via request to fr_preauthcmd */ - error = EINVAL; + fr_lock(data, &fr_auth_lock); break; + case SIOCATHST: fr_authstats.fas_faelist = fae_list; - error = IWCOPYPTR((char *)&fr_authstats, data, - sizeof(fr_authstats)); + error = fr_outobj(data, &fr_authstats, IPFOBJ_AUTHSTAT); break; + + case SIOCIPFFL: + SPL_NET(s); + WRITE_ENTER(&ipf_auth); + i = fr_authflush(); + RWLOCK_EXIT(&ipf_auth); + SPL_X(s); + error = copyoutptr((char *)&i, data, sizeof(i)); + break; + case SIOCAUTHW: - if (!(mode & FWRITE)) { - error = EPERM; - break; - } fr_authioctlloop: + error = fr_inobj(data, au, IPFOBJ_FRAUTH); READ_ENTER(&ipf_auth); if ((fr_authnext != fr_authend) && fr_authpkts[fr_authnext]) { - error = IWCOPYPTR((char *)&fr_auth[fr_authnext], data, - sizeof(frauth_t)); + error = fr_outobj(data, &fr_auth[fr_authnext], + IPFOBJ_FRAUTH); + if (auth.fra_len != 0 && auth.fra_buf != NULL) { + /* + * Copy packet contents out to user space if + * requested. Bail on an error. + */ + m = fr_authpkts[fr_authnext]; + len = MSGDSIZE(m); + if (len > auth.fra_len) + len = auth.fra_len; + auth.fra_len = len; + for (t = auth.fra_buf; m && (len > 0); ) { + i = MIN(M_LEN(m), len); + error = copyoutptr(MTOD(m, char *), + t, i); + len -= i; + t += i; + if (error != 0) + break; + } + } RWLOCK_EXIT(&ipf_auth); - if (error) + if (error != 0) break; - WRITE_ENTER(&ipf_auth); SPL_NET(s); + WRITE_ENTER(&ipf_auth); fr_authnext++; - if (fr_authnext == FR_NUMAUTH) + if (fr_authnext == fr_authsize) fr_authnext = 0; - SPL_X(s); RWLOCK_EXIT(&ipf_auth); + SPL_X(s); return 0; } RWLOCK_EXIT(&ipf_auth); + /* + * We exit ipf_global here because a program that enters in + * here will have a lock on it and goto sleep having this lock. + * If someone were to do an 'ipf -D' the system would then + * deadlock. The catch with releasing it here is that the + * caller of this function expects it to be held when we + * return so we have to reacquire it in here. + */ + RWLOCK_EXIT(&ipf_global); + + MUTEX_ENTER(&ipf_authmx); #ifdef _KERNEL # if SOLARIS - mutex_enter(&ipf_authmx); - if (!cv_wait_sig(&ipfauthwait, &ipf_authmx)) { - mutex_exit(&ipf_authmx); - return EINTR; + error = 0; + if (!cv_wait_sig(&ipfauthwait, &ipf_authmx.ipf_lk)) + error = EINTR; +# else /* SOLARIS */ +# ifdef __hpux + { + lock_t *l; + + l = get_sleep_lock(&fr_authnext); + error = sleep(&fr_authnext, PZERO+1); + spinunlock(l); } - mutex_exit(&ipf_authmx); -# else +# else +# ifdef __osf__ + error = mpsleep(&fr_authnext, PSUSP|PCATCH, "fr_authnext", 0, + &ipf_authmx, MS_LOCK_SIMPLE); +# else error = SLEEP(&fr_authnext, "fr_authnext"); -# endif +# endif /* __osf__ */ +# endif /* __hpux */ +# endif /* SOLARIS */ #endif - if (!error) + MUTEX_EXIT(&ipf_authmx); + READ_ENTER(&ipf_global); + if (error == 0) { + READ_ENTER(&ipf_auth); goto fr_authioctlloop; + } break; + case SIOCAUTHR: - if (!(mode & FWRITE)) { - error = EPERM; - break; - } - error = IRCOPYPTR(data, (caddr_t)&auth, sizeof(auth)); - if (error) + error = fr_inobj(data, &auth, IPFOBJ_FRAUTH); + if (error != 0) return error; - WRITE_ENTER(&ipf_auth); SPL_NET(s); + WRITE_ENTER(&ipf_auth); i = au->fra_index; fra = fr_auth + i; - if ((i < 0) || (i > FR_NUMAUTH) || + if ((i < 0) || (i >= fr_authsize) || (fra->fra_info.fin_id != au->fra_info.fin_id)) { - SPL_X(s); RWLOCK_EXIT(&ipf_auth); - return EINVAL; + SPL_X(s); + return ESRCH; } m = fr_authpkts[i]; fra->fra_index = -2; @@ -411,63 +503,67 @@ fr_authioctlloop: fr_authpkts[i] = NULL; RWLOCK_EXIT(&ipf_auth); #ifdef _KERNEL - if (m && au->fra_info.fin_out) { -# if SOLARIS - error = (fr_qout(fra->fra_q, m) == 0) ? EINVAL : 0; -# else /* SOLARIS */ - struct route ro; - - bzero((char *)&ro, sizeof(ro)); -# if ((_BSDI_VERSION >= 199802) && (_BSDI_VERSION < 200005)) || \ - defined(__OpenBSD__) || (defined(IRIX) && (IRIX >= 605)) || \ - (__FreeBSD_version >= 470102) - error = ip_output(m, NULL, &ro, IP_FORWARDING, NULL, - NULL); + if ((m != NULL) && (au->fra_info.fin_out != 0)) { +# ifdef MENTAT + error = !putq(fra->fra_q, m); +# else /* MENTAT */ +# ifdef linux # else - error = ip_output(m, NULL, &ro, IP_FORWARDING, NULL); -# endif - if (ro.ro_rt) { - RTFREE(ro.ro_rt); - } -# endif /* SOLARIS */ - if (error) +# if (_BSDI_VERSION >= 199802) || defined(__OpenBSD__) || \ + (defined(__sgi) && (IRIX >= 60500) || \ + (defined(__FreeBSD__) && (__FreeBSD_version >= 470102))) + error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL, + NULL); +# else + error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL); +# endif +# endif /* Linux */ +# endif /* MENTAT */ + if (error != 0) fr_authstats.fas_sendfail++; else fr_authstats.fas_sendok++; } else if (m) { -# if SOLARIS - error = (fr_qin(fra->fra_q, m) == 0) ? EINVAL : 0; -# else /* SOLARIS */ -# if __FreeBSD_version >= 501104 - netisr_dispatch(NETISR_IP, m); +# ifdef MENTAT + error = !putq(fra->fra_q, m); +# else /* MENTAT */ +# ifdef linux # else +# if __FreeBSD_version >= 501000 + netisr_dispatch(NETISR_IP, m); +# else +# if IRIX >= 60516 + ifq = &((struct ifnet *)fra->fra_info.fin_ifp)->if_snd; +# else ifq = &ipintrq; +# endif if (IF_QFULL(ifq)) { IF_DROP(ifq); - m_freem(m); + FREE_MB_T(m); error = ENOBUFS; } else { IF_ENQUEUE(ifq, m); -# if IRIX < 605 +# if IRIX < 60500 schednetisr(NETISR_IP); -# endif +# endif } -# endif -# endif /* SOLARIS */ - if (error) +# endif +# endif /* Linux */ +# endif /* MENTAT */ + if (error != 0) fr_authstats.fas_quefail++; else fr_authstats.fas_queok++; } else error = EINVAL; -# if SOLARIS - if (error) +# ifdef MENTAT + if (error != 0) error = EINVAL; -# else +# else /* MENTAT */ /* * If we experience an error which will result in the packet * not being processed, make sure we advance to the next one. - */ + */ if (error == ENOBUFS) { fr_authused--; fra->fra_index = -1; @@ -475,7 +571,7 @@ fr_authioctlloop: if (i == fr_authstart) { while (fra->fra_index == -1) { i++; - if (i == FR_NUMAUTH) + if (i == fr_authsize) i = 0; fr_authstart = i; if (i == fr_authend) @@ -487,10 +583,11 @@ fr_authioctlloop: } } } -# endif +# endif /* MENTAT */ #endif /* _KERNEL */ SPL_X(s); break; + default : error = EINVAL; break; @@ -509,41 +606,48 @@ void fr_authunload() frentry_t *fr, **frp; mb_t *m; - WRITE_ENTER(&ipf_auth); - for (i = 0; i < FR_NUMAUTH; i++) { - if ((m = fr_authpkts[i])) { - FREE_MB_T(m); - fr_authpkts[i] = NULL; - fr_auth[i].fra_index = -1; - } + if (fr_auth != NULL) { + KFREES(fr_auth, fr_authsize * sizeof(*fr_auth)); + fr_auth = NULL; } + if (fr_authpkts != NULL) { + for (i = 0; i < fr_authsize; i++) { + m = fr_authpkts[i]; + if (m != NULL) { + FREE_MB_T(m); + fr_authpkts[i] = NULL; + } + } + KFREES(fr_authpkts, fr_authsize * sizeof(*fr_authpkts)); + fr_authpkts = NULL; + } - for (faep = &fae_list; (fae = *faep); ) { + faep = &fae_list; + while ((fae = *faep) != NULL) { *faep = fae->fae_next; KFREE(fae); } ipauth = NULL; - RWLOCK_EXIT(&ipf_auth); - if (fr_authlist) { - /* - * We *MuST* reget ipf_auth because otherwise we won't get the - * locks in the right order and risk deadlock. - * We need ipf_mutex here to prevent a rule from using it - * inside fr_check(). - */ - WRITE_ENTER(&ipf_mutex); - WRITE_ENTER(&ipf_auth); - for (frp = &fr_authlist; (fr = *frp); ) { + if (fr_authlist != NULL) { + for (frp = &fr_authlist; ((fr = *frp) != NULL); ) { if (fr->fr_ref == 1) { *frp = fr->fr_next; KFREE(fr); } else frp = &fr->fr_next; } - RWLOCK_EXIT(&ipf_auth); - RWLOCK_EXIT(&ipf_mutex); + } + + if (fr_auth_init == 1) { +# if SOLARIS && defined(_KERNEL) + cv_destroy(&ipfauthwait); +# endif + MUTEX_DESTROY(&ipf_authmx); + RW_DESTROY(&ipf_auth); + + fr_auth_init = 0; } } @@ -559,17 +663,18 @@ void fr_authexpire() register frauthent_t *fae, **faep; register frentry_t *fr, **frp; mb_t *m; -#if !SOLARIS && defined(_KERNEL) +# if !defined(MENAT) && defined(_KERNEL) && defined(USE_SPL) int s; -#endif +# endif if (fr_auth_lock) return; SPL_NET(s); WRITE_ENTER(&ipf_auth); - for (i = 0, fra = fr_auth; i < FR_NUMAUTH; i++, fra++) { - if ((!--fra->fra_age) && (m = fr_authpkts[i])) { + for (i = 0, fra = fr_auth; i < fr_authsize; i++, fra++) { + fra->fra_age--; + if ((fra->fra_age == 0) && (m = fr_authpkts[i])) { FREE_MB_T(m); fr_authpkts[i] = NULL; fr_auth[i].fra_index = -1; @@ -578,8 +683,9 @@ void fr_authexpire() } } - for (faep = &fae_list; (fae = *faep); ) { - if (!--fae->fae_age) { + for (faep = &fae_list; ((fae = *faep) != NULL); ) { + fae->fae_age--; + if (fae->fae_age == 0) { *faep = fae->fae_next; KFREE(fae); fr_authstats.fas_expire++; @@ -591,7 +697,7 @@ void fr_authexpire() else ipauth = NULL; - for (frp = &fr_authlist; (fr = *frp); ) { + for (frp = &fr_authlist; ((fr = *frp) != NULL); ) { if (fr->fr_ref == 1) { *frp = fr->fr_next; KFREE(fr); @@ -603,52 +709,48 @@ void fr_authexpire() } int fr_preauthcmd(cmd, fr, frptr) -#if defined(__NetBSD__) || defined(__OpenBSD__) || \ - (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000) -u_long cmd; -#else -int cmd; -#endif +ioctlcmd_t cmd; frentry_t *fr, **frptr; { frauthent_t *fae, **faep; int error = 0; -#if defined(KERNEL) && !SOLARIS +# if !defined(MENAT) && defined(_KERNEL) && defined(USE_SPL) int s; #endif - if ((cmd != SIOCADAFR) && (cmd != SIOCRMAFR)) { - /* Should not happen */ - printf("fr_preauthcmd called with bad cmd 0x%lx", (u_long)cmd); + if ((cmd != SIOCADAFR) && (cmd != SIOCRMAFR)) return EIO; - } - for (faep = &fae_list; (fae = *faep); ) + for (faep = &fae_list; ((fae = *faep) != NULL); ) { if (&fae->fae_fr == fr) break; else faep = &fae->fae_next; - if (cmd == SIOCRMAFR) { - if (!fr || !frptr) + } + + if (cmd == (ioctlcmd_t)SIOCRMAFR) { + if (fr == NULL || frptr == NULL) error = EINVAL; - else if (!fae) + else if (fae == NULL) error = ESRCH; else { - WRITE_ENTER(&ipf_auth); SPL_NET(s); + WRITE_ENTER(&ipf_auth); *faep = fae->fae_next; - *frptr = fr->fr_next; - SPL_X(s); + if (ipauth == &fae->fae_fr) + ipauth = fae_list ? &fae_list->fae_fr : NULL; RWLOCK_EXIT(&ipf_auth); + SPL_X(s); + KFREE(fae); } - } else if (fr && frptr) { + } else if (fr != NULL && frptr != NULL) { KMALLOC(fae, frauthent_t *); if (fae != NULL) { bcopy((char *)fr, (char *)&fae->fae_fr, sizeof(*fr)); - WRITE_ENTER(&ipf_auth); SPL_NET(s); + WRITE_ENTER(&ipf_auth); fae->fae_age = fr_defaultauthage; fae->fae_fr.fr_hits = 0; fae->fae_fr.fr_next = *frptr; @@ -656,11 +758,47 @@ frentry_t *fr, **frptr; fae->fae_next = *faep; *faep = fae; ipauth = &fae_list->fae_fr; - SPL_X(s); RWLOCK_EXIT(&ipf_auth); + SPL_X(s); } else error = ENOMEM; } else error = EINVAL; return error; } + + +/* + * Flush held packets. + * Must already be properly SPL'ed and Locked on &ipf_auth. + * + */ +int fr_authflush() +{ + register int i, num_flushed; + mb_t *m; + + if (fr_auth_lock) + return -1; + + num_flushed = 0; + + for (i = 0 ; i < fr_authsize; i++) { + m = fr_authpkts[i]; + if (m != NULL) { + FREE_MB_T(m); + fr_authpkts[i] = NULL; + fr_auth[i].fra_index = -1; + /* perhaps add & use a flush counter inst.*/ + fr_authstats.fas_expire++; + fr_authused--; + num_flushed++; + } + } + + fr_authstart = 0; + fr_authend = 0; + fr_authnext = 0; + + return num_flushed; +} |