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 /*
    2  * Copyright (C) 1997 by Darren Reed & Guido van Rooij.
    3  *
    4  * Redistribution and use in source and binary forms are permitted
    5  * provided that this notice is preserved and due credit is given
    6  * to the original author and the contributors.
    7  */
    8 #if !defined(lint)
    9 static const char rcsid[] = "@(#)$FreeBSD$";
   10 #endif
   11 
   12 #if defined(KERNEL) && !defined(_KERNEL)
   13 #define _KERNEL
   14 #endif
   15 #define __FreeBSD_version 300000        /* just a hack - no <sys/osreldate.h> */
   16 
   17 #if !defined(_KERNEL) && !defined(KERNEL)
   18 # include <stdlib.h>
   19 # include <string.h>
   20 #endif
   21 #include <sys/errno.h>
   22 #include <sys/types.h>
   23 #include <sys/param.h>
   24 #include <sys/time.h>
   25 #include <sys/file.h>
   26 #if defined(KERNEL) && (__FreeBSD_version >= 220000)
   27 # include <sys/filio.h>
   28 # include <sys/fcntl.h>
   29 #else
   30 # include <sys/ioctl.h>
   31 #endif
   32 #include <sys/uio.h>
   33 #ifndef linux
   34 # include <sys/protosw.h>
   35 #endif
   36 #include <sys/socket.h>
   37 #if defined(_KERNEL) && !defined(linux)
   38 # include <sys/systm.h>
   39 #endif
   40 #if !defined(__SVR4) && !defined(__svr4__)
   41 # ifndef linux
   42 #  include <sys/mbuf.h>
   43 # endif
   44 #else
   45 # include <sys/filio.h>
   46 # include <sys/byteorder.h>
   47 # include <sys/dditypes.h>
   48 # include <sys/stream.h>
   49 # include <sys/kmem.h>
   50 #endif
   51 #if defined(KERNEL) && (__FreeBSD_version >= 300000)
   52 # include <sys/malloc.h>
   53 #endif
   54 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(bsdi)
   55 # include <machine/cpu.h>
   56 #endif
   57 #include <net/if.h>
   58 #ifdef sun
   59 #include <net/af.h>
   60 #endif
   61 #if !defined(KERNEL) && (__FreeBSD_version >= 300000)
   62 # include <net/if_var.h>
   63 #endif
   64 #include <net/route.h>
   65 #include <netinet/in.h>
   66 #include <netinet/in_systm.h>
   67 #include <netinet/ip.h>
   68 #ifndef KERNEL
   69 #define KERNEL
   70 #define NOT_KERNEL
   71 #endif
   72 #ifndef linux
   73 # include <netinet/ip_var.h>
   74 #endif
   75 #ifdef  NOT_KERNEL
   76 #undef  KERNEL
   77 #endif
   78 #ifdef __sgi
   79 # ifdef IFF_DRVRLOCK /* IRIX6 */
   80 #include <sys/hashing.h>
   81 # endif
   82 #endif
   83 #include <netinet/tcp.h>
   84 #if defined(__sgi) && !defined(IFF_DRVRLOCK) /* IRIX < 6 */
   85 extern struct ifqueue   ipintrq;                /* ip packet input queue */
   86 #else
   87 # ifndef linux
   88 #  include <netinet/in_var.h>
   89 #  include <netinet/tcp_fsm.h>
   90 # endif
   91 #endif
   92 #include <netinet/udp.h>
   93 #include <netinet/ip_icmp.h>
   94 #include "netinet/ip_compat.h"
   95 #include <netinet/tcpip.h>
   96 #include "netinet/ip_fil.h"
   97 #include "netinet/ip_auth.h"
   98 #if !SOLARIS && !defined(linux)
   99 # include <net/netisr.h>
  100 # ifdef __FreeBSD__
  101 #  include <machine/cpufunc.h>
  102 # endif
  103 #endif
  104 
  105 
  106 #if (SOLARIS || defined(__sgi)) && defined(_KERNEL)
  107 extern kmutex_t ipf_auth;
  108 # if SOLARIS
  109 extern kcondvar_t ipfauthwait;
  110 # endif
  111 #endif
  112 #ifdef linux
  113 static struct wait_queue *ipfauthwait = NULL;
  114 #endif
  115 
  116 int     fr_authsize = FR_NUMAUTH;
  117 int     fr_authused = 0;
  118 int     fr_defaultauthage = 600;
  119 fr_authstat_t   fr_authstats;
  120 static frauth_t fr_auth[FR_NUMAUTH];
  121 mb_t    *fr_authpkts[FR_NUMAUTH];
  122 static int      fr_authstart = 0, fr_authend = 0, fr_authnext = 0;
  123 static frauthent_t      *fae_list = NULL;
  124 frentry_t       *ipauth = NULL;
  125 
  126 
  127 /*
  128  * Check if a packet has authorization.  If the packet is found to match an
  129  * authorization result and that would result in a feedback loop (i.e. it
  130  * will end up returning FR_AUTH) then return FR_BLOCK instead.
  131  */
  132 int fr_checkauth(ip, fin)
  133 ip_t *ip;
  134 fr_info_t *fin;
  135 {
  136         u_short id = ip->ip_id;
  137         u_32_t pass;
  138         int i;
  139 
  140         MUTEX_ENTER(&ipf_auth);
  141         for (i = fr_authstart; i != fr_authend; ) {
  142                 /*
  143                  * index becomes -2 only after an SIOCAUTHW.  Check this in
  144                  * case the same packet gets sent again and it hasn't yet been
  145                  * auth'd.
  146                  */
  147                 if ((fr_auth[i].fra_index == -2) &&
  148                     (id == fr_auth[i].fra_info.fin_id) &&
  149                     !bcmp((char *)fin,(char *)&fr_auth[i].fra_info,FI_CSIZE)) {
  150                         /*
  151                          * Avoid feedback loop.
  152                          */
  153                         if (!(pass = fr_auth[i].fra_pass) || (pass & FR_AUTH))
  154                                 pass = FR_BLOCK;
  155                         fr_authstats.fas_hits++;
  156                         fr_auth[i].fra_index = -1;
  157                         fr_authused--;
  158                         if (i == fr_authstart) {
  159                                 while (fr_auth[i].fra_index == -1) {
  160                                         i++;
  161                                         if (i == FR_NUMAUTH)
  162                                                 i = 0;
  163                                         fr_authstart = i;
  164                                         if (i == fr_authend)
  165                                                 break;
  166                                 }
  167                                 if (fr_authstart == fr_authend) {
  168                                         fr_authnext = 0;
  169                                         fr_authstart = fr_authend = 0;
  170                                 }
  171                         }
  172                         MUTEX_EXIT(&ipf_auth);
  173                         return pass;
  174                 }
  175                 i++;
  176                 if (i == FR_NUMAUTH)
  177                         i = 0;
  178         }
  179         fr_authstats.fas_miss++;
  180         MUTEX_EXIT(&ipf_auth);
  181         return 0;
  182 }
  183 
  184 
  185 /*
  186  * Check if we have room in the auth array to hold details for another packet.
  187  * If we do, store it and wake up any user programs which are waiting to
  188  * hear about these events.
  189  */
  190 int fr_newauth(m, fin, ip
  191 #if defined(_KERNEL) && SOLARIS
  192 , qif)
  193 qif_t *qif;
  194 #else
  195 )
  196 #endif
  197 mb_t *m;
  198 fr_info_t *fin;
  199 ip_t *ip;
  200 {
  201         int i;
  202 
  203         MUTEX_ENTER(&ipf_auth);
  204         if ((fr_authstart > fr_authend) && (fr_authstart - fr_authend == -1)) {
  205                 fr_authstats.fas_nospace++;
  206                 MUTEX_EXIT(&ipf_auth);
  207                 return 0;
  208         }
  209         if (fr_authend - fr_authstart == FR_NUMAUTH - 1) {
  210                 fr_authstats.fas_nospace++;
  211                 MUTEX_EXIT(&ipf_auth);
  212                 return 0;
  213         }
  214 
  215         fr_authstats.fas_added++;
  216         fr_authused++;
  217         i = fr_authend++;
  218         if (fr_authend == FR_NUMAUTH)
  219                 fr_authend = 0;
  220         MUTEX_EXIT(&ipf_auth);
  221         fr_auth[i].fra_index = i;
  222         fr_auth[i].fra_pass = 0;
  223         fr_auth[i].fra_age = fr_defaultauthage;
  224         bcopy((char *)fin, (char *)&fr_auth[i].fra_info, sizeof(*fin));
  225 #if !defined(sparc) && !defined(m68k)
  226         /*
  227          * No need to copyback here as we want to undo the changes, not keep
  228          * them.
  229          */
  230 # if SOLARIS && defined(_KERNEL)
  231         if (ip == (ip_t *)m->b_rptr)
  232 # endif
  233         {
  234                 register u_short bo;
  235 
  236                 bo = ip->ip_len;
  237                 ip->ip_len = htons(bo);
  238 # if !SOLARIS   /* 4.4BSD converts this ip_input.c, but I don't in solaris.c */
  239                 bo = ip->ip_id;
  240                 ip->ip_id = htons(bo);
  241 # endif
  242                 bo = ip->ip_off;
  243                 ip->ip_off = htons(bo);
  244         }
  245 #endif
  246 #if SOLARIS && defined(_KERNEL)
  247         m->b_rptr -= qif->qf_off;
  248         fr_authpkts[i] = *(mblk_t **)fin->fin_mp;
  249         fr_auth[i].fra_q = qif->qf_q;
  250         cv_signal(&ipfauthwait);
  251 #else
  252         fr_authpkts[i] = m;
  253 # if defined(linux) && defined(_KERNEL)
  254         wake_up_interruptible(&ipfauthwait);
  255 # else
  256         WAKEUP(&fr_authnext);
  257 # endif
  258 #endif
  259         return 1;
  260 }
  261 
  262 
  263 int fr_auth_ioctl(data, cmd, fr, frptr)
  264 caddr_t data;
  265 #if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003)
  266 u_long cmd;
  267 #else
  268 int cmd;
  269 #endif
  270 frentry_t *fr, **frptr;
  271 {
  272         mb_t *m;
  273 #if defined(_KERNEL)
  274 # if !SOLARIS
  275         struct ifqueue *ifq;
  276         int s;
  277 # endif
  278 #endif
  279         frauth_t auth, *au = &auth;
  280         frauthent_t *fae, **faep;
  281         int i, error = 0;
  282 
  283         switch (cmd)
  284         {
  285         case SIOCINIFR :
  286         case SIOCRMIFR :
  287         case SIOCADIFR :
  288                 error = EINVAL;
  289                 break;
  290         case SIOCINAFR :
  291         case SIOCRMAFR :
  292         case SIOCADAFR :
  293                 for (faep = &fae_list; (fae = *faep); )
  294                         if (&fae->fae_fr == fr)
  295                                 break;
  296                         else
  297                                 faep = &fae->fae_next;
  298                 if (cmd == SIOCRMAFR) {
  299                         if (!fae)
  300                                 error = ESRCH;
  301                         else {
  302                                 *faep = fae->fae_next;
  303                                 *frptr = fr->fr_next;
  304                                 KFREE(fae);
  305                         }
  306                 } else {
  307                         KMALLOC(fae, frauthent_t *, sizeof(*fae));
  308                         if (fae != NULL) {
  309                                 IRCOPY((char *)data, (char *)&fae->fae_fr,
  310                                        sizeof(fae->fae_fr));
  311                                 if (!fae->fae_age)
  312                                         fae->fae_age = fr_defaultauthage;
  313                                 fae->fae_fr.fr_hits = 0;
  314                                 fae->fae_fr.fr_next = *frptr;
  315                                 *frptr = &fae->fae_fr;
  316                                 fae->fae_next = *faep;
  317                                 *faep = fae;
  318                         } else
  319                                 error = ENOMEM;
  320                 }
  321                 break;
  322         case SIOCATHST:
  323                 IWCOPY((char *)&fr_authstats, data, sizeof(fr_authstats));
  324                 break;
  325         case SIOCAUTHW:
  326 fr_authioctlloop:
  327                 MUTEX_ENTER(&ipf_auth);
  328                 if ((fr_authnext != fr_authend) && fr_authpkts[fr_authnext]) {
  329                         IWCOPY((char *)&fr_auth[fr_authnext++], data,
  330                                sizeof(fr_info_t));
  331                         if (fr_authnext == FR_NUMAUTH)
  332                                 fr_authnext = 0;
  333                         MUTEX_EXIT(&ipf_auth);
  334                         return 0;
  335                 }
  336 #ifdef  _KERNEL
  337 # if    SOLARIS
  338                 if (!cv_wait_sig(&ipfauthwait, &ipf_auth)) {
  339                         mutex_exit(&ipf_auth);
  340                         return EINTR;
  341                 }
  342 # else
  343 #  ifdef linux
  344                 interruptible_sleep_on(&ipfauthwait);
  345                 if (current->signal & ~current->blocked)
  346                         error = -EINTR;
  347 #  else
  348                 error = SLEEP(&fr_authnext, "fr_authnext");
  349 # endif
  350 # endif
  351 #endif
  352                 MUTEX_EXIT(&ipf_auth);
  353                 if (!error)
  354                         goto fr_authioctlloop;
  355                 break;
  356         case SIOCAUTHR:
  357                 IRCOPY(data, (caddr_t)&auth, sizeof(auth));
  358                 MUTEX_ENTER(&ipf_auth);
  359                 i = au->fra_index;
  360                 if ((i < 0) || (i > FR_NUMAUTH) ||
  361                     (fr_auth[i].fra_info.fin_id != au->fra_info.fin_id)) {
  362                         MUTEX_EXIT(&ipf_auth);
  363                         return EINVAL;
  364                 }
  365                 m = fr_authpkts[i];
  366                 fr_auth[i].fra_index = -2;
  367                 fr_auth[i].fra_pass = au->fra_pass;
  368                 fr_authpkts[i] = NULL;
  369 #ifdef  _KERNEL
  370                 MUTEX_EXIT(&ipf_auth);
  371                 SPL_NET(s);
  372 # ifndef linux
  373                 if (m && au->fra_info.fin_out) {
  374 #  if SOLARIS
  375                         error = fr_qout(fr_auth[i].fra_q, m);
  376 #  else /* SOLARIS */
  377                         error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL);
  378 #  endif /* SOLARIS */
  379                         if (error)
  380                                 fr_authstats.fas_sendfail++;
  381                         else
  382                                 fr_authstats.fas_sendok++;
  383                 } else if (m) {
  384 # if SOLARIS
  385                         error = fr_qin(fr_auth[i].fra_q, m);
  386 # else /* SOLARIS */
  387                         ifq = &ipintrq;
  388                         if (IF_QFULL(ifq)) {
  389                                 IF_DROP(ifq);
  390                                 m_freem(m);
  391                                 error = ENOBUFS;
  392                         } else {
  393                                 IF_ENQUEUE(ifq, m);
  394                                 schednetisr(NETISR_IP);
  395                         }
  396 # endif /* SOLARIS */
  397                         if (error)
  398                                 fr_authstats.fas_quefail++;
  399                         else
  400                                 fr_authstats.fas_queok++;
  401                 } else
  402                         error = EINVAL;
  403 # endif
  404 # if SOLARIS
  405                 if (error)
  406                         error = EINVAL;
  407 # else
  408                 /*
  409                  * If we experience an error which will result in the packet
  410                  * not being processed, make sure we advance to the next one.
  411                  */ 
  412                 if (error == ENOBUFS) {
  413                         fr_authused--;
  414                         fr_auth[i].fra_index = -1;
  415                         fr_auth[i].fra_pass = 0;
  416                         if (i == fr_authstart) {
  417                                 while (fr_auth[i].fra_index == -1) {
  418                                         i++;
  419                                         if (i == FR_NUMAUTH)
  420                                                 i = 0;
  421                                         fr_authstart = i;
  422                                         if (i == fr_authend)
  423                                                 break;
  424                                 }
  425                                 if (fr_authstart == fr_authend) {
  426                                         fr_authnext = 0;
  427                                         fr_authstart = fr_authend = 0;
  428                                 }
  429                         }
  430                 }
  431 # endif
  432                 SPL_X(s);
  433 #endif /* _KERNEL */
  434                 break;
  435         default :
  436                 error = EINVAL;
  437                 break;
  438         }
  439         return error;
  440 }
  441 
  442 
  443 #ifdef  _KERNEL
  444 /*
  445  * Free all network buffer memory used to keep saved packets.
  446  */
  447 void fr_authunload()
  448 {
  449         register int i;
  450         register frauthent_t *fae, **faep;
  451         mb_t *m;
  452 
  453         MUTEX_ENTER(&ipf_auth);
  454         for (i = 0; i < FR_NUMAUTH; i++) {
  455                 if ((m = fr_authpkts[i])) {
  456                         FREE_MB_T(m);
  457                         fr_authpkts[i] = NULL;
  458                         fr_auth[i].fra_index = -1;
  459                 }
  460         }
  461 
  462 
  463         for (faep = &fae_list; (fae = *faep); ) {
  464                 *faep = fae->fae_next;
  465                 KFREE(fae);
  466         }
  467         MUTEX_EXIT(&ipf_auth);
  468 }
  469 
  470 
  471 /*
  472  * Slowly expire held auth records.  Timeouts are set
  473  * in expectation of this being called twice per second.
  474  */
  475 void fr_authexpire()
  476 {
  477         register int i;
  478         register frauth_t *fra;
  479         register frauthent_t *fae, **faep;
  480         mb_t *m;
  481 #if !SOLARIS
  482         int s;
  483 #endif
  484 
  485         SPL_NET(s);
  486         MUTEX_ENTER(&ipf_auth);
  487         for (i = 0, fra = fr_auth; i < FR_NUMAUTH; i++, fra++) {
  488                 if ((!--fra->fra_age) && (m = fr_authpkts[i])) {
  489                         FREE_MB_T(m);
  490                         fr_authpkts[i] = NULL;
  491                         fr_auth[i].fra_index = -1;
  492                         fr_authstats.fas_expire++;
  493                         fr_authused--;
  494                 }
  495         }
  496 
  497         for (faep = &fae_list; (fae = *faep); ) {
  498                 if (!--fra->fra_age) {
  499                         *faep = fae->fae_next;
  500                         KFREE(fae);
  501                         fr_authstats.fas_expire++;
  502                 } else
  503                         faep = &fae->fae_next;
  504         }
  505         MUTEX_EXIT(&ipf_auth);
  506         SPL_X(s);
  507 }
  508 #endif

Cache object: cdc681abb00a701074e3af11804290df


[ 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.