]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/contrib/ipfilter/netinet/ip_auth.c
Copy head (r256279) to stable/10 as part of the 10.0-RELEASE cycle.
[FreeBSD/stable/10.git] / sys / contrib / ipfilter / netinet / ip_auth.c
1 /*      $FreeBSD$       */
2
3 /*
4  * Copyright (C) 2012 by Darren Reed.
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 # ifdef _STDC_C99
23 #  include <stdbool.h>
24 # endif
25 # include <string.h>
26 # define _KERNEL
27 # ifdef __OpenBSD__
28 struct file;
29 # endif
30 # include <sys/uio.h>
31 # undef _KERNEL
32 #endif
33 #if defined(_KERNEL) && (__FreeBSD_version >= 220000)
34 # include <sys/filio.h>
35 # include <sys/fcntl.h>
36 #else
37 # include <sys/ioctl.h>
38 #endif
39 #if !defined(linux)
40 # include <sys/protosw.h>
41 #endif
42 #include <sys/socket.h>
43 #if defined(_KERNEL)
44 # include <sys/systm.h>
45 # if !defined(__SVR4) && !defined(__svr4__) && !defined(linux)
46 #  include <sys/mbuf.h>
47 # endif
48 #endif
49 #if defined(__SVR4) || defined(__svr4__)
50 # include <sys/filio.h>
51 # include <sys/byteorder.h>
52 # ifdef _KERNEL
53 #  include <sys/dditypes.h>
54 # endif
55 # include <sys/stream.h>
56 # include <sys/kmem.h>
57 #endif
58 #if (defined(_BSDI_VERSION) && (_BSDI_VERSION >= 199802)) || \
59     (defined(__FreeBSD_version) &&(__FreeBSD_version >= 400000))
60 # include <sys/queue.h>
61 #endif
62 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(bsdi)
63 # include <machine/cpu.h>
64 #endif
65 #if defined(_KERNEL) && defined(__NetBSD__) && (__NetBSD_Version__ >= 104000000)
66 # include <sys/proc.h>
67 #endif
68 #if defined(__NetBSD_Version__) &&  (__NetBSD_Version__ >= 400000) && \
69      !defined(_KERNEL)
70 # include <stdbool.h>
71 #endif
72 #include <net/if.h>
73 #ifdef sun
74 # include <net/af.h>
75 #endif
76 #include <netinet/in.h>
77 #include <netinet/in_systm.h>
78 #include <netinet/ip.h>
79 #if !defined(linux)
80 # include <netinet/ip_var.h>
81 #endif
82 #if !defined(_KERNEL) && !defined(__osf__) && !defined(__sgi)
83 # define        KERNEL
84 # define        _KERNEL
85 # define        NOT_KERNEL
86 #endif
87 #ifdef  NOT_KERNEL
88 # undef _KERNEL
89 # undef KERNEL
90 #endif
91 #include <netinet/tcp.h>
92 #if defined(IRIX) && (IRIX < 60516) /* IRIX < 6 */
93 extern struct ifqueue   ipintrq;                /* ip packet input queue */
94 #else
95 # if !defined(__hpux) && !defined(linux)
96 #  if __FreeBSD_version >= 300000
97 #   include <net/if_var.h>
98 #   if __FreeBSD_version >= 500042
99 #    define IF_QFULL _IF_QFULL
100 #    define IF_DROP _IF_DROP
101 #   endif /* __FreeBSD_version >= 500042 */
102 #  endif
103 #  include <netinet/in_var.h>
104 #  include <netinet/tcp_fsm.h>
105 # endif
106 #endif
107 #include <netinet/udp.h>
108 #include <netinet/ip_icmp.h>
109 #include "netinet/ip_compat.h"
110 #include <netinet/tcpip.h>
111 #include "netinet/ip_fil.h"
112 #include "netinet/ip_auth.h"
113 #if !defined(MENTAT) && !defined(linux)
114 # include <net/netisr.h>
115 # ifdef __FreeBSD__
116 #  include <machine/cpufunc.h>
117 # endif
118 #endif
119 #if (__FreeBSD_version >= 300000)
120 # include <sys/malloc.h>
121 # if defined(_KERNEL) && !defined(IPFILTER_LKM)
122 #  include <sys/libkern.h>
123 #  include <sys/systm.h>
124 # endif
125 #endif
126 /* END OF INCLUDES */
127
128 #if !defined(lint)
129 static const char rcsid[] = "@(#)$FreeBSD$";
130 /* static const char rcsid[] = "@(#)$Id: ip_auth.c,v 2.73.2.24 2007/09/09 11:32:04 darrenr Exp $"; */
131 #endif
132
133
134
135 typedef struct ipf_auth_softc_s {
136 #if SOLARIS && defined(_KERNEL)
137         kcondvar_t      ipf_auth_wait;
138 #endif /* SOLARIS */
139 #if defined(linux) && defined(_KERNEL)
140         wait_queue_head_t ipf_auth_next_linux;
141 #endif
142         ipfrwlock_t     ipf_authlk;
143         ipfmutex_t      ipf_auth_mx;
144         int             ipf_auth_size;
145         int             ipf_auth_used;
146         int             ipf_auth_replies;
147         int             ipf_auth_defaultage;
148         int             ipf_auth_lock;
149         ipf_authstat_t  ipf_auth_stats;
150         frauth_t        *ipf_auth;
151         mb_t            **ipf_auth_pkts;
152         int             ipf_auth_start;
153         int             ipf_auth_end;
154         int             ipf_auth_next;
155         frauthent_t     *ipf_auth_entries;
156         frentry_t       *ipf_auth_ip;
157         frentry_t       *ipf_auth_rules;
158 } ipf_auth_softc_t;
159
160
161 static void ipf_auth_deref __P((frauthent_t **));
162 static void ipf_auth_deref_unlocked __P((ipf_auth_softc_t *, frauthent_t **));
163 static int ipf_auth_geniter __P((ipf_main_softc_t *, ipftoken_t *,
164                                  ipfgeniter_t *, ipfobj_t *));
165 static int ipf_auth_reply __P((ipf_main_softc_t *, ipf_auth_softc_t *, char *));
166 static int ipf_auth_wait __P((ipf_main_softc_t *, ipf_auth_softc_t *, char *));
167 static int ipf_auth_flush __P((void *));
168
169
170 /* ------------------------------------------------------------------------ */
171 /* Function:    ipf_auth_main_load                                          */
172 /* Returns:     int - 0 == success, else error                              */
173 /* Parameters:  None                                                        */
174 /*                                                                          */
175 /* A null-op function that exists as a placeholder so that the flow in      */
176 /* other functions is obvious.                                              */
177 /* ------------------------------------------------------------------------ */
178 int
179 ipf_auth_main_load()
180 {
181         return 0;
182 }
183
184
185 /* ------------------------------------------------------------------------ */
186 /* Function:    ipf_auth_main_unload                                        */
187 /* Returns:     int - 0 == success, else error                              */
188 /* Parameters:  None                                                        */
189 /*                                                                          */
190 /* A null-op function that exists as a placeholder so that the flow in      */
191 /* other functions is obvious.                                              */
192 /* ------------------------------------------------------------------------ */
193 int
194 ipf_auth_main_unload()
195 {
196         return 0;
197 }
198
199
200 /* ------------------------------------------------------------------------ */
201 /* Function:    ipf_auth_soft_create                                        */
202 /* Returns:     int - NULL = failure, else success                          */
203 /* Parameters:  softc(I) - pointer to soft context data                     */
204 /*                                                                          */
205 /* Create a structre to store all of the run-time data for packet auth in   */
206 /* and initialise some fields to their defaults.                            */
207 /* ------------------------------------------------------------------------ */
208 void *
209 ipf_auth_soft_create(softc)
210         ipf_main_softc_t *softc;
211 {
212         ipf_auth_softc_t *softa;
213
214         KMALLOC(softa, ipf_auth_softc_t *);
215         if (softa == NULL)
216                 return NULL;
217
218         bzero((char *)softa, sizeof(*softa));
219
220         softa->ipf_auth_size = FR_NUMAUTH;
221         softa->ipf_auth_defaultage = 600;
222
223         RWLOCK_INIT(&softa->ipf_authlk, "ipf IP User-Auth rwlock");
224         MUTEX_INIT(&softa->ipf_auth_mx, "ipf auth log mutex");
225 #if SOLARIS && defined(_KERNEL)
226         cv_init(&softa->ipf_auth_wait, "ipf auth condvar", CV_DRIVER, NULL);
227 #endif
228
229         return softa;
230 }
231
232 /* ------------------------------------------------------------------------ */
233 /* Function:    ipf_auth_soft_init                                          */
234 /* Returns:     int - 0 == success, else error                              */
235 /* Parameters:  softc(I) - pointer to soft context data                     */
236 /*              arg(I)   - opaque pointer to auth context data              */
237 /*                                                                          */
238 /* Allocate memory and initialise data structures used in handling auth     */
239 /* rules.                                                                   */
240 /* ------------------------------------------------------------------------ */
241 int
242 ipf_auth_soft_init(softc, arg)
243         ipf_main_softc_t *softc;
244         void *arg;
245 {
246         ipf_auth_softc_t *softa = arg;
247
248         KMALLOCS(softa->ipf_auth, frauth_t *,
249                  softa->ipf_auth_size * sizeof(*softa->ipf_auth));
250         if (softa->ipf_auth == NULL)
251                 return -1;
252         bzero((char *)softa->ipf_auth,
253               softa->ipf_auth_size * sizeof(*softa->ipf_auth));
254
255         KMALLOCS(softa->ipf_auth_pkts, mb_t **,
256                  softa->ipf_auth_size * sizeof(*softa->ipf_auth_pkts));
257         if (softa->ipf_auth_pkts == NULL)
258                 return -2;
259         bzero((char *)softa->ipf_auth_pkts,
260               softa->ipf_auth_size * sizeof(*softa->ipf_auth_pkts));
261
262 #if defined(linux) && defined(_KERNEL)
263         init_waitqueue_head(&softa->ipf_auth_next_linux);
264 #endif
265
266         return 0;
267 }
268
269
270 /* ------------------------------------------------------------------------ */
271 /* Function:    ipf_auth_soft_fini                                          */
272 /* Returns:     int - 0 == success, else error                              */
273 /* Parameters:  softc(I) - pointer to soft context data                     */
274 /*              arg(I)   - opaque pointer to auth context data              */
275 /*                                                                          */
276 /* Free all network buffer memory used to keep saved packets that have been */
277 /* connectedd to the soft soft context structure *but* do not free that: it */
278 /* is free'd by _destroy().                                                 */
279 /* ------------------------------------------------------------------------ */
280 int
281 ipf_auth_soft_fini(softc, arg)
282         ipf_main_softc_t *softc;
283         void *arg;
284 {
285         ipf_auth_softc_t *softa = arg;
286         frauthent_t *fae, **faep;
287         frentry_t *fr, **frp;
288         mb_t *m;
289         int i;
290
291         if (softa->ipf_auth != NULL) {
292                 KFREES(softa->ipf_auth,
293                        softa->ipf_auth_size * sizeof(*softa->ipf_auth));
294                 softa->ipf_auth = NULL;
295         }
296
297         if (softa->ipf_auth_pkts != NULL) {
298                 for (i = 0; i < softa->ipf_auth_size; i++) {
299                         m = softa->ipf_auth_pkts[i];
300                         if (m != NULL) {
301                                 FREE_MB_T(m);
302                                 softa->ipf_auth_pkts[i] = NULL;
303                         }
304                 }
305                 KFREES(softa->ipf_auth_pkts,
306                        softa->ipf_auth_size * sizeof(*softa->ipf_auth_pkts));
307                 softa->ipf_auth_pkts = NULL;
308         }
309
310         faep = &softa->ipf_auth_entries;
311         while ((fae = *faep) != NULL) {
312                 *faep = fae->fae_next;
313                 KFREE(fae);
314         }
315         softa->ipf_auth_ip = NULL;
316
317         if (softa->ipf_auth_rules != NULL) {
318                 for (frp = &softa->ipf_auth_rules; ((fr = *frp) != NULL); ) {
319                         if (fr->fr_ref == 1) {
320                                 *frp = fr->fr_next;
321                                 MUTEX_DESTROY(&fr->fr_lock);
322                                 KFREE(fr);
323                         } else
324                                 frp = &fr->fr_next;
325                 }
326         }
327
328         return 0;
329 }
330
331
332 /* ------------------------------------------------------------------------ */
333 /* Function:    ipf_auth_soft_destroy                                       */
334 /* Returns:     void                                                        */
335 /* Parameters:  softc(I) - pointer to soft context data                     */
336 /*              arg(I)   - opaque pointer to auth context data              */
337 /*                                                                          */
338 /* Undo what was done in _create() - i.e. free the soft context data.       */
339 /* ------------------------------------------------------------------------ */
340 void
341 ipf_auth_soft_destroy(softc, arg)
342         ipf_main_softc_t *softc;
343         void *arg;
344 {
345         ipf_auth_softc_t *softa = arg;
346
347 # if SOLARIS && defined(_KERNEL)
348         cv_destroy(&softa->ipf_auth_wait);
349 # endif
350         MUTEX_DESTROY(&softa->ipf_auth_mx);
351         RW_DESTROY(&softa->ipf_authlk);
352
353         KFREE(softa);
354 }
355
356
357 /* ------------------------------------------------------------------------ */
358 /* Function:    ipf_auth_setlock                                            */
359 /* Returns:     void                                                        */
360 /* Paramters:   arg(I) - pointer to soft context data                       */
361 /*              tmp(I) - value to assign to auth lock                       */
362 /*                                                                          */
363 /* ------------------------------------------------------------------------ */
364 void
365 ipf_auth_setlock(arg, tmp)
366         void *arg;
367         int tmp;
368 {
369         ipf_auth_softc_t *softa = arg;
370
371         softa->ipf_auth_lock = tmp;
372 }
373
374
375 /* ------------------------------------------------------------------------ */
376 /* Function:    ipf_auth_check                                              */
377 /* Returns:     frentry_t* - pointer to ipf rule if match found, else NULL  */
378 /* Parameters:  fin(I)   - pointer to ipftoken structure                    */
379 /*              passp(I) - pointer to ipfgeniter structure                  */
380 /*                                                                          */
381 /* Check if a packet has authorization.  If the packet is found to match an */
382 /* authorization result and that would result in a feedback loop (i.e. it   */
383 /* will end up returning FR_AUTH) then return FR_BLOCK instead.             */
384 /* ------------------------------------------------------------------------ */
385 frentry_t *
386 ipf_auth_check(fin, passp)
387         fr_info_t *fin;
388         u_32_t *passp;
389 {
390         ipf_main_softc_t *softc = fin->fin_main_soft;
391         ipf_auth_softc_t *softa = softc->ipf_auth_soft;
392         frentry_t *fr;
393         frauth_t *fra;
394         u_32_t pass;
395         u_short id;
396         ip_t *ip;
397         int i;
398
399         if (softa->ipf_auth_lock || !softa->ipf_auth_used)
400                 return NULL;
401
402         ip = fin->fin_ip;
403         id = ip->ip_id;
404
405         READ_ENTER(&softa->ipf_authlk);
406         for (i = softa->ipf_auth_start; i != softa->ipf_auth_end; ) {
407                 /*
408                  * index becomes -2 only after an SIOCAUTHW.  Check this in
409                  * case the same packet gets sent again and it hasn't yet been
410                  * auth'd.
411                  */
412                 fra = softa->ipf_auth + i;
413                 if ((fra->fra_index == -2) && (id == fra->fra_info.fin_id) &&
414                     !bcmp((char *)fin, (char *)&fra->fra_info, FI_CSIZE)) {
415                         /*
416                          * Avoid feedback loop.
417                          */
418                         if (!(pass = fra->fra_pass) || (FR_ISAUTH(pass))) {
419                                 pass = FR_BLOCK;
420                                 fin->fin_reason = FRB_AUTHFEEDBACK;
421                         }
422                         /*
423                          * Create a dummy rule for the stateful checking to
424                          * use and return.  Zero out any values we don't
425                          * trust from userland!
426                          */
427                         if ((pass & FR_KEEPSTATE) || ((pass & FR_KEEPFRAG) &&
428                              (fin->fin_flx & FI_FRAG))) {
429                                 KMALLOC(fr, frentry_t *);
430                                 if (fr) {
431                                         bcopy((char *)fra->fra_info.fin_fr,
432                                               (char *)fr, sizeof(*fr));
433                                         fr->fr_grp = NULL;
434                                         fr->fr_ifa = fin->fin_ifp;
435                                         fr->fr_func = NULL;
436                                         fr->fr_ref = 1;
437                                         fr->fr_flags = pass;
438                                         fr->fr_ifas[1] = NULL;
439                                         fr->fr_ifas[2] = NULL;
440                                         fr->fr_ifas[3] = NULL;
441                                         MUTEX_INIT(&fr->fr_lock,
442                                                    "ipf auth rule");
443                                 }
444                         } else
445                                 fr = fra->fra_info.fin_fr;
446                         fin->fin_fr = fr;
447                         fin->fin_flx |= fra->fra_flx;
448                         RWLOCK_EXIT(&softa->ipf_authlk);
449
450                         WRITE_ENTER(&softa->ipf_authlk);
451                         /*
452                          * ipf_auth_rules is populated with the rules malloc'd
453                          * above and only those.
454                          */
455                         if ((fr != NULL) && (fr != fra->fra_info.fin_fr)) {
456                                 fr->fr_next = softa->ipf_auth_rules;
457                                 softa->ipf_auth_rules = fr;
458                         }
459                         softa->ipf_auth_stats.fas_hits++;
460                         fra->fra_index = -1;
461                         softa->ipf_auth_used--;
462                         softa->ipf_auth_replies--;
463                         if (i == softa->ipf_auth_start) {
464                                 while (fra->fra_index == -1) {
465                                         i++;
466                                         fra++;
467                                         if (i == softa->ipf_auth_size) {
468                                                 i = 0;
469                                                 fra = softa->ipf_auth;
470                                         }
471                                         softa->ipf_auth_start = i;
472                                         if (i == softa->ipf_auth_end)
473                                                 break;
474                                 }
475                                 if (softa->ipf_auth_start ==
476                                     softa->ipf_auth_end) {
477                                         softa->ipf_auth_next = 0;
478                                         softa->ipf_auth_start = 0;
479                                         softa->ipf_auth_end = 0;
480                                 }
481                         }
482                         RWLOCK_EXIT(&softa->ipf_authlk);
483                         if (passp != NULL)
484                                 *passp = pass;
485                         softa->ipf_auth_stats.fas_hits++;
486                         return fr;
487                 }
488                 i++;
489                 if (i == softa->ipf_auth_size)
490                         i = 0;
491         }
492         RWLOCK_EXIT(&softa->ipf_authlk);
493         softa->ipf_auth_stats.fas_miss++;
494         return NULL;
495 }
496
497
498 /* ------------------------------------------------------------------------ */
499 /* Function:    ipf_auth_new                                                */
500 /* Returns:     int - 1 == success, 0 = did not put packet on auth queue    */
501 /* Parameters:  m(I)   - pointer to mb_t with packet in it                  */
502 /*              fin(I) - pointer to packet information                      */
503 /*                                                                          */
504 /* Check if we have room in the auth array to hold details for another      */
505 /* packet. If we do, store it and wake up any user programs which are       */
506 /* waiting to hear about these events.                                      */
507 /* ------------------------------------------------------------------------ */
508 int
509 ipf_auth_new(m, fin)
510         mb_t *m;
511         fr_info_t *fin;
512 {
513         ipf_main_softc_t *softc = fin->fin_main_soft;
514         ipf_auth_softc_t *softa = softc->ipf_auth_soft;
515 #if defined(_KERNEL) && defined(MENTAT)
516         qpktinfo_t *qpi = fin->fin_qpi;
517 #endif
518         frauth_t *fra;
519 #if !defined(sparc) && !defined(m68k)
520         ip_t *ip;
521 #endif
522         int i;
523
524         if (softa->ipf_auth_lock)
525                 return 0;
526
527         WRITE_ENTER(&softa->ipf_authlk);
528         if (((softa->ipf_auth_end + 1) % softa->ipf_auth_size) ==
529             softa->ipf_auth_start) {
530                 softa->ipf_auth_stats.fas_nospace++;
531                 RWLOCK_EXIT(&softa->ipf_authlk);
532                 return 0;
533         }
534
535         softa->ipf_auth_stats.fas_added++;
536         softa->ipf_auth_used++;
537         i = softa->ipf_auth_end++;
538         if (softa->ipf_auth_end == softa->ipf_auth_size)
539                 softa->ipf_auth_end = 0;
540
541         fra = softa->ipf_auth + i;
542         fra->fra_index = i;
543         if (fin->fin_fr != NULL)
544                 fra->fra_pass = fin->fin_fr->fr_flags;
545         else
546                 fra->fra_pass = 0;
547         fra->fra_age = softa->ipf_auth_defaultage;
548         bcopy((char *)fin, (char *)&fra->fra_info, sizeof(*fin));
549         fra->fra_flx = fra->fra_info.fin_flx & (FI_STATE|FI_NATED);
550         fra->fra_info.fin_flx &= ~(FI_STATE|FI_NATED);
551 #if !defined(sparc) && !defined(m68k)
552         /*
553          * No need to copyback here as we want to undo the changes, not keep
554          * them.
555          */
556         ip = fin->fin_ip;
557 # if defined(MENTAT) && defined(_KERNEL)
558         if ((ip == (ip_t *)m->b_rptr) && (fin->fin_v == 4))
559 # endif
560         {
561                 register u_short bo;
562
563                 bo = ip->ip_len;
564                 ip->ip_len = htons(bo);
565                 bo = ip->ip_off;
566                 ip->ip_off = htons(bo);
567         }
568 #endif
569 #if SOLARIS && defined(_KERNEL)
570         COPYIFNAME(fin->fin_v, fin->fin_ifp, fra->fra_info.fin_ifname);
571         m->b_rptr -= qpi->qpi_off;
572         fra->fra_q = qpi->qpi_q;        /* The queue can disappear! */
573         fra->fra_m = *fin->fin_mp;
574         fra->fra_info.fin_mp = &fra->fra_m;
575         softa->ipf_auth_pkts[i] = *(mblk_t **)fin->fin_mp;
576         RWLOCK_EXIT(&softa->ipf_authlk);
577         cv_signal(&softa->ipf_auth_wait);
578         pollwakeup(&softc->ipf_poll_head[IPL_LOGAUTH], POLLIN|POLLRDNORM);
579 #else
580         softa->ipf_auth_pkts[i] = m;
581         RWLOCK_EXIT(&softa->ipf_authlk);
582         WAKEUP(&softa->ipf_auth_next, 0);
583 #endif
584         return 1;
585 }
586
587
588 /* ------------------------------------------------------------------------ */
589 /* Function:    ipf_auth_ioctl                                              */
590 /* Returns:     int - 0 == success, else error                              */
591 /* Parameters:  data(IO) - pointer to ioctl data                            */
592 /*              cmd(I)   - ioctl command                                    */
593 /*              mode(I)  - mode flags associated with open descriptor       */
594 /*              uid(I)   - uid associatd with application making the call   */
595 /*              ctx(I)   - pointer for context                              */
596 /*                                                                          */
597 /* This function handles all of the ioctls recognised by the auth component */
598 /* in IPFilter - ie ioctls called on an open fd for /dev/ipf_auth           */
599 /* ------------------------------------------------------------------------ */
600 int
601 ipf_auth_ioctl(softc, data, cmd, mode, uid, ctx)
602         ipf_main_softc_t *softc;
603         caddr_t data;
604         ioctlcmd_t cmd;
605         int mode, uid;
606         void *ctx;
607 {
608         ipf_auth_softc_t *softa = softc->ipf_auth_soft;
609         int error = 0, i;
610         SPL_INT(s);
611
612         switch (cmd)
613         {
614         case SIOCGENITER :
615             {
616                 ipftoken_t *token;
617                 ipfgeniter_t iter;
618                 ipfobj_t obj;
619
620                 error = ipf_inobj(softc, data, &obj, &iter, IPFOBJ_GENITER);
621                 if (error != 0)
622                         break;
623
624                 SPL_SCHED(s);
625                 token = ipf_token_find(softc, IPFGENITER_AUTH, uid, ctx);
626                 if (token != NULL)
627                         error = ipf_auth_geniter(softc, token, &iter, &obj);
628                 else {
629                         WRITE_ENTER(&softc->ipf_tokens);
630                         ipf_token_deref(softc, token);
631                         RWLOCK_EXIT(&softc->ipf_tokens);
632                         IPFERROR(10001);
633                         error = ESRCH;
634                 }
635                 SPL_X(s);
636
637                 break;
638             }
639
640         case SIOCADAFR :
641         case SIOCRMAFR :
642                 if (!(mode & FWRITE)) {
643                         IPFERROR(10002);
644                         error = EPERM;
645                 } else
646                         error = frrequest(softc, IPL_LOGAUTH, cmd, data,
647                                           softc->ipf_active, 1);
648                 break;
649
650         case SIOCSTLCK :
651                 if (!(mode & FWRITE)) {
652                         IPFERROR(10003);
653                         error = EPERM;
654                 } else {
655                         error = ipf_lock(data, &softa->ipf_auth_lock);
656                 }
657                 break;
658
659         case SIOCATHST:
660                 softa->ipf_auth_stats.fas_faelist = softa->ipf_auth_entries;
661                 error = ipf_outobj(softc, data, &softa->ipf_auth_stats,
662                                    IPFOBJ_AUTHSTAT);
663                 break;
664
665         case SIOCIPFFL:
666                 SPL_NET(s);
667                 WRITE_ENTER(&softa->ipf_authlk);
668                 i = ipf_auth_flush(softa);
669                 RWLOCK_EXIT(&softa->ipf_authlk);
670                 SPL_X(s);
671                 error = BCOPYOUT(&i, data, sizeof(i));
672                 if (error != 0) {
673                         IPFERROR(10004);
674                         error = EFAULT;
675                 }
676                 break;
677
678         case SIOCAUTHW:
679                 error = ipf_auth_wait(softc, softa, data);
680                 break;
681
682         case SIOCAUTHR:
683                 error = ipf_auth_reply(softc, softa, data);
684                 break;
685
686         default :
687                 IPFERROR(10005);
688                 error = EINVAL;
689                 break;
690         }
691         return error;
692 }
693
694
695 /* ------------------------------------------------------------------------ */
696 /* Function:    ipf_auth_expire                                             */
697 /* Returns:     None                                                        */
698 /* Parameters:  None                                                        */
699 /*                                                                          */
700 /* Slowly expire held auth records.  Timeouts are set in expectation of     */
701 /* this being called twice per second.                                      */
702 /* ------------------------------------------------------------------------ */
703 void
704 ipf_auth_expire(softc)
705         ipf_main_softc_t *softc;
706 {
707         ipf_auth_softc_t *softa = softc->ipf_auth_soft;
708         frauthent_t *fae, **faep;
709         frentry_t *fr, **frp;
710         frauth_t *fra;
711         mb_t *m;
712         int i;
713         SPL_INT(s);
714
715         if (softa->ipf_auth_lock)
716                 return;
717         SPL_NET(s);
718         WRITE_ENTER(&softa->ipf_authlk);
719         for (i = 0, fra = softa->ipf_auth; i < softa->ipf_auth_size;
720              i++, fra++) {
721                 fra->fra_age--;
722                 if ((fra->fra_age == 0) &&
723                     (softa->ipf_auth[i].fra_index != -1)) {
724                         if ((m = softa->ipf_auth_pkts[i]) != NULL) {
725                                 FREE_MB_T(m);
726                                 softa->ipf_auth_pkts[i] = NULL;
727                         } else if (softa->ipf_auth[i].fra_index == -2) {
728                                 softa->ipf_auth_replies--;
729                         }
730                         softa->ipf_auth[i].fra_index = -1;
731                         softa->ipf_auth_stats.fas_expire++;
732                         softa->ipf_auth_used--;
733                 }
734         }
735
736         /*
737          * Expire pre-auth rules
738          */
739         for (faep = &softa->ipf_auth_entries; ((fae = *faep) != NULL); ) {
740                 fae->fae_age--;
741                 if (fae->fae_age == 0) {
742                         ipf_auth_deref(&fae);
743                         softa->ipf_auth_stats.fas_expire++;
744                 } else
745                         faep = &fae->fae_next;
746         }
747         if (softa->ipf_auth_entries != NULL)
748                 softa->ipf_auth_ip = &softa->ipf_auth_entries->fae_fr;
749         else
750                 softa->ipf_auth_ip = NULL;
751
752         for (frp = &softa->ipf_auth_rules; ((fr = *frp) != NULL); ) {
753                 if (fr->fr_ref == 1) {
754                         *frp = fr->fr_next;
755                         MUTEX_DESTROY(&fr->fr_lock);
756                         KFREE(fr);
757                 } else
758                         frp = &fr->fr_next;
759         }
760         RWLOCK_EXIT(&softa->ipf_authlk);
761         SPL_X(s);
762 }
763
764
765 /* ------------------------------------------------------------------------ */
766 /* Function:    ipf_auth_precmd                                             */
767 /* Returns:     int - 0 == success, else error                              */
768 /* Parameters:  cmd(I)  - ioctl command for rule                            */
769 /*              fr(I)   - pointer to ipf rule                               */
770 /*              fptr(I) - pointer to caller's 'fr'                          */
771 /*                                                                          */
772 /* ------------------------------------------------------------------------ */
773 int
774 ipf_auth_precmd(softc, cmd, fr, frptr)
775         ipf_main_softc_t *softc;
776         ioctlcmd_t cmd;
777         frentry_t *fr, **frptr;
778 {
779         ipf_auth_softc_t *softa = softc->ipf_auth_soft;
780         frauthent_t *fae, **faep;
781         int error = 0;
782         SPL_INT(s);
783
784         if ((cmd != SIOCADAFR) && (cmd != SIOCRMAFR)) {
785                 IPFERROR(10006);
786                 return EIO;
787         }
788
789         for (faep = &softa->ipf_auth_entries; ((fae = *faep) != NULL); ) {
790                 if (&fae->fae_fr == fr)
791                         break;
792                 else
793                         faep = &fae->fae_next;
794         }
795
796         if (cmd == (ioctlcmd_t)SIOCRMAFR) {
797                 if (fr == NULL || frptr == NULL) {
798                         IPFERROR(10007);
799                         error = EINVAL;
800
801                 } else if (fae == NULL) {
802                         IPFERROR(10008);
803                         error = ESRCH;
804
805                 } else {
806                         SPL_NET(s);
807                         WRITE_ENTER(&softa->ipf_authlk);
808                         *faep = fae->fae_next;
809                         if (softa->ipf_auth_ip == &fae->fae_fr)
810                                 softa->ipf_auth_ip = softa->ipf_auth_entries ?
811                                     &softa->ipf_auth_entries->fae_fr : NULL;
812                         RWLOCK_EXIT(&softa->ipf_authlk);
813                         SPL_X(s);
814
815                         KFREE(fae);
816                 }
817         } else if (fr != NULL && frptr != NULL) {
818                 KMALLOC(fae, frauthent_t *);
819                 if (fae != NULL) {
820                         bcopy((char *)fr, (char *)&fae->fae_fr,
821                               sizeof(*fr));
822                         SPL_NET(s);
823                         WRITE_ENTER(&softa->ipf_authlk);
824                         fae->fae_age = softa->ipf_auth_defaultage;
825                         fae->fae_fr.fr_hits = 0;
826                         fae->fae_fr.fr_next = *frptr;
827                         fae->fae_ref = 1;
828                         *frptr = &fae->fae_fr;
829                         fae->fae_next = *faep;
830                         *faep = fae;
831                         softa->ipf_auth_ip = &softa->ipf_auth_entries->fae_fr;
832                         RWLOCK_EXIT(&softa->ipf_authlk);
833                         SPL_X(s);
834                 } else {
835                         IPFERROR(10009);
836                         error = ENOMEM;
837                 }
838         } else {
839                 IPFERROR(10010);
840                 error = EINVAL;
841         }
842         return error;
843 }
844
845
846 /* ------------------------------------------------------------------------ */
847 /* Function:    ipf_auth_flush                                              */
848 /* Returns:     int - number of auth entries flushed                        */
849 /* Parameters:  None                                                        */
850 /* Locks:       WRITE(ipf_authlk)                                           */
851 /*                                                                          */
852 /* This function flushs the ipf_auth_pkts array of any packet data with     */
853 /* references still there.                                                  */
854 /* It is expected that the caller has already acquired the correct locks or */
855 /* set the priority level correctly for this to block out other code paths  */
856 /* into these data structures.                                              */
857 /* ------------------------------------------------------------------------ */
858 static int
859 ipf_auth_flush(arg)
860         void *arg;
861 {
862         ipf_auth_softc_t *softa = arg;
863         int i, num_flushed;
864         mb_t *m;
865
866         if (softa->ipf_auth_lock)
867                 return -1;
868
869         num_flushed = 0;
870
871         for (i = 0 ; i < softa->ipf_auth_size; i++) {
872                 if (softa->ipf_auth[i].fra_index != -1) {
873                         m = softa->ipf_auth_pkts[i];
874                         if (m != NULL) {
875                                 FREE_MB_T(m);
876                                 softa->ipf_auth_pkts[i] = NULL;
877                         }
878
879                         softa->ipf_auth[i].fra_index = -1;
880                         /* perhaps add & use a flush counter inst.*/
881                         softa->ipf_auth_stats.fas_expire++;
882                         num_flushed++;
883                 }
884         }
885
886         softa->ipf_auth_start = 0;
887         softa->ipf_auth_end = 0;
888         softa->ipf_auth_next = 0;
889         softa->ipf_auth_used = 0;
890         softa->ipf_auth_replies = 0;
891
892         return num_flushed;
893 }
894
895
896 /* ------------------------------------------------------------------------ */
897 /* Function:    ipf_auth_waiting                                            */
898 /* Returns:     int - number of packets in the auth queue                   */
899 /* Parameters:  None                                                        */
900 /*                                                                          */
901 /* Simple truth check to see if there are any packets waiting in the auth   */
902 /* queue.                                                                   */
903 /* ------------------------------------------------------------------------ */
904 int
905 ipf_auth_waiting(softc)
906         ipf_main_softc_t *softc;
907 {
908         ipf_auth_softc_t *softa = softc->ipf_auth_soft;
909
910         return (softa->ipf_auth_used != 0);
911 }
912
913
914 /* ------------------------------------------------------------------------ */
915 /* Function:    ipf_auth_geniter                                            */
916 /* Returns:     int - 0 == success, else error                              */
917 /* Parameters:  token(I) - pointer to ipftoken structure                    */
918 /*              itp(I)   - pointer to ipfgeniter structure                  */
919 /*              objp(I)  - pointer to ipf object destription                */
920 /*                                                                          */
921 /* Iterate through the list of entries in the auth queue list.              */
922 /* objp is used here to get the location of where to do the copy out to.    */
923 /* Stomping over various fields with new information will not harm anything */
924 /* ------------------------------------------------------------------------ */
925 static int
926 ipf_auth_geniter(softc, token, itp, objp)
927         ipf_main_softc_t *softc;
928         ipftoken_t *token;
929         ipfgeniter_t *itp;
930         ipfobj_t *objp;
931 {
932         ipf_auth_softc_t *softa = softc->ipf_auth_soft;
933         frauthent_t *fae, *next, zero;
934         int error;
935
936         if (itp->igi_data == NULL) {
937                 IPFERROR(10011);
938                 return EFAULT;
939         }
940
941         if (itp->igi_type != IPFGENITER_AUTH) {
942                 IPFERROR(10012);
943                 return EINVAL;
944         }
945
946         objp->ipfo_type = IPFOBJ_FRAUTH;
947         objp->ipfo_ptr = itp->igi_data;
948         objp->ipfo_size = sizeof(frauth_t);
949
950         READ_ENTER(&softa->ipf_authlk);
951
952         fae = token->ipt_data;
953         if (fae == NULL) {
954                 next = softa->ipf_auth_entries;
955         } else {
956                 next = fae->fae_next;
957         }
958
959         /*
960          * If we found an auth entry to use, bump its reference count
961          * so that it can be used for is_next when we come back.
962          */
963         if (next != NULL) {
964                 ATOMIC_INC(next->fae_ref);
965                 token->ipt_data = next;
966         } else {
967                 bzero(&zero, sizeof(zero));
968                 next = &zero;
969                 token->ipt_data = NULL;
970         }
971
972         RWLOCK_EXIT(&softa->ipf_authlk);
973
974         error = ipf_outobjk(softc, objp, next);
975         if (fae != NULL)
976                 ipf_auth_deref_unlocked(softa, &fae);
977
978         if (next->fae_next == NULL)
979                 ipf_token_mark_complete(token);
980         return error;
981 }
982
983
984 /* ------------------------------------------------------------------------ */
985 /* Function:    ipf_auth_deref_unlocked                                     */
986 /* Returns:     None                                                        */
987 /* Parameters:  faep(IO) - pointer to caller's frauthent_t pointer          */
988 /*                                                                          */
989 /* Wrapper for ipf_auth_deref for when a write lock on ipf_authlk is not    */
990 /* held.                                                                    */
991 /* ------------------------------------------------------------------------ */
992 static void
993 ipf_auth_deref_unlocked(softa, faep)
994         ipf_auth_softc_t *softa;
995         frauthent_t **faep;
996 {
997         WRITE_ENTER(&softa->ipf_authlk);
998         ipf_auth_deref(faep);
999         RWLOCK_EXIT(&softa->ipf_authlk);
1000 }
1001
1002
1003 /* ------------------------------------------------------------------------ */
1004 /* Function:    ipf_auth_deref                                              */
1005 /* Returns:     None                                                        */
1006 /* Parameters:  faep(IO) - pointer to caller's frauthent_t pointer          */
1007 /* Locks:       WRITE(ipf_authlk)                                           */
1008 /*                                                                          */
1009 /* This function unconditionally sets the pointer in the caller to NULL,    */
1010 /* to make it clear that it should no longer use that pointer, and drops    */
1011 /* the reference count on the structure by 1.  If it reaches 0, free it up. */
1012 /* ------------------------------------------------------------------------ */
1013 static void
1014 ipf_auth_deref(faep)
1015         frauthent_t **faep;
1016 {
1017         frauthent_t *fae;
1018
1019         fae = *faep;
1020         *faep = NULL;
1021
1022         fae->fae_ref--;
1023         if (fae->fae_ref == 0) {
1024                 KFREE(fae);
1025         }
1026 }
1027
1028
1029 /* ------------------------------------------------------------------------ */
1030 /* Function:    ipf_auth_wait_pkt                                           */
1031 /* Returns:     int - 0 == success, else error                              */
1032 /* Parameters:  data(I) - pointer to data from ioctl call                   */
1033 /*                                                                          */
1034 /* This function is called when an application is waiting for a packet to   */
1035 /* match an "auth" rule by issuing an SIOCAUTHW ioctl.  If there is already */
1036 /* a packet waiting on the queue then we will return that _one_ immediately.*/
1037 /* If there are no packets present in the queue (ipf_auth_pkts) then we go  */
1038 /* to sleep.                                                                */
1039 /* ------------------------------------------------------------------------ */
1040 static int
1041 ipf_auth_wait(softc, softa, data)
1042         ipf_main_softc_t *softc;
1043         ipf_auth_softc_t *softa;
1044         char *data;
1045 {
1046         frauth_t auth, *au = &auth;
1047         int error, len, i;
1048         mb_t *m;
1049         char *t;
1050         SPL_INT(s);
1051
1052 ipf_auth_ioctlloop:
1053         error = ipf_inobj(softc, data, NULL, au, IPFOBJ_FRAUTH);
1054         if (error != 0)
1055                 return error;
1056
1057         /*
1058          * XXX Locks are held below over calls to copyout...a better
1059          * solution needs to be found so this isn't necessary.  The situation
1060          * we are trying to guard against here is an error in the copyout
1061          * steps should not cause the packet to "disappear" from the queue.
1062          */
1063         SPL_NET(s);
1064         READ_ENTER(&softa->ipf_authlk);
1065
1066         /*
1067          * If ipf_auth_next is not equal to ipf_auth_end it will be because
1068          * there is a packet waiting to be delt with in the ipf_auth_pkts
1069          * array.  We copy as much of that out to user space as requested.
1070          */
1071         if (softa->ipf_auth_used > 0) {
1072                 while (softa->ipf_auth_pkts[softa->ipf_auth_next] == NULL) {
1073                         softa->ipf_auth_next++;
1074                         if (softa->ipf_auth_next == softa->ipf_auth_size)
1075                                 softa->ipf_auth_next = 0;
1076                 }
1077
1078                 error = ipf_outobj(softc, data,
1079                                    &softa->ipf_auth[softa->ipf_auth_next],
1080                                    IPFOBJ_FRAUTH);
1081                 if (error != 0) {
1082                         RWLOCK_EXIT(&softa->ipf_authlk);
1083                         SPL_X(s);
1084                         return error;
1085                 }
1086
1087                 if (auth.fra_len != 0 && auth.fra_buf != NULL) {
1088                         /*
1089                          * Copy packet contents out to user space if
1090                          * requested.  Bail on an error.
1091                          */
1092                         m = softa->ipf_auth_pkts[softa->ipf_auth_next];
1093                         len = MSGDSIZE(m);
1094                         if (len > auth.fra_len)
1095                                 len = auth.fra_len;
1096                         auth.fra_len = len;
1097
1098                         for (t = auth.fra_buf; m && (len > 0); ) {
1099                                 i = MIN(M_LEN(m), len);
1100                                 error = copyoutptr(softc, MTOD(m, char *),
1101                                                    &t, i);
1102                                 len -= i;
1103                                 t += i;
1104                                 if (error != 0) {
1105                                         RWLOCK_EXIT(&softa->ipf_authlk);
1106                                         SPL_X(s);
1107                                         return error;
1108                                 }
1109                                 m = m->m_next;
1110                         }
1111                 }
1112                 RWLOCK_EXIT(&softa->ipf_authlk);
1113
1114                 SPL_NET(s);
1115                 WRITE_ENTER(&softa->ipf_authlk);
1116                 softa->ipf_auth_next++;
1117                 if (softa->ipf_auth_next == softa->ipf_auth_size)
1118                         softa->ipf_auth_next = 0;
1119                 RWLOCK_EXIT(&softa->ipf_authlk);
1120                 SPL_X(s);
1121
1122                 return 0;
1123         }
1124         RWLOCK_EXIT(&softa->ipf_authlk);
1125         SPL_X(s);
1126
1127         MUTEX_ENTER(&softa->ipf_auth_mx);
1128 #ifdef  _KERNEL
1129 # if    SOLARIS
1130         error = 0;
1131         if (!cv_wait_sig(&softa->ipf_auth_wait, &softa->ipf_auth_mx.ipf_lk)) {
1132                 IPFERROR(10014);
1133                 error = EINTR;
1134         }
1135 # else /* SOLARIS */
1136 #  ifdef __hpux
1137         {
1138         lock_t *l;
1139
1140         l = get_sleep_lock(&softa->ipf_auth_next);
1141         error = sleep(&softa->ipf_auth_next, PZERO+1);
1142         spinunlock(l);
1143         }
1144 #  else
1145 #   ifdef __osf__
1146         error = mpsleep(&softa->ipf_auth_next, PSUSP|PCATCH, "ipf_auth_next",
1147                         0, &softa->ipf_auth_mx, MS_LOCK_SIMPLE);
1148 #   else
1149         error = SLEEP(&softa->ipf_auth_next, "ipf_auth_next");
1150 #   endif /* __osf__ */
1151 #  endif /* __hpux */
1152 # endif /* SOLARIS */
1153 #endif
1154         MUTEX_EXIT(&softa->ipf_auth_mx);
1155         if (error == 0)
1156                 goto ipf_auth_ioctlloop;
1157         return error;
1158 }
1159
1160
1161 /* ------------------------------------------------------------------------ */
1162 /* Function:    ipf_auth_reply                                              */
1163 /* Returns:     int - 0 == success, else error                              */
1164 /* Parameters:  data(I) - pointer to data from ioctl call                   */
1165 /*                                                                          */
1166 /* This function is called by an application when it wants to return a      */
1167 /* decision on a packet using the SIOCAUTHR ioctl.  This is after it has    */
1168 /* received information using an SIOCAUTHW.  The decision returned in the   */
1169 /* form of flags, the same as those used in each rule.                      */
1170 /* ------------------------------------------------------------------------ */
1171 static int
1172 ipf_auth_reply(softc, softa, data)
1173         ipf_main_softc_t *softc;
1174         ipf_auth_softc_t *softa;
1175         char *data;
1176 {
1177         frauth_t auth, *au = &auth, *fra;
1178         fr_info_t fin;
1179         int error, i;
1180         mb_t *m;
1181         SPL_INT(s);
1182
1183         error = ipf_inobj(softc, data, NULL, &auth, IPFOBJ_FRAUTH);
1184         if (error != 0)
1185                 return error;
1186
1187         SPL_NET(s);
1188         WRITE_ENTER(&softa->ipf_authlk);
1189
1190         i = au->fra_index;
1191         fra = softa->ipf_auth + i;
1192         error = 0;
1193
1194         /*
1195          * Check the validity of the information being returned with two simple
1196          * checks.  First, the auth index value should be within the size of
1197          * the array and second the packet id being returned should also match.
1198          */
1199         if ((i < 0) || (i >= softa->ipf_auth_size)) {
1200                 RWLOCK_EXIT(&softa->ipf_authlk);
1201                 SPL_X(s);
1202                 IPFERROR(10015);
1203                 return ESRCH;
1204         }
1205         if  (fra->fra_info.fin_id != au->fra_info.fin_id) {
1206                 RWLOCK_EXIT(&softa->ipf_authlk);
1207                 SPL_X(s);
1208                 IPFERROR(10019);
1209                 return ESRCH;
1210         }
1211
1212         m = softa->ipf_auth_pkts[i];
1213         fra->fra_index = -2;
1214         fra->fra_pass = au->fra_pass;
1215         softa->ipf_auth_pkts[i] = NULL;
1216         softa->ipf_auth_replies++;
1217         bcopy(&fra->fra_info, &fin, sizeof(fin));
1218
1219         RWLOCK_EXIT(&softa->ipf_authlk);
1220
1221         /*
1222          * Re-insert the packet back into the packet stream flowing through
1223          * the kernel in a manner that will mean IPFilter sees the packet
1224          * again.  This is not the same as is done with fastroute,
1225          * deliberately, as we want to resume the normal packet processing
1226          * path for it.
1227          */
1228 #ifdef  _KERNEL
1229         if ((m != NULL) && (au->fra_info.fin_out != 0)) {
1230                 error = ipf_inject(&fin, m);
1231                 if (error != 0) {
1232                         IPFERROR(10016);
1233                         error = ENOBUFS;
1234                         softa->ipf_auth_stats.fas_sendfail++;
1235                 } else {
1236                         softa->ipf_auth_stats.fas_sendok++;
1237                 }
1238         } else if (m) {
1239                 error = ipf_inject(&fin, m);
1240                 if (error != 0) {
1241                         IPFERROR(10017);
1242                         error = ENOBUFS;
1243                         softa->ipf_auth_stats.fas_quefail++;
1244                 } else {
1245                         softa->ipf_auth_stats.fas_queok++;
1246                 }
1247         } else {
1248                 IPFERROR(10018);
1249                 error = EINVAL;
1250         }
1251
1252         /*
1253          * If we experience an error which will result in the packet
1254          * not being processed, make sure we advance to the next one.
1255          */
1256         if (error == ENOBUFS) {
1257                 WRITE_ENTER(&softa->ipf_authlk);
1258                 softa->ipf_auth_used--;
1259                 fra->fra_index = -1;
1260                 fra->fra_pass = 0;
1261                 if (i == softa->ipf_auth_start) {
1262                         while (fra->fra_index == -1) {
1263                                 i++;
1264                                 if (i == softa->ipf_auth_size)
1265                                         i = 0;
1266                                 softa->ipf_auth_start = i;
1267                                 if (i == softa->ipf_auth_end)
1268                                         break;
1269                         }
1270                         if (softa->ipf_auth_start == softa->ipf_auth_end) {
1271                                 softa->ipf_auth_next = 0;
1272                                 softa->ipf_auth_start = 0;
1273                                 softa->ipf_auth_end = 0;
1274                         }
1275                 }
1276                 RWLOCK_EXIT(&softa->ipf_authlk);
1277         }
1278 #endif /* _KERNEL */
1279         SPL_X(s);
1280
1281         return 0;
1282 }
1283
1284
1285 u_32_t
1286 ipf_auth_pre_scanlist(softc, fin, pass)
1287         ipf_main_softc_t *softc;
1288         fr_info_t *fin;
1289         u_32_t pass;
1290 {
1291         ipf_auth_softc_t *softa = softc->ipf_auth_soft;
1292
1293         if (softa->ipf_auth_ip != NULL)
1294                 return ipf_scanlist(fin, softc->ipf_pass);
1295
1296         return pass;
1297 }
1298
1299
1300 frentry_t **
1301 ipf_auth_rulehead(softc)
1302         ipf_main_softc_t *softc;
1303 {
1304         ipf_auth_softc_t *softa = softc->ipf_auth_soft;
1305
1306         return &softa->ipf_auth_ip;
1307 }