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/netpfil/ipfilter/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 /* $FreeBSD$ */
    2 /*
    3  * Copyright (C) 2012 by Darren Reed.
    4  *
    5  * See the IPFILTER.LICENCE file for details on licencing.
    6  */
    7 #if defined(KERNEL) || defined(_KERNEL)
    8 # undef KERNEL
    9 # undef _KERNEL
   10 # define        KERNEL  1
   11 # define        _KERNEL 1
   12 #endif
   13 #include <sys/param.h>
   14 #include <sys/errno.h>
   15 #include <sys/types.h>
   16 #include <sys/time.h>
   17 #include <sys/file.h>
   18 #if defined(__FreeBSD__) && defined(_KERNEL)
   19 # include <sys/fcntl.h>
   20 # include <sys/filio.h>
   21 #else
   22 # include <sys/ioctl.h>
   23 #endif
   24 #if !defined(_KERNEL)
   25 # include <stdio.h>
   26 # include <string.h>
   27 # include <stdlib.h>
   28 # define _KERNEL
   29 # include <sys/uio.h>
   30 # undef _KERNEL
   31 #endif
   32 #include <sys/socket.h>
   33 #include <net/if.h>
   34 #if defined(__FreeBSD__)
   35 # include <sys/cdefs.h>
   36 # include <sys/proc.h>
   37 #endif
   38 #if defined(_KERNEL)
   39 # include <sys/systm.h>
   40 # if !defined(__SVR4)
   41 #  include <sys/mbuf.h>
   42 # endif
   43 #else
   44 # include "ipf.h"
   45 #endif
   46 #include <netinet/in.h>
   47 
   48 #include "netinet/ip_compat.h"
   49 #include "netinet/ip_fil.h"
   50 #include "netinet/ip_lookup.h"
   51 #include "netinet/ip_pool.h"
   52 #include "netinet/ip_htable.h"
   53 #include "netinet/ip_dstlist.h"
   54 /* END OF INCLUDES */
   55 
   56 #if !defined(lint)
   57 static const char rcsid[] = "@(#)$Id$";
   58 #endif
   59 
   60 /*
   61  * In this file, ip_pool.c, ip_htable.c and ip_dstlist.c, you will find the
   62  * range for unit is [-1,IPL_LOGMAX]. The -1 is considered to be a valid number
   63  * and represents a "wildcard" or "all" units (IPL_LOGALL). The reason for not
   64  * starting the numbering at 0 is because the numbers [0,IPL_LOGMAX] correspond
   65  * to the minor device number for their respective device. Thus where there is
   66  * array indexing on the unit, +1 is used to map [-1.IPL_LOGMAX] to
   67  * [0.POOL_LOOKUP_MAX].
   68  */
   69 static int ipf_lookup_addnode(ipf_main_softc_t *, caddr_t, int);
   70 static int ipf_lookup_delnode(ipf_main_softc_t *, caddr_t, int);
   71 static int ipf_lookup_addtable(ipf_main_softc_t *, caddr_t);
   72 static int ipf_lookup_deltable(ipf_main_softc_t *, caddr_t);
   73 static int ipf_lookup_stats(ipf_main_softc_t *, caddr_t);
   74 static int ipf_lookup_flush(ipf_main_softc_t *, caddr_t);
   75 static int ipf_lookup_iterate(ipf_main_softc_t *, void *, int, void *);
   76 static int ipf_lookup_deltok(ipf_main_softc_t *, void *, int, void *);
   77 
   78 #define MAX_BACKENDS    3
   79 static ipf_lookup_t *backends[MAX_BACKENDS] = {
   80         &ipf_pool_backend,
   81         &ipf_htable_backend,
   82         &ipf_dstlist_backend
   83 };
   84 
   85 
   86 typedef struct ipf_lookup_softc_s {
   87         void            *ipf_back[MAX_BACKENDS];
   88 } ipf_lookup_softc_t;
   89 
   90 
   91 /* ------------------------------------------------------------------------ */
   92 /* Function:    ipf_lookup_init                                             */
   93 /* Returns:     int      - 0 = success, else error                          */
   94 /* Parameters:  softc(I) - pointer to soft context main structure           */
   95 /*                                                                          */
   96 /* Initialise all of the subcomponents of the lookup infrstructure.         */
   97 /* ------------------------------------------------------------------------ */
   98 void *
   99 ipf_lookup_soft_create(ipf_main_softc_t *softc)
  100 {
  101         ipf_lookup_softc_t *softl;
  102         ipf_lookup_t **l;
  103         int i;
  104 
  105         KMALLOC(softl, ipf_lookup_softc_t *);
  106         if (softl == NULL)
  107                 return (NULL);
  108 
  109         bzero((char *)softl, sizeof(*softl));
  110 
  111         for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
  112                 softl->ipf_back[i] = (*(*l)->ipfl_create)(softc);
  113                 if (softl->ipf_back[i] == NULL) {
  114                         ipf_lookup_soft_destroy(softc, softl);
  115                         return (NULL);
  116                 }
  117         }
  118 
  119         return (softl);
  120 }
  121 
  122 
  123 /* ------------------------------------------------------------------------ */
  124 /* Function:    ipf_lookup_soft_init                                        */
  125 /* Returns:     int      - 0 = success, else error                          */
  126 /* Parameters:  softc(I) - pointer to soft context main structure           */
  127 /*              arg(I)   - pointer to local context to use                  */
  128 /*                                                                          */
  129 /* Initialise all of the subcomponents of the lookup infrstructure.         */
  130 /* ------------------------------------------------------------------------ */
  131 int
  132 ipf_lookup_soft_init(ipf_main_softc_t *softc, void *arg)
  133 {
  134         ipf_lookup_softc_t *softl = (ipf_lookup_softc_t *)arg;
  135         int err = 0;
  136         int i;
  137 
  138         for (i = 0; i < MAX_BACKENDS; i++) {
  139                 err = (*backends[i]->ipfl_init)(softc, softl->ipf_back[i]);
  140                 if (err != 0)
  141                         break;
  142         }
  143 
  144         return (err);
  145 }
  146 
  147 
  148 /* ------------------------------------------------------------------------ */
  149 /* Function:    ipf_lookup_soft_fini                                        */
  150 /* Returns:     int      - 0 = success, else error                          */
  151 /* Parameters:  softc(I) - pointer to soft context main structure           */
  152 /*              arg(I)   - pointer to local context to use                  */
  153 /*                                                                          */
  154 /* Call the fini function in each backend to cleanup all allocated data.    */
  155 /* ------------------------------------------------------------------------ */
  156 int
  157 ipf_lookup_soft_fini(ipf_main_softc_t *softc, void *arg)
  158 {
  159         ipf_lookup_softc_t *softl = (ipf_lookup_softc_t *)arg;
  160         int i;
  161 
  162         for (i = 0; i < MAX_BACKENDS; i++) {
  163                 if (softl->ipf_back[i] != NULL)
  164                         (*backends[i]->ipfl_fini)(softc,
  165                                                   softl->ipf_back[i]);
  166         }
  167 
  168         return (0);
  169 }
  170 
  171 
  172 /* ------------------------------------------------------------------------ */
  173 /* Function:    ipf_lookup_expire                                           */
  174 /* Returns:     Nil                                                         */
  175 /* Parameters:  softc(I) - pointer to soft context main structure           */
  176 /*                                                                          */
  177 /* Step through each of the backends and call their expire functions,       */
  178 /* allowing them to delete any lifetime limited data.                       */
  179 /* ------------------------------------------------------------------------ */
  180 void
  181 ipf_lookup_expire(ipf_main_softc_t *softc)
  182 {
  183         ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
  184         int i;
  185 
  186         WRITE_ENTER(&softc->ipf_poolrw);
  187         for (i = 0; i < MAX_BACKENDS; i++)
  188                 (*backends[i]->ipfl_expire)(softc, softl->ipf_back[i]);
  189         RWLOCK_EXIT(&softc->ipf_poolrw);
  190 }
  191 
  192 
  193 /* ------------------------------------------------------------------------ */
  194 /* Function:    ipf_lookup_softc_destroy                                    */
  195 /* Returns:     int     - 0 = success, else error                           */
  196 /* Parameters:  softc(I) - pointer to soft context main structure           */
  197 /*              arg(I)   - pointer to local context to use                  */
  198 /*                                                                          */
  199 /* Free up all pool related memory that has been allocated whilst IPFilter  */
  200 /* has been running.  Also, do any other deinitialisation required such     */
  201 /* ipf_lookup_init() can be called again, safely.                           */
  202 /* ------------------------------------------------------------------------ */
  203 void
  204 ipf_lookup_soft_destroy(ipf_main_softc_t *softc, void *arg)
  205 {
  206         ipf_lookup_softc_t *softl = (ipf_lookup_softc_t *)arg;
  207         int i;
  208 
  209         for (i = 0; i < MAX_BACKENDS; i++) {
  210                 if (softl->ipf_back[i] != NULL)
  211                         (*backends[i]->ipfl_destroy)(softc,
  212                                                      softl->ipf_back[i]);
  213         }
  214 
  215         KFREE(softl);
  216 }
  217 
  218 
  219 /* ------------------------------------------------------------------------ */
  220 /* Function:    ipf_lookup_ioctl                                            */
  221 /* Returns:     int      - 0 = success, else error                          */
  222 /* Parameters:  softc(I) - pointer to soft context main structure           */
  223 /*              arg(I)   - pointer to local context to use                  */
  224 /*              data(IO) - pointer to ioctl data to be copied to/from user  */
  225 /*                         space.                                           */
  226 /*              cmd(I)   - ioctl command number                             */
  227 /*              mode(I)  - file mode bits used with open                    */
  228 /*              uid(I)   - uid of process doing ioctl                       */
  229 /*              ctx(I)   - pointer that represents context for uid          */
  230 /*                                                                          */
  231 /* Handle ioctl commands sent to the ioctl device.  For the most part, this */
  232 /* involves just calling another function to handle the specifics of each   */
  233 /* command.                                                                 */
  234 /* ------------------------------------------------------------------------ */
  235 int
  236 ipf_lookup_ioctl(ipf_main_softc_t *softc, caddr_t data, ioctlcmd_t cmd,
  237         int mode, int uid, void *ctx)
  238 {
  239         int err;
  240         SPL_INT(s);
  241 
  242         mode = mode;    /* LINT */
  243 
  244         SPL_NET(s);
  245 
  246         switch (cmd)
  247         {
  248         case SIOCLOOKUPADDNODE :
  249         case SIOCLOOKUPADDNODEW :
  250                 WRITE_ENTER(&softc->ipf_poolrw);
  251                 err = ipf_lookup_addnode(softc, data, uid);
  252                 RWLOCK_EXIT(&softc->ipf_poolrw);
  253                 break;
  254 
  255         case SIOCLOOKUPDELNODE :
  256         case SIOCLOOKUPDELNODEW :
  257                 WRITE_ENTER(&softc->ipf_poolrw);
  258                 err = ipf_lookup_delnode(softc, data, uid);
  259                 RWLOCK_EXIT(&softc->ipf_poolrw);
  260                 break;
  261 
  262         case SIOCLOOKUPADDTABLE :
  263                 WRITE_ENTER(&softc->ipf_poolrw);
  264                 err = ipf_lookup_addtable(softc, data);
  265                 RWLOCK_EXIT(&softc->ipf_poolrw);
  266                 break;
  267 
  268         case SIOCLOOKUPDELTABLE :
  269                 WRITE_ENTER(&softc->ipf_poolrw);
  270                 err = ipf_lookup_deltable(softc, data);
  271                 RWLOCK_EXIT(&softc->ipf_poolrw);
  272                 break;
  273 
  274         case SIOCLOOKUPSTAT :
  275         case SIOCLOOKUPSTATW :
  276                 WRITE_ENTER(&softc->ipf_poolrw);
  277                 err = ipf_lookup_stats(softc, data);
  278                 RWLOCK_EXIT(&softc->ipf_poolrw);
  279                 break;
  280 
  281         case SIOCLOOKUPFLUSH :
  282                 WRITE_ENTER(&softc->ipf_poolrw);
  283                 err = ipf_lookup_flush(softc, data);
  284                 RWLOCK_EXIT(&softc->ipf_poolrw);
  285                 break;
  286 
  287         case SIOCLOOKUPITER :
  288                 err = ipf_lookup_iterate(softc, data, uid, ctx);
  289                 break;
  290 
  291         case SIOCIPFDELTOK :
  292                 err = ipf_lookup_deltok(softc, data, uid, ctx);
  293                 break;
  294 
  295         default :
  296                 IPFERROR(50001);
  297                 err = EINVAL;
  298                 break;
  299         }
  300         SPL_X(s);
  301         return (err);
  302 }
  303 
  304 
  305 /* ------------------------------------------------------------------------ */
  306 /* Function:    ipf_lookup_addnode                                          */
  307 /* Returns:     int     - 0 = success, else error                           */
  308 /* Parameters:  softc(I) - pointer to soft context main structure           */
  309 /*              data(I) - pointer to data from ioctl call                   */
  310 /*                                                                          */
  311 /* Add a new data node to a lookup structure.  First, check to see if the   */
  312 /* parent structure refered to by name exists and if it does, then go on to */
  313 /* add a node to it.                                                        */
  314 /* ------------------------------------------------------------------------ */
  315 static int
  316 ipf_lookup_addnode(ipf_main_softc_t *softc, caddr_t data, int uid)
  317 {
  318         ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
  319         iplookupop_t op;
  320         ipf_lookup_t **l;
  321         int err;
  322         int i;
  323 
  324         err = BCOPYIN(data, &op, sizeof(op));
  325         if (err != 0) {
  326                 IPFERROR(50002);
  327                 return (EFAULT);
  328         }
  329 
  330         if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) &&
  331             (op.iplo_unit != IPLT_ALL)) {
  332                 IPFERROR(50003);
  333                 return (EINVAL);
  334         }
  335 
  336         op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
  337 
  338         for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
  339                 if (op.iplo_type == (*l)->ipfl_type) {
  340                         err = (*(*l)->ipfl_node_add)(softc,
  341                                                      softl->ipf_back[i],
  342                                                      &op, uid);
  343                         break;
  344                 }
  345         }
  346 
  347         if (i == MAX_BACKENDS) {
  348                 IPFERROR(50012);
  349                 err = EINVAL;
  350         }
  351 
  352         return (err);
  353 }
  354 
  355 
  356 /* ------------------------------------------------------------------------ */
  357 /* Function:    ipf_lookup_delnode                                          */
  358 /* Returns:     int     - 0 = success, else error                           */
  359 /* Parameters:  softc(I) - pointer to soft context main structure           */
  360 /*              data(I) - pointer to data from ioctl call                   */
  361 /*                                                                          */
  362 /* Delete a node from a lookup table by first looking for the table it is   */
  363 /* in and then deleting the entry that gets found.                          */
  364 /* ------------------------------------------------------------------------ */
  365 static int
  366 ipf_lookup_delnode(ipf_main_softc_t *softc, caddr_t data, int uid)
  367 {
  368         ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
  369         iplookupop_t op;
  370         ipf_lookup_t **l;
  371         int err;
  372         int i;
  373 
  374         err = BCOPYIN(data, &op, sizeof(op));
  375         if (err != 0) {
  376                 IPFERROR(50042);
  377                 return (EFAULT);
  378         }
  379 
  380         if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) &&
  381             (op.iplo_unit != IPLT_ALL)) {
  382                 IPFERROR(50013);
  383                 return (EINVAL);
  384         }
  385 
  386         op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
  387 
  388         for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
  389                 if (op.iplo_type == (*l)->ipfl_type) {
  390                         err = (*(*l)->ipfl_node_del)(softc, softl->ipf_back[i],
  391                                                      &op, uid);
  392                         break;
  393                 }
  394         }
  395 
  396         if (i == MAX_BACKENDS) {
  397                 IPFERROR(50021);
  398                 err = EINVAL;
  399         }
  400         return (err);
  401 }
  402 
  403 
  404 /* ------------------------------------------------------------------------ */
  405 /* Function:    ipf_lookup_addtable                                         */
  406 /* Returns:     int     - 0 = success, else error                           */
  407 /* Parameters:  softc(I) - pointer to soft context main structure           */
  408 /*              data(I) - pointer to data from ioctl call                   */
  409 /*                                                                          */
  410 /* Create a new lookup table, if one doesn't already exist using the name   */
  411 /* for this one.                                                            */
  412 /* ------------------------------------------------------------------------ */
  413 static int
  414 ipf_lookup_addtable(ipf_main_softc_t *softc, caddr_t data)
  415 {
  416         ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
  417         iplookupop_t op;
  418         ipf_lookup_t **l;
  419         int err, i;
  420 
  421         err = BCOPYIN(data, &op, sizeof(op));
  422         if (err != 0) {
  423                 IPFERROR(50022);
  424                 return (EFAULT);
  425         }
  426 
  427         if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) &&
  428             (op.iplo_unit != IPLT_ALL)) {
  429                 IPFERROR(50023);
  430                 return (EINVAL);
  431         }
  432 
  433         op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
  434 
  435         for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
  436                 if (op.iplo_type == (*l)->ipfl_type) {
  437                         err = (*(*l)->ipfl_table_add)(softc,
  438                                                       softl->ipf_back[i],
  439                                                       &op);
  440                         break;
  441                 }
  442         }
  443 
  444         if (i == MAX_BACKENDS) {
  445                 IPFERROR(50026);
  446                 err = EINVAL;
  447         }
  448 
  449         /*
  450          * For anonymous pools, copy back the operation struct because in the
  451          * case of success it will contain the new table's name.
  452          */
  453         if ((err == 0) && ((op.iplo_arg & LOOKUP_ANON) != 0)) {
  454                 err = BCOPYOUT(&op, data, sizeof(op));
  455                 if (err != 0) {
  456                         IPFERROR(50027);
  457                         err = EFAULT;
  458                 }
  459         }
  460 
  461         return (err);
  462 }
  463 
  464 
  465 /* ------------------------------------------------------------------------ */
  466 /* Function:    ipf_lookup_deltable                                         */
  467 /* Returns:     int     - 0 = success, else error                           */
  468 /* Parameters:  softc(I) - pointer to soft context main structure           */
  469 /*              data(I) - pointer to data from ioctl call                   */
  470 /*                                                                          */
  471 /* Decodes ioctl request to remove a particular hash table or pool and      */
  472 /* calls the relevant function to do the cleanup.                           */
  473 /* ------------------------------------------------------------------------ */
  474 static int
  475 ipf_lookup_deltable(ipf_main_softc_t *softc, caddr_t data)
  476 {
  477         ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
  478         iplookupop_t op;
  479         ipf_lookup_t **l;
  480         int err, i;
  481 
  482         err = BCOPYIN(data, &op, sizeof(op));
  483         if (err != 0) {
  484                 IPFERROR(50028);
  485                 return (EFAULT);
  486         }
  487 
  488         if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) &&
  489             (op.iplo_unit != IPLT_ALL)) {
  490                 IPFERROR(50029);
  491                 return (EINVAL);
  492         }
  493 
  494         op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
  495 
  496         for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
  497                 if (op.iplo_type == (*l)->ipfl_type) {
  498                         err = (*(*l)->ipfl_table_del)(softc,
  499                                                       softl->ipf_back[i],
  500                                                       &op);
  501                         break;
  502                 }
  503         }
  504 
  505         if (i == MAX_BACKENDS) {
  506                 IPFERROR(50030);
  507                 err = EINVAL;
  508         }
  509         return (err);
  510 }
  511 
  512 
  513 /* ------------------------------------------------------------------------ */
  514 /* Function:    ipf_lookup_stats                                            */
  515 /* Returns:     int     - 0 = success, else error                           */
  516 /* Parameters:  softc(I) - pointer to soft context main structure           */
  517 /*              data(I) - pointer to data from ioctl call                   */
  518 /*                                                                          */
  519 /* Copy statistical information from inside the kernel back to user space.  */
  520 /* ------------------------------------------------------------------------ */
  521 static int
  522 ipf_lookup_stats(ipf_main_softc_t *softc, caddr_t data)
  523 {
  524         ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
  525         iplookupop_t op;
  526         ipf_lookup_t **l;
  527         int err;
  528         int i;
  529 
  530         err = BCOPYIN(data, &op, sizeof(op));
  531         if (err != 0) {
  532                 IPFERROR(50031);
  533                 return (EFAULT);
  534         }
  535 
  536         if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) &&
  537             (op.iplo_unit != IPLT_ALL)) {
  538                 IPFERROR(50032);
  539                 return (EINVAL);
  540         }
  541 
  542         for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
  543                 if (op.iplo_type == (*l)->ipfl_type) {
  544                         err = (*(*l)->ipfl_stats_get)(softc,
  545                                                       softl->ipf_back[i],
  546                                                       &op);
  547                         break;
  548                 }
  549         }
  550 
  551         if (i == MAX_BACKENDS) {
  552                 IPFERROR(50033);
  553                 err = EINVAL;
  554         }
  555 
  556         return (err);
  557 }
  558 
  559 
  560 /* ------------------------------------------------------------------------ */
  561 /* Function:    ipf_lookup_flush                                            */
  562 /* Returns:     int     - 0 = success, else error                           */
  563 /* Parameters:  softc(I) - pointer to soft context main structure           */
  564 /*              data(I) - pointer to data from ioctl call                   */
  565 /*                                                                          */
  566 /* A flush is called when we want to flush all the nodes from a particular  */
  567 /* entry in the hash table/pool or want to remove all groups from those.    */
  568 /* ------------------------------------------------------------------------ */
  569 static int
  570 ipf_lookup_flush(ipf_main_softc_t *softc, caddr_t data)
  571 {
  572         ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
  573         int err, unit, num, type, i;
  574         iplookupflush_t flush;
  575         ipf_lookup_t **l;
  576 
  577         err = BCOPYIN(data, &flush, sizeof(flush));
  578         if (err != 0) {
  579                 IPFERROR(50034);
  580                 return (EFAULT);
  581         }
  582 
  583         unit = flush.iplf_unit;
  584         if ((unit < 0 || unit > IPL_LOGMAX) && (unit != IPLT_ALL)) {
  585                 IPFERROR(50035);
  586                 return (EINVAL);
  587         }
  588 
  589         flush.iplf_name[sizeof(flush.iplf_name) - 1] = '\0';
  590 
  591         type = flush.iplf_type;
  592         IPFERROR(50036);
  593         err = EINVAL;
  594         num = 0;
  595 
  596         for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
  597                 if (type == (*l)->ipfl_type || type == IPLT_ALL) {
  598                         err = 0;
  599                         num += (*(*l)->ipfl_flush)(softc,
  600                                                    softl->ipf_back[i],
  601                                                    &flush);
  602                 }
  603         }
  604 
  605         if (err == 0) {
  606                 flush.iplf_count = num;
  607                 err = BCOPYOUT(&flush, data, sizeof(flush));
  608                 if (err != 0) {
  609                         IPFERROR(50037);
  610                         err = EFAULT;
  611                 }
  612         }
  613         return (err);
  614 }
  615 
  616 
  617 /* ------------------------------------------------------------------------ */
  618 /* Function:    ipf_lookup_delref                                           */
  619 /* Returns:     void                                                        */
  620 /* Parameters:  softc(I) - pointer to soft context main structure           */
  621 /*              type(I) - table type to operate on                          */
  622 /*              ptr(I)  - pointer to object to remove reference for         */
  623 /*                                                                          */
  624 /* This function organises calling the correct deref function for a given   */
  625 /* type of object being passed into it.                                     */
  626 /* ------------------------------------------------------------------------ */
  627 void
  628 ipf_lookup_deref(ipf_main_softc_t *softc, int type, void *ptr)
  629 {
  630         ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
  631         int i;
  632 
  633         if (ptr == NULL)
  634                 return;
  635 
  636         for (i = 0; i < MAX_BACKENDS; i++) {
  637                 if (type == backends[i]->ipfl_type) {
  638                         WRITE_ENTER(&softc->ipf_poolrw);
  639                         (*backends[i]->ipfl_table_deref)(softc,
  640                                                          softl->ipf_back[i],
  641                                                          ptr);
  642                         RWLOCK_EXIT(&softc->ipf_poolrw);
  643                         break;
  644                 }
  645         }
  646 }
  647 
  648 
  649 /* ------------------------------------------------------------------------ */
  650 /* Function:    ipf_lookup_iterate                                          */
  651 /* Returns:     int     - 0 = success, else error                           */
  652 /* Parameters:  softc(I) - pointer to soft context main structure           */
  653 /*              data(I) - pointer to data from ioctl call                   */
  654 /*              uid(I)  - uid of caller                                     */
  655 /*              ctx(I)  - pointer to give the uid context                   */
  656 /*                                                                          */
  657 /* Decodes ioctl request to step through either hash tables or pools.       */
  658 /* ------------------------------------------------------------------------ */
  659 static int
  660 ipf_lookup_iterate(ipf_main_softc_t *softc, void *data, int uid, void *ctx)
  661 {
  662         ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
  663         ipflookupiter_t iter;
  664         ipftoken_t *token;
  665         int err, i;
  666         SPL_INT(s);
  667 
  668         err = ipf_inobj(softc, data, NULL, &iter, IPFOBJ_LOOKUPITER);
  669         if (err != 0)
  670                 return (err);
  671 
  672         if (iter.ili_unit < IPL_LOGALL && iter.ili_unit > IPL_LOGMAX) {
  673                 IPFERROR(50038);
  674                 return (EINVAL);
  675         }
  676 
  677         if (iter.ili_ival != IPFGENITER_LOOKUP) {
  678                 IPFERROR(50039);
  679                 return (EINVAL);
  680         }
  681 
  682         SPL_SCHED(s);
  683         token = ipf_token_find(softc, iter.ili_key, uid, ctx);
  684         if (token == NULL) {
  685                 SPL_X(s);
  686                 IPFERROR(50040);
  687                 return (ESRCH);
  688         }
  689 
  690         for (i = 0; i < MAX_BACKENDS; i++) {
  691                 if (iter.ili_type == backends[i]->ipfl_type) {
  692                         err = (*backends[i]->ipfl_iter_next)(softc,
  693                                                              softl->ipf_back[i],
  694                                                              token, &iter);
  695                         break;
  696                 }
  697         }
  698         SPL_X(s);
  699 
  700         if (i == MAX_BACKENDS) {
  701                 IPFERROR(50041);
  702                 err = EINVAL;
  703         }
  704 
  705         WRITE_ENTER(&softc->ipf_tokens);
  706         ipf_token_deref(softc, token);
  707         RWLOCK_EXIT(&softc->ipf_tokens);
  708 
  709         return (err);
  710 }
  711 
  712 
  713 /* ------------------------------------------------------------------------ */
  714 /* Function:    ipf_lookup_iterderef                                        */
  715 /* Returns:     void                                                        */
  716 /* Parameters:  softc(I) - pointer to soft context main structure           */
  717 /*              type(I)  - backend type to iterate through                  */
  718 /*              data(I)  - pointer to data from ioctl call                  */
  719 /*                                                                          */
  720 /* Decodes ioctl request to remove a particular hash table or pool and      */
  721 /* calls the relevant function to do the cleanup.                           */
  722 /* Because each of the backend types has a different data structure,        */
  723 /* iteration is limited to one type at a time (i.e. it is not permitted to  */
  724 /* go on from pool types to hash types as part of the "get next".)          */
  725 /* ------------------------------------------------------------------------ */
  726 void
  727 ipf_lookup_iterderef(ipf_main_softc_t *softc, u_32_t type, void *data)
  728 {
  729         ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
  730         struct iplookupiterkey *lkey;
  731         iplookupiterkey_t key;
  732         int i;
  733 
  734         key.ilik_key = type;
  735         lkey = &key.ilik_unstr;
  736 
  737         if (lkey->ilik_ival != IPFGENITER_LOOKUP)
  738                 return;
  739 
  740         WRITE_ENTER(&softc->ipf_poolrw);
  741 
  742         for (i = 0; i < MAX_BACKENDS; i++) {
  743                 if (lkey->ilik_type == backends[i]->ipfl_type) {
  744                         (*backends[i]->ipfl_iter_deref)(softc,
  745                                                         softl->ipf_back[i],
  746                                                         lkey->ilik_otype,
  747                                                         lkey->ilik_unit,
  748                                                         data);
  749                         break;
  750                 }
  751         }
  752         RWLOCK_EXIT(&softc->ipf_poolrw);
  753 }
  754 
  755 
  756 /* ------------------------------------------------------------------------ */
  757 /* Function:    ipf_lookup_deltok                                           */
  758 /* Returns:     int     - 0 = success, else error                           */
  759 /* Parameters:  softc(I) - pointer to soft context main structure           */
  760 /*              data(I) - pointer to data from ioctl call                   */
  761 /*              uid(I)  - uid of caller                                     */
  762 /*              ctx(I)  - pointer to give the uid context                   */
  763 /*                                                                          */
  764 /* Deletes the token identified by the combination of (type,uid,ctx)        */
  765 /* "key" is a combination of the table type, iterator type and the unit for */
  766 /* which the token was being used.                                          */
  767 /* ------------------------------------------------------------------------ */
  768 int
  769 ipf_lookup_deltok(ipf_main_softc_t *softc, void *data, int uid, void *ctx)
  770 {
  771         int error, key;
  772         SPL_INT(s);
  773 
  774         SPL_SCHED(s);
  775         error = BCOPYIN(data, &key, sizeof(key));
  776         if (error == 0)
  777                 error = ipf_token_del(softc, key, uid, ctx);
  778         SPL_X(s);
  779         return (error);
  780 }
  781 
  782 
  783 /* ------------------------------------------------------------------------ */
  784 /* Function:    ipf_lookup_res_num                                          */
  785 /* Returns:     void * - NULL = failure, else success.                      */
  786 /* Parameters:  softc(I) - pointer to soft context main structure           */
  787 /*              unit(I)     - device for which this is for                  */
  788 /*              type(I)     - type of lookup these parameters are for.      */
  789 /*              number(I)   - table number to use when searching            */
  790 /*              funcptr(IO) - pointer to pointer for storing IP address     */
  791 /*                            searching function.                           */
  792 /*                                                                          */
  793 /* Search for the "table" number passed in amongst those configured for     */
  794 /* that particular type.  If the type is recognised then the function to    */
  795 /* call to do the IP address search will be change, regardless of whether   */
  796 /* or not the "table" number exists.                                        */
  797 /* ------------------------------------------------------------------------ */
  798 void *
  799 ipf_lookup_res_num(ipf_main_softc_t *softc, int unit, u_int type, u_int number,
  800         lookupfunc_t *funcptr)
  801 {
  802         char name[FR_GROUPLEN];
  803 
  804         (void) snprintf(name, sizeof(name), "%u", number);
  805 
  806         return (ipf_lookup_res_name(softc, unit, type, name, funcptr));
  807 }
  808 
  809 
  810 /* ------------------------------------------------------------------------ */
  811 /* Function:    ipf_lookup_res_name                                         */
  812 /* Returns:     void * - NULL = failure, else success.                      */
  813 /* Parameters:  softc(I) - pointer to soft context main structure           */
  814 /*              unit(I)     - device for which this is for                  */
  815 /*              type(I)     - type of lookup these parameters are for.      */
  816 /*              name(I)     - table name to use when searching              */
  817 /*              funcptr(IO) - pointer to pointer for storing IP address     */
  818 /*                            searching function.                           */
  819 /*                                                                          */
  820 /* Search for the "table" number passed in amongst those configured for     */
  821 /* that particular type.  If the type is recognised then the function to    */
  822 /* call to do the IP address search will be changed, regardless of whether  */
  823 /* or not the "table" number exists.                                        */
  824 /* ------------------------------------------------------------------------ */
  825 void *
  826 ipf_lookup_res_name(ipf_main_softc_t *softc, int unit, u_int type, char *name,
  827         lookupfunc_t *funcptr)
  828 {
  829         ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
  830         ipf_lookup_t **l;
  831         void *ptr = NULL;
  832         int i;
  833 
  834         READ_ENTER(&softc->ipf_poolrw);
  835 
  836         for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
  837                 if (type == (*l)->ipfl_type) {
  838                         ptr = (*(*l)->ipfl_select_add_ref)(softl->ipf_back[i],
  839                                                            unit, name);
  840                         if (ptr != NULL && funcptr != NULL) {
  841                                 *funcptr = (*l)->ipfl_addr_find;
  842                         }
  843                         break;
  844                 }
  845         }
  846 
  847         if (i == MAX_BACKENDS) {
  848                 ptr = NULL;
  849                 if (funcptr != NULL)
  850                         *funcptr = NULL;
  851         }
  852 
  853         RWLOCK_EXIT(&softc->ipf_poolrw);
  854 
  855         return (ptr);
  856 }
  857 
  858 
  859 /* ------------------------------------------------------------------------ */
  860 /* Function:    ipf_lookup_find_htable                                      */
  861 /* Returns:     void * - NULL = failure, else success.                      */
  862 /* Parameters:  softc(I) - pointer to soft context main structure           */
  863 /*              unit(I)     - device for which this is for                  */
  864 /*              name(I)     - table name to use when searching              */
  865 /*                                                                          */
  866 /* To support the group-map feature, where a hash table maps address        */
  867 /* networks to rule group numbers, we need to expose a function that uses   */
  868 /* only the hash table backend.                                             */
  869 /* ------------------------------------------------------------------------ */
  870 void *
  871 ipf_lookup_find_htable(ipf_main_softc_t *softc, int unit, char *name)
  872 {
  873         ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
  874         ipf_lookup_t **l;
  875         void *tab = NULL;
  876         int i;
  877 
  878         READ_ENTER(&softc->ipf_poolrw);
  879 
  880         for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++)
  881                 if (IPLT_HASH == (*l)->ipfl_type) {
  882                         tab = ipf_htable_find(softl->ipf_back[i], unit, name);
  883                         break;
  884                 }
  885 
  886         RWLOCK_EXIT(&softc->ipf_poolrw);
  887 
  888         return (tab);
  889 }
  890 
  891 
  892 /* ------------------------------------------------------------------------ */
  893 /* Function:    ipf_lookup_sync                                             */
  894 /* Returns:     void                                                        */
  895 /* Parameters:  softc(I) - pointer to soft context main structure           */
  896 /*                                                                          */
  897 /* This function is the interface that the machine dependent sync functions */
  898 /* call when a network interface name change occurs. It then calls the sync */
  899 /* functions of the lookup implementations - if they have one.              */
  900 /* ------------------------------------------------------------------------ */
  901 /*ARGSUSED*/
  902 void
  903 ipf_lookup_sync(ipf_main_softc_t *softc, void *ifp)
  904 {
  905         ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
  906         ipf_lookup_t **l;
  907         int i;
  908 
  909         READ_ENTER(&softc->ipf_poolrw);
  910 
  911         for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++)
  912                 if ((*l)->ipfl_sync != NULL)
  913                         (*(*l)->ipfl_sync)(softc, softl->ipf_back[i]);
  914 
  915         RWLOCK_EXIT(&softc->ipf_poolrw);
  916 }
  917 
  918 
  919 #ifndef _KERNEL
  920 void
  921 ipf_lookup_dump(ipf_main_softc_t *softc, void *arg)
  922 {
  923         ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
  924         ipf_lookup_t **l;
  925         int i;
  926 
  927         for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++)
  928                 if (IPLT_POOL == (*l)->ipfl_type) {
  929                         ipf_pool_dump(softc, softl->ipf_back[i]);
  930                         break;
  931                 }
  932 
  933         for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++)
  934                 if (IPLT_HASH == (*l)->ipfl_type) {
  935                         ipf_htable_dump(softc, softl->ipf_back[i]);
  936                         break;
  937                 }
  938 }
  939 #endif

Cache object: 05d203447fbbcba09f8523fc3acbf992


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