Simplify parsing of npf.conf elements, create the npfvar_t when a value is trunk
authorrmind <rmind@NetBSD.org>
Tue, 19 Nov 2013 00:28:41 +0000
branchtrunk
changeset 222556 63ffb1b5fa44
parent 222555 6ab51e0a43f1
child 222557 f0a64e552025
Simplify parsing of npf.conf elements, create the npfvar_t when a value is parsed (to be used as a general structured for variables and inlined values), few misc improvements.
usr.sbin/npf/npfctl/npf.conf.5
usr.sbin/npf/npfctl/npf_build.c
usr.sbin/npf/npfctl/npf_data.c
usr.sbin/npf/npfctl/npf_parse.y
usr.sbin/npf/npfctl/npf_scan.l
usr.sbin/npf/npfctl/npf_show.c
usr.sbin/npf/npfctl/npf_var.c
usr.sbin/npf/npfctl/npf_var.h
--- a/usr.sbin/npf/npfctl/npf.conf.5	Mon Nov 18 21:39:03 2013 +0000
+++ b/usr.sbin/npf/npfctl/npf.conf.5	Tue Nov 19 00:28:41 2013 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: npf.conf.5,v 1.34 2013/11/12 06:07:30 wiz Exp $
+.\"    $NetBSD: npf.conf.5,v 1.35 2013/11/19 00:28:41 rmind Exp $
 .\"
 .\" Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -27,7 +27,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd November 10, 2013
+.Dd November 18, 2013
 .Dt NPF.CONF 5
 .Os
 .Sh NAME
@@ -99,7 +99,7 @@
 Interfaces can be specified as the values of the variables:
 .Pp
 .Bd -literal
-$pub_if_list = { ifnet(wm0), ifnet(wm1) }
+$pub_if_list = { inet4(wm0), inet4(wm1) }
 .Ed
 .Pp
 In the context of filtering, an interface provides a list of its
@@ -107,7 +107,7 @@
 Specific interface addresses can be selected by the family, e.g.:
 .Bd -literal
 $pub_if4 = inet4(wm0)
-$pub_if6 = { inet6(wm0) }
+$pub_if46 = { inet4(wm0), inet6(wm0) }
 .Ed
 .Ss Groups
 Groups may have the following options: name, interface, and direction.
@@ -281,8 +281,8 @@
 .\" -----
 .Sh EXAMPLES
 .Bd -literal
-$ext_if = ifnet(wm0)
-$int_if = ifnet(wm1)
+$ext_if = { inet4(wm0), inet6(wm0) }
+$int_if = { inet4(wm1), inet6(wm1) }
 
 table <black> type hash file "/etc/npf_blacklist"
 table <limited> type tree dynamic
--- a/usr.sbin/npf/npfctl/npf_build.c	Mon Nov 18 21:39:03 2013 +0000
+++ b/usr.sbin/npf/npfctl/npf_build.c	Tue Nov 19 00:28:41 2013 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_build.c,v 1.29 2013/11/12 00:46:34 rmind Exp $	*/
+/*	$NetBSD: npf_build.c,v 1.30 2013/11/19 00:28:41 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2011-2013 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: npf_build.c,v 1.29 2013/11/12 00:46:34 rmind Exp $");
+__RCSID("$NetBSD: npf_build.c,v 1.30 2013/11/19 00:28:41 rmind Exp $");
 
 #include <sys/types.h>
 #include <sys/ioctl.h>
@@ -171,25 +171,25 @@
 		}
 		return false;
 	}
+
 	family = fam->fam_family;
+	if (family != AF_INET && family != AF_INET6) {
+		yyerror("family %d is not supported", family);
+	}
 
 	/*
 	 * Optimise 0.0.0.0/0 case to be NOP.  Otherwise, address with
 	 * zero mask would never match and therefore is not valid.
 	 */
 	if (fam->fam_mask == 0) {
-		npf_addr_t zero;
+		static const npf_addr_t zero; /* must be static */
 
-		memset(&zero, 0, sizeof(npf_addr_t));
 		if (memcmp(&fam->fam_addr, &zero, sizeof(npf_addr_t))) {
 			yyerror("filter criterion would never match");
 		}
 		return false;
 	}
 
-	if (family != AF_INET && family != AF_INET6) {
-		yyerror("family %d is not supported", family);
-	}
 	npfctl_bpf_cidr(ctx, opts, family, &fam->fam_addr, fam->fam_mask);
 	return true;
 }
