summaryrefslogtreecommitdiffstats
path: root/sys/contrib/ipfilter/netinet/ip_lookup.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/ipfilter/netinet/ip_lookup.c')
-rw-r--r--sys/contrib/ipfilter/netinet/ip_lookup.c935
1 files changed, 622 insertions, 313 deletions
diff --git a/sys/contrib/ipfilter/netinet/ip_lookup.c b/sys/contrib/ipfilter/netinet/ip_lookup.c
index e33a6fe..45999e0 100644
--- a/sys/contrib/ipfilter/netinet/ip_lookup.c
+++ b/sys/contrib/ipfilter/netinet/ip_lookup.c
@@ -1,5 +1,6 @@
+/* $FreeBSD$ */
/*
- * Copyright (C) 2002-2003 by Darren Reed.
+ * Copyright (C) 2012 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*/
@@ -24,7 +25,9 @@
# include <sys/ioctl.h>
#endif
#if !defined(_KERNEL)
+# include <stdio.h>
# include <string.h>
+# include <stdlib.h>
# define _KERNEL
# ifdef __OpenBSD__
struct file;
@@ -33,106 +36,223 @@ struct file;
# undef _KERNEL
#endif
#include <sys/socket.h>
-#if (defined(__osf__) || defined(AIX) || defined(__hpux) || defined(__sgi)) && defined(_KERNEL)
-# include "radix_ipf_local.h"
-# define _RADIX_H_
-#endif
#include <net/if.h>
#if defined(__FreeBSD__)
-# include <sys/cdefs.h>
-# include <sys/proc.h>
+# include <sys/cdefs.h>
+# include <sys/proc.h>
#endif
#if defined(_KERNEL)
# include <sys/systm.h>
# if !defined(__SVR4) && !defined(__svr4__)
# include <sys/mbuf.h>
# endif
+#else
+# include "ipf.h"
#endif
#include <netinet/in.h>
#include "netinet/ip_compat.h"
#include "netinet/ip_fil.h"
+#include "netinet/ip_lookup.h"
#include "netinet/ip_pool.h"
#include "netinet/ip_htable.h"
-#include "netinet/ip_lookup.h"
+#include "netinet/ip_dstlist.h"
/* END OF INCLUDES */
#if !defined(lint)
-static const char rcsid[] = "@(#)$Id: ip_lookup.c,v 2.35.2.19 2007/10/11 09:05:51 darrenr Exp $";
+static const char rcsid[] = "@(#)$Id$";
#endif
-#ifdef IPFILTER_LOOKUP
-int ip_lookup_inited = 0;
+/*
+ * In this file, ip_pool.c, ip_htable.c and ip_dstlist.c, you will find the
+ * range for unit is [-1,IPL_LOGMAX]. The -1 is considered to be a valid number
+ * and represents a "wildcard" or "all" units (IPL_LOGALL). The reason for not
+ * starting the numbering at 0 is because the numbers [0,IPL_LOGMAX] correspond
+ * to the minor device number for their respective device. Thus where there is
+ * array indexing on the unit, +1 is used to map [-1.IPL_LOGMAX] to
+ * [0.POOL_LOOKUP_MAX].
+ */
+static int ipf_lookup_addnode __P((ipf_main_softc_t *, caddr_t, int));
+static int ipf_lookup_delnode __P((ipf_main_softc_t *, caddr_t, int));
+static int ipf_lookup_addtable __P((ipf_main_softc_t *, caddr_t));
+static int ipf_lookup_deltable __P((ipf_main_softc_t *, caddr_t));
+static int ipf_lookup_stats __P((ipf_main_softc_t *, caddr_t));
+static int ipf_lookup_flush __P((ipf_main_softc_t *, caddr_t));
+static int ipf_lookup_iterate __P((ipf_main_softc_t *, void *, int, void *));
+static int ipf_lookup_deltok __P((ipf_main_softc_t *, void *, int, void *));
+
+#define MAX_BACKENDS 3
+static ipf_lookup_t *backends[MAX_BACKENDS] = {
+ &ipf_pool_backend,
+ &ipf_htable_backend,
+ &ipf_dstlist_backend
+};
+
-static int iplookup_addnode __P((caddr_t));
-static int iplookup_delnode __P((caddr_t data));
-static int iplookup_addtable __P((caddr_t));
-static int iplookup_deltable __P((caddr_t));
-static int iplookup_stats __P((caddr_t));
-static int iplookup_flush __P((caddr_t));
-static int iplookup_iterate __P((void *, int, void *));
-static int iplookup_deltok __P((void *, int, void *));
+typedef struct ipf_lookup_softc_s {
+ void *ipf_back[MAX_BACKENDS];
+} ipf_lookup_softc_t;
/* ------------------------------------------------------------------------ */
-/* Function: iplookup_init */
-/* Returns: int - 0 = success, else error */
-/* Parameters: Nil */
+/* Function: ipf_lookup_init */
+/* Returns: int - 0 = success, else error */
+/* Parameters: softc(I) - pointer to soft context main structure */
/* */
/* Initialise all of the subcomponents of the lookup infrstructure. */
/* ------------------------------------------------------------------------ */
-int ip_lookup_init()
+void *
+ipf_lookup_soft_create(softc)
+ ipf_main_softc_t *softc;
{
+ ipf_lookup_softc_t *softl;
+ ipf_lookup_t **l;
+ int i;
+
+ KMALLOC(softl, ipf_lookup_softc_t *);
+ if (softl == NULL)
+ return NULL;
+
+ bzero((char *)softl, sizeof(*softl));
+
+ for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
+ softl->ipf_back[i] = (*(*l)->ipfl_create)(softc);
+ if (softl->ipf_back[i] == NULL) {
+ ipf_lookup_soft_destroy(softc, softl);
+ return NULL;
+ }
+ }
+
+ return softl;
+}
+
- if (ip_pool_init() == -1)
- return -1;
+/* ------------------------------------------------------------------------ */
+/* Function: ipf_lookup_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 all of the subcomponents of the lookup infrstructure. */
+/* ------------------------------------------------------------------------ */
+int
+ipf_lookup_soft_init(softc, arg)
+ ipf_main_softc_t *softc;
+ void *arg;
+{
+ ipf_lookup_softc_t *softl = (ipf_lookup_softc_t *)arg;
+ int err = 0;
+ int i;
- RWLOCK_INIT(&ip_poolrw, "ip pool rwlock");
+ for (i = 0; i < MAX_BACKENDS; i++) {
+ err = (*backends[i]->ipfl_init)(softc, softl->ipf_back[i]);
+ if (err != 0)
+ break;
+ }
- ip_lookup_inited = 1;
+ return err;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ipf_lookup_soft_fini */
+/* Returns: int - 0 = success, else error */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* arg(I) - pointer to local context to use */
+/* */
+/* Call the fini function in each backend to cleanup all allocated data. */
+/* ------------------------------------------------------------------------ */
+int
+ipf_lookup_soft_fini(softc, arg)
+ ipf_main_softc_t *softc;
+ void *arg;
+{
+ ipf_lookup_softc_t *softl = (ipf_lookup_softc_t *)arg;
+ int i;
+
+ for (i = 0; i < MAX_BACKENDS; i++) {
+ if (softl->ipf_back[i] != NULL)
+ (*backends[i]->ipfl_fini)(softc,
+ softl->ipf_back[i]);
+ }
return 0;
}
/* ------------------------------------------------------------------------ */
-/* Function: iplookup_unload */
+/* Function: ipf_lookup_expire */
+/* Returns: Nil */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* */
+/* Step through each of the backends and call their expire functions, */
+/* allowing them to delete any lifetime limited data. */
+/* ------------------------------------------------------------------------ */
+void
+ipf_lookup_expire(softc)
+ ipf_main_softc_t *softc;
+{
+ ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
+ int i;
+
+ WRITE_ENTER(&softc->ipf_poolrw);
+ for (i = 0; i < MAX_BACKENDS; i++)
+ (*backends[i]->ipfl_expire)(softc, softl->ipf_back[i]);
+ RWLOCK_EXIT(&softc->ipf_poolrw);
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ipf_lookup_softc_destroy */
/* Returns: int - 0 = success, else error */
-/* Parameters: Nil */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* arg(I) - pointer to local context to use */
/* */
/* Free up all pool related memory that has been allocated whilst IPFilter */
/* has been running. Also, do any other deinitialisation required such */
-/* ip_lookup_init() can be called again, safely. */
+/* ipf_lookup_init() can be called again, safely. */
/* ------------------------------------------------------------------------ */
-void ip_lookup_unload()
+void
+ipf_lookup_soft_destroy(softc, arg)
+ ipf_main_softc_t *softc;
+ void *arg;
{
- ip_pool_fini();
- fr_htable_unload();
+ ipf_lookup_softc_t *softl = (ipf_lookup_softc_t *)arg;
+ int i;
- if (ip_lookup_inited == 1) {
- RW_DESTROY(&ip_poolrw);
- ip_lookup_inited = 0;
+ for (i = 0; i < MAX_BACKENDS; i++) {
+ if (softl->ipf_back[i] != NULL)
+ (*backends[i]->ipfl_destroy)(softc,
+ softl->ipf_back[i]);
}
+
+ KFREE(softl);
}
/* ------------------------------------------------------------------------ */
-/* Function: iplookup_ioctl */
+/* Function: ipf_lookup_ioctl */
/* Returns: int - 0 = success, else error */
-/* Parameters: data(IO) - pointer to ioctl data to be copied to/from user */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* arg(I) - pointer to local context to use */
+/* data(IO) - pointer to ioctl data to be copied to/from user */
/* space. */
/* cmd(I) - ioctl command number */
/* mode(I) - file mode bits used with open */
+/* uid(I) - uid of process doing ioctl */
+/* ctx(I) - pointer that represents context for uid */
/* */
/* Handle ioctl commands sent to the ioctl device. For the most part, this */
/* involves just calling another function to handle the specifics of each */
/* command. */
/* ------------------------------------------------------------------------ */
-int ip_lookup_ioctl(data, cmd, mode, uid, ctx)
-caddr_t data;
-ioctlcmd_t cmd;
-int mode, uid;
-void *ctx;
+int
+ipf_lookup_ioctl(softc, data, cmd, mode, uid, ctx)
+ ipf_main_softc_t *softc;
+ caddr_t data;
+ ioctlcmd_t cmd;
+ int mode, uid;
+ void *ctx;
{
int err;
SPL_INT(s);
@@ -145,52 +265,53 @@ void *ctx;
{
case SIOCLOOKUPADDNODE :
case SIOCLOOKUPADDNODEW :
- WRITE_ENTER(&ip_poolrw);
- err = iplookup_addnode(data);
- RWLOCK_EXIT(&ip_poolrw);
+ WRITE_ENTER(&softc->ipf_poolrw);
+ err = ipf_lookup_addnode(softc, data, uid);
+ RWLOCK_EXIT(&softc->ipf_poolrw);
break;
case SIOCLOOKUPDELNODE :
case SIOCLOOKUPDELNODEW :
- WRITE_ENTER(&ip_poolrw);
- err = iplookup_delnode(data);
- RWLOCK_EXIT(&ip_poolrw);
+ WRITE_ENTER(&softc->ipf_poolrw);
+ err = ipf_lookup_delnode(softc, data, uid);
+ RWLOCK_EXIT(&softc->ipf_poolrw);
break;
case SIOCLOOKUPADDTABLE :
- WRITE_ENTER(&ip_poolrw);
- err = iplookup_addtable(data);
- RWLOCK_EXIT(&ip_poolrw);
+ WRITE_ENTER(&softc->ipf_poolrw);
+ err = ipf_lookup_addtable(softc, data);
+ RWLOCK_EXIT(&softc->ipf_poolrw);
break;
case SIOCLOOKUPDELTABLE :
- WRITE_ENTER(&ip_poolrw);
- err = iplookup_deltable(data);
- RWLOCK_EXIT(&ip_poolrw);
+ WRITE_ENTER(&softc->ipf_poolrw);
+ err = ipf_lookup_deltable(softc, data);
+ RWLOCK_EXIT(&softc->ipf_poolrw);
break;
case SIOCLOOKUPSTAT :
case SIOCLOOKUPSTATW :
- WRITE_ENTER(&ip_poolrw);
- err = iplookup_stats(data);
- RWLOCK_EXIT(&ip_poolrw);
+ WRITE_ENTER(&softc->ipf_poolrw);
+ err = ipf_lookup_stats(softc, data);
+ RWLOCK_EXIT(&softc->ipf_poolrw);
break;
case SIOCLOOKUPFLUSH :
- WRITE_ENTER(&ip_poolrw);
- err = iplookup_flush(data);
- RWLOCK_EXIT(&ip_poolrw);
+ WRITE_ENTER(&softc->ipf_poolrw);
+ err = ipf_lookup_flush(softc, data);
+ RWLOCK_EXIT(&softc->ipf_poolrw);
break;
case SIOCLOOKUPITER :
- err = iplookup_iterate(data, uid, ctx);
+ err = ipf_lookup_iterate(softc, data, uid, ctx);
break;
case SIOCIPFDELTOK :
- err = iplookup_deltok(data, uid, ctx);
+ err = ipf_lookup_deltok(softc, data, uid, ctx);
break;
default :
+ IPFERROR(50001);
err = EINVAL;
break;
}
@@ -200,192 +321,155 @@ void *ctx;
/* ------------------------------------------------------------------------ */
-/* Function: iplookup_addnode */
+/* Function: ipf_lookup_addnode */
/* Returns: int - 0 = success, else error */
-/* Parameters: data(I) - pointer to data from ioctl call */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* data(I) - pointer to data from ioctl call */
/* */
/* Add a new data node to a lookup structure. First, check to see if the */
/* parent structure refered to by name exists and if it does, then go on to */
/* add a node to it. */
/* ------------------------------------------------------------------------ */
-static int iplookup_addnode(data)
-caddr_t data;
+static int
+ipf_lookup_addnode(softc, data, uid)
+ ipf_main_softc_t *softc;
+ caddr_t data;
+ int uid;
{
- ip_pool_node_t node, *m;
+ ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
iplookupop_t op;
- iphtable_t *iph;
- iphtent_t hte;
- ip_pool_t *p;
+ ipf_lookup_t **l;
int err;
+ int i;
err = BCOPYIN(data, &op, sizeof(op));
- if (err != 0)
+ if (err != 0) {
+ IPFERROR(50002);
return EFAULT;
+ }
- if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX)
+ if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) &&
+ (op.iplo_unit != IPLT_ALL)) {
+ IPFERROR(50003);
return EINVAL;
+ }
op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
- switch (op.iplo_type)
- {
- case IPLT_POOL :
- if (op.iplo_size != sizeof(node))
- return EINVAL;
-
- err = COPYIN(op.iplo_struct, &node, sizeof(node));
- if (err != 0)
- return EFAULT;
-
- p = ip_pool_find(op.iplo_unit, op.iplo_name);
- if (p == NULL)
- return ESRCH;
-
- /*
- * 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 = ip_pool_findeq(p, &node.ipn_addr, &node.ipn_mask);
- if (m)
- return EEXIST;
- err = ip_pool_insert(p, &node.ipn_addr.adf_addr,
- &node.ipn_mask.adf_addr, node.ipn_info);
- break;
-
- case IPLT_HASH :
- if (op.iplo_size != sizeof(hte))
- return EINVAL;
-
- err = COPYIN(op.iplo_struct, &hte, sizeof(hte));
- if (err != 0)
- return EFAULT;
-
- iph = fr_findhtable(op.iplo_unit, op.iplo_name);
- if (iph == NULL)
- return ESRCH;
- err = fr_addhtent(iph, &hte);
- break;
+ for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
+ if (op.iplo_type == (*l)->ipfl_type) {
+ err = (*(*l)->ipfl_node_add)(softc,
+ softl->ipf_back[i],
+ &op, uid);
+ break;
+ }
+ }
- default :
+ if (i == MAX_BACKENDS) {
+ IPFERROR(50012);
err = EINVAL;
- break;
}
+
return err;
}
/* ------------------------------------------------------------------------ */
-/* Function: iplookup_delnode */
+/* Function: ipf_lookup_delnode */
/* Returns: int - 0 = success, else error */
-/* Parameters: data(I) - pointer to data from ioctl call */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* data(I) - pointer to data from ioctl call */
/* */
/* Delete a node from a lookup table by first looking for the table it is */
/* in and then deleting the entry that gets found. */
/* ------------------------------------------------------------------------ */
-static int iplookup_delnode(data)
-caddr_t data;
+static int
+ipf_lookup_delnode(softc, data, uid)
+ ipf_main_softc_t *softc;
+ caddr_t data;
+ int uid;
{
- ip_pool_node_t node, *m;
+ ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
iplookupop_t op;
- iphtable_t *iph;
- iphtent_t hte;
- ip_pool_t *p;
+ ipf_lookup_t **l;
int err;
+ int i;
err = BCOPYIN(data, &op, sizeof(op));
- if (err != 0)
+ if (err != 0) {
+ IPFERROR(50042);
return EFAULT;
+ }
- if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX)
+ if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) &&
+ (op.iplo_unit != IPLT_ALL)) {
+ IPFERROR(50013);
return EINVAL;
+ }
op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
- switch (op.iplo_type)
- {
- case IPLT_POOL :
- if (op.iplo_size != sizeof(node))
- return EINVAL;
-
- err = COPYIN(op.iplo_struct, &node, sizeof(node));
- if (err != 0)
- return EFAULT;
-
- p = ip_pool_find(op.iplo_unit, op.iplo_name);
- if (!p)
- return ESRCH;
-
- m = ip_pool_findeq(p, &node.ipn_addr, &node.ipn_mask);
- if (m == NULL)
- return ENOENT;
- err = ip_pool_remove(p, m);
- break;
-
- case IPLT_HASH :
- if (op.iplo_size != sizeof(hte))
- return EINVAL;
-
- err = COPYIN(op.iplo_struct, &hte, sizeof(hte));
- if (err != 0)
- return EFAULT;
-
- iph = fr_findhtable(op.iplo_unit, op.iplo_name);
- if (iph == NULL)
- return ESRCH;
- err = fr_delhtent(iph, &hte);
- break;
+ for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
+ if (op.iplo_type == (*l)->ipfl_type) {
+ err = (*(*l)->ipfl_node_del)(softc, softl->ipf_back[i],
+ &op, uid);
+ break;
+ }
+ }
- default :
+ if (i == MAX_BACKENDS) {
+ IPFERROR(50021);
err = EINVAL;
- break;
}
return err;
}
/* ------------------------------------------------------------------------ */
-/* Function: iplookup_addtable */
+/* Function: ipf_lookup_addtable */
/* Returns: int - 0 = success, else error */
-/* Parameters: data(I) - pointer to data from ioctl call */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* data(I) - pointer to data from ioctl call */
/* */
/* Create a new lookup table, if one doesn't already exist using the name */
/* for this one. */
/* ------------------------------------------------------------------------ */
-static int iplookup_addtable(data)
-caddr_t data;
+static int
+ipf_lookup_addtable(softc, data)
+ ipf_main_softc_t *softc;
+ caddr_t data;
{
+ ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
iplookupop_t op;
- int err;
+ ipf_lookup_t **l;
+ int err, i;
err = BCOPYIN(data, &op, sizeof(op));
- if (err != 0)
+ if (err != 0) {
+ IPFERROR(50022);
return EFAULT;
+ }
- if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX)
+ if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) &&
+ (op.iplo_unit != IPLT_ALL)) {
+ IPFERROR(50023);
return EINVAL;
+ }
op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
- switch (op.iplo_type)
- {
- case IPLT_POOL :
- if (ip_pool_find(op.iplo_unit, op.iplo_name) != NULL)
- err = EEXIST;
- else
- err = ip_pool_create(&op);
- break;
-
- case IPLT_HASH :
- if (fr_findhtable(op.iplo_unit, op.iplo_name) != NULL)
- err = EEXIST;
- else
- err = fr_newhtable(&op);
- break;
+ for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
+ if (op.iplo_type == (*l)->ipfl_type) {
+ err = (*(*l)->ipfl_table_add)(softc,
+ softl->ipf_back[i],
+ &op);
+ break;
+ }
+ }
- default :
+ if (i == MAX_BACKENDS) {
+ IPFERROR(50026);
err = EINVAL;
- break;
}
/*
@@ -394,8 +478,10 @@ caddr_t data;
*/
if ((err == 0) && ((op.iplo_arg & LOOKUP_ANON) != 0)) {
err = BCOPYOUT(&op, data, sizeof(op));
- if (err != 0)
+ if (err != 0) {
+ IPFERROR(50027);
err = EFAULT;
+ }
}
return err;
@@ -403,260 +489,317 @@ caddr_t data;
/* ------------------------------------------------------------------------ */
-/* Function: iplookup_deltable */
+/* Function: ipf_lookup_deltable */
/* Returns: int - 0 = success, else error */
-/* Parameters: data(I) - pointer to data from ioctl call */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* data(I) - pointer to data from ioctl call */
/* */
/* Decodes ioctl request to remove a particular hash table or pool and */
/* calls the relevant function to do the cleanup. */
/* ------------------------------------------------------------------------ */
-static int iplookup_deltable(data)
-caddr_t data;
+static int
+ipf_lookup_deltable(softc, data)
+ ipf_main_softc_t *softc;
+ caddr_t data;
{
+ ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
iplookupop_t op;
- int err;
+ ipf_lookup_t **l;
+ int err, i;
err = BCOPYIN(data, &op, sizeof(op));
- if (err != 0)
+ if (err != 0) {
+ IPFERROR(50028);
return EFAULT;
+ }
- if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX)
+ if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) &&
+ (op.iplo_unit != IPLT_ALL)) {
+ IPFERROR(50029);
return EINVAL;
+ }
op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
- /*
- * create a new pool - fail if one already exists with
- * the same #
- */
- switch (op.iplo_type)
- {
- case IPLT_POOL :
- err = ip_pool_destroy(op.iplo_unit, op.iplo_name);
- break;
-
- case IPLT_HASH :
- err = fr_removehtable(op.iplo_unit, op.iplo_name);
- break;
+ for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
+ if (op.iplo_type == (*l)->ipfl_type) {
+ err = (*(*l)->ipfl_table_del)(softc,
+ softl->ipf_back[i],
+ &op);
+ break;
+ }
+ }
- default :
+ if (i == MAX_BACKENDS) {
+ IPFERROR(50030);
err = EINVAL;
- break;
}
return err;
}
/* ------------------------------------------------------------------------ */
-/* Function: iplookup_stats */
+/* Function: ipf_lookup_stats */
/* Returns: int - 0 = success, else error */
-/* Parameters: data(I) - pointer to data from ioctl call */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* data(I) - pointer to data from ioctl call */
/* */
/* Copy statistical information from inside the kernel back to user space. */
/* ------------------------------------------------------------------------ */
-static int iplookup_stats(data)
-caddr_t data;
+static int
+ipf_lookup_stats(softc, data)
+ ipf_main_softc_t *softc;
+ caddr_t data;
{
+ ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
iplookupop_t op;
+ ipf_lookup_t **l;
int err;
+ int i;
err = BCOPYIN(data, &op, sizeof(op));
- if (err != 0)
+ if (err != 0) {
+ IPFERROR(50031);
return EFAULT;
+ }
- if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX)
+ if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) &&
+ (op.iplo_unit != IPLT_ALL)) {
+ IPFERROR(50032);
return EINVAL;
+ }
- switch (op.iplo_type)
- {
- case IPLT_POOL :
- err = ip_pool_statistics(&op);
- break;
-
- case IPLT_HASH :
- err = fr_gethtablestat(&op);
- break;
+ for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
+ if (op.iplo_type == (*l)->ipfl_type) {
+ err = (*(*l)->ipfl_stats_get)(softc,
+ softl->ipf_back[i],
+ &op);
+ break;
+ }
+ }
- default :
+ if (i == MAX_BACKENDS) {
+ IPFERROR(50033);
err = EINVAL;
- break;
}
+
return err;
}
/* ------------------------------------------------------------------------ */
-/* Function: iplookup_flush */
+/* Function: ipf_lookup_flush */
/* Returns: int - 0 = success, else error */
-/* Parameters: data(I) - pointer to data from ioctl call */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* data(I) - pointer to data from ioctl call */
/* */
/* A flush is called when we want to flush all the nodes from a particular */
/* entry in the hash table/pool or want to remove all groups from those. */
/* ------------------------------------------------------------------------ */
-static int iplookup_flush(data)
-caddr_t data;
+static int
+ipf_lookup_flush(softc, data)
+ ipf_main_softc_t *softc;
+ caddr_t data;
{
- int err, unit, num, type;
+ ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
+ int err, unit, num, type, i;
iplookupflush_t flush;
+ ipf_lookup_t **l;
err = BCOPYIN(data, &flush, sizeof(flush));
- if (err != 0)
+ if (err != 0) {
+ IPFERROR(50034);
return EFAULT;
+ }
unit = flush.iplf_unit;
- if ((unit < 0 || unit > IPL_LOGMAX) && (unit != IPLT_ALL))
+ if ((unit < 0 || unit > IPL_LOGMAX) && (unit != IPLT_ALL)) {
+ IPFERROR(50035);
return EINVAL;
+ }
flush.iplf_name[sizeof(flush.iplf_name) - 1] = '\0';
type = flush.iplf_type;
+ IPFERROR(50036);
err = EINVAL;
num = 0;
- if (type == IPLT_POOL || type == IPLT_ALL) {
- err = 0;
- num = ip_pool_flush(&flush);
- }
-
- if (type == IPLT_HASH || type == IPLT_ALL) {
- err = 0;
- num += fr_flushhtable(&flush);
+ for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
+ if (type == (*l)->ipfl_type || type == IPLT_ALL) {
+ err = 0;
+ num += (*(*l)->ipfl_flush)(softc,
+ softl->ipf_back[i],
+ &flush);
+ }
}
if (err == 0) {
flush.iplf_count = num;
err = BCOPYOUT(&flush, data, sizeof(flush));
- if (err != 0)
+ if (err != 0) {
+ IPFERROR(50037);
err = EFAULT;
+ }
}
return err;
}
/* ------------------------------------------------------------------------ */
-/* Function: ip_lookup_delref */
+/* Function: ipf_lookup_delref */
/* Returns: void */
-/* Parameters: type(I) - table type to operate on */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* type(I) - table type to operate on */
/* ptr(I) - pointer to object to remove reference for */
/* */
/* This function organises calling the correct deref function for a given */
/* type of object being passed into it. */
/* ------------------------------------------------------------------------ */
-void ip_lookup_deref(type, ptr)
-int type;
-void *ptr;
+void
+ipf_lookup_deref(softc, type, ptr)
+ ipf_main_softc_t *softc;
+ int type;
+ void *ptr;
{
+ ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
+ int i;
+
if (ptr == NULL)
return;
- WRITE_ENTER(&ip_poolrw);
- switch (type)
- {
- case IPLT_POOL :
- ip_pool_deref(ptr);
- break;
-
- case IPLT_HASH :
- fr_derefhtable(ptr);
- break;
+ for (i = 0; i < MAX_BACKENDS; i++) {
+ if (type == backends[i]->ipfl_type) {
+ WRITE_ENTER(&softc->ipf_poolrw);
+ (*backends[i]->ipfl_table_deref)(softc,
+ softl->ipf_back[i],
+ ptr);
+ RWLOCK_EXIT(&softc->ipf_poolrw);
+ break;
+ }
}
- RWLOCK_EXIT(&ip_poolrw);
}
/* ------------------------------------------------------------------------ */
-/* Function: iplookup_iterate */
+/* Function: ipf_lookup_iterate */
/* Returns: int - 0 = success, else error */
-/* Parameters: data(I) - pointer to data from ioctl call */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* data(I) - pointer to data from ioctl call */
/* uid(I) - uid of caller */
/* ctx(I) - pointer to give the uid context */
/* */
/* Decodes ioctl request to step through either hash tables or pools. */
/* ------------------------------------------------------------------------ */
-static int iplookup_iterate(data, uid, ctx)
-void *data;
-int uid;
-void *ctx;
+static int
+ipf_lookup_iterate(softc, data, uid, ctx)
+ ipf_main_softc_t *softc;
+ void *data;
+ int uid;
+ void *ctx;
{
+ ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
ipflookupiter_t iter;
ipftoken_t *token;
- int err;
+ int err, i;
SPL_INT(s);
- err = fr_inobj(data, &iter, IPFOBJ_LOOKUPITER);
+ err = ipf_inobj(softc, data, NULL, &iter, IPFOBJ_LOOKUPITER);
if (err != 0)
return err;
- if (iter.ili_unit > IPL_LOGMAX)
+ if (iter.ili_unit < IPL_LOGALL && iter.ili_unit > IPL_LOGMAX) {
+ IPFERROR(50038);
return EINVAL;
+ }
- if (iter.ili_ival != IPFGENITER_LOOKUP)
+ if (iter.ili_ival != IPFGENITER_LOOKUP) {
+ IPFERROR(50039);
return EINVAL;
+ }
SPL_SCHED(s);
- token = ipf_findtoken(iter.ili_key, uid, ctx);
+ token = ipf_token_find(softc, iter.ili_key, uid, ctx);
if (token == NULL) {
- RWLOCK_EXIT(&ipf_tokens);
SPL_X(s);
+ IPFERROR(50040);
return ESRCH;
}
- switch (iter.ili_type)
- {
- case IPLT_POOL :
- err = ip_pool_getnext(token, &iter);
- break;
- case IPLT_HASH :
- err = fr_htable_getnext(token, &iter);
- break;
- default :
- err = EINVAL;
- break;
+ for (i = 0; i < MAX_BACKENDS; i++) {
+ if (iter.ili_type == backends[i]->ipfl_type) {
+ err = (*backends[i]->ipfl_iter_next)(softc,
+ softl->ipf_back[i],
+ token, &iter);
+ break;
+ }
}
- RWLOCK_EXIT(&ipf_tokens);
SPL_X(s);
+ if (i == MAX_BACKENDS) {
+ IPFERROR(50041);
+ err = EINVAL;
+ }
+
+ WRITE_ENTER(&softc->ipf_tokens);
+ ipf_token_deref(softc, token);
+ RWLOCK_EXIT(&softc->ipf_tokens);
+
return err;
}
/* ------------------------------------------------------------------------ */
-/* Function: iplookup_iterderef */
-/* Returns: int - 0 = success, else error */
-/* Parameters: data(I) - pointer to data from ioctl call */
+/* Function: ipf_lookup_iterderef */
+/* Returns: void */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* type(I) - backend type to iterate through */
+/* data(I) - pointer to data from ioctl call */
/* */
/* Decodes ioctl request to remove a particular hash table or pool and */
/* calls the relevant function to do the cleanup. */
+/* Because each of the backend types has a different data structure, */
+/* iteration is limited to one type at a time (i.e. it is not permitted to */
+/* go on from pool types to hash types as part of the "get next".) */
/* ------------------------------------------------------------------------ */
-void ip_lookup_iterderef(type, data)
-u_32_t type;
-void *data;
+void
+ipf_lookup_iterderef(softc, type, data)
+ ipf_main_softc_t *softc;
+ u_32_t type;
+ void *data;
{
- iplookupiterkey_t key;
+ ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
+ struct iplookupiterkey *lkey;
+ iplookupiterkey_t key;
+ int i;
key.ilik_key = type;
+ lkey = &key.ilik_unstr;
- if (key.ilik_unstr.ilik_ival != IPFGENITER_LOOKUP)
+ if (lkey->ilik_ival != IPFGENITER_LOOKUP)
return;
- switch (key.ilik_unstr.ilik_type)
- {
- case IPLT_HASH :
- fr_htable_iterderef((u_int)key.ilik_unstr.ilik_otype,
- (int)key.ilik_unstr.ilik_unit, data);
- break;
- case IPLT_POOL :
- ip_pool_iterderef((u_int)key.ilik_unstr.ilik_otype,
- (int)key.ilik_unstr.ilik_unit, data);
- break;
+ WRITE_ENTER(&softc->ipf_poolrw);
+
+ for (i = 0; i < MAX_BACKENDS; i++) {
+ if (lkey->ilik_type == backends[i]->ipfl_type) {
+ (*backends[i]->ipfl_iter_deref)(softc,
+ softl->ipf_back[i],
+ lkey->ilik_otype,
+ lkey->ilik_unit,
+ data);
+ break;
+ }
}
+ RWLOCK_EXIT(&softc->ipf_poolrw);
}
/* ------------------------------------------------------------------------ */
-/* Function: iplookup_deltok */
+/* Function: ipf_lookup_deltok */
/* Returns: int - 0 = success, else error */
-/* Parameters: data(I) - pointer to data from ioctl call */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* data(I) - pointer to data from ioctl call */
/* uid(I) - uid of caller */
/* ctx(I) - pointer to give the uid context */
/* */
@@ -664,32 +807,198 @@ void *data;
/* "key" is a combination of the table type, iterator type and the unit for */
/* which the token was being used. */
/* ------------------------------------------------------------------------ */
-static int iplookup_deltok(data, uid, ctx)
-void *data;
-int uid;
-void *ctx;
+int
+ipf_lookup_deltok(softc, data, uid, ctx)
+ ipf_main_softc_t *softc;
+ void *data;
+ int uid;
+ void *ctx;
{
int error, key;
SPL_INT(s);
SPL_SCHED(s);
- error = BCOPYIN(data, &key, sizeof(key));
+ error = BCOPYIN(data, &key, sizeof(key));
if (error == 0)
- error = ipf_deltoken(key, uid, ctx);
+ error = ipf_token_del(softc, key, uid, ctx);
SPL_X(s);
return error;
}
-#else /* IPFILTER_LOOKUP */
+/* ------------------------------------------------------------------------ */
+/* Function: ipf_lookup_res_num */
+/* Returns: void * - NULL = failure, else success. */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* unit(I) - device for which this is for */
+/* type(I) - type of lookup these parameters are for. */
+/* number(I) - table number to use when searching */
+/* funcptr(IO) - pointer to pointer for storing IP address */
+/* searching function. */
+/* */
+/* Search for the "table" number passed in amongst those configured for */
+/* that particular type. If the type is recognised then the function to */
+/* call to do the IP address search will be change, regardless of whether */
+/* or not the "table" number exists. */
+/* ------------------------------------------------------------------------ */
+void *
+ipf_lookup_res_num(softc, unit, type, number, funcptr)
+ ipf_main_softc_t *softc;
+ int unit;
+ u_int type;
+ u_int number;
+ lookupfunc_t *funcptr;
+{
+ char name[FR_GROUPLEN];
+
+#if defined(SNPRINTF) && defined(_KERNEL)
+ SNPRINTF(name, sizeof(name), "%u", number);
+#else
+ (void) sprintf(name, "%u", number);
+#endif
+
+ return ipf_lookup_res_name(softc, unit, type, name, funcptr);
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ipf_lookup_res_name */
+/* Returns: void * - NULL = failure, else success. */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* unit(I) - device for which this is for */
+/* type(I) - type of lookup these parameters are for. */
+/* name(I) - table name to use when searching */
+/* funcptr(IO) - pointer to pointer for storing IP address */
+/* searching function. */
+/* */
+/* Search for the "table" number passed in amongst those configured for */
+/* that particular type. If the type is recognised then the function to */
+/* call to do the IP address search will be changed, regardless of whether */
+/* or not the "table" number exists. */
+/* ------------------------------------------------------------------------ */
+void *
+ipf_lookup_res_name(softc, unit, type, name, funcptr)
+ ipf_main_softc_t *softc;
+ int unit;
+ u_int type;
+ char *name;
+ lookupfunc_t *funcptr;
+{
+ ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
+ ipf_lookup_t **l;
+ void *ptr = NULL;
+ int i;
+
+ READ_ENTER(&softc->ipf_poolrw);
+
+ for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
+ if (type == (*l)->ipfl_type) {
+ ptr = (*(*l)->ipfl_select_add_ref)(softl->ipf_back[i],
+ unit, name);
+ if (ptr != NULL && funcptr != NULL) {
+ *funcptr = (*l)->ipfl_addr_find;
+ }
+ break;
+ }
+ }
+
+ if (i == MAX_BACKENDS) {
+ ptr = NULL;
+ if (funcptr != NULL)
+ *funcptr = NULL;
+ }
+
+ RWLOCK_EXIT(&softc->ipf_poolrw);
+
+ return ptr;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Function: ipf_lookup_find_htable */
+/* Returns: void * - NULL = failure, else success. */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* unit(I) - device for which this is for */
+/* name(I) - table name to use when searching */
+/* */
+/* To support the group-map feature, where a hash table maps address */
+/* networks to rule group numbers, we need to expose a function that uses */
+/* only the hash table backend. */
+/* ------------------------------------------------------------------------ */
+void *
+ipf_lookup_find_htable(softc, unit, name)
+ ipf_main_softc_t *softc;
+ int unit;
+ char *name;
+{
+ ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
+ ipf_lookup_t **l;
+ void *tab = NULL;
+ int i;
+
+ READ_ENTER(&softc->ipf_poolrw);
+
+ for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++)
+ if (IPLT_HASH == (*l)->ipfl_type) {
+ tab = ipf_htable_find(softl->ipf_back[i], unit, name);
+ break;
+ }
+
+ RWLOCK_EXIT(&softc->ipf_poolrw);
+
+ return tab;
+}
+
+/* ------------------------------------------------------------------------ */
+/* Function: ipf_lookup_sync */
+/* Returns: void */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* */
+/* This function is the interface that the machine dependent sync functions */
+/* call when a network interface name change occurs. It then calls the sync */
+/* functions of the lookup implementations - if they have one. */
+/* ------------------------------------------------------------------------ */
/*ARGSUSED*/
-int ip_lookup_ioctl(data, cmd, mode, uid, ctx)
-caddr_t data;
-ioctlcmd_t cmd;
-int mode, uid;
-void *ctx;
+void
+ipf_lookup_sync(softc, ifp)
+ ipf_main_softc_t *softc;
+ void *ifp;
{
- return EIO;
+ ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
+ ipf_lookup_t **l;
+ int i;
+
+ READ_ENTER(&softc->ipf_poolrw);
+
+ for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++)
+ if ((*l)->ipfl_sync != NULL)
+ (*(*l)->ipfl_sync)(softc, softl->ipf_back[i]);
+
+ RWLOCK_EXIT(&softc->ipf_poolrw);
}
-#endif /* IPFILTER_LOOKUP */
+
+
+#ifndef _KERNEL
+void
+ipf_lookup_dump(softc, arg)
+ ipf_main_softc_t *softc;
+ void *arg;
+{
+ ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
+ ipf_lookup_t **l;
+ int i;
+
+ for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++)
+ if (IPLT_POOL == (*l)->ipfl_type) {
+ ipf_pool_dump(softc, softl->ipf_back[i]);
+ break;
+ }
+
+ for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++)
+ if (IPLT_HASH == (*l)->ipfl_type) {
+ ipf_htable_dump(softc, softl->ipf_back[i]);
+ break;
+ }
+}
+#endif
OpenPOWER on IntegriCloud