diff options
Diffstat (limited to 'sys/contrib/ipfilter/netinet/ip_pool.c')
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_pool.c | 992 |
1 files changed, 0 insertions, 992 deletions
diff --git a/sys/contrib/ipfilter/netinet/ip_pool.c b/sys/contrib/ipfilter/netinet/ip_pool.c deleted file mode 100644 index eab3310..0000000 --- a/sys/contrib/ipfilter/netinet/ip_pool.c +++ /dev/null @@ -1,992 +0,0 @@ -/* - * Copyright (C) 1993-2001, 2003 by Darren Reed. - * - * See the IPFILTER.LICENCE file for details on licencing. - */ -#if defined(KERNEL) || defined(_KERNEL) -# undef KERNEL -# undef _KERNEL -# define KERNEL 1 -# define _KERNEL 1 -#endif -#if defined(__osf__) -# define _PROTO_NET_H_ -#endif -#include <sys/errno.h> -#include <sys/types.h> -#include <sys/param.h> -#include <sys/file.h> -#if !defined(_KERNEL) && !defined(__KERNEL__) -# include <stdio.h> -# include <stdlib.h> -# include <string.h> -# define _KERNEL -# ifdef __OpenBSD__ -struct file; -# endif -# include <sys/uio.h> -# undef _KERNEL -#else -# include <sys/systm.h> -# if defined(NetBSD) && (__NetBSD_Version__ >= 104000000) -# include <sys/proc.h> -# endif -#endif -#include <sys/time.h> -#if !defined(linux) -# include <sys/protosw.h> -#endif -#include <sys/socket.h> -#if defined(_KERNEL) && (!defined(__SVR4) && !defined(__svr4__)) -# include <sys/mbuf.h> -#endif -#if defined(__SVR4) || defined(__svr4__) -# include <sys/filio.h> -# include <sys/byteorder.h> -# ifdef _KERNEL -# include <sys/dditypes.h> -# endif -# include <sys/stream.h> -# include <sys/kmem.h> -#endif -#if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) -# include <sys/malloc.h> -#endif - -#if defined(SOLARIS2) && !defined(_KERNEL) -# include "radix_ipf.h" -#endif -#if defined(_KERNEL) && (defined(__osf__) || defined(AIX) || \ - defined(__hpux) || defined(__sgi)) -# include "radix_ipf_local.h" -# define _RADIX_H_ -#endif -#include <net/if.h> -#include <netinet/in.h> - -#include "netinet/ip_compat.h" -#include "netinet/ip_fil.h" -#include "netinet/ip_pool.h" - -#if defined(IPFILTER_LOOKUP) && defined(_KERNEL) && \ - ((BSD >= 198911) && !defined(__osf__) && \ - !defined(__hpux) && !defined(__sgi)) -static int rn_freenode __P((struct radix_node *, void *)); -#endif - -/* END OF INCLUDES */ - -#if !defined(lint) -static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_pool.c,v 2.55.2.24 2007/10/10 09:45:37 darrenr Exp $"; -#endif - -#ifdef IPFILTER_LOOKUP - -# if !defined(RADIX_NODE_HEAD_LOCK) || !defined(RADIX_NODE_HEAD_UNLOCK) || \ - !defined(_KERNEL) -# undef RADIX_NODE_HEAD_LOCK -# undef RADIX_NODE_HEAD_UNLOCK -# define RADIX_NODE_HEAD_LOCK(x) ; -# define RADIX_NODE_HEAD_UNLOCK(x) ; -# endif - -static void ip_pool_clearnodes __P((ip_pool_t *)); -static void *ip_pool_exists __P((int, char *)); - -ip_pool_stat_t ipoolstat; -ipfrwlock_t ip_poolrw; - -/* - * Binary tree routines from Sedgewick and enhanced to do ranges of addresses. - * NOTE: Insertion *MUST* be from greatest range to least for it to work! - * These should be replaced, eventually, by something else - most notably a - * interval searching method. The important feature is to be able to find - * the best match. - * - * So why not use a radix tree for this? As the first line implies, it - * has been written to work with a _range_ of addresses. A range is not - * necessarily a match with any given netmask so what we end up dealing - * with is an interval tree. Implementations of these are hard to find - * and the one herein is far from bug free. - * - * Sigh, in the end I became convinced that the bugs the code contained did - * not make it worthwhile not using radix trees. For now the radix tree from - * 4.4 BSD is used, but this is not viewed as a long term solution. - */ -ip_pool_t *ip_pool_list[IPL_LOGSIZE] = { NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL }; - - -#ifdef TEST_POOL -void treeprint __P((ip_pool_t *)); - -int -main(argc, argv) - int argc; - char *argv[]; -{ - addrfamily_t a, b; - iplookupop_t op; - ip_pool_t *ipo; - i6addr_t ip; - - RWLOCK_INIT(&ip_poolrw, "poolrw"); - ip_pool_init(); - - bzero((char *)&a, sizeof(a)); - bzero((char *)&b, sizeof(b)); - bzero((char *)&ip, sizeof(ip)); - bzero((char *)&op, sizeof(op)); - strcpy(op.iplo_name, "0"); - - if (ip_pool_create(&op) == 0) - ipo = ip_pool_exists(0, "0"); - - a.adf_addr.in4.s_addr = 0x0a010203; - b.adf_addr.in4.s_addr = 0xffffffff; - ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1); - ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1); - - a.adf_addr.in4.s_addr = 0x0a000000; - b.adf_addr.in4.s_addr = 0xff000000; - ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0); - ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0); - - a.adf_addr.in4.s_addr = 0x0a010100; - b.adf_addr.in4.s_addr = 0xffffff00; - ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1); - ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1); - - a.adf_addr.in4.s_addr = 0x0a010200; - b.adf_addr.in4.s_addr = 0xffffff00; - ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0); - ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 0); - - a.adf_addr.in4.s_addr = 0x0a010000; - b.adf_addr.in4.s_addr = 0xffff0000; - ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1); - ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1); - - a.adf_addr.in4.s_addr = 0x0a01020f; - b.adf_addr.in4.s_addr = 0xffffffff; - ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1); - ip_pool_insert(ipo, &a.adf_addr, &b.adf_addr, 1); -#ifdef DEBUG_POOL -treeprint(ipo); -#endif - ip.in4.s_addr = 0x0a00aabb; - printf("search(%#x) = %d (0)\n", ip.in4.s_addr, - ip_pool_search(ipo, 4, &ip)); - - ip.in4.s_addr = 0x0a000001; - printf("search(%#x) = %d (0)\n", ip.in4.s_addr, - ip_pool_search(ipo, 4, &ip)); - - ip.in4.s_addr = 0x0a000101; - printf("search(%#x) = %d (0)\n", ip.in4.s_addr, - ip_pool_search(ipo, 4, &ip)); - - ip.in4.s_addr = 0x0a010001; - printf("search(%#x) = %d (1)\n", ip.in4.s_addr, - ip_pool_search(ipo, 4, &ip)); - - ip.in4.s_addr = 0x0a010101; - printf("search(%#x) = %d (1)\n", ip.in4.s_addr, - ip_pool_search(ipo, 4, &ip)); - - ip.in4.s_addr = 0x0a010201; - printf("search(%#x) = %d (0)\n", ip.in4.s_addr, - ip_pool_search(ipo, 4, &ip)); - - ip.in4.s_addr = 0x0a010203; - printf("search(%#x) = %d (1)\n", ip.in4.s_addr, - ip_pool_search(ipo, 4, &ip)); - - ip.in4.s_addr = 0x0a01020f; - printf("search(%#x) = %d (1)\n", ip.in4.s_addr, - ip_pool_search(ipo, 4, &ip)); - - ip.in4.s_addr = 0x0b00aabb; - printf("search(%#x) = %d (-1)\n", ip.in4.s_addr, - ip_pool_search(ipo, 4, &ip)); - -#ifdef DEBUG_POOL -treeprint(ipo); -#endif - - ip_pool_fini(); - - return 0; -} - - -void -treeprint(ipo) -ip_pool_t *ipo; -{ - ip_pool_node_t *c; - - for (c = ipo->ipo_list; c != NULL; c = c->ipn_next) - printf("Node %p(%s) (%#x/%#x) = %d hits %lu\n", - c, c->ipn_name, c->ipn_addr.adf_addr.in4.s_addr, - c->ipn_mask.adf_addr.in4.s_addr, - c->ipn_info, c->ipn_hits); -} -#endif /* TEST_POOL */ - - -/* ------------------------------------------------------------------------ */ -/* Function: ip_pool_init */ -/* Returns: int - 0 = success, else error */ -/* */ -/* Initialise the routing table data structures where required. */ -/* ------------------------------------------------------------------------ */ -int ip_pool_init() -{ - - bzero((char *)&ipoolstat, sizeof(ipoolstat)); - -#if (!defined(_KERNEL) || (BSD < 199306)) - rn_init(); -#endif - return 0; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ip_pool_fini */ -/* Returns: int - 0 = success, else error */ -/* Locks: WRITE(ipf_global) */ -/* */ -/* Clean up all the pool data structures allocated and call the cleanup */ -/* function for the radix tree that supports the pools. ip_pool_destroy() is*/ -/* used to delete the pools one by one to ensure they're properly freed up. */ -/* ------------------------------------------------------------------------ */ -void ip_pool_fini() -{ - ip_pool_t *p, *q; - int i; - - for (i = 0; i <= IPL_LOGMAX; i++) { - for (q = ip_pool_list[i]; (p = q) != NULL; ) { - q = p->ipo_next; - (void) ip_pool_destroy(i, p->ipo_name); - } - } - -#if (!defined(_KERNEL) || (BSD < 199306)) - rn_fini(); -#endif -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ip_pool_statistics */ -/* Returns: int - 0 = success, else error */ -/* Parameters: op(I) - pointer to lookup operation arguments */ -/* */ -/* Copy the current statistics out into user space, collecting pool list */ -/* pointers as appropriate for later use. */ -/* ------------------------------------------------------------------------ */ -int ip_pool_statistics(op) -iplookupop_t *op; -{ - ip_pool_stat_t stats; - int unit, i, err = 0; - - if (op->iplo_size != sizeof(ipoolstat)) - return EINVAL; - - bcopy((char *)&ipoolstat, (char *)&stats, sizeof(stats)); - unit = op->iplo_unit; - if (unit == IPL_LOGALL) { - for (i = 0; i < IPL_LOGSIZE; i++) - stats.ipls_list[i] = ip_pool_list[i]; - } else if (unit >= 0 && unit < IPL_LOGSIZE) { - if (op->iplo_name[0] != '\0') - stats.ipls_list[unit] = ip_pool_exists(unit, - op->iplo_name); - else - stats.ipls_list[unit] = ip_pool_list[unit]; - } else - err = EINVAL; - if (err == 0) - err = COPYOUT(&stats, op->iplo_struct, sizeof(stats)); - return err; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ip_pool_exists */ -/* Returns: int - 0 = success, else error */ -/* Parameters: ipo(I) - pointer to the pool getting the new node. */ -/* */ -/* Find a matching pool inside the collection of pools for a particular */ -/* device, indicated by the unit number. */ -/* ------------------------------------------------------------------------ */ -static void *ip_pool_exists(unit, name) -int unit; -char *name; -{ - ip_pool_t *p; - - for (p = ip_pool_list[unit]; p != NULL; p = p->ipo_next) - if (strncmp(p->ipo_name, name, sizeof(p->ipo_name)) == 0) - break; - return p; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ip_pool_find */ -/* Returns: int - 0 = success, else error */ -/* Parameters: ipo(I) - pointer to the pool getting the new node. */ -/* */ -/* Find a matching pool inside the collection of pools for a particular */ -/* device, indicated by the unit number. If it is marked for deletion then */ -/* pretend it does not exist. */ -/* ------------------------------------------------------------------------ */ -void *ip_pool_find(unit, name) -int unit; -char *name; -{ - ip_pool_t *p; - - p = ip_pool_exists(unit, name); - if ((p != NULL) && (p->ipo_flags & IPOOL_DELETE)) - return NULL; - - return p; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ip_pool_findeq */ -/* Returns: int - 0 = success, else error */ -/* Parameters: ipo(I) - pointer to the pool getting the new node. */ -/* addr(I) - pointer to address information to delete */ -/* mask(I) - */ -/* */ -/* Searches for an exact match of an entry in the pool. */ -/* ------------------------------------------------------------------------ */ -ip_pool_node_t *ip_pool_findeq(ipo, addr, mask) -ip_pool_t *ipo; -addrfamily_t *addr, *mask; -{ - struct radix_node *n; - SPL_INT(s); - - SPL_NET(s); - RADIX_NODE_HEAD_LOCK(ipo->ipo_head); - n = ipo->ipo_head->rnh_lookup(addr, mask, ipo->ipo_head); - RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head); - SPL_X(s); - return (ip_pool_node_t *)n; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ip_pool_search */ -/* Returns: int - 0 == +ve match, -1 == error, 1 == -ve/no match */ -/* Parameters: tptr(I) - pointer to the pool to search */ -/* version(I) - IP protocol version (4 or 6) */ -/* dptr(I) - pointer to address information */ -/* */ -/* Search the pool for a given address and return a search result. */ -/* ------------------------------------------------------------------------ */ -int ip_pool_search(tptr, ipversion, dptr) -void *tptr; -int ipversion; -void *dptr; -{ - struct radix_node *rn; - ip_pool_node_t *m; - i6addr_t *addr; - addrfamily_t v; - ip_pool_t *ipo; - int rv; - - ipo = tptr; - if (ipo == NULL) - return -1; - - rv = 1; - m = NULL; - addr = (i6addr_t *)dptr; - bzero(&v, sizeof(v)); - v.adf_len = offsetof(addrfamily_t, adf_addr); - - if (ipversion == 4) { - v.adf_len += sizeof(addr->in4); - v.adf_addr.in4 = addr->in4; -#ifdef USE_INET6 - } else if (ipversion == 6) { - v.adf_len += sizeof(addr->in6); - v.adf_addr.in6 = addr->in6; -#endif - } else - return -1; - - READ_ENTER(&ip_poolrw); - - RADIX_NODE_HEAD_LOCK(ipo->ipo_head); - rn = ipo->ipo_head->rnh_matchaddr(&v, ipo->ipo_head); - RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head); - - if ((rn != NULL) && ((rn->rn_flags & RNF_ROOT) == 0)) { - m = (ip_pool_node_t *)rn; - ipo->ipo_hits++; - m->ipn_hits++; - rv = m->ipn_info; - } - RWLOCK_EXIT(&ip_poolrw); - return rv; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ip_pool_insert */ -/* Returns: int - 0 = success, else error */ -/* Parameters: ipo(I) - pointer to the pool getting the new node. */ -/* addr(I) - address being added as a node */ -/* mask(I) - netmask to with the node being added */ -/* info(I) - extra information to store in this node. */ -/* Locks: WRITE(ip_poolrw) */ -/* */ -/* Add another node to the pool given by ipo. The three parameters passed */ -/* in (addr, mask, info) shold all be stored in the node. */ -/* ------------------------------------------------------------------------ */ -int ip_pool_insert(ipo, addr, mask, info) -ip_pool_t *ipo; -i6addr_t *addr, *mask; -int info; -{ - struct radix_node *rn; - ip_pool_node_t *x; - - KMALLOC(x, ip_pool_node_t *); - if (x == NULL) { - return ENOMEM; - } - - bzero(x, sizeof(*x)); - - x->ipn_info = info; - (void)strncpy(x->ipn_name, ipo->ipo_name, sizeof(x->ipn_name)); - - bcopy(addr, &x->ipn_addr.adf_addr, sizeof(*addr)); - x->ipn_addr.adf_len = sizeof(x->ipn_addr); - bcopy(mask, &x->ipn_mask.adf_addr, sizeof(*mask)); - x->ipn_mask.adf_len = sizeof(x->ipn_mask); - - RADIX_NODE_HEAD_LOCK(ipo->ipo_head); - rn = ipo->ipo_head->rnh_addaddr(&x->ipn_addr, &x->ipn_mask, - ipo->ipo_head, x->ipn_nodes); - RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head); -#ifdef DEBUG_POOL - printf("Added %p at %p\n", x, rn); -#endif - - if (rn == NULL) { - KFREE(x); - return ENOMEM; - } - - x->ipn_ref = 1; - x->ipn_next = ipo->ipo_list; - x->ipn_pnext = &ipo->ipo_list; - if (ipo->ipo_list != NULL) - ipo->ipo_list->ipn_pnext = &x->ipn_next; - ipo->ipo_list = x; - - ipoolstat.ipls_nodes++; - - return 0; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ip_pool_create */ -/* Returns: int - 0 = success, else error */ -/* Parameters: op(I) - pointer to iplookup struct with call details */ -/* Locks: WRITE(ip_poolrw) */ -/* */ -/* Creates a new group according to the paramters passed in via the */ -/* iplookupop structure. Does not check to see if the group already exists */ -/* when being inserted - assume this has already been done. If the pool is */ -/* marked as being anonymous, give it a new, unique, identifier. Call any */ -/* other functions required to initialise the structure. */ -/* */ -/* If the structure is flagged for deletion then reset the flag and return, */ -/* as this likely means we've tried to free a pool that is in use (flush) */ -/* and now want to repopulate it with "new" data. */ -/* ------------------------------------------------------------------------ */ -int ip_pool_create(op) -iplookupop_t *op; -{ - char name[FR_GROUPLEN]; - int poolnum, unit; - ip_pool_t *h; - - unit = op->iplo_unit; - - if ((op->iplo_arg & LOOKUP_ANON) == 0) { - h = ip_pool_exists(unit, op->iplo_name); - if (h != NULL) { - if ((h->ipo_flags & IPOOL_DELETE) == 0) - return EEXIST; - h->ipo_flags &= ~IPOOL_DELETE; - return 0; - } - } - - KMALLOC(h, ip_pool_t *); - if (h == NULL) - return ENOMEM; - bzero(h, sizeof(*h)); - - if (rn_inithead((void **)&h->ipo_head, - offsetof(addrfamily_t, adf_addr) << 3) == 0) { - KFREE(h); - return ENOMEM; - } - - if ((op->iplo_arg & LOOKUP_ANON) != 0) { - ip_pool_t *p; - - h->ipo_flags |= IPOOL_ANON; - poolnum = LOOKUP_ANON; - -#if defined(SNPRINTF) && defined(_KERNEL) - SNPRINTF(name, sizeof(name), "%x", poolnum); -#else - (void)sprintf(name, "%x", poolnum); -#endif - - for (p = ip_pool_list[unit]; p != NULL; ) { - if (strncmp(name, p->ipo_name, - sizeof(p->ipo_name)) == 0) { - poolnum++; -#if defined(SNPRINTF) && defined(_KERNEL) - SNPRINTF(name, sizeof(name), "%x", poolnum); -#else - (void)sprintf(name, "%x", poolnum); -#endif - p = ip_pool_list[unit]; - } else - p = p->ipo_next; - } - - (void)strncpy(h->ipo_name, name, sizeof(h->ipo_name)); - (void)strncpy(op->iplo_name, name, sizeof(op->iplo_name)); - } else { - (void)strncpy(h->ipo_name, op->iplo_name, sizeof(h->ipo_name)); - } - - h->ipo_ref = 1; - h->ipo_list = NULL; - h->ipo_unit = unit; - h->ipo_next = ip_pool_list[unit]; - if (ip_pool_list[unit] != NULL) - ip_pool_list[unit]->ipo_pnext = &h->ipo_next; - h->ipo_pnext = &ip_pool_list[unit]; - ip_pool_list[unit] = h; - - ipoolstat.ipls_pools++; - - return 0; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ip_pool_remove */ -/* Returns: int - 0 = success, else error */ -/* Parameters: ipo(I) - pointer to the pool to remove the node from. */ -/* ipe(I) - address being deleted as a node */ -/* Locks: WRITE(ip_poolrw) */ -/* */ -/* Remove a node from the pool given by ipo. */ -/* ------------------------------------------------------------------------ */ -int ip_pool_remove(ipo, ipe) -ip_pool_t *ipo; -ip_pool_node_t *ipe; -{ - - if (ipe->ipn_pnext != NULL) - *ipe->ipn_pnext = ipe->ipn_next; - if (ipe->ipn_next != NULL) - ipe->ipn_next->ipn_pnext = ipe->ipn_pnext; - - RADIX_NODE_HEAD_LOCK(ipo->ipo_head); - ipo->ipo_head->rnh_deladdr(&ipe->ipn_addr, &ipe->ipn_mask, - ipo->ipo_head); - RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head); - - ip_pool_node_deref(ipe); - - return 0; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ip_pool_destroy */ -/* Returns: int - 0 = success, else error */ -/* Parameters: op(I) - information about the pool to remove */ -/* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */ -/* */ -/* Search for a pool using paramters passed in and if it's not otherwise */ -/* busy, free it. If it is busy, clear all of its nodes, mark it for being */ -/* deleted and return an error saying it is busy. */ -/* */ -/* NOTE: Because this function is called out of ipfdetach() where ip_poolrw */ -/* may not be initialised, we can't use an ASSERT to enforce the locking */ -/* assertion that one of the two (ip_poolrw,ipf_global) is held. */ -/* ------------------------------------------------------------------------ */ -int ip_pool_destroy(unit, name) -int unit; -char *name; -{ - ip_pool_t *ipo; - - ipo = ip_pool_exists(unit, name); - if (ipo == NULL) - return ESRCH; - - if (ipo->ipo_ref != 1) { - ip_pool_clearnodes(ipo); - ipo->ipo_flags |= IPOOL_DELETE; - return 0; - } - - ip_pool_free(ipo); - return 0; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ip_pool_flush */ -/* Returns: int - number of pools deleted */ -/* Parameters: fp(I) - which pool(s) to flush */ -/* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */ -/* */ -/* Free all pools associated with the device that matches the unit number */ -/* passed in with operation. */ -/* */ -/* NOTE: Because this function is called out of ipfdetach() where ip_poolrw */ -/* may not be initialised, we can't use an ASSERT to enforce the locking */ -/* assertion that one of the two (ip_poolrw,ipf_global) is held. */ -/* ------------------------------------------------------------------------ */ -int ip_pool_flush(fp) -iplookupflush_t *fp; -{ - int i, num = 0, unit, err; - ip_pool_t *p, *q; - iplookupop_t op; - - unit = fp->iplf_unit; - - for (i = 0; i <= IPL_LOGMAX; i++) { - if (unit != IPLT_ALL && i != unit) - continue; - for (q = ip_pool_list[i]; (p = q) != NULL; ) { - op.iplo_unit = i; - (void)strncpy(op.iplo_name, p->ipo_name, - sizeof(op.iplo_name)); - q = p->ipo_next; - err = ip_pool_destroy(op.iplo_unit, op.iplo_name); - if (err == 0) - num++; - else - break; - } - } - return num; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ip_pool_free */ -/* Returns: void */ -/* Parameters: ipo(I) - pointer to pool structure */ -/* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */ -/* */ -/* Deletes the pool strucutre passed in from the list of pools and deletes */ -/* all of the address information stored in it, including any tree data */ -/* structures also allocated. */ -/* */ -/* NOTE: Because this function is called out of ipfdetach() where ip_poolrw */ -/* may not be initialised, we can't use an ASSERT to enforce the locking */ -/* assertion that one of the two (ip_poolrw,ipf_global) is held. */ -/* ------------------------------------------------------------------------ */ -void ip_pool_free(ipo) -ip_pool_t *ipo; -{ - - ip_pool_clearnodes(ipo); - - if (ipo->ipo_next != NULL) - ipo->ipo_next->ipo_pnext = ipo->ipo_pnext; - *ipo->ipo_pnext = ipo->ipo_next; - rn_freehead(ipo->ipo_head); - KFREE(ipo); - - ipoolstat.ipls_pools--; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ip_pool_clearnodes */ -/* Returns: void */ -/* Parameters: ipo(I) - pointer to pool structure */ -/* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */ -/* */ -/* Deletes all nodes stored in a pool structure. */ -/* ------------------------------------------------------------------------ */ -static void ip_pool_clearnodes(ipo) -ip_pool_t *ipo; -{ - ip_pool_node_t *n; - - RADIX_NODE_HEAD_LOCK(ipo->ipo_head); - while ((n = ipo->ipo_list) != NULL) { - ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask, - ipo->ipo_head); - - *n->ipn_pnext = n->ipn_next; - if (n->ipn_next) - n->ipn_next->ipn_pnext = n->ipn_pnext; - - KFREE(n); - - ipoolstat.ipls_nodes--; - } - RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head); - - ipo->ipo_list = NULL; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ip_pool_deref */ -/* Returns: void */ -/* Parameters: ipo(I) - pointer to pool structure */ -/* Locks: WRITE(ip_poolrw) */ -/* */ -/* Drop the number of known references to this pool structure by one and if */ -/* we arrive at zero known references, free it. */ -/* ------------------------------------------------------------------------ */ -void ip_pool_deref(ipo) -ip_pool_t *ipo; -{ - - ipo->ipo_ref--; - - if (ipo->ipo_ref == 0) - ip_pool_free(ipo); - - else if ((ipo->ipo_ref == 1) && (ipo->ipo_flags & IPOOL_DELETE)) - ip_pool_destroy(ipo->ipo_unit, ipo->ipo_name); -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ip_pool_node_deref */ -/* Returns: void */ -/* Parameters: ipn(I) - pointer to pool structure */ -/* Locks: WRITE(ip_poolrw) */ -/* */ -/* Drop a reference to the pool node passed in and if we're the last, free */ -/* it all up and adjust the stats accordingly. */ -/* ------------------------------------------------------------------------ */ -void ip_pool_node_deref(ipn) -ip_pool_node_t *ipn; -{ - - ipn->ipn_ref--; - - if (ipn->ipn_ref == 0) { - KFREE(ipn); - ipoolstat.ipls_nodes--; - } -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ip_pool_getnext */ -/* Returns: void */ -/* Parameters: token(I) - pointer to pool structure */ -/* Parameters: ilp(IO) - pointer to pool iterating structure */ -/* */ -/* ------------------------------------------------------------------------ */ -int ip_pool_getnext(token, ilp) -ipftoken_t *token; -ipflookupiter_t *ilp; -{ - ip_pool_node_t *node, zn, *nextnode; - ip_pool_t *ipo, zp, *nextipo; - int err; - - err = 0; - node = NULL; - nextnode = NULL; - ipo = NULL; - nextipo = NULL; - - READ_ENTER(&ip_poolrw); - - switch (ilp->ili_otype) - { - case IPFLOOKUPITER_LIST : - ipo = token->ipt_data; - if (ipo == NULL) { - nextipo = ip_pool_list[(int)ilp->ili_unit]; - } else { - nextipo = ipo->ipo_next; - } - - if (nextipo != NULL) { - ATOMIC_INC(nextipo->ipo_ref); - token->ipt_data = nextipo; - } else { - bzero((char *)&zp, sizeof(zp)); - nextipo = &zp; - token->ipt_data = NULL; - } - break; - - case IPFLOOKUPITER_NODE : - node = token->ipt_data; - if (node == NULL) { - ipo = ip_pool_exists(ilp->ili_unit, ilp->ili_name); - if (ipo == NULL) - err = ESRCH; - else { - nextnode = ipo->ipo_list; - ipo = NULL; - } - } else { - nextnode = node->ipn_next; - } - - if (nextnode != NULL) { - ATOMIC_INC(nextnode->ipn_ref); - token->ipt_data = nextnode; - } else { - bzero((char *)&zn, sizeof(zn)); - nextnode = &zn; - token->ipt_data = NULL; - } - break; - default : - err = EINVAL; - break; - } - - RWLOCK_EXIT(&ip_poolrw); - - if (err != 0) - return err; - - switch (ilp->ili_otype) - { - case IPFLOOKUPITER_LIST : - if (ipo != NULL) { - WRITE_ENTER(&ip_poolrw); - ip_pool_deref(ipo); - RWLOCK_EXIT(&ip_poolrw); - } - err = COPYOUT(nextipo, ilp->ili_data, sizeof(*nextipo)); - if (err != 0) - err = EFAULT; - break; - - case IPFLOOKUPITER_NODE : - if (node != NULL) { - WRITE_ENTER(&ip_poolrw); - ip_pool_node_deref(node); - RWLOCK_EXIT(&ip_poolrw); - } - err = COPYOUT(nextnode, ilp->ili_data, sizeof(*nextnode)); - if (err != 0) - err = EFAULT; - break; - } - - return err; -} - - -/* ------------------------------------------------------------------------ */ -/* Function: ip_pool_iterderef */ -/* Returns: void */ -/* Parameters: ipn(I) - pointer to pool structure */ -/* Locks: WRITE(ip_poolrw) */ -/* */ -/* ------------------------------------------------------------------------ */ -void ip_pool_iterderef(otype, unit, data) -u_int otype; -int unit; -void *data; -{ - - if (data == NULL) - return; - - if (unit < 0 || unit > IPL_LOGMAX) - return; - - switch (otype) - { - case IPFLOOKUPITER_LIST : - WRITE_ENTER(&ip_poolrw); - ip_pool_deref((ip_pool_t *)data); - RWLOCK_EXIT(&ip_poolrw); - break; - - case IPFLOOKUPITER_NODE : - WRITE_ENTER(&ip_poolrw); - ip_pool_node_deref((ip_pool_node_t *)data); - RWLOCK_EXIT(&ip_poolrw); - break; - default : - break; - } -} - - -# if defined(_KERNEL) && ((BSD >= 198911) && !defined(__osf__) && \ - !defined(__hpux) && !defined(__sgi)) -static int -rn_freenode(struct radix_node *n, void *p) -{ - struct radix_node_head *rnh = p; - struct radix_node *d; - - d = rnh->rnh_deladdr(n->rn_key, NULL, rnh); - if (d != NULL) { - FreeS(d, max_keylen + 2 * sizeof (*d)); - } - return 0; -} - - -void -rn_freehead(rnh) - struct radix_node_head *rnh; -{ - - RADIX_NODE_HEAD_LOCK(rnh); - (*rnh->rnh_walktree)(rnh, rn_freenode, rnh); - - rnh->rnh_addaddr = NULL; - rnh->rnh_deladdr = NULL; - rnh->rnh_matchaddr = NULL; - rnh->rnh_lookup = NULL; - rnh->rnh_walktree = NULL; - RADIX_NODE_HEAD_UNLOCK(rnh); - - Free(rnh); -} -# endif -#endif /* IPFILTER_LOOKUP */ |