--- a/usr.sbin/npf/npfctl/npf_data.c	Mon Nov 18 21:39:03 2013 +0000
+++ b/usr.sbin/npf/npfctl/npf_data.c	Tue Nov 19 00:28:41 2013 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_data.c,v 1.21 2013/11/08 00:38:26 rmind Exp $	*/
+/*	$NetBSD: npf_data.c,v 1.22 2013/11/19 00:28:41 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: npf_data.c,v 1.21 2013/11/08 00:38:26 rmind Exp $");
+__RCSID("$NetBSD: npf_data.c,v 1.22 2013/11/19 00:28:41 rmind Exp $");
 
 #include <sys/types.h>
 #include <sys/null.h>
@@ -201,13 +201,12 @@
 npfctl_parse_fam_addr_mask(const char *addr, const char *mask,
     unsigned long *nummask)
 {
-	npfvar_t *vp = npfvar_create(".addr");
 	fam_addr_mask_t fam;
 
 	memset(&fam, 0, sizeof(fam));
 
 	if (!npfctl_parse_fam_addr(addr, &fam.fam_family, &fam.fam_addr))
-		goto out;
+		return NULL;
 
 	/*
 	 * Note: both mask and nummask may be NULL.  In such case,
@@ -216,36 +215,19 @@
 	if (nummask) {
 		fam.fam_mask = *nummask;
 	} else if (!npfctl_parse_mask(mask, fam.fam_family, &fam.fam_mask)) {
-		goto out;
+		return NULL;
 	}
-
-	if (!npfvar_add_element(vp, NPFVAR_FAM, &fam, sizeof(fam)))
-		goto out;
-
-	return vp;
-out:
-	npfvar_destroy(vp);
-	return NULL;
+	return npfvar_create_element(NPFVAR_FAM, &fam, sizeof(fam));
 }
 
 npfvar_t *
 npfctl_parse_table_id(const char *id)
 {
-	npfvar_t *vp;
-
 	if (!npfctl_table_exists_p(id)) {
 		yyerror("table '%s' is not defined", id);
 		return NULL;
 	}
-	vp = npfvar_create(".table");
-
-	if (!npfvar_add_element(vp, NPFVAR_TABLE, id, strlen(id) + 1))
-		goto out;
-
-	return vp;
-out:
-	npfvar_destroy(vp);
-	return NULL;
+	return npfvar_create_from_string(NPFVAR_TABLE, id);
 }
 
 /*
@@ -255,19 +237,12 @@
 npfvar_t *
 npfctl_parse_port_range(in_port_t s, in_port_t e)
 {
-	npfvar_t *vp = npfvar_create(".port_range");
 	port_range_t pr;
 
 	pr.pr_start = htons(s);
 	pr.pr_end = htons(e);
 
-	if (!npfvar_add_element(vp, NPFVAR_PORT_RANGE, &pr, sizeof(pr)))
-		goto out;
-
-	return vp;
-out:
-	npfvar_destroy(vp);
-	return NULL;
+	return npfvar_create_element(NPFVAR_PORT_RANGE, &pr, sizeof(pr));
 }
 
 npfvar_t *
@@ -275,7 +250,7 @@
 {
 	npfvar_t *vp = npfvar_lookup(v);
 	size_t count = npfvar_get_count(vp);
-	npfvar_t *pvp = npfvar_create(".port_range");
+	npfvar_t *pvp = npfvar_create();
 	port_range_t *pr;
 	in_port_t p;
 
@@ -311,15 +286,15 @@
 npfvar_t *
 npfctl_parse_ifnet(const char *ifname, const int family)
 {
-	npfvar_t *vpa, *vp;
 	struct ifaddrs *ifa;
 	ifnet_addr_t ifna;
+	npfvar_t *vpa;
 
 	if (ifs_list == NULL && getifaddrs(&ifs_list) == -1) {
 		err(EXIT_FAILURE, "getifaddrs");
 	}
 
-	vpa = npfvar_create(".ifaddrs");
+	vpa = npfvar_create();
 	ifna.ifna_name = estrdup(ifname);
 	ifna.ifna_addrs = vpa;
 	ifna.ifna_index = npfctl_find_ifindex(ifname);
@@ -359,9 +334,7 @@
 		goto out;
 	}
 
-	vp = npfvar_create(".interface");
-	npfvar_add_element(vp, NPFVAR_INTERFACE, &ifna, sizeof(ifna));
-	return vp;
+	return npfvar_create_element(NPFVAR_INTERFACE, &ifna, sizeof(ifna));
 out:
 	npfvar_destroy(ifna.ifna_addrs);
 	return NULL;
@@ -474,14 +447,7 @@
 		}
 		s++;
 	}
-
-	npfvar_t *vp = npfvar_create(".tcp_flag");
-	if (!npfvar_add_element(vp, NPFVAR_TCPFLAG, &tfl, sizeof(tfl))) {
-		npfvar_destroy(vp);
-		return NULL;
-	}
-
-	return vp;
+	return npfvar_create_element(NPFVAR_TCPFLAG, &tfl, sizeof(tfl));
 }
 
 uint8_t
@@ -501,7 +467,7 @@
 				return ul;
 		for (ul = 0; icmp6_type_info[ul]; ul++)
 			if (strcmp(icmp6_type_info[ul], type) == 0)
-				return (ul+128);
+				return ul + 128;
 		break;
 	default:
 		assert(false);
@@ -603,7 +569,7 @@
 npfvar_t *
 npfctl_parse_icmp(int proto, int type, int code)
 {
-	npfvar_t *vp = npfvar_create(".icmp");
+	npfvar_t *vp = npfvar_create();
 
 	if (!npfvar_add_element(vp, NPFVAR_ICMP, &type, sizeof(type)))
 		goto out;
--- a/usr.sbin/npf/npfctl/npf_parse.y	Mon Nov 18 21:39:03 2013 +0000
+++ b/usr.sbin/npf/npfctl/npf_parse.y	Tue Nov 19 00:28:41 2013 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_parse.y,v 1.28 2013/11/18 21:39:03 rmind Exp $	*/
+/*	$NetBSD: npf_parse.y,v 1.29 2013/11/19 00:28:41 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2011-2013 The NetBSD Foundation, Inc.
@@ -46,9 +46,6 @@
 extern int		yylineno, yycolumn;
 extern int		yylex(void);
 
-/* Variable under construction (bottom up). */
-static npfvar_t *	cvar;
-
 void
 yyerror(const char *fmt, ...)
 {
@@ -112,7 +109,7 @@
 %token			ID
 %token			IFNET
 %token			IN
-%token			INET
+%token			INET4
 %token			INET6
 %token			INTERFACE
 %token			MAP
@@ -155,14 +152,15 @@
 %token	<str>		TABLE_ID
 %token	<str>		VAR_ID
 
-%type	<str>		addr, some_name, element, table_store, string
-%type	<str>		proc_param_val, opt_apply, ifname, on_ifname
+%type	<str>		addr, some_name, table_store
+%type	<str>		proc_param_val, opt_apply, ifname, on_ifname, ifref
 %type	<num>		port, opt_final, number, afamily, opt_family
 %type	<num>		block_or_pass, rule_dir, group_dir, block_opts
 %type	<num>		opt_stateful, icmp_type, table_type, map_sd, map_type
-%type	<var>		ifnet, addr_or_ifnet, port_range, icmp_type_and_code
+%type	<var>		ifaddrs, addr_or_ifaddr, port_range, icmp_type_and_code
 %type	<var>		filt_addr, addr_and_mask, tcp_flags, tcp_flags_and_mask
 %type	<var>		procs, proc_call, proc_param_list, proc_param
+%type	<var>		element, list_elems, list, value
 %type	<addrport>	mapseg
 %type	<filtopts>	filt_opts, all_or_filt_opts
 %type	<optproto>	opt_proto
@@ -214,14 +212,9 @@
  */
 
 vardef
-	: VAR_ID
+	: VAR_ID EQ value
 	{
-		cvar = npfvar_create($1);
-		npfvar_add(cvar);
-	}
-	  EQ value
-	{
-		cvar = NULL;
+		npfvar_add($3, $1);
 	}
 	;
 
@@ -232,51 +225,43 @@
 
 list
 	: CURLY_OPEN list_elems CURLY_CLOSE
+	{
+		$$ = $2;
+	}
 	;
 
 list_elems
 	: element COMMA list_elems
+	{
+		npfvar_add_elements($1, $3);
+	}
 	| element
 	;
 
 element
 	: IDENTIFIER
 	{
-		npfvar_t *vp = npfvar_create(".identifier");
-		npfvar_add_element(vp, NPFVAR_IDENTIFIER, $1, strlen($1) + 1);
-		npfvar_add_elements(cvar, vp);
+		$$ = npfvar_create_from_string(NPFVAR_IDENTIFIER, $1);
 	}
 	| STRING
 	{
-		npfvar_t *vp = npfvar_create(".string");
-		npfvar_add_element(vp, NPFVAR_STRING, $1, strlen($1) + 1);
-		npfvar_add_elements(cvar, vp);
+		$$ = npfvar_create_from_string(NPFVAR_STRING, $1);
 	}
 	| number MINUS number
 	{
-		npfvar_t *vp = npfctl_parse_port_range($1, $3);
-		npfvar_add_elements(cvar, vp);
+		$$ = npfctl_parse_port_range($1, $3);
 	}
 	| number
 	{
-		npfvar_t *vp = npfvar_create(".num");
-		npfvar_add_element(vp, NPFVAR_NUM, &$1, sizeof($1));
-		npfvar_add_elements(cvar, vp);
+		$$ = npfvar_create_element(NPFVAR_NUM, &$1, sizeof($1));
 	}
 	| VAR_ID
 	{
-		npfvar_t *vp = npfvar_create(".var_id");
-		npfvar_add_element(vp, NPFVAR_VAR_ID, $1, strlen($1) + 1);
-		npfvar_add_elements(cvar, vp);
+		$$ = npfvar_create_from_string(NPFVAR_VAR_ID, $1);
 	}
-	| ifnet
-	{
-		npfvar_add_elements(cvar, $1);
-	}
-	| addr_and_mask
-	{
-		npfvar_add_elements(cvar, $1);
-	}
+	| TABLE_ID		{ $$ = npfctl_parse_table_id($1); }
+	| ifaddrs		{ $$ = $1; }
+	| addr_and_mask		{ $$ = $1; }
 	;
 
 /*
@@ -317,7 +302,7 @@
 	;
 
 mapseg
-	: addr_or_ifnet port_range
+	: addr_or_ifaddr port_range
 	{
 		$$.ap_netaddr = $1;
 		$$.ap_portrange = $2;
@@ -325,11 +310,11 @@
 	;
 
 map
-	: MAP ifname map_sd mapseg map_type mapseg PASS filt_opts
+	: MAP ifref map_sd mapseg map_type mapseg PASS filt_opts
 	{
 		npfctl_build_natseg($3, $5, $2, &$4, &$6, &$8);
 	}
-	| MAP ifname map_sd mapseg map_type mapseg
+	| MAP ifref map_sd mapseg map_type mapseg
 	{
 		npfctl_build_natseg($3, $5, $2, &$4, &$6, NULL);
 	}
@@ -365,10 +350,10 @@
 
 		pc.pc_name = estrdup($1);
 		pc.pc_opts = $3;
-		$$ = npfvar_create(".proc_call");
-		npfvar_add_element($$, NPFVAR_PROC, &pc, sizeof(pc));
+
+		$$ = npfvar_create_element(NPFVAR_PROC, &pc, sizeof(pc));
 	}
-	|	{ $$ = NULL; }
+	|		{ $$ = NULL; }
 	;
 
 proc_param_list
@@ -381,15 +366,14 @@
 	;
 
 proc_param
-	/* Key and value pair. */
 	: some_name proc_param_val
 	{
 		proc_param_t pp;
 
 		pp.pp_param = estrdup($1);
 		pp.pp_value = $2 ? estrdup($2) : NULL;
-		$$ = npfvar_create(".proc_param");
-		npfvar_add_element($$, NPFVAR_PROC_PARAM, &pp, sizeof(pp));
+
+		$$ = npfvar_create_element(NPFVAR_PROC_PARAM, &pp, sizeof(pp));
 	}
 	;
 
@@ -407,7 +391,7 @@
 group
 	: GROUP group_opts
 	{
-		/* Build a group.  Increases the nesting level. */
+		/* Build a group.  Increase the nesting level. */
 		npfctl_build_group($2.rg_name, $2.rg_attr,
 		    $2.rg_ifname, $2.rg_default);
 	}
@@ -500,12 +484,12 @@
 	;
 
 on_ifname
-	: ON ifname		{ $$ = $2; }
+	: ON ifref		{ $$ = $2; }
 	|			{ $$ = NULL; }
 	;
 
 afamily
-	: INET			{ $$ = AF_INET; }
+	: INET4			{ $$ = AF_INET; }
 	| INET6			{ $$ = AF_INET6; }
 	;
 
@@ -600,7 +584,7 @@
 	;
 
 filt_addr
-	: addr_or_ifnet		{ $$ = $1; }
+	: addr_or_ifaddr	{ $$ = $1; }
 	| TABLE_ID		{ $$ = npfctl_parse_table_id($1); }
 	| ANY			{ $$ = NULL; }
 	;
@@ -620,13 +604,13 @@
 	}
 	;
 
