ip_auth.c revision 153876
1/* $FreeBSD: head/sys/contrib/ipfilter/netinet/ip_auth.c 153876 2005-12-30 11:32:23Z guido $ */ 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 (defined(_BSDI_VERSION) && _BSDI_VERSION >= 199802) || \ 56 (__FreeBSD_version >= 400000) 57# include <sys/queue.h> 58#endif 59#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(bsdi) 60# include <machine/cpu.h> 61#endif 62#if defined(_KERNEL) && defined(__NetBSD__) && (__NetBSD_Version__ >= 104000000) 63# include <sys/proc.h> 64#endif 65#include <net/if.h> 66#ifdef sun 67# include <net/af.h> 68#endif 69#include <net/route.h> 70#include <netinet/in.h> 71#include <netinet/in_systm.h> 72#include <netinet/ip.h> 73#if !defined(_KERNEL) && !defined(__osf__) && !defined(__sgi) 74# define KERNEL 75# define _KERNEL 76# define NOT_KERNEL 77#endif 78#if !defined(linux) 79# include <netinet/ip_var.h> 80#endif 81#ifdef NOT_KERNEL 82# undef _KERNEL 83# undef KERNEL 84#endif 85#include <netinet/tcp.h> 86#if defined(IRIX) && (IRIX < 60516) /* IRIX < 6 */ 87extern struct ifqueue ipintrq; /* ip packet input queue */ 88#else 89# if !defined(__hpux) && !defined(linux) 90# if __FreeBSD_version >= 300000 91# include <net/if_var.h> 92# if __FreeBSD_version >= 500042 93# define IF_QFULL _IF_QFULL 94# define IF_DROP _IF_DROP 95# endif /* __FreeBSD_version >= 500042 */ 96# endif 97# include <netinet/in_var.h> 98# include <netinet/tcp_fsm.h> 99# endif 100#endif 101#include <netinet/udp.h> 102#include <netinet/ip_icmp.h> 103#include "netinet/ip_compat.h" 104#include <netinet/tcpip.h> 105#include "netinet/ip_fil.h" 106#include "netinet/ip_auth.h" 107#if !defined(MENTAT) && !defined(linux) 108# include <net/netisr.h> 109# ifdef __FreeBSD__ 110# include <machine/cpufunc.h> 111# endif 112#endif 113#if (__FreeBSD_version >= 300000) 114# include <sys/malloc.h> 115# if defined(_KERNEL) && !defined(IPFILTER_LKM) 116# include <sys/libkern.h> 117# include <sys/systm.h> 118# endif 119#endif 120/* END OF INCLUDES */ 121 122#if !defined(lint) 123static const char rcsid[] = "@(#)$FreeBSD: head/sys/contrib/ipfilter/netinet/ip_auth.c 153876 2005-12-30 11:32:23Z guido $"; 124/* static const char rcsid[] = "@(#)Id: ip_auth.c,v 2.73.2.3 2004/08/26 11:25:21 darrenr Exp"; */ 125#endif 126 127 128#if SOLARIS 129extern kcondvar_t ipfauthwait; 130#endif /* SOLARIS */ 131#if defined(linux) && defined(_KERNEL) 132wait_queue_head_t fr_authnext_linux; 133#endif 134 135int fr_authsize = FR_NUMAUTH; 136int fr_authused = 0; 137int fr_defaultauthage = 600; 138int fr_auth_lock = 0; 139int fr_auth_init = 0; 140fr_authstat_t fr_authstats; 141static frauth_t *fr_auth = NULL; 142mb_t **fr_authpkts = NULL; 143int fr_authstart = 0, fr_authend = 0, fr_authnext = 0; 144frauthent_t *fae_list = NULL; 145frentry_t *ipauth = NULL, 146 *fr_authlist = NULL; 147 148 149int fr_authinit() 150{ 151 KMALLOCS(fr_auth, frauth_t *, fr_authsize * sizeof(*fr_auth)); 152 if (fr_auth != NULL) 153 bzero((char *)fr_auth, fr_authsize * sizeof(*fr_auth)); 154 else 155 return -1; 156 157 KMALLOCS(fr_authpkts, mb_t **, fr_authsize * sizeof(*fr_authpkts)); 158 if (fr_authpkts != NULL) 159 bzero((char *)fr_authpkts, fr_authsize * sizeof(*fr_authpkts)); 160 else 161 return -2; 162 163 MUTEX_INIT(&ipf_authmx, "ipf auth log mutex"); 164 RWLOCK_INIT(&ipf_auth, "ipf IP User-Auth rwlock"); 165#if SOLARIS && defined(_KERNEL) 166 cv_init(&ipfauthwait, "ipf auth condvar", CV_DRIVER, NULL); 167#endif 168#if defined(linux) && defined(_KERNEL) 169 init_waitqueue_head(&fr_authnext_linux); 170#endif 171 172 fr_auth_init = 1; 173 174 return 0; 175} 176 177 178/* 179 * Check if a packet has authorization. If the packet is found to match an 180 * authorization result and that would result in a feedback loop (i.e. it 181 * will end up returning FR_AUTH) then return FR_BLOCK instead. 182 */ 183frentry_t *fr_checkauth(fin, passp) 184fr_info_t *fin; 185u_32_t *passp; 186{ 187 frentry_t *fr; 188 frauth_t *fra; 189 u_32_t pass; 190 u_short id; 191 ip_t *ip; 192 int i; 193 194 if (fr_auth_lock || !fr_authused) 195 return NULL; 196 197 ip = fin->fin_ip; 198 id = ip->ip_id; 199 200 READ_ENTER(&ipf_auth); 201 for (i = fr_authstart; i != fr_authend; ) { 202 /* 203 * index becomes -2 only after an SIOCAUTHW. Check this in 204 * case the same packet gets sent again and it hasn't yet been 205 * auth'd. 206 */ 207 fra = fr_auth + i; 208 if ((fra->fra_index == -2) && (id == fra->fra_info.fin_id) && 209 !bcmp((char *)fin, (char *)&fra->fra_info, FI_CSIZE)) { 210 /* 211 * Avoid feedback loop. 212 */ 213 if (!(pass = fra->fra_pass) || (FR_ISAUTH(pass))) 214 pass = FR_BLOCK; 215 /* 216 * Create a dummy rule for the stateful checking to 217 * use and return. Zero out any values we don't 218 * trust from userland! 219 */ 220 if ((pass & FR_KEEPSTATE) || ((pass & FR_KEEPFRAG) && 221 (fin->fin_flx & FI_FRAG))) { 222 KMALLOC(fr, frentry_t *); 223 if (fr) { 224 bcopy((char *)fra->fra_info.fin_fr, 225 (char *)fr, sizeof(*fr)); 226 fr->fr_grp = NULL; 227 fr->fr_ifa = fin->fin_ifp; 228 fr->fr_func = NULL; 229 fr->fr_ref = 1; 230 fr->fr_flags = pass; 231 fr->fr_ifas[1] = NULL; 232 fr->fr_ifas[2] = NULL; 233 fr->fr_ifas[3] = NULL; 234 } 235 } else 236 fr = fra->fra_info.fin_fr; 237 fin->fin_fr = fr; 238 RWLOCK_EXIT(&ipf_auth); 239 WRITE_ENTER(&ipf_auth); 240 if ((fr != NULL) && (fr != fra->fra_info.fin_fr)) { 241 fr->fr_next = fr_authlist; 242 fr_authlist = fr; 243 } 244 fr_authstats.fas_hits++; 245 fra->fra_index = -1; 246 fr_authused--; 247 if (i == fr_authstart) { 248 while (fra->fra_index == -1) { 249 i++; 250 fra++; 251 if (i == fr_authsize) { 252 i = 0; 253 fra = fr_auth; 254 } 255 fr_authstart = i; 256 if (i == fr_authend) 257 break; 258 } 259 if (fr_authstart == fr_authend) { 260 fr_authnext = 0; 261 fr_authstart = fr_authend = 0; 262 } 263 } 264 RWLOCK_EXIT(&ipf_auth); 265 if (passp != NULL) 266 *passp = pass; 267 ATOMIC_INC64(fr_authstats.fas_hits); 268 return fr; 269 } 270 i++; 271 if (i == fr_authsize) 272 i = 0; 273 } 274 fr_authstats.fas_miss++; 275 RWLOCK_EXIT(&ipf_auth); 276 ATOMIC_INC64(fr_authstats.fas_miss); 277 return NULL; 278} 279 280 281/* 282 * Check if we have room in the auth array to hold details for another packet. 283 * If we do, store it and wake up any user programs which are waiting to 284 * hear about these events. 285 */ 286int fr_newauth(m, fin) 287mb_t *m; 288fr_info_t *fin; 289{ 290#if defined(_KERNEL) && defined(MENTAT) 291 qpktinfo_t *qpi = fin->fin_qpi; 292#endif 293 frauth_t *fra; 294#if !defined(sparc) && !defined(m68k) 295 ip_t *ip; 296#endif 297 int i; 298 299 if (fr_auth_lock) 300 return 0; 301 302 WRITE_ENTER(&ipf_auth); 303 if (fr_authstart > fr_authend) { 304 fr_authstats.fas_nospace++; 305 RWLOCK_EXIT(&ipf_auth); 306 return 0; 307 } else { 308 if (fr_authused == fr_authsize) { 309 fr_authstats.fas_nospace++; 310 RWLOCK_EXIT(&ipf_auth); 311 return 0; 312 } 313 } 314 315 fr_authstats.fas_added++; 316 fr_authused++; 317 i = fr_authend++; 318 if (fr_authend == fr_authsize) 319 fr_authend = 0; 320 RWLOCK_EXIT(&ipf_auth); 321 322 fra = fr_auth + i; 323 fra->fra_index = i; 324 fra->fra_pass = 0; 325 fra->fra_age = fr_defaultauthage; 326 bcopy((char *)fin, (char *)&fra->fra_info, sizeof(*fin)); 327#if !defined(sparc) && !defined(m68k) 328 /* 329 * No need to copyback here as we want to undo the changes, not keep 330 * them. 331 */ 332 ip = fin->fin_ip; 333# if defined(MENTAT) && defined(_KERNEL) 334 if ((ip == (ip_t *)m->b_rptr) && (fin->fin_v == 4)) 335# endif 336 { 337 register u_short bo; 338 339 bo = ip->ip_len; 340 ip->ip_len = htons(bo); 341 bo = ip->ip_off; 342 ip->ip_off = htons(bo); 343 } 344#endif 345#if SOLARIS && defined(_KERNEL) 346 m->b_rptr -= qpi->qpi_off; 347 fr_authpkts[i] = *(mblk_t **)fin->fin_mp; 348 fra->fra_q = qpi->qpi_q; /* The queue can disappear! */ 349 cv_signal(&ipfauthwait); 350#else 351# if defined(BSD) && !defined(sparc) && (BSD >= 199306) 352 if (!fin->fin_out) { 353 ip->ip_len = htons(ip->ip_len); 354 ip->ip_off = htons(ip->ip_off); 355 } 356# endif 357 fr_authpkts[i] = m; 358 WAKEUP(&fr_authnext,0); 359#endif 360 return 1; 361} 362 363 364int fr_auth_ioctl(data, cmd, mode) 365caddr_t data; 366ioctlcmd_t cmd; 367int mode; 368{ 369 mb_t *m; 370#if defined(_KERNEL) && !defined(MENTAT) && !defined(linux) && \ 371 (!defined(__FreeBSD_version) || (__FreeBSD_version < 501000)) 372 struct ifqueue *ifq; 373 SPL_INT(s); 374#endif 375 frauth_t auth, *au = &auth, *fra; 376 int i, error = 0, len; 377 char *t; 378 379 switch (cmd) 380 { 381 case SIOCSTLCK : 382 if (!(mode & FWRITE)) { 383 error = EPERM; 384 break; 385 } 386 fr_lock(data, &fr_auth_lock); 387 break; 388 389 case SIOCATHST: 390 fr_authstats.fas_faelist = fae_list; 391 error = fr_outobj(data, &fr_authstats, IPFOBJ_AUTHSTAT); 392 break; 393 394 case SIOCIPFFL: 395 SPL_NET(s); 396 WRITE_ENTER(&ipf_auth); 397 i = fr_authflush(); 398 RWLOCK_EXIT(&ipf_auth); 399 SPL_X(s); 400 error = copyoutptr((char *)&i, data, sizeof(i)); 401 break; 402 403 case SIOCAUTHW: 404fr_authioctlloop: 405 error = fr_inobj(data, au, IPFOBJ_FRAUTH); 406 READ_ENTER(&ipf_auth); 407 if ((fr_authnext != fr_authend) && fr_authpkts[fr_authnext]) { 408 error = fr_outobj(data, &fr_auth[fr_authnext], 409 IPFOBJ_FRAUTH); 410 if (auth.fra_len != 0 && auth.fra_buf != NULL) { 411 /* 412 * Copy packet contents out to user space if 413 * requested. Bail on an error. 414 */ 415 m = fr_authpkts[fr_authnext]; 416 len = MSGDSIZE(m); 417 if (len > auth.fra_len) 418 len = auth.fra_len; 419 auth.fra_len = len; 420 for (t = auth.fra_buf; m && (len > 0); ) { 421 i = MIN(M_LEN(m), len); 422 error = copyoutptr(MTOD(m, char *), 423 t, i); 424 len -= i; 425 t += i; 426 if (error != 0) 427 break; 428 } 429 } 430 RWLOCK_EXIT(&ipf_auth); 431 if (error != 0) 432 break; 433 SPL_NET(s); 434 WRITE_ENTER(&ipf_auth); 435 fr_authnext++; 436 if (fr_authnext == fr_authsize) 437 fr_authnext = 0; 438 RWLOCK_EXIT(&ipf_auth); 439 SPL_X(s); 440 return 0; 441 } 442 RWLOCK_EXIT(&ipf_auth); 443 /* 444 * We exit ipf_global here because a program that enters in 445 * here will have a lock on it and goto sleep having this lock. 446 * If someone were to do an 'ipf -D' the system would then 447 * deadlock. The catch with releasing it here is that the 448 * caller of this function expects it to be held when we 449 * return so we have to reacquire it in here. 450 */ 451 RWLOCK_EXIT(&ipf_global); 452 453 MUTEX_ENTER(&ipf_authmx); 454#ifdef _KERNEL 455# if SOLARIS 456 error = 0; 457 if (!cv_wait_sig(&ipfauthwait, &ipf_authmx.ipf_lk)) 458 error = EINTR; 459# else /* SOLARIS */ 460# ifdef __hpux 461 { 462 lock_t *l; 463 464 l = get_sleep_lock(&fr_authnext); 465 error = sleep(&fr_authnext, PZERO+1); 466 spinunlock(l); 467 } 468# else 469# ifdef __osf__ 470 error = mpsleep(&fr_authnext, PSUSP|PCATCH, "fr_authnext", 0, 471 &ipf_authmx, MS_LOCK_SIMPLE); 472# else 473 error = SLEEP(&fr_authnext, "fr_authnext"); 474# endif /* __osf__ */ 475# endif /* __hpux */ 476# endif /* SOLARIS */ 477#endif 478 MUTEX_EXIT(&ipf_authmx); 479 READ_ENTER(&ipf_global); 480 if (error == 0) { 481 READ_ENTER(&ipf_auth); 482 goto fr_authioctlloop; 483 } 484 break; 485 486 case SIOCAUTHR: 487 error = fr_inobj(data, &auth, IPFOBJ_FRAUTH); 488 if (error != 0) 489 return error; 490 SPL_NET(s); 491 WRITE_ENTER(&ipf_auth); 492 i = au->fra_index; 493 fra = fr_auth + i; 494 if ((i < 0) || (i >= fr_authsize) || 495 (fra->fra_info.fin_id != au->fra_info.fin_id)) { 496 RWLOCK_EXIT(&ipf_auth); 497 SPL_X(s); 498 return ESRCH; 499 } 500 m = fr_authpkts[i]; 501 fra->fra_index = -2; 502 fra->fra_pass = au->fra_pass; 503 fr_authpkts[i] = NULL; 504 RWLOCK_EXIT(&ipf_auth); 505#ifdef _KERNEL 506 if ((m != NULL) && (au->fra_info.fin_out != 0)) { 507# ifdef MENTAT 508 error = !putq(fra->fra_q, m); 509# else /* MENTAT */ 510# if defined(linux) || defined(AIX) 511# else 512# if (defined(_BSDI_VERSION) && _BSDI_VERSION >= 199802) || \ 513 (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# if defined(linux) || defined(AIX) 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 SPL_INT(s); 668 669 if (fr_auth_lock) 670 return; 671 672 SPL_NET(s); 673 WRITE_ENTER(&ipf_auth); 674 for (i = 0, fra = fr_auth; i < fr_authsize; i++, fra++) { 675 fra->fra_age--; 676 if ((fra->fra_age == 0) && (m = fr_authpkts[i])) { 677 FREE_MB_T(m); 678 fr_authpkts[i] = NULL; 679 fr_auth[i].fra_index = -1; 680 fr_authstats.fas_expire++; 681 fr_authused--; 682 } 683 } 684 685 for (faep = &fae_list; ((fae = *faep) != NULL); ) { 686 fae->fae_age--; 687 if (fae->fae_age == 0) { 688 *faep = fae->fae_next; 689 KFREE(fae); 690 fr_authstats.fas_expire++; 691 } else 692 faep = &fae->fae_next; 693 } 694 if (fae_list != NULL) 695 ipauth = &fae_list->fae_fr; 696 else 697 ipauth = NULL; 698 699 for (frp = &fr_authlist; ((fr = *frp) != NULL); ) { 700 if (fr->fr_ref == 1) { 701 *frp = fr->fr_next; 702 KFREE(fr); 703 } else 704 frp = &fr->fr_next; 705 } 706 RWLOCK_EXIT(&ipf_auth); 707 SPL_X(s); 708} 709 710int fr_preauthcmd(cmd, fr, frptr) 711ioctlcmd_t cmd; 712frentry_t *fr, **frptr; 713{ 714 frauthent_t *fae, **faep; 715 int error = 0; 716 SPL_INT(s); 717 718 if ((cmd != SIOCADAFR) && (cmd != SIOCRMAFR)) 719 return EIO; 720 721 for (faep = &fae_list; ((fae = *faep) != NULL); ) { 722 if (&fae->fae_fr == fr) 723 break; 724 else 725 faep = &fae->fae_next; 726 } 727 728 if (cmd == (ioctlcmd_t)SIOCRMAFR) { 729 if (fr == NULL || frptr == NULL) 730 error = EINVAL; 731 else if (fae == NULL) 732 error = ESRCH; 733 else { 734 SPL_NET(s); 735 WRITE_ENTER(&ipf_auth); 736 *faep = fae->fae_next; 737 if (ipauth == &fae->fae_fr) 738 ipauth = fae_list ? &fae_list->fae_fr : NULL; 739 RWLOCK_EXIT(&ipf_auth); 740 SPL_X(s); 741 742 KFREE(fae); 743 } 744 } else if (fr != NULL && frptr != NULL) { 745 KMALLOC(fae, frauthent_t *); 746 if (fae != NULL) { 747 bcopy((char *)fr, (char *)&fae->fae_fr, 748 sizeof(*fr)); 749 SPL_NET(s); 750 WRITE_ENTER(&ipf_auth); 751 fae->fae_age = fr_defaultauthage; 752 fae->fae_fr.fr_hits = 0; 753 fae->fae_fr.fr_next = *frptr; 754 *frptr = &fae->fae_fr; 755 fae->fae_next = *faep; 756 *faep = fae; 757 ipauth = &fae_list->fae_fr; 758 RWLOCK_EXIT(&ipf_auth); 759 SPL_X(s); 760 } else 761 error = ENOMEM; 762 } else 763 error = EINVAL; 764 return error; 765} 766 767 768/* 769 * Flush held packets. 770 * Must already be properly SPL'ed and Locked on &ipf_auth. 771 * 772 */ 773int fr_authflush() 774{ 775 register int i, num_flushed; 776 mb_t *m; 777 778 if (fr_auth_lock) 779 return -1; 780 781 num_flushed = 0; 782 783 for (i = 0 ; i < fr_authsize; i++) { 784 m = fr_authpkts[i]; 785 if (m != NULL) { 786 FREE_MB_T(m); 787 fr_authpkts[i] = NULL; 788 fr_auth[i].fra_index = -1; 789 /* perhaps add & use a flush counter inst.*/ 790 fr_authstats.fas_expire++; 791 fr_authused--; 792 num_flushed++; 793 } 794 } 795 796 fr_authstart = 0; 797 fr_authend = 0; 798 fr_authnext = 0; 799 800 return num_flushed; 801} 802