- Save active config in proplib dictionary; add GETCONF ioctl to retrieve. trunk
authorrmind <rmind@NetBSD.org>
Sun, 11 Mar 2012 18:27:59 +0000
branchtrunk
changeset 209810 c5e83429958d
parent 209809 cbce99dfb934
child 209811 2a4ec488633f
- Save active config in proplib dictionary; add GETCONF ioctl to retrieve. - Few fixes. Improve some comments.
sys/net/npf/npf.c
sys/net/npf/npf.h
sys/net/npf/npf_ctl.c
sys/net/npf/npf_handler.c
sys/net/npf/npf_impl.h
sys/net/npf/npf_nat.c
sys/net/npf/npf_session.c
--- a/sys/net/npf/npf.c	Sun Mar 11 17:28:47 2012 +0000
+++ b/sys/net/npf/npf.c	Sun Mar 11 18:27:59 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf.c,v 1.8 2012/02/20 00:18:19 rmind Exp $	*/
+/*	$NetBSD: npf.c,v 1.9 2012/03/11 18:27:59 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2009-2010 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.8 2012/02/20 00:18:19 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.9 2012/03/11 18:27:59 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -70,6 +70,7 @@
 	npf_ruleset_t *		n_rules;
 	npf_tableset_t *	n_tables;
 	npf_ruleset_t *		n_nat_rules;
+	prop_dictionary_t	n_dict;
 	bool			n_default_pass;
 } npf_core_t;
 
@@ -93,6 +94,7 @@
 #endif
 	npf_ruleset_t *rset, *nset;
 	npf_tableset_t *tset;
+	prop_dictionary_t dict;
 	int error = 0;
 
 	rw_init(&npf_lock);
@@ -104,10 +106,11 @@
 	npflogattach(1);
 
 	/* Load empty configuration. */
+	dict = prop_dictionary_create();
 	rset = npf_ruleset_create();
 	tset = npf_tableset_create();
 	nset = npf_ruleset_create();
-	npf_reload(rset, tset, nset, true);
+	npf_reload(dict, rset, tset, nset, true);
 	KASSERT(npf_core != NULL);
 
 #ifdef _MODULE
