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_lookup.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_lookup.c,v 1.1.1.1.2.2 2004/08/13 03:55:35 jmc Exp $        */
    2 
    3 /*
    4  * Copyright (C) 2002-2003 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 #if defined(__osf__)
   15 # define _PROTO_NET_H_
   16 #endif
   17 #include <sys/param.h>
   18 #include <sys/errno.h>
   19 #include <sys/types.h>
   20 #include <sys/time.h>
   21 #include <sys/file.h>
   22 #if __FreeBSD_version >= 220000 && defined(_KERNEL)
   23 # include <sys/fcntl.h>
   24 # include <sys/filio.h>
   25 #else
   26 # include <sys/ioctl.h>
   27 #endif
   28 #if !defined(_KERNEL)
   29 # include <string.h>
   30 # define _KERNEL
   31 # ifdef __OpenBSD__
   32 struct file;
   33 # endif
   34 # include <sys/uio.h>
   35 # undef _KERNEL
   36 #endif
   37 #include <sys/socket.h>
   38 #if (defined(__osf__) || defined(__hpux) || defined(__sgi)) && defined(_KERNEL)
   39 # ifdef __osf__
   40 #  include <net/radix.h>
   41 # endif
   42 # include "radix_ipf_local.h"
   43 # define _RADIX_H_
   44 #endif
   45 #include <net/if.h>
   46 #if defined(__FreeBSD__)
   47 #  include <sys/cdefs.h>
   48 #  include <sys/proc.h>
   49 #endif
   50 #if defined(_KERNEL)
   51 # include <sys/systm.h>
   52 # if !defined(__SVR4) && !defined(__svr4__)
   53 #  include <sys/mbuf.h>
   54 # endif
   55 #endif
   56 #include <netinet/in.h>
   57 
   58 #include "netinet/ip_compat.h"
   59 #include "netinet/ip_fil.h"
   60 #include "netinet/ip_pool.h"
   61 #include "netinet/ip_htable.h"
   62 #include "netinet/ip_lookup.h"
   63 /* END OF INCLUDES */
   64 
   65 #if !defined(lint)
   66 static const char rcsid[] = "@(#)Id: ip_lookup.c,v 2.35.2.5 2004/07/06 11:16:25 darrenr Exp";
   67 #endif
   68 
   69 #ifdef  IPFILTER_LOOKUP
   70 int     ip_lookup_inited = 0;
   71 
   72 static int iplookup_addnode __P((caddr_t));
   73 static int iplookup_delnode __P((caddr_t data));
   74 static int iplookup_addtable __P((caddr_t));
   75 static int iplookup_deltable __P((caddr_t));
   76 static int iplookup_stats __P((caddr_t));
   77 static int iplookup_flush __P((caddr_t));
   78 
   79 
   80 /* ------------------------------------------------------------------------ */
   81 /* Function:    iplookup_init                                               */
   82 /* Returns:     int     - 0 = success, else error                           */
   83 /* Parameters:  Nil                                                         */
   84 /*                                                                          */
   85 /* Initialise all of the subcomponents of the lookup infrstructure.         */
   86 /* ------------------------------------------------------------------------ */
   87 int ip_lookup_init()
   88 {
   89 
   90         if (ip_pool_init() == -1)
   91                 return -1;
   92 
   93         RWLOCK_INIT(&ip_poolrw, "ip pool rwlock");
   94 
   95         ip_lookup_inited = 1;
   96 
   97         return 0;
   98 }
   99 
  100 
  101 /* ------------------------------------------------------------------------ */
  102 /* Function:    iplookup_unload                                             */
  103 /* Returns:     int     - 0 = success, else error                           */
  104 /* Parameters:  Nil                                                         */
  105 /*                                                                          */
  106 /* Free up all pool related memory that has been allocated whilst IPFilter  */
  107 /* has been running.  Also, do any other deinitialisation required such     */
  108 /* ip_lookup_init() can be called again, safely.                            */
  109 /* ------------------------------------------------------------------------ */
  110 void ip_lookup_unload()
  111 {
  112         ip_pool_fini();
  113         fr_htable_unload();
  114 
  115         if (ip_lookup_inited == 1) {
  116                 RW_DESTROY(&ip_poolrw);
  117                 ip_lookup_inited = 0;
  118         }
  119 }
  120 
  121 
  122 /* ------------------------------------------------------------------------ */
  123 /* Function:    iplookup_ioctl                                              */
  124 /* Returns:     int      - 0 = success, else error                          */
  125 /* Parameters:  data(IO) - pointer to ioctl data to be copied to/from user  */
  126 /*                         space.                                           */
  127 /*              cmd(I)   - ioctl command number                             */
  128 /*              mode(I)  - file mode bits used with open                    */
  129 /*                                                                          */
  130 /* Handle ioctl commands sent to the ioctl device.  For the most part, this */
  131 /* involves just calling another function to handle the specifics of each   */
  132 /* command.                                                                 */
  133 /* ------------------------------------------------------------------------ */
  134 int ip_lookup_ioctl(data, cmd, mode)
  135 caddr_t data;
  136 ioctlcmd_t cmd;
  137 int mode;
  138 {
  139         int err;
  140 # if defined(_KERNEL) && !defined(MENTAT) && defined(USE_SPL)
  141         int s;
  142 # endif
  143 
  144         mode = mode;    /* LINT */
  145 
  146         SPL_NET(s);
  147 
  148         switch (cmd)
  149         {
  150         case SIOCLOOKUPADDNODE :
  151         case SIOCLOOKUPADDNODEW :
  152                 WRITE_ENTER(&ip_poolrw);
  153                 err = iplookup_addnode(data);
  154                 RWLOCK_EXIT(&ip_poolrw);
  155                 break;
  156 
  157         case SIOCLOOKUPDELNODE :
  158         case SIOCLOOKUPDELNODEW :
  159                 WRITE_ENTER(&ip_poolrw);
  160                 err = iplookup_delnode(data);
  161                 RWLOCK_EXIT(&ip_poolrw);
  162                 break;
  163 
  164         case SIOCLOOKUPADDTABLE :
  165                 WRITE_ENTER(&ip_poolrw);
  166                 err = iplookup_addtable(data);
  167                 RWLOCK_EXIT(&ip_poolrw);
  168                 break;
  169 
  170         case SIOCLOOKUPDELTABLE :
  171                 WRITE_ENTER(&ip_poolrw);
  172                 err = iplookup_deltable(data);
  173                 RWLOCK_EXIT(&ip_poolrw);
  174                 break;
  175 
  176         case SIOCLOOKUPSTAT :
  177         case SIOCLOOKUPSTATW :
  178                 WRITE_ENTER(&ip_poolrw);
  179                 err = iplookup_stats(data);
  180                 RWLOCK_EXIT(&ip_poolrw);
  181                 break;
  182 
  183         case SIOCLOOKUPFLUSH :
  184                 WRITE_ENTER(&ip_poolrw);
  185                 err = iplookup_flush(data);
  186                 RWLOCK_EXIT(&ip_poolrw);
  187                 break;
  188 
  189         default :
  190                 err = EINVAL;
  191                 break;
  192         }
  193         SPL_X(s);
  194         return err;
  195 }
  196 
  197 
  198 /* ------------------------------------------------------------------------ */
  199 /* Function:    iplookup_addnode                                            */
  200 /* Returns:     int     - 0 = success, else error                           */
  201 /* Parameters:  data(I) - pointer to data from ioctl call                   */
  202 /*                                                                          */
  203 /* Add a new data node to a lookup structure.  First, check to see if the   */
  204 /* parent structure refered to by name exists and if it does, then go on to */
  205 /* add a node to it.                                                        */
  206 /* ------------------------------------------------------------------------ */
  207 static int iplookup_addnode(data)
  208 caddr_t data;
  209 {
  210         ip_pool_node_t node, *m;
  211         iplookupop_t op;
  212         iphtable_t *iph;
  213         iphtent_t hte;
  214         ip_pool_t *p;
  215         int err;
  216 
  217         err = 0;
  218         BCOPYIN(data, &op, sizeof(op));
  219         op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
  220 
  221         switch (op.iplo_type)
  222         {
  223         case IPLT_POOL :
  224                 if (op.iplo_size != sizeof(node))
  225                         return EINVAL;
  226 
  227                 err = COPYIN(op.iplo_struct, &node, sizeof(node));
  228                 if (err != 0)
  229                         return EFAULT;
  230 
  231                 p = ip_pool_find(op.iplo_unit, op.iplo_name);
  232                 if (p == NULL)
  233                         return ESRCH;
  234 
  235                 /*
  236                  * add an entry to a pool - return an error if it already
  237                  * exists remove an entry from a pool - if it exists
  238                  * - in both cases, the pool *must* exist!
  239                  */
  240                 m = ip_pool_findeq(p, &node.ipn_addr, &node.ipn_mask);
  241                 if (m)
  242                         return EEXIST;
  243                 err = ip_pool_insert(p, &node.ipn_addr.adf_addr,
  244                                      &node.ipn_mask.adf_addr, node.ipn_info);
  245                 break;
  246 
  247         case IPLT_HASH :
  248                 if (op.iplo_size != sizeof(hte))
  249                         return EINVAL;
  250 
  251                 err = COPYIN(op.iplo_struct, &hte, sizeof(hte));
  252                 if (err != 0)
  253                         return EFAULT;
  254 
  255                 iph = fr_findhtable(op.iplo_unit, op.iplo_name);
  256                 if (iph == NULL)
  257                         return ESRCH;
  258                 err = fr_addhtent(iph, &hte);
  259                 break;
  260 
  261         default :
  262                 err = EINVAL;
  263                 break;
  264         }
  265         return err;
  266 }
  267 
  268 
  269 /* ------------------------------------------------------------------------ */
  270 /* Function:    iplookup_delnode                                            */
  271 /* Returns:     int     - 0 = success, else error                           */
  272 /* Parameters:  data(I) - pointer to data from ioctl call                   */
  273 /*                                                                          */
  274 /* Delete a node from a lookup table by first looking for the table it is   */
  275 /* in and then deleting the entry that gets found.                          */
  276 /* ------------------------------------------------------------------------ */
  277 static int iplookup_delnode(data)
  278 caddr_t data;
  279 {
  280         ip_pool_node_t node, *m;
  281         iplookupop_t op;
  282         iphtable_t *iph;
  283         iphtent_t hte;
  284         ip_pool_t *p;
  285         int err;
  286 
  287         err = 0;
  288         BCOPYIN(data, &op, sizeof(op));
  289 
  290         op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
  291 
  292         switch (op.iplo_type)
  293         {
  294         case IPLT_POOL :
  295                 if (op.iplo_size != sizeof(node))
  296                         return EINVAL;
  297 
  298                 err = COPYIN(op.iplo_struct, &node, sizeof(node));
  299                 if (err != 0)
  300                         return EFAULT;
  301 
  302                 p = ip_pool_find(op.iplo_unit, op.iplo_name);
  303                 if (!p)
  304                         return ESRCH;
  305 
  306                 m = ip_pool_findeq(p, &node.ipn_addr, &node.ipn_mask);
  307                 if (m == NULL)
  308                         return ENOENT;
  309                 err = ip_pool_remove(p, m);
  310                 break;
  311 
  312         case IPLT_HASH :
  313                 if (op.iplo_size != sizeof(hte))
  314                         return EINVAL;
  315 
  316                 err = COPYIN(op.iplo_struct, &hte, sizeof(hte));
  317                 if (err != 0)
  318                         return EFAULT;
  319 
  320                 iph = fr_findhtable(op.iplo_unit, op.iplo_name);
  321                 if (iph == NULL)
  322                         return ESRCH;
  323                 err = fr_delhtent(iph, &hte);
  324                 break;
  325 
  326         default :
  327                 err = EINVAL;
  328                 break;
  329         }
  330         return err;
  331 }
  332 
  333 
  334 /* ------------------------------------------------------------------------ */
  335 /* Function:    iplookup_addtable                                           */
  336 /* Returns:     int     - 0 = success, else error                           */
  337 /* Parameters:  data(I) - pointer to data from ioctl call                   */
  338 /*                                                                          */
  339 /* Create a new lookup table, if one doesn't already exist using the name   */
  340 /* for this one.                                                            */
  341 /* ------------------------------------------------------------------------ */
  342 static int iplookup_addtable(data)
  343 caddr_t data;
  344 {
  345         iplookupop_t op;
  346         int err;
  347 
  348         err = 0;
  349         BCOPYIN(data, &op, sizeof(op));
  350 
  351         op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
  352 
  353         switch (op.iplo_type)
  354         {
  355         case IPLT_POOL :
  356                 if (ip_pool_find(op.iplo_unit, op.iplo_name) != NULL)
  357                         err = EEXIST;
  358                 else
  359                         err = ip_pool_create(&op);
  360                 break;
  361 
  362         case IPLT_HASH :
  363                 if (fr_findhtable(op.iplo_unit, op.iplo_name) != NULL)
  364                         err = EEXIST;
  365                 else
  366                         err = fr_newhtable(&op);
  367                 break;
  368 
  369         default :
  370                 err = EINVAL;
  371                 break;
  372         }
  373         return err;
  374 }
  375 
  376 
  377 /* ------------------------------------------------------------------------ */
  378 /* Function:    iplookup_deltable                                           */
  379 /* Returns:     int     - 0 = success, else error                           */
  380 /* Parameters:  data(I) - pointer to data from ioctl call                   */
  381 /*                                                                          */
  382 /* Decodes ioctl request to remove a particular hash table or pool and      */
  383 /* calls the relevant function to do the cleanup.                           */
  384 /* ------------------------------------------------------------------------ */
  385 static int iplookup_deltable(data)
  386 caddr_t data;
  387 {
  388         iplookupop_t op;
  389         int err;
  390 
  391         BCOPYIN(data, &op, sizeof(op));
  392         op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
  393 
  394         if (op.iplo_arg & IPLT_ANON)
  395                 op.iplo_arg &= IPLT_ANON;
  396 
  397         /*
  398          * create a new pool - fail if one already exists with
  399          * the same #
  400          */
  401         switch (op.iplo_type)
  402         {
  403         case IPLT_POOL :
  404                 err = ip_pool_destroy(&op);
  405                 break;
  406 
  407         case IPLT_HASH :
  408                 err = fr_removehtable(&op);
  409                 break;
  410 
  411         default :
  412                 err = EINVAL;
  413                 break;
  414         }
  415         return err;
  416 }
  417 
  418 
  419 /* ------------------------------------------------------------------------ */
  420 /* Function:    iplookup_stats                                              */
  421 /* Returns:     int     - 0 = success, else error                           */
  422 /* Parameters:  data(I) - pointer to data from ioctl call                   */
  423 /*                                                                          */
  424 /* Copy statistical information from inside the kernel back to user space.  */
  425 /* ------------------------------------------------------------------------ */
  426 static int iplookup_stats(data)
  427 caddr_t data;
  428 {
  429         iplookupop_t op;
  430         int err;
  431 
  432         err = 0;
  433         BCOPYIN(data, &op, sizeof(op));
  434 
  435         switch (op.iplo_type)
  436         {
  437         case IPLT_POOL :
  438                 err = ip_pool_statistics(&op);
  439                 break;
  440 
  441         case IPLT_HASH :
  442                 err = fr_gethtablestat(&op);
  443                 break;
  444 
  445         default :
  446                 err = EINVAL;
  447                 break;
  448         }
  449         return err;
  450 }
  451 
  452 
  453 /* ------------------------------------------------------------------------ */
  454 /* Function:    iplookup_flush                                              */
  455 /* Returns:     int     - 0 = success, else error                           */
  456 /* Parameters:  data(I) - pointer to data from ioctl call                   */
  457 /*                                                                          */
  458 /* A flush is called when we want to flush all the nodes from a particular  */
  459 /* entry in the hash table/pool or want to remove all groups from those.    */
  460 /* ------------------------------------------------------------------------ */
  461 static int iplookup_flush(data)
  462 caddr_t data;
  463 {
  464         int err, unit, num, type;
  465         iplookupflush_t flush;
  466 
  467         err = 0;
  468         BCOPYIN(data, &flush, sizeof(flush));
  469 
  470         flush.iplf_name[sizeof(flush.iplf_name) - 1] = '\0';
  471 
  472         unit = flush.iplf_unit;
  473         if ((unit < 0 || unit > IPL_LOGMAX) && (unit != IPLT_ALL))
  474                 return EINVAL;
  475 
  476         type = flush.iplf_type;
  477         err = EINVAL;
  478         num = 0;
  479 
  480         if (type == IPLT_POOL || type == IPLT_ALL) {
  481                 err = 0;
  482                 num = ip_pool_flush(&flush);
  483         }
  484 
  485         if (type == IPLT_HASH  || type == IPLT_ALL) {
  486                 err = 0;
  487                 num += fr_flushhtable(&flush);
  488         }
  489 
  490         if (err == 0) {
  491                 flush.iplf_count = num;
  492                 err = COPYOUT(&flush, data, sizeof(flush));
  493         }
  494         return err;
  495 }
  496 
  497 
  498 void ip_lookup_deref(type, ptr)
  499 int type;
  500 void *ptr;
  501 {
  502         if (ptr == NULL)
  503                 return;
  504 
  505         WRITE_ENTER(&ip_poolrw);
  506         switch (type)
  507         {
  508         case IPLT_POOL :
  509                 ip_pool_deref(ptr);
  510                 break;
  511 
  512         case IPLT_HASH :
  513                 fr_derefhtable(ptr);
  514                 break;
  515         }
  516         RWLOCK_EXIT(&ip_poolrw);
  517 }
  518 
  519 
  520 #else /* IPFILTER_LOOKUP */
  521 
  522 /*ARGSUSED*/
  523 int ip_lookup_ioctl(data, cmd, mode)
  524 caddr_t data;
  525 ioctlcmd_t cmd;
  526 int mode;
  527 {
  528         return EIO;
  529 }
  530 #endif /* IPFILTER_LOOKUP */

Cache object: df509aeb000f38d706f9059ef74deb43


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