From 1e7342c150c1e366b847af9caa5f438420af74bd Mon Sep 17 00:00:00 2001 From: rmind Date: Tue, 12 Nov 2013 00:46:34 +0000 Subject: [PATCH] NPF: add support for table naming and remove NPF_TABLE_SLOTS (there is just an arbitrary sanity limit of NPF_MAX_TABLES currently set to 128). Few misc fixes. Bump NPF_VERSION. --- lib/libnpf/npf.3 | 12 +- lib/libnpf/npf.c | 19 +- lib/libnpf/npf.h | 5 +- sys/net/npf/npf.h | 8 +- sys/net/npf/npf_bpf.c | 10 +- sys/net/npf/npf_conf.c | 6 +- sys/net/npf/npf_ctl.c | 75 ++++--- sys/net/npf/npf_impl.h | 32 +-- sys/net/npf/npf_tableset.c | 205 ++++++++++-------- usr.sbin/npf/npfctl/npf.conf.5 | 36 +-- usr.sbin/npf/npfctl/npf_build.c | 14 +- usr.sbin/npf/npfctl/npf_scan.l | 8 +- usr.sbin/npf/npfctl/npf_show.c | 49 +++-- usr.sbin/npf/npfctl/npfctl.c | 9 +- .../npf/npftest/libnpftest/npf_table_test.c | 83 ++++--- 15 files changed, 341 insertions(+), 230 deletions(-) diff --git a/lib/libnpf/npf.3 b/lib/libnpf/npf.3 index a5758b527a89..4922da49a010 100644 --- a/lib/libnpf/npf.3 +++ b/lib/libnpf/npf.3 @@ -1,4 +1,4 @@ -.\" $NetBSD: npf.3,v 1.11 2013/11/08 13:17:45 wiz Exp $ +.\" $NetBSD: npf.3,v 1.12 2013/11/12 00:46:34 rmind Exp $ .\" .\" Copyright (c) 2011-2013 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -27,7 +27,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd November 7, 2013 +.Dd November 12, 2013 .Dt NPF 3 .Os .Sh NAME @@ -78,7 +78,7 @@ .Fn npf_nat_insert "nl_config_t *ncf" "nl_nat_t *nt" "pri_t pri" .\" --- .Ft nl_table_t * -.Fn npf_table_create "u_int id" "int type" +.Fn npf_table_create "const char *name", "u_int id" "int type" .Ft int .Fn npf_table_add_entry "nl_table_t *tl" "int af" \ "in_addr_t addr" "in_addr_t mask" @@ -261,7 +261,7 @@ Insert NAT policy, its rule, into the specified configuration. .\" ----- .Ss Table interface .Bl -tag -width 4n -.It Fn npf_table_create "index" "type" +.It Fn npf_table_create "name" "index" "type" Create NPF table of specified type. The following types are supported: .Bl -tag -width "NPF_TABLE_TREE " @@ -269,7 +269,9 @@ The following types are supported: Indicates to use hash table for storage. .It Dv NPF_TABLE_TREE Indicates to use red-black tree for storage. -Table is identified by +Table is identified by the +.Fa name +and .Fa index , which should be in the range between 1 and .Dv NPF_MAX_TABLE_ID . diff --git a/lib/libnpf/npf.c b/lib/libnpf/npf.c index 3f8f83e1539d..20f3300cf6c3 100644 --- a/lib/libnpf/npf.c +++ b/lib/libnpf/npf.c @@ -1,4 +1,4 @@ -/* $NetBSD: npf.c,v 1.22 2013/11/08 00:38:27 rmind Exp $ */ +/* $NetBSD: npf.c,v 1.23 2013/11/12 00:46:34 rmind Exp $ */ /*- * Copyright (c) 2010-2013 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.22 2013/11/08 00:38:27 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.23 2013/11/12 00:46:34 rmind Exp $"); #include #include @@ -892,7 +892,7 @@ npf_nat_getmap(nl_nat_t *nt, npf_addr_t *addr, size_t *alen, in_port_t *port) */ nl_table_t * -npf_table_create(u_int id, int type) +npf_table_create(const char *name, u_int id, int type) { prop_dictionary_t tldict; prop_array_t tblents; @@ -907,6 +907,7 @@ npf_table_create(u_int id, int type) free(tl); return NULL; } + prop_dictionary_set_cstring(tldict, "name", name); prop_dictionary_set_uint32(tldict, "id", id); prop_dictionary_set_int32(tldict, "type", type); @@ -1014,12 +1015,22 @@ unsigned npf_table_getid(nl_table_t *tl) { prop_dictionary_t tldict = tl->ntl_dict; - u_int id = 0; + unsigned id = (unsigned)-1; prop_dictionary_get_uint32(tldict, "id", &id); return id; } +const char * +npf_table_getname(nl_table_t *tl) +{ + prop_dictionary_t tldict = tl->ntl_dict; + const char *tname = NULL; + + prop_dictionary_get_cstring_nocopy(tldict, "name", &tname); + return tname; +} + int npf_table_gettype(nl_table_t *tl) { diff --git a/lib/libnpf/npf.h b/lib/libnpf/npf.h index 578143ce607f..4005a06ed8d0 100644 --- a/lib/libnpf/npf.h +++ b/lib/libnpf/npf.h @@ -1,4 +1,4 @@ -/* $NetBSD: npf.h,v 1.19 2013/11/08 00:38:27 rmind Exp $ */ +/* $NetBSD: npf.h,v 1.20 2013/11/12 00:46:34 rmind Exp $ */ /*- * Copyright (c) 2011-2013 The NetBSD Foundation, Inc. @@ -108,7 +108,7 @@ nl_nat_t * npf_nat_create(int, u_int, const char *, npf_addr_t *, int, in_port_t); int npf_nat_insert(nl_config_t *, nl_nat_t *, pri_t); -nl_table_t * npf_table_create(u_int, int); +nl_table_t * npf_table_create(const char *, u_int, int); int npf_table_add_entry(nl_table_t *, int, const npf_addr_t *, const npf_netmask_t); bool npf_table_exists_p(nl_config_t *, u_int); @@ -130,6 +130,7 @@ const void * npf_rule_getinfo(nl_rule_t *, size_t *); const char * npf_rule_getproc(nl_rule_t *); nl_table_t * npf_table_iterate(nl_config_t *); +const char * npf_table_getname(nl_table_t *); unsigned npf_table_getid(nl_table_t *); int npf_table_gettype(nl_table_t *); diff --git a/sys/net/npf/npf.h b/sys/net/npf/npf.h index c25737f65ff2..3dc7d607d384 100644 --- a/sys/net/npf/npf.h +++ b/sys/net/npf/npf.h @@ -1,4 +1,4 @@ -/* $NetBSD: npf.h,v 1.32 2013/11/08 00:38:26 rmind Exp $ */ +/* $NetBSD: npf.h,v 1.33 2013/11/12 00:46:34 rmind Exp $ */ /*- * Copyright (c) 2009-2013 The NetBSD Foundation, Inc. @@ -45,7 +45,7 @@ #include #include -#define NPF_VERSION 11 +#define NPF_VERSION 12 /* * Public declarations and definitions. @@ -231,6 +231,8 @@ bool npf_autounload_p(void); #define NPF_TABLE_HASH 1 #define NPF_TABLE_TREE 2 +#define NPF_TABLE_MAXNAMELEN 32 + /* Layers. */ #define NPF_LAYER_2 2 #define NPF_LAYER_3 3 @@ -272,7 +274,7 @@ typedef struct npf_ioctl_buf { typedef struct npf_ioctl_table { int nct_cmd; - u_int nct_tid; + const char * nct_name; union { npf_ioctl_ent_t ent; npf_ioctl_buf_t buf; diff --git a/sys/net/npf/npf_bpf.c b/sys/net/npf/npf_bpf.c index 4095e04c36bb..90906dd85d9e 100644 --- a/sys/net/npf/npf_bpf.c +++ b/sys/net/npf/npf_bpf.c @@ -1,4 +1,4 @@ -/* $NetBSD: npf_bpf.c,v 1.1 2013/09/19 01:04:46 rmind Exp $ */ +/* $NetBSD: npf_bpf.c,v 1.2 2013/11/12 00:46:34 rmind Exp $ */ /*- * Copyright (c) 2009-2013 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: npf_bpf.c,v 1.1 2013/09/19 01:04:46 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: npf_bpf.c,v 1.2 2013/11/12 00:46:34 rmind Exp $"); #include #include @@ -145,11 +145,15 @@ npf_cop_table(const struct mbuf *pkt, void *arg, uint32_t A, uint32_t *M) npf_tableset_t *tblset = npf_config_tableset(); const uint32_t tid = A & (SRC_FLAG_BIT - 1); const npf_addr_t *addr; + npf_table_t *t; KASSERT(npc != NULL); KASSERT(npf_iscached(npc, NPC_IP46)); memset(M, 0, sizeof(uint32_t) * BPF_MEMWORDS); + if ((t = npf_tableset_getbyid(tblset, tid)) == NULL) { + return 0; + } addr = (A & SRC_FLAG_BIT) ? npc->npc_srcip : npc->npc_dstip; - return npf_table_lookup(tblset, tid, npc->npc_alen, addr) == 0; + return npf_table_lookup(t, npc->npc_alen, addr) == 0; } diff --git a/sys/net/npf/npf_conf.c b/sys/net/npf/npf_conf.c index 10dcfcff5975..96eed2c05f39 100644 --- a/sys/net/npf/npf_conf.c +++ b/sys/net/npf/npf_conf.c @@ -1,4 +1,4 @@ -/* $NetBSD: npf_conf.c,v 1.3 2013/11/08 00:38:26 rmind Exp $ */ +/* $NetBSD: npf_conf.c,v 1.4 2013/11/12 00:46:34 rmind Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -48,7 +48,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: npf_conf.c,v 1.3 2013/11/08 00:38:26 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: npf_conf.c,v 1.4 2013/11/12 00:46:34 rmind Exp $"); #include #include @@ -86,7 +86,7 @@ npf_config_init(void) /* Load the empty configuration. */ dict = prop_dictionary_create(); - tset = npf_tableset_create(); + tset = npf_tableset_create(0); rpset = npf_rprocset_create(); rlset = npf_ruleset_create(0); nset = npf_ruleset_create(0); diff --git a/sys/net/npf/npf_ctl.c b/sys/net/npf/npf_ctl.c index 0773203cda87..2534586d2023 100644 --- a/sys/net/npf/npf_ctl.c +++ b/sys/net/npf/npf_ctl.c @@ -1,4 +1,4 @@ -/* $NetBSD: npf_ctl.c,v 1.31 2013/11/08 00:38:26 rmind Exp $ */ +/* $NetBSD: npf_ctl.c,v 1.32 2013/11/12 00:46:34 rmind Exp $ */ /*- * Copyright (c) 2009-2013 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: npf_ctl.c,v 1.31 2013/11/08 00:38:26 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: npf_ctl.c,v 1.32 2013/11/12 00:46:34 rmind Exp $"); #include #include @@ -95,6 +95,7 @@ npf_mk_tables(npf_tableset_t *tblset, prop_array_t tables, prop_dictionary_t ent; prop_object_iterator_t eit; prop_array_t entries; + const char *name; npf_table_t *t; u_int tid; int type; @@ -106,17 +107,22 @@ npf_mk_tables(npf_tableset_t *tblset, prop_array_t tables, break; } - /* Table ID and type. */ + /* Table name, ID and type. Validate them. */ + if (!prop_dictionary_get_cstring_nocopy(tbldict, "name", &name)) { + NPF_ERR_DEBUG(errdict); + error = EINVAL; + break; + } prop_dictionary_get_uint32(tbldict, "id", &tid); prop_dictionary_get_int32(tbldict, "type", &type); - - /* Validate them, check for duplicate IDs. */ - error = npf_table_check(tblset, tid, type); - if (error) + error = npf_table_check(tblset, name, tid, type); + if (error) { + NPF_ERR_DEBUG(errdict); break; + } /* Create and insert the table. */ - t = npf_table_create(tid, type, 1024); /* XXX */ + t = npf_table_create(name, tid, type, 1024); /* XXX */ if (t == NULL) { NPF_ERR_DEBUG(errdict); error = ENOMEM; @@ -144,7 +150,7 @@ npf_mk_tables(npf_tableset_t *tblset, prop_array_t tables, prop_dictionary_get_uint8(ent, "mask", &mask); alen = prop_data_size(obj); - error = npf_table_insert(tblset, tid, alen, addr, mask); + error = npf_table_insert(t, alen, addr, mask); if (error) break; } @@ -478,16 +484,22 @@ npfctl_reload(u_long cmd, void *data) } /* Tables. */ - tblset = npf_tableset_create(); tables = prop_dictionary_get(npf_dict, "tables"); + if ((nitems = prop_array_count(tables)) > NPF_MAX_TABLES) { + goto fail; + } + tblset = npf_tableset_create(nitems); error = npf_mk_tables(tblset, tables, errdict); if (error) { goto fail; } /* Rule procedures. */ - rpset = npf_rprocset_create(); rprocs = prop_dictionary_get(npf_dict, "rprocs"); + if ((nitems = prop_array_count(rprocs)) > NPF_MAX_RPROCS) { + goto fail; + } + rpset = npf_rprocset_create(); error = npf_mk_rprocs(rpset, rprocs, errdict); if (error) { goto fail; @@ -778,39 +790,48 @@ int npfctl_table(void *data) { const npf_ioctl_table_t *nct = data; - npf_tableset_t *tblset; - int error; + char tname[NPF_TABLE_MAXNAMELEN]; + npf_tableset_t *ts; + npf_table_t *t; + int s, error; - //npf_config_ref(); - tblset = npf_config_tableset(); + error = copyinstr(nct->nct_name, tname, sizeof(tname), NULL); + if (error) { + return error; + } + + s = npf_config_read_enter(); /* XXX */ + ts = npf_config_tableset(); + if ((t = npf_tableset_getbyname(ts, tname)) == NULL) { + npf_config_read_exit(s); + return EINVAL; + } switch (nct->nct_cmd) { case NPF_CMD_TABLE_LOOKUP: - error = npf_table_lookup(tblset, nct->nct_tid, - nct->nct_data.ent.alen, &nct->nct_data.ent.addr); + error = npf_table_lookup(t, nct->nct_data.ent.alen, + &nct->nct_data.ent.addr); break; case NPF_CMD_TABLE_ADD: - error = npf_table_insert(tblset, nct->nct_tid, - nct->nct_data.ent.alen, &nct->nct_data.ent.addr, - nct->nct_data.ent.mask); + error = npf_table_insert(t, nct->nct_data.ent.alen, + &nct->nct_data.ent.addr, nct->nct_data.ent.mask); break; case NPF_CMD_TABLE_REMOVE: - error = npf_table_remove(tblset, nct->nct_tid, - nct->nct_data.ent.alen, &nct->nct_data.ent.addr, - nct->nct_data.ent.mask); + error = npf_table_remove(t, nct->nct_data.ent.alen, + &nct->nct_data.ent.addr, nct->nct_data.ent.mask); break; case NPF_CMD_TABLE_LIST: - error = npf_table_list(tblset, nct->nct_tid, - nct->nct_data.buf.buf, nct->nct_data.buf.len); + error = npf_table_list(t, nct->nct_data.buf.buf, + nct->nct_data.buf.len); break; case NPF_CMD_TABLE_FLUSH: - error = npf_table_flush(tblset, nct->nct_tid); + error = npf_table_flush(t); break; default: error = EINVAL; break; } - //npf_config_unref(); + npf_config_read_exit(s); return error; } diff --git a/sys/net/npf/npf_impl.h b/sys/net/npf/npf_impl.h index 490bb21ef73b..5ec583fa41d9 100644 --- a/sys/net/npf/npf_impl.h +++ b/sys/net/npf/npf_impl.h @@ -1,4 +1,4 @@ -/* $NetBSD: npf_impl.h,v 1.37 2013/11/08 00:38:26 rmind Exp $ */ +/* $NetBSD: npf_impl.h,v 1.38 2013/11/12 00:46:34 rmind Exp $ */ /*- * Copyright (c) 2009-2013 The NetBSD Foundation, Inc. @@ -86,11 +86,11 @@ typedef struct npf_session npf_session_t; struct npf_sehash; struct npf_table; +struct npf_tableset; typedef struct npf_sehash npf_sehash_t; typedef struct npf_table npf_table_t; - -typedef npf_table_t * npf_tableset_t; +typedef struct npf_tableset npf_tableset_t; /* * DEFINITIONS. @@ -101,8 +101,9 @@ typedef npf_session_t *(*npf_alg_sfunc_t)(npf_cache_t *, nbuf_t *, int); typedef void (*npf_workfunc_t)(void); /* Some artificial limits. */ -#define NPF_TABLE_SLOTS 32 #define NPF_MAX_RULES (1024 * 1024) +#define NPF_MAX_TABLES 128 +#define NPF_MAX_RPROCS 128 #define NPF_MAX_IFMAP 64 /* @@ -216,23 +217,24 @@ void npf_tableset_sysfini(void); extern const pt_tree_ops_t npf_table_ptree_ops; -npf_tableset_t *npf_tableset_create(void); +npf_tableset_t *npf_tableset_create(u_int); void npf_tableset_destroy(npf_tableset_t *); int npf_tableset_insert(npf_tableset_t *, npf_table_t *); +npf_table_t * npf_tableset_getbyname(npf_tableset_t *, const char *); +npf_table_t * npf_tableset_getbyid(npf_tableset_t *, u_int); void npf_tableset_reload(npf_tableset_t *, npf_tableset_t *); -npf_table_t * npf_table_create(u_int, int, size_t); +npf_table_t * npf_table_create(const char *, u_int, int, size_t); void npf_table_destroy(npf_table_t *); -int npf_table_check(const npf_tableset_t *, u_int, int); -int npf_table_insert(npf_tableset_t *, u_int, - const int, const npf_addr_t *, const npf_netmask_t); -int npf_table_remove(npf_tableset_t *, u_int, - const int, const npf_addr_t *, const npf_netmask_t); -int npf_table_lookup(npf_tableset_t *, u_int, - const int, const npf_addr_t *); -int npf_table_list(npf_tableset_t *, u_int, void *, size_t); -int npf_table_flush(npf_tableset_t *, u_int); +int npf_table_check(npf_tableset_t *, const char *, u_int, int); +int npf_table_insert(npf_table_t *, const int, + const npf_addr_t *, const npf_netmask_t); +int npf_table_remove(npf_table_t *, const int, + const npf_addr_t *, const npf_netmask_t); +int npf_table_lookup(npf_table_t *, const int, const npf_addr_t *); +int npf_table_list(npf_table_t *, void *, size_t); +int npf_table_flush(npf_table_t *); /* Ruleset interface. */ npf_ruleset_t * npf_ruleset_create(size_t); diff --git a/sys/net/npf/npf_tableset.c b/sys/net/npf/npf_tableset.c index 54356a1f564f..855896cf922e 100644 --- a/sys/net/npf/npf_tableset.c +++ b/sys/net/npf/npf_tableset.c @@ -1,4 +1,4 @@ -/* $NetBSD: npf_tableset.c,v 1.18 2013/05/19 20:45:34 rmind Exp $ */ +/* $NetBSD: npf_tableset.c,v 1.19 2013/11/12 00:46:34 rmind Exp $ */ /*- * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. @@ -41,7 +41,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: npf_tableset.c,v 1.18 2013/05/19 20:45:34 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: npf_tableset.c,v 1.19 2013/11/12 00:46:34 rmind Exp $"); #include #include @@ -57,10 +57,6 @@ __KERNEL_RCSID(0, "$NetBSD: npf_tableset.c,v 1.18 2013/05/19 20:45:34 rmind Exp #include "npf_impl.h" -/* - * Table structures. - */ - typedef struct npf_tblent { union { LIST_ENTRY(npf_tblent) hashq; @@ -73,22 +69,36 @@ typedef struct npf_tblent { LIST_HEAD(npf_hashl, npf_tblent); struct npf_table { - char t_name[16]; - /* Lock and reference count. */ - krwlock_t t_lock; - u_int t_refcnt; - /* Total number of items. */ - u_int t_nitems; - /* Table ID. */ - u_int t_id; - /* The storage type can be: a) hash b) tree. */ - int t_type; + /* + * The storage type can be: a) hash b) tree. + * There are separate trees for IPv4 and IPv6. + */ struct npf_hashl * t_hashl; u_long t_hashmask; - /* Separate trees for IPv4 and IPv6. */ pt_tree_t t_tree[2]; + + /* + * Table ID, type and lock. The ID may change during the + * config reload, it is protected by the npf_config_lock. + */ + int t_type; + u_int t_id; + krwlock_t t_lock; + + /* The number of items, reference count and table name. */ + u_int t_nitems; + u_int t_refcnt; + char t_name[NPF_TABLE_MAXNAMELEN]; }; +struct npf_tableset { + u_int ts_nitems; + npf_table_t * ts_map[]; +}; + +#define NPF_TABLESET_SIZE(n) \ + (offsetof(npf_tableset_t, ts_map[n]) * sizeof(npf_table_t *)) + #define NPF_ADDRLEN2TREE(alen) ((alen) >> 4) static pool_cache_t tblent_cache __read_mostly; @@ -99,7 +109,6 @@ static pool_cache_t tblent_cache __read_mostly; void npf_tableset_sysinit(void) { - tblent_cache = pool_cache_init(sizeof(npf_tblent_t), coherency_unit, 0, 0, "npftblpl", NULL, IPL_NONE, NULL, NULL, NULL); } @@ -107,36 +116,32 @@ npf_tableset_sysinit(void) void npf_tableset_sysfini(void) { - pool_cache_destroy(tblent_cache); } npf_tableset_t * -npf_tableset_create(void) +npf_tableset_create(u_int nitems) { - const size_t sz = NPF_TABLE_SLOTS * sizeof(npf_table_t *); - - return kmem_zalloc(sz, KM_SLEEP); + npf_tableset_t *ts = kmem_zalloc(NPF_TABLESET_SIZE(nitems), KM_SLEEP); + ts->ts_nitems = nitems; + return ts; } void -npf_tableset_destroy(npf_tableset_t *tblset) +npf_tableset_destroy(npf_tableset_t *ts) { - const size_t sz = NPF_TABLE_SLOTS * sizeof(npf_table_t *); - npf_table_t *t; - u_int tid; - /* - * Destroy all tables (no references should be held, as ruleset - * should be destroyed before). + * Destroy all tables (no references should be held, since the + * ruleset should be destroyed before). */ - for (tid = 0; tid < NPF_TABLE_SLOTS; tid++) { - t = tblset[tid]; + for (u_int tid = 0; tid < ts->ts_nitems; tid++) { + npf_table_t *t = ts->ts_map[tid]; + if (t && atomic_dec_uint_nv(&t->t_refcnt) == 0) { npf_table_destroy(t); } } - kmem_free(tblset, sz); + kmem_free(ts, NPF_TABLESET_SIZE(ts->ts_nitems)); } /* @@ -145,16 +150,16 @@ npf_tableset_destroy(npf_tableset_t *tblset) * => Returns 0 on success. Fails and returns error if ID is already used. */ int -npf_tableset_insert(npf_tableset_t *tblset, npf_table_t *t) +npf_tableset_insert(npf_tableset_t *ts, npf_table_t *t) { const u_int tid = t->t_id; int error; - KASSERT((u_int)tid < NPF_TABLE_SLOTS); + KASSERT((u_int)tid < ts->ts_nitems); - if (tblset[tid] == NULL) { + if (ts->ts_map[tid] == NULL) { atomic_inc_uint(&t->t_refcnt); - tblset[tid] = t; + ts->ts_map[tid] = t; error = 0; } else { error = EEXIST; @@ -162,6 +167,32 @@ npf_tableset_insert(npf_tableset_t *tblset, npf_table_t *t) return error; } +/* + * npf_tableset_getbyname: look for a table in the set given the name. + */ +npf_table_t * +npf_tableset_getbyname(npf_tableset_t *ts, const char *name) +{ + npf_table_t *t; + + for (u_int tid = 0; tid < ts->ts_nitems; tid++) { + if ((t = ts->ts_map[tid]) == NULL) + continue; + if (strcmp(name, t->t_name) == 0) + return t; + } + return NULL; +} + +npf_table_t * +npf_tableset_getbyid(npf_tableset_t *ts, u_int tid) +{ + if (__predict_true(tid < ts->ts_nitems)) { + return ts->ts_map[tid]; + } + return NULL; +} + /* * npf_tableset_reload: iterate all tables and if the new table is of the * same type and has no items, then we preserve the old one and its entries. @@ -169,26 +200,44 @@ npf_tableset_insert(npf_tableset_t *tblset, npf_table_t *t) * => The caller is responsible for providing synchronisation. */ void -npf_tableset_reload(npf_tableset_t *ntset, npf_tableset_t *otset) +npf_tableset_reload(npf_tableset_t *nts, npf_tableset_t *ots) { - for (int i = 0; i < NPF_TABLE_SLOTS; i++) { - npf_table_t *t = ntset[i], *ot = otset[i]; + for (u_int tid = 0; tid < nts->ts_nitems; tid++) { + npf_table_t *t, *ot; - if (t == NULL || ot == NULL) { + if ((t = nts->ts_map[tid]) == NULL) { continue; } - if (t->t_nitems || t->t_type != ot->t_type) { + + /* If our table has entries, just load it. */ + if (t->t_nitems) { + continue; + } + + /* Look for a currently existing table with such name. */ + ot = npf_tableset_getbyname(ots, t->t_name); + if (ot == NULL) { + /* Not found: we have a new table. */ + continue; + } + + /* Found. Did the type change? */ + if (t->t_type != ot->t_type) { + /* Yes, load the new. */ continue; } /* - * Acquire a reference since the table has to be kept - * in the old tableset. + * Preserve the current table. Acquire a reference since + * we are keeping it in the old table set. Update its ID. */ atomic_inc_uint(&ot->t_refcnt); - ntset[i] = ot; + nts->ts_map[tid] = ot; - /* Only reference, never been visible. */ + KASSERT(npf_config_locked_p()); + ot->t_id = tid; + + /* Destroy the new table (we hold only reference). */ t->t_refcnt--; npf_table_destroy(t); } @@ -250,13 +299,13 @@ table_tree_destroy(pt_tree_t *tree) * npf_table_create: create table with a specified ID. */ npf_table_t * -npf_table_create(u_int tid, int type, size_t hsize) +npf_table_create(const char *name, u_int tid, int type, size_t hsize) { npf_table_t *t; - KASSERT((u_int)tid < NPF_TABLE_SLOTS); - t = kmem_zalloc(sizeof(npf_table_t), KM_SLEEP); + strlcpy(t->t_name, name, NPF_TABLE_MAXNAMELEN); + switch (type) { case NPF_TABLE_TREE: ptree_init(&t->t_tree[0], &npf_table_ptree_ops, @@ -310,21 +359,26 @@ npf_table_destroy(npf_table_t *t) } /* - * npf_table_check: validate ID and type. + * npf_table_check: validate the name, ID and type. */ int -npf_table_check(const npf_tableset_t *tset, u_int tid, int type) +npf_table_check(npf_tableset_t *ts, const char *name, u_int tid, int type) { - - if ((u_int)tid >= NPF_TABLE_SLOTS) { + if ((u_int)tid >= ts->ts_nitems) { return EINVAL; } - if (tset[tid] != NULL) { + if (ts->ts_map[tid] != NULL) { return EEXIST; } if (type != NPF_TABLE_TREE && type != NPF_TABLE_HASH) { return EINVAL; } + if (strlen(name) >= NPF_TABLE_MAXNAMELEN) { + return ENAMETOOLONG; + } + if (npf_tableset_getbyname(ts, name)) { + return EINVAL; + } return 0; } @@ -332,11 +386,10 @@ static int table_cidr_check(const u_int aidx, const npf_addr_t *addr, const npf_netmask_t mask) { - - if (mask > NPF_MAX_NETMASK && mask != NPF_NO_NETMASK) { + if (aidx > 1) { return EINVAL; } - if (aidx > 1) { + if (mask > NPF_MAX_NETMASK && mask != NPF_NO_NETMASK) { return EINVAL; } @@ -354,18 +407,13 @@ table_cidr_check(const u_int aidx, const npf_addr_t *addr, * npf_table_insert: add an IP CIDR entry into the table. */ int -npf_table_insert(npf_tableset_t *tset, u_int tid, const int alen, +npf_table_insert(npf_table_t *t, const int alen, const npf_addr_t *addr, const npf_netmask_t mask) { const u_int aidx = NPF_ADDRLEN2TREE(alen); npf_tblent_t *ent; - npf_table_t *t; int error; - if ((u_int)tid >= NPF_TABLE_SLOTS || (t = tset[tid]) == NULL) { - return EINVAL; - } - error = table_cidr_check(aidx, addr, mask); if (error) { return error; @@ -430,12 +478,11 @@ npf_table_insert(npf_tableset_t *tset, u_int tid, const int alen, * npf_table_remove: remove the IP CIDR entry from the table. */ int -npf_table_remove(npf_tableset_t *tset, u_int tid, const int alen, +npf_table_remove(npf_table_t *t, const int alen, const npf_addr_t *addr, const npf_netmask_t mask) { const u_int aidx = NPF_ADDRLEN2TREE(alen); npf_tblent_t *ent; - npf_table_t *t; int error; error = table_cidr_check(aidx, addr, mask); @@ -443,10 +490,6 @@ npf_table_remove(npf_tableset_t *tset, u_int tid, const int alen, return error; } - if ((u_int)tid >= NPF_TABLE_SLOTS || (t = tset[tid]) == NULL) { - return EINVAL; - } - rw_enter(&t->t_lock, RW_WRITER); switch (t->t_type) { case NPF_TABLE_HASH: { @@ -487,21 +530,15 @@ npf_table_remove(npf_tableset_t *tset, u_int tid, const int alen, * the contents with the specified IP address. */ int -npf_table_lookup(npf_tableset_t *tset, u_int tid, - const int alen, const npf_addr_t *addr) +npf_table_lookup(npf_table_t *t, const int alen, const npf_addr_t *addr) { const u_int aidx = NPF_ADDRLEN2TREE(alen); npf_tblent_t *ent; - npf_table_t *t; if (__predict_false(aidx > 1)) { return EINVAL; } - if ((u_int)tid >= NPF_TABLE_SLOTS || (t = tset[tid]) == NULL) { - return EINVAL; - } - rw_enter(&t->t_lock, RW_READER); switch (t->t_type) { case NPF_TABLE_HASH: { @@ -563,16 +600,11 @@ table_tree_list(pt_tree_t *tree, npf_netmask_t maxmask, void *ubuf, * npf_table_list: copy a list of all table entries into a userspace buffer. */ int -npf_table_list(npf_tableset_t *tset, u_int tid, void *ubuf, size_t len) +npf_table_list(npf_table_t *t, void *ubuf, size_t len) { - npf_table_t *t; size_t off = 0; int error = 0; - if ((u_int)tid >= NPF_TABLE_SLOTS || (t = tset[tid]) == NULL) { - return EINVAL; - } - rw_enter(&t->t_lock, RW_READER); switch (t->t_type) { case NPF_TABLE_HASH: @@ -603,14 +635,8 @@ npf_table_list(npf_tableset_t *tset, u_int tid, void *ubuf, size_t len) * npf_table_flush: remove all table entries. */ int -npf_table_flush(npf_tableset_t *tset, u_int tid) +npf_table_flush(npf_table_t *t) { - npf_table_t *t; - - if ((u_int)tid >= NPF_TABLE_SLOTS || (t = tset[tid]) == NULL) { - return EINVAL; - } - rw_enter(&t->t_lock, RW_WRITER); switch (t->t_type) { case NPF_TABLE_HASH: @@ -626,6 +652,5 @@ npf_table_flush(npf_tableset_t *tset, u_int tid) KASSERT(false); } rw_exit(&t->t_lock); - return 0; } diff --git a/usr.sbin/npf/npfctl/npf.conf.5 b/usr.sbin/npf/npfctl/npf.conf.5 index dc0c1c9ff429..40ab53b41f6f 100644 --- a/usr.sbin/npf/npfctl/npf.conf.5 +++ b/usr.sbin/npf/npfctl/npf.conf.5 @@ -1,4 +1,4 @@ -.\" $NetBSD: npf.conf.5,v 1.32 2013/11/05 13:09:12 kefren Exp $ +.\" $NetBSD: npf.conf.5,v 1.33 2013/11/12 00:46:34 rmind Exp $ .\" .\" Copyright (c) 2009-2013 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -27,7 +27,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd November 5, 2013 +.Dd November 10, 2013 .Dt NPF.CONF 5 .Os .Sh NAME @@ -78,12 +78,11 @@ $var2 = { 10.0.0.1, 10.0.0.2 } Common variable definitions are for IP addresses, networks, ports, and interfaces. .Ss Tables -Tables are specified using a number between angle brackets +Tables are specified using a name between angle brackets \*[Lt] and \*[Gt]. -The number used to specify a table should be between 0 and 15. The following is an example of table definition: .Bd -literal -table <1> type hash dynamic +table type hash dynamic .Pp .Ed Currently, tables support two storage types: "hash" or "tree". @@ -115,7 +114,7 @@ Groups may have the following options: name, interface, and direction. They are defined in the following form: .Pp .Bd -literal -group "my_group_name" in on wm0 { +group "my-name" in on wm0 { # List of rules } .Ed @@ -146,6 +145,13 @@ specification at present is limited to protocol TCP understanding flags, TCP and UDP understanding source and destination ports, and ICMP and IPv6-ICMP understanding icmp-type. .Pp +Alternatively, NPF supports +.Xr pcap-filter 7 +syntax, for example: +.Bd -literal +block out final pcap-filter "tcp and dst 10.1.1.252" +.Ed +.Pp Fragments are not selectable since NPF always reassembles packets before further processing. .Ss Map @@ -216,7 +222,7 @@ var-def = var "=" ( var-value | "{" value *[ "," value ] "}" ) ; Table definition. Table ID shall be numeric. Path is in the double quotes. -table-id = \*[Lt]tid\*[Gt] +table-id = \*[Lt]table-name\*[Gt] table-def = "table" table-id "type" ( "hash" | "tree" ) ( "dynamic" | "file" path ) @@ -242,10 +248,13 @@ group = "group" ( "default" | group-opts ) "{" rule-list "}" group-opts = name-string [ "in" | "out" ] [ "on" interface ] rule-list = [ rule new-line ] rule-list +npf-filter = [ "family" family-opt ] [ "proto" protocol [ proto-opts ] ] + ( "all" | filt-opts ) static-rule = ( "block" [ block-opts ] | "pass" ) [ "stateful" ] [ "in" | out" ] [ "final" ] [ "on" interface ] - [ "family" family-opt ] [ "proto" protocol [ proto-opts ] ] - ( "all" | filt-opts ) [ "apply" proc-name ] + ( npf-filter | "pcap-filter" pcap-filter-expr ) + [ "apply" proc-name ] + dynamic-ruleset = "ruleset" group-opts rule = static-rule | dynamic-ruleset @@ -275,8 +284,8 @@ directory containing further examples $ext_if = ifnet(wm0) $int_if = ifnet(wm1) -table <1> type hash file "/etc/npf_blacklist" -table <2> type tree dynamic +table type hash file "/etc/npf_blacklist" +table type tree dynamic $services_tcp = { http, https, smtp, domain, 6000, 9022 } $services_udp = { domain, ntp, 6000 } @@ -296,7 +305,7 @@ procedure "log" { group "external" on $ext_if { pass stateful out final all - block in final from \*[Lt]1\*[Gt] + block in final from \*[Lt]black\*[Gt] pass stateful in final family inet proto tcp to $ext_if port ssh apply "log" pass stateful in final proto tcp to $ext_if port $services_tcp pass stateful in final proto udp to $ext_if port $services_udp @@ -306,7 +315,7 @@ group "external" on $ext_if { group "internal" on $int_if { block in all - block in final from \*[Lt]2\*[Gt] + block in final from \*[Lt]limited\*[Gt] # Ingress filtering as per RFC 2827. pass in final from $localnet @@ -321,6 +330,7 @@ group default { .\" ----- .Sh SEE ALSO .Xr bpf 4 , +.Xr pcap-filter 7 , .Xr npfctl 8 .Sh HISTORY NPF first appeared in diff --git a/usr.sbin/npf/npfctl/npf_build.c b/usr.sbin/npf/npfctl/npf_build.c index a32343cc6e5b..e06ba60355f4 100644 --- a/usr.sbin/npf/npfctl/npf_build.c +++ b/usr.sbin/npf/npfctl/npf_build.c @@ -1,4 +1,4 @@ -/* $NetBSD: npf_build.c,v 1.28 2013/11/08 00:38:26 rmind Exp $ */ +/* $NetBSD: npf_build.c,v 1.29 2013/11/12 00:46:34 rmind Exp $ */ /*- * Copyright (c) 2011-2013 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ */ #include -__RCSID("$NetBSD: npf_build.c,v 1.28 2013/11/08 00:38:26 rmind Exp $"); +__RCSID("$NetBSD: npf_build.c,v 1.29 2013/11/12 00:46:34 rmind Exp $"); #include #include @@ -42,6 +42,7 @@ __RCSID("$NetBSD: npf_build.c,v 1.28 2013/11/08 00:38:26 rmind Exp $"); #include #include #include +#include #include #include @@ -658,17 +659,16 @@ npfctl_fill_table(nl_table_t *tl, u_int type, const char *fname) * if required, fill with contents from a file. */ void -npfctl_build_table(const char *tid, u_int type, const char *fname) +npfctl_build_table(const char *tname, u_int type, const char *fname) { + static unsigned tid = 0; nl_table_t *tl; - u_int id; - id = atoi(tid); - tl = npf_table_create(id, type); + tl = npf_table_create(tname, tid++, type); assert(tl != NULL); if (npf_table_insert(npf_conf, tl)) { - errx(EXIT_FAILURE, "table '%d' is already defined\n", id); + yyerror("table '%s' is already defined", tname); } if (fname) { diff --git a/usr.sbin/npf/npfctl/npf_scan.l b/usr.sbin/npf/npfctl/npf_scan.l index d730ce847047..426f974b05f1 100644 --- a/usr.sbin/npf/npfctl/npf_scan.l +++ b/usr.sbin/npf/npfctl/npf_scan.l @@ -1,4 +1,4 @@ -/* $NetBSD: npf_scan.l,v 1.13 2013/09/20 03:03:52 rmind Exp $ */ +/* $NetBSD: npf_scan.l,v 1.14 2013/11/12 00:46:34 rmind Exp $ */ /*- * Copyright (c) 2011-2012 The NetBSD Foundation, Inc. @@ -82,7 +82,7 @@ npfctl_parse_string(const char *str) %option noyywrap nounput noinput ID [a-zA-Z_][a-zA-Z_0-9]* -NID [a-zA-Z_0-9]+ +DID [a-zA-Z_][a-zA-Z_0-9-]* NUMBER [0-9]+ %% @@ -181,12 +181,12 @@ any return ANY; return NUM; } -"<"{NID}">" { +"<"{DID}">" { yylval.str = estrndup(yytext + 1, yyleng - 2); return TABLE_ID; } -"$"{NID} { +"$"{ID} { yylval.str = estrndup(yytext + 1, yyleng - 1); return VAR_ID; } diff --git a/usr.sbin/npf/npfctl/npf_show.c b/usr.sbin/npf/npfctl/npf_show.c index d228abc6d326..e23b6ad09b22 100644 --- a/usr.sbin/npf/npfctl/npf_show.c +++ b/usr.sbin/npf/npfctl/npf_show.c @@ -1,4 +1,4 @@ -/* $NetBSD: npf_show.c,v 1.3 2013/11/08 00:38:26 rmind Exp $ */ +/* $NetBSD: npf_show.c,v 1.4 2013/11/12 00:46:34 rmind Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -36,7 +36,7 @@ */ #include -__RCSID("$NetBSD: npf_show.c,v 1.3 2013/11/08 00:38:26 rmind Exp $"); +__RCSID("$NetBSD: npf_show.c,v 1.4 2013/11/12 00:46:34 rmind Exp $"); #include #include @@ -54,6 +54,7 @@ __RCSID("$NetBSD: npf_show.c,v 1.3 2013/11/08 00:38:26 rmind Exp $"); #include "npfctl.h" typedef struct { + nl_config_t * conf; FILE * fp; long fpos; } npf_conf_info_t; @@ -104,7 +105,7 @@ tcpflags2string(char *buf, u_int tfl) } static char * -print_family(const uint32_t *words) +print_family(npf_conf_info_t *ctx, const uint32_t *words) { const int af = words[0]; @@ -120,7 +121,7 @@ print_family(const uint32_t *words) } static char * -print_address(const uint32_t *words) +print_address(npf_conf_info_t *ctx, const uint32_t *words) { const int af = *words++; const u_int mask = *words++; @@ -142,7 +143,7 @@ print_address(const uint32_t *words) } static char * -print_number(const uint32_t *words) +print_number(npf_conf_info_t *ctx, const uint32_t *words) { char *p; easprintf(&p, "%u", words[0]); @@ -150,7 +151,22 @@ print_number(const uint32_t *words) } static char * -print_proto(const uint32_t *words) +print_table(npf_conf_info_t *ctx, const uint32_t *words) +{ + unsigned tid = words[0]; + nl_table_t *tl; + char *p; + + while ((tl = npf_table_iterate(ctx->conf)) != NULL) { + if (npf_table_getid(tl) == tid) + break; + } + easprintf(&p, "%s", npf_table_getname(tl)); + return p; +} + +static char * +print_proto(npf_conf_info_t *ctx, const uint32_t *words) { switch (words[0]) { case IPPROTO_TCP: @@ -162,11 +178,11 @@ print_proto(const uint32_t *words) case IPPROTO_ICMPV6: return estrdup("ipv6-icmp"); } - return print_number(words); + return print_number(ctx, words); } static char * -print_tcpflags(const uint32_t *words) +print_tcpflags(npf_conf_info_t *ctx, const uint32_t *words) { const u_int tf = words[0], tf_mask = words[1]; char buf[16]; @@ -180,7 +196,7 @@ print_tcpflags(const uint32_t *words) } static char * -print_portrange(const uint32_t *words) +print_portrange(npf_conf_info_t *ctx, const uint32_t *words) { u_int fport = words[0], tport = words[1]; char *p; @@ -224,7 +240,7 @@ static const struct mark_keyword_mapent { u_int mark; const char * token; const char * sep; - char * (*printfn)(const uint32_t *); + char * (*printfn)(npf_conf_info_t *, const uint32_t *); u_int fwords; } mark_keyword_map[] = { { BM_IPVER, "family %s", NULL, print_family, 1 }, @@ -234,11 +250,11 @@ static const struct mark_keyword_mapent { { BM_ICMP_CODE, "code %s", NULL, print_number, 1 }, { BM_SRC_CIDR, "from %s", ", ", print_address, 6 }, - { BM_SRC_TABLE, "from <%s>", NULL, print_number, 1 }, + { BM_SRC_TABLE, "from <%s>", NULL, print_table, 1 }, { BM_SRC_PORTS, "port %s", ", ", print_portrange,2 }, { BM_DST_CIDR, "to %s", ", ", print_address, 6 }, - { BM_DST_TABLE, "to <%s>", NULL, print_number, 1 }, + { BM_DST_TABLE, "to <%s>", NULL, print_table, 1 }, { BM_DST_PORTS, "port %s", ", ", print_portrange,2 }, }; @@ -267,7 +283,7 @@ scan_marks(npf_conf_info_t *ctx, const struct mark_keyword_mapent *mk, if (m == mk->mark) { /* Value is processed by the print function. */ assert(mk->fwords == nwords); - vals[nvals++] = mk->printfn(marks); + vals[nvals++] = mk->printfn(ctx, marks); } marks += nwords; mlen -= nwords; @@ -401,10 +417,10 @@ npfctl_print_nat(npf_conf_info_t *ctx, nl_nat_t *nt) static void npfctl_print_table(npf_conf_info_t *ctx, nl_table_t *tl) { - const u_int id = npf_table_getid(tl); + const char *name = npf_table_getname(tl); const int type = npf_table_gettype(tl); - fprintf(ctx->fp, "table <%u> type %s\n", id, + fprintf(ctx->fp, "table <%s> type %s\n", name, (type == NPF_TABLE_HASH) ? "hash" : (type == NPF_TABLE_TREE) ? "tree" : "unknown"); @@ -431,6 +447,7 @@ npfctl_config_show(int fd) ncf = npfctl_config_ref(); loaded = true; } + ctx->conf = ncf; if (loaded) { nl_rule_t *rl; @@ -475,6 +492,8 @@ npfctl_ruleset_show(int fd, const char *ruleset_name) int error; ncf = npf_config_create(); + ctx->conf = ncf; + if ((error = _npf_ruleset_list(fd, ruleset_name, ncf)) != 0) { return error; } diff --git a/usr.sbin/npf/npfctl/npfctl.c b/usr.sbin/npf/npfctl/npfctl.c index 85f8ffa7d8fa..abe9febffe80 100644 --- a/usr.sbin/npf/npfctl/npfctl.c +++ b/usr.sbin/npf/npfctl/npfctl.c @@ -1,4 +1,4 @@ -/* $NetBSD: npfctl.c,v 1.39 2013/09/19 12:05:11 rmind Exp $ */ +/* $NetBSD: npfctl.c,v 1.40 2013/11/12 00:46:34 rmind Exp $ */ /*- * Copyright (c) 2009-2013 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include -__RCSID("$NetBSD: npfctl.c,v 1.39 2013/09/19 12:05:11 rmind Exp $"); +__RCSID("$NetBSD: npfctl.c,v 1.40 2013/11/12 00:46:34 rmind Exp $"); #include #include @@ -274,12 +274,12 @@ npfctl_table(int fd, int argc, char **argv) npf_ioctl_table_t nct; fam_addr_mask_t fam; size_t buflen = 512; - char *cmd, *arg = NULL; /* XXX gcc */ + char *cmd, *arg; int n, alen; /* Default action is list. */ memset(&nct, 0, sizeof(npf_ioctl_table_t)); - nct.nct_tid = atoi(argv[0]); + nct.nct_name = argv[0]; cmd = argv[1]; for (n = 0; tblops[n].cmd != NULL; n++) { @@ -296,6 +296,7 @@ npfctl_table(int fd, int argc, char **argv) switch (nct.nct_cmd) { case NPF_CMD_TABLE_LIST: case NPF_CMD_TABLE_FLUSH: + arg = NULL; break; default: if (argc < 3) { diff --git a/usr.sbin/npf/npftest/libnpftest/npf_table_test.c b/usr.sbin/npf/npftest/libnpftest/npf_table_test.c index 14f12af67263..e0b89ffc1de6 100644 --- a/usr.sbin/npf/npftest/libnpftest/npf_table_test.c +++ b/usr.sbin/npf/npftest/libnpftest/npf_table_test.c @@ -1,4 +1,4 @@ -/* $NetBSD: npf_table_test.c,v 1.6 2012/10/29 02:27:11 rmind Exp $ */ +/* $NetBSD: npf_table_test.c,v 1.7 2013/11/12 00:46:34 rmind Exp $ */ /* * NPF tableset test. @@ -41,8 +41,8 @@ static const uint16_t ip6_list[][8] = { } }; -#define HASH_TID 1 -#define TREE_TID 2 +#define HASH_TID "hash-table" +#define TREE_TID "tree-table" static bool npf_table_test_fill4(npf_tableset_t *tblset, npf_addr_t *addr) @@ -53,18 +53,21 @@ npf_table_test_fill4(npf_tableset_t *tblset, npf_addr_t *addr) /* Fill both tables with IP addresses. */ for (unsigned i = 0; i < __arraycount(ip_list); i++) { + npf_table_t *t; int error; addr->s6_addr32[0] = inet_addr(ip_list[i]); - error = npf_table_insert(tblset, HASH_TID, alen, addr, nm); + t = npf_tableset_getbyname(tblset, HASH_TID); + error = npf_table_insert(t, alen, addr, nm); fail |= !(error == 0); - error = npf_table_insert(tblset, HASH_TID, alen, addr, nm); + error = npf_table_insert(t, alen, addr, nm); fail |= !(error != 0); - error = npf_table_insert(tblset, TREE_TID, alen, addr, nm); + t = npf_tableset_getbyname(tblset, TREE_TID); + error = npf_table_insert(t, alen, addr, nm); fail |= !(error == 0); - error = npf_table_insert(tblset, TREE_TID, alen, addr, nm); + error = npf_table_insert(t, alen, addr, nm); fail |= !(error != 0); } return fail; @@ -76,16 +79,16 @@ npf_table_test(bool verbose) npf_addr_t addr_storage, *addr = &addr_storage; const int nm = NPF_NO_NETMASK; npf_tableset_t *tblset; - npf_table_t *t1, *t2; + npf_table_t *t, *t1, *t2; int error, alen; bool fail = false; u_int i; - tblset = npf_tableset_create(); + tblset = npf_tableset_create(2); fail |= !(tblset != NULL); /* Table ID 1, using hash table with 256 lists. */ - t1 = npf_table_create(HASH_TID, NPF_TABLE_HASH, 256); + t1 = npf_table_create(HASH_TID, 0, NPF_TABLE_HASH, 256); fail |= !(t1 != NULL); error = npf_tableset_insert(tblset, t1); fail |= !(error == 0); @@ -94,8 +97,8 @@ npf_table_test(bool verbose) error = npf_tableset_insert(tblset, t1); fail |= !(error != 0); - /* Table ID 2, using RB-tree. */ - t2 = npf_table_create(TREE_TID, NPF_TABLE_TREE, 0); + /* Table ID 2, using a prefix tree. */ + t2 = npf_table_create(TREE_TID, 1, NPF_TABLE_TREE, 0); fail |= !(t2 != NULL); error = npf_tableset_insert(tblset, t2); fail |= !(error == 0); @@ -104,10 +107,12 @@ npf_table_test(bool verbose) addr->s6_addr32[0] = inet_addr(ip_list[0]); alen = sizeof(struct in_addr); - error = npf_table_lookup(tblset, HASH_TID, alen, addr); + t = npf_tableset_getbyname(tblset, HASH_TID); + error = npf_table_lookup(t, alen, addr); fail |= !(error != 0); - error = npf_table_lookup(tblset, TREE_TID, alen, addr); + t = npf_tableset_getbyname(tblset, TREE_TID); + error = npf_table_lookup(t, alen, addr); fail |= !(error != 0); /* Fill both tables with IP addresses. */ @@ -117,20 +122,24 @@ npf_table_test(bool verbose) addr->s6_addr32[0] = inet_addr(ip_list[0]); alen = sizeof(struct in_addr); - error = npf_table_insert(tblset, HASH_TID, alen, addr, nm); + t = npf_tableset_getbyname(tblset, HASH_TID); + error = npf_table_insert(t, alen, addr, nm); fail |= !(error != 0); - error = npf_table_insert(tblset, TREE_TID, alen, addr, nm); + t = npf_tableset_getbyname(tblset, TREE_TID); + error = npf_table_insert(t, alen, addr, nm); fail |= !(error != 0); /* Match (validate) each IP entry. */ for (i = 0; i < __arraycount(ip_list); i++) { addr->s6_addr32[0] = inet_addr(ip_list[i]); - error = npf_table_lookup(tblset, HASH_TID, alen, addr); + t = npf_tableset_getbyname(tblset, HASH_TID); + error = npf_table_lookup(t, alen, addr); fail |= !(error == 0); - error = npf_table_lookup(tblset, TREE_TID, alen, addr); + t = npf_tableset_getbyname(tblset, TREE_TID); + error = npf_table_lookup(t, alen, addr); fail |= !(error == 0); } @@ -138,18 +147,20 @@ npf_table_test(bool verbose) memcpy(addr, ip6_list[0], sizeof(ip6_list[0])); alen = sizeof(struct in6_addr); - error = npf_table_insert(tblset, HASH_TID, alen, addr, nm); + t = npf_tableset_getbyname(tblset, HASH_TID); + error = npf_table_insert(t, alen, addr, nm); fail |= !(error == 0); - error = npf_table_lookup(tblset, HASH_TID, alen, addr); + error = npf_table_lookup(t, alen, addr); fail |= !(error == 0); - error = npf_table_remove(tblset, HASH_TID, alen, addr, nm); + error = npf_table_remove(t, alen, addr, nm); fail |= !(error == 0); - error = npf_table_insert(tblset, TREE_TID, alen, addr, nm); + t = npf_tableset_getbyname(tblset, TREE_TID); + error = npf_table_insert(t, alen, addr, nm); fail |= !(error == 0); - error = npf_table_lookup(tblset, TREE_TID, alen, addr); + error = npf_table_lookup(t, alen, addr); fail |= !(error == 0); - error = npf_table_remove(tblset, TREE_TID, alen, addr, nm); + error = npf_table_remove(t, alen, addr, nm); fail |= !(error == 0); /* @@ -157,41 +168,41 @@ npf_table_test(bool verbose) */ memcpy(addr, ip6_list[1], sizeof(ip6_list[1])); - error = npf_table_insert(tblset, TREE_TID, alen, addr, 96); + error = npf_table_insert(t, alen, addr, 96); fail |= !(error == 0); memcpy(addr, ip6_list[0], sizeof(ip6_list[0])); - error = npf_table_lookup(tblset, TREE_TID, alen, addr); + error = npf_table_lookup(t, alen, addr); fail |= !(error == 0); memcpy(addr, ip6_list[1], sizeof(ip6_list[1])); - error = npf_table_remove(tblset, TREE_TID, alen, addr, 96); + error = npf_table_remove(t, alen, addr, 96); fail |= !(error == 0); memcpy(addr, ip6_list[2], sizeof(ip6_list[2])); - error = npf_table_insert(tblset, TREE_TID, alen, addr, 32); + error = npf_table_insert(t, alen, addr, 32); fail |= !(error == 0); memcpy(addr, ip6_list[0], sizeof(ip6_list[0])); - error = npf_table_lookup(tblset, TREE_TID, alen, addr); + error = npf_table_lookup(t, alen, addr); fail |= !(error == 0); memcpy(addr, ip6_list[2], sizeof(ip6_list[2])); - error = npf_table_remove(tblset, TREE_TID, alen, addr, 32); + error = npf_table_remove(t, alen, addr, 32); fail |= !(error == 0); memcpy(addr, ip6_list[3], sizeof(ip6_list[3])); - error = npf_table_insert(tblset, TREE_TID, alen, addr, 126); + error = npf_table_insert(t, alen, addr, 126); fail |= !(error == 0); memcpy(addr, ip6_list[0], sizeof(ip6_list[0])); - error = npf_table_lookup(tblset, TREE_TID, alen, addr); + error = npf_table_lookup(t, alen, addr); fail |= !(error != 0); memcpy(addr, ip6_list[3], sizeof(ip6_list[3])); - error = npf_table_remove(tblset, TREE_TID, alen, addr, 126); + error = npf_table_remove(t, alen, addr, 126); fail |= !(error == 0); @@ -201,10 +212,12 @@ npf_table_test(bool verbose) for (i = 0; i < __arraycount(ip_list); i++) { addr->s6_addr32[0] = inet_addr(ip_list[i]); - error = npf_table_remove(tblset, HASH_TID, alen, addr, nm); + t = npf_tableset_getbyname(tblset, HASH_TID); + error = npf_table_remove(t, alen, addr, nm); fail |= !(error == 0); - error = npf_table_remove(tblset, TREE_TID, alen, addr, nm); + t = npf_tableset_getbyname(tblset, TREE_TID); + error = npf_table_remove(t, alen, addr, nm); fail |= !(error == 0); }