The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet/ip_auth.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.