ip_auth.c revision 98004
113978Smrkam/* 213978Smrkam * Copyright (C) 1998-2001 by Darren Reed & Guido van Rooij. 313978Smrkam * 413978Smrkam * See the IPFILTER.LICENCE file for details on licencing. 513978Smrkam */ 613978Smrkam#ifdef __sgi 713978Smrkam# include <sys/ptimers.h> 813978Smrkam#endif 913978Smrkam#include <sys/errno.h> 1013978Smrkam#include <sys/types.h> 1113978Smrkam#include <sys/param.h> 1213978Smrkam#include <sys/time.h> 1313978Smrkam#include <sys/file.h> 1413978Smrkam#if !defined(_KERNEL) && !defined(KERNEL) 1513978Smrkam# include <stdio.h> 1613978Smrkam# include <stdlib.h> 1713978Smrkam# include <string.h> 1813978Smrkam#endif 1913978Smrkam#if (defined(KERNEL) || defined(_KERNEL)) && (__FreeBSD_version >= 220000) 2013978Smrkam# include <sys/filio.h> 2113978Smrkam# include <sys/fcntl.h> 2213978Smrkam#else 2313978Smrkam# include <sys/ioctl.h> 2413978Smrkam#endif 2513978Smrkam#ifndef linux 2613978Smrkam# include <sys/protosw.h> 2713978Smrkam#endif 2813978Smrkam#include <sys/socket.h> 2913978Smrkam#if (defined(_KERNEL) || defined(KERNEL)) && !defined(linux) 3013978Smrkam# include <sys/systm.h> 3113978Smrkam#endif 3213978Smrkam#if !defined(__SVR4) && !defined(__svr4__) 3313978Smrkam# ifndef linux 3413978Smrkam# include <sys/mbuf.h> 3513978Smrkam# endif 3613978Smrkam#else 3713978Smrkam# include <sys/filio.h> 3813978Smrkam# include <sys/byteorder.h> 3913978Smrkam# ifdef _KERNEL 4013978Smrkam# include <sys/dditypes.h> 4113978Smrkam# endif 4213978Smrkam# include <sys/stream.h> 4313978Smrkam# include <sys/kmem.h> 4413978Smrkam#endif 4513978Smrkam#if (_BSDI_VERSION >= 199802) || (__FreeBSD_version >= 400000) 4613978Smrkam# include <sys/queue.h> 4713978Smrkam#endif 4813978Smrkam#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(bsdi) 4913978Smrkam# include <machine/cpu.h> 5013978Smrkam#endif 5113978Smrkam#include <net/if.h> 5213978Smrkam#ifdef sun 5313978Smrkam# include <net/af.h> 5413978Smrkam#endif 5513978Smrkam#include <net/route.h> 5613978Smrkam#include <netinet/in.h> 5713978Smrkam#include <netinet/in_systm.h> 5813978Smrkam#include <netinet/ip.h> 5913978Smrkam#ifndef KERNEL 6013978Smrkam# define KERNEL 6113978Smrkam# define NOT_KERNEL 6213978Smrkam#endif 6313978Smrkam#ifndef linux 6413978Smrkam# include <netinet/ip_var.h> 6513978Smrkam#endif 6613978Smrkam#ifdef NOT_KERNEL 6713978Smrkam# undef KERNEL 6813978Smrkam#endif 6913978Smrkam#ifdef __sgi 7013978Smrkam# ifdef IFF_DRVRLOCK /* IRIX6 */ 7113978Smrkam# include <sys/hashing.h> 7213978Smrkam# endif 7313978Smrkam#endif 7413978Smrkam#include <netinet/tcp.h> 7513978Smrkam#if defined(__sgi) && !defined(IFF_DRVRLOCK) /* IRIX < 6 */ 7613978Smrkamextern struct ifqueue ipintrq; /* ip packet input queue */ 7713978Smrkam#else 7813978Smrkam# ifndef linux 7913978Smrkam# if __FreeBSD_version >= 300000 8013978Smrkam# include <net/if_var.h> 8113978Smrkam# endif 8213978Smrkam# include <netinet/in_var.h> 8313978Smrkam# include <netinet/tcp_fsm.h> 8413978Smrkam# endif 8513978Smrkam#endif 8613978Smrkam#include <netinet/udp.h> 8713978Smrkam#include <netinet/ip_icmp.h> 8813978Smrkam#include "netinet/ip_compat.h" 8913978Smrkam#include <netinet/tcpip.h> 9013978Smrkam#include "netinet/ip_fil.h" 9113978Smrkam#include "netinet/ip_auth.h" 9213978Smrkam#if !SOLARIS && !defined(linux) 9313978Smrkam# include <net/netisr.h> 9413978Smrkam# ifdef __FreeBSD__ 9513978Smrkam# include <machine/cpufunc.h> 9613978Smrkam# endif 9713978Smrkam#endif 9813978Smrkam#if (__FreeBSD_version >= 300000) 9913978Smrkam# include <sys/malloc.h> 10013978Smrkam# if (defined(_KERNEL) || defined(KERNEL)) && !defined(IPFILTER_LKM) 10113978Smrkam# include <sys/libkern.h> 10213978Smrkam# include <sys/systm.h> 10313978Smrkam# endif 10413978Smrkam#endif 10513978Smrkam 10613978Smrkam#if !defined(lint) 10713978Smrkam/* static const char rcsid[] = "@(#)$Id: ip_auth.c,v 2.11.2.12 2001/07/18 14:57:08 darrenr Exp $"; */ 10813978Smrkamstatic const char rcsid[] = "@(#)$FreeBSD: head/sys/contrib/ipfilter/netinet/ip_auth.c 98004 2002-06-07 08:56:30Z darrenr $"; 10913978Smrkam#endif 11013978Smrkam 11113978Smrkam 11213978Smrkam#if (SOLARIS || defined(__sgi)) && defined(_KERNEL) 11313978Smrkamextern KRWLOCK_T ipf_auth, ipf_mutex; 11413978Smrkamextern kmutex_t ipf_authmx; 11513978Smrkam# if SOLARIS 11613978Smrkamextern kcondvar_t ipfauthwait; 11713978Smrkam# endif 11813978Smrkam#endif 11913978Smrkam#ifdef linux 12013978Smrkamstatic struct wait_queue *ipfauthwait = NULL; 12113978Smrkam#endif 12213978Smrkam 12313978Smrkamint fr_authsize = FR_NUMAUTH; 12413978Smrkamint fr_authused = 0; 12513978Smrkamint fr_defaultauthage = 600; 12613978Smrkamint fr_auth_lock = 0; 12713978Smrkamfr_authstat_t fr_authstats; 12813978Smrkamstatic frauth_t fr_auth[FR_NUMAUTH]; 12913978Smrkammb_t *fr_authpkts[FR_NUMAUTH]; 13013978Smrkamstatic int fr_authstart = 0, fr_authend = 0, fr_authnext = 0; 13113978Smrkamstatic frauthent_t *fae_list = NULL; 13213978Smrkamfrentry_t *ipauth = NULL, 13313978Smrkam *fr_authlist = NULL; 13413978Smrkam 13513978Smrkam 13613978Smrkam/* 13713978Smrkam * Check if a packet has authorization. If the packet is found to match an 13813978Smrkam * authorization result and that would result in a feedback loop (i.e. it 13913978Smrkam * will end up returning FR_AUTH) then return FR_BLOCK instead. 14013978Smrkam */ 14113978Smrkamu_32_t fr_checkauth(ip, fin) 14213978Smrkamip_t *ip; 14313978Smrkamfr_info_t *fin; 14413978Smrkam{ 14513978Smrkam u_short id = ip->ip_id; 14613978Smrkam frentry_t *fr; 14713978Smrkam frauth_t *fra; 14813978Smrkam u_32_t pass; 14913978Smrkam int i; 15013978Smrkam 15113978Smrkam if (fr_auth_lock || !fr_authused) 15213978Smrkam return 0; 15313978Smrkam 15413978Smrkam READ_ENTER(&ipf_auth); 15513978Smrkam for (i = fr_authstart; i != fr_authend; ) { 15613978Smrkam /* 15713978Smrkam * index becomes -2 only after an SIOCAUTHW. Check this in 15813978Smrkam * case the same packet gets sent again and it hasn't yet been 15913978Smrkam * auth'd. 16013978Smrkam */ 16113978Smrkam fra = fr_auth + i; 16213978Smrkam if ((fra->fra_index == -2) && (id == fra->fra_info.fin_id) && 16313978Smrkam !bcmp((char *)fin, (char *)&fra->fra_info, FI_CSIZE)) { 16413978Smrkam /* 16513978Smrkam * Avoid feedback loop. 16613978Smrkam */ 16713978Smrkam if (!(pass = fra->fra_pass) || (pass & FR_AUTH)) 16813978Smrkam pass = FR_BLOCK; 16913978Smrkam /* 17013978Smrkam * Create a dummy rule for the stateful checking to 17113978Smrkam * use and return. Zero out any values we don't 17213978Smrkam * trust from userland! 17313978Smrkam */ 17413978Smrkam if ((pass & FR_KEEPSTATE) || ((pass & FR_KEEPFRAG) && 17513978Smrkam (fin->fin_fi.fi_fl & FI_FRAG))) { 17613978Smrkam KMALLOC(fr, frentry_t *); 17713978Smrkam if (fr) { 17813978Smrkam bcopy((char *)fra->fra_info.fin_fr, 17913978Smrkam fr, sizeof(*fr)); 18013978Smrkam fr->fr_grp = NULL; 18113978Smrkam fr->fr_ifa = fin->fin_ifp; 18213978Smrkam fr->fr_func = NULL; 18313978Smrkam fr->fr_ref = 1; 18413978Smrkam fr->fr_flags = pass; 18513978Smrkam#if BSD >= 199306 18613978Smrkam fr->fr_oifa = NULL; 18713978Smrkam#endif 18813978Smrkam } 18913978Smrkam } else 19013978Smrkam fr = fra->fra_info.fin_fr; 19113978Smrkam fin->fin_fr = fr; 19213978Smrkam RWLOCK_EXIT(&ipf_auth); 19313978Smrkam WRITE_ENTER(&ipf_auth); 19413978Smrkam if (fr && fr != fra->fra_info.fin_fr) { 19513978Smrkam fr->fr_next = fr_authlist; 19613978Smrkam fr_authlist = fr; 19713978Smrkam } 19813978Smrkam fr_authstats.fas_hits++; 19913978Smrkam fra->fra_index = -1; 20013978Smrkam fr_authused--; 20113978Smrkam if (i == fr_authstart) { 20213978Smrkam while (fra->fra_index == -1) { 20313978Smrkam i++; 20413978Smrkam fra++; 20513978Smrkam if (i == FR_NUMAUTH) { 20613978Smrkam i = 0; 20713978Smrkam fra = fr_auth; 20813978Smrkam } 20913978Smrkam fr_authstart = i; 21013978Smrkam if (i == fr_authend) 21113978Smrkam break; 21213978Smrkam } 21313978Smrkam if (fr_authstart == fr_authend) { 21413978Smrkam fr_authnext = 0; 21513978Smrkam fr_authstart = fr_authend = 0; 21613978Smrkam } 21713978Smrkam } 21813978Smrkam RWLOCK_EXIT(&ipf_auth); 21913978Smrkam return pass; 22013978Smrkam } 22113978Smrkam i++; 22213978Smrkam if (i == FR_NUMAUTH) 22313978Smrkam i = 0; 22413978Smrkam } 22513978Smrkam fr_authstats.fas_miss++; 22613978Smrkam RWLOCK_EXIT(&ipf_auth); 22713978Smrkam return 0; 22813978Smrkam} 22913978Smrkam 23013978Smrkam 23113978Smrkam/* 23213978Smrkam * Check if we have room in the auth array to hold details for another packet. 23313978Smrkam * If we do, store it and wake up any user programs which are waiting to 23413978Smrkam * hear about these events. 23513978Smrkam */ 23613978Smrkamint fr_newauth(m, fin, ip) 23713978Smrkammb_t *m; 23813978Smrkamfr_info_t *fin; 23913978Smrkamip_t *ip; 24013978Smrkam{ 24113978Smrkam#if defined(_KERNEL) && SOLARIS 24213978Smrkam qif_t *qif = fin->fin_qif; 24313978Smrkam#endif 24413978Smrkam frauth_t *fra; 24513978Smrkam int i; 24613978Smrkam 24713978Smrkam if (fr_auth_lock) 24813978Smrkam return 0; 24913978Smrkam 25013978Smrkam WRITE_ENTER(&ipf_auth); 25113978Smrkam if (fr_authstart > fr_authend) { 25213978Smrkam fr_authstats.fas_nospace++; 25313978Smrkam RWLOCK_EXIT(&ipf_auth); 25413978Smrkam return 0; 25513978Smrkam } else { 25613978Smrkam if (fr_authused == FR_NUMAUTH) { 25713978Smrkam fr_authstats.fas_nospace++; 25813978Smrkam RWLOCK_EXIT(&ipf_auth); 25913978Smrkam return 0; 26013978Smrkam } 26113978Smrkam } 26213978Smrkam 26313978Smrkam fr_authstats.fas_added++; 26413978Smrkam fr_authused++; 26513978Smrkam i = fr_authend++; 26613978Smrkam if (fr_authend == FR_NUMAUTH) 26713978Smrkam fr_authend = 0; 26813978Smrkam RWLOCK_EXIT(&ipf_auth); 26913978Smrkam fra = fr_auth + i; 27013978Smrkam fra->fra_index = i; 27113978Smrkam fra->fra_pass = 0; 27213978Smrkam fra->fra_age = fr_defaultauthage; 27313978Smrkam bcopy((char *)fin, (char *)&fra->fra_info, sizeof(*fin)); 27413978Smrkam#if SOLARIS && defined(_KERNEL) 27513978Smrkam# if !defined(sparc) 27613978Smrkam /* 27713978Smrkam * No need to copyback here as we want to undo the changes, not keep 27813978Smrkam * them. 27913978Smrkam */ 28013978Smrkam if ((ip == (ip_t *)m->b_rptr) && (ip->ip_v == 4)) 28113978Smrkam { 28213978Smrkam register u_short bo; 28313978Smrkam 28413978Smrkam bo = ip->ip_len; 28513978Smrkam ip->ip_len = htons(bo); 28613978Smrkam# if !SOLARIS && !defined(__NetBSD__) && !defined(__FreeBSD__) 28713978Smrkam /* 4.4BSD converts this ip_input.c, but I don't in solaris.c */ 28813978Smrkam bo = ip->ip_id; 28913978Smrkam ip->ip_id = htons(bo); 29013978Smrkam# endif 29113978Smrkam bo = ip->ip_off; 29213978Smrkam ip->ip_off = htons(bo); 29313978Smrkam } 29413978Smrkam# endif 29513978Smrkam m->b_rptr -= qif->qf_off; 29613978Smrkam fr_authpkts[i] = *(mblk_t **)fin->fin_mp; 29713978Smrkam fra->fra_q = qif->qf_q; 29813978Smrkam cv_signal(&ipfauthwait); 29913978Smrkam#else 30013978Smrkam# if defined(BSD) && !defined(sparc) && (BSD >= 199306) 30113978Smrkam if (!fin->fin_out) { 30213978Smrkam ip->ip_len = htons(ip->ip_len); 30313978Smrkam ip->ip_off = htons(ip->ip_off); 30413978Smrkam } 30513978Smrkam# endif 30613978Smrkam fr_authpkts[i] = m; 30713978Smrkam WAKEUP(&fr_authnext); 30813978Smrkam#endif 30913978Smrkam return 1; 31013978Smrkam} 31113978Smrkam 31213978Smrkam 31313978Smrkamint fr_auth_ioctl(data, mode, cmd, fr, frptr) 31413978Smrkamcaddr_t data; 31513978Smrkamint mode; 31613978Smrkam#if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003) 31713978Smrkamu_long cmd; 31813978Smrkam#else 31913978Smrkamint cmd; 32013978Smrkam#endif 32113978Smrkamfrentry_t *fr, **frptr; 32213978Smrkam{ 32313978Smrkam mb_t *m; 32413978Smrkam#if defined(_KERNEL) && !SOLARIS 32513978Smrkam int s; 32613978Smrkam#endif 32713978Smrkam frauth_t auth, *au = &auth, *fra; 32813978Smrkam frauthent_t *fae, **faep; 32913978Smrkam int i, error = 0; 33013978Smrkam 33113978Smrkam switch (cmd) 33213978Smrkam { 33313978Smrkam case SIOCSTLCK : 33413978Smrkam error = fr_lock(data, &fr_auth_lock); 33513978Smrkam break; 33613978Smrkam case SIOCINIFR : 33713978Smrkam case SIOCRMIFR : 33813978Smrkam case SIOCADIFR : 33913978Smrkam error = EINVAL; 34013978Smrkam break; 34113978Smrkam case SIOCINAFR : 34213978Smrkam error = EINVAL; 34313978Smrkam break; 34413978Smrkam case SIOCRMAFR : 34513978Smrkam case SIOCADAFR : 34613978Smrkam for (faep = &fae_list; (fae = *faep); ) 34713978Smrkam if (&fae->fae_fr == fr) 34813978Smrkam break; 34913978Smrkam else 35013978Smrkam faep = &fae->fae_next; 35113978Smrkam if (cmd == SIOCRMAFR) { 35213978Smrkam if (!fr || !frptr) 35313978Smrkam error = EINVAL; 35413978Smrkam else if (!fae) 35513978Smrkam error = ESRCH; 35613978Smrkam else { 35713978Smrkam WRITE_ENTER(&ipf_auth); 35813978Smrkam SPL_NET(s); 35913978Smrkam *faep = fae->fae_next; 36013978Smrkam *frptr = fr->fr_next; 36113978Smrkam SPL_X(s); 36213978Smrkam RWLOCK_EXIT(&ipf_auth); 36313978Smrkam KFREE(fae); 36413978Smrkam } 36513978Smrkam } else if (fr && frptr) { 36613978Smrkam KMALLOC(fae, frauthent_t *); 36713978Smrkam if (fae != NULL) { 36813978Smrkam bcopy((char *)fr, (char *)&fae->fae_fr, 36913978Smrkam sizeof(*fr)); 37013978Smrkam WRITE_ENTER(&ipf_auth); 37113978Smrkam SPL_NET(s); 37213978Smrkam fae->fae_age = fr_defaultauthage; 37313978Smrkam fae->fae_fr.fr_hits = 0; 37413978Smrkam fae->fae_fr.fr_next = *frptr; 37513978Smrkam *frptr = &fae->fae_fr; 37613978Smrkam fae->fae_next = *faep; 37713978Smrkam *faep = fae; 37813978Smrkam ipauth = &fae_list->fae_fr; 37913978Smrkam SPL_X(s); 38013978Smrkam RWLOCK_EXIT(&ipf_auth); 38113978Smrkam } else 38213978Smrkam error = ENOMEM; 38313978Smrkam } else 38413978Smrkam error = EINVAL; 38513978Smrkam break; 38613978Smrkam case SIOCATHST: 38713978Smrkam fr_authstats.fas_faelist = fae_list; 38813978Smrkam error = IWCOPYPTR((char *)&fr_authstats, data, 38913978Smrkam sizeof(fr_authstats)); 39013978Smrkam break; 39113978Smrkam case SIOCAUTHW: 39213978Smrkam if (!(mode & FWRITE)) { 39313978Smrkam error = EPERM; 39413978Smrkam break; 39513978Smrkam } 39613978Smrkamfr_authioctlloop: 39713978Smrkam READ_ENTER(&ipf_auth); 39813978Smrkam if ((fr_authnext != fr_authend) && fr_authpkts[fr_authnext]) { 39913978Smrkam error = IWCOPYPTR((char *)&fr_auth[fr_authnext], data, 40013978Smrkam sizeof(frauth_t)); 40113978Smrkam RWLOCK_EXIT(&ipf_auth); 40213978Smrkam if (error) 40313978Smrkam break; 40413978Smrkam WRITE_ENTER(&ipf_auth); 40513978Smrkam SPL_NET(s); 40613978Smrkam fr_authnext++; 40713978Smrkam if (fr_authnext == FR_NUMAUTH) 40813978Smrkam fr_authnext = 0; 40913978Smrkam SPL_X(s); 41013978Smrkam RWLOCK_EXIT(&ipf_auth); 41113978Smrkam return 0; 41213978Smrkam } 41313978Smrkam RWLOCK_EXIT(&ipf_auth); 41413978Smrkam#ifdef _KERNEL 41513978Smrkam# if SOLARIS 41613978Smrkam mutex_enter(&ipf_authmx); 41713978Smrkam if (!cv_wait_sig(&ipfauthwait, &ipf_authmx)) { 41813978Smrkam mutex_exit(&ipf_authmx); 41913978Smrkam return EINTR; 42013978Smrkam } 42113978Smrkam mutex_exit(&ipf_authmx); 42213978Smrkam# else 42313978Smrkam error = SLEEP(&fr_authnext, "fr_authnext"); 42413978Smrkam# endif 42513978Smrkam#endif 42613978Smrkam if (!error) 42713978Smrkam goto fr_authioctlloop; 42813978Smrkam break; 42913978Smrkam case SIOCAUTHR: 43013978Smrkam if (!(mode & FWRITE)) { 43113978Smrkam error = EPERM; 43213978Smrkam break; 43313978Smrkam } 43413978Smrkam error = IRCOPYPTR(data, (caddr_t)&auth, sizeof(auth)); 43513978Smrkam if (error) 43613978Smrkam return error; 43713978Smrkam WRITE_ENTER(&ipf_auth); 43813978Smrkam SPL_NET(s); 43913978Smrkam i = au->fra_index; 44013978Smrkam fra = fr_auth + i; 44113978Smrkam if ((i < 0) || (i > FR_NUMAUTH) || 44213978Smrkam (fra->fra_info.fin_id != au->fra_info.fin_id)) { 44313978Smrkam SPL_X(s); 44413978Smrkam RWLOCK_EXIT(&ipf_auth); 44513978Smrkam return EINVAL; 44613978Smrkam } 44713978Smrkam m = fr_authpkts[i]; 44813978Smrkam fra->fra_index = -2; 44913978Smrkam fra->fra_pass = au->fra_pass; 45013978Smrkam fr_authpkts[i] = NULL; 45113978Smrkam RWLOCK_EXIT(&ipf_auth); 45213978Smrkam#ifdef _KERNEL 45313978Smrkam if (m && au->fra_info.fin_out) { 45413978Smrkam# if SOLARIS 45513978Smrkam error = (fr_qout(fra->fra_q, m) == 0) ? EINVAL : 0; 45613978Smrkam# else /* SOLARIS */ 45713978Smrkam struct route ro; 45813978Smrkam 45913978Smrkam bzero((char *)&ro, sizeof(ro)); 46013978Smrkam# if ((_BSDI_VERSION >= 199802) && (_BSDI_VERSION < 200005)) || \ 46113978Smrkam defined(__OpenBSD__) || (defined(IRIX) && (IRIX >= 605)) 46213978Smrkam error = ip_output(m, NULL, &ro, IP_FORWARDING, NULL, 46313978Smrkam NULL); 46413978Smrkam# else 46513978Smrkam error = ip_output(m, NULL, &ro, IP_FORWARDING, NULL); 46613978Smrkam# endif 46713978Smrkam if (ro.ro_rt) { 46813978Smrkam RTFREE(ro.ro_rt); 46913978Smrkam } 47013978Smrkam# endif /* SOLARIS */ 47113978Smrkam if (error) 47213978Smrkam fr_authstats.fas_sendfail++; 47313978Smrkam else 47413978Smrkam fr_authstats.fas_sendok++; 47513978Smrkam } else if (m) { 47613978Smrkam# if SOLARIS 47713978Smrkam error = (fr_qin(fra->fra_q, m) == 0) ? EINVAL : 0; 47813978Smrkam# else /* SOLARIS */ 47913978Smrkam if (! IF_HANDOFF(&ipintrq, m, NULL)) 48013978Smrkam error = ENOBUFS; 48113978Smrkam else 48213978Smrkam schednetisr(NETISR_IP); 48313978Smrkam# endif /* SOLARIS */ 48413978Smrkam if (error) 48513978Smrkam fr_authstats.fas_quefail++; 48613978Smrkam else 48713978Smrkam fr_authstats.fas_queok++; 48813978Smrkam } else 48913978Smrkam error = EINVAL; 49013978Smrkam# if SOLARIS 49113978Smrkam if (error) 49213978Smrkam error = EINVAL; 49313978Smrkam# else 49413978Smrkam /* 49513978Smrkam * If we experience an error which will result in the packet 49613978Smrkam * not being processed, make sure we advance to the next one. 49713978Smrkam */ 49813978Smrkam if (error == ENOBUFS) { 49913978Smrkam fr_authused--; 50013978Smrkam fra->fra_index = -1; 50113978Smrkam fra->fra_pass = 0; 50213978Smrkam if (i == fr_authstart) { 50313978Smrkam while (fra->fra_index == -1) { 50413978Smrkam i++; 50513978Smrkam if (i == FR_NUMAUTH) 50613978Smrkam i = 0; 50713978Smrkam fr_authstart = i; 50813978Smrkam if (i == fr_authend) 50913978Smrkam break; 51013978Smrkam } 51113978Smrkam if (fr_authstart == fr_authend) { 51213978Smrkam fr_authnext = 0; 51313978Smrkam fr_authstart = fr_authend = 0; 51413978Smrkam } 51513978Smrkam } 51613978Smrkam } 51713978Smrkam# endif 51813978Smrkam#endif /* _KERNEL */ 51913978Smrkam SPL_X(s); 52013978Smrkam break; 52113978Smrkam default : 52213978Smrkam error = EINVAL; 52313978Smrkam break; 52413978Smrkam } 52513978Smrkam return error; 52613978Smrkam} 52713978Smrkam 52813978Smrkam 52913978Smrkam/* 53013978Smrkam * Free all network buffer memory used to keep saved packets. 53113978Smrkam */ 53213978Smrkamvoid fr_authunload() 53313978Smrkam{ 53413978Smrkam register int i; 53513978Smrkam register frauthent_t *fae, **faep; 53613978Smrkam frentry_t *fr, **frp; 53713978Smrkam mb_t *m; 53813978Smrkam 53913978Smrkam WRITE_ENTER(&ipf_auth); 54013978Smrkam for (i = 0; i < FR_NUMAUTH; i++) { 54113978Smrkam if ((m = fr_authpkts[i])) { 54213978Smrkam FREE_MB_T(m); 54313978Smrkam fr_authpkts[i] = NULL; 54413978Smrkam fr_auth[i].fra_index = -1; 54513978Smrkam } 54613978Smrkam } 54713978Smrkam 54813978Smrkam 54913978Smrkam for (faep = &fae_list; (fae = *faep); ) { 55013978Smrkam *faep = fae->fae_next; 55113978Smrkam KFREE(fae); 55213978Smrkam } 55313978Smrkam ipauth = NULL; 55413978Smrkam RWLOCK_EXIT(&ipf_auth); 55513978Smrkam 55613978Smrkam if (fr_authlist) { 55713978Smrkam /* 55813978Smrkam * We *MuST* reget ipf_auth because otherwise we won't get the 55913978Smrkam * locks in the right order and risk deadlock. 56013978Smrkam * We need ipf_mutex here to prevent a rule from using it 56113978Smrkam * inside fr_check(). 56213978Smrkam */ 56313978Smrkam WRITE_ENTER(&ipf_mutex); 56413978Smrkam WRITE_ENTER(&ipf_auth); 56513978Smrkam for (frp = &fr_authlist; (fr = *frp); ) { 56613978Smrkam if (fr->fr_ref == 1) { 56713978Smrkam *frp = fr->fr_next; 56813978Smrkam KFREE(fr); 56913978Smrkam } else 57013978Smrkam frp = &fr->fr_next; 57113978Smrkam } 57213978Smrkam RWLOCK_EXIT(&ipf_auth); 57313978Smrkam RWLOCK_EXIT(&ipf_mutex); 57413978Smrkam } 57513978Smrkam} 57613978Smrkam 57713978Smrkam 57813978Smrkam/* 57913978Smrkam * Slowly expire held auth records. Timeouts are set 58013978Smrkam * in expectation of this being called twice per second. 58113978Smrkam */ 58213978Smrkamvoid fr_authexpire() 58313978Smrkam{ 58413978Smrkam register int i; 58513978Smrkam register frauth_t *fra; 58613978Smrkam register frauthent_t *fae, **faep; 58713978Smrkam register frentry_t *fr, **frp; 58813978Smrkam mb_t *m; 58913978Smrkam#if !SOLARIS && defined(_KERNEL) 59013978Smrkam int s; 59113978Smrkam#endif 59213978Smrkam 59313978Smrkam if (fr_auth_lock) 59413978Smrkam return; 59513978Smrkam 59613978Smrkam SPL_NET(s); 59713978Smrkam WRITE_ENTER(&ipf_auth); 59813978Smrkam for (i = 0, fra = fr_auth; i < FR_NUMAUTH; i++, fra++) { 59913978Smrkam if ((!--fra->fra_age) && (m = fr_authpkts[i])) { 60013978Smrkam FREE_MB_T(m); 60113978Smrkam fr_authpkts[i] = NULL; 60213978Smrkam fr_auth[i].fra_index = -1; 60313978Smrkam fr_authstats.fas_expire++; 60413978Smrkam fr_authused--; 60513978Smrkam } 60613978Smrkam } 60713978Smrkam 60813978Smrkam for (faep = &fae_list; (fae = *faep); ) { 60913978Smrkam if (!--fae->fae_age) { 61013978Smrkam *faep = fae->fae_next; 61113978Smrkam KFREE(fae); 61213978Smrkam fr_authstats.fas_expire++; 61313978Smrkam } else 61413978Smrkam faep = &fae->fae_next; 61513978Smrkam } 61613978Smrkam if (fae_list != NULL) 61713978Smrkam ipauth = &fae_list->fae_fr; 61813978Smrkam else 61913978Smrkam ipauth = NULL; 62013978Smrkam 62113978Smrkam for (frp = &fr_authlist; (fr = *frp); ) { 62213978Smrkam if (fr->fr_ref == 1) { 62313978Smrkam *frp = fr->fr_next; 62413978Smrkam KFREE(fr); 62513978Smrkam } else 62613978Smrkam frp = &fr->fr_next; 62713978Smrkam } 62813978Smrkam RWLOCK_EXIT(&ipf_auth); 62913978Smrkam SPL_X(s); 63013978Smrkam} 63113978Smrkam