-addr_or_ifnet
+addr_or_ifaddr
 	: addr_and_mask
 	{
 		assert($1 != NULL);
 		$$ = $1;
 	}
-	| ifnet
+	| ifaddrs
 	{
 		ifnet_addr_t *ifna = npfvar_get_data($1, NPFVAR_INTERFACE, 0);
 		$$ = ifna->ifna_addrs;
@@ -745,55 +729,12 @@
 	}
 	;
 
-string
-	: IDENTIFIER
-	{
-		$$ = $1;
-	}
-	| VAR_ID
-	{
-		npfvar_t *vp = npfvar_lookup($1);
-		const int type = npfvar_get_type(vp, 0);
-
-		switch (type) {
-		case NPFVAR_STRING:
-		case NPFVAR_IDENTIFIER:
-			$$ = npfvar_expand_string(vp);
-			break;
-		case -1:
-			yyerror("undefined variable '%s' for interface", $1);
-			break;
-		default:
-			yyerror("wrong variable '%s' type '%s' for string",
-			    $1, npfvar_type(type));
-			break;
-		}
-	}
-	;
-
-ifnet
-	: IFNET PAR_OPEN string PAR_CLOSE
-	{
-		$$ = npfctl_parse_ifnet($3, AF_UNSPEC);
-	}
-	| afamily PAR_OPEN string PAR_CLOSE
-	{
-		$$ = npfctl_parse_ifnet($3, $1);
-	}
-	;
-
 ifname
 	: some_name
 	{
 		npfctl_note_interface($1);
 		$$ = $1;
 	}
