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