@@ -125,20 +128,20 @@
 npf_fini(void)
 {
 
-	/*
-	 * At first, detach device, remove pfil hooks and unload existing
-	 * configuration, destroy structures.
-	 */
+	/* At first, detach device and remove pfil hooks. */
 #ifdef _MODULE
 	devsw_detach(NULL, &npf_cdevsw);
 #endif
-	npf_unregister_pfil();
-	npf_core_destroy(npf_core);
 	npflogdetach();
+	npf_pfil_unregister();
 
-	/* Note: order is particular. */
+	/* Flush all sessions, destroy configuration (ruleset, etc). */
+	npf_session_tracking(false);
+	npf_core_destroy(npf_core);
+
+	/* Finally, safe to destroy the subsystems. */
+	npf_alg_sysfini();
 	npf_nat_sysfini();
-	npf_alg_sysfini();
 	npf_session_sysfini();
 	npf_tableset_sysfini();
 	percpu_free(npf_stats_percpu, NPF_STATS_SIZE);
@@ -211,6 +214,9 @@
 	case IOC_NPF_RELOAD:
 		error = npfctl_reload(cmd, data);
 		break;
+	case IOC_NPF_GETCONF:
+		error = npfctl_getconf(cmd, data);
+		break;
 	case IOC_NPF_TABLE:
 		error = npfctl_table(data);
 		break;
@@ -255,6 +261,7 @@
 npf_core_destroy(npf_core_t *nc)
 {
 
+	prop_object_release(nc->n_dict);
 	npf_ruleset_destroy(nc->n_rules);
 	npf_ruleset_destroy(nc->n_nat_rules);
 	npf_tableset_destroy(nc->n_tables);
@@ -266,17 +273,18 @@
  * Then destroy old (unloaded) structures.
  */
 void
-npf_reload(npf_ruleset_t *rset, npf_tableset_t *tset, npf_ruleset_t *nset,
-    bool flush)
+npf_reload(prop_dictionary_t dict, npf_ruleset_t *rset,
+    npf_tableset_t *tset, npf_ruleset_t *nset, bool flush)
 {
 	npf_core_t *nc, *onc;
 
 	/* Setup a new core structure. */
 	nc = kmem_zalloc(sizeof(npf_core_t), KM_SLEEP);
-	nc->n_default_pass = flush;
 	nc->n_rules = rset;
 	nc->n_tables = tset;
 	nc->n_nat_rules = nset;
+	nc->n_dict = dict;
+	nc->n_default_pass = flush;
 
 	/* Lock and load the core structure. */
 	rw_enter(&npf_lock, RW_WRITER);
@@ -333,6 +341,13 @@
 	return rw_lock_held(&npf_lock);
 }
 
+prop_dictionary_t
+npf_core_dict(void)
+{
+	KASSERT(rw_lock_held(&npf_lock));
+	return npf_core->n_dict;
+}
+
 bool
 npf_default_pass(void)
 {
--- a/sys/net/npf/npf.h	Sun Mar 11 17:28:47 2012 +0000
+++ b/sys/net/npf/npf.h	Sun Mar 11 18:27:59 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf.h,v 1.14 2012/02/06 23:30:14 rmind Exp $	*/
+/*	$NetBSD: npf.h,v 1.15 2012/03/11 18:27:59 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2009-2011 The NetBSD Foundation, Inc.
@@ -306,5 +306,6 @@
 #define	IOC_NPF_SESSIONS_SAVE	_IOR('N', 105, struct plistref)
 #define	IOC_NPF_SESSIONS_LOAD	_IOW('N', 106, struct plistref)
 #define	IOC_NPF_UPDATE_RULE	_IOWR('N', 107, struct plistref)
+#define	IOC_NPF_GETCONF		_IOR('N', 108, struct plistref)
 
 #endif	/* _NPF_NET_H_ */
--- a/sys/net/npf/npf_ctl.c	Sun Mar 11 17:28:47 2012 +0000
+++ b/sys/net/npf/npf_ctl.c	Sun Mar 11 18:27:59 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_ctl.c,v 1.13 2012/02/20 00:18:19 rmind Exp $	*/
+/*	$NetBSD: npf_ctl.c,v 1.14 2012/03/11 18:27:59 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_ctl.c,v 1.13 2012/02/20 00:18:19 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_ctl.c,v 1.14 2012/03/11 18:27:59 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/conf.h>
@@ -66,10 +66,10 @@
 
 	if (onoff) {
 		/* Enable: add pfil hooks. */
-		error = npf_register_pfil();
+		error = npf_pfil_register();
 	} else {
 		/* Disable: remove pfil hooks. */
-		npf_unregister_pfil();
+		npf_pfil_unregister();
 		error = 0;
 	}
 	return error;
@@ -425,7 +425,7 @@
 npfctl_reload(u_long cmd, void *data)
 {
 	struct plistref *pref = data;
-	prop_dictionary_t dict, errdict;
+	prop_dictionary_t npf_dict, errdict;
 	prop_array_t natlist, tables, rprocs, rules;
 	npf_tableset_t *tblset = NULL;
 	npf_ruleset_t *rlset = NULL;
@@ -435,12 +435,12 @@
 
 	/* Retrieve the dictionary. */
 #ifdef _KERNEL
-	error = prop_dictionary_copyin_ioctl(pref, cmd, &dict);
+	error = prop_dictionary_copyin_ioctl(pref, cmd, &npf_dict);
 	if (error)
 		return error;
 #else
-	dict = prop_dictionary_internalize_from_file(data);
-	if (dict == NULL)
+	npf_dict = prop_dictionary_internalize_from_file(data);
+	if (npf_dict == NULL)
 		return EINVAL;
 #endif
 	/* Dictionary for error reporting. */
@@ -448,7 +448,7 @@
 
 	/* NAT policies. */
 	nset = npf_ruleset_create();
-	natlist = prop_dictionary_get(dict, "translation");
+	natlist = prop_dictionary_get(npf_dict, "translation");
 	error = npf_mk_natlist(nset, natlist, errdict);
 	if (error) {
 		goto fail;
@@ -456,7 +456,7 @@
 
 	/* Tables. */
 	tblset = npf_tableset_create();
-	tables = prop_dictionary_get(dict, "tables");
+	tables = prop_dictionary_get(npf_dict, "tables");
 	error = npf_mk_tables(tblset, tables, errdict);
 	if (error) {
 		goto fail;
@@ -464,21 +464,21 @@
 
 	/* Rules and rule procedures. */
 	rlset = npf_ruleset_create();
-	rprocs = prop_dictionary_get(dict, "rprocs");
-	rules = prop_dictionary_get(dict, "rules");
+	rprocs = prop_dictionary_get(npf_dict, "rprocs");
+	rules = prop_dictionary_get(npf_dict, "rules");
 	error = npf_mk_rules(rlset, rules, rprocs, errdict);
 	if (error) {
 		goto fail;
 	}
 
 	flush = false;
-	prop_dictionary_get_bool(dict, "flush", &flush);
+	prop_dictionary_get_bool(npf_dict, "flush", &flush);
 
 	/*
 	 * Finally - reload ruleset, tableset and NAT policies.
 	 * Operation will be performed as a single transaction.
 	 */
-	npf_reload(rlset, tblset, nset, flush);
+	npf_reload(npf_dict, rlset, tblset, nset, flush);
 
 	/* Turn on/off session tracking accordingly. */
 	npf_session_tracking(!flush);
@@ -501,7 +501,9 @@
 	if (tblset) {
 		npf_tableset_destroy(tblset);
 	}
-	prop_object_release(dict);
+	if (error) {
+		prop_object_release(npf_dict);
+	}
 
 	/* Error report. */
 	prop_dictionary_set_int32(errdict, "errno", error);
@@ -512,6 +514,22 @@
 	return 0;
 }
 
+int
+npfctl_getconf(u_long cmd, void *data)
+{
+	struct plistref *pref = data;
+	prop_dictionary_t npf_dict;
+	int error;
+
+	npf_core_enter();
+	npf_dict = npf_core_dict();
+	prop_dictionary_set_bool(npf_dict, "active", npf_pfil_registered_p());
+	error = prop_dictionary_copyout_ioctl(pref, cmd, npf_dict);
+	npf_core_exit();
+
+	return error;
+}
+
 /*
  * npfctl_update_rule: reload a specific rule identified by the name.
  */
--- a/sys/net/npf/npf_handler.c	Sun Mar 11 17:28:47 2012 +0000
+++ b/sys/net/npf/npf_handler.c	Sun Mar 11 18:27:59 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_handler.c,v 1.14 2012/02/20 00:18:19 rmind Exp $	*/
+/*	$NetBSD: npf_handler.c,v 1.15 2012/03/11 18:27:59 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_handler.c,v 1.14 2012/02/20 00:18:19 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_handler.c,v 1.15 2012/03/11 18:27:59 rmind Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -251,10 +251,10 @@
 }
 
 /*
- * npf_register_pfil: register pfil(9) hooks.
+ * npf_pfil_register: register pfil(9) hooks.
  */
 int
-npf_register_pfil(void)
+npf_pfil_register(void)
 {
 	int error;
 
@@ -298,10 +298,10 @@
 }
 
 /*
- * npf_unregister: unregister pfil(9) hooks.
+ * npf_pfil_unregister: unregister pfil(9) hooks.
  */
 void
-npf_unregister_pfil(void)
+npf_pfil_unregister(void)
 {
 
 	mutex_enter(softnet_lock);
@@ -321,3 +321,9 @@
 	KERNEL_UNLOCK_ONE(NULL);
 	mutex_exit(softnet_lock);
 }
+
+bool
+npf_pfil_registered_p(void)
+{
+	return npf_ph_if != NULL;
+}
--- a/sys/net/npf/npf_impl.h	Sun Mar 11 17:28:47 2012 +0000
+++ b/sys/net/npf/npf_impl.h	Sun Mar 11 18:27:59 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_impl.h,v 1.11 2012/02/20 00:18:19 rmind Exp $	*/
+/*	$NetBSD: npf_impl.h,v 1.12 2012/03/11 18:27:59 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
@@ -131,13 +131,16 @@
 void		npf_core_exit(void);
 bool		npf_core_locked(void);
 bool		npf_default_pass(void);
-void		npf_reload(npf_ruleset_t *, npf_tableset_t *,
-		    npf_ruleset_t *, bool);
+prop_dictionary_t npf_core_dict(void);
+
+void		npf_reload(prop_dictionary_t, npf_ruleset_t *,
+		    npf_tableset_t *, npf_ruleset_t *, bool);
 
 void		npflogattach(int);
 void		npflogdetach(void);
 int		npfctl_switch(void *);
 int		npfctl_reload(u_long, void *);
+int		npfctl_getconf(u_long, void *);
 int		npfctl_sessions_save(u_long, void *);
 int		npfctl_sessions_load(u_long, void *);
 int		npfctl_update_rule(u_long, void *);
@@ -147,8 +150,9 @@
 void		npf_stats_dec(npf_stats_t);
 
 /* Packet filter hooks. */
-int		npf_register_pfil(void);
-void		npf_unregister_pfil(void);
+int		npf_pfil_register(void);
+void		npf_pfil_unregister(void);
+bool		npf_pfil_registered_p(void);
 void		npf_log_packet(npf_cache_t *, nbuf_t *, int);
 
 /* Protocol helpers. */
--- a/sys/net/npf/npf_nat.c	Sun Mar 11 17:28:47 2012 +0000
+++ b/sys/net/npf/npf_nat.c	Sun Mar 11 18:27:59 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_nat.c,v 1.11 2012/02/20 00:18:20 rmind Exp $	*/
+/*	$NetBSD: npf_nat.c,v 1.12 2012/03/11 18:27:59 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2010-2011 The NetBSD Foundation, Inc.
@@ -76,7 +76,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_nat.c,v 1.11 2012/02/20 00:18:20 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_nat.c,v 1.12 2012/03/11 18:27:59 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -112,7 +112,9 @@
 #define	PORTMAP_MEM_SIZE	\
     (sizeof(npf_portmap_t) + (PORTMAP_SIZE * sizeof(uint32_t)))
 
-/* NAT policy structure. */
+/*
+ * NAT policy structure.
+ */
 struct npf_natpolicy {
 	LIST_HEAD(, npf_nat)	n_nat_list;
 	kmutex_t		n_lock;
@@ -128,7 +130,9 @@
 #define	NPF_NP_CMP_START	offsetof(npf_natpolicy_t, n_type)
 #define	NPF_NP_CMP_SIZE		(sizeof(npf_natpolicy_t) - NPF_NP_CMP_START)
 
-/* NAT translation entry for a session. */ 
+/*
+ * NAT translation entry for a session.
+ */
 struct npf_nat {
 	/* Association (list entry and a link pointer) with NAT policy. */
 	LIST_ENTRY(npf_nat)	nt_entry;
@@ -302,7 +306,7 @@
 	/* If NAT policy has an old port map - drop the reference. */
 	mpm = mnp->n_portmap;
 	if (mpm) {
-		/* Note: in such case, we must not be a last reference. */
+		/* Note: at this point we cannot hold a last reference. */
 		KASSERT(mpm->p_refcnt > 1);
 		mpm->p_refcnt--;
 	}
@@ -440,10 +444,6 @@
 	nt->nt_session = NULL;
 	nt->nt_alg = NULL;
 
-	mutex_enter(&np->n_lock);
-	LIST_INSERT_HEAD(&np->n_nat_list, nt, nt_entry);
-	mutex_exit(&np->n_lock);
-
 	/* Save the original address which may be rewritten. */
 	if (np->n_type == NPF_NATOUT) {
 		/* Source (local) for Outbound NAT. */
@@ -461,8 +461,9 @@
 	    (proto != IPPROTO_TCP && proto != IPPROTO_UDP)) {
 		nt->nt_oport = 0;
 		nt->nt_tport = 0;
-		return nt;
+		goto out;
 	}
+
 	/* Save the relevant TCP/UDP port. */
 	if (proto == IPPROTO_TCP) {
 		struct tcphdr *th = &npc->npc_l4.tcp;
@@ -480,6 +481,10 @@
 	} else {
 		nt->nt_tport = np->n_tport;
 	}
+out:
+	mutex_enter(&np->n_lock);
+	LIST_INSERT_HEAD(&np->n_nat_list, nt, nt_entry);
+	mutex_exit(&np->n_lock);
 	return nt;
 }
 
@@ -526,6 +531,7 @@
 	if (!npf_rwrcksum(npc, nbuf, n_ptr, di, addr, port)) {
 		return EINVAL;
 	}
+
 	/*
 	 * Address translation: rewrite source/destination address, depending
 	 * on direction (PFIL_OUT - for source, PFIL_IN - for destination).
@@ -537,6 +543,7 @@
 		/* Done. */
 		return 0;
 	}
+
 	switch (npf_cache_ipproto(npc)) {
 	case IPPROTO_TCP:
 	case IPPROTO_UDP:
--- a/sys/net/npf/npf_session.c	Sun Mar 11 17:28:47 2012 +0000
+++ b/sys/net/npf/npf_session.c	Sun Mar 11 18:27:59 2012 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_session.c,v 1.11 2012/02/20 00:18:20 rmind Exp $	*/
+/*	$NetBSD: npf_session.c,v 1.12 2012/03/11 18:27:59 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2010-2012 The NetBSD Foundation, Inc.
@@ -49,7 +49,7 @@
  *	indicate that the packet of the backwards stream should be passed
  *	without inspection of the ruleset.  Another purpose is to associate
  *	NAT with a connection (which implies connection tracking).  Such
- *	sessions are created according to the NAT policies and they have a 1:1
+ *	sessions are created according to the NAT policies and they have a
  *	relationship with NAT translation structure via npf_session_t::s_nat.
  *	A single session can serve both purposes, which is a common case.
  *
@@ -61,9 +61,9 @@
  *	depending on session properties (e.g. last activity time, protocol)
  *	removes session entries and expires the actual sessions.
  *
- *	Each session has a reference count, which is taken on lookup and
- *	needs to be released by the caller.  Reference guarantees that
- *	session will not be destroyed, although it might be expired.
+ *	Each session has a reference count.  Reference is acquired on lookup
+ *	and should be released by the caller.  Reference guarantees that the
+ *	session will not be destroyed, although it may be expired.
  *
  * External session identifiers
  *
@@ -74,7 +74,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_session.c,v 1.11 2012/02/20 00:18:20 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_session.c,v 1.12 2012/03/11 18:27:59 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -196,7 +196,7 @@
 {
 
 	/* Disable tracking, flush all sessions. */
-	sess_tracking_stop();
+	npf_session_tracking(false);
 	KASSERT(sess_tracking == 0);
 	KASSERT(sess_gc_lwp == NULL);