1*ab25eeb5Syz155240 /* 2*ab25eeb5Syz155240 * Copyright (C) 1998-2003 by Darren Reed & Guido van Rooij. 3*ab25eeb5Syz155240 * 4*ab25eeb5Syz155240 * See the IPFILTER.LICENCE file for details on licencing. 5*ab25eeb5Syz155240 */ 6*ab25eeb5Syz155240 #if defined(KERNEL) || defined(_KERNEL) 7*ab25eeb5Syz155240 # undef KERNEL 8*ab25eeb5Syz155240 # undef _KERNEL 9*ab25eeb5Syz155240 # define KERNEL 1 10*ab25eeb5Syz155240 # define _KERNEL 1 11*ab25eeb5Syz155240 #endif 12*ab25eeb5Syz155240 #include <sys/errno.h> 13*ab25eeb5Syz155240 #include <sys/types.h> 14*ab25eeb5Syz155240 #include <sys/param.h> 15*ab25eeb5Syz155240 #include <sys/time.h> 16*ab25eeb5Syz155240 #include <sys/file.h> 17*ab25eeb5Syz155240 #if !defined(_KERNEL) 18*ab25eeb5Syz155240 # include <stdio.h> 19*ab25eeb5Syz155240 # include <stdlib.h> 20*ab25eeb5Syz155240 # include <string.h> 21*ab25eeb5Syz155240 # define _KERNEL 22*ab25eeb5Syz155240 # ifdef __OpenBSD__ 23*ab25eeb5Syz155240 struct file; 24*ab25eeb5Syz155240 # endif 25*ab25eeb5Syz155240 # include <sys/uio.h> 26*ab25eeb5Syz155240 # undef _KERNEL 27*ab25eeb5Syz155240 #endif 28*ab25eeb5Syz155240 #if defined(_KERNEL) && (__FreeBSD_version >= 220000) 29*ab25eeb5Syz155240 # include <sys/filio.h> 30*ab25eeb5Syz155240 # include <sys/fcntl.h> 31*ab25eeb5Syz155240 #else 32*ab25eeb5Syz155240 # include <sys/ioctl.h> 33*ab25eeb5Syz155240 #endif 34*ab25eeb5Syz155240 #if !defined(linux) 35*ab25eeb5Syz155240 # include <sys/protosw.h> 36*ab25eeb5Syz155240 #endif 37*ab25eeb5Syz155240 #include <sys/socket.h> 38*ab25eeb5Syz155240 #if defined(_KERNEL) 39*ab25eeb5Syz155240 # include <sys/systm.h> 40*ab25eeb5Syz155240 # if !defined(__SVR4) && !defined(__svr4__) && !defined(linux) 41*ab25eeb5Syz155240 # include <sys/mbuf.h> 42*ab25eeb5Syz155240 # endif 43*ab25eeb5Syz155240 #endif 44*ab25eeb5Syz155240 #if defined(__SVR4) || defined(__svr4__) 45*ab25eeb5Syz155240 # include <sys/filio.h> 46*ab25eeb5Syz155240 # include <sys/byteorder.h> 47*ab25eeb5Syz155240 # ifdef _KERNEL 48*ab25eeb5Syz155240 # include <sys/dditypes.h> 49*ab25eeb5Syz155240 # endif 50*ab25eeb5Syz155240 # include <sys/stream.h> 51*ab25eeb5Syz155240 # include <sys/kmem.h> 52*ab25eeb5Syz155240 #endif 53*ab25eeb5Syz155240 #if (_BSDI_VERSION >= 199802) || (__FreeBSD_version >= 400000) 54*ab25eeb5Syz155240 # include <sys/queue.h> 55*ab25eeb5Syz155240 #endif 56*ab25eeb5Syz155240 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(bsdi) 57*ab25eeb5Syz155240 # include <machine/cpu.h> 58*ab25eeb5Syz155240 #endif 59*ab25eeb5Syz155240 #if defined(_KERNEL) && defined(__NetBSD__) && (__NetBSD_Version__ >= 104000000) 60*ab25eeb5Syz155240 # include <sys/proc.h> 61*ab25eeb5Syz155240 #endif 62*ab25eeb5Syz155240 #include <net/if.h> 63*ab25eeb5Syz155240 #ifdef sun 64*ab25eeb5Syz155240 # include <net/af.h> 65*ab25eeb5Syz155240 #endif 66*ab25eeb5Syz155240 #include <net/route.h> 67*ab25eeb5Syz155240 #include <netinet/in.h> 68*ab25eeb5Syz155240 #include <netinet/in_systm.h> 69*ab25eeb5Syz155240 #include <netinet/ip.h> 70*ab25eeb5Syz155240 #if !defined(_KERNEL) && !defined(__osf__) && !defined(__sgi) 71*ab25eeb5Syz155240 # define KERNEL 72*ab25eeb5Syz155240 # define _KERNEL 73*ab25eeb5Syz155240 # define NOT_KERNEL 74*ab25eeb5Syz155240 #endif 75*ab25eeb5Syz155240 #if !defined(linux) 76*ab25eeb5Syz155240 # include <netinet/ip_var.h> 77*ab25eeb5Syz155240 #endif 78*ab25eeb5Syz155240 #ifdef NOT_KERNEL 79*ab25eeb5Syz155240 # undef _KERNEL 80*ab25eeb5Syz155240 # undef KERNEL 81*ab25eeb5Syz155240 #endif 82*ab25eeb5Syz155240 #include <netinet/tcp.h> 83*ab25eeb5Syz155240 #if defined(IRIX) && (IRIX < 60516) /* IRIX < 6 */ 84*ab25eeb5Syz155240 extern struct ifqueue ipintrq; /* ip packet input queue */ 85*ab25eeb5Syz155240 #else 86*ab25eeb5Syz155240 # if !defined(__hpux) && !defined(linux) 87*ab25eeb5Syz155240 # if __FreeBSD_version >= 300000 88*ab25eeb5Syz155240 # include <net/if_var.h> 89*ab25eeb5Syz155240 # if __FreeBSD_version >= 500042 90*ab25eeb5Syz155240 # define IF_QFULL _IF_QFULL 91*ab25eeb5Syz155240 # define IF_DROP _IF_DROP 92*ab25eeb5Syz155240 # endif /* __FreeBSD_version >= 500042 */ 93*ab25eeb5Syz155240 # endif 94*ab25eeb5Syz155240 # include <netinet/in_var.h> 95*ab25eeb5Syz155240 # include <netinet/tcp_fsm.h> 96*ab25eeb5Syz155240 # endif 97*ab25eeb5Syz155240 #endif 98*ab25eeb5Syz155240 #include <netinet/udp.h> 99*ab25eeb5Syz155240 #include <netinet/ip_icmp.h> 100*ab25eeb5Syz155240 #include "netinet/ip_compat.h" 101*ab25eeb5Syz155240 #include <netinet/tcpip.h> 102*ab25eeb5Syz155240 #include "netinet/ip_fil.h" 103*ab25eeb5Syz155240 #include "netinet/ip_auth.h" 104*ab25eeb5Syz155240 #if !defined(MENTAT) && !defined(linux) 105*ab25eeb5Syz155240 # include <net/netisr.h> 106*ab25eeb5Syz155240 # ifdef __FreeBSD__ 107*ab25eeb5Syz155240 # include <machine/cpufunc.h> 108*ab25eeb5Syz155240 # endif 109*ab25eeb5Syz155240 #endif 110*ab25eeb5Syz155240 #if (__FreeBSD_version >= 300000) 111*ab25eeb5Syz155240 # include <sys/malloc.h> 112*ab25eeb5Syz155240 # if defined(_KERNEL) && !defined(IPFILTER_LKM) 113*ab25eeb5Syz155240 # include <sys/libkern.h> 114*ab25eeb5Syz155240 # include <sys/systm.h> 115*ab25eeb5Syz155240 # endif 116*ab25eeb5Syz155240 #endif 117*ab25eeb5Syz155240 /* END OF INCLUDES */ 118*ab25eeb5Syz155240 119*ab25eeb5Syz155240 #if !defined(lint) 120*ab25eeb5Syz155240 static const char rcsid[] = "@(#)$Id: ip_auth.c,v 2.73.2.5 2005/06/12 07:18:14 darrenr Exp $"; 121*ab25eeb5Syz155240 #endif 122*ab25eeb5Syz155240 123*ab25eeb5Syz155240 124*ab25eeb5Syz155240 #if SOLARIS 125*ab25eeb5Syz155240 extern kcondvar_t ipfauthwait; 126*ab25eeb5Syz155240 #endif /* SOLARIS */ 127*ab25eeb5Syz155240 #if defined(linux) && defined(_KERNEL) 128*ab25eeb5Syz155240 wait_queue_head_t fr_authnext_linux; 129*ab25eeb5Syz155240 #endif 130*ab25eeb5Syz155240 131*ab25eeb5Syz155240 int fr_authsize = FR_NUMAUTH; 132*ab25eeb5Syz155240 int fr_authused = 0; 133*ab25eeb5Syz155240 int fr_defaultauthage = 600; 134*ab25eeb5Syz155240 int fr_auth_lock = 0; 135*ab25eeb5Syz155240 int fr_auth_init = 0; 136*ab25eeb5Syz155240 fr_authstat_t fr_authstats; 137*ab25eeb5Syz155240 static frauth_t *fr_auth = NULL; 138*ab25eeb5Syz155240 mb_t **fr_authpkts = NULL; 139*ab25eeb5Syz155240 int fr_authstart = 0, fr_authend = 0, fr_authnext = 0; 140*ab25eeb5Syz155240 frauthent_t *fae_list = NULL; 141*ab25eeb5Syz155240 frentry_t *ipauth = NULL, 142*ab25eeb5Syz155240 *fr_authlist = NULL; 143*ab25eeb5Syz155240 144*ab25eeb5Syz155240 145*ab25eeb5Syz155240 int fr_authinit() 146*ab25eeb5Syz155240 { 147*ab25eeb5Syz155240 KMALLOCS(fr_auth, frauth_t *, fr_authsize * sizeof(*fr_auth)); 148*ab25eeb5Syz155240 if (fr_auth != NULL) 149*ab25eeb5Syz155240 bzero((char *)fr_auth, fr_authsize * sizeof(*fr_auth)); 150*ab25eeb5Syz155240 else 151*ab25eeb5Syz155240 return -1; 152*ab25eeb5Syz155240 153*ab25eeb5Syz155240 KMALLOCS(fr_authpkts, mb_t **, fr_authsize * sizeof(*fr_authpkts)); 154*ab25eeb5Syz155240 if (fr_authpkts != NULL) 155*ab25eeb5Syz155240 bzero((char *)fr_authpkts, fr_authsize * sizeof(*fr_authpkts)); 156*ab25eeb5Syz155240 else 157*ab25eeb5Syz155240 return -2; 158*ab25eeb5Syz155240 159*ab25eeb5Syz155240 MUTEX_INIT(&ipf_authmx, "ipf auth log mutex"); 160*ab25eeb5Syz155240 RWLOCK_INIT(&ipf_auth, "ipf IP User-Auth rwlock"); 161*ab25eeb5Syz155240 #if SOLARIS && defined(_KERNEL) 162*ab25eeb5Syz155240 cv_init(&ipfauthwait, "ipf auth condvar", CV_DRIVER, NULL); 163*ab25eeb5Syz155240 #endif 164*ab25eeb5Syz155240 #if defined(linux) && defined(_KERNEL) 165*ab25eeb5Syz155240 init_waitqueue_head(&fr_authnext_linux); 166*ab25eeb5Syz155240 #endif 167*ab25eeb5Syz155240 168*ab25eeb5Syz155240 fr_auth_init = 1; 169*ab25eeb5Syz155240 170*ab25eeb5Syz155240 return 0; 171*ab25eeb5Syz155240 } 172*ab25eeb5Syz155240 173*ab25eeb5Syz155240 174*ab25eeb5Syz155240 /* 175*ab25eeb5Syz155240 * Check if a packet has authorization. If the packet is found to match an 176*ab25eeb5Syz155240 * authorization result and that would result in a feedback loop (i.e. it 177*ab25eeb5Syz155240 * will end up returning FR_AUTH) then return FR_BLOCK instead. 178*ab25eeb5Syz155240 */ 179*ab25eeb5Syz155240 frentry_t *fr_checkauth(fin, passp) 180*ab25eeb5Syz155240 fr_info_t *fin; 181*ab25eeb5Syz155240 u_32_t *passp; 182*ab25eeb5Syz155240 { 183*ab25eeb5Syz155240 frentry_t *fr; 184*ab25eeb5Syz155240 frauth_t *fra; 185*ab25eeb5Syz155240 u_32_t pass; 186*ab25eeb5Syz155240 u_short id; 187*ab25eeb5Syz155240 ip_t *ip; 188*ab25eeb5Syz155240 int i; 189*ab25eeb5Syz155240 190*ab25eeb5Syz155240 if (fr_auth_lock || !fr_authused) 191*ab25eeb5Syz155240 return NULL; 192*ab25eeb5Syz155240 193*ab25eeb5Syz155240 ip = fin->fin_ip; 194*ab25eeb5Syz155240 id = ip->ip_id; 195*ab25eeb5Syz155240 196*ab25eeb5Syz155240 READ_ENTER(&ipf_auth); 197*ab25eeb5Syz155240 for (i = fr_authstart; i != fr_authend; ) { 198*ab25eeb5Syz155240 /* 199*ab25eeb5Syz155240 * index becomes -2 only after an SIOCAUTHW. Check this in 200*ab25eeb5Syz155240 * case the same packet gets sent again and it hasn't yet been 201*ab25eeb5Syz155240 * auth'd. 202*ab25eeb5Syz155240 */ 203*ab25eeb5Syz155240 fra = fr_auth + i; 204*ab25eeb5Syz155240 if ((fra->fra_index == -2) && (id == fra->fra_info.fin_id) && 205*ab25eeb5Syz155240 !bcmp((char *)fin, (char *)&fra->fra_info, FI_CSIZE)) { 206*ab25eeb5Syz155240 /* 207*ab25eeb5Syz155240 * Avoid feedback loop. 208*ab25eeb5Syz155240 */ 209*ab25eeb5Syz155240 if (!(pass = fra->fra_pass) || (FR_ISAUTH(pass))) 210*ab25eeb5Syz155240 pass = FR_BLOCK; 211*ab25eeb5Syz155240 /* 212*ab25eeb5Syz155240 * Create a dummy rule for the stateful checking to 213*ab25eeb5Syz155240 * use and return. Zero out any values we don't 214*ab25eeb5Syz155240 * trust from userland! 215*ab25eeb5Syz155240 */ 216*ab25eeb5Syz155240 if ((pass & FR_KEEPSTATE) || ((pass & FR_KEEPFRAG) && 217*ab25eeb5Syz155240 (fin->fin_flx & FI_FRAG))) { 218*ab25eeb5Syz155240 KMALLOC(fr, frentry_t *); 219*ab25eeb5Syz155240 if (fr) { 220*ab25eeb5Syz155240 bcopy((char *)fra->fra_info.fin_fr, 221*ab25eeb5Syz155240 (char *)fr, sizeof(*fr)); 222*ab25eeb5Syz155240 fr->fr_grp = NULL; 223*ab25eeb5Syz155240 fr->fr_ifa = fin->fin_ifp; 224*ab25eeb5Syz155240 fr->fr_func = NULL; 225*ab25eeb5Syz155240 fr->fr_ref = 1; 226*ab25eeb5Syz155240 fr->fr_flags = pass; 227*ab25eeb5Syz155240 fr->fr_ifas[1] = NULL; 228*ab25eeb5Syz155240 fr->fr_ifas[2] = NULL; 229*ab25eeb5Syz155240 fr->fr_ifas[3] = NULL; 230*ab25eeb5Syz155240 } 231*ab25eeb5Syz155240 } else 232*ab25eeb5Syz155240 fr = fra->fra_info.fin_fr; 233*ab25eeb5Syz155240 fin->fin_fr = fr; 234*ab25eeb5Syz155240 RWLOCK_EXIT(&ipf_auth); 235*ab25eeb5Syz155240 WRITE_ENTER(&ipf_auth); 236*ab25eeb5Syz155240 if ((fr != NULL) && (fr != fra->fra_info.fin_fr)) { 237*ab25eeb5Syz155240 fr->fr_next = fr_authlist; 238*ab25eeb5Syz155240 fr_authlist = fr; 239*ab25eeb5Syz155240 } 240*ab25eeb5Syz155240 fr_authstats.fas_hits++; 241*ab25eeb5Syz155240 fra->fra_index = -1; 242*ab25eeb5Syz155240 fr_authused--; 243*ab25eeb5Syz155240 if (i == fr_authstart) { 244*ab25eeb5Syz155240 while (fra->fra_index == -1) { 245*ab25eeb5Syz155240 i++; 246*ab25eeb5Syz155240 fra++; 247*ab25eeb5Syz155240 if (i == fr_authsize) { 248*ab25eeb5Syz155240 i = 0; 249*ab25eeb5Syz155240 fra = fr_auth; 250*ab25eeb5Syz155240 } 251*ab25eeb5Syz155240 fr_authstart = i; 252*ab25eeb5Syz155240 if (i == fr_authend) 253*ab25eeb5Syz155240 break; 254*ab25eeb5Syz155240 } 255*ab25eeb5Syz155240 if (fr_authstart == fr_authend) { 256*ab25eeb5Syz155240 fr_authnext = 0; 257*ab25eeb5Syz155240 fr_authstart = fr_authend = 0; 258*ab25eeb5Syz155240 } 259*ab25eeb5Syz155240 } 260*ab25eeb5Syz155240 RWLOCK_EXIT(&ipf_auth); 261*ab25eeb5Syz155240 if (passp != NULL) 262*ab25eeb5Syz155240 *passp = pass; 263*ab25eeb5Syz155240 ATOMIC_INC64(fr_authstats.fas_hits); 264*ab25eeb5Syz155240 return fr; 265*ab25eeb5Syz155240 } 266*ab25eeb5Syz155240 i++; 267*ab25eeb5Syz155240 if (i == fr_authsize) 268*ab25eeb5Syz155240 i = 0; 269*ab25eeb5Syz155240 } 270*ab25eeb5Syz155240 fr_authstats.fas_miss++; 271*ab25eeb5Syz155240 RWLOCK_EXIT(&ipf_auth); 272*ab25eeb5Syz155240 ATOMIC_INC64(fr_authstats.fas_miss); 273*ab25eeb5Syz155240 return NULL; 274*ab25eeb5Syz155240 } 275*ab25eeb5Syz155240 276*ab25eeb5Syz155240 277*ab25eeb5Syz155240 /* 278*ab25eeb5Syz155240 * Check if we have room in the auth array to hold details for another packet. 279*ab25eeb5Syz155240 * If we do, store it and wake up any user programs which are waiting to 280*ab25eeb5Syz155240 * hear about these events. 281*ab25eeb5Syz155240 */ 282*ab25eeb5Syz155240 int fr_newauth(m, fin) 283*ab25eeb5Syz155240 mb_t *m; 284*ab25eeb5Syz155240 fr_info_t *fin; 285*ab25eeb5Syz155240 { 286*ab25eeb5Syz155240 #if defined(_KERNEL) && defined(MENTAT) 287*ab25eeb5Syz155240 qpktinfo_t *qpi = fin->fin_qpi; 288*ab25eeb5Syz155240 #endif 289*ab25eeb5Syz155240 frauth_t *fra; 290*ab25eeb5Syz155240 #if !defined(sparc) && !defined(m68k) 291*ab25eeb5Syz155240 ip_t *ip; 292*ab25eeb5Syz155240 #endif 293*ab25eeb5Syz155240 int i; 294*ab25eeb5Syz155240 295*ab25eeb5Syz155240 if (fr_auth_lock) 296*ab25eeb5Syz155240 return 0; 297*ab25eeb5Syz155240 298*ab25eeb5Syz155240 WRITE_ENTER(&ipf_auth); 299*ab25eeb5Syz155240 if (fr_authstart > fr_authend) { 300*ab25eeb5Syz155240 fr_authstats.fas_nospace++; 301*ab25eeb5Syz155240 RWLOCK_EXIT(&ipf_auth); 302*ab25eeb5Syz155240 return 0; 303*ab25eeb5Syz155240 } else { 304*ab25eeb5Syz155240 if (fr_authused == fr_authsize) { 305*ab25eeb5Syz155240 fr_authstats.fas_nospace++; 306*ab25eeb5Syz155240 RWLOCK_EXIT(&ipf_auth); 307*ab25eeb5Syz155240 return 0; 308*ab25eeb5Syz155240 } 309*ab25eeb5Syz155240 } 310*ab25eeb5Syz155240 311*ab25eeb5Syz155240 fr_authstats.fas_added++; 312*ab25eeb5Syz155240 fr_authused++; 313*ab25eeb5Syz155240 i = fr_authend++; 314*ab25eeb5Syz155240 if (fr_authend == fr_authsize) 315*ab25eeb5Syz155240 fr_authend = 0; 316*ab25eeb5Syz155240 RWLOCK_EXIT(&ipf_auth); 317*ab25eeb5Syz155240 318*ab25eeb5Syz155240 fra = fr_auth + i; 319*ab25eeb5Syz155240 fra->fra_index = i; 320*ab25eeb5Syz155240 fra->fra_pass = 0; 321*ab25eeb5Syz155240 fra->fra_age = fr_defaultauthage; 322*ab25eeb5Syz155240 bcopy((char *)fin, (char *)&fra->fra_info, sizeof(*fin)); 323*ab25eeb5Syz155240 #if !defined(sparc) && !defined(m68k) 324*ab25eeb5Syz155240 /* 325*ab25eeb5Syz155240 * No need to copyback here as we want to undo the changes, not keep 326*ab25eeb5Syz155240 * them. 327*ab25eeb5Syz155240 */ 328*ab25eeb5Syz155240 ip = fin->fin_ip; 329*ab25eeb5Syz155240 # if defined(MENTAT) && defined(_KERNEL) 330*ab25eeb5Syz155240 if ((ip == (ip_t *)m->b_rptr) && (fin->fin_v == 4)) 331*ab25eeb5Syz155240 # endif 332*ab25eeb5Syz155240 { 333*ab25eeb5Syz155240 register u_short bo; 334*ab25eeb5Syz155240 335*ab25eeb5Syz155240 bo = ip->ip_len; 336*ab25eeb5Syz155240 ip->ip_len = htons(bo); 337*ab25eeb5Syz155240 bo = ip->ip_off; 338*ab25eeb5Syz155240 ip->ip_off = htons(bo); 339*ab25eeb5Syz155240 } 340*ab25eeb5Syz155240 #endif 341*ab25eeb5Syz155240 #if SOLARIS && defined(_KERNEL) 342*ab25eeb5Syz155240 m->b_rptr -= qpi->qpi_off; 343*ab25eeb5Syz155240 fr_authpkts[i] = *(mblk_t **)fin->fin_mp; 344*ab25eeb5Syz155240 fra->fra_q = qpi->qpi_q; /* The queue can disappear! */ 345*ab25eeb5Syz155240 cv_signal(&ipfauthwait); 346*ab25eeb5Syz155240 #else 347*ab25eeb5Syz155240 # if defined(BSD) && !defined(sparc) && (BSD >= 199306) 348*ab25eeb5Syz155240 if (!fin->fin_out) { 349*ab25eeb5Syz155240 ip->ip_len = htons(ip->ip_len); 350*ab25eeb5Syz155240 ip->ip_off = htons(ip->ip_off); 351*ab25eeb5Syz155240 } 352*ab25eeb5Syz155240 # endif 353*ab25eeb5Syz155240 fr_authpkts[i] = m; 354*ab25eeb5Syz155240 WAKEUP(&fr_authnext,0); 355*ab25eeb5Syz155240 #endif 356*ab25eeb5Syz155240 return 1; 357*ab25eeb5Syz155240 } 358*ab25eeb5Syz155240 359*ab25eeb5Syz155240 360*ab25eeb5Syz155240 int fr_auth_ioctl(data, cmd, mode) 361*ab25eeb5Syz155240 caddr_t data; 362*ab25eeb5Syz155240 ioctlcmd_t cmd; 363*ab25eeb5Syz155240 int mode; 364*ab25eeb5Syz155240 { 365*ab25eeb5Syz155240 mb_t *m; 366*ab25eeb5Syz155240 #if defined(_KERNEL) && !defined(MENTAT) && !defined(linux) && \ 367*ab25eeb5Syz155240 (!defined(__FreeBSD_version) || (__FreeBSD_version < 501000)) 368*ab25eeb5Syz155240 struct ifqueue *ifq; 369*ab25eeb5Syz155240 SPL_INT(s); 370*ab25eeb5Syz155240 #endif 371*ab25eeb5Syz155240 frauth_t auth, *au = &auth, *fra; 372*ab25eeb5Syz155240 int i, error = 0, len; 373*ab25eeb5Syz155240 char *t; 374*ab25eeb5Syz155240 375*ab25eeb5Syz155240 switch (cmd) 376*ab25eeb5Syz155240 { 377*ab25eeb5Syz155240 case SIOCSTLCK : 378*ab25eeb5Syz155240 if (!(mode & FWRITE)) { 379*ab25eeb5Syz155240 error = EPERM; 380*ab25eeb5Syz155240 break; 381*ab25eeb5Syz155240 } 382*ab25eeb5Syz155240 fr_lock(data, &fr_auth_lock); 383*ab25eeb5Syz155240 break; 384*ab25eeb5Syz155240 385*ab25eeb5Syz155240 case SIOCATHST: 386*ab25eeb5Syz155240 fr_authstats.fas_faelist = fae_list; 387*ab25eeb5Syz155240 error = fr_outobj(data, &fr_authstats, IPFOBJ_AUTHSTAT); 388*ab25eeb5Syz155240 break; 389*ab25eeb5Syz155240 390*ab25eeb5Syz155240 case SIOCIPFFL: 391*ab25eeb5Syz155240 SPL_NET(s); 392*ab25eeb5Syz155240 WRITE_ENTER(&ipf_auth); 393*ab25eeb5Syz155240 i = fr_authflush(); 394*ab25eeb5Syz155240 RWLOCK_EXIT(&ipf_auth); 395*ab25eeb5Syz155240 SPL_X(s); 396*ab25eeb5Syz155240 error = copyoutptr((char *)&i, data, sizeof(i)); 397*ab25eeb5Syz155240 break; 398*ab25eeb5Syz155240 399*ab25eeb5Syz155240 case SIOCAUTHW: 400*ab25eeb5Syz155240 fr_authioctlloop: 401*ab25eeb5Syz155240 error = fr_inobj(data, au, IPFOBJ_FRAUTH); 402*ab25eeb5Syz155240 READ_ENTER(&ipf_auth); 403*ab25eeb5Syz155240 if ((fr_authnext != fr_authend) && fr_authpkts[fr_authnext]) { 404*ab25eeb5Syz155240 error = fr_outobj(data, &fr_auth[fr_authnext], 405*ab25eeb5Syz155240 IPFOBJ_FRAUTH); 406*ab25eeb5Syz155240 if (auth.fra_len != 0 && auth.fra_buf != NULL) { 407*ab25eeb5Syz155240 /* 408*ab25eeb5Syz155240 * Copy packet contents out to user space if 409*ab25eeb5Syz155240 * requested. Bail on an error. 410*ab25eeb5Syz155240 */ 411*ab25eeb5Syz155240 m = fr_authpkts[fr_authnext]; 412*ab25eeb5Syz155240 len = MSGDSIZE(m); 413*ab25eeb5Syz155240 if (len > auth.fra_len) 414*ab25eeb5Syz155240 len = auth.fra_len; 415*ab25eeb5Syz155240 auth.fra_len = len; 416*ab25eeb5Syz155240 for (t = auth.fra_buf; m && (len > 0); ) { 417*ab25eeb5Syz155240 i = MIN(M_LEN(m), len); 418*ab25eeb5Syz155240 error = copyoutptr(MTOD(m, char *), 419*ab25eeb5Syz155240 t, i); 420*ab25eeb5Syz155240 len -= i; 421*ab25eeb5Syz155240 t += i; 422*ab25eeb5Syz155240 if (error != 0) 423*ab25eeb5Syz155240 break; 424*ab25eeb5Syz155240 } 425*ab25eeb5Syz155240 } 426*ab25eeb5Syz155240 RWLOCK_EXIT(&ipf_auth); 427*ab25eeb5Syz155240 if (error != 0) 428*ab25eeb5Syz155240 break; 429*ab25eeb5Syz155240 SPL_NET(s); 430*ab25eeb5Syz155240 WRITE_ENTER(&ipf_auth); 431*ab25eeb5Syz155240 fr_authnext++; 432*ab25eeb5Syz155240 if (fr_authnext == fr_authsize) 433*ab25eeb5Syz155240 fr_authnext = 0; 434*ab25eeb5Syz155240 RWLOCK_EXIT(&ipf_auth); 435*ab25eeb5Syz155240 SPL_X(s); 436*ab25eeb5Syz155240 return 0; 437*ab25eeb5Syz155240 } 438*ab25eeb5Syz155240 RWLOCK_EXIT(&ipf_auth); 439*ab25eeb5Syz155240 /* 440*ab25eeb5Syz155240 * We exit ipf_global here because a program that enters in 441*ab25eeb5Syz155240 * here will have a lock on it and goto sleep having this lock. 442*ab25eeb5Syz155240 * If someone were to do an 'ipf -D' the system would then 443*ab25eeb5Syz155240 * deadlock. The catch with releasing it here is that the 444*ab25eeb5Syz155240 * caller of this function expects it to be held when we 445*ab25eeb5Syz155240 * return so we have to reacquire it in here. 446*ab25eeb5Syz155240 */ 447*ab25eeb5Syz155240 RWLOCK_EXIT(&ipf_global); 448*ab25eeb5Syz155240 449*ab25eeb5Syz155240 MUTEX_ENTER(&ipf_authmx); 450*ab25eeb5Syz155240 #ifdef _KERNEL 451*ab25eeb5Syz155240 # if SOLARIS 452*ab25eeb5Syz155240 error = 0; 453*ab25eeb5Syz155240 if (!cv_wait_sig(&ipfauthwait, &ipf_authmx.ipf_lk)) 454*ab25eeb5Syz155240 error = EINTR; 455*ab25eeb5Syz155240 # else /* SOLARIS */ 456*ab25eeb5Syz155240 # ifdef __hpux 457*ab25eeb5Syz155240 { 458*ab25eeb5Syz155240 lock_t *l; 459*ab25eeb5Syz155240 460*ab25eeb5Syz155240 l = get_sleep_lock(&fr_authnext); 461*ab25eeb5Syz155240 error = sleep(&fr_authnext, PZERO+1); 462*ab25eeb5Syz155240 spinunlock(l); 463*ab25eeb5Syz155240 } 464*ab25eeb5Syz155240 # else 465*ab25eeb5Syz155240 # ifdef __osf__ 466*ab25eeb5Syz155240 error = mpsleep(&fr_authnext, PSUSP|PCATCH, "fr_authnext", 0, 467*ab25eeb5Syz155240 &ipf_authmx, MS_LOCK_SIMPLE); 468*ab25eeb5Syz155240 # else 469*ab25eeb5Syz155240 error = SLEEP(&fr_authnext, "fr_authnext"); 470*ab25eeb5Syz155240 # endif /* __osf__ */ 471*ab25eeb5Syz155240 # endif /* __hpux */ 472*ab25eeb5Syz155240 # endif /* SOLARIS */ 473*ab25eeb5Syz155240 #endif 474*ab25eeb5Syz155240 MUTEX_EXIT(&ipf_authmx); 475*ab25eeb5Syz155240 READ_ENTER(&ipf_global); 476*ab25eeb5Syz155240 if (error == 0) { 477*ab25eeb5Syz155240 READ_ENTER(&ipf_auth); 478*ab25eeb5Syz155240 goto fr_authioctlloop; 479*ab25eeb5Syz155240 } 480*ab25eeb5Syz155240 break; 481*ab25eeb5Syz155240 482*ab25eeb5Syz155240 case SIOCAUTHR: 483*ab25eeb5Syz155240 error = fr_inobj(data, &auth, IPFOBJ_FRAUTH); 484*ab25eeb5Syz155240 if (error != 0) 485*ab25eeb5Syz155240 return error; 486*ab25eeb5Syz155240 SPL_NET(s); 487*ab25eeb5Syz155240 WRITE_ENTER(&ipf_auth); 488*ab25eeb5Syz155240 i = au->fra_index; 489*ab25eeb5Syz155240 fra = fr_auth + i; 490*ab25eeb5Syz155240 if ((i < 0) || (i >= fr_authsize) || 491*ab25eeb5Syz155240 (fra->fra_info.fin_id != au->fra_info.fin_id)) { 492*ab25eeb5Syz155240 RWLOCK_EXIT(&ipf_auth); 493*ab25eeb5Syz155240 SPL_X(s); 494*ab25eeb5Syz155240 return ESRCH; 495*ab25eeb5Syz155240 } 496*ab25eeb5Syz155240 m = fr_authpkts[i]; 497*ab25eeb5Syz155240 fra->fra_index = -2; 498*ab25eeb5Syz155240 fra->fra_pass = au->fra_pass; 499*ab25eeb5Syz155240 fr_authpkts[i] = NULL; 500*ab25eeb5Syz155240 RWLOCK_EXIT(&ipf_auth); 501*ab25eeb5Syz155240 #ifdef _KERNEL 502*ab25eeb5Syz155240 if ((m != NULL) && (au->fra_info.fin_out != 0)) { 503*ab25eeb5Syz155240 # ifdef MENTAT 504*ab25eeb5Syz155240 error = !putq(fra->fra_q, m); 505*ab25eeb5Syz155240 # else /* MENTAT */ 506*ab25eeb5Syz155240 # if defined(linux) || defined(AIX) 507*ab25eeb5Syz155240 # else 508*ab25eeb5Syz155240 # if (_BSDI_VERSION >= 199802) || defined(__OpenBSD__) || \ 509*ab25eeb5Syz155240 (defined(__sgi) && (IRIX >= 60500) || defined(AIX) || \ 510*ab25eeb5Syz155240 (defined(__FreeBSD__) && (__FreeBSD_version >= 470102))) 511*ab25eeb5Syz155240 error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL, 512*ab25eeb5Syz155240 NULL); 513*ab25eeb5Syz155240 # else 514*ab25eeb5Syz155240 error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL); 515*ab25eeb5Syz155240 # endif 516*ab25eeb5Syz155240 # endif /* Linux */ 517*ab25eeb5Syz155240 # endif /* MENTAT */ 518*ab25eeb5Syz155240 if (error != 0) 519*ab25eeb5Syz155240 fr_authstats.fas_sendfail++; 520*ab25eeb5Syz155240 else 521*ab25eeb5Syz155240 fr_authstats.fas_sendok++; 522*ab25eeb5Syz155240 } else if (m) { 523*ab25eeb5Syz155240 # ifdef MENTAT 524*ab25eeb5Syz155240 error = !putq(fra->fra_q, m); 525*ab25eeb5Syz155240 # else /* MENTAT */ 526*ab25eeb5Syz155240 # if defined(linux) || defined(AIX) 527*ab25eeb5Syz155240 # else 528*ab25eeb5Syz155240 # if (__FreeBSD_version >= 501000) 529*ab25eeb5Syz155240 netisr_dispatch(NETISR_IP, m); 530*ab25eeb5Syz155240 # else 531*ab25eeb5Syz155240 # if (IRIX >= 60516) 532*ab25eeb5Syz155240 ifq = &((struct ifnet *)fra->fra_info.fin_ifp)->if_snd; 533*ab25eeb5Syz155240 # else 534*ab25eeb5Syz155240 ifq = &ipintrq; 535*ab25eeb5Syz155240 # endif 536*ab25eeb5Syz155240 if (IF_QFULL(ifq)) { 537*ab25eeb5Syz155240 IF_DROP(ifq); 538*ab25eeb5Syz155240 FREE_MB_T(m); 539*ab25eeb5Syz155240 error = ENOBUFS; 540*ab25eeb5Syz155240 } else { 541*ab25eeb5Syz155240 IF_ENQUEUE(ifq, m); 542*ab25eeb5Syz155240 # if IRIX < 60500 543*ab25eeb5Syz155240 schednetisr(NETISR_IP); 544*ab25eeb5Syz155240 # endif 545*ab25eeb5Syz155240 } 546*ab25eeb5Syz155240 # endif 547*ab25eeb5Syz155240 # endif /* Linux */ 548*ab25eeb5Syz155240 # endif /* MENTAT */ 549*ab25eeb5Syz155240 if (error != 0) 550*ab25eeb5Syz155240 fr_authstats.fas_quefail++; 551*ab25eeb5Syz155240 else 552*ab25eeb5Syz155240 fr_authstats.fas_queok++; 553*ab25eeb5Syz155240 } else 554*ab25eeb5Syz155240 error = EINVAL; 555*ab25eeb5Syz155240 # ifdef MENTAT 556*ab25eeb5Syz155240 if (error != 0) 557*ab25eeb5Syz155240 error = EINVAL; 558*ab25eeb5Syz155240 # else /* MENTAT */ 559*ab25eeb5Syz155240 /* 560*ab25eeb5Syz155240 * If we experience an error which will result in the packet 561*ab25eeb5Syz155240 * not being processed, make sure we advance to the next one. 562*ab25eeb5Syz155240 */ 563*ab25eeb5Syz155240 if (error == ENOBUFS) { 564*ab25eeb5Syz155240 fr_authused--; 565*ab25eeb5Syz155240 fra->fra_index = -1; 566*ab25eeb5Syz155240 fra->fra_pass = 0; 567*ab25eeb5Syz155240 if (i == fr_authstart) { 568*ab25eeb5Syz155240 while (fra->fra_index == -1) { 569*ab25eeb5Syz155240 i++; 570*ab25eeb5Syz155240 if (i == fr_authsize) 571*ab25eeb5Syz155240 i = 0; 572*ab25eeb5Syz155240 fr_authstart = i; 573*ab25eeb5Syz155240 if (i == fr_authend) 574*ab25eeb5Syz155240 break; 575*ab25eeb5Syz155240 } 576*ab25eeb5Syz155240 if (fr_authstart == fr_authend) { 577*ab25eeb5Syz155240 fr_authnext = 0; 578*ab25eeb5Syz155240 fr_authstart = fr_authend = 0; 579*ab25eeb5Syz155240 } 580*ab25eeb5Syz155240 } 581*ab25eeb5Syz155240 } 582*ab25eeb5Syz155240 # endif /* MENTAT */ 583*ab25eeb5Syz155240 #endif /* _KERNEL */ 584*ab25eeb5Syz155240 SPL_X(s); 585*ab25eeb5Syz155240 break; 586*ab25eeb5Syz155240 587*ab25eeb5Syz155240 default : 588*ab25eeb5Syz155240 error = EINVAL; 589*ab25eeb5Syz155240 break; 590*ab25eeb5Syz155240 } 591*ab25eeb5Syz155240 return error; 592*ab25eeb5Syz155240 } 593*ab25eeb5Syz155240 594*ab25eeb5Syz155240 595*ab25eeb5Syz155240 /* 596*ab25eeb5Syz155240 * Free all network buffer memory used to keep saved packets. 597*ab25eeb5Syz155240 */ 598*ab25eeb5Syz155240 void fr_authunload() 599*ab25eeb5Syz155240 { 600*ab25eeb5Syz155240 register int i; 601*ab25eeb5Syz155240 register frauthent_t *fae, **faep; 602*ab25eeb5Syz155240 frentry_t *fr, **frp; 603*ab25eeb5Syz155240 mb_t *m; 604*ab25eeb5Syz155240 605*ab25eeb5Syz155240 if (fr_auth != NULL) { 606*ab25eeb5Syz155240 KFREES(fr_auth, fr_authsize * sizeof(*fr_auth)); 607*ab25eeb5Syz155240 fr_auth = NULL; 608*ab25eeb5Syz155240 } 609*ab25eeb5Syz155240 610*ab25eeb5Syz155240 if (fr_authpkts != NULL) { 611*ab25eeb5Syz155240 for (i = 0; i < fr_authsize; i++) { 612*ab25eeb5Syz155240 m = fr_authpkts[i]; 613*ab25eeb5Syz155240 if (m != NULL) { 614*ab25eeb5Syz155240 FREE_MB_T(m); 615*ab25eeb5Syz155240 fr_authpkts[i] = NULL; 616*ab25eeb5Syz155240 } 617*ab25eeb5Syz155240 } 618*ab25eeb5Syz155240 KFREES(fr_authpkts, fr_authsize * sizeof(*fr_authpkts)); 619*ab25eeb5Syz155240 fr_authpkts = NULL; 620*ab25eeb5Syz155240 } 621*ab25eeb5Syz155240 622*ab25eeb5Syz155240 faep = &fae_list; 623*ab25eeb5Syz155240 while ((fae = *faep) != NULL) { 624*ab25eeb5Syz155240 *faep = fae->fae_next; 625*ab25eeb5Syz155240 KFREE(fae); 626*ab25eeb5Syz155240 } 627*ab25eeb5Syz155240 ipauth = NULL; 628*ab25eeb5Syz155240 629*ab25eeb5Syz155240 if (fr_authlist != NULL) { 630*ab25eeb5Syz155240 for (frp = &fr_authlist; ((fr = *frp) != NULL); ) { 631*ab25eeb5Syz155240 if (fr->fr_ref == 1) { 632*ab25eeb5Syz155240 *frp = fr->fr_next; 633*ab25eeb5Syz155240 KFREE(fr); 634*ab25eeb5Syz155240 } else 635*ab25eeb5Syz155240 frp = &fr->fr_next; 636*ab25eeb5Syz155240 } 637*ab25eeb5Syz155240 } 638*ab25eeb5Syz155240 639*ab25eeb5Syz155240 if (fr_auth_init == 1) { 640*ab25eeb5Syz155240 # if SOLARIS && defined(_KERNEL) 641*ab25eeb5Syz155240 cv_destroy(&ipfauthwait); 642*ab25eeb5Syz155240 # endif 643*ab25eeb5Syz155240 MUTEX_DESTROY(&ipf_authmx); 644*ab25eeb5Syz155240 RW_DESTROY(&ipf_auth); 645*ab25eeb5Syz155240 646*ab25eeb5Syz155240 fr_auth_init = 0; 647*ab25eeb5Syz155240 } 648*ab25eeb5Syz155240 } 649*ab25eeb5Syz155240 650*ab25eeb5Syz155240 651*ab25eeb5Syz155240 /* 652*ab25eeb5Syz155240 * Slowly expire held auth records. Timeouts are set 653*ab25eeb5Syz155240 * in expectation of this being called twice per second. 654*ab25eeb5Syz155240 */ 655*ab25eeb5Syz155240 void fr_authexpire() 656*ab25eeb5Syz155240 { 657*ab25eeb5Syz155240 register int i; 658*ab25eeb5Syz155240 register frauth_t *fra; 659*ab25eeb5Syz155240 register frauthent_t *fae, **faep; 660*ab25eeb5Syz155240 register frentry_t *fr, **frp; 661*ab25eeb5Syz155240 mb_t *m; 662*ab25eeb5Syz155240 SPL_INT(s); 663*ab25eeb5Syz155240 664*ab25eeb5Syz155240 if (fr_auth_lock) 665*ab25eeb5Syz155240 return; 666*ab25eeb5Syz155240 667*ab25eeb5Syz155240 SPL_NET(s); 668*ab25eeb5Syz155240 WRITE_ENTER(&ipf_auth); 669*ab25eeb5Syz155240 for (i = 0, fra = fr_auth; i < fr_authsize; i++, fra++) { 670*ab25eeb5Syz155240 fra->fra_age--; 671*ab25eeb5Syz155240 if ((fra->fra_age == 0) && (m = fr_authpkts[i])) { 672*ab25eeb5Syz155240 FREE_MB_T(m); 673*ab25eeb5Syz155240 fr_authpkts[i] = NULL; 674*ab25eeb5Syz155240 fr_auth[i].fra_index = -1; 675*ab25eeb5Syz155240 fr_authstats.fas_expire++; 676*ab25eeb5Syz155240 fr_authused--; 677*ab25eeb5Syz155240 } 678*ab25eeb5Syz155240 } 679*ab25eeb5Syz155240 680*ab25eeb5Syz155240 for (faep = &fae_list; ((fae = *faep) != NULL); ) { 681*ab25eeb5Syz155240 fae->fae_age--; 682*ab25eeb5Syz155240 if (fae->fae_age == 0) { 683*ab25eeb5Syz155240 *faep = fae->fae_next; 684*ab25eeb5Syz155240 KFREE(fae); 685*ab25eeb5Syz155240 fr_authstats.fas_expire++; 686*ab25eeb5Syz155240 } else 687*ab25eeb5Syz155240 faep = &fae->fae_next; 688*ab25eeb5Syz155240 } 689*ab25eeb5Syz155240 if (fae_list != NULL) 690*ab25eeb5Syz155240 ipauth = &fae_list->fae_fr; 691*ab25eeb5Syz155240 else 692*ab25eeb5Syz155240 ipauth = NULL; 693*ab25eeb5Syz155240 694*ab25eeb5Syz155240 for (frp = &fr_authlist; ((fr = *frp) != NULL); ) { 695*ab25eeb5Syz155240 if (fr->fr_ref == 1) { 696*ab25eeb5Syz155240 *frp = fr->fr_next; 697*ab25eeb5Syz155240 KFREE(fr); 698*ab25eeb5Syz155240 } else 699*ab25eeb5Syz155240 frp = &fr->fr_next; 700*ab25eeb5Syz155240 } 701*ab25eeb5Syz155240 RWLOCK_EXIT(&ipf_auth); 702*ab25eeb5Syz155240 SPL_X(s); 703*ab25eeb5Syz155240 } 704*ab25eeb5Syz155240 705*ab25eeb5Syz155240 int fr_preauthcmd(cmd, fr, frptr) 706*ab25eeb5Syz155240 ioctlcmd_t cmd; 707*ab25eeb5Syz155240 frentry_t *fr, **frptr; 708*ab25eeb5Syz155240 { 709*ab25eeb5Syz155240 frauthent_t *fae, **faep; 710*ab25eeb5Syz155240 int error = 0; 711*ab25eeb5Syz155240 SPL_INT(s); 712*ab25eeb5Syz155240 713*ab25eeb5Syz155240 if ((cmd != SIOCADAFR) && (cmd != SIOCRMAFR)) 714*ab25eeb5Syz155240 return EIO; 715*ab25eeb5Syz155240 716*ab25eeb5Syz155240 for (faep = &fae_list; ((fae = *faep) != NULL); ) { 717*ab25eeb5Syz155240 if (&fae->fae_fr == fr) 718*ab25eeb5Syz155240 break; 719*ab25eeb5Syz155240 else 720*ab25eeb5Syz155240 faep = &fae->fae_next; 721*ab25eeb5Syz155240 } 722*ab25eeb5Syz155240 723*ab25eeb5Syz155240 if (cmd == (ioctlcmd_t)SIOCRMAFR) { 724*ab25eeb5Syz155240 if (fr == NULL || frptr == NULL) 725*ab25eeb5Syz155240 error = EINVAL; 726*ab25eeb5Syz155240 else if (fae == NULL) 727*ab25eeb5Syz155240 error = ESRCH; 728*ab25eeb5Syz155240 else { 729*ab25eeb5Syz155240 SPL_NET(s); 730*ab25eeb5Syz155240 WRITE_ENTER(&ipf_auth); 731*ab25eeb5Syz155240 *faep = fae->fae_next; 732*ab25eeb5Syz155240 if (ipauth == &fae->fae_fr) 733*ab25eeb5Syz155240 ipauth = fae_list ? &fae_list->fae_fr : NULL; 734*ab25eeb5Syz155240 RWLOCK_EXIT(&ipf_auth); 735*ab25eeb5Syz155240 SPL_X(s); 736*ab25eeb5Syz155240 737*ab25eeb5Syz155240 KFREE(fae); 738*ab25eeb5Syz155240 } 739*ab25eeb5Syz155240 } else if (fr != NULL && frptr != NULL) { 740*ab25eeb5Syz155240 KMALLOC(fae, frauthent_t *); 741*ab25eeb5Syz155240 if (fae != NULL) { 742*ab25eeb5Syz155240 bcopy((char *)fr, (char *)&fae->fae_fr, 743*ab25eeb5Syz155240 sizeof(*fr)); 744*ab25eeb5Syz155240 SPL_NET(s); 745*ab25eeb5Syz155240 WRITE_ENTER(&ipf_auth); 746*ab25eeb5Syz155240 fae->fae_age = fr_defaultauthage; 747*ab25eeb5Syz155240 fae->fae_fr.fr_hits = 0; 748*ab25eeb5Syz155240 fae->fae_fr.fr_next = *frptr; 749*ab25eeb5Syz155240 *frptr = &fae->fae_fr; 750*ab25eeb5Syz155240 fae->fae_next = *faep; 751*ab25eeb5Syz155240 *faep = fae; 752*ab25eeb5Syz155240 ipauth = &fae_list->fae_fr; 753*ab25eeb5Syz155240 RWLOCK_EXIT(&ipf_auth); 754*ab25eeb5Syz155240 SPL_X(s); 755*ab25eeb5Syz155240 } else 756*ab25eeb5Syz155240 error = ENOMEM; 757*ab25eeb5Syz155240 } else 758*ab25eeb5Syz155240 error = EINVAL; 759*ab25eeb5Syz155240 return error; 760*ab25eeb5Syz155240 } 761*ab25eeb5Syz155240 762*ab25eeb5Syz155240 763*ab25eeb5Syz155240 /* 764*ab25eeb5Syz155240 * Flush held packets. 765*ab25eeb5Syz155240 * Must already be properly SPL'ed and Locked on &ipf_auth. 766*ab25eeb5Syz155240 * 767*ab25eeb5Syz155240 */ 768*ab25eeb5Syz155240 int fr_authflush() 769*ab25eeb5Syz155240 { 770*ab25eeb5Syz155240 register int i, num_flushed; 771*ab25eeb5Syz155240 mb_t *m; 772*ab25eeb5Syz155240 773*ab25eeb5Syz155240 if (fr_auth_lock) 774*ab25eeb5Syz155240 return -1; 775*ab25eeb5Syz155240 776*ab25eeb5Syz155240 num_flushed = 0; 777*ab25eeb5Syz155240 778*ab25eeb5Syz155240 for (i = 0 ; i < fr_authsize; i++) { 779*ab25eeb5Syz155240 m = fr_authpkts[i]; 780*ab25eeb5Syz155240 if (m != NULL) { 781*ab25eeb5Syz155240 FREE_MB_T(m); 782*ab25eeb5Syz155240 fr_authpkts[i] = NULL; 783*ab25eeb5Syz155240 fr_auth[i].fra_index = -1; 784*ab25eeb5Syz155240 /* perhaps add & use a flush counter inst.*/ 785*ab25eeb5Syz155240 fr_authstats.fas_expire++; 786*ab25eeb5Syz155240 fr_authused--; 787*ab25eeb5Syz155240 num_flushed++; 788*ab25eeb5Syz155240 } 789*ab25eeb5Syz155240 } 790*ab25eeb5Syz155240 791*ab25eeb5Syz155240 fr_authstart = 0; 792*ab25eeb5Syz155240 fr_authend = 0; 793*ab25eeb5Syz155240 fr_authnext = 0; 794*ab25eeb5Syz155240 795*ab25eeb5Syz155240 return num_flushed; 796*ab25eeb5Syz155240 } 797