2 * Copyright (C) 1993-2001, 2003 by Darren Reed.
4 * See the IPFILTER.LICENCE file for details on licencing.
6 #if defined(KERNEL) || defined(_KERNEL)
13 # define _PROTO_NET_H_
15 #include <sys/errno.h>
16 #include <sys/types.h>
17 #include <sys/param.h>
19 #if !defined(_KERNEL) && !defined(__KERNEL__)
30 # include <sys/systm.h>
31 # if defined(NetBSD) && (__NetBSD_Version__ >= 104000000)
32 # include <sys/proc.h>
37 # include <sys/protosw.h>
39 #include <sys/socket.h>
40 #if defined(_KERNEL) && (!defined(__SVR4) && !defined(__svr4__))
41 # include <sys/mbuf.h>
43 #if defined(__SVR4) || defined(__svr4__)
44 # include <sys/filio.h>
45 # include <sys/byteorder.h>
47 # include <sys/dditypes.h>
49 # include <sys/stream.h>
50 # include <sys/kmem.h>
52 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
53 # include <sys/malloc.h>
56 #if defined(SOLARIS2) && !defined(_KERNEL)
57 # include "radix_ipf.h"
59 #if defined(_KERNEL) && (defined(__osf__) || defined(AIX) || \
60 defined(__hpux) || defined(__sgi))
61 # include "radix_ipf_local.h"
65 #include <netinet/in.h>
67 #include "netinet/ip_compat.h"
68 #include "netinet/ip_fil.h"
69 #include "netinet/ip_pool.h"
71 #if defined(IPFILTER_LOOKUP) && defined(_KERNEL) && \
72 ((BSD >= 198911) && !defined(__osf__) && \
73 !defined(__hpux) && !defined(__sgi))
74 static int rn_freenode __P((struct radix_node *, void *));
80 static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
81 static const char rcsid[] = "@(#)$Id: ip_pool.c,v 2.55.2.24 2007/10/10 09:45:37 darrenr Exp $";
84 #ifdef IPFILTER_LOOKUP
86 # if !defined(RADIX_NODE_HEAD_LOCK) || !defined(RADIX_NODE_HEAD_UNLOCK) || \
88 # undef RADIX_NODE_HEAD_LOCK
89 # undef RADIX_NODE_HEAD_UNLOCK
90 # define RADIX_NODE_HEAD_LOCK(x) ;
91 # define RADIX_NODE_HEAD_UNLOCK(x) ;
94 static void ip_pool_clearnodes __P((ip_pool_t *));
95 static void *ip_pool_exists __P((int, char *));
97 ip_pool_stat_t ipoolstat;
98 ipfrwlock_t ip_poolrw;
101 * Binary tree routines from Sedgewick and enhanced to do ranges of addresses.
102 * NOTE: Insertion *MUST* be from greatest range to least for it to work!
103 * These should be replaced, eventually, by something else - most notably a
104 * interval searching method. The important feature is to be able to find
107 * So why not use a radix tree for this? As the first line implies, it
108 * has been written to work with a _range_ of addresses. A range is not
109 * necessarily a match with any given netmask so what we end up dealing
110 * with is an interval tree. Implementations of these are hard to find
111 * and the one herein is far from bug free.
113 * Sigh, in the end I became convinced that the bugs the code contained did
114 * not make it worthwhile not using radix trees. For now the radix tree from
115 * 4.4 BSD is used, but this is not viewed as a long term solution.
117 ip_pool_t *ip_pool_list[IPL_LOGSIZE] = { NULL, NULL, NULL, NULL,
118 NULL, NULL, NULL, NULL };
122 void treeprint __P((ip_pool_t *));
134 RWLOCK_INIT(&ip_poolrw, "poolrw");
137 bzero((char *)&a, sizeof(a));
138 bzero((char *)&b, sizeof(b));
139 bzero((char *)&ip, sizeof(ip));
140 bzero((char *)&op, sizeof(op));
141 strcpy(op.iplo_name, "0");
143 if (ip_pool_create(&op) == 0)
144 ipo = ip_pool_exists(0, "0");
146 a.adf_addr.in4.s_addr = 0x0a010203;
147 b.adf_addr.in4.s_addr = 0xffffffff;
148 ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
149 ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
151 a.adf_addr.in4.s_addr = 0x0a000000;
152 b.adf_addr.in4.s_addr = 0xff000000;
153 ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0);
154 ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0);
156 a.adf_addr.in4.s_addr = 0x0a010100;
157 b.adf_addr.in4.s_addr = 0xffffff00;
158 ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
159 ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
161 a.adf_addr.in4.s_addr = 0x0a010200;
162 b.adf_addr.in4.s_addr = 0xffffff00;
163 ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0);
164 ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0);
166 a.adf_addr.in4.s_addr = 0x0a010000;
167 b.adf_addr.in4.s_addr = 0xffff0000;
168 ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
169 ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
171 a.adf_addr.in4.s_addr = 0x0a01020f;
172 b.adf_addr.in4.s_addr = 0xffffffff;
173 ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
174 ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1);
178 ip.in4.s_addr = 0x0a00aabb;
179 printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
180 ip_pool_search(ipo, 4, &ip));
182 ip.in4.s_addr = 0x0a000001;
183 printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
184 ip_pool_search(ipo, 4, &ip));
186 ip.in4.s_addr = 0x0a000101;
187 printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
188 ip_pool_search(ipo, 4, &ip));
190 ip.in4.s_addr = 0x0a010001;
191 printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
192 ip_pool_search(ipo, 4, &ip));
194 ip.in4.s_addr = 0x0a010101;
195 printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
196 ip_pool_search(ipo, 4, &ip));
198 ip.in4.s_addr = 0x0a010201;
199 printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
200 ip_pool_search(ipo, 4, &ip));
202 ip.in4.s_addr = 0x0a010203;
203 printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
204 ip_pool_search(ipo, 4, &ip));
206 ip.in4.s_addr = 0x0a01020f;
207 printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
208 ip_pool_search(ipo, 4, &ip));
210 ip.in4.s_addr = 0x0b00aabb;
211 printf("search(%#x) = %d (-1)\n", ip.in4.s_addr,
212 ip_pool_search(ipo, 4, &ip));
230 for (c = ipo->ipo_list; c != NULL; c = c->ipn_next)
231 printf("Node %p(%s) (%#x/%#x) = %d hits %lu\n",
232 c, c->ipn_name, c->ipn_addr.adf_addr.in4.s_addr,
233 c->ipn_mask.adf_addr.in4.s_addr,
234 c->ipn_info, c->ipn_hits);
236 #endif /* TEST_POOL */
239 /* ------------------------------------------------------------------------ */
240 /* Function: ip_pool_init */
241 /* Returns: int - 0 = success, else error */
243 /* Initialise the routing table data structures where required. */
244 /* ------------------------------------------------------------------------ */
248 bzero((char *)&ipoolstat, sizeof(ipoolstat));
250 #if (!defined(_KERNEL) || (BSD < 199306))
257 /* ------------------------------------------------------------------------ */
258 /* Function: ip_pool_fini */
259 /* Returns: int - 0 = success, else error */
260 /* Locks: WRITE(ipf_global) */
262 /* Clean up all the pool data structures allocated and call the cleanup */
263 /* function for the radix tree that supports the pools. ip_pool_destroy() is*/
264 /* used to delete the pools one by one to ensure they're properly freed up. */
265 /* ------------------------------------------------------------------------ */
271 for (i = 0; i <= IPL_LOGMAX; i++) {
272 for (q = ip_pool_list[i]; (p = q) != NULL; ) {
274 (void) ip_pool_destroy(i, p->ipo_name);
278 #if (!defined(_KERNEL) || (BSD < 199306))
284 /* ------------------------------------------------------------------------ */
285 /* Function: ip_pool_statistics */
286 /* Returns: int - 0 = success, else error */
287 /* Parameters: op(I) - pointer to lookup operation arguments */
289 /* Copy the current statistics out into user space, collecting pool list */
290 /* pointers as appropriate for later use. */
291 /* ------------------------------------------------------------------------ */
292 int ip_pool_statistics(op)
295 ip_pool_stat_t stats;
296 int unit, i, err = 0;
298 if (op->iplo_size != sizeof(ipoolstat))
301 bcopy((char *)&ipoolstat, (char *)&stats, sizeof(stats));
302 unit = op->iplo_unit;
303 if (unit == IPL_LOGALL) {
304 for (i = 0; i < IPL_LOGSIZE; i++)
305 stats.ipls_list[i] = ip_pool_list[i];
306 } else if (unit >= 0 && unit < IPL_LOGSIZE) {
307 if (op->iplo_name[0] != '\0')
308 stats.ipls_list[unit] = ip_pool_exists(unit,
311 stats.ipls_list[unit] = ip_pool_list[unit];
315 err = COPYOUT(&stats, op->iplo_struct, sizeof(stats));
320 /* ------------------------------------------------------------------------ */
321 /* Function: ip_pool_exists */
322 /* Returns: int - 0 = success, else error */
323 /* Parameters: ipo(I) - pointer to the pool getting the new node. */
325 /* Find a matching pool inside the collection of pools for a particular */
326 /* device, indicated by the unit number. */
327 /* ------------------------------------------------------------------------ */
328 static void *ip_pool_exists(unit, name)
334 for (p = ip_pool_list[unit]; p != NULL; p = p->ipo_next)
335 if (strncmp(p->ipo_name, name, sizeof(p->ipo_name)) == 0)
341 /* ------------------------------------------------------------------------ */
342 /* Function: ip_pool_find */
343 /* Returns: int - 0 = success, else error */
344 /* Parameters: ipo(I) - pointer to the pool getting the new node. */
346 /* Find a matching pool inside the collection of pools for a particular */
347 /* device, indicated by the unit number. If it is marked for deletion then */
348 /* pretend it does not exist. */
349 /* ------------------------------------------------------------------------ */
350 void *ip_pool_find(unit, name)
356 p = ip_pool_exists(unit, name);
357 if ((p != NULL) && (p->ipo_flags & IPOOL_DELETE))
364 /* ------------------------------------------------------------------------ */
365 /* Function: ip_pool_findeq */
366 /* Returns: int - 0 = success, else error */
367 /* Parameters: ipo(I) - pointer to the pool getting the new node. */
368 /* addr(I) - pointer to address information to delete */
371 /* Searches for an exact match of an entry in the pool. */
372 /* ------------------------------------------------------------------------ */
373 ip_pool_node_t *ip_pool_findeq(ipo, addr, mask)
375 addrfamily_t *addr, *mask;
377 struct radix_node *n;
381 RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
382 n = ipo->ipo_head->rnh_lookup(addr, mask, ipo->ipo_head);
383 RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
385 return (ip_pool_node_t *)n;
389 /* ------------------------------------------------------------------------ */
390 /* Function: ip_pool_search */
391 /* Returns: int - 0 == +ve match, -1 == error, 1 == -ve/no match */
392 /* Parameters: tptr(I) - pointer to the pool to search */
393 /* version(I) - IP protocol version (4 or 6) */
394 /* dptr(I) - pointer to address information */
396 /* Search the pool for a given address and return a search result. */
397 /* ------------------------------------------------------------------------ */
398 int ip_pool_search(tptr, ipversion, dptr)
403 struct radix_node *rn;
416 addr = (i6addr_t *)dptr;
417 bzero(&v, sizeof(v));
418 v.adf_len = offsetof(addrfamily_t, adf_addr);
420 if (ipversion == 4) {
421 v.adf_len += sizeof(addr->in4);
422 v.adf_addr.in4 = addr->in4;
424 } else if (ipversion == 6) {
425 v.adf_len += sizeof(addr->in6);
426 v.adf_addr.in6 = addr->in6;
431 READ_ENTER(&ip_poolrw);
433 RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
434 rn = ipo->ipo_head->rnh_matchaddr(&v, ipo->ipo_head);
435 RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
437 if ((rn != NULL) && ((rn->rn_flags & RNF_ROOT) == 0)) {
438 m = (ip_pool_node_t *)rn;
443 RWLOCK_EXIT(&ip_poolrw);
448 /* ------------------------------------------------------------------------ */
449 /* Function: ip_pool_insert */
450 /* Returns: int - 0 = success, else error */
451 /* Parameters: ipo(I) - pointer to the pool getting the new node. */
452 /* addr(I) - address being added as a node */
453 /* mask(I) - netmask to with the node being added */
454 /* info(I) - extra information to store in this node. */
455 /* Locks: WRITE(ip_poolrw) */
457 /* Add another node to the pool given by ipo. The three parameters passed */
458 /* in (addr, mask, info) shold all be stored in the node. */
459 /* ------------------------------------------------------------------------ */
460 int ip_pool_insert(ipo, addr, mask, info)
462 i6addr_t *addr, *mask;
465 struct radix_node *rn;
468 KMALLOC(x, ip_pool_node_t *);
473 bzero(x, sizeof(*x));
476 (void)strncpy(x->ipn_name, ipo->ipo_name, sizeof(x->ipn_name));
478 bcopy(addr, &x->ipn_addr.adf_addr, sizeof(*addr));
479 x->ipn_addr.adf_len = sizeof(x->ipn_addr);
480 bcopy(mask, &x->ipn_mask.adf_addr, sizeof(*mask));
481 x->ipn_mask.adf_len = sizeof(x->ipn_mask);
483 RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
484 rn = ipo->ipo_head->rnh_addaddr(&x->ipn_addr, &x->ipn_mask,
485 ipo->ipo_head, x->ipn_nodes);
486 RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
488 printf("Added %p at %p\n", x, rn);
497 x->ipn_next = ipo->ipo_list;
498 x->ipn_pnext = &ipo->ipo_list;
499 if (ipo->ipo_list != NULL)
500 ipo->ipo_list->ipn_pnext = &x->ipn_next;
503 ipoolstat.ipls_nodes++;
509 /* ------------------------------------------------------------------------ */
510 /* Function: ip_pool_create */
511 /* Returns: int - 0 = success, else error */
512 /* Parameters: op(I) - pointer to iplookup struct with call details */
513 /* Locks: WRITE(ip_poolrw) */
515 /* Creates a new group according to the paramters passed in via the */
516 /* iplookupop structure. Does not check to see if the group already exists */
517 /* when being inserted - assume this has already been done. If the pool is */
518 /* marked as being anonymous, give it a new, unique, identifier. Call any */
519 /* other functions required to initialise the structure. */
521 /* If the structure is flagged for deletion then reset the flag and return, */
522 /* as this likely means we've tried to free a pool that is in use (flush) */
523 /* and now want to repopulate it with "new" data. */
524 /* ------------------------------------------------------------------------ */
525 int ip_pool_create(op)
528 char name[FR_GROUPLEN];
532 unit = op->iplo_unit;
534 if ((op->iplo_arg & LOOKUP_ANON) == 0) {
535 h = ip_pool_exists(unit, op->iplo_name);
537 if ((h->ipo_flags & IPOOL_DELETE) == 0)
539 h->ipo_flags &= ~IPOOL_DELETE;
544 KMALLOC(h, ip_pool_t *);
547 bzero(h, sizeof(*h));
549 if (rn_inithead((void **)&h->ipo_head,
550 offsetof(addrfamily_t, adf_addr) << 3) == 0) {
555 if ((op->iplo_arg & LOOKUP_ANON) != 0) {
558 h->ipo_flags |= IPOOL_ANON;
559 poolnum = LOOKUP_ANON;
561 #if defined(SNPRINTF) && defined(_KERNEL)
562 SNPRINTF(name, sizeof(name), "%x", poolnum);
564 (void)sprintf(name, "%x", poolnum);
567 for (p = ip_pool_list[unit]; p != NULL; ) {
568 if (strncmp(name, p->ipo_name,
569 sizeof(p->ipo_name)) == 0) {
571 #if defined(SNPRINTF) && defined(_KERNEL)
572 SNPRINTF(name, sizeof(name), "%x", poolnum);
574 (void)sprintf(name, "%x", poolnum);
576 p = ip_pool_list[unit];
581 (void)strncpy(h->ipo_name, name, sizeof(h->ipo_name));
582 (void)strncpy(op->iplo_name, name, sizeof(op->iplo_name));
584 (void)strncpy(h->ipo_name, op->iplo_name, sizeof(h->ipo_name));
590 h->ipo_next = ip_pool_list[unit];
591 if (ip_pool_list[unit] != NULL)
592 ip_pool_list[unit]->ipo_pnext = &h->ipo_next;
593 h->ipo_pnext = &ip_pool_list[unit];
594 ip_pool_list[unit] = h;
596 ipoolstat.ipls_pools++;
602 /* ------------------------------------------------------------------------ */
603 /* Function: ip_pool_remove */
604 /* Returns: int - 0 = success, else error */
605 /* Parameters: ipo(I) - pointer to the pool to remove the node from. */
606 /* ipe(I) - address being deleted as a node */
607 /* Locks: WRITE(ip_poolrw) */
609 /* Remove a node from the pool given by ipo. */
610 /* ------------------------------------------------------------------------ */
611 int ip_pool_remove(ipo, ipe)
616 if (ipe->ipn_pnext != NULL)
617 *ipe->ipn_pnext = ipe->ipn_next;
618 if (ipe->ipn_next != NULL)
619 ipe->ipn_next->ipn_pnext = ipe->ipn_pnext;
621 RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
622 ipo->ipo_head->rnh_deladdr(&ipe->ipn_addr, &ipe->ipn_mask,
624 RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
626 ip_pool_node_deref(ipe);
632 /* ------------------------------------------------------------------------ */
633 /* Function: ip_pool_destroy */
634 /* Returns: int - 0 = success, else error */
635 /* Parameters: op(I) - information about the pool to remove */
636 /* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */
638 /* Search for a pool using paramters passed in and if it's not otherwise */
639 /* busy, free it. If it is busy, clear all of its nodes, mark it for being */
640 /* deleted and return an error saying it is busy. */
642 /* NOTE: Because this function is called out of ipfdetach() where ip_poolrw */
643 /* may not be initialised, we can't use an ASSERT to enforce the locking */
644 /* assertion that one of the two (ip_poolrw,ipf_global) is held. */
645 /* ------------------------------------------------------------------------ */
646 int ip_pool_destroy(unit, name)
652 ipo = ip_pool_exists(unit, name);
656 if (ipo->ipo_ref != 1) {
657 ip_pool_clearnodes(ipo);
658 ipo->ipo_flags |= IPOOL_DELETE;
667 /* ------------------------------------------------------------------------ */
668 /* Function: ip_pool_flush */
669 /* Returns: int - number of pools deleted */
670 /* Parameters: fp(I) - which pool(s) to flush */
671 /* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */
673 /* Free all pools associated with the device that matches the unit number */
674 /* passed in with operation. */
676 /* NOTE: Because this function is called out of ipfdetach() where ip_poolrw */
677 /* may not be initialised, we can't use an ASSERT to enforce the locking */
678 /* assertion that one of the two (ip_poolrw,ipf_global) is held. */
679 /* ------------------------------------------------------------------------ */
680 int ip_pool_flush(fp)
683 int i, num = 0, unit, err;
687 unit = fp->iplf_unit;
689 for (i = 0; i <= IPL_LOGMAX; i++) {
690 if (unit != IPLT_ALL && i != unit)
692 for (q = ip_pool_list[i]; (p = q) != NULL; ) {
694 (void)strncpy(op.iplo_name, p->ipo_name,
695 sizeof(op.iplo_name));
697 err = ip_pool_destroy(op.iplo_unit, op.iplo_name);
708 /* ------------------------------------------------------------------------ */
709 /* Function: ip_pool_free */
711 /* Parameters: ipo(I) - pointer to pool structure */
712 /* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */
714 /* Deletes the pool strucutre passed in from the list of pools and deletes */
715 /* all of the address information stored in it, including any tree data */
716 /* structures also allocated. */
718 /* NOTE: Because this function is called out of ipfdetach() where ip_poolrw */
719 /* may not be initialised, we can't use an ASSERT to enforce the locking */
720 /* assertion that one of the two (ip_poolrw,ipf_global) is held. */
721 /* ------------------------------------------------------------------------ */
722 void ip_pool_free(ipo)
726 ip_pool_clearnodes(ipo);
728 if (ipo->ipo_next != NULL)
729 ipo->ipo_next->ipo_pnext = ipo->ipo_pnext;
730 *ipo->ipo_pnext = ipo->ipo_next;
731 rn_freehead(ipo->ipo_head);
734 ipoolstat.ipls_pools--;
738 /* ------------------------------------------------------------------------ */
739 /* Function: ip_pool_clearnodes */
741 /* Parameters: ipo(I) - pointer to pool structure */
742 /* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */
744 /* Deletes all nodes stored in a pool structure. */
745 /* ------------------------------------------------------------------------ */
746 static void ip_pool_clearnodes(ipo)
751 RADIX_NODE_HEAD_LOCK(ipo->ipo_head);
752 while ((n = ipo->ipo_list) != NULL) {
753 ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask,
756 *n->ipn_pnext = n->ipn_next;
758 n->ipn_next->ipn_pnext = n->ipn_pnext;
762 ipoolstat.ipls_nodes--;
764 RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
766 ipo->ipo_list = NULL;
770 /* ------------------------------------------------------------------------ */
771 /* Function: ip_pool_deref */
773 /* Parameters: ipo(I) - pointer to pool structure */
774 /* Locks: WRITE(ip_poolrw) */
776 /* Drop the number of known references to this pool structure by one and if */
777 /* we arrive at zero known references, free it. */
778 /* ------------------------------------------------------------------------ */
779 void ip_pool_deref(ipo)
785 if (ipo->ipo_ref == 0)
788 else if ((ipo->ipo_ref == 1) && (ipo->ipo_flags & IPOOL_DELETE))
789 ip_pool_destroy(ipo->ipo_unit, ipo->ipo_name);
793 /* ------------------------------------------------------------------------ */
794 /* Function: ip_pool_node_deref */
796 /* Parameters: ipn(I) - pointer to pool structure */
797 /* Locks: WRITE(ip_poolrw) */
799 /* Drop a reference to the pool node passed in and if we're the last, free */
800 /* it all up and adjust the stats accordingly. */
801 /* ------------------------------------------------------------------------ */
802 void ip_pool_node_deref(ipn)
808 if (ipn->ipn_ref == 0) {
810 ipoolstat.ipls_nodes--;
815 /* ------------------------------------------------------------------------ */
816 /* Function: ip_pool_getnext */
818 /* Parameters: token(I) - pointer to pool structure */
819 /* Parameters: ilp(IO) - pointer to pool iterating structure */
821 /* ------------------------------------------------------------------------ */
822 int ip_pool_getnext(token, ilp)
824 ipflookupiter_t *ilp;
826 ip_pool_node_t *node, zn, *nextnode;
827 ip_pool_t *ipo, zp, *nextipo;
836 READ_ENTER(&ip_poolrw);
838 switch (ilp->ili_otype)
840 case IPFLOOKUPITER_LIST :
841 ipo = token->ipt_data;
843 nextipo = ip_pool_list[(int)ilp->ili_unit];
845 nextipo = ipo->ipo_next;
848 if (nextipo != NULL) {
849 ATOMIC_INC(nextipo->ipo_ref);
850 token->ipt_data = nextipo;
852 bzero((char *)&zp, sizeof(zp));
854 token->ipt_data = NULL;
858 case IPFLOOKUPITER_NODE :
859 node = token->ipt_data;
861 ipo = ip_pool_exists(ilp->ili_unit, ilp->ili_name);
865 nextnode = ipo->ipo_list;
869 nextnode = node->ipn_next;
872 if (nextnode != NULL) {
873 ATOMIC_INC(nextnode->ipn_ref);
874 token->ipt_data = nextnode;
876 bzero((char *)&zn, sizeof(zn));
878 token->ipt_data = NULL;
886 RWLOCK_EXIT(&ip_poolrw);
891 switch (ilp->ili_otype)
893 case IPFLOOKUPITER_LIST :
895 WRITE_ENTER(&ip_poolrw);
897 RWLOCK_EXIT(&ip_poolrw);
899 err = COPYOUT(nextipo, ilp->ili_data, sizeof(*nextipo));
904 case IPFLOOKUPITER_NODE :
906 WRITE_ENTER(&ip_poolrw);
907 ip_pool_node_deref(node);
908 RWLOCK_EXIT(&ip_poolrw);
910 err = COPYOUT(nextnode, ilp->ili_data, sizeof(*nextnode));
920 /* ------------------------------------------------------------------------ */
921 /* Function: ip_pool_iterderef */
923 /* Parameters: ipn(I) - pointer to pool structure */
924 /* Locks: WRITE(ip_poolrw) */
926 /* ------------------------------------------------------------------------ */
927 void ip_pool_iterderef(otype, unit, data)
936 if (unit < 0 || unit > IPL_LOGMAX)
941 case IPFLOOKUPITER_LIST :
942 WRITE_ENTER(&ip_poolrw);
943 ip_pool_deref((ip_pool_t *)data);
944 RWLOCK_EXIT(&ip_poolrw);
947 case IPFLOOKUPITER_NODE :
948 WRITE_ENTER(&ip_poolrw);
949 ip_pool_node_deref((ip_pool_node_t *)data);
950 RWLOCK_EXIT(&ip_poolrw);
958 # if defined(_KERNEL) && ((BSD >= 198911) && !defined(__osf__) && \
959 !defined(__hpux) && !defined(__sgi))
961 rn_freenode(struct radix_node *n, void *p)
963 struct radix_node_head *rnh = p;
964 struct radix_node *d;
966 d = rnh->rnh_deladdr(n->rn_key, NULL, rnh);
968 FreeS(d, max_keylen + 2 * sizeof (*d));
976 struct radix_node_head *rnh;
979 RADIX_NODE_HEAD_LOCK(rnh);
980 (*rnh->rnh_walktree)(rnh, rn_freenode, rnh);
982 rnh->rnh_addaddr = NULL;
983 rnh->rnh_deladdr = NULL;
984 rnh->rnh_matchaddr = NULL;
985 rnh->rnh_lookup = NULL;
986 rnh->rnh_walktree = NULL;
987 RADIX_NODE_HEAD_UNLOCK(rnh);
992 #endif /* IPFILTER_LOOKUP */