ip_pool.c revision c793af95640863cd29868fc7c419c5d2496b207b
/*
* Copyright (C) 1993-2001, 2003 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
# define KERNEL 1
# define _KERNEL 1
#endif
#if defined(__osf__)
# define _PROTO_NET_H_
#endif
#if !defined(_KERNEL) && !defined(__KERNEL__)
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# define _KERNEL
# ifdef __OpenBSD__
struct file;
# endif
#else
# endif
#endif
#if !defined(linux)
#endif
#endif
# include <sys/byteorder.h>
# ifdef _KERNEL
# include <sys/dditypes.h>
# endif
#endif
#endif
# ifdef __osf__
# endif
# include "radix_ipf_local.h"
# define _RADIX_H_
#endif
#include "netinet/ip_compat.h"
#if defined(IPFILTER_LOOKUP) && defined(_KERNEL) && \
#endif
/* END OF INCLUDES */
#if !defined(lint)
#endif
#ifdef IPFILTER_LOOKUP
/*
* 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.
*/
#ifdef TEST_POOL
int
int argc;
char *argv[];
{
addrfamily_t a, b;
ip_pool_init();
bzero((char *)&a, sizeof(a));
bzero((char *)&b, sizeof(b));
if (ip_pool_create(&op) == 0)
ip_pool_insert(ipo, &a, &b, 0);
ip_pool_insert(ipo, &a, &b, 0);
ip_pool_insert(ipo, &a, &b, 0);
ip_pool_insert(ipo, &a, &b, 0);
#ifdef DEBUG_POOL
#endif
#ifdef DEBUG_POOL
#endif
ip_pool_fini();
return 0;
}
void
{
ip_pool_node_t *c;
printf("Node %p(%s) (%#x/%#x) = %d hits %lu\n",
}
#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()
{
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(&op);
}
}
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)
{
return EINVAL;
if (unit == IPL_LOGALL) {
for (i = 0; i < IPL_LOGSIZE; i++)
else
} else
if (err == 0)
return err;
}
/* ------------------------------------------------------------------------ */
/* 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. */
/* ------------------------------------------------------------------------ */
int unit;
char *name;
{
ip_pool_t *p;
break;
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. */
/* ------------------------------------------------------------------------ */
{
struct radix_node *n;
SPL_INT(s);
SPL_NET(s);
SPL_X(s);
return (ip_pool_node_t *)n;
}
/* ------------------------------------------------------------------------ */
/* Function: ip_pool_search */
/* 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. */
/* ------------------------------------------------------------------------ */
void *tptr;
int version;
void *dptr;
{
struct radix_node *rn;
ip_pool_node_t *m;
addrfamily_t v;
int rv;
return -1;
rv = 1;
m = NULL;
bzero(&v, sizeof(v));
if (version == 4) {
#ifdef USE_INET6
} else if (version == 6) {
#endif
} else
return -1;
m = (ip_pool_node_t *)rn;
m->ipn_hits++;
}
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) - IPv4/6 address being added as a node */
/* mask(I) - IPv4/6 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 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));
#ifdef DEBUG_POOL
#endif
KFREE(x);
return ENOMEM;
}
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. */
/* ------------------------------------------------------------------------ */
int ip_pool_create(op)
{
char name[FR_GROUPLEN];
ip_pool_t *h;
if (h == NULL)
return ENOMEM;
bzero(h, sizeof(*h));
if (rn_inithead((void **)&h->ipo_head,
KFREE(h);
return ENOMEM;
}
ip_pool_t *p;
#else
#endif
sizeof(p->ipo_name)) == 0) {
poolnum++;
#else
#endif
p = ip_pool_list[unit];
} else
p = p->ipo_next;
}
} else {
}
h->ipo_ref = 1;
ip_pool_list[unit] = h;
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) */
/* */
/* Add another node to the pool given by ipo. The three parameters passed */
/* in (addr, mask, info) shold all be stored in the node. */
/* ------------------------------------------------------------------------ */
{
ip_pool_node_t **ipp, *n;
if (ipe == n) {
if (n->ipn_next)
break;
}
}
if (n == NULL)
return ENOENT;
KFREE(n);
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. */
/* */
/* NOTE: Because this function is called out of ipldetach() 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(op)
{
return ESRCH;
return EBUSY;
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 ipldetach() 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)
{
ip_pool_t *p, *q;
for (i = 0; i <= IPL_LOGMAX; i++) {
continue;
for (q = ip_pool_list[i]; (p = q) != NULL; ) {
q = p->ipo_next;
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 ipldetach() 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_node_t *n;
if (n->ipn_next)
KFREE(n);
}
}
/* ------------------------------------------------------------------------ */
/* 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)
{
}
static int
rn_freenode(struct radix_node *n, void *p)
{
struct radix_node_head *rnh = p;
struct radix_node *d;
if (d != NULL) {
}
return 0;
}
void
struct radix_node_head *rnh;
{
}
# endif
#endif /* IPFILTER_LOOKUP */