Pull up following revision(s) (requested by rmind in ticket #479): netbsd-7
authorsnj <snj@NetBSD.org>
Wed, 04 Feb 2015 07:13:04 +0000
branchnetbsd-7
changeset 253921 611cb89064c5
parent 253920 d02841c3e3b1
child 253922 aaf788e0efde
Pull up following revision(s) (requested by rmind in ticket #479): lib/libnpf/npf.c: revision 1.35 lib/libnpf/npf.h: revision 1.28 sys/net/npf/npf_conn.c: revision 1.15 sys/net/npf/npf_impl.h: revision 1.61 sys/net/npf/npf_ruleset.c: revision 1.41 usr.sbin/npf/npfctl/npf.conf.5: revision 1.44 usr.sbin/npf/npfctl/npf_parse.y: revision 1.37 usr.sbin/npf/npfctl/npf_show.c: revisions 1.16, 1.17 usr.sbin/npf/npfctl/npfctl.c: revision 1.46 load the config file before bpfjit so that we can disable the warning. -- Don't depend on yacc to include stdlib.h or string.h. -- - npf_conn_establish: remove a rare race condition when we might destroy a connection when it is still referenced by another thread. - npf_conn_destroy: remove the backwards entry using the saved key, PR/49488. - Sprinkle some asserts. -- npf.conf(5): mention alg, include in the example, minor fix. -- npfctl(8): report dynamic rule ID in a comment, print the case when libpcap is used correctly. Also, add npf_ruleset_dump() helper in the kernel. -- libnpf: add npf_rule_getid() and npf_rule_getcode(). Missed in the previous commit. -- npfctl_print_rule: print the ID in hex, not decimal.
lib/libnpf/npf.c
lib/libnpf/npf.h
sys/net/npf/npf_conn.c
sys/net/npf/npf_impl.h
sys/net/npf/npf_ruleset.c
usr.sbin/npf/npfctl/npf.conf.5
usr.sbin/npf/npfctl/npf_parse.y
usr.sbin/npf/npfctl/npf_show.c
usr.sbin/npf/npfctl/npfctl.c
--- a/lib/libnpf/npf.c	Wed Feb 04 06:58:54 2015 +0000
+++ b/lib/libnpf/npf.c	Wed Feb 04 07:13:04 2015 +0000
@@ -1,7 +1,7 @@
-/*	$NetBSD: npf.c,v 1.32.2.1 2014/08/29 11:14:14 martin Exp $	*/
+/*	$NetBSD: npf.c,v 1.32.2.2 2015/02/04 07:13:04 snj Exp $	*/
 
 /*-
- * Copyright (c) 2010-2014 The NetBSD Foundation, Inc.
+ * Copyright (c) 2010-2015 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.32.2.1 2014/08/29 11:14:14 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.32.2.2 2015/02/04 07:13:04 snj Exp $");
 
 #include <sys/types.h>
 #include <netinet/in_systm.h>
@@ -715,6 +715,27 @@
 	return rpname;
 }
 
+uint64_t
+npf_rule_getid(nl_rule_t *rl)
+{
+	prop_dictionary_t rldict = rl->nrl_dict;
+	uint64_t id = 0;
+
+	(void)prop_dictionary_get_uint64(rldict, "id", &id);
+	return id;
+}
+
+const void *
+npf_rule_getcode(nl_rule_t *rl, int *type, size_t *len)
+{
+	prop_dictionary_t rldict = rl->nrl_dict;
+	prop_object_t obj = prop_dictionary_get(rldict, "code");
+
+	prop_dictionary_get_uint32(rldict, "code-type", (uint32_t *)type);
+	*len = prop_data_size(obj);
+	return prop_data_data_nocopy(obj);
+}
+
 int
 _npf_ruleset_list(int fd, const char *rname, nl_config_t *ncf)
 {
--- a/lib/libnpf/npf.h	Wed Feb 04 06:58:54 2015 +0000
+++ b/lib/libnpf/npf.h	Wed Feb 04 07:13:04 2015 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf.h,v 1.27 2014/07/23 01:25:34 rmind Exp $	*/
+/*	$NetBSD: npf.h,v 1.27.2.1 2015/02/04 07:13:04 snj Exp $	*/
 
 /*-
  * Copyright (c) 2011-2014 The NetBSD Foundation, Inc.
@@ -129,6 +129,8 @@
 const char *	npf_rule_getinterface(nl_rule_t *);
 const void *	npf_rule_getinfo(nl_rule_t *, size_t *);
 const char *	npf_rule_getproc(nl_rule_t *);
+uint64_t	npf_rule_getid(nl_rule_t *);
+const void *	npf_rule_getcode(nl_rule_t *, int *, size_t *);
 
 nl_table_t *	npf_table_iterate(nl_config_t *);
 const char *	npf_table_getname(nl_table_t *);
--- a/sys/net/npf/npf_conn.c	Wed Feb 04 06:58:54 2015 +0000
+++ b/sys/net/npf/npf_conn.c	Wed Feb 04 07:13:04 2015 +0000
@@ -1,7 +1,7 @@
-/*	$NetBSD: npf_conn.c,v 1.10.2.3 2014/12/22 02:10:30 msaitoh Exp $	*/
+/*	$NetBSD: npf_conn.c,v 1.10.2.4 2015/02/04 07:13:04 snj Exp $	*/
 
 /*-
- * Copyright (c) 2014 Mindaugas Rasiukevicius <rmind at netbsd org>
+ * Copyright (c) 2014-2015 Mindaugas Rasiukevicius <rmind at netbsd org>
  * Copyright (c) 2010-2014 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
@@ -99,7 +99,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_conn.c,v 1.10.2.3 2014/12/22 02:10:30 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_conn.c,v 1.10.2.4 2015/02/04 07:13:04 snj Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -369,7 +369,6 @@
 	/* Check if connection is active and not expired. */
 	flags = con->c_flags;
 	ok = (flags & (CONN_ACTIVE | CONN_EXPIRE)) == CONN_ACTIVE;
-
 	if (__predict_false(!ok)) {
 		atomic_dec_uint(&con->c_refcnt);
 		return NULL;
@@ -453,6 +452,7 @@
 {
 	const nbuf_t *nbuf = npc->npc_nbuf;
 	npf_conn_t *con;
+	int error = 0;
 
 	KASSERT(!nbuf_flag_p(nbuf, NBUF_DATAREF_RESET));
 
@@ -468,16 +468,16 @@
 	NPF_PRINTF(("NPF: create conn %p\n", con));
 	npf_stats_inc(NPF_STAT_CONN_CREATE);
 
-	/* Reference count and flags (indicate direction). */
 	mutex_init(&con->c_lock, MUTEX_DEFAULT, IPL_SOFTNET);
 	con->c_flags = (di & PFIL_ALL);
-	con->c_refcnt = 1;
+	con->c_refcnt = 0;
 	con->c_rproc = NULL;
 	con->c_nat = NULL;
 
-	/* Initialize protocol state. */
+	/* Initialize the protocol state. */
 	if (!npf_state_init(npc, &con->c_state)) {
-		goto err;
+		npf_conn_destroy(con);
+		return NULL;
 	}
 
 	KASSERT(npf_iscached(npc, NPC_IP46));
@@ -488,45 +488,65 @@
 	 * Construct "forwards" and "backwards" keys.  Also, set the
 	 * interface ID for this connection (unless it is global).
 	 */
-	if (!npf_conn_conkey(npc, fw, true)) {
-		goto err;
-	}
-	if (!npf_conn_conkey(npc, bk, false)) {
-		goto err;
+	if (!npf_conn_conkey(npc, fw, true) ||
+	    !npf_conn_conkey(npc, bk, false)) {
+		npf_conn_destroy(con);
+		return NULL;
 	}
 	fw->ck_backptr = bk->ck_backptr = con;
 	con->c_ifid = per_if ? nbuf->nb_ifid : 0;
 	con->c_proto = npc->npc_proto;
 
-	/* Set last activity time for a new connection. */
+	/*
+	 * Set last activity time for a new connection and acquire
+	 * a reference for the caller before we make it visible.
+	 */
 	getnanouptime(&con->c_atime);
+	con->c_refcnt = 1;
 
 	/*
 	 * Insert both keys (entries representing directions) of the
-	 * connection.  At this point, it becomes visible.
+	 * connection.  At this point it becomes visible, but we activate
+	 * the connection later.
 	 */
+	mutex_enter(&con->c_lock);
 	if (!npf_conndb_insert(conn_db, fw, con)) {
+		error = EISCONN;
 		goto err;
 	}
 	if (!npf_conndb_insert(conn_db, bk, con)) {
-		/* We have hit the duplicate. */
-		npf_conndb_remove(conn_db, fw);
+		npf_conn_t *ret __diagused;
+		ret = npf_conndb_remove(conn_db, fw);
+		KASSERT(ret == con);
+		error = EISCONN;
+		goto err;
+	}
+err:
+	/*
+	 * If we have hit the duplicate: mark the connection as expired
+	 * and let the G/C thread to take care of it.  We cannot do it
+	 * here since there might be references acquired already.
+	 */
+	if (error) {
+		const u_int dflags = CONN_REMOVED | CONN_EXPIRE;
+		atomic_or_uint(&con->c_flags, dflags);
 		npf_stats_inc(NPF_STAT_RACE_CONN);
-		goto err;
+	} else {
+		NPF_PRINTF(("NPF: establish conn %p\n", con));
 	}
 
 	/* Finally, insert into the connection list. */
-	NPF_PRINTF(("NPF: establish conn %p\n", con));
 	npf_conndb_enqueue(conn_db, con);
-	return con;
-err:
-	npf_conn_destroy(con);
-	return NULL;
+	mutex_exit(&con->c_lock);
+
+	return error ? NULL : con;
 }
 
 static void
 npf_conn_destroy(npf_conn_t *con)
 {
+	KASSERT(con->c_refcnt == 0);
+
 	if (con->c_nat) {
 		/* Release any NAT structures. */
 		npf_nat_destroy(con->c_nat);
@@ -582,6 +602,8 @@
 		mutex_exit(&con->c_lock);
 		return EINVAL;
 	}
+	KASSERT((con->c_flags & CONN_REMOVED) == 0);
+
 	if (__predict_false(con->c_nat != NULL)) {
 		/* Race with a duplicate packet. */
 		mutex_exit(&con->c_lock);
@@ -590,7 +612,7 @@
 	}
 
 	/* Remove the "backwards" entry. */
-	ret = npf_conndb_remove(conn_db, &key);
+	ret = npf_conndb_remove(conn_db, &con->c_back_entry);
 	KASSERT(ret == con);
 
 	/* Set the source/destination IDs to the translation values. */
@@ -606,7 +628,9 @@
 		 * Race: we have hit the duplicate, remove the "forwards"
 		 * entry and expire our connection; it is no longer valid.
 		 */
-		(void)npf_conndb_remove(conn_db, &con->c_forw_entry);
+		ret = npf_conndb_remove(conn_db, &con->c_forw_entry);
+		KASSERT(ret == con);
+
 		atomic_or_uint(&con->c_flags, CONN_REMOVED | CONN_EXPIRE);
 		mutex_exit(&con->c_lock);
 
--- a/sys/net/npf/npf_impl.h	Wed Feb 04 06:58:54 2015 +0000
+++ b/sys/net/npf/npf_impl.h	Wed Feb 04 07:13:04 2015 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_impl.h,v 1.58.2.2 2014/12/01 13:05:26 martin Exp $	*/
+/*	$NetBSD: npf_impl.h,v 1.58.2.3 2015/02/04 07:13:04 snj Exp $	*/
 
 /*-
  * Copyright (c) 2009-2014 The NetBSD Foundation, Inc.
@@ -344,6 +344,7 @@
 const char *	npf_addr_dump(const npf_addr_t *, int);
 void		npf_state_dump(const npf_state_t *);
 void		npf_nat_dump(const npf_nat_t *);
+void		npf_ruleset_dump(const char *);
 void		npf_state_setsampler(void (*)(npf_state_t *, bool));
 
 #endif	/* _NPF_IMPL_H_ */
--- a/sys/net/npf/npf_ruleset.c	Wed Feb 04 06:58:54 2015 +0000
+++ b/sys/net/npf/npf_ruleset.c	Wed Feb 04 07:13:04 2015 +0000
@@ -1,7 +1,7 @@
-/*	$NetBSD: npf_ruleset.c,v 1.37.2.2 2014/12/01 13:05:26 martin Exp $	*/
+/*	$NetBSD: npf_ruleset.c,v 1.37.2.3 2015/02/04 07:13:04 snj Exp $	*/
 
 /*-
- * Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
+ * Copyright (c) 2009-2015 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This material is based upon work partially supported by The
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_ruleset.c,v 1.37.2.2 2014/12/01 13:05:26 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_ruleset.c,v 1.37.2.3 2015/02/04 07:13:04 snj Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -936,3 +936,25 @@
 	*retfl = rl->r_attr;
 	return (rl->r_attr & NPF_RULE_PASS) ? 0 : ENETUNREACH;
 }
+
+
+#if defined(DDB) || defined(_NPF_TESTING)
+
+void
+npf_ruleset_dump(const char *name)
+{
+	npf_ruleset_t *rlset = npf_config_ruleset();
+	npf_rule_t *rg, *rl;
+
+	LIST_FOREACH(rg, &rlset->rs_dynamic, r_dentry) {
+		printf("ruleset '%s':\n", rg->r_name);
+		TAILQ_FOREACH(rl, &rg->r_subset, r_entry) {
+			printf("\tid %"PRIu64", key: ", rl->r_id);
+			for (u_int i = 0; i < NPF_RULE_MAXKEYLEN; i++)
+				printf("%x", rl->r_key[i]);
+			printf("\n");
+		}
+	}
+}
+
+#endif
--- a/usr.sbin/npf/npfctl/npf.conf.5	Wed Feb 04 06:58:54 2015 +0000
+++ b/usr.sbin/npf/npfctl/npf.conf.5	Wed Feb 04 07:13:04 2015 +0000
@@ -1,6 +1,6 @@
-.\"    $NetBSD: npf.conf.5,v 1.42.2.1 2014/12/29 17:31:47 martin Exp $
+.\"    $NetBSD: npf.conf.5,v 1.42.2.2 2015/02/04 07:13:04 snj Exp $
 .\"
-.\" Copyright (c) 2009-2014 The NetBSD Foundation, Inc.
+.\" Copyright (c) 2009-2015 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 December 26, 2014
+.Dd February 1, 2015
 .Dt NPF.CONF 5
 .Os
 .Sh NAME
@@ -232,7 +232,8 @@
 ; Syntax of a single line.  Lines can be separated by LF (\\n) or
 ; a semicolon.  Comments start with a hash (#) character.
 
-syntax		= var-def | table-def | map | group | rproc | comment
+syntax		= var-def | set-param | alg | table-def |
+		  map | group | rproc | comment
 
 ; Variable definition.  Names can be alpha-numeric, including "_" character.
 
@@ -240,8 +241,12 @@
 interface	= interface-name | var-name
 var-def		= var "=" ( var-value | "{" value *[ "," value ] "}" )
 
-; Parameter setting
-set-statement	= "set" parameter value
+; Parameter setting.
+set-param	= "set" param-value
+
+; Application level gateway.  The name should be in the double quotes.
+
+alg		= "alg" alg-name
 
 ; Table definition.  Table ID shall be numeric.  Path is in the double quotes.
 
@@ -306,8 +311,8 @@
 .\" -----
 .Sh EXAMPLES
 .Bd -literal
-$ext_if = { inet4(wm0), inet6(wm0) }
-$int_if = { inet4(wm1), inet6(wm1) }
+$ext_if = { inet4(wm0) }
+$int_if = { inet4(wm1) }
 
 table <blacklist> type hash file "/etc/npf_blacklist"
 table <limited> type tree dynamic
@@ -316,6 +321,8 @@
 $services_udp = { domain, ntp, 6000 }
 $localnet = { 10.1.1.0/24 }
 
+alg "icmp"
+
 # Note: if $ext_if has multiple IP address (e.g. IPv6 as well),
 # then the translation address has to be specified explicitly.
 map $ext_if dynamic 10.1.1.0/24 -> $ext_if
--- a/usr.sbin/npf/npfctl/npf_parse.y	Wed Feb 04 06:58:54 2015 +0000
+++ b/usr.sbin/npf/npfctl/npf_parse.y	Wed Feb 04 07:13:04 2015 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_parse.y,v 1.35.4.1 2014/12/29 17:31:47 martin Exp $	*/
+/*	$NetBSD: npf_parse.y,v 1.35.4.2 2015/02/04 07:13:04 snj Exp $	*/
 
 /*-
  * Copyright (c) 2011-2014 The NetBSD Foundation, Inc.
@@ -31,10 +31,12 @@
 
 %{
 
+#include <err.h>
+#include <netdb.h>
 #include <stdio.h>
-#include <err.h>
+#include <stdlib.h>
+#include <string.h>
 #include <vis.h>
-#include <netdb.h>
 
 #include "npfctl.h"
 
--- a/usr.sbin/npf/npfctl/npf_show.c	Wed Feb 04 06:58:54 2015 +0000
+++ b/usr.sbin/npf/npfctl/npf_show.c	Wed Feb 04 07:13:04 2015 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_show.c,v 1.15 2014/07/20 00:48:51 rmind Exp $	*/
+/*	$NetBSD: npf_show.c,v 1.15.2.1 2015/02/04 07:13:04 snj Exp $	*/
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: npf_show.c,v 1.15 2014/07/20 00:48:51 rmind Exp $");
+__RCSID("$NetBSD: npf_show.c,v 1.15.2.1 2015/02/04 07:13:04 snj Exp $");
 
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -316,10 +316,25 @@
 npfctl_print_filter(npf_conf_info_t *ctx, nl_rule_t *rl)
 {
 	const void *marks;
-	size_t mlen;
+	size_t mlen, len;
+	const void *code;
+	int type;
 
-	/* BPF filter criteria described by the byte-code marks. */
 	marks = npf_rule_getinfo(rl, &mlen);
+	if (!marks && (code = npf_rule_getcode(rl, &type, &len)) != NULL) {
+		/*
+		 * No marks, but the byte-code is present.  This must
+		 * have been filled by libpcap(3) or possibly an unknown
+		 * to us byte-code.
+		 */
+		fprintf(ctx->fp, "%s ", type == NPF_CODE_BPF ?
+		    "pcap-filter \"...\"" : "unrecognized-bytecode");
+		return;
+	}
+
+	/*
+	 * BPF filter criteria described by the byte-code marks.
+	 */
 	for (u_int i = 0; i < __arraycount(mark_keyword_map); i++) {
 		const struct mark_keyword_mapent *mk = &mark_keyword_map[i];
 		char *val;
@@ -356,7 +371,7 @@
 		fprintf(ctx->fp, "on %s ", ifname);
 	}
 
-	if ((attr & (NPF_RULE_GROUP | NPF_RULE_DYNAMIC)) == NPF_RULE_GROUP) {
+	if ((attr & NPF_DYNAMIC_GROUP) == NPF_RULE_GROUP) {
 		/* Group; done. */
 		fputs("\n", ctx->fp);
 		return;
@@ -367,8 +382,15 @@
 
 	/* Rule procedure. */
 	if ((rproc = npf_rule_getproc(rl)) != NULL) {
-		fprintf(ctx->fp, "apply \"%s\"", rproc);
+		fprintf(ctx->fp, "apply \"%s\" ", rproc);
 	}
+
+	/* If dynamic rule - print its ID. */
+	if ((attr & NPF_DYNAMIC_GROUP) == NPF_RULE_DYNAMIC) {
+		uint64_t id = npf_rule_getid(rl);
+		fprintf(ctx->fp, "# id = \"%" PRIx64 "\" ", id);
+	}
+
 	fputs("\n", ctx->fp);
 }
 
--- a/usr.sbin/npf/npfctl/npfctl.c	Wed Feb 04 06:58:54 2015 +0000
+++ b/usr.sbin/npf/npfctl/npfctl.c	Wed Feb 04 07:13:04 2015 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npfctl.c,v 1.42.2.2 2014/12/29 17:31:47 martin Exp $	*/
+/*	$NetBSD: npfctl.c,v 1.42.2.3 2015/02/04 07:13:04 snj Exp $	*/
 
 /*-
  * Copyright (c) 2009-2014 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: npfctl.c,v 1.42.2.2 2014/12/29 17:31:47 martin Exp $");
+__RCSID("$NetBSD: npfctl.c,v 1.42.2.3 2015/02/04 07:13:04 snj Exp $");
 
 #include <sys/ioctl.h>
 #include <sys/stat.h>
@@ -580,9 +580,9 @@
 		fun = "ioctl(IOC_NPF_SWITCH)";
 		break;
 	case NPFCTL_RELOAD:
-		npfctl_preload_bpfjit();
 		npfctl_config_init(false);
 		npfctl_parse_file(argc < 3 ? NPF_CONF_PATH : argv[2]);
+		npfctl_preload_bpfjit();
 		errno = ret = npfctl_config_send(fd, NULL);
 		fun = "npfctl_config_send";
 		break;