-	| ifnet
-	{
-		ifnet_addr_t *ifna = npfvar_get_data($1, NPFVAR_INTERFACE, 0);
-		npfctl_note_interface(ifna->ifna_name);
-		$$ = ifna->ifna_name;
-	}
 	| VAR_ID
 	{
 		npfvar_t *vp = npfvar_lookup($1);
@@ -821,6 +762,23 @@
 	}
 	;
 
+ifaddrs
+	: afamily PAR_OPEN ifname PAR_CLOSE
+	{
+		$$ = npfctl_parse_ifnet($3, $1);
+	}
+	;
+
+ifref
+	: ifname
+	| ifaddrs
+	{
+		ifnet_addr_t *ifna = npfvar_get_data($1, NPFVAR_INTERFACE, 0);
+		npfctl_note_interface(ifna->ifna_name);
+		$$ = ifna->ifna_name;
+	}
+	;
+
 number
 	: HEX		{ $$ = $1; }
 	| NUM		{ $$ = $1; }
--- a/usr.sbin/npf/npfctl/npf_scan.l	Mon Nov 18 21:39:03 2013 +0000
+++ b/usr.sbin/npf/npfctl/npf_scan.l	Tue Nov 19 00:28:41 2013 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_scan.l,v 1.15 2013/11/18 21:39:03 rmind Exp $	*/
+/*	$NetBSD: npf_scan.l,v 1.16 2013/11/19 00:28:41 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2011-2012 The NetBSD Foundation, Inc.
@@ -119,10 +119,9 @@
 final			return FINAL;
 quick			return FINAL;
 on			return ON;
-ifnet			return IFNET;
 inet6			return INET6;
-inet4			return INET;
-inet			return INET;
+inet4			return INET4;
+inet			return INET4;
 proto			return PROTO;
 family			return FAMILY;
 tcp			return TCP;
--- a/usr.sbin/npf/npfctl/npf_show.c	Mon Nov 18 21:39:03 2013 +0000
+++ b/usr.sbin/npf/npfctl/npf_show.c	Tue Nov 19 00:28:41 2013 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_show.c,v 1.4 2013/11/12 00:46:34 rmind Exp $	*/
+/*	$NetBSD: npf_show.c,v 1.5 2013/11/19 00:28:41 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: npf_show.c,v 1.4 2013/11/12 00:46:34 rmind Exp $");
+__RCSID("$NetBSD: npf_show.c,v 1.5 2013/11/19 00:28:41 rmind Exp $");
 
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -420,6 +420,11 @@
 	const char *name = npf_table_getname(tl);
 	const int type = npf_table_gettype(tl);
 
+	if (name[0] == '.') {
+		/* Internal tables use dot and are hidden. */
+		return;
+	}
+
 	fprintf(ctx->fp, "table <%s> type %s\n", name,
 	    (type == NPF_TABLE_HASH) ? "hash" :
 	    (type == NPF_TABLE_TREE) ? "tree" :
--- a/usr.sbin/npf/npfctl/npf_var.c	Mon Nov 18 21:39:03 2013 +0000
+++ b/usr.sbin/npf/npfctl/npf_var.c	Tue Nov 19 00:28:41 2013 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_var.c,v 1.7 2012/11/15 22:20:27 rmind Exp $	*/
+/*	$NetBSD: npf_var.c,v 1.8 2013/11/19 00:28:41 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2011-2012 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: npf_var.c,v 1.7 2012/11/15 22:20:27 rmind Exp $");
+__RCSID("$NetBSD: npf_var.c,v 1.8 2013/11/19 00:28:41 rmind Exp $");
 
 #include <stdlib.h>
 #include <string.h>
@@ -58,10 +58,9 @@
 static size_t		var_num = 0;
 
 npfvar_t *
-npfvar_create(const char *name)
+npfvar_create(void)
 {
 	npfvar_t *vp = ecalloc(1, sizeof(*vp));
-	vp->v_key = estrdup(name);
 	var_num++;
 	return vp;
 }
@@ -85,13 +84,27 @@
 }
 
 void
-npfvar_add(npfvar_t *vp)
+npfvar_add(npfvar_t *vp, const char *name)
 {
+	vp->v_key = estrdup(name);
 	vp->v_next = var_list;
 	var_list = vp;
 }
 
 npfvar_t *
+npfvar_create_element(int type, const void *data, size_t len)
+{
+	npfvar_t *vp = npfvar_create();
+	return npfvar_add_element(vp, type, data, len);
+}
+
+npfvar_t *
+npfvar_create_from_string(int type, const char *string)
+{
+	return npfvar_create_element(type, string, strlen(string) + 1);
+}
+
+npfvar_t *
 npfvar_add_element(npfvar_t *vp, int type, const void *data, size_t len)
 {
 	npf_element_t *el;
--- a/usr.sbin/npf/npfctl/npf_var.h	Mon Nov 18 21:39:03 2013 +0000
+++ b/usr.sbin/npf/npfctl/npf_var.h	Tue Nov 19 00:28:41 2013 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_var.h,v 1.7 2013/09/19 01:04:45 rmind Exp $	*/
+/*	$NetBSD: npf_var.h,v 1.8 2013/11/19 00:28:41 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2011-2012 The NetBSD Foundation, Inc.
@@ -63,17 +63,19 @@
 	[NPFVAR_PROC_PARAM]	= "procedure-parameter",
 	[NPFVAR_TCPFLAG]	= "tcp-flag",
 	[NPFVAR_ICMP]		= "icmp",
-	[NPFVAR_INTERFACE]	= "interface"
+	[NPFVAR_INTERFACE]	= "interface-address"
 };
 #endif
 
 struct npfvar;
 typedef struct npfvar npfvar_t;
 
-npfvar_t *	npfvar_create(const char *);
+npfvar_t *	npfvar_create(void);
+npfvar_t *	npfvar_create_element(int, const void *, size_t);
+npfvar_t *	npfvar_create_from_string(int, const char *);
 npfvar_t *	npfvar_lookup(const char *);
 const char *	npfvar_type(size_t);
-void		npfvar_add(npfvar_t *);
+void		npfvar_add(npfvar_t *, const char *);
 npfvar_t *	npfvar_add_element(npfvar_t *, int, const void *, size_t);
 npfvar_t *	npfvar_add_elements(npfvar_t *, npfvar_t *);
 void		npfvar_destroy(npfvar_t *);