4 * Copyright (C) 1998-2003 by Darren Reed & Guido van Rooij.
6 * See the IPFILTER.LICENCE file for details on licencing.
8 * Copyright 2008 Sun Microsystems, Inc.
10 #if defined(KERNEL) || defined(_KERNEL)
16 #include <sys/errno.h>
17 #include <sys/types.h>
18 #include <sys/param.h>
32 #if defined(_KERNEL) && (__FreeBSD_version >= 220000)
33 # include <sys/filio.h>
34 # include <sys/fcntl.h>
36 # include <sys/ioctl.h>
39 # include <sys/protosw.h>
41 #include <sys/socket.h>
43 # include <sys/systm.h>
44 # if !defined(__SVR4) && !defined(__svr4__) && !defined(linux)
45 # include <sys/mbuf.h>
48 #if defined(__SVR4) || defined(__svr4__)
49 # include <sys/filio.h>
50 # include <sys/byteorder.h>
52 # include <sys/dditypes.h>
54 # include <sys/stream.h>
55 # include <sys/kmem.h>
57 #if (defined(_BSDI_VERSION) && (_BSDI_VERSION >= 199802)) || \
58 (defined(__FreeBSD_version) &&(__FreeBSD_version >= 400000))
59 # include <sys/queue.h>
61 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(bsdi)
62 # include <machine/cpu.h>
64 #if defined(_KERNEL) && defined(__NetBSD__) && (__NetBSD_Version__ >= 104000000)
65 # include <sys/proc.h>
68 #include <net/route.h>
72 #include <netinet/in.h>
73 #include <netinet/in_systm.h>
74 #include <netinet/ip.h>
75 #if !defined(_KERNEL) && !defined(__osf__) && !defined(__sgi)
81 # include <netinet/ip_var.h>
87 #include <netinet/tcp.h>
88 #if defined(IRIX) && (IRIX < 60516) /* IRIX < 6 */
89 extern struct ifqueue ipintrq
; /* ip packet input queue */
91 # if !defined(__hpux) && !defined(linux)
92 # if __FreeBSD_version >= 300000
93 # include <net/if_var.h>
94 # if __FreeBSD_version >= 500042
95 # define IF_QFULL _IF_QFULL
96 # define IF_DROP _IF_DROP
97 # endif /* __FreeBSD_version >= 500042 */
99 # include <netinet/in_var.h>
100 # include <netinet/tcp_fsm.h>
103 #include <netinet/udp.h>
104 #include <netinet/ip_icmp.h>
105 #include "netinet/ip_compat.h"
106 #include <netinet/tcpip.h>
107 #include "netinet/ip_fil.h"
108 #include "netinet/ip_auth.h"
109 #if !defined(MENTAT) && !defined(linux)
110 # include <net/netisr.h>
112 # include <machine/cpufunc.h>
115 #if (__FreeBSD_version >= 300000)
116 # include <sys/malloc.h>
117 # if defined(_KERNEL) && !defined(IPFILTER_LKM)
118 # include <sys/libkern.h>
119 # include <sys/systm.h>
122 /* END OF INCLUDES */
125 #if defined(__NetBSD__)
126 #include <sys/cdefs.h>
127 __KERNEL_RCSID(0, "$NetBSD$");
129 static const char rcsid
[] = "@(#)Id: ip_auth.c,v 2.73.2.33 2009/05/13 18:31:14 darrenr Exp";
134 #if SOLARIS && defined(_KERNEL)
135 extern kcondvar_t ipfauthwait
;
136 extern struct pollhead iplpollhead
[IPL_LOGSIZE
];
138 #if defined(linux) && defined(_KERNEL)
139 wait_queue_head_t fr_authnext_linux
;
142 int fr_authsize
= FR_NUMAUTH
;
144 int fr_authreplies
= 0;
145 int fr_defaultauthage
= 600;
146 int fr_auth_lock
= 0;
147 int fr_auth_init
= 0;
148 fr_authstat_t fr_authstats
;
149 static frauth_t
*fr_auth
= NULL
;
150 mb_t
**fr_authpkts
= NULL
;
151 int fr_authstart
= 0, fr_authend
= 0, fr_authnext
= 0;
152 frauthent_t
*fae_list
= NULL
;
153 frentry_t
*ipauth
= NULL
,
156 void fr_authderef
__P((frauthent_t
**));
157 int fr_authgeniter
__P((ipftoken_t
*, ipfgeniter_t
*));
158 int fr_authreply
__P((char *));
159 int fr_authwait
__P((char *));
161 /* ------------------------------------------------------------------------ */
162 /* Function: fr_authinit */
163 /* Returns: int - 0 == success, else error */
164 /* Parameters: None */
166 /* Allocate memory and initialise data structures used in handling auth */
168 /* ------------------------------------------------------------------------ */
171 KMALLOCS(fr_auth
, frauth_t
*, fr_authsize
* sizeof(*fr_auth
));
173 bzero((char *)fr_auth
, fr_authsize
* sizeof(*fr_auth
));
177 KMALLOCS(fr_authpkts
, mb_t
**, fr_authsize
* sizeof(*fr_authpkts
));
178 if (fr_authpkts
!= NULL
)
179 bzero((char *)fr_authpkts
, fr_authsize
* sizeof(*fr_authpkts
));
183 MUTEX_INIT(&ipf_authmx
, "ipf auth log mutex");
184 RWLOCK_INIT(&ipf_auth
, "ipf IP User-Auth rwlock");
185 #if SOLARIS && defined(_KERNEL)
186 cv_init(&ipfauthwait
, "ipf auth condvar", CV_DRIVER
, NULL
);
188 #if defined(linux) && defined(_KERNEL)
189 init_waitqueue_head(&fr_authnext_linux
);
198 /* ------------------------------------------------------------------------ */
199 /* Function: fr_checkauth */
200 /* Returns: frentry_t* - pointer to ipf rule if match found, else NULL */
201 /* Parameters: fin(I) - pointer to ipftoken structure */
202 /* passp(I) - pointer to ipfgeniter structure */
204 /* Check if a packet has authorization. If the packet is found to match an */
205 /* authorization result and that would result in a feedback loop (i.e. it */
206 /* will end up returning FR_AUTH) then return FR_BLOCK instead. */
207 /* ------------------------------------------------------------------------ */
208 frentry_t
*fr_checkauth(fin
, passp
)
219 if (fr_auth_lock
|| !fr_authused
)
225 READ_ENTER(&ipf_auth
);
226 for (i
= fr_authstart
; i
!= fr_authend
; ) {
228 * index becomes -2 only after an SIOCAUTHW. Check this in
229 * case the same packet gets sent again and it hasn't yet been
233 if ((fra
->fra_index
== -2) && (id
== fra
->fra_info
.fin_id
) &&
234 !bcmp((char *)fin
, (char *)&fra
->fra_info
, FI_CSIZE
)) {
236 * Avoid feedback loop.
238 if (!(pass
= fra
->fra_pass
) || (FR_ISAUTH(pass
)))
241 * Create a dummy rule for the stateful checking to
242 * use and return. Zero out any values we don't
243 * trust from userland!
245 if ((pass
& FR_KEEPSTATE
) || ((pass
& FR_KEEPFRAG
) &&
246 (fin
->fin_flx
& FI_FRAG
))) {
247 KMALLOC(fr
, frentry_t
*);
249 bcopy((char *)fra
->fra_info
.fin_fr
,
250 (char *)fr
, sizeof(*fr
));
252 fr
->fr_ifa
= fin
->fin_ifp
;
256 fr
->fr_ifas
[1] = NULL
;
257 fr
->fr_ifas
[2] = NULL
;
258 fr
->fr_ifas
[3] = NULL
;
261 fr
= fra
->fra_info
.fin_fr
;
263 fin
->fin_flx
|= fra
->fra_flx
;
264 RWLOCK_EXIT(&ipf_auth
);
266 WRITE_ENTER(&ipf_auth
);
268 * fr_authlist is populated with the rules malloc'd
269 * above and only those.
271 if ((fr
!= NULL
) && (fr
!= fra
->fra_info
.fin_fr
)) {
272 fr
->fr_next
= fr_authlist
;
275 fr_authstats
.fas_hits
++;
279 if (i
== fr_authstart
) {
280 while (fra
->fra_index
== -1) {
283 if (i
== fr_authsize
) {
291 if (fr_authstart
== fr_authend
) {
297 RWLOCK_EXIT(&ipf_auth
);
300 ATOMIC_INC64(fr_authstats
.fas_hits
);
304 if (i
== fr_authsize
)
307 fr_authstats
.fas_miss
++;
308 RWLOCK_EXIT(&ipf_auth
);
309 ATOMIC_INC64(fr_authstats
.fas_miss
);
314 /* ------------------------------------------------------------------------ */
315 /* Function: fr_newauth */
316 /* Returns: int - 1 == success, 0 = did not put packet on auth queue */
317 /* Parameters: m(I) - pointer to mb_t with packet in it */
318 /* fin(I) - pointer to packet information */
320 /* Check if we have room in the auth array to hold details for another */
321 /* packet. If we do, store it and wake up any user programs which are */
322 /* waiting to hear about these events. */
323 /* ------------------------------------------------------------------------ */
324 int fr_newauth(m
, fin
)
328 #if defined(_KERNEL) && defined(MENTAT)
329 qpktinfo_t
*qpi
= fin
->fin_qpi
;
332 #if !defined(sparc) && !defined(m68k)
340 WRITE_ENTER(&ipf_auth
);
341 if (((fr_authend
+ 1) % fr_authsize
) == fr_authstart
) {
342 fr_authstats
.fas_nospace
++;
343 RWLOCK_EXIT(&ipf_auth
);
347 fr_authstats
.fas_added
++;
350 if (fr_authend
== fr_authsize
)
355 if (fin
->fin_fr
!= NULL
)
356 fra
->fra_pass
= fin
->fin_fr
->fr_flags
;
359 fra
->fra_age
= fr_defaultauthage
;
360 bcopy((char *)fin
, (char *)&fra
->fra_info
, sizeof(*fin
));
361 fra
->fra_flx
= fra
->fra_info
.fin_flx
& (FI_STATE
|FI_NATED
);
362 fra
->fra_info
.fin_flx
&= ~(FI_STATE
|FI_NATED
);
363 #if !defined(sparc) && !defined(m68k)
365 * No need to copyback here as we want to undo the changes, not keep
369 # if defined(MENTAT) && defined(_KERNEL)
370 if ((ip
== (ip_t
*)m
->b_rptr
) && (fin
->fin_v
== 4))
376 ip
->ip_len
= htons(bo
);
378 ip
->ip_off
= htons(bo
);
381 #if SOLARIS && defined(_KERNEL)
382 COPYIFNAME(fin
->fin_v
, fin
->fin_ifp
, fra
->fra_info
.fin_ifname
);
383 m
->b_rptr
-= qpi
->qpi_off
;
384 # if !defined(_INET_IP_STACK_H)
385 fra
->fra_q
= qpi
->qpi_q
; /* The queue can disappear! */
387 fra
->fra_m
= *fin
->fin_mp
;
388 fra
->fra_info
.fin_mp
= &fra
->fra_m
;
389 fr_authpkts
[i
] = fra
->fra_m
;
390 RWLOCK_EXIT(&ipf_auth
);
391 cv_signal(&ipfauthwait
);
392 pollwakeup(&iplpollhead
[IPL_LOGAUTH
], POLLIN
|POLLRDNORM
);
395 RWLOCK_EXIT(&ipf_auth
);
396 WAKEUP(&fr_authnext
, 0);
402 /* ------------------------------------------------------------------------ */
403 /* Function: fr_auth_ioctl */
404 /* Returns: int - 0 == success, else error */
405 /* Parameters: data(IO) - pointer to ioctl data */
406 /* cmd(I) - ioctl command */
407 /* mode(I) - mode flags associated with open descriptor */
408 /* uid(I) - uid associatd with application making the call */
409 /* ctx(I) - pointer for context */
411 /* This function handles all of the ioctls recognised by the auth component */
412 /* in IPFilter - ie ioctls called on an open fd for /dev/ipauth */
413 /* ------------------------------------------------------------------------ */
414 int fr_auth_ioctl(data
, cmd
, mode
, uid
, ctx
)
430 error
= fr_inobj(data
, &iter
, IPFOBJ_GENITER
);
435 token
= ipf_findtoken(IPFGENITER_AUTH
, uid
, ctx
);
437 error
= fr_authgeniter(token
, &iter
);
438 WRITE_ENTER(&ipf_tokens
);
439 if (token
->ipt_data
== NULL
)
440 ipf_freetoken(token
);
442 ipf_dereftoken(token
);
443 RWLOCK_EXIT(&ipf_tokens
);
454 if (!(mode
& FWRITE
))
457 error
= frrequest(IPL_LOGAUTH
, cmd
, data
,
462 if (!(mode
& FWRITE
)) {
466 error
= fr_lock(data
, &fr_auth_lock
);
470 fr_authstats
.fas_faelist
= fae_list
;
471 error
= fr_outobj(data
, &fr_authstats
, IPFOBJ_AUTHSTAT
);
476 WRITE_ENTER(&ipf_auth
);
478 RWLOCK_EXIT(&ipf_auth
);
480 BCOPYOUT((char *)&i
, data
, sizeof(i
));
484 error
= fr_authwait(data
);
488 error
= fr_authreply(data
);
499 /* ------------------------------------------------------------------------ */
500 /* Function: fr_authunload */
502 /* Parameters: None */
504 /* Free all network buffer memory used to keep saved packets. */
505 /* ------------------------------------------------------------------------ */
509 register frauthent_t
*fae
, **faep
;
510 frentry_t
*fr
, **frp
;
513 if (fr_auth
!= NULL
) {
514 KFREES(fr_auth
, fr_authsize
* sizeof(*fr_auth
));
518 if (fr_authpkts
!= NULL
) {
519 for (i
= 0; i
< fr_authsize
; i
++) {
523 fr_authpkts
[i
] = NULL
;
526 KFREES(fr_authpkts
, fr_authsize
* sizeof(*fr_authpkts
));
531 while ((fae
= *faep
) != NULL
) {
532 *faep
= fae
->fae_next
;
537 if (fr_authlist
!= NULL
) {
538 for (frp
= &fr_authlist
; ((fr
= *frp
) != NULL
); ) {
539 if (fr
->fr_ref
== 1) {
547 if (fr_auth_init
== 1) {
548 # if SOLARIS && defined(_KERNEL)
549 cv_destroy(&ipfauthwait
);
551 MUTEX_DESTROY(&ipf_authmx
);
552 RW_DESTROY(&ipf_auth
);
559 /* ------------------------------------------------------------------------ */
560 /* Function: fr_authexpire */
562 /* Parameters: None */
564 /* Slowly expire held auth records. Timeouts are set in expectation of */
565 /* this being called twice per second. */
566 /* ------------------------------------------------------------------------ */
569 frauthent_t
*fae
, **faep
;
570 frentry_t
*fr
, **frp
;
580 WRITE_ENTER(&ipf_auth
);
581 for (i
= 0, fra
= fr_auth
; i
< fr_authsize
; i
++, fra
++) {
583 if ((fra
->fra_age
== 0) && (fr_auth
[i
].fra_index
!= -1)) {
584 if ((m
= fr_authpkts
[i
]) != NULL
) {
586 fr_authpkts
[i
] = NULL
;
587 } else if (fr_auth
[i
].fra_index
== -2) {
591 fr_auth
[i
].fra_index
= -1;
592 fr_authstats
.fas_expire
++;
598 * Expire pre-auth rules
600 for (faep
= &fae_list
; ((fae
= *faep
) != NULL
); ) {
602 if (fae
->fae_age
== 0) {
604 fr_authstats
.fas_expire
++;
606 faep
= &fae
->fae_next
;
608 if (fae_list
!= NULL
)
609 ipauth
= &fae_list
->fae_fr
;
613 for (frp
= &fr_authlist
; ((fr
= *frp
) != NULL
); ) {
614 if (fr
->fr_ref
== 1) {
620 RWLOCK_EXIT(&ipf_auth
);
625 /* ------------------------------------------------------------------------ */
626 /* Function: fr_preauthcmd */
627 /* Returns: int - 0 == success, else error */
628 /* Parameters: cmd(I) - ioctl command for rule */
629 /* fr(I) - pointer to ipf rule */
630 /* fptr(I) - pointer to caller's 'fr' */
632 /* ------------------------------------------------------------------------ */
633 int fr_preauthcmd(cmd
, fr
, frptr
)
635 frentry_t
*fr
, **frptr
;
637 frauthent_t
*fae
, **faep
;
641 if ((cmd
!= SIOCADAFR
) && (cmd
!= SIOCRMAFR
))
644 for (faep
= &fae_list
; ((fae
= *faep
) != NULL
); ) {
645 if (&fae
->fae_fr
== fr
)
648 faep
= &fae
->fae_next
;
651 if (cmd
== (ioctlcmd_t
)SIOCRMAFR
) {
652 if (fr
== NULL
|| frptr
== NULL
)
654 else if (fae
== NULL
)
658 WRITE_ENTER(&ipf_auth
);
659 *faep
= fae
->fae_next
;
660 if (ipauth
== &fae
->fae_fr
)
661 ipauth
= fae_list
? &fae_list
->fae_fr
: NULL
;
662 RWLOCK_EXIT(&ipf_auth
);
667 } else if (fr
!= NULL
&& frptr
!= NULL
) {
668 KMALLOC(fae
, frauthent_t
*);
670 bcopy((char *)fr
, (char *)&fae
->fae_fr
,
673 WRITE_ENTER(&ipf_auth
);
674 fae
->fae_age
= fr_defaultauthage
;
675 fae
->fae_fr
.fr_hits
= 0;
676 fae
->fae_fr
.fr_next
= *frptr
;
678 *frptr
= &fae
->fae_fr
;
679 fae
->fae_next
= *faep
;
681 ipauth
= &fae_list
->fae_fr
;
682 RWLOCK_EXIT(&ipf_auth
);
692 /* ------------------------------------------------------------------------ */
693 /* Function: fr_authflush */
694 /* Returns: int - number of auth entries flushed */
695 /* Parameters: None */
696 /* Locks: WRITE(ipf_auth) */
698 /* This function flushs the fr_authpkts array of any packet data with */
699 /* references still there. */
700 /* It is expected that the caller has already acquired the correct locks or */
701 /* set the priority level correctly for this to block out other code paths */
702 /* into these data structures. */
703 /* ------------------------------------------------------------------------ */
706 register int i
, num_flushed
;
714 for (i
= 0 ; i
< fr_authsize
; i
++) {
715 if (fr_auth
[i
].fra_index
!= -1) {
719 fr_authpkts
[i
] = NULL
;
722 fr_auth
[i
].fra_index
= -1;
723 /* perhaps add & use a flush counter inst.*/
724 fr_authstats
.fas_expire
++;
739 /* ------------------------------------------------------------------------ */
740 /* Function: fr_auth_waiting */
741 /* Returns: int - 0 = no pakcets wiating, 1 = packets waiting. */
742 /* Parameters: None */
744 /* Simple truth check to see if there are any packets waiting in the auth */
746 /* ------------------------------------------------------------------------ */
747 int fr_auth_waiting()
749 return (fr_authused
!= 0);
753 /* ------------------------------------------------------------------------ */
754 /* Function: fr_authgeniter */
755 /* Returns: int - 0 == success, else error */
756 /* Parameters: token(I) - pointer to ipftoken structure */
757 /* itp(I) - pointer to ipfgeniter structure */
759 /* ------------------------------------------------------------------------ */
760 int fr_authgeniter(token
, itp
)
764 frauthent_t
*fae
, *next
, zero
;
767 if (itp
->igi_data
== NULL
)
770 if (itp
->igi_type
!= IPFGENITER_AUTH
)
773 READ_ENTER(&ipf_auth
);
776 * Retrieve "previous" entry from token and find the next entry.
778 fae
= token
->ipt_data
;
782 next
= fae
->fae_next
;
786 * If we found an entry, add reference to it and update token.
787 * Otherwise, zero out data to be returned and NULL out token.
790 ATOMIC_INC(next
->fae_ref
);
791 token
->ipt_data
= next
;
793 bzero(&zero
, sizeof(zero
));
795 token
->ipt_data
= NULL
;
799 * Safe to release the lock now that we have a reference.
801 RWLOCK_EXIT(&ipf_auth
);
804 * Copy out the data and clean up references and token as needed.
806 error
= COPYOUT(next
, itp
->igi_data
, sizeof(*next
));
811 * Clean up reference and token.
813 if (token
->ipt_data
!= NULL
) {
815 WRITE_ENTER(&ipf_auth
);
817 RWLOCK_EXIT(&ipf_auth
);
819 if (next
->fae_next
== NULL
)
820 token
->ipt_data
= NULL
;
826 /* ------------------------------------------------------------------------ */
827 /* Function: fr_authderef */
829 /* Parameters: faep(IO) - pointer to caller's frauthent_t pointer */
830 /* Locks: WRITE(ipf_auth) */
832 /* This function unconditionally sets the pointer in the caller to NULL, */
833 /* to make it clear that it should no longer use that pointer, and drops */
834 /* the reference count on the structure by 1. If it reaches 0, free it up. */
835 /* ------------------------------------------------------------------------ */
836 void fr_authderef(faep
)
845 if (fae
->fae_ref
== 0) {
851 /* ------------------------------------------------------------------------ */
852 /* Function: fr_authwait */
853 /* Returns: int - 0 == success, else error */
854 /* Parameters: data(I) - pointer to data from ioctl call */
856 /* This function is called when an application is waiting for a packet to */
857 /* match an "auth" rule by issuing an SIOCAUTHW ioctl. If there is already */
858 /* a packet waiting on the queue then we will return that _one_ immediately.*/
859 /* If there are no packets present in the queue (fr_authpkts) then we go to */
861 /* ------------------------------------------------------------------------ */
862 int fr_authwait(data
)
865 frauth_t auth
, *au
= &auth
;
872 error
= fr_inobj(data
, au
, IPFOBJ_FRAUTH
);
877 * XXX Locks are held below over calls to copyout...a better
878 * solution needs to be found so this isn't necessary. The situation
879 * we are trying to guard against here is an error in the copyout
880 * steps should not cause the packet to "disappear" from the queue.
883 READ_ENTER(&ipf_auth
);
886 * If fr_authnext is not equal to fr_authend it will be because there
887 * is a packet waiting to be delt with in the fr_authpkts array. We
888 * copy as much of that out to user space as requested.
890 if (fr_authused
> fr_authreplies
) {
891 while (fr_authpkts
[fr_authnext
] == NULL
) {
893 if (fr_authnext
== fr_authsize
)
897 error
= fr_outobj(data
, &fr_auth
[fr_authnext
], IPFOBJ_FRAUTH
);
899 RWLOCK_EXIT(&ipf_auth
);
904 if (auth
.fra_len
!= 0 && auth
.fra_buf
!= NULL
) {
906 * Copy packet contents out to user space if
907 * requested. Bail on an error.
909 m
= fr_authpkts
[fr_authnext
];
911 if (len
> auth
.fra_len
)
915 for (t
= auth
.fra_buf
; m
&& (len
> 0); ) {
916 i
= MIN(M_LEN(m
), len
);
917 error
= copyoutptr(MTOD(m
, char *), &t
, i
);
921 RWLOCK_EXIT(&ipf_auth
);
928 RWLOCK_EXIT(&ipf_auth
);
931 WRITE_ENTER(&ipf_auth
);
933 if (fr_authnext
== fr_authsize
)
935 RWLOCK_EXIT(&ipf_auth
);
940 RWLOCK_EXIT(&ipf_auth
);
943 MUTEX_ENTER(&ipf_authmx
);
947 if (!cv_wait_sig(&ipfauthwait
, &ipf_authmx
.ipf_lk
))
954 l
= get_sleep_lock(&fr_authnext
);
955 error
= sleep(&fr_authnext
, PZERO
+1);
960 error
= mpsleep(&fr_authnext
, PSUSP
|PCATCH
, "fr_authnext", 0,
961 &ipf_authmx
, MS_LOCK_SIMPLE
);
963 error
= SLEEP(&fr_authnext
, "fr_authnext");
964 # endif /* __osf__ */
966 # endif /* SOLARIS */
968 MUTEX_EXIT(&ipf_authmx
);
970 goto fr_authioctlloop
;
975 /* ------------------------------------------------------------------------ */
976 /* Function: fr_authreply */
977 /* Returns: int - 0 == success, else error */
978 /* Parameters: data(I) - pointer to data from ioctl call */
980 /* This function is called by an application when it wants to return a */
981 /* decision on a packet using the SIOCAUTHR ioctl. This is after it has */
982 /* received information using an SIOCAUTHW. The decision returned in the */
983 /* form of flags, the same as those used in each rule. */
984 /* ------------------------------------------------------------------------ */
985 int fr_authreply(data
)
988 frauth_t auth
, *au
= &auth
, *fra
;
994 error
= fr_inobj(data
, &auth
, IPFOBJ_FRAUTH
);
999 WRITE_ENTER(&ipf_auth
);
1006 * Check the validity of the information being returned with two simple
1007 * checks. First, the auth index value should be within the size of
1008 * the array and second the packet id being returned should also match.
1010 if ((i
< 0) || (i
>= fr_authsize
) ||
1011 (fra
->fra_info
.fin_id
!= au
->fra_info
.fin_id
)) {
1012 RWLOCK_EXIT(&ipf_auth
);
1018 fra
->fra_index
= -2;
1019 fra
->fra_pass
= au
->fra_pass
;
1020 fr_authpkts
[i
] = NULL
;
1022 bcopy(&fra
->fra_info
, &fin
, sizeof(fin
));
1024 RWLOCK_EXIT(&ipf_auth
);
1027 * Re-insert the packet back into the packet stream flowing through
1028 * the kernel in a manner that will mean IPFilter sees the packet
1029 * again. This is not the same as is done with fastroute,
1030 * deliberately, as we want to resume the normal packet processing
1034 if ((m
!= NULL
) && (au
->fra_info
.fin_out
!= 0)) {
1035 error
= ipf_inject(&fin
, m
);
1038 fr_authstats
.fas_sendfail
++;
1040 fr_authstats
.fas_sendok
++;
1043 error
= ipf_inject(&fin
, m
);
1046 fr_authstats
.fas_quefail
++;
1048 fr_authstats
.fas_queok
++;
1055 * If we experience an error which will result in the packet
1056 * not being processed, make sure we advance to the next one.
1058 if (error
== ENOBUFS
) {
1059 WRITE_ENTER(&ipf_auth
);
1061 * Check that the queue item has not been flushed
1062 * (and possible reused) yet.
1064 if ((fra
->fra_index
== -2) &&
1065 !bcmp((char *)&fin
, (char *)&fra
->fra_info
, sizeof(fin
))) {
1068 fra
->fra_index
= -1;
1070 if (i
== fr_authstart
) {
1071 while (fra
->fra_index
== -1) {
1074 if (i
== fr_authsize
) {
1079 if (i
== fr_authend
)
1082 if (fr_authstart
== fr_authend
) {
1089 RWLOCK_EXIT(&ipf_auth
);
1091 #endif /* _KERNEL */