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