ip_auth.c revision 63523
1264790Sbapt/* 2264790Sbapt * Copyright (C) 1998-2000 by Darren Reed & Guido van Rooij. 3264790Sbapt * 4264790Sbapt * Redistribution and use in source and binary forms are permitted 5264790Sbapt * provided that this notice is preserved and due credit is given 6264790Sbapt * to the original author and the contributors. 7264790Sbapt */ 8264790Sbapt#if !defined(lint) 9264790Sbapt/*static const char rcsid[] = "@(#)$Id: ip_auth.c,v 2.1.2.2 2000/01/16 10:12:14 darrenr Exp $";*/ 10264790Sbaptstatic const char rcsid[] = "@(#)$FreeBSD: head/sys/contrib/ipfilter/netinet/ip_auth.c 63523 2000-07-19 14:02:09Z darrenr $"; 11264790Sbapt#endif 12264790Sbapt 13264790Sbapt#include <sys/errno.h> 14264790Sbapt#include <sys/types.h> 15264790Sbapt#include <sys/param.h> 16264790Sbapt#include <sys/time.h> 17264790Sbapt#include <sys/file.h> 18264790Sbapt#if !defined(_KERNEL) && !defined(KERNEL) 19264790Sbapt# include <stdio.h> 20264790Sbapt# include <stdlib.h> 21264790Sbapt# include <string.h> 22264790Sbapt#endif 23264790Sbapt#if (defined(KERNEL) || defined(_KERNEL)) && (__FreeBSD_version >= 220000) 24264790Sbapt# include <sys/filio.h> 25264790Sbapt# include <sys/fcntl.h> 26264790Sbapt#else 27264790Sbapt# include <sys/ioctl.h> 28264790Sbapt#endif 29264790Sbapt#include <sys/uio.h> 30264790Sbapt#ifndef linux 31264790Sbapt# include <sys/protosw.h> 32264790Sbapt#endif 33264790Sbapt#include <sys/socket.h> 34264790Sbapt#if (defined(_KERNEL) || defined(KERNEL)) && !defined(linux) 35264790Sbapt# include <sys/systm.h> 36264790Sbapt#endif 37264790Sbapt#if !defined(__SVR4) && !defined(__svr4__) 38264790Sbapt# ifndef linux 39264790Sbapt# include <sys/mbuf.h> 40264790Sbapt# endif 41264790Sbapt#else 42264790Sbapt# include <sys/filio.h> 43264790Sbapt# include <sys/byteorder.h> 44264790Sbapt# ifdef _KERNEL 45264790Sbapt# include <sys/dditypes.h> 46264790Sbapt# endif 47264790Sbapt# include <sys/stream.h> 48264790Sbapt# include <sys/kmem.h> 49264790Sbapt#endif 50264790Sbapt#if (_BSDI_VERSION >= 199802) || (__FreeBSD_Version >= 400000) 51264790Sbapt# include <sys/queue.h> 52264790Sbapt#endif 53264790Sbapt#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(bsdi) 54264790Sbapt# include <machine/cpu.h> 55264790Sbapt#endif 56264790Sbapt#include <net/if.h> 57264790Sbapt#ifdef sun 58264790Sbapt# include <net/af.h> 59264790Sbapt#endif 60264790Sbapt#include <net/route.h> 61264790Sbapt#include <netinet/in.h> 62264790Sbapt#include <netinet/in_systm.h> 63264790Sbapt#include <netinet/ip.h> 64264790Sbapt#ifndef KERNEL 65264790Sbapt# define KERNEL 66264790Sbapt# define NOT_KERNEL 67264790Sbapt#endif 68264790Sbapt#ifndef linux 69264790Sbapt# include <netinet/ip_var.h> 70264790Sbapt#endif 71264790Sbapt#ifdef NOT_KERNEL 72264790Sbapt# undef KERNEL 73264790Sbapt#endif 74264790Sbapt#ifdef __sgi 75264790Sbapt# ifdef IFF_DRVRLOCK /* IRIX6 */ 76264790Sbapt# include <sys/hashing.h> 77264790Sbapt# endif 78264790Sbapt#endif 79264790Sbapt#include <netinet/tcp.h> 80264790Sbapt#if defined(__sgi) && !defined(IFF_DRVRLOCK) /* IRIX < 6 */ 81264790Sbaptextern struct ifqueue ipintrq; /* ip packet input queue */ 82264790Sbapt#else 83264790Sbapt# ifndef linux 84264790Sbapt# if __FreeBSD_version >= 300000 85264790Sbapt# include <net/if_var.h> 86264790Sbapt# endif 87264790Sbapt# include <netinet/in_var.h> 88264790Sbapt# include <netinet/tcp_fsm.h> 89264790Sbapt# endif 90264790Sbapt#endif 91264790Sbapt#include <netinet/udp.h> 92264790Sbapt#include <netinet/ip_icmp.h> 93264790Sbapt#include "netinet/ip_compat.h" 94264790Sbapt#include <netinet/tcpip.h> 95264790Sbapt#include "netinet/ip_fil.h" 96264790Sbapt#include "netinet/ip_auth.h" 97264790Sbapt#if !SOLARIS && !defined(linux) 98264790Sbapt# include <net/netisr.h> 99264790Sbapt# ifdef __FreeBSD__ 100264790Sbapt# include <machine/cpufunc.h> 101264790Sbapt# endif 102264790Sbapt#endif 103264790Sbapt#if (__FreeBSD_version >= 300000) 104264790Sbapt# include <sys/malloc.h> 105264790Sbapt# if (defined(_KERNEL) || defined(KERNEL)) && !defined(IPFILTER_LKM) 106264790Sbapt# include <sys/libkern.h> 107264790Sbapt# include <sys/systm.h> 108264790Sbapt# endif 109264790Sbapt#endif 110264790Sbapt 111264790Sbapt 112264790Sbapt 113264790Sbapt#if (SOLARIS || defined(__sgi)) && defined(_KERNEL) 114264790Sbaptextern KRWLOCK_T ipf_auth; 115264790Sbaptextern kmutex_t ipf_authmx; 116264790Sbapt# if SOLARIS 117264790Sbaptextern kcondvar_t ipfauthwait; 118264790Sbapt# endif 119264790Sbapt#endif 120264790Sbapt#ifdef linux 121264790Sbaptstatic struct wait_queue *ipfauthwait = NULL; 122264790Sbapt#endif 123264790Sbapt 124264790Sbaptint fr_authsize = FR_NUMAUTH; 125264790Sbaptint fr_authused = 0; 126264790Sbaptint fr_defaultauthage = 600; 127264790Sbaptint fr_auth_lock = 0; 128264790Sbaptfr_authstat_t fr_authstats; 129264790Sbaptstatic frauth_t fr_auth[FR_NUMAUTH]; 130264790Sbaptmb_t *fr_authpkts[FR_NUMAUTH]; 131264790Sbaptstatic int fr_authstart = 0, fr_authend = 0, fr_authnext = 0; 132264790Sbaptstatic frauthent_t *fae_list = NULL; 133264790Sbaptfrentry_t *ipauth = NULL; 134264790Sbapt 135264790Sbapt 136264790Sbapt/* 137264790Sbapt * Check if a packet has authorization. If the packet is found to match an 138264790Sbapt * authorization result and that would result in a feedback loop (i.e. it 139264790Sbapt * will end up returning FR_AUTH) then return FR_BLOCK instead. 140264790Sbapt */ 141264790Sbaptu_32_t fr_checkauth(ip, fin) 142264790Sbaptip_t *ip; 143264790Sbaptfr_info_t *fin; 144264790Sbapt{ 145264790Sbapt u_short id = ip->ip_id; 146264790Sbapt u_32_t pass; 147264790Sbapt int i; 148264790Sbapt 149264790Sbapt if (fr_auth_lock) 150264790Sbapt return 0; 151264790Sbapt 152264790Sbapt READ_ENTER(&ipf_auth); 153264790Sbapt for (i = fr_authstart; i != fr_authend; ) { 154264790Sbapt /* 155264790Sbapt * index becomes -2 only after an SIOCAUTHW. Check this in 156264790Sbapt * case the same packet gets sent again and it hasn't yet been 157264790Sbapt * auth'd. 158264790Sbapt */ 159264790Sbapt if ((fr_auth[i].fra_index == -2) && 160264790Sbapt (id == fr_auth[i].fra_info.fin_id) && 161264790Sbapt !bcmp((char *)fin,(char *)&fr_auth[i].fra_info,FI_CSIZE)) { 162264790Sbapt /* 163264790Sbapt * Avoid feedback loop. 164264790Sbapt */ 165264790Sbapt if (!(pass = fr_auth[i].fra_pass) || (pass & FR_AUTH)) 166264790Sbapt pass = FR_BLOCK; 167264790Sbapt RWLOCK_EXIT(&ipf_auth); 168264790Sbapt WRITE_ENTER(&ipf_auth); 169264790Sbapt fr_authstats.fas_hits++; 170264790Sbapt fr_auth[i].fra_index = -1; 171264790Sbapt fr_authused--; 172264790Sbapt if (i == fr_authstart) { 173264790Sbapt while (fr_auth[i].fra_index == -1) { 174264790Sbapt i++; 175264790Sbapt if (i == FR_NUMAUTH) 176264790Sbapt i = 0; 177264790Sbapt fr_authstart = i; 178264790Sbapt if (i == fr_authend) 179264790Sbapt break; 180264790Sbapt } 181264790Sbapt if (fr_authstart == fr_authend) { 182264790Sbapt fr_authnext = 0; 183264790Sbapt fr_authstart = fr_authend = 0; 184264790Sbapt } 185264790Sbapt } 186264790Sbapt RWLOCK_EXIT(&ipf_auth); 187264790Sbapt return pass; 188264790Sbapt } 189264790Sbapt i++; 190264790Sbapt if (i == FR_NUMAUTH) 191264790Sbapt i = 0; 192264790Sbapt } 193264790Sbapt fr_authstats.fas_miss++; 194264790Sbapt RWLOCK_EXIT(&ipf_auth); 195264790Sbapt return 0; 196264790Sbapt} 197264790Sbapt 198264790Sbapt 199264790Sbapt/* 200264790Sbapt * Check if we have room in the auth array to hold details for another packet. 201264790Sbapt * If we do, store it and wake up any user programs which are waiting to 202264790Sbapt * hear about these events. 203264790Sbapt */ 204264790Sbaptint fr_newauth(m, fin, ip) 205264790Sbaptmb_t *m; 206264790Sbaptfr_info_t *fin; 207264790Sbaptip_t *ip; 208264790Sbapt{ 209264790Sbapt#if defined(_KERNEL) && SOLARIS 210264790Sbapt qif_t *qif = fin->fin_qif; 211264790Sbapt#endif 212264790Sbapt int i; 213264790Sbapt 214264790Sbapt if (fr_auth_lock) 215264790Sbapt return 0; 216264790Sbapt 217264790Sbapt WRITE_ENTER(&ipf_auth); 218264790Sbapt if (fr_authstart > fr_authend) { 219264790Sbapt fr_authstats.fas_nospace++; 220264790Sbapt RWLOCK_EXIT(&ipf_auth); 221264790Sbapt return 0; 222264790Sbapt } else { 223264790Sbapt if ((fr_authstart == 0) && (fr_authend == FR_NUMAUTH - 1)) { 224264790Sbapt fr_authstats.fas_nospace++; 225264790Sbapt RWLOCK_EXIT(&ipf_auth); 226264790Sbapt return 0; 227264790Sbapt } 228264790Sbapt } 229264790Sbapt 230264790Sbapt fr_authstats.fas_added++; 231264790Sbapt fr_authused++; 232264790Sbapt i = fr_authend++; 233264790Sbapt if (fr_authend == FR_NUMAUTH) 234264790Sbapt fr_authend = 0; 235264790Sbapt RWLOCK_EXIT(&ipf_auth); 236264790Sbapt fr_auth[i].fra_index = i; 237264790Sbapt fr_auth[i].fra_pass = 0; 238264790Sbapt fr_auth[i].fra_age = fr_defaultauthage; 239264790Sbapt bcopy((char *)fin, (char *)&fr_auth[i].fra_info, sizeof(*fin)); 240264790Sbapt#if !defined(sparc) && !defined(m68k) 241264790Sbapt /* 242264790Sbapt * No need to copyback here as we want to undo the changes, not keep 243264790Sbapt * them. 244264790Sbapt */ 245264790Sbapt# if SOLARIS && defined(_KERNEL) 246264790Sbapt if ((ip == (ip_t *)m->b_rptr) && (ip->ip_v == 4)) 247264790Sbapt# endif 248264790Sbapt { 249264790Sbapt register u_short bo; 250264790Sbapt 251264790Sbapt bo = ip->ip_len; 252264790Sbapt ip->ip_len = htons(bo); 253264790Sbapt# if !SOLARIS && !defined(__NetBSD__) 254264790Sbapt /* 4.4BSD converts this ip_input.c, but I don't in solaris.c */ 255264790Sbapt bo = ip->ip_id; 256264790Sbapt ip->ip_id = htons(bo); 257264790Sbapt# endif 258264790Sbapt bo = ip->ip_off; 259264790Sbapt ip->ip_off = htons(bo); 260264790Sbapt } 261264790Sbapt#endif 262264790Sbapt#if SOLARIS && defined(_KERNEL) 263264790Sbapt m->b_rptr -= qif->qf_off; 264264790Sbapt fr_authpkts[i] = *(mblk_t **)fin->fin_mp; 265264790Sbapt fr_auth[i].fra_q = qif->qf_q; 266264790Sbapt cv_signal(&ipfauthwait); 267264790Sbapt#else 268264790Sbapt fr_authpkts[i] = m; 269264790Sbapt# if defined(linux) && defined(_KERNEL) 270264790Sbapt wake_up_interruptible(&ipfauthwait); 271264790Sbapt# else 272264790Sbapt WAKEUP(&fr_authnext); 273264790Sbapt# endif 274264790Sbapt#endif 275264790Sbapt return 1; 276264790Sbapt} 277264790Sbapt 278264790Sbapt 279264790Sbaptint fr_auth_ioctl(data, cmd, fr, frptr) 280264790Sbaptcaddr_t data; 281264790Sbapt#if defined(__NetBSD__) || defined(__OpenBSD__) || (FreeBSD_version >= 300003) 282264790Sbaptu_long cmd; 283264790Sbapt#else 284264790Sbaptint cmd; 285264790Sbapt#endif 286264790Sbaptfrentry_t *fr, **frptr; 287264790Sbapt{ 288264790Sbapt mb_t *m; 289264790Sbapt#if defined(_KERNEL) && !SOLARIS 290264790Sbapt struct ifqueue *ifq; 291264790Sbapt#endif 292264790Sbapt frauth_t auth, *au = &auth; 293264790Sbapt frauthent_t *fae, **faep; 294264790Sbapt int i, error = 0; 295264790Sbapt 296264790Sbapt switch (cmd) 297264790Sbapt { 298264790Sbapt case SIOCSTLCK : 299264790Sbapt error = fr_lock(data, &fr_auth_lock); 300264790Sbapt break; 301264790Sbapt case SIOCINIFR : 302264790Sbapt case SIOCRMIFR : 303264790Sbapt case SIOCADIFR : 304264790Sbapt error = EINVAL; 305264790Sbapt break; 306264790Sbapt case SIOCINAFR : 307264790Sbapt error = EINVAL; 308264790Sbapt break; 309264790Sbapt case SIOCRMAFR : 310264790Sbapt case SIOCADAFR : 311264790Sbapt for (faep = &fae_list; (fae = *faep); ) 312264790Sbapt if (&fae->fae_fr == fr) 313264790Sbapt break; 314264790Sbapt else 315264790Sbapt faep = &fae->fae_next; 316264790Sbapt if (cmd == SIOCRMAFR) { 317264790Sbapt if (!fae) 318264790Sbapt error = ESRCH; 319264790Sbapt else { 320264790Sbapt WRITE_ENTER(&ipf_auth); 321264790Sbapt *faep = fae->fae_next; 322264790Sbapt *frptr = fr->fr_next; 323264790Sbapt RWLOCK_EXIT(&ipf_auth); 324264790Sbapt KFREE(fae); 325264790Sbapt } 326264790Sbapt } else { 327264790Sbapt KMALLOC(fae, frauthent_t *); 328264790Sbapt if (fae != NULL) { 329264790Sbapt bcopy((char *)fr, (char *)&fae->fae_fr, 330264790Sbapt sizeof(*fr)); 331264790Sbapt WRITE_ENTER(&ipf_auth); 332264790Sbapt fae->fae_age = fr_defaultauthage; 333264790Sbapt fae->fae_fr.fr_hits = 0; 334264790Sbapt fae->fae_fr.fr_next = *frptr; 335264790Sbapt *frptr = &fae->fae_fr; 336264790Sbapt fae->fae_next = *faep; 337264790Sbapt *faep = fae; 338264790Sbapt ipauth = &fae_list->fae_fr; 339264790Sbapt RWLOCK_EXIT(&ipf_auth); 340264790Sbapt } else 341264790Sbapt error = ENOMEM; 342264790Sbapt } 343264790Sbapt break; 344264790Sbapt case SIOCATHST: 345264790Sbapt READ_ENTER(&ipf_auth); 346264790Sbapt fr_authstats.fas_faelist = fae_list; 347264790Sbapt RWLOCK_EXIT(&ipf_auth); 348264790Sbapt error = IWCOPYPTR((char *)&fr_authstats, data, 349264790Sbapt sizeof(fr_authstats)); 350264790Sbapt break; 351264790Sbapt case SIOCAUTHW: 352264790Sbaptfr_authioctlloop: 353264790Sbapt READ_ENTER(&ipf_auth); 354264790Sbapt if ((fr_authnext != fr_authend) && fr_authpkts[fr_authnext]) { 355264790Sbapt error = IWCOPYPTR((char *)&fr_auth[fr_authnext], data, 356264790Sbapt sizeof(fr_info_t)); 357264790Sbapt RWLOCK_EXIT(&ipf_auth); 358264790Sbapt if (error) 359264790Sbapt break; 360264790Sbapt WRITE_ENTER(&ipf_auth); 361264790Sbapt fr_authnext++; 362264790Sbapt if (fr_authnext == FR_NUMAUTH) 363264790Sbapt fr_authnext = 0; 364264790Sbapt RWLOCK_EXIT(&ipf_auth); 365264790Sbapt return 0; 366264790Sbapt } 367264790Sbapt#ifdef _KERNEL 368264790Sbapt# if SOLARIS 369264790Sbapt mutex_enter(&ipf_authmx); 370264790Sbapt if (!cv_wait_sig(&ipfauthwait, &ipf_authmx)) { 371264790Sbapt mutex_exit(&ipf_authmx); 372264790Sbapt return EINTR; 373264790Sbapt } 374264790Sbapt mutex_exit(&ipf_authmx); 375264790Sbapt# else 376264790Sbapt# ifdef linux 377264790Sbapt interruptible_sleep_on(&ipfauthwait); 378264790Sbapt if (current->signal & ~current->blocked) 379264790Sbapt error = -EINTR; 380264790Sbapt# else 381264790Sbapt error = SLEEP(&fr_authnext, "fr_authnext"); 382264790Sbapt# endif 383264790Sbapt# endif 384264790Sbapt#endif 385264790Sbapt RWLOCK_EXIT(&ipf_auth); 386264790Sbapt if (!error) 387264790Sbapt goto fr_authioctlloop; 388264790Sbapt break; 389264790Sbapt case SIOCAUTHR: 390264790Sbapt error = IRCOPYPTR(data, (caddr_t)&auth, sizeof(auth)); 391264790Sbapt if (error) 392264790Sbapt return error; 393264790Sbapt WRITE_ENTER(&ipf_auth); 394264790Sbapt i = au->fra_index; 395264790Sbapt if ((i < 0) || (i > FR_NUMAUTH) || 396264790Sbapt (fr_auth[i].fra_info.fin_id != au->fra_info.fin_id)) { 397264790Sbapt RWLOCK_EXIT(&ipf_auth); 398264790Sbapt return EINVAL; 399264790Sbapt } 400264790Sbapt m = fr_authpkts[i]; 401264790Sbapt fr_auth[i].fra_index = -2; 402264790Sbapt fr_auth[i].fra_pass = au->fra_pass; 403264790Sbapt fr_authpkts[i] = NULL; 404264790Sbapt#ifdef _KERNEL 405264790Sbapt RWLOCK_EXIT(&ipf_auth); 406264790Sbapt# ifndef linux 407264790Sbapt if (m && au->fra_info.fin_out) { 408264790Sbapt# if SOLARIS 409264790Sbapt error = fr_qout(fr_auth[i].fra_q, m); 410264790Sbapt# else /* SOLARIS */ 411264790Sbapt# if (_BSDI_VERSION >= 199802) || defined(__OpenBSD__) 412264790Sbapt error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL, 413264790Sbapt NULL); 414264790Sbapt# else 415264790Sbapt error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL); 416264790Sbapt# endif 417264790Sbapt# endif /* SOLARIS */ 418264790Sbapt if (error) 419264790Sbapt fr_authstats.fas_sendfail++; 420264790Sbapt else 421264790Sbapt fr_authstats.fas_sendok++; 422264790Sbapt } else if (m) { 423264790Sbapt# if SOLARIS 424264790Sbapt error = fr_qin(fr_auth[i].fra_q, m); 425264790Sbapt# else /* SOLARIS */ 426264790Sbapt ifq = &ipintrq; 427264790Sbapt if (IF_QFULL(ifq)) { 428264790Sbapt IF_DROP(ifq); 429264790Sbapt m_freem(m); 430264790Sbapt error = ENOBUFS; 431264790Sbapt } else { 432264790Sbapt IF_ENQUEUE(ifq, m); 433264790Sbapt schednetisr(NETISR_IP); 434264790Sbapt } 435264790Sbapt# endif /* SOLARIS */ 436264790Sbapt if (error) 437264790Sbapt fr_authstats.fas_quefail++; 438264790Sbapt else 439264790Sbapt fr_authstats.fas_queok++; 440264790Sbapt } else 441264790Sbapt error = EINVAL; 442264790Sbapt# endif 443264790Sbapt# if SOLARIS 444264790Sbapt if (error) 445264790Sbapt error = EINVAL; 446264790Sbapt# else 447264790Sbapt /* 448264790Sbapt * If we experience an error which will result in the packet 449264790Sbapt * not being processed, make sure we advance to the next one. 450264790Sbapt */ 451264790Sbapt if (error == ENOBUFS) { 452264790Sbapt fr_authused--; 453264790Sbapt fr_auth[i].fra_index = -1; 454264790Sbapt fr_auth[i].fra_pass = 0; 455264790Sbapt if (i == fr_authstart) { 456264790Sbapt while (fr_auth[i].fra_index == -1) { 457264790Sbapt i++; 458264790Sbapt if (i == FR_NUMAUTH) 459264790Sbapt i = 0; 460264790Sbapt fr_authstart = i; 461264790Sbapt if (i == fr_authend) 462264790Sbapt break; 463264790Sbapt } 464264790Sbapt if (fr_authstart == fr_authend) { 465264790Sbapt fr_authnext = 0; 466264790Sbapt fr_authstart = fr_authend = 0; 467264790Sbapt } 468264790Sbapt } 469264790Sbapt } 470264790Sbapt# endif 471264790Sbapt#endif /* _KERNEL */ 472264790Sbapt break; 473264790Sbapt default : 474264790Sbapt error = EINVAL; 475264790Sbapt break; 476264790Sbapt } 477264790Sbapt return error; 478264790Sbapt} 479264790Sbapt 480264790Sbapt 481264790Sbapt#ifdef _KERNEL 482264790Sbapt/* 483264790Sbapt * Free all network buffer memory used to keep saved packets. 484264790Sbapt */ 485264790Sbaptvoid fr_authunload() 486264790Sbapt{ 487264790Sbapt register int i; 488264790Sbapt register frauthent_t *fae, **faep; 489264790Sbapt mb_t *m; 490264790Sbapt 491264790Sbapt WRITE_ENTER(&ipf_auth); 492264790Sbapt for (i = 0; i < FR_NUMAUTH; i++) { 493264790Sbapt if ((m = fr_authpkts[i])) { 494264790Sbapt FREE_MB_T(m); 495264790Sbapt fr_authpkts[i] = NULL; 496264790Sbapt fr_auth[i].fra_index = -1; 497264790Sbapt } 498264790Sbapt } 499264790Sbapt 500264790Sbapt 501264790Sbapt for (faep = &fae_list; (fae = *faep); ) { 502264790Sbapt *faep = fae->fae_next; 503264790Sbapt KFREE(fae); 504264790Sbapt } 505264790Sbapt ipauth = NULL; 506264790Sbapt RWLOCK_EXIT(&ipf_auth); 507264790Sbapt} 508264790Sbapt 509264790Sbapt 510264790Sbapt/* 511264790Sbapt * Slowly expire held auth records. Timeouts are set 512264790Sbapt * in expectation of this being called twice per second. 513264790Sbapt */ 514264790Sbaptvoid fr_authexpire() 515264790Sbapt{ 516264790Sbapt register int i; 517264790Sbapt register frauth_t *fra; 518264790Sbapt register frauthent_t *fae, **faep; 519264790Sbapt mb_t *m; 520264790Sbapt#if !SOLARIS 521264790Sbapt int s; 522264790Sbapt#endif 523264790Sbapt 524264790Sbapt if (fr_auth_lock) 525264790Sbapt return; 526264790Sbapt 527264790Sbapt SPL_NET(s); 528264790Sbapt WRITE_ENTER(&ipf_auth); 529264790Sbapt for (i = 0, fra = fr_auth; i < FR_NUMAUTH; i++, fra++) { 530264790Sbapt if ((!--fra->fra_age) && (m = fr_authpkts[i])) { 531264790Sbapt FREE_MB_T(m); 532264790Sbapt fr_authpkts[i] = NULL; 533264790Sbapt fr_auth[i].fra_index = -1; 534264790Sbapt fr_authstats.fas_expire++; 535264790Sbapt fr_authused--; 536264790Sbapt } 537264790Sbapt } 538264790Sbapt 539264790Sbapt for (faep = &fae_list; (fae = *faep); ) { 540264790Sbapt if (!--fae->fae_age) { 541264790Sbapt *faep = fae->fae_next; 542264790Sbapt KFREE(fae); 543264790Sbapt fr_authstats.fas_expire++; 544264790Sbapt } else 545264790Sbapt faep = &fae->fae_next; 546264790Sbapt } 547264790Sbapt ipauth = &fae_list->fae_fr; 548264790Sbapt RWLOCK_EXIT(&ipf_auth); 549264790Sbapt SPL_X(s); 550264790Sbapt} 551264790Sbapt#endif 552264790Sbapt