Module Name: src
Committed By: rmind
Date: Thu Feb 6 02:51:28 UTC 2014
Modified Files:
src/lib/libnpf: npf.c npf.h
src/sys/net/npf: npf.h npf_ctl.c npf_impl.h npf_tableset.c
src/usr.sbin/npf/npfctl: npf.conf.5 npf_build.c npf_parse.y npf_scan.l
src/usr.sbin/npf/npftest: npftest.c npftest.h
src/usr.sbin/npf/npftest/libnpftest: npf_table_test.c npf_test.h
Log Message:
Add support for CDB based NPF tables.
To generate a diff of this commit:
cvs rdiff -u -r1.25 -r1.26 src/lib/libnpf/npf.c
cvs rdiff -u -r1.22 -r1.23 src/lib/libnpf/npf.h
cvs rdiff -u -r1.34 -r1.35 src/sys/net/npf/npf.h
cvs rdiff -u -r1.32 -r1.33 src/sys/net/npf/npf_ctl.c
cvs rdiff -u -r1.45 -r1.46 src/sys/net/npf/npf_impl.h
cvs rdiff -u -r1.20 -r1.21 src/sys/net/npf/npf_tableset.c
cvs rdiff -u -r1.35 -r1.36 src/usr.sbin/npf/npfctl/npf.conf.5
cvs rdiff -u -r1.32 -r1.33 src/usr.sbin/npf/npfctl/npf_build.c
cvs rdiff -u -r1.29 -r1.30 src/usr.sbin/npf/npfctl/npf_parse.y
cvs rdiff -u -r1.16 -r1.17 src/usr.sbin/npf/npfctl/npf_scan.l
cvs rdiff -u -r1.15 -r1.16 src/usr.sbin/npf/npftest/npftest.c
cvs rdiff -u -r1.11 -r1.12 src/usr.sbin/npf/npftest/npftest.h
cvs rdiff -u -r1.7 -r1.8 src/usr.sbin/npf/npftest/libnpftest/npf_table_test.c
cvs rdiff -u -r1.12 -r1.13 src/usr.sbin/npf/npftest/libnpftest/npf_test.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/lib/libnpf/npf.c
diff -u src/lib/libnpf/npf.c:1.25 src/lib/libnpf/npf.c:1.26
--- src/lib/libnpf/npf.c:1.25 Mon Feb 3 02:21:52 2014
+++ src/lib/libnpf/npf.c Thu Feb 6 02:51:28 2014
@@ -1,7 +1,7 @@
-/* $NetBSD: npf.c,v 1.25 2014/02/03 02:21:52 rmind Exp $ */
+/* $NetBSD: npf.c,v 1.26 2014/02/06 02:51:28 rmind Exp $ */
/*-
- * Copyright (c) 2010-2013 The NetBSD Foundation, Inc.
+ * Copyright (c) 2010-2014 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This material is based upon work partially supported by The
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.25 2014/02/03 02:21:52 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.26 2014/02/06 02:51:28 rmind Exp $");
#include <sys/types.h>
#include <netinet/in_systm.h>
@@ -961,6 +961,20 @@ npf_table_add_entry(nl_table_t *tl, int
return 0;
}
+int
+npf_table_setdata(nl_table_t *tl, const void *blob, size_t len)
+{
+ prop_dictionary_t tldict = tl->ntl_dict;
+ prop_data_t bobj;
+
+ if ((bobj = prop_data_create_data(blob, len)) == NULL) {
+ return ENOMEM;
+ }
+ prop_dictionary_set(tldict, "data", bobj);
+ prop_object_release(bobj);
+ return 0;
+}
+
static bool
_npf_table_exists_p(nl_config_t *ncf, const char *name)
{
Index: src/lib/libnpf/npf.h
diff -u src/lib/libnpf/npf.h:1.22 src/lib/libnpf/npf.h:1.23
--- src/lib/libnpf/npf.h:1.22 Mon Feb 3 02:21:52 2014
+++ src/lib/libnpf/npf.h Thu Feb 6 02:51:28 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: npf.h,v 1.22 2014/02/03 02:21:52 rmind Exp $ */
+/* $NetBSD: npf.h,v 1.23 2014/02/06 02:51:28 rmind Exp $ */
/*-
* Copyright (c) 2011-2013 The NetBSD Foundation, Inc.
@@ -111,6 +111,7 @@ int npf_nat_insert(nl_config_t *, nl_na
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);
+int npf_table_setdata(nl_table_t *, const void *, size_t);
int npf_table_insert(nl_config_t *, nl_table_t *);
void npf_table_destroy(nl_table_t *);
Index: src/sys/net/npf/npf.h
diff -u src/sys/net/npf/npf.h:1.34 src/sys/net/npf/npf.h:1.35
--- src/sys/net/npf/npf.h:1.34 Fri Dec 6 01:33:37 2013
+++ src/sys/net/npf/npf.h Thu Feb 6 02:51:28 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: npf.h,v 1.34 2013/12/06 01:33:37 rmind Exp $ */
+/* $NetBSD: npf.h,v 1.35 2014/02/06 02:51:28 rmind Exp $ */
/*-
* Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
@@ -239,6 +239,7 @@ bool npf_autounload_p(void);
/* Table types. */
#define NPF_TABLE_HASH 1
#define NPF_TABLE_TREE 2
+#define NPF_TABLE_CDB 3
#define NPF_TABLE_MAXNAMELEN 32
Index: src/sys/net/npf/npf_ctl.c
diff -u src/sys/net/npf/npf_ctl.c:1.32 src/sys/net/npf/npf_ctl.c:1.33
--- src/sys/net/npf/npf_ctl.c:1.32 Tue Nov 12 00:46:34 2013
+++ src/sys/net/npf/npf_ctl.c Thu Feb 6 02:51:28 2014
@@ -1,7 +1,7 @@
-/* $NetBSD: npf_ctl.c,v 1.32 2013/11/12 00:46:34 rmind Exp $ */
+/* $NetBSD: npf_ctl.c,v 1.33 2014/02/06 02:51:28 rmind Exp $ */
/*-
- * Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
+ * Copyright (c) 2009-2014 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This material is based upon work partially supported by The
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_ctl.c,v 1.32 2013/11/12 00:46:34 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_ctl.c,v 1.33 2014/02/06 02:51:28 rmind Exp $");
#include <sys/param.h>
#include <sys/conf.h>
@@ -77,6 +77,34 @@ npfctl_switch(void *data)
}
static int __noinline
+npf_mk_table_entries(npf_table_t *t, prop_array_t entries)
+{
+ prop_object_iterator_t eit;
+ prop_dictionary_t ent;
+ int error = 0;
+
+ /* Fill all the entries. */
+ eit = prop_array_iterator(entries);
+ while ((ent = prop_object_iterator_next(eit)) != NULL) {
+ const npf_addr_t *addr;
+ npf_netmask_t mask;
+ int alen;
+
+ /* Get address and mask. Add a table entry. */
+ prop_object_t obj = prop_dictionary_get(ent, "addr");
+ addr = (const npf_addr_t *)prop_data_data_nocopy(obj);
+ prop_dictionary_get_uint8(ent, "mask", &mask);
+ alen = prop_data_size(obj);
+
+ error = npf_table_insert(t, alen, addr, mask);
+ if (error)
+ break;
+ }
+ prop_object_iterator_release(eit);
+ return error;
+}
+
+static int __noinline
npf_mk_tables(npf_tableset_t *tblset, prop_array_t tables,
prop_dictionary_t errdict)
{
@@ -92,9 +120,6 @@ npf_mk_tables(npf_tableset_t *tblset, pr
it = prop_array_iterator(tables);
while ((tbldict = prop_object_iterator_next(it)) != NULL) {
- prop_dictionary_t ent;
- prop_object_iterator_t eit;
- prop_array_t entries;
const char *name;
npf_table_t *t;
u_int tid;
@@ -121,8 +146,25 @@ npf_mk_tables(npf_tableset_t *tblset, pr
break;
}
+ /* Get the entries or binary data. */
+ prop_array_t entries = prop_dictionary_get(tbldict, "entries");
+ if (prop_object_type(entries) != PROP_TYPE_ARRAY) {
+ NPF_ERR_DEBUG(errdict);
+ error = EINVAL;
+ break;
+ }
+ prop_object_t obj = prop_dictionary_get(tbldict, "data");
+ void *blob = prop_data_data(obj);
+ size_t size = prop_data_size(obj);
+
+ if (type == NPF_TABLE_CDB && (blob == NULL || size == 0)) {
+ NPF_ERR_DEBUG(errdict);
+ error = EINVAL;
+ break;
+ }
+
/* Create and insert the table. */
- t = npf_table_create(name, tid, type, 1024); /* XXX */
+ t = npf_table_create(name, tid, type, blob, size);
if (t == NULL) {
NPF_ERR_DEBUG(errdict);
error = ENOMEM;
@@ -131,32 +173,10 @@ npf_mk_tables(npf_tableset_t *tblset, pr
error = npf_tableset_insert(tblset, t);
KASSERT(error == 0);
- /* Entries. */
- entries = prop_dictionary_get(tbldict, "entries");
- if (prop_object_type(entries) != PROP_TYPE_ARRAY) {
+ if ((error = npf_mk_table_entries(t, entries)) != 0) {
NPF_ERR_DEBUG(errdict);
- error = EINVAL;
break;
}
- eit = prop_array_iterator(entries);
- while ((ent = prop_object_iterator_next(eit)) != NULL) {
- const npf_addr_t *addr;
- npf_netmask_t mask;
- int alen;
-
- /* Get address and mask. Add a table entry. */
- prop_object_t obj = prop_dictionary_get(ent, "addr");
- addr = (const npf_addr_t *)prop_data_data_nocopy(obj);
- prop_dictionary_get_uint8(ent, "mask", &mask);
- alen = prop_data_size(obj);
-
- error = npf_table_insert(t, alen, addr, mask);
- if (error)
- break;
- }
- prop_object_iterator_release(eit);
- if (error)
- break;
}
prop_object_iterator_release(it);
/*
Index: src/sys/net/npf/npf_impl.h
diff -u src/sys/net/npf/npf_impl.h:1.45 src/sys/net/npf/npf_impl.h:1.46
--- src/sys/net/npf/npf_impl.h:1.45 Fri Dec 6 01:33:37 2013
+++ src/sys/net/npf/npf_impl.h Thu Feb 6 02:51:28 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_impl.h,v 1.45 2013/12/06 01:33:37 rmind Exp $ */
+/* $NetBSD: npf_impl.h,v 1.46 2014/02/06 02:51:28 rmind Exp $ */
/*-
* Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
@@ -229,7 +229,7 @@ npf_table_t * npf_tableset_getbyid(npf_t
void npf_tableset_reload(npf_tableset_t *, npf_tableset_t *);
void npf_tableset_syncdict(const npf_tableset_t *, prop_dictionary_t);
-npf_table_t * npf_table_create(const char *, u_int, int, size_t);
+npf_table_t * npf_table_create(const char *, u_int, int, void *, size_t);
void npf_table_destroy(npf_table_t *);
int npf_table_check(npf_tableset_t *, const char *, u_int, int);
Index: src/sys/net/npf/npf_tableset.c
diff -u src/sys/net/npf/npf_tableset.c:1.20 src/sys/net/npf/npf_tableset.c:1.21
--- src/sys/net/npf/npf_tableset.c:1.20 Fri Nov 22 00:25:51 2013
+++ src/sys/net/npf/npf_tableset.c Thu Feb 6 02:51:28 2014
@@ -1,7 +1,7 @@
-/* $NetBSD: npf_tableset.c,v 1.20 2013/11/22 00:25:51 rmind Exp $ */
+/* $NetBSD: npf_tableset.c,v 1.21 2014/02/06 02:51:28 rmind Exp $ */
/*-
- * Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
+ * Copyright (c) 2009-2014 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This material is based upon work partially supported by The
@@ -41,14 +41,16 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_tableset.c,v 1.20 2013/11/22 00:25:51 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_tableset.c,v 1.21 2014/02/06 02:51:28 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
#include <sys/atomic.h>
#include <sys/hash.h>
+#include <sys/cdbr.h>
#include <sys/kmem.h>
+#include <sys/malloc.h>
#include <sys/pool.h>
#include <sys/queue.h>
#include <sys/rwlock.h>
@@ -59,9 +61,9 @@ __KERNEL_RCSID(0, "$NetBSD: npf_tableset
typedef struct npf_tblent {
union {
- LIST_ENTRY(npf_tblent) hashq;
- pt_node_t node;
- } te_entry;
+ LIST_ENTRY(npf_tblent) te_hashent;
+ pt_node_t te_node;
+ } /* C11 */;
int te_alen;
npf_addr_t te_addr;
} npf_tblent_t;
@@ -70,12 +72,23 @@ LIST_HEAD(npf_hashl, npf_tblent);
struct npf_table {
/*
- * The storage type can be: a) hash b) tree.
+ * The storage type can be: a) hash b) tree c) cdb.
* There are separate trees for IPv4 and IPv6.
*/
- struct npf_hashl * t_hashl;
- u_long t_hashmask;
- pt_tree_t t_tree[2];
+ union {
+ struct {
+ struct npf_hashl *t_hashl;
+ u_long t_hashmask;
+ };
+ struct {
+ pt_tree_t t_tree[2];
+ };
+ struct {
+ void * t_blob;
+ size_t t_bsize;
+ struct cdbr * t_cdb;
+ };
+ } /* C11 */;
/*
* Table ID, type and lock. The ID may change during the
@@ -237,7 +250,7 @@ npf_tableset_reload(npf_tableset_t *nts,
KASSERT(npf_config_locked_p());
ot->t_id = tid;
- /* Destroy the new table (we hold only reference). */
+ /* Destroy the new table (we hold the only reference). */
t->t_refcnt--;
npf_table_destroy(t);
}
@@ -284,7 +297,7 @@ table_hash_lookup(const npf_table_t *t,
* Lookup the hash table and check for duplicates.
* Note: mask is ignored for the hash storage.
*/
- LIST_FOREACH(ent, htbl, te_entry.hashq) {
+ LIST_FOREACH(ent, htbl, te_hashent) {
if (ent->te_alen != alen) {
continue;
}
@@ -303,7 +316,7 @@ table_hash_destroy(npf_table_t *t)
npf_tblent_t *ent;
while ((ent = LIST_FIRST(&t->t_hashl[n])) != NULL) {
- LIST_REMOVE(ent, te_entry.hashq);
+ LIST_REMOVE(ent, te_hashent);
pool_cache_put(tblent_cache, ent);
}
}
@@ -324,7 +337,8 @@ table_tree_destroy(pt_tree_t *tree)
* npf_table_create: create table with a specified ID.
*/
npf_table_t *
-npf_table_create(const char *name, u_int tid, int type, size_t hsize)
+npf_table_create(const char *name, u_int tid, int type,
+ void *blob, size_t size)
{
npf_table_t *t;
@@ -335,20 +349,31 @@ npf_table_create(const char *name, u_int
case NPF_TABLE_TREE:
ptree_init(&t->t_tree[0], &npf_table_ptree_ops,
(void *)(sizeof(struct in_addr) / sizeof(uint32_t)),
- offsetof(npf_tblent_t, te_entry.node),
+ offsetof(npf_tblent_t, te_node),
offsetof(npf_tblent_t, te_addr));
ptree_init(&t->t_tree[1], &npf_table_ptree_ops,
(void *)(sizeof(struct in6_addr) / sizeof(uint32_t)),
- offsetof(npf_tblent_t, te_entry.node),
+ offsetof(npf_tblent_t, te_node),
offsetof(npf_tblent_t, te_addr));
break;
case NPF_TABLE_HASH:
- t->t_hashl = hashinit(hsize, HASH_LIST, true, &t->t_hashmask);
+ t->t_hashl = hashinit(1024, HASH_LIST, true, &t->t_hashmask);
if (t->t_hashl == NULL) {
kmem_free(t, sizeof(npf_table_t));
return NULL;
}
break;
+ case NPF_TABLE_CDB:
+ t->t_blob = blob;
+ t->t_bsize = size;
+ t->t_cdb = cdbr_open_mem(blob, size, CDBR_DEFAULT, NULL, NULL);
+ if (t->t_cdb == NULL) {
+ kmem_free(t, sizeof(npf_table_t));
+ free(blob, M_TEMP);
+ return NULL;
+ }
+ t->t_nitems = cdbr_entries(t->t_cdb);
+ break;
default:
KASSERT(false);
}
@@ -376,6 +401,10 @@ npf_table_destroy(npf_table_t *t)
table_tree_destroy(&t->t_tree[0]);
table_tree_destroy(&t->t_tree[1]);
break;
+ case NPF_TABLE_CDB:
+ cdbr_close(t->t_cdb);
+ free(t->t_blob, M_TEMP);
+ break;
default:
KASSERT(false);
}
@@ -395,7 +424,12 @@ npf_table_check(npf_tableset_t *ts, cons
if (ts->ts_map[tid] != NULL) {
return EEXIST;
}
- if (type != NPF_TABLE_TREE && type != NPF_TABLE_HASH) {
+ switch (type) {
+ case NPF_TABLE_TREE:
+ case NPF_TABLE_HASH:
+ case NPF_TABLE_CDB:
+ break;
+ default:
return EINVAL;
}
if (strlen(name) >= NPF_TABLE_MAXNAMELEN) {
@@ -463,7 +497,7 @@ npf_table_insert(npf_table_t *t, const i
break;
}
if (!table_hash_lookup(t, addr, alen, &htbl)) {
- LIST_INSERT_HEAD(htbl, ent, te_entry.hashq);
+ LIST_INSERT_HEAD(htbl, ent, te_hashent);
t->t_nitems++;
} else {
error = EEXIST;
@@ -488,6 +522,9 @@ npf_table_insert(npf_table_t *t, const i
}
break;
}
+ case NPF_TABLE_CDB:
+ error = EINVAL;
+ break;
default:
KASSERT(false);
}
@@ -507,8 +544,8 @@ npf_table_remove(npf_table_t *t, const i
const npf_addr_t *addr, const npf_netmask_t mask)
{
const u_int aidx = NPF_ADDRLEN2TREE(alen);
- npf_tblent_t *ent;
- int error;
+ npf_tblent_t *ent = NULL;
+ int error = ENOENT;
error = table_cidr_check(aidx, addr, mask);
if (error) {
@@ -522,7 +559,7 @@ npf_table_remove(npf_table_t *t, const i
ent = table_hash_lookup(t, addr, alen, &htbl);
if (__predict_true(ent != NULL)) {
- LIST_REMOVE(ent, te_entry.hashq);
+ LIST_REMOVE(ent, te_hashent);
t->t_nitems--;
}
break;
@@ -537,17 +574,19 @@ npf_table_remove(npf_table_t *t, const i
}
break;
}
+ case NPF_TABLE_CDB:
+ error = EINVAL;
+ break;
default:
KASSERT(false);
ent = NULL;
}
rw_exit(&t->t_lock);
- if (ent == NULL) {
- return ENOENT;
+ if (ent) {
+ pool_cache_put(tblent_cache, ent);
}
- pool_cache_put(tblent_cache, ent);
- return 0;
+ return error;
}
/*
@@ -558,34 +597,43 @@ int
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;
+ struct npf_hashl *htbl;
+ const void *data;
+ size_t dlen;
+ bool found;
if (__predict_false(aidx > 1)) {
return EINVAL;
}
- rw_enter(&t->t_lock, RW_READER);
switch (t->t_type) {
- case NPF_TABLE_HASH: {
- struct npf_hashl *htbl;
- ent = table_hash_lookup(t, addr, alen, &htbl);
+ case NPF_TABLE_HASH:
+ rw_enter(&t->t_lock, RW_READER);
+ found = table_hash_lookup(t, addr, alen, &htbl) != NULL;
+ rw_exit(&t->t_lock);
break;
- }
- case NPF_TABLE_TREE: {
- ent = ptree_find_node(&t->t_tree[aidx], addr);
+ case NPF_TABLE_TREE:
+ rw_enter(&t->t_lock, RW_READER);
+ found = ptree_find_node(&t->t_tree[aidx], addr) != NULL;
+ rw_exit(&t->t_lock);
+ break;
+ case NPF_TABLE_CDB:
+ if (cdbr_find(t->t_cdb, addr, alen, &data, &dlen) == 0) {
+ found = dlen == alen && memcmp(addr, data, dlen) == 0;
+ } else {
+ found = false;
+ }
break;
- }
default:
KASSERT(false);
- ent = NULL;
+ found = false;
}
- rw_exit(&t->t_lock);
- return ent ? 0 : ENOENT;
+ return found ? 0 : ENOENT;
}
static int
-table_ent_copyout(npf_tblent_t *ent, npf_netmask_t mask,
+table_ent_copyout(const npf_addr_t *addr, const int alen, npf_netmask_t mask,
void *ubuf, size_t len, size_t *off)
{
void *ubufp = (uint8_t *)ubuf + *off;
@@ -594,14 +642,33 @@ table_ent_copyout(npf_tblent_t *ent, npf
if ((*off += sizeof(npf_ioctl_ent_t)) > len) {
return ENOMEM;
}
- uent.alen = ent->te_alen;
- memcpy(&uent.addr, &ent->te_addr, sizeof(npf_addr_t));
+ uent.alen = alen;
+ memcpy(&uent.addr, addr, sizeof(npf_addr_t));
uent.mask = mask;
return copyout(&uent, ubufp, sizeof(npf_ioctl_ent_t));
}
static int
+table_hash_list(const npf_table_t *t, void *ubuf, size_t len)
+{
+ size_t off = 0;
+ int error = 0;
+
+ for (unsigned n = 0; n <= t->t_hashmask; n++) {
+ npf_tblent_t *ent;
+
+ LIST_FOREACH(ent, &t->t_hashl[n], te_hashent) {
+ error = table_ent_copyout(&ent->te_addr,
+ ent->te_alen, 0, ubuf, len, &off);
+ if (error)
+ break;
+ }
+ }
+ return error;
+}
+
+static int
table_tree_list(pt_tree_t *tree, npf_netmask_t maxmask, void *ubuf,
size_t len, size_t *off)
{
@@ -614,7 +681,26 @@ table_tree_list(pt_tree_t *tree, npf_net
if (!ptree_mask_node_p(tree, ent, &blen)) {
blen = maxmask;
}
- error = table_ent_copyout(ent, blen, ubuf, len, off);
+ error = table_ent_copyout(&ent->te_addr, ent->te_alen,
+ blen, ubuf, len, off);
+ if (error)
+ break;
+ }
+ return error;
+}
+
+static int
+table_cdb_list(npf_table_t *t, void *ubuf, size_t len)
+{
+ size_t off = 0, dlen;
+ const void *data;
+ int error = 0;
+
+ for (size_t i = 0; i < t->t_nitems; i++) {
+ if (cdbr_get(t->t_cdb, i, &data, &dlen) != 0) {
+ return EINVAL;
+ }
+ error = table_ent_copyout(data, dlen, 0, ubuf, len, &off);
if (error)
break;
}
@@ -633,14 +719,7 @@ npf_table_list(npf_table_t *t, void *ubu
rw_enter(&t->t_lock, RW_READER);
switch (t->t_type) {
case NPF_TABLE_HASH:
- for (unsigned n = 0; n <= t->t_hashmask; n++) {
- npf_tblent_t *ent;
-
- LIST_FOREACH(ent, &t->t_hashl[n], te_entry.hashq)
- if ((error = table_ent_copyout(ent, 0, ubuf,
- len, &off)) != 0)
- break;
- }
+ error = table_hash_list(t, ubuf, len);
break;
case NPF_TABLE_TREE:
error = table_tree_list(&t->t_tree[0], 32, ubuf, len, &off);
@@ -648,6 +727,9 @@ npf_table_list(npf_table_t *t, void *ubu
break;
error = table_tree_list(&t->t_tree[1], 128, ubuf, len, &off);
break;
+ case NPF_TABLE_CDB:
+ error = table_cdb_list(t, ubuf, len);
+ break;
default:
KASSERT(false);
}
@@ -662,6 +744,8 @@ npf_table_list(npf_table_t *t, void *ubu
int
npf_table_flush(npf_table_t *t)
{
+ int error = 0;
+
rw_enter(&t->t_lock, RW_WRITER);
switch (t->t_type) {
case NPF_TABLE_HASH:
@@ -673,9 +757,12 @@ npf_table_flush(npf_table_t *t)
table_tree_destroy(&t->t_tree[1]);
t->t_nitems = 0;
break;
+ case NPF_TABLE_CDB:
+ error = EINVAL;
+ break;
default:
KASSERT(false);
}
rw_exit(&t->t_lock);
- return 0;
+ return error;
}
Index: src/usr.sbin/npf/npfctl/npf.conf.5
diff -u src/usr.sbin/npf/npfctl/npf.conf.5:1.35 src/usr.sbin/npf/npfctl/npf.conf.5:1.36
--- src/usr.sbin/npf/npfctl/npf.conf.5:1.35 Tue Nov 19 00:28:41 2013
+++ src/usr.sbin/npf/npfctl/npf.conf.5 Thu Feb 6 02:51:28 2014
@@ -1,6 +1,6 @@
-.\" $NetBSD: npf.conf.5,v 1.35 2013/11/19 00:28:41 rmind Exp $
+.\" $NetBSD: npf.conf.5,v 1.36 2014/02/06 02:51:28 rmind Exp $
.\"
-.\" Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
+.\" Copyright (c) 2009-2014 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This material is based upon work partially supported by The
@@ -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 18, 2013
+.Dd February 6, 2014
.Dt NPF.CONF 5
.Os
.Sh NAME
@@ -85,7 +85,7 @@ The following is an example of table def
table <black> type hash dynamic
.Pp
.Ed
-Currently, tables support two storage types: "hash" or "tree".
+Currently, tables support two storage types: "hash", "tree" or "cdb".
They can also be "dynamic" or static i.e. loaded from the specified file.
.Pp
The file should contain a list of IP addresses and/or networks in the form of:
@@ -94,7 +94,8 @@ The file should contain a list of IP add
10.1.1.1
.Ed
.Pp
-Tables of type "hash" can only contain IP addresses.
+Tables of type "hash" and "cdb" can only contain IP addresses.
+Also, the latter can only be static.
.Ss Interfaces
Interfaces can be specified as the values of the variables:
.Pp
@@ -223,7 +224,7 @@ var-def = var "=" ( var-value | "{" val
; Table definition. Table ID shall be numeric. Path is in the double quotes.
table-id = \*[Lt]table-name\*[Gt]
-table-def = "table" table-id "type" ( "hash" | "tree" )
+table-def = "table" table-id "type" ( "hash" | "tree" | "cdb" )
( "dynamic" | "file" path )
; Mapping for address translation.
Index: src/usr.sbin/npf/npfctl/npf_build.c
diff -u src/usr.sbin/npf/npfctl/npf_build.c:1.32 src/usr.sbin/npf/npfctl/npf_build.c:1.33
--- src/usr.sbin/npf/npfctl/npf_build.c:1.32 Mon Feb 3 02:21:52 2014
+++ src/usr.sbin/npf/npfctl/npf_build.c Thu Feb 6 02:51:28 2014
@@ -1,7 +1,7 @@
-/* $NetBSD: npf_build.c,v 1.32 2014/02/03 02:21:52 rmind Exp $ */
+/* $NetBSD: npf_build.c,v 1.33 2014/02/06 02:51:28 rmind Exp $ */
/*-
- * Copyright (c) 2011-2013 The NetBSD Foundation, Inc.
+ * Copyright (c) 2011-2014 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This material is based upon work partially supported by The
@@ -34,19 +34,22 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: npf_build.c,v 1.32 2014/02/03 02:21:52 rmind Exp $");
+__RCSID("$NetBSD: npf_build.c,v 1.33 2014/02/06 02:51:28 rmind Exp $");
#include <sys/types.h>
-#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
#include <stdlib.h>
#include <inttypes.h>
#include <string.h>
#include <ctype.h>
+#include <unistd.h>
#include <errno.h>
#include <err.h>
#include <pcap/pcap.h>
+#include <cdbw.h>
#include "npfctl.h"
@@ -635,11 +638,15 @@ npfctl_build_natseg(int sd, int type, co
static void
npfctl_fill_table(nl_table_t *tl, u_int type, const char *fname)
{
+ struct cdbw *cdbw;
char *buf = NULL;
int l = 0;
FILE *fp;
size_t n;
+ if (type == NPF_TABLE_CDB && (cdbw = cdbw_open()) == NULL) {
+ err(EXIT_FAILURE, "cdbw_open");
+ }
fp = fopen(fname, "r");
if (fp == NULL) {
err(EXIT_FAILURE, "open '%s'", fname);
@@ -656,18 +663,56 @@ npfctl_fill_table(nl_table_t *tl, u_int
errx(EXIT_FAILURE,
"%s:%d: invalid table entry", fname, l);
}
- if (type == NPF_TABLE_HASH && fam.fam_mask != NPF_NO_NETMASK) {
- errx(EXIT_FAILURE,
- "%s:%d: mask used with the hash table", fname, l);
+ if (type != NPF_TABLE_TREE && fam.fam_mask != NPF_NO_NETMASK) {
+ errx(EXIT_FAILURE, "%s:%d: mask used with the "
+ "non-tree table", fname, l);
}
- /* Create and add a table entry. */
- npf_table_add_entry(tl, fam.fam_family,
- &fam.fam_addr, fam.fam_mask);
+ /*
+ * Create and add a table entry.
+ */
+ if (type == NPF_TABLE_CDB) {
+ const npf_addr_t *addr = &fam.fam_addr;
+ if (cdbw_put(cdbw, addr, alen, addr, alen) == -1) {
+ err(EXIT_FAILURE, "cdbw_put");
+ }
+ } else {
+ npf_table_add_entry(tl, fam.fam_family,
+ &fam.fam_addr, fam.fam_mask);
+ }
}
if (buf != NULL) {
free(buf);
}
+
+ if (type == NPF_TABLE_CDB) {
+ struct stat sb;
+ char sfn[32];
+ void *cdb;
+ int fd;
+
+ strlcpy(sfn, "/tmp/npfcdb.XXXXXX", sizeof(sfn));
+ if ((fd = mkstemp(sfn)) == -1) {
+ err(EXIT_FAILURE, "mkstemp");
+ }
+ unlink(sfn);
+
+ if (cdbw_output(cdbw, fd, "npf-table-cdb", NULL) == -1) {
+ err(EXIT_FAILURE, "cdbw_output");
+ }
+ cdbw_close(cdbw);
+
+ if (fstat(fd, &sb) == -1) {
+ err(EXIT_FAILURE, "fstat");
+ }
+ if ((cdb = mmap(NULL, sb.st_size, PROT_READ,
+ MAP_FILE | MAP_PRIVATE, fd, 0)) == MAP_FAILED) {
+ err(EXIT_FAILURE, "mmap");
+ }
+ npf_table_setdata(tl, cdb, sb.st_size);
+
+ close(fd);
+ }
}
/*
@@ -689,6 +734,8 @@ npfctl_build_table(const char *tname, u_
if (fname) {
npfctl_fill_table(tl, type, fname);
+ } else if (type == NPF_TABLE_CDB) {
+ errx(EXIT_FAILURE, "tables of cdb type must be static");
}
}
Index: src/usr.sbin/npf/npfctl/npf_parse.y
diff -u src/usr.sbin/npf/npfctl/npf_parse.y:1.29 src/usr.sbin/npf/npfctl/npf_parse.y:1.30
--- src/usr.sbin/npf/npfctl/npf_parse.y:1.29 Tue Nov 19 00:28:41 2013
+++ src/usr.sbin/npf/npfctl/npf_parse.y Thu Feb 6 02:51:28 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_parse.y,v 1.29 2013/11/19 00:28:41 rmind Exp $ */
+/* $NetBSD: npf_parse.y,v 1.30 2014/02/06 02:51:28 rmind Exp $ */
/*-
* Copyright (c) 2011-2013 The NetBSD Foundation, Inc.
@@ -91,6 +91,7 @@ yyerror(const char *fmt, ...)
%token ARROWLEFT
%token ARROWRIGHT
%token BLOCK
+%token CDB
%token CURLY_CLOSE
%token CURLY_OPEN
%token CODE
@@ -278,6 +279,7 @@ table
table_type
: HASH { $$ = NPF_TABLE_HASH; }
| TREE { $$ = NPF_TABLE_TREE; }
+ | CDB { $$ = NPF_TABLE_CDB; }
;
table_store
Index: src/usr.sbin/npf/npfctl/npf_scan.l
diff -u src/usr.sbin/npf/npfctl/npf_scan.l:1.16 src/usr.sbin/npf/npfctl/npf_scan.l:1.17
--- src/usr.sbin/npf/npfctl/npf_scan.l:1.16 Tue Nov 19 00:28:41 2013
+++ src/usr.sbin/npf/npfctl/npf_scan.l Thu Feb 6 02:51:28 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_scan.l,v 1.16 2013/11/19 00:28:41 rmind Exp $ */
+/* $NetBSD: npf_scan.l,v 1.17 2014/02/06 02:51:28 rmind Exp $ */
/*-
* Copyright (c) 2011-2012 The NetBSD Foundation, Inc.
@@ -91,6 +91,7 @@ table return TABLE;
type return TYPE;
hash return HASH;
tree return TREE;
+cdb return CDB;
static return TSTATIC;
dynamic return TDYNAMIC;
file return TFILE;
Index: src/usr.sbin/npf/npftest/npftest.c
diff -u src/usr.sbin/npf/npftest/npftest.c:1.15 src/usr.sbin/npf/npftest/npftest.c:1.16
--- src/usr.sbin/npf/npftest/npftest.c:1.15 Wed Feb 5 03:49:48 2014
+++ src/usr.sbin/npf/npftest/npftest.c Thu Feb 6 02:51:28 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: npftest.c,v 1.15 2014/02/05 03:49:48 rmind Exp $ */
+/* $NetBSD: npftest.c,v 1.16 2014/02/06 02:51:28 rmind Exp $ */
/*
* NPF testing framework.
@@ -15,6 +15,7 @@
#include <fcntl.h>
#include <err.h>
+#include <sys/mman.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <arpa/inet.h>
@@ -22,6 +23,8 @@
#include <rump/rump.h>
#include <rump/rump_syscalls.h>
+#include <cdbw.h>
+
#include "npftest.h"
static bool verbose, quiet;
@@ -121,6 +124,51 @@ load_npf_config(const char *config)
}
}
+static void *
+generate_test_cdb(size_t *size)
+{
+ in_addr_t addr;
+ struct cdbw *cdbw;
+ struct stat sb;
+ char sfn[32];
+ int alen, fd;
+ void *cdb;
+
+ if ((cdbw = cdbw_open()) == NULL) {
+ err(EXIT_FAILURE, "cdbw_open");
+ }
+ strlcpy(sfn, "/tmp/npftest_cdb.XXXXXX", sizeof(sfn));
+ if ((fd = mkstemp(sfn)) == -1) {
+ err(EXIT_FAILURE, "mkstemp");
+ }
+ unlink(sfn);
+
+ addr = inet_addr("192.168.1.1"), alen = sizeof(struct in_addr);
+ if (cdbw_put(cdbw, &addr, alen, &addr, alen) == -1)
+ err(EXIT_FAILURE, "cdbw_put");
+
+ addr = inet_addr("10.0.0.2"), alen = sizeof(struct in_addr);
+ if (cdbw_put(cdbw, &addr, alen, &addr, alen) == -1)
+ err(EXIT_FAILURE, "cdbw_put");
+
+ if (cdbw_output(cdbw, fd, "npf-table-cdb", NULL) == -1) {
+ err(EXIT_FAILURE, "cdbw_output");
+ }
+ cdbw_close(cdbw);
+
+ if (fstat(fd, &sb) == -1) {
+ err(EXIT_FAILURE, "fstat");
+ }
+ if ((cdb = mmap(NULL, sb.st_size, PROT_READ,
+ MAP_FILE | MAP_PRIVATE, fd, 0)) == MAP_FAILED) {
+ err(EXIT_FAILURE, "mmap");
+ }
+ close(fd);
+
+ *size = sb.st_size;
+ return cdb;
+}
+
int
main(int argc, char **argv)
{
@@ -233,9 +281,14 @@ main(int argc, char **argv)
}
if (!testname || strcmp("table", testname) == 0) {
- ok = rumpns_npf_table_test(verbose);
+ void *cdb;
+ size_t len;
+
+ cdb = generate_test_cdb(&len);
+ ok = rumpns_npf_table_test(verbose, cdb, len);
fail |= result("table", ok);
tname_matched = true;
+ munmap(cdb, len);
}
if (!testname || strcmp("state", testname) == 0) {
Index: src/usr.sbin/npf/npftest/npftest.h
diff -u src/usr.sbin/npf/npftest/npftest.h:1.11 src/usr.sbin/npf/npftest/npftest.h:1.12
--- src/usr.sbin/npf/npftest/npftest.h:1.11 Wed Feb 5 03:49:48 2014
+++ src/usr.sbin/npf/npftest/npftest.h Thu Feb 6 02:51:28 2014
@@ -23,7 +23,7 @@ void rumpns_npf_test_conc(bool, unsigne
bool rumpns_npf_nbuf_test(bool);
bool rumpns_npf_bpf_test(bool);
-bool rumpns_npf_table_test(bool);
+bool rumpns_npf_table_test(bool, void *, size_t);
bool rumpns_npf_state_test(bool);
bool rumpns_npf_rule_test(bool);
Index: src/usr.sbin/npf/npftest/libnpftest/npf_table_test.c
diff -u src/usr.sbin/npf/npftest/libnpftest/npf_table_test.c:1.7 src/usr.sbin/npf/npftest/libnpftest/npf_table_test.c:1.8
--- src/usr.sbin/npf/npftest/libnpftest/npf_table_test.c:1.7 Tue Nov 12 00:46:34 2013
+++ src/usr.sbin/npf/npftest/libnpftest/npf_table_test.c Thu Feb 6 02:51:28 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_table_test.c,v 1.7 2013/11/12 00:46:34 rmind Exp $ */
+/* $NetBSD: npf_table_test.c,v 1.8 2014/02/06 02:51:28 rmind Exp $ */
/*
* NPF tableset test.
@@ -7,6 +7,7 @@
*/
#include <sys/types.h>
+#include <sys/malloc.h>
#include "npf_impl.h"
#include "npf_test.h"
@@ -43,6 +44,7 @@ static const uint16_t ip6_list[][8] = {
#define HASH_TID "hash-table"
#define TREE_TID "tree-table"
+#define CDB_TID "cdb-table"
static bool
npf_table_test_fill4(npf_tableset_t *tblset, npf_addr_t *addr)
@@ -74,21 +76,22 @@ npf_table_test_fill4(npf_tableset_t *tbl
}
bool
-npf_table_test(bool verbose)
+npf_table_test(bool verbose, void *blob, size_t size)
{
npf_addr_t addr_storage, *addr = &addr_storage;
const int nm = NPF_NO_NETMASK;
+ npf_table_t *t, *t1, *t2, *t3;
npf_tableset_t *tblset;
- npf_table_t *t, *t1, *t2;
int error, alen;
bool fail = false;
+ void *cdb;
u_int i;
- tblset = npf_tableset_create(2);
+ tblset = npf_tableset_create(3);
fail |= !(tblset != NULL);
/* Table ID 1, using hash table with 256 lists. */
- t1 = npf_table_create(HASH_TID, 0, NPF_TABLE_HASH, 256);
+ t1 = npf_table_create(HASH_TID, 0, NPF_TABLE_HASH, NULL, 256);
fail |= !(t1 != NULL);
error = npf_tableset_insert(tblset, t1);
fail |= !(error == 0);
@@ -98,11 +101,20 @@ npf_table_test(bool verbose)
fail |= !(error != 0);
/* Table ID 2, using a prefix tree. */
- t2 = npf_table_create(TREE_TID, 1, NPF_TABLE_TREE, 0);
+ t2 = npf_table_create(TREE_TID, 1, NPF_TABLE_TREE, NULL, 0);
fail |= !(t2 != NULL);
error = npf_tableset_insert(tblset, t2);
fail |= !(error == 0);
+ /* Table ID 3, using a CDB. */
+ cdb = malloc(size, M_TEMP, M_WAITOK);
+ memcpy(cdb, blob, size);
+
+ t3 = npf_table_create(CDB_TID, 2, NPF_TABLE_CDB, cdb, size);
+ fail |= !(t3 != NULL);
+ error = npf_tableset_insert(tblset, t3);
+ fail |= !(error == 0);
+
/* Attempt to match non-existing entries - should fail. */
addr->s6_addr32[0] = inet_addr(ip_list[0]);
alen = sizeof(struct in_addr);
@@ -221,6 +233,19 @@ npf_table_test(bool verbose)
fail |= !(error == 0);
}
+ /* Test CDB. */
+ addr->s6_addr32[0] = inet_addr(ip_list[0]);
+ alen = sizeof(struct in_addr);
+ error = npf_table_lookup(t3, alen, addr);
+ fail |= !(error == 0);
+
+ for (i = 1; i < __arraycount(ip_list) - 1; i++) {
+ addr->s6_addr32[0] = inet_addr(ip_list[i]);
+ alen = sizeof(struct in_addr);
+ error = npf_table_lookup(t3, alen, addr);
+ fail |= !(error != 0);
+ }
+
npf_tableset_destroy(tblset);
return !fail;
Index: src/usr.sbin/npf/npftest/libnpftest/npf_test.h
diff -u src/usr.sbin/npf/npftest/libnpftest/npf_test.h:1.12 src/usr.sbin/npf/npftest/libnpftest/npf_test.h:1.13
--- src/usr.sbin/npf/npftest/libnpftest/npf_test.h:1.12 Wed Feb 5 03:49:48 2014
+++ src/usr.sbin/npf/npftest/libnpftest/npf_test.h Thu Feb 6 02:51:28 2014
@@ -57,7 +57,7 @@ void mbuf_icmp_append(struct mbuf *, st
bool npf_nbuf_test(bool);
bool npf_bpf_test(bool);
-bool npf_table_test(bool);
+bool npf_table_test(bool, void *, size_t);
bool npf_state_test(bool);
bool npf_rule_test(bool);