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);

Reply via email to