summaryrefslogtreecommitdiffstats
path: root/sys/contrib/ipfilter/netinet/ip_pool.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/ipfilter/netinet/ip_pool.c')
-rw-r--r--sys/contrib/ipfilter/netinet/ip_pool.c1271
1 files changed, 884 insertions, 387 deletions
diff --git a/sys/contrib/ipfilter/netinet/ip_pool.c b/sys/contrib/ipfilter/netinet/ip_pool.c
index eab3310..2a43cdb 100644
--- a/sys/contrib/ipfilter/netinet/ip_pool.c
+++ b/sys/contrib/ipfilter/netinet/ip_pool.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1993-2001, 2003 by Darren Reed.
+ * Copyright (C) 2012 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*/
@@ -33,15 +33,10 @@ struct file;
# 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__))
+#if defined(_KERNEL) && !defined(SOLARIS2)
# include <sys/mbuf.h>
#endif
#if defined(__SVR4) || defined(__svr4__)
-# include <sys/filio.h>
# include <sys/byteorder.h>
# ifdef _KERNEL
# include <sys/dditypes.h>
@@ -53,69 +48,91 @@ struct file;
# 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 <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
+#if !defined(_KERNEL)
+# include "ipf.h"
+#endif
#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
+#include "netinet/radix_ipf.h"
/* 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 $";
+static const char rcsid[] = "@(#)$Id$";
#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 };
+typedef struct ipf_pool_softc_s {
+ void *ipf_radix;
+ ip_pool_t *ipf_pool_list[LOOKUP_POOL_SZ];
+ ipf_pool_stat_t ipf_pool_stats;
+ ip_pool_node_t *ipf_node_explist;
+} ipf_pool_softc_t;
+
+
+static void ipf_pool_clearnodes __P((ipf_main_softc_t *, ipf_pool_softc_t *,
+ ip_pool_t *));
+static int ipf_pool_create __P((ipf_main_softc_t *, ipf_pool_softc_t *, iplookupop_t *));
+static int ipf_pool_deref __P((ipf_main_softc_t *, void *, void *));
+static int ipf_pool_destroy __P((ipf_main_softc_t *, ipf_pool_softc_t *, int, char *));
+static void *ipf_pool_exists __P((ipf_pool_softc_t *, int, char *));
+static void *ipf_pool_find __P((void *, int, char *));
+static ip_pool_node_t *ipf_pool_findeq __P((ipf_pool_softc_t *, ip_pool_t *,
+ addrfamily_t *, addrfamily_t *));
+static void ipf_pool_free __P((ipf_main_softc_t *, ipf_pool_softc_t *,
+ ip_pool_t *));
+static int ipf_pool_insert_node __P((ipf_main_softc_t *, ipf_pool_softc_t *,
+ ip_pool_t *, struct ip_pool_node *));
+static int ipf_pool_iter_deref __P((ipf_main_softc_t *, void *, int, int, void *));
+static int ipf_pool_iter_next __P((ipf_main_softc_t *, void *, ipftoken_t *,
+ ipflookupiter_t *));
+static size_t ipf_pool_flush __P((ipf_main_softc_t *, void *, iplookupflush_t *));
+static int ipf_pool_node_add __P((ipf_main_softc_t *, void *, iplookupop_t *,
+ int));
+static int ipf_pool_node_del __P((ipf_main_softc_t *, void *, iplookupop_t *,
+ int));
+static void ipf_pool_node_deref __P((ipf_pool_softc_t *, ip_pool_node_t *));
+static int ipf_pool_remove_node __P((ipf_main_softc_t *, ipf_pool_softc_t *,
+ ip_pool_t *, ip_pool_node_t *));
+static int ipf_pool_search __P((ipf_main_softc_t *, void *, int,
+ void *, u_int));
+static void *ipf_pool_soft_create __P((ipf_main_softc_t *));
+static void ipf_pool_soft_destroy __P((ipf_main_softc_t *, void *));
+static void ipf_pool_soft_fini __P((ipf_main_softc_t *, void *));
+static int ipf_pool_soft_init __P((ipf_main_softc_t *, void *));
+static int ipf_pool_stats_get __P((ipf_main_softc_t *, void *, iplookupop_t *));
+static int ipf_pool_table_add __P((ipf_main_softc_t *, void *, iplookupop_t *));
+static int ipf_pool_table_del __P((ipf_main_softc_t *, void *, iplookupop_t *));
+static void *ipf_pool_select_add_ref __P((void *, int, char *));
+static void ipf_pool_expire __P((ipf_main_softc_t *, void *));
+
+ipf_lookup_t ipf_pool_backend = {
+ IPLT_POOL,
+ ipf_pool_soft_create,
+ ipf_pool_soft_destroy,
+ ipf_pool_soft_init,
+ ipf_pool_soft_fini,
+ ipf_pool_search,
+ ipf_pool_flush,
+ ipf_pool_iter_deref,
+ ipf_pool_iter_next,
+ ipf_pool_node_add,
+ ipf_pool_node_del,
+ ipf_pool_stats_get,
+ ipf_pool_table_add,
+ ipf_pool_table_del,
+ ipf_pool_deref,
+ ipf_pool_find,
+ ipf_pool_select_add_ref,
+ NULL,
+ ipf_pool_expire,
+ NULL
+};
#ifdef TEST_POOL
@@ -126,96 +143,98 @@ main(argc, argv)
int argc;
char *argv[];
{
+ ip_pool_node_t node;
addrfamily_t a, b;
iplookupop_t op;
ip_pool_t *ipo;
i6addr_t ip;
- RWLOCK_INIT(&ip_poolrw, "poolrw");
- ip_pool_init();
+ RWLOCK_INIT(softc->ipf_poolrw, "poolrw");
+ ipf_pool_init();
- bzero((char *)&a, sizeof(a));
- bzero((char *)&b, sizeof(b));
bzero((char *)&ip, sizeof(ip));
bzero((char *)&op, sizeof(op));
+ bzero((char *)&node, sizeof(node));
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);
+ if (ipf_pool_create(&op) == 0)
+ ipo = ipf_pool_exists(0, "0");
+
+ node.ipn_addr.adf_family = AF_INET;
+
+ node.ipn_addr.adf_addr.in4.s_addr = 0x0a010203;
+ node.ipn_mask.adf_addr.in4.s_addr = 0xffffffff;
+ node.ipn_info = 1;
+ ipf_pool_insert_node(ipo, &node);
+
+ node.ipn_addr.adf_addr.in4.s_addr = 0x0a000000;
+ node.ipn_mask.adf_addr.in4.s_addr = 0xff000000;
+ node.ipn_info = 0;
+ ipf_pool_insert_node(ipo, &node);
+
+ node.ipn_addr.adf_addr.in4.s_addr = 0x0a010100;
+ node.ipn_mask.adf_addr.in4.s_addr = 0xffffff00;
+ node.ipn_info = 1;
+ ipf_pool_insert_node(ipo, &node);
+
+ node.ipn_addr.adf_addr.in4.s_addr = 0x0a010200;
+ node.ipn_mask.adf_addr.in4.s_addr = 0xffffff00;
+ node.ipn_info = 0;
+ ipf_pool_insert_node(ipo, &node);
+
+ node.ipn_addr.adf_addr.in4.s_addr = 0x0a010000;
+ node.ipn_mask.adf_addr.in4.s_addr = 0xffff0000;
+ node.ipn_info = 1;
+ ipf_pool_insert_node(ipo, &node);
+
+ node.ipn_addr.adf_addr.in4.s_addr = 0x0a01020f;
+ node.ipn_mask.adf_addr.in4.s_addr = 0xffffffff;
+ node.ipn_info = 1;
+ ipf_pool_insert_node(ipo, &node);
#ifdef DEBUG_POOL
-treeprint(ipo);
+ treeprint(ipo);
#endif
ip.in4.s_addr = 0x0a00aabb;
printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
- ip_pool_search(ipo, 4, &ip));
+ ipf_pool_search(ipo, 4, &ip, 1));
ip.in4.s_addr = 0x0a000001;
printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
- ip_pool_search(ipo, 4, &ip));
+ ipf_pool_search(ipo, 4, &ip, 1));
ip.in4.s_addr = 0x0a000101;
printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
- ip_pool_search(ipo, 4, &ip));
+ ipf_pool_search(ipo, 4, &ip, 1));
ip.in4.s_addr = 0x0a010001;
printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
- ip_pool_search(ipo, 4, &ip));
+ ipf_pool_search(ipo, 4, &ip, 1));
ip.in4.s_addr = 0x0a010101;
printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
- ip_pool_search(ipo, 4, &ip));
+ ipf_pool_search(ipo, 4, &ip, 1));
ip.in4.s_addr = 0x0a010201;
printf("search(%#x) = %d (0)\n", ip.in4.s_addr,
- ip_pool_search(ipo, 4, &ip));
+ ipf_pool_search(ipo, 4, &ip, 1));
ip.in4.s_addr = 0x0a010203;
printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
- ip_pool_search(ipo, 4, &ip));
+ ipf_pool_search(ipo, 4, &ip, 1));
ip.in4.s_addr = 0x0a01020f;
printf("search(%#x) = %d (1)\n", ip.in4.s_addr,
- ip_pool_search(ipo, 4, &ip));
+ ipf_pool_search(ipo, 4, &ip, 1));
ip.in4.s_addr = 0x0b00aabb;
printf("search(%#x) = %d (-1)\n", ip.in4.s_addr,
- ip_pool_search(ipo, 4, &ip));
+ ipf_pool_search(ipo, 4, &ip, 1));
#ifdef DEBUG_POOL
-treeprint(ipo);
+ treeprint(ipo);
#endif
- ip_pool_fini();
+ ipf_pool_fini();
return 0;
}
@@ -223,7 +242,7 @@ treeprint(ipo);
void
treeprint(ipo)
-ip_pool_t *ipo;
+ ip_pool_t *ipo;
{
ip_pool_node_t *c;
@@ -237,123 +256,445 @@ ip_pool_t *ipo;
/* ------------------------------------------------------------------------ */
-/* Function: ip_pool_init */
+/* Function: ipf_pool_soft_create */
+/* Returns: void * - NULL = failure, else pointer to local context */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* */
+/* Initialise the routing table data structures where required. */
+/* ------------------------------------------------------------------------ */
+static void *
+ipf_pool_soft_create(softc)
+ ipf_main_softc_t *softc;
+{
+ ipf_pool_softc_t *softp;
+
+ KMALLOC(softp, ipf_pool_softc_t *);
+ if (softp == NULL) {
+ IPFERROR(70032);
+ return NULL;
+ }
+
+ bzero((char *)softp, sizeof(*softp));
+
+ softp->ipf_radix = ipf_rx_create();
+ if (softp->ipf_radix == NULL) {
+ IPFERROR(70033);
+ KFREE(softp);
+ return NULL;
+ }
+
+ return softp;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ipf_pool_soft_init */
/* Returns: int - 0 = success, else error */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* arg(I) - pointer to local context to use */
/* */
/* Initialise the routing table data structures where required. */
/* ------------------------------------------------------------------------ */
-int ip_pool_init()
+static int
+ipf_pool_soft_init(softc, arg)
+ ipf_main_softc_t *softc;
+ void *arg;
{
+ ipf_pool_softc_t *softp = arg;
- bzero((char *)&ipoolstat, sizeof(ipoolstat));
+ ipf_rx_init(softp->ipf_radix);
-#if (!defined(_KERNEL) || (BSD < 199306))
- rn_init();
-#endif
return 0;
}
/* ------------------------------------------------------------------------ */
-/* Function: ip_pool_fini */
-/* Returns: int - 0 = success, else error */
+/* Function: ipf_pool_soft_fini */
+/* Returns: Nil */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* arg(I) - pointer to local context to use */
/* 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*/
+/* function for the radix tree that supports the pools. ipf_pool_destroy is */
/* used to delete the pools one by one to ensure they're properly freed up. */
/* ------------------------------------------------------------------------ */
-void ip_pool_fini()
+static void
+ipf_pool_soft_fini(softc, arg)
+ ipf_main_softc_t *softc;
+ void *arg;
{
+ ipf_pool_softc_t *softp = arg;
ip_pool_t *p, *q;
int i;
- for (i = 0; i <= IPL_LOGMAX; i++) {
- for (q = ip_pool_list[i]; (p = q) != NULL; ) {
+ softc = arg;
+
+ for (i = -1; i <= IPL_LOGMAX; i++) {
+ for (q = softp->ipf_pool_list[i + 1]; (p = q) != NULL; ) {
q = p->ipo_next;
- (void) ip_pool_destroy(i, p->ipo_name);
+ (void) ipf_pool_destroy(softc, arg, i, p->ipo_name);
}
}
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ipf_pool_soft_destroy */
+/* Returns: Nil */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* arg(I) - pointer to local context to use */
+/* */
+/* Clean up the pool by free'ing the radix tree associated with it and free */
+/* up the pool context too. */
+/* ------------------------------------------------------------------------ */
+static void
+ipf_pool_soft_destroy(softc, arg)
+ ipf_main_softc_t *softc;
+ void *arg;
+{
+ ipf_pool_softc_t *softp = arg;
+
+ ipf_rx_destroy(softp->ipf_radix);
+
+ KFREE(softp);
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ipf_pool_node_add */
+/* Returns: int - 0 = success, else error */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* arg(I) - pointer to local context to use */
+/* op(I) - pointer to lookup operatin data */
+/* */
+/* When adding a new node, a check is made to ensure that the address/mask */
+/* pair supplied has been appropriately prepared by applying the mask to */
+/* the address prior to calling for the pair to be added. */
+/* ------------------------------------------------------------------------ */
+static int
+ipf_pool_node_add(softc, arg, op, uid)
+ ipf_main_softc_t *softc;
+ void *arg;
+ iplookupop_t *op;
+ int uid;
+{
+ ip_pool_node_t node, *m;
+ ip_pool_t *p;
+ int err;
-#if (!defined(_KERNEL) || (BSD < 199306))
- rn_fini();
+ if (op->iplo_size != sizeof(node)) {
+ IPFERROR(70014);
+ return EINVAL;
+ }
+
+ err = COPYIN(op->iplo_struct, &node, sizeof(node));
+ if (err != 0) {
+ IPFERROR(70015);
+ return EFAULT;
+ }
+
+ p = ipf_pool_find(arg, op->iplo_unit, op->iplo_name);
+ if (p == NULL) {
+ IPFERROR(70017);
+ return ESRCH;
+ }
+
+ if (node.ipn_addr.adf_family == AF_INET) {
+ if (node.ipn_addr.adf_len != offsetof(addrfamily_t, adf_addr) +
+ sizeof(struct in_addr)) {
+ IPFERROR(70028);
+ return EINVAL;
+ }
+ }
+#ifdef USE_INET6
+ else if (node.ipn_addr.adf_family == AF_INET6) {
+ if (node.ipn_addr.adf_len != offsetof(addrfamily_t, adf_addr) +
+ sizeof(struct in6_addr)) {
+ IPFERROR(70034);
+ return EINVAL;
+ }
+ }
+#endif
+ if (node.ipn_mask.adf_len != node.ipn_addr.adf_len) {
+ IPFERROR(70029);
+ return EINVAL;
+ }
+
+ /*
+ * Check that the address/mask pair works.
+ */
+ if (node.ipn_addr.adf_family == AF_INET) {
+ if ((node.ipn_addr.adf_addr.in4.s_addr &
+ node.ipn_mask.adf_addr.in4.s_addr) !=
+ node.ipn_addr.adf_addr.in4.s_addr) {
+ IPFERROR(70035);
+ return EINVAL;
+ }
+ }
+#ifdef USE_INET6
+ else if (node.ipn_addr.adf_family == AF_INET6) {
+ if (IP6_MASKNEQ(&node.ipn_addr.adf_addr.in6,
+ &node.ipn_mask.adf_addr.in6,
+ &node.ipn_addr.adf_addr.in6)) {
+ IPFERROR(70036);
+ return EINVAL;
+ }
+ }
#endif
+
+ /*
+ * add an entry to a pool - return an error if it already
+ * exists remove an entry from a pool - if it exists
+ * - in both cases, the pool *must* exist!
+ */
+ m = ipf_pool_findeq(arg, p, &node.ipn_addr, &node.ipn_mask);
+ if (m != NULL) {
+ IPFERROR(70018);
+ return EEXIST;
+ }
+ err = ipf_pool_insert_node(softc, arg, p, &node);
+
+ return err;
}
/* ------------------------------------------------------------------------ */
-/* Function: ip_pool_statistics */
-/* Returns: int - 0 = success, else error */
-/* Parameters: op(I) - pointer to lookup operation arguments */
+/* Function: ipf_pool_node_del */
+/* Returns: int - 0 = success, else error */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* arg(I) - pointer to local context to use */
+/* op(I) - pointer to lookup operatin data */
+/* */
+/* ------------------------------------------------------------------------ */
+static int
+ipf_pool_node_del(softc, arg, op, uid)
+ ipf_main_softc_t *softc;
+ void *arg;
+ iplookupop_t *op;
+ int uid;
+{
+ ip_pool_node_t node, *m;
+ ip_pool_t *p;
+ int err;
+
+
+ if (op->iplo_size != sizeof(node)) {
+ IPFERROR(70019);
+ return EINVAL;
+ }
+ node.ipn_uid = uid;
+
+ err = COPYIN(op->iplo_struct, &node, sizeof(node));
+ if (err != 0) {
+ IPFERROR(70020);
+ return EFAULT;
+ }
+
+ if (node.ipn_addr.adf_family == AF_INET) {
+ if (node.ipn_addr.adf_len != offsetof(addrfamily_t, adf_addr) +
+ sizeof(struct in_addr)) {
+ IPFERROR(70030);
+ return EINVAL;
+ }
+ }
+#ifdef USE_INET6
+ else if (node.ipn_addr.adf_family == AF_INET6) {
+ if (node.ipn_addr.adf_len != offsetof(addrfamily_t, adf_addr) +
+ sizeof(struct in6_addr)) {
+ IPFERROR(70037);
+ return EINVAL;
+ }
+ }
+#endif
+ if (node.ipn_mask.adf_len != node.ipn_addr.adf_len) {
+ IPFERROR(70031);
+ return EINVAL;
+ }
+
+ p = ipf_pool_find(arg, op->iplo_unit, op->iplo_name);
+ if (p == NULL) {
+ IPFERROR(70021);
+ return ESRCH;
+ }
+
+ m = ipf_pool_findeq(arg, p, &node.ipn_addr, &node.ipn_mask);
+ if (m == NULL) {
+ IPFERROR(70022);
+ return ENOENT;
+ }
+
+ if ((uid != 0) && (uid != m->ipn_uid)) {
+ IPFERROR(70024);
+ return EACCES;
+ }
+
+ err = ipf_pool_remove_node(softc, arg, p, m);
+
+ return err;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ipf_pool_table_add */
+/* Returns: int - 0 = success, else error */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* arg(I) - pointer to local context to use */
+/* op(I) - pointer to lookup operatin data */
+/* */
+/* ------------------------------------------------------------------------ */
+static int
+ipf_pool_table_add(softc, arg, op)
+ ipf_main_softc_t *softc;
+ void *arg;
+ iplookupop_t *op;
+{
+ int err;
+
+ if (((op->iplo_arg & LOOKUP_ANON) == 0) &&
+ (ipf_pool_find(arg, op->iplo_unit, op->iplo_name) != NULL)) {
+ IPFERROR(70023);
+ err = EEXIST;
+ } else {
+ err = ipf_pool_create(softc, arg, op);
+ }
+
+ return err;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ipf_pool_table_del */
+/* Returns: int - 0 = success, else error */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* arg(I) - pointer to local context to use */
+/* op(I) - pointer to lookup operatin data */
+/* */
+/* ------------------------------------------------------------------------ */
+static int
+ipf_pool_table_del(softc, arg, op)
+ ipf_main_softc_t *softc;
+ void *arg;
+ iplookupop_t *op;
+{
+ return ipf_pool_destroy(softc, arg, op->iplo_unit, op->iplo_name);
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ipf_pool_statistics */
+/* Returns: int - 0 = success, else error */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* arg(I) - pointer to local context to use */
+/* op(I) - pointer to lookup operatin data */
/* */
/* 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;
+static int
+ipf_pool_stats_get(softc, arg, op)
+ ipf_main_softc_t *softc;
+ void *arg;
+ iplookupop_t *op;
{
- ip_pool_stat_t stats;
+ ipf_pool_softc_t *softp = arg;
+ ipf_pool_stat_t stats;
int unit, i, err = 0;
- if (op->iplo_size != sizeof(ipoolstat))
+ if (op->iplo_size != sizeof(ipf_pool_stat_t)) {
+ IPFERROR(70001);
return EINVAL;
+ }
- bcopy((char *)&ipoolstat, (char *)&stats, sizeof(stats));
+ bcopy((char *)&softp->ipf_pool_stats, (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) {
+ for (i = 0; i <= LOOKUP_POOL_MAX; i++)
+ stats.ipls_list[i] = softp->ipf_pool_list[i];
+ } else if (unit >= 0 && unit <= IPL_LOGMAX) {
+ unit++; /* -1 => 0 */
if (op->iplo_name[0] != '\0')
- stats.ipls_list[unit] = ip_pool_exists(unit,
- op->iplo_name);
+ stats.ipls_list[unit] = ipf_pool_exists(softp, unit - 1,
+ op->iplo_name);
else
- stats.ipls_list[unit] = ip_pool_list[unit];
- } else
+ stats.ipls_list[unit] = softp->ipf_pool_list[unit];
+ } else {
+ IPFERROR(70025);
err = EINVAL;
- if (err == 0)
+ }
+ if (err == 0) {
err = COPYOUT(&stats, op->iplo_struct, sizeof(stats));
- return err;
+ if (err != 0) {
+ IPFERROR(70026);
+ return EFAULT;
+ }
+ }
+ return 0;
}
/* ------------------------------------------------------------------------ */
-/* Function: ip_pool_exists */
-/* Returns: int - 0 = success, else error */
-/* Parameters: ipo(I) - pointer to the pool getting the new node. */
+/* Function: ipf_pool_exists */
+/* Returns: int - 0 = success, else error */
+/* Parameters: softp(I) - pointer to soft context pool information */
+/* unit(I) - ipfilter device to which we are working on */
+/* name(I) - name of the pool */
/* */
/* 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;
+static void *
+ipf_pool_exists(softp, unit, name)
+ ipf_pool_softc_t *softp;
+ int unit;
+ char *name;
{
ip_pool_t *p;
+ int i;
- for (p = ip_pool_list[unit]; p != NULL; p = p->ipo_next)
- if (strncmp(p->ipo_name, name, sizeof(p->ipo_name)) == 0)
- break;
+ if (unit == IPL_LOGALL) {
+ for (i = 0; i <= LOOKUP_POOL_MAX; i++) {
+ for (p = softp->ipf_pool_list[i]; p != NULL;
+ p = p->ipo_next) {
+ if (strncmp(p->ipo_name, name,
+ sizeof(p->ipo_name)) == 0)
+ break;
+ }
+ if (p != NULL)
+ break;
+ }
+ } else {
+ for (p = softp->ipf_pool_list[unit + 1]; 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. */
+/* Function: ipf_pool_find */
+/* Returns: int - 0 = success, else error */
+/* Parameters: arg(I) - pointer to local context to use */
+/* unit(I) - ipfilter device to which we are working on */
+/* name(I) - name of the pool */
/* */
/* 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;
+static void *
+ipf_pool_find(arg, unit, name)
+ void *arg;
+ int unit;
+ char *name;
{
+ ipf_pool_softc_t *softp = arg;
ip_pool_t *p;
- p = ip_pool_exists(unit, name);
+ p = ipf_pool_exists(softp, unit, name);
if ((p != NULL) && (p->ipo_flags & IPOOL_DELETE))
return NULL;
@@ -362,45 +703,75 @@ char *name;
/* ------------------------------------------------------------------------ */
-/* Function: ip_pool_findeq */
+/* Function: ipf_pool_select_add_ref */
+/* Returns: int - 0 = success, else error */
+/* Parameters: arg(I) - pointer to local context to use */
+/* unit(I) - ipfilter device to which we are working on */
+/* name(I) - name of the pool */
+/* */
+/* ------------------------------------------------------------------------ */
+static void *
+ipf_pool_select_add_ref(arg, unit, name)
+ void *arg;
+ int unit;
+ char *name;
+{
+ ip_pool_t *p;
+
+ p = ipf_pool_find(arg, -1, name);
+ if (p == NULL)
+ p = ipf_pool_find(arg, unit, name);
+ if (p != NULL) {
+ ATOMIC_INC32(p->ipo_ref);
+ }
+ return p;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ipf_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) - */
+/* Parameters: softp(I) - pointer to soft context pool information */
+/* ipo(I) - pointer to the pool getting the new node. */
+/* addr(I) - pointer to address information to match on */
+/* mask(I) - pointer to the address mask to match */
/* */
/* 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;
+extern void printhostmask __P((int, u_32_t *, u_32_t *));
+static ip_pool_node_t *
+ipf_pool_findeq(softp, ipo, addr, mask)
+ ipf_pool_softc_t *softp;
+ 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);
+ ipf_rdx_node_t *n;
+
+ n = ipo->ipo_head->lookup(ipo->ipo_head, addr, mask);
return (ip_pool_node_t *)n;
}
/* ------------------------------------------------------------------------ */
-/* Function: ip_pool_search */
+/* Function: ipf_pool_search */
/* Returns: int - 0 == +ve match, -1 == error, 1 == -ve/no match */
-/* Parameters: tptr(I) - pointer to the pool to search */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* tptr(I) - pointer to the pool to search */
/* version(I) - IP protocol version (4 or 6) */
/* dptr(I) - pointer to address information */
+/* bytes(I) - length of packet */
/* */
/* 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;
+static int
+ipf_pool_search(softc, tptr, ipversion, dptr, bytes)
+ ipf_main_softc_t *softc;
+ void *tptr;
+ int ipversion;
+ void *dptr;
+ u_int bytes;
{
- struct radix_node *rn;
+ ipf_rdx_node_t *rn;
ip_pool_node_t *m;
i6addr_t *addr;
addrfamily_t v;
@@ -415,102 +786,154 @@ void *dptr;
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_family = AF_INET;
+ v.adf_len = offsetof(addrfamily_t, adf_addr) +
+ sizeof(struct in_addr);
v.adf_addr.in4 = addr->in4;
#ifdef USE_INET6
} else if (ipversion == 6) {
- v.adf_len += sizeof(addr->in6);
+ v.adf_family = AF_INET6;
+ v.adf_len = offsetof(addrfamily_t, adf_addr) +
+ sizeof(struct in6_addr);
v.adf_addr.in6 = addr->in6;
#endif
} else
return -1;
- READ_ENTER(&ip_poolrw);
+ READ_ENTER(&softc->ipf_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);
+ rn = ipo->ipo_head->matchaddr(ipo->ipo_head, &v);
- if ((rn != NULL) && ((rn->rn_flags & RNF_ROOT) == 0)) {
+ if ((rn != NULL) && (rn->root == 0)) {
m = (ip_pool_node_t *)rn;
ipo->ipo_hits++;
+ m->ipn_bytes += bytes;
m->ipn_hits++;
rv = m->ipn_info;
}
- RWLOCK_EXIT(&ip_poolrw);
+ RWLOCK_EXIT(&softc->ipf_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) */
+/* Function: ipf_pool_insert_node */
+/* Returns: int - 0 = success, else error */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* softp(I) - pointer to soft context pool information */
+/* ipo(I) - pointer to the pool getting the new node. */
+/* node(I) - structure with address/mask to add */
+/* Locks: WRITE(ipf_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;
+static int
+ipf_pool_insert_node(softc, softp, ipo, node)
+ ipf_main_softc_t *softc;
+ ipf_pool_softc_t *softp;
+ ip_pool_t *ipo;
+ struct ip_pool_node *node;
{
- struct radix_node *rn;
+ ipf_rdx_node_t *rn;
ip_pool_node_t *x;
+ if ((node->ipn_addr.adf_len > sizeof(*rn)) ||
+ (node->ipn_addr.adf_len < 4)) {
+ IPFERROR(70003);
+ return EINVAL;
+ }
+
+ if ((node->ipn_mask.adf_len > sizeof(*rn)) ||
+ (node->ipn_mask.adf_len < 4)) {
+ IPFERROR(70004);
+ return EINVAL;
+ }
+
KMALLOC(x, ip_pool_node_t *);
if (x == NULL) {
+ IPFERROR(70002);
return ENOMEM;
}
- bzero(x, sizeof(*x));
-
- x->ipn_info = info;
- (void)strncpy(x->ipn_name, ipo->ipo_name, sizeof(x->ipn_name));
+ *x = *node;
+ bzero((char *)x->ipn_nodes, sizeof(x->ipn_nodes));
+ x->ipn_owner = ipo;
+ x->ipn_hits = 0;
+ x->ipn_next = NULL;
+ x->ipn_pnext = NULL;
+ x->ipn_dnext = NULL;
+ x->ipn_pdnext = NULL;
+
+ if (x->ipn_die != 0) {
+ /*
+ * If the new node has a given expiration time, insert it
+ * into the list of expiring nodes with the ones to be
+ * removed first added to the front of the list. The
+ * insertion is O(n) but it is kept sorted for quick scans
+ * at expiration interval checks.
+ */
+ ip_pool_node_t *n;
+
+ x->ipn_die = softc->ipf_ticks + IPF_TTLVAL(x->ipn_die);
+ for (n = softp->ipf_node_explist; n != NULL; n = n->ipn_dnext) {
+ if (x->ipn_die < n->ipn_die)
+ break;
+ if (n->ipn_dnext == NULL) {
+ /*
+ * We've got to the last node and everything
+ * wanted to be expired before this new node,
+ * so we have to tack it on the end...
+ */
+ n->ipn_dnext = x;
+ x->ipn_pdnext = &n->ipn_dnext;
+ n = NULL;
+ break;
+ }
+ }
- 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);
+ if (softp->ipf_node_explist == NULL) {
+ softp->ipf_node_explist = x;
+ x->ipn_pdnext = &softp->ipf_node_explist;
+ } else if (n != NULL) {
+ x->ipn_dnext = n;
+ x->ipn_pdnext = n->ipn_pdnext;
+ n->ipn_pdnext = &x->ipn_dnext;
+ }
+ }
- 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);
+ rn = ipo->ipo_head->addaddr(ipo->ipo_head, &x->ipn_addr, &x->ipn_mask,
+ x->ipn_nodes);
#ifdef DEBUG_POOL
printf("Added %p at %p\n", x, rn);
#endif
if (rn == NULL) {
KFREE(x);
+ IPFERROR(70005);
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;
+ x->ipn_pnext = ipo->ipo_tail;
+ *ipo->ipo_tail = x;
+ ipo->ipo_tail = &x->ipn_next;
- ipoolstat.ipls_nodes++;
+ softp->ipf_pool_stats.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) */
+/* Function: ipf_pool_create */
+/* Returns: int - 0 = success, else error */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* softp(I) - pointer to soft context pool information */
+/* op(I) - pointer to iplookup struct with call details */
+/* Locks: WRITE(ipf_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 */
@@ -522,8 +945,11 @@ int info;
/* 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;
+static int
+ipf_pool_create(softc, softp, op)
+ ipf_main_softc_t *softc;
+ ipf_pool_softc_t *softp;
+ iplookupop_t *op;
{
char name[FR_GROUPLEN];
int poolnum, unit;
@@ -532,23 +958,27 @@ iplookupop_t *op;
unit = op->iplo_unit;
if ((op->iplo_arg & LOOKUP_ANON) == 0) {
- h = ip_pool_exists(unit, op->iplo_name);
+ h = ipf_pool_exists(softp, unit, op->iplo_name);
if (h != NULL) {
- if ((h->ipo_flags & IPOOL_DELETE) == 0)
+ if ((h->ipo_flags & IPOOL_DELETE) == 0) {
+ IPFERROR(70006);
return EEXIST;
+ }
h->ipo_flags &= ~IPOOL_DELETE;
return 0;
}
}
KMALLOC(h, ip_pool_t *);
- if (h == NULL)
+ if (h == NULL) {
+ IPFERROR(70007);
return ENOMEM;
+ }
bzero(h, sizeof(*h));
- if (rn_inithead((void **)&h->ipo_head,
- offsetof(addrfamily_t, adf_addr) << 3) == 0) {
+ if (ipf_rx_inithead(softp->ipf_radix, &h->ipo_head) != 0) {
KFREE(h);
+ IPFERROR(70008);
return ENOMEM;
}
@@ -564,7 +994,7 @@ iplookupop_t *op;
(void)sprintf(name, "%x", poolnum);
#endif
- for (p = ip_pool_list[unit]; p != NULL; ) {
+ for (p = softp->ipf_pool_list[unit + 1]; p != NULL; ) {
if (strncmp(name, p->ipo_name,
sizeof(p->ipo_name)) == 0) {
poolnum++;
@@ -573,7 +1003,7 @@ iplookupop_t *op;
#else
(void)sprintf(name, "%x", poolnum);
#endif
- p = ip_pool_list[unit];
+ p = softp->ipf_pool_list[unit + 1];
} else
p = p->ipo_next;
}
@@ -584,121 +1014,144 @@ iplookupop_t *op;
(void)strncpy(h->ipo_name, op->iplo_name, sizeof(h->ipo_name));
}
+ h->ipo_radix = softp->ipf_radix;
h->ipo_ref = 1;
h->ipo_list = NULL;
+ h->ipo_tail = &h->ipo_list;
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;
+ h->ipo_next = softp->ipf_pool_list[unit + 1];
+ if (softp->ipf_pool_list[unit + 1] != NULL)
+ softp->ipf_pool_list[unit + 1]->ipo_pnext = &h->ipo_next;
+ h->ipo_pnext = &softp->ipf_pool_list[unit + 1];
+ softp->ipf_pool_list[unit + 1] = h;
- ipoolstat.ipls_pools++;
+ softp->ipf_pool_stats.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) */
+/* Function: ipf_pool_remove_node */
+/* Returns: int - 0 = success, else error */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* ipo(I) - pointer to the pool to remove the node from. */
+/* ipe(I) - address being deleted as a node */
+/* Locks: WRITE(ipf_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;
+static int
+ipf_pool_remove_node(softc, softp, ipo, ipe)
+ ipf_main_softc_t *softc;
+ ipf_pool_softc_t *softp;
+ ip_pool_t *ipo;
+ ip_pool_node_t *ipe;
{
+ void *ptr;
+
+ if (ipo->ipo_tail == &ipe->ipn_next)
+ ipo->ipo_tail = ipe->ipn_pnext;
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);
+ if (ipe->ipn_pdnext != NULL)
+ *ipe->ipn_pdnext = ipe->ipn_dnext;
+ if (ipe->ipn_dnext != NULL)
+ ipe->ipn_dnext->ipn_pdnext = ipe->ipn_pdnext;
- ip_pool_node_deref(ipe);
+ ptr = ipo->ipo_head->deladdr(ipo->ipo_head, &ipe->ipn_addr,
+ &ipe->ipn_mask);
- return 0;
+ if (ptr != NULL) {
+ ipf_pool_node_deref(softp, ipe);
+ return 0;
+ }
+ IPFERROR(70027);
+ return ESRCH;
}
/* ------------------------------------------------------------------------ */
-/* Function: ip_pool_destroy */
+/* Function: ipf_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) */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* softp(I) - pointer to soft context pool information */
+/* unit(I) - ipfilter device to which we are working on */
+/* name(I) - name of the pool */
+/* Locks: WRITE(ipf_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 */
+/* NOTE: Because this function is called out of ipfdetach() where ipf_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. */
+/* assertion that one of the two (ipf_poolrw,ipf_global) is held. */
/* ------------------------------------------------------------------------ */
-int ip_pool_destroy(unit, name)
-int unit;
-char *name;
+static int
+ipf_pool_destroy(softc, softp, unit, name)
+ ipf_main_softc_t *softc;
+ ipf_pool_softc_t *softp;
+ int unit;
+ char *name;
{
ip_pool_t *ipo;
- ipo = ip_pool_exists(unit, name);
- if (ipo == NULL)
+ ipo = ipf_pool_exists(softp, unit, name);
+ if (ipo == NULL) {
+ IPFERROR(70009);
return ESRCH;
+ }
if (ipo->ipo_ref != 1) {
- ip_pool_clearnodes(ipo);
+ ipf_pool_clearnodes(softc, softp, ipo);
ipo->ipo_flags |= IPOOL_DELETE;
return 0;
}
- ip_pool_free(ipo);
+ ipf_pool_free(softc, softp, ipo);
return 0;
}
/* ------------------------------------------------------------------------ */
-/* Function: ip_pool_flush */
+/* Function: ipf_pool_flush */
/* Returns: int - number of pools deleted */
-/* Parameters: fp(I) - which pool(s) to flush */
-/* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* arg(I) - pointer to local context to use */
+/* fp(I) - which pool(s) to flush */
+/* Locks: WRITE(ipf_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 */
+/* NOTE: Because this function is called out of ipfdetach() where ipf_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. */
+/* assertion that one of the two (ipf_poolrw,ipf_global) is held. */
/* ------------------------------------------------------------------------ */
-int ip_pool_flush(fp)
-iplookupflush_t *fp;
+static size_t
+ipf_pool_flush(softc, arg, fp)
+ ipf_main_softc_t *softc;
+ void *arg;
+ iplookupflush_t *fp;
{
+ ipf_pool_softc_t *softp = arg;
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++) {
+ for (i = -1; 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));
+ for (q = softp->ipf_pool_list[i + 1]; (p = q) != NULL; ) {
q = p->ipo_next;
- err = ip_pool_destroy(op.iplo_unit, op.iplo_name);
+ err = ipf_pool_destroy(softc, softp, i, p->ipo_name);
if (err == 0)
num++;
- else
- break;
}
}
return num;
@@ -706,125 +1159,140 @@ iplookupflush_t *fp;
/* ------------------------------------------------------------------------ */
-/* Function: ip_pool_free */
+/* Function: ipf_pool_free */
/* Returns: void */
-/* Parameters: ipo(I) - pointer to pool structure */
-/* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* softp(I) - pointer to soft context pool information */
+/* ipo(I) - pointer to pool structure */
+/* Locks: WRITE(ipf_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 */
+/* NOTE: Because this function is called out of ipfdetach() where ipf_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. */
+/* assertion that one of the two (ipf_poolrw,ipf_global) is held. */
/* ------------------------------------------------------------------------ */
-void ip_pool_free(ipo)
-ip_pool_t *ipo;
+static void
+ipf_pool_free(softc, softp, ipo)
+ ipf_main_softc_t *softc;
+ ipf_pool_softc_t *softp;
+ ip_pool_t *ipo;
{
- ip_pool_clearnodes(ipo);
+ ipf_pool_clearnodes(softc, softp, 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);
+ ipf_rx_freehead(ipo->ipo_head);
KFREE(ipo);
- ipoolstat.ipls_pools--;
+ softp->ipf_pool_stats.ipls_pools--;
}
/* ------------------------------------------------------------------------ */
-/* Function: ip_pool_clearnodes */
+/* Function: ipf_pool_clearnodes */
/* Returns: void */
-/* Parameters: ipo(I) - pointer to pool structure */
-/* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* softp(I) - pointer to soft context pool information */
+/* ipo(I) - pointer to pool structure */
+/* Locks: WRITE(ipf_poolrw) or WRITE(ipf_global) */
/* */
/* Deletes all nodes stored in a pool structure. */
/* ------------------------------------------------------------------------ */
-static void ip_pool_clearnodes(ipo)
-ip_pool_t *ipo;
+static void
+ipf_pool_clearnodes(softc, softp, ipo)
+ ipf_main_softc_t *softc;
+ ipf_pool_softc_t *softp;
+ 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);
+ ip_pool_node_t *n, **next;
- ipoolstat.ipls_nodes--;
- }
- RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head);
+ for (next = &ipo->ipo_list; (n = *next) != NULL; )
+ ipf_pool_remove_node(softc, softp, ipo, n);
ipo->ipo_list = NULL;
}
/* ------------------------------------------------------------------------ */
-/* Function: ip_pool_deref */
+/* Function: ipf_pool_deref */
/* Returns: void */
-/* Parameters: ipo(I) - pointer to pool structure */
-/* Locks: WRITE(ip_poolrw) */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* arg(I) - pointer to local context to use */
+/* pool(I) - pointer to pool structure */
+/* Locks: WRITE(ipf_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;
+static int
+ipf_pool_deref(softc, arg, pool)
+ ipf_main_softc_t *softc;
+ void *arg, *pool;
{
+ ip_pool_t *ipo = pool;
ipo->ipo_ref--;
if (ipo->ipo_ref == 0)
- ip_pool_free(ipo);
+ ipf_pool_free(softc, arg, ipo);
else if ((ipo->ipo_ref == 1) && (ipo->ipo_flags & IPOOL_DELETE))
- ip_pool_destroy(ipo->ipo_unit, ipo->ipo_name);
+ ipf_pool_destroy(softc, arg, ipo->ipo_unit, ipo->ipo_name);
+
+ return 0;
}
/* ------------------------------------------------------------------------ */
-/* Function: ip_pool_node_deref */
+/* Function: ipf_pool_node_deref */
/* Returns: void */
-/* Parameters: ipn(I) - pointer to pool structure */
-/* Locks: WRITE(ip_poolrw) */
+/* Parameters: softp(I) - pointer to soft context pool information */
+/* ipn(I) - pointer to pool structure */
+/* Locks: WRITE(ipf_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;
+static void
+ipf_pool_node_deref(softp, ipn)
+ ipf_pool_softc_t *softp;
+ ip_pool_node_t *ipn;
{
ipn->ipn_ref--;
if (ipn->ipn_ref == 0) {
KFREE(ipn);
- ipoolstat.ipls_nodes--;
+ softp->ipf_pool_stats.ipls_nodes--;
}
}
/* ------------------------------------------------------------------------ */
-/* Function: ip_pool_getnext */
+/* Function: ipf_pool_iter_next */
/* Returns: void */
-/* Parameters: token(I) - pointer to pool structure */
-/* Parameters: ilp(IO) - pointer to pool iterating structure */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* arg(I) - pointer to local context to use */
+/* token(I) - pointer to pool structure */
+/* ilp(IO) - pointer to pool iterating structure */
/* */
/* ------------------------------------------------------------------------ */
-int ip_pool_getnext(token, ilp)
-ipftoken_t *token;
-ipflookupiter_t *ilp;
+static int
+ipf_pool_iter_next(softc, arg, token, ilp)
+ ipf_main_softc_t *softc;
+ void *arg;
+ ipftoken_t *token;
+ ipflookupiter_t *ilp;
{
+ ipf_pool_softc_t *softp = arg;
ip_pool_node_t *node, zn, *nextnode;
ip_pool_t *ipo, zp, *nextipo;
+ void *pnext;
int err;
err = 0;
@@ -833,35 +1301,38 @@ ipflookupiter_t *ilp;
ipo = NULL;
nextipo = NULL;
- READ_ENTER(&ip_poolrw);
+ READ_ENTER(&softc->ipf_poolrw);
switch (ilp->ili_otype)
{
case IPFLOOKUPITER_LIST :
ipo = token->ipt_data;
if (ipo == NULL) {
- nextipo = ip_pool_list[(int)ilp->ili_unit];
+ nextipo = softp->ipf_pool_list[(int)ilp->ili_unit + 1];
} else {
nextipo = ipo->ipo_next;
}
if (nextipo != NULL) {
- ATOMIC_INC(nextipo->ipo_ref);
+ ATOMIC_INC32(nextipo->ipo_ref);
token->ipt_data = nextipo;
} else {
bzero((char *)&zp, sizeof(zp));
nextipo = &zp;
token->ipt_data = NULL;
}
+ pnext = nextipo->ipo_next;
break;
case IPFLOOKUPITER_NODE :
node = token->ipt_data;
if (node == NULL) {
- ipo = ip_pool_exists(ilp->ili_unit, ilp->ili_name);
- if (ipo == NULL)
+ ipo = ipf_pool_exists(arg, ilp->ili_unit,
+ ilp->ili_name);
+ if (ipo == NULL) {
+ IPFERROR(70010);
err = ESRCH;
- else {
+ } else {
nextnode = ipo->ipo_list;
ipo = NULL;
}
@@ -870,123 +1341,149 @@ ipflookupiter_t *ilp;
}
if (nextnode != NULL) {
- ATOMIC_INC(nextnode->ipn_ref);
+ ATOMIC_INC32(nextnode->ipn_ref);
token->ipt_data = nextnode;
} else {
bzero((char *)&zn, sizeof(zn));
nextnode = &zn;
token->ipt_data = NULL;
}
+ pnext = nextnode->ipn_next;
break;
+
default :
+ IPFERROR(70011);
+ pnext = NULL;
err = EINVAL;
break;
}
- RWLOCK_EXIT(&ip_poolrw);
-
+ RWLOCK_EXIT(&softc->ipf_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)
+ if (err != 0) {
+ IPFERROR(70012);
err = EFAULT;
+ }
+ if (ipo != NULL) {
+ WRITE_ENTER(&softc->ipf_poolrw);
+ ipf_pool_deref(softc, softp, ipo);
+ RWLOCK_EXIT(&softc->ipf_poolrw);
+ }
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)
+ if (err != 0) {
+ IPFERROR(70013);
err = EFAULT;
+ }
+ if (node != NULL) {
+ WRITE_ENTER(&softc->ipf_poolrw);
+ ipf_pool_node_deref(softp, node);
+ RWLOCK_EXIT(&softc->ipf_poolrw);
+ }
break;
}
+ if (pnext == NULL)
+ ipf_token_mark_complete(token);
return err;
}
/* ------------------------------------------------------------------------ */
-/* Function: ip_pool_iterderef */
+/* Function: ipf_pool_iterderef */
/* Returns: void */
-/* Parameters: ipn(I) - pointer to pool structure */
-/* Locks: WRITE(ip_poolrw) */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* arg(I) - pointer to local context to use */
+/* unit(I) - ipfilter device to which we are working on */
+/* Locks: WRITE(ipf_poolrw) */
/* */
/* ------------------------------------------------------------------------ */
-void ip_pool_iterderef(otype, unit, data)
-u_int otype;
-int unit;
-void *data;
+static int
+ipf_pool_iter_deref(softc, arg, otype, unit, data)
+ ipf_main_softc_t *softc;
+ void *arg;
+ int otype;
+ int unit;
+ void *data;
{
+ ipf_pool_softc_t *softp = arg;
if (data == NULL)
- return;
+ return EINVAL;
if (unit < 0 || unit > IPL_LOGMAX)
- return;
+ return EINVAL;
switch (otype)
{
case IPFLOOKUPITER_LIST :
- WRITE_ENTER(&ip_poolrw);
- ip_pool_deref((ip_pool_t *)data);
- RWLOCK_EXIT(&ip_poolrw);
+ ipf_pool_deref(softc, softp, (ip_pool_t *)data);
break;
case IPFLOOKUPITER_NODE :
- WRITE_ENTER(&ip_poolrw);
- ip_pool_node_deref((ip_pool_node_t *)data);
- RWLOCK_EXIT(&ip_poolrw);
+ ipf_pool_node_deref(softp, (ip_pool_node_t *)data);
break;
default :
break;
}
+
+ return 0;
}
-# if defined(_KERNEL) && ((BSD >= 198911) && !defined(__osf__) && \
- !defined(__hpux) && !defined(__sgi))
-static int
-rn_freenode(struct radix_node *n, void *p)
+/* ------------------------------------------------------------------------ */
+/* Function: ipf_pool_expire */
+/* Returns: Nil */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* arg(I) - pointer to local context to use */
+/* */
+/* At present this function exists just to support temporary addition of */
+/* nodes to the address pool. */
+/* ------------------------------------------------------------------------ */
+static void
+ipf_pool_expire(softc, arg)
+ ipf_main_softc_t *softc;
+ void *arg;
{
- struct radix_node_head *rnh = p;
- struct radix_node *d;
+ ipf_pool_softc_t *softp = arg;
+ ip_pool_node_t *n;
- d = rnh->rnh_deladdr(n->rn_key, NULL, rnh);
- if (d != NULL) {
- FreeS(d, max_keylen + 2 * sizeof (*d));
+ while ((n = softp->ipf_node_explist) != NULL) {
+ /*
+ * Because the list is kept sorted on insertion, the fist
+ * one that dies in the future means no more work to do.
+ */
+ if (n->ipn_die > softc->ipf_ticks)
+ break;
+ ipf_pool_remove_node(softc, softp, n->ipn_owner, n);
}
- 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);
+#ifndef _KERNEL
+void
+ipf_pool_dump(softc, arg)
+ ipf_main_softc_t *softc;
+ void *arg;
+{
+ ipf_pool_softc_t *softp = arg;
+ ip_pool_t *ipl;
+ int i;
- Free(rnh);
+ printf("List of configured pools\n");
+ for (i = 0; i <= LOOKUP_POOL_MAX; i++)
+ for (ipl = softp->ipf_pool_list[i]; ipl != NULL;
+ ipl = ipl->ipo_next)
+ printpool(ipl, bcopywrap, NULL, opts, NULL);
}
-# endif
-#endif /* IPFILTER_LOOKUP */
+#endif
OpenPOWER on IntegriCloud