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_pool.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_pool.c,v 1.2.2.1 2004/08/13 03:55:47 jmc Exp $      */
    2 
    3 /*
    4  * Copyright (C) 1993-2001, 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/errno.h>
   18 #include <sys/types.h>
   19 #include <sys/param.h>
   20 #include <sys/file.h>
   21 #if !defined(_KERNEL) && !defined(__KERNEL__)
   22 # include <stdio.h>
   23 # include <stdlib.h>
   24 # include <string.h>
   25 # define _KERNEL
   26 # ifdef __OpenBSD__
   27 struct file;
   28 # endif
   29 # include <sys/uio.h>
   30 # undef _KERNEL
   31 #else
   32 # include <sys/systm.h>
   33 # if defined(NetBSD) && (__NetBSD_Version__ >= 104000000)
   34 #  include <sys/proc.h>
   35 # endif
   36 #endif
   37 #include <sys/time.h>
   38 #if !defined(linux)
   39 # include <sys/protosw.h>
   40 #endif
   41 #include <sys/socket.h>
   42 #if defined(_KERNEL) && (!defined(__SVR4) && !defined(__svr4__))
   43 # include <sys/mbuf.h>
   44 #endif
   45 #if defined(__SVR4) || defined(__svr4__)
   46 # include <sys/filio.h>
   47 # include <sys/byteorder.h>
   48 # ifdef _KERNEL
   49 #  include <sys/dditypes.h>
   50 # endif
   51 # include <sys/stream.h>
   52 # include <sys/kmem.h>
   53 #endif
   54 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
   55 # include <sys/malloc.h>
   56 #endif
   57 
   58 #if (defined(__osf__) || defined(__hpux) || defined(__sgi)) && defined(_KERNEL)
   59 # ifdef __osf__
   60 #  include <net/radix.h>
   61 # endif
   62 # include "radix_ipf_local.h"
   63 # define _RADIX_H_
   64 #endif
   65 #include <net/if.h>
   66 #include <netinet/in.h>
   67 
   68 #include "netinet/ip_compat.h"
   69 #include "netinet/ip_fil.h"
   70 #include "netinet/ip_pool.h"
   71 
   72 #if defined(IPFILTER_LOOKUP) && defined(_KERNEL) && \
   73       ((BSD >= 198911) && !defined(__osf__) && \
   74       !defined(__hpux) && !defined(__sgi))
   75 static int rn_freenode __P((struct radix_node *, void *));
   76 #endif
   77 
   78 /* END OF INCLUDES */
   79 
   80 #if !defined(lint)
   81 static const char sccsid[] = "@(#)ip_fil.c      2.41 6/5/96 (C) 1993-2000 Darren Reed";
   82 static const char rcsid[] = "@(#)Id: ip_pool.c,v 2.55.2.9 2004/06/13 23:45:18 darrenr Exp";
   83 #endif
   84 
   85 #ifdef IPFILTER_LOOKUP
   86 
   87 # ifndef RADIX_NODE_HEAD_LOCK
   88 #  define RADIX_NODE_HEAD_LOCK(x)       ;
   89 # endif
   90 # ifndef RADIX_NODE_HEAD_UNLOCK
   91 #  define RADIX_NODE_HEAD_UNLOCK(x)     ;
   92 # endif
   93 
   94 ip_pool_stat_t ipoolstat;
   95 ipfrwlock_t ip_poolrw;
   96 
   97 /*
   98  * Binary tree routines from Sedgewick and enhanced to do ranges of addresses.
   99  * NOTE: Insertion *MUST* be from greatest range to least for it to work!
  100  * These should be replaced, eventually, by something else - most notably a
  101  * interval searching method.  The important feature is to be able to find
  102  * the best match.
  103  *
  104  * So why not use a radix tree for this?  As the first line implies, it
  105  * has been written to work with a _range_ of addresses.  A range is not
  106  * necessarily a match with any given netmask so what we end up dealing
  107  * with is an interval tree.  Implementations of these are hard to find
  108  * and the one herein is far from bug free.
  109  *
  110  * Sigh, in the end I became convinced that the bugs the code contained did
  111  * not make it worthwhile not using radix trees.  For now the radix tree from
  112  * 4.4 BSD is used, but this is not viewed as a long term solution.
  113  */
  114 ip_pool_t *ip_pool_list[IPL_LOGSIZE] = { NULL, NULL, NULL, NULL,
  115                                          NULL, NULL, NULL, NULL };
  116 
  117 
  118 #ifdef TEST_POOL
  119 void treeprint __P((ip_pool_t *));
  120 
  121 int
  122 main(argc, argv)
  123         int argc;
  124         char *argv[];
  125 {
  126         addrfamily_t a, b;
  127         iplookupop_t op;
  128         ip_pool_t *ipo;
  129         i6addr_t ip;
  130 
  131         RWLOCK_INIT(&ip_poolrw, "poolrw");
  132         ip_pool_init();
  133 
  134         bzero((char *)&a, sizeof(a));
  135         bzero((char *)&b, sizeof(b));
  136         bzero((char *)&ip, sizeof(ip));
  137         bzero((char *)&op, sizeof(op));
  138         strlcpy(op.iplo_name, "", sizeof(op.iplo_name));
  139 
  140         if (ip_pool_create(&op) == 0)
  141                 ipo = ip_pool_find(0, "");
  142 
  143         a.adf_addr.in4.s_addr = 0x0a010203;
  144         b.adf_addr.in4.s_addr = 0xffffffff;
  145         ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
  146         ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
  147 
  148         a.adf_addr.in4.s_addr = 0x0a000000;
  149         b.adf_addr.in4.s_addr = 0xff000000;
  150         ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0);
  151         ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0);
  152 
  153         a.adf_addr.in4.s_addr = 0x0a010100;
  154         b.adf_addr.in4.s_addr = 0xffffff00;
  155         ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
  156         ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
  157 
  158         a.adf_addr.in4.s_addr = 0x0a010200;
  159         b.adf_addr.in4.s_addr = 0xffffff00;
  160         ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0);
  161         ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0);
  162 
  163         a.adf_addr.in4.s_addr = 0x0a010000;
  164         b.adf_addr.in4.s_addr = 0xffff0000;
  165         ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
  166         ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
  167 
  168         a.adf_addr.in4.s_addr = 0x0a01020f;
  169         b.adf_addr.in4.s_addr = 0xffffffff;
  170         ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
  171         ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
  172 #ifdef  DEBUG_POOL
  173 treeprint(ipo);
  174 #endif
  175         ip.in4.s_addr = 0x0a00aabb;
  176         printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
  177                 ip_pool_search(ipo, 4, &ip));
  178 
  179         ip.in4.s_addr = 0x0a000001;
  180         printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
  181                 ip_pool_search(ipo, 4, &ip));
  182 
  183         ip.in4.s_addr = 0x0a000101;
  184         printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
  185                 ip_pool_search(ipo, 4, &ip));
  186 
  187         ip.in4.s_addr = 0x0a010001;
  188         printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
  189                 ip_pool_search(ipo, 4, &ip));
  190 
  191         ip.in4.s_addr = 0x0a010101;
  192         printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
  193                 ip_pool_search(ipo, 4, &ip));
  194 
  195         ip.in4.s_addr = 0x0a010201;
  196         printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
  197                 ip_pool_search(ipo, 4, &ip));
  198 
  199         ip.in4.s_addr = 0x0a010203;
  200         printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
  201                 ip_pool_search(ipo, 4, &ip));
  202 
  203         ip.in4.s_addr = 0x0a01020f;
  204         printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
  205                 ip_pool_search(ipo, 4, &ip));
  206 
  207         ip.in4.s_addr = 0x0b00aabb;
  208         printf("search(%#x) = %d (-1)\n", ip.in4.s_addr,
  209                 ip_pool_search(ipo, 4, &ip));
  210 
  211 #ifdef  DEBUG_POOL
  212 treeprint(ipo);
  213 #endif
  214 
  215         ip_pool_fini();
  216 
  217         return 0;
  218 }
  219 
  220 
  221 void
  222 treeprint(ipo)
  223 ip_pool_t *ipo;
  224 {
  225         ip_pool_node_t *c;
  226 
  227         for (c = ipo->ipo_list; c != NULL; c = c->ipn_next)
  228                 printf("Node %p(%s) (%#x/%#x) = %d hits %lu\n",
  229                         c, c->ipn_name, c->ipn_addr.adf_addr.in4.s_addr,
  230                         c->ipn_mask.adf_addr.in4.s_addr,
  231                         c->ipn_info, c->ipn_hits);
  232 }
  233 #endif /* TEST_POOL */
  234 
  235 
  236 /* ------------------------------------------------------------------------ */
  237 /* Function:    ip_pool_init                                                */
  238 /* Returns:     int     - 0 = success, else error                           */
  239 /*                                                                          */
  240 /* Initialise the routing table data structures where required.             */
  241 /* ------------------------------------------------------------------------ */
  242 int ip_pool_init()
  243 {
  244 
  245         bzero((char *)&ipoolstat, sizeof(ipoolstat));
  246 
  247 #if (!defined(_KERNEL) || (BSD < 199306))
  248         rn_init();
  249 #endif
  250         return 0;
  251 }
  252 
  253 
  254 /* ------------------------------------------------------------------------ */
  255 /* Function:    ip_pool_fini                                                */
  256 /* Returns:     int     - 0 = success, else error                           */
  257 /* Locks:       WRITE(ipf_global)                                           */
  258 /*                                                                          */
  259 /* Clean up all the pool data structures allocated and call the cleanup     */
  260 /* function for the radix tree that supports the pools. ip_pool_destroy() is*/
  261 /* used to delete the pools one by one to ensure they're properly freed up. */
  262 /* ------------------------------------------------------------------------ */
  263 void ip_pool_fini()
  264 {
  265         ip_pool_t *p, *q;
  266         iplookupop_t op;
  267         int i;
  268 
  269         ASSERT(rw_read_locked(&ipf_global.ipf_lk) == 0);
  270 
  271         for (i = 0; i <= IPL_LOGMAX; i++) {
  272                 for (q = ip_pool_list[i]; (p = q) != NULL; ) {
  273                         op.iplo_unit = i;
  274                         (void)strncpy(op.iplo_name, p->ipo_name,
  275                                 sizeof(op.iplo_name));
  276                         q = p->ipo_next;
  277                         (void) ip_pool_destroy(&op);
  278                 }
  279         }
  280 
  281 #if (!defined(_KERNEL) || (BSD < 199306))
  282         rn_fini();
  283 #endif
  284 }
  285 
  286 
  287 /* ------------------------------------------------------------------------ */
  288 /* Function:    ip_pool_statistics                                          */
  289 /* Returns:     int     - 0 = success, else error                           */
  290 /* Parameters:  op(I)   - pointer to lookup operation arguments             */
  291 /*                                                                          */
  292 /* Copy the current statistics out into user space, collecting pool list    */
  293 /* pointers as appropriate for later use.                                   */
  294 /* ------------------------------------------------------------------------ */
  295 int ip_pool_statistics(op)
  296 iplookupop_t *op;
  297 {
  298         ip_pool_stat_t stats;
  299         int unit, i, err = 0;
  300 
  301         if (op->iplo_size != sizeof(ipoolstat))
  302                 return EINVAL;
  303 
  304         bcopy((char *)&ipoolstat, (char *)&stats, sizeof(stats));
  305         unit = op->iplo_unit;
  306         if (unit == IPL_LOGALL) {
  307                 for (i = 0; i < IPL_LOGSIZE; i++)
  308                         stats.ipls_list[i] = ip_pool_list[i];
  309         } else if (unit >= 0 && unit < IPL_LOGSIZE) {
  310                 stats.ipls_list[unit] = ip_pool_list[unit];
  311         } else
  312                 err = EINVAL;
  313         if (err == 0)
  314                 err = COPYOUT(&stats, op->iplo_struct, sizeof(stats));
  315         return err;
  316 }
  317 
  318 
  319 
  320 /* ------------------------------------------------------------------------ */
  321 /* Function:    ip_pool_find                                                */
  322 /* Returns:     int     - 0 = success, else error                           */
  323 /* Parameters:  ipo(I)  - pointer to the pool getting the new node.         */
  324 /*                                                                          */
  325 /* Find a matching pool inside the collection of pools for a particular     */
  326 /* device, indicated by the unit number.                                    */
  327 /* ------------------------------------------------------------------------ */
  328 void *ip_pool_find(unit, name)
  329 int unit;
  330 char *name;
  331 {
  332         ip_pool_t *p;
  333 
  334         for (p = ip_pool_list[unit]; p != NULL; p = p->ipo_next)
  335                 if (strcmp(p->ipo_name, name) == 0)
  336                         break;
  337         return p;
  338 }
  339 
  340 
  341 /* ------------------------------------------------------------------------ */
  342 /* Function:    ip_pool_findeq                                              */
  343 /* Returns:     int     - 0 = success, else error                           */
  344 /* Parameters:  ipo(I)  - pointer to the pool getting the new node.         */
  345 /*              addr(I) - pointer to address information to delete          */
  346 /*              mask(I) -                                                   */
  347 /*                                                                          */
  348 /* Searches for an exact match of an entry in the pool.                     */
  349 /* ------------------------------------------------------------------------ */
  350 ip_pool_node_t *ip_pool_findeq(ipo, addr, mask)
  351 ip_pool_t *ipo;
  352 addrfamily_t *addr, *mask;
  353 {
  354         struct radix_node *n;
  355 #ifdef USE_SPL
  356         int s;
  357 
  358         SPL_NET(s);
  359 #endif
  360         RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
  361         n = ipo->ipo_head->rnh_lookup(addr, mask, ipo->ipo_head);
  362         RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
  363         SPL_X(s);
  364         return (ip_pool_node_t *)n;
  365 }
  366 
  367 
  368 /* ------------------------------------------------------------------------ */
  369 /* Function:    ip_pool_search                                              */
  370 /* Returns:     int     - 0 == +ve match, -1 == error, 1 == -ve match       */
  371 /* Parameters:  tptr(I)    - pointer to the pool to search                  */
  372 /*              version(I) - IP protocol version (4 or 6)                   */
  373 /*              dptr(I)    - pointer to address information                 */
  374 /*                                                                          */
  375 /* Search the pool for a given address and return a search result.          */
  376 /* ------------------------------------------------------------------------ */
  377 int ip_pool_search(tptr, version, dptr)
  378 void *tptr;
  379 int version;
  380 void *dptr;
  381 {
  382         struct radix_node *rn;
  383         ip_pool_node_t *m;
  384         i6addr_t *addr;
  385         addrfamily_t v;
  386         ip_pool_t *ipo;
  387         int rv;
  388 
  389         ipo = tptr;
  390         if (ipo == NULL)
  391                 return -1;
  392 
  393         rv = -1;
  394         m = NULL;
  395         addr = (i6addr_t *)dptr;
  396         bzero(&v, sizeof(v));
  397         v.adf_len = offsetof(addrfamily_t, adf_addr);
  398 
  399         if (version == 4) {
  400                 v.adf_len += sizeof(addr->in4);
  401                 v.adf_addr.in4 = addr->in4;
  402 #ifdef USE_INET6
  403         } else if (version == 6) {
  404                 v.adf_len += sizeof(addr->in6);
  405                 v.adf_addr.in6 = addr->in6;
  406 #endif
  407         } else
  408                 return -1;
  409 
  410         READ_ENTER(&ip_poolrw);
  411 
  412         RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
  413         rn = ipo->ipo_head->rnh_matchaddr(&v, ipo->ipo_head);
  414         RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
  415 
  416         if ((rn != NULL) && ((rn->rn_flags & RNF_ROOT) == 0)) {
  417                 m = (ip_pool_node_t *)rn;
  418                 ipo->ipo_hits++;
  419                 m->ipn_hits++;
  420                 rv = m->ipn_info;
  421         }
  422         RWLOCK_EXIT(&ip_poolrw);
  423         return rv;
  424 }
  425 
  426 
  427 /* ------------------------------------------------------------------------ */
  428 /* Function:    ip_pool_insert                                              */
  429 /* Returns:     int     - 0 = success, else error                           */
  430 /* Parameters:  ipo(I)  - pointer to the pool getting the new node.         */
  431 /*              addr(I) - address being added as a node                     */
  432 /*              mask(I) - netmask to with the node being added              */
  433 /*              info(I) - extra information to store in this node.          */
  434 /* Locks:       WRITE(ip_poolrw)                                            */
  435 /*                                                                          */
  436 /* Add another node to the pool given by ipo.  The three parameters passed  */
  437 /* in (addr, mask, info) shold all be stored in the node.                   */
  438 /* ------------------------------------------------------------------------ */
  439 int ip_pool_insert(ipo, addr, mask, info)
  440 ip_pool_t *ipo;
  441 i6addr_t *addr, *mask;
  442 int info;
  443 {
  444         struct radix_node *rn;
  445         ip_pool_node_t *x;
  446 
  447         ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0);
  448 
  449         KMALLOC(x, ip_pool_node_t *);
  450         if (x == NULL) {
  451                 return ENOMEM;
  452         }
  453 
  454         bzero(x, sizeof(*x));
  455 
  456         x->ipn_info = info;
  457         (void)strncpy(x->ipn_name, ipo->ipo_name, sizeof(x->ipn_name));
  458 
  459         bcopy(addr, &x->ipn_addr.adf_addr, sizeof(*addr));
  460         x->ipn_addr.adf_len = sizeof(x->ipn_addr);
  461         bcopy(mask, &x->ipn_mask.adf_addr, sizeof(*mask));
  462         x->ipn_mask.adf_len = sizeof(x->ipn_mask);
  463 
  464         RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
  465         rn = ipo->ipo_head->rnh_addaddr(&x->ipn_addr, &x->ipn_mask,
  466                                         ipo->ipo_head, x->ipn_nodes);
  467         RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
  468 #ifdef  DEBUG_POOL
  469         printf("Added %p at %p\n", x, rn);
  470 #endif
  471 
  472         if (rn == NULL) {
  473                 KFREE(x);
  474                 return ENOMEM;
  475         }
  476 
  477         x->ipn_next = ipo->ipo_list;
  478         x->ipn_pnext = &ipo->ipo_list;
  479         if (ipo->ipo_list != NULL)
  480                 ipo->ipo_list->ipn_pnext = &x->ipn_next;
  481         ipo->ipo_list = x;
  482 
  483         ipoolstat.ipls_nodes++;
  484 
  485         return 0;
  486 }
  487 
  488 
  489 /* ------------------------------------------------------------------------ */
  490 /* Function:    ip_pool_create                                              */
  491 /* Returns:     int     - 0 = success, else error                           */
  492 /* Parameters:  op(I) - pointer to iplookup struct with call details        */
  493 /* Locks:       WRITE(ip_poolrw)                                            */
  494 /*                                                                          */
  495 /* Creates a new group according to the paramters passed in via the         */
  496 /* iplookupop structure.  Does not check to see if the group already exists */
  497 /* when being inserted - assume this has already been done.  If the pool is */
  498 /* marked as being anonymous, give it a new, unique, identifier.  Call any  */
  499 /* other functions required to initialise the structure.                    */
  500 /* ------------------------------------------------------------------------ */
  501 int ip_pool_create(op)
  502 iplookupop_t *op;
  503 {
  504         char name[FR_GROUPLEN];
  505         int poolnum, unit;
  506         ip_pool_t *h;
  507 
  508         ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0);
  509 
  510         KMALLOC(h, ip_pool_t *);
  511         if (h == NULL)
  512                 return ENOMEM;
  513         bzero(h, sizeof(*h));
  514 
  515         if (rn_inithead((void **)&h->ipo_head,
  516                         offsetof(addrfamily_t, adf_addr) << 3) == 0) {
  517                 KFREE(h);
  518                 return ENOMEM;
  519         }
  520 
  521         unit = op->iplo_unit;
  522 
  523         if ((op->iplo_arg & IPOOL_ANON) != 0) {
  524                 ip_pool_t *p;
  525 
  526                 poolnum = IPOOL_ANON;
  527 
  528 #if defined(SNPRINTF) && defined(_KERNEL)
  529                 SNPRINTF(name, sizeof(name), "%x", poolnum);
  530 #else
  531                 (void)sprintf(name, "%x", poolnum);
  532 #endif
  533 
  534                 for (p = ip_pool_list[unit]; p != NULL; ) {
  535                         if (strcmp(name, p->ipo_name) == 0) {
  536                                 poolnum++;
  537 #if defined(SNPRINTF) && defined(_KERNEL)
  538                                 SNPRINTF(name, sizeof(name), "%x", poolnum);
  539 #else
  540                                 (void)sprintf(name, "%x", poolnum);
  541 #endif
  542                                 p = ip_pool_list[unit];
  543                         } else
  544                                 p = p->ipo_next;
  545                 }
  546 
  547                 (void)strncpy(h->ipo_name, name, sizeof(h->ipo_name));
  548         } else {
  549                 (void) strncpy(h->ipo_name, op->iplo_name, sizeof(h->ipo_name));
  550         }
  551 
  552         h->ipo_ref = 1;
  553         h->ipo_list = NULL;
  554         h->ipo_unit = unit;
  555         h->ipo_next = ip_pool_list[unit];
  556         if (ip_pool_list[unit] != NULL)
  557                 ip_pool_list[unit]->ipo_pnext = &h->ipo_next;
  558         h->ipo_pnext = &ip_pool_list[unit];
  559         ip_pool_list[unit] = h;
  560 
  561         ipoolstat.ipls_pools++;
  562 
  563         return 0;
  564 }
  565 
  566 
  567 /* ------------------------------------------------------------------------ */
  568 /* Function:    ip_pool_remove                                              */
  569 /* Returns:     int    - 0 = success, else error                            */
  570 /* Parameters:  ipo(I) - pointer to the pool to remove the node from.       */
  571 /*              ipe(I) - address being deleted as a node                    */
  572 /* Locks:       WRITE(ip_poolrw)                                            */
  573 /*                                                                          */
  574 /* Add another node to the pool given by ipo.  The three parameters passed  */
  575 /* in (addr, mask, info) shold all be stored in the node.                   */
  576 /* ------------------------------------------------------------------------ */
  577 int ip_pool_remove(ipo, ipe)
  578 ip_pool_t *ipo;
  579 ip_pool_node_t *ipe;
  580 {
  581         ip_pool_node_t **ipp, *n;
  582 
  583         ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0);
  584 
  585         for (ipp = &ipo->ipo_list; (n = *ipp) != NULL; ipp = &n->ipn_next) {
  586                 if (ipe == n) {
  587                         *n->ipn_pnext = n->ipn_next;
  588                         if (n->ipn_next)
  589                                 n->ipn_next->ipn_pnext = n->ipn_pnext;
  590                         break;
  591                 }
  592         }
  593 
  594         if (n == NULL)
  595                 return ENOENT;
  596 
  597         RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
  598         ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask,
  599                                    ipo->ipo_head);
  600         RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
  601         KFREE(n);
  602 
  603         ipoolstat.ipls_nodes--;
  604 
  605         return 0;
  606 }
  607 
  608 
  609 /* ------------------------------------------------------------------------ */
  610 /* Function:    ip_pool_destroy                                             */
  611 /* Returns:     int    - 0 = success, else error                            */
  612 /* Parameters:  op(I)  -  information about the pool to remove              */
  613 /* Locks:       WRITE(ip_poolrw) or WRITE(ipf_global)                       */
  614 /*                                                                          */
  615 /* Search for a pool using paramters passed in and if it's not otherwise    */
  616 /* busy, free it.                                                           */
  617 /*                                                                          */
  618 /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */
  619 /* may not be initialised, we can't use an ASSERT to enforce the locking    */
  620 /* assertion that one of the two (ip_poolrw,ipf_global) is held.            */
  621 /* ------------------------------------------------------------------------ */
  622 int ip_pool_destroy(op)
  623 iplookupop_t *op;
  624 {
  625         ip_pool_t *ipo;
  626 
  627         ipo = ip_pool_find(op->iplo_unit, op->iplo_name);
  628         if (ipo == NULL)
  629                 return ESRCH;
  630 
  631         if (ipo->ipo_ref != 1)
  632                 return EBUSY;
  633 
  634         ip_pool_free(ipo);
  635         return 0;
  636 }
  637 
  638 
  639 /* ------------------------------------------------------------------------ */
  640 /* Function:    ip_pool_flush                                               */
  641 /* Returns:     int    - number of pools deleted                            */
  642 /* Parameters:  fp(I)  - which pool(s) to flush                             */
  643 /* Locks:       WRITE(ip_poolrw) or WRITE(ipf_global)                       */
  644 /*                                                                          */
  645 /* Free all pools associated with the device that matches the unit number   */
  646 /* passed in with operation.                                                */
  647 /*                                                                          */
  648 /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */
  649 /* may not be initialised, we can't use an ASSERT to enforce the locking    */
  650 /* assertion that one of the two (ip_poolrw,ipf_global) is held.            */
  651 /* ------------------------------------------------------------------------ */
  652 int ip_pool_flush(fp)
  653 iplookupflush_t *fp;
  654 {
  655         int i, num = 0, unit, err;
  656         ip_pool_t *p, *q;
  657         iplookupop_t op;
  658 
  659         unit = fp->iplf_unit;
  660 
  661         for (i = 0; i <= IPL_LOGMAX; i++) {
  662                 if (unit != IPLT_ALL && i != unit)
  663                         continue;
  664                 for (q = ip_pool_list[i]; (p = q) != NULL; ) {
  665                         op.iplo_unit = i;
  666                         (void)strncpy(op.iplo_name, p->ipo_name,
  667                                 sizeof(op.iplo_name));
  668                         q = p->ipo_next;
  669                         err = ip_pool_destroy(&op);
  670                         if (err == 0)
  671                                 num++;
  672                         else
  673                                 break;
  674                 }
  675         }
  676         return num;
  677 }
  678 
  679 
  680 /* ------------------------------------------------------------------------ */
  681 /* Function:    ip_pool_free                                                */
  682 /* Returns:     void                                                        */
  683 /* Parameters:  ipo(I) -  pointer to pool structure                         */
  684 /* Locks:       WRITE(ip_poolrw) or WRITE(ipf_global)                       */
  685 /*                                                                          */
  686 /* Deletes the pool strucutre passed in from the list of pools and deletes  */
  687 /* all of the address information stored in it, including any tree data     */
  688 /* structures also allocated.                                               */
  689 /*                                                                          */
  690 /* NOTE: Because this function is called out of ipldetach() where ip_poolrw */
  691 /* may not be initialised, we can't use an ASSERT to enforce the locking    */
  692 /* assertion that one of the two (ip_poolrw,ipf_global) is held.            */
  693 /* ------------------------------------------------------------------------ */
  694 void ip_pool_free(ipo)
  695 ip_pool_t *ipo;
  696 {
  697         ip_pool_node_t *n;
  698 
  699         RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
  700         while ((n = ipo->ipo_list) != NULL) {
  701                 ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask,
  702                                            ipo->ipo_head);
  703 
  704                 *n->ipn_pnext = n->ipn_next;
  705                 if (n->ipn_next)
  706                         n->ipn_next->ipn_pnext = n->ipn_pnext;
  707 
  708                 KFREE(n);
  709 
  710                 ipoolstat.ipls_nodes--;
  711         }
  712         RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
  713 
  714         ipo->ipo_list = NULL;
  715         if (ipo->ipo_next != NULL)
  716                 ipo->ipo_next->ipo_pnext = ipo->ipo_pnext;
  717         *ipo->ipo_pnext = ipo->ipo_next;
  718         rn_freehead(ipo->ipo_head);
  719         KFREE(ipo);
  720 
  721         ipoolstat.ipls_pools--;
  722 }
  723 
  724 
  725 /* ------------------------------------------------------------------------ */
  726 /* Function:    ip_pool_deref                                               */
  727 /* Returns:     void                                                        */
  728 /* Parameters:  ipo(I) -  pointer to pool structure                         */
  729 /* Locks:       WRITE(ip_poolrw)                                            */
  730 /*                                                                          */
  731 /* Drop the number of known references to this pool structure by one and if */
  732 /* we arrive at zero known references, free it.                             */
  733 /* ------------------------------------------------------------------------ */
  734 void ip_pool_deref(ipo)
  735 ip_pool_t *ipo;
  736 {
  737 
  738         ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0);
  739 
  740         ipo->ipo_ref--;
  741         if (ipo->ipo_ref == 0)
  742                 ip_pool_free(ipo);
  743 }
  744 
  745 
  746 # if defined(_KERNEL) && ((BSD >= 198911) && !defined(__osf__) && \
  747       !defined(__hpux) && !defined(__sgi))
  748 static int
  749 rn_freenode(struct radix_node *n, void *p)
  750 {
  751         struct radix_node_head *rnh = p;
  752         struct radix_node *d;
  753 
  754         d = rnh->rnh_deladdr(n->rn_key, NULL, rnh);
  755         if (d != NULL) {
  756                 FreeS(d, max_keylen + 2 * sizeof (*d));
  757         }
  758         return 0;
  759 }
  760 
  761 
  762 void
  763 rn_freehead(rnh)
  764       struct radix_node_head *rnh;
  765 {
  766 
  767         RADIX_NODE_HEAD_LOCK(rnh);
  768         (*rnh->rnh_walktree)(rnh, rn_freenode, rnh);
  769 
  770         rnh->rnh_addaddr = NULL;
  771         rnh->rnh_deladdr = NULL;
  772         rnh->rnh_matchaddr = NULL;
  773         rnh->rnh_lookup = NULL;
  774         rnh->rnh_walktree = NULL;
  775         RADIX_NODE_HEAD_UNLOCK(rnh);
  776 
  777         Free(rnh);
  778 }
  779 # endif
  780 
  781 #endif /* IPFILTER_LOOKUP */

Cache object: 416097a7d62c85c0d18720dff1959aad


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