npf.conf: add support for logical NOT, e.g.: pass from ! 10.0.0.1 to any trunk
authorrmind <rmind@NetBSD.org>
Tue, 27 Dec 2016 22:35:33 +0000
branchtrunk
changeset 247153 8018b97c9a6d
parent 247152 05f736137870
child 247154 417f0df5964c
npf.conf: add support for logical NOT, e.g.: pass from ! 10.0.0.1 to any
usr.sbin/npf/npfctl/npf.conf.5
usr.sbin/npf/npfctl/npf_bpf_comp.c
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/npfctl.h
--- a/usr.sbin/npf/npfctl/npf.conf.5	Tue Dec 27 22:20:00 2016 +0000
+++ b/usr.sbin/npf/npfctl/npf.conf.5	Tue Dec 27 22:35:33 2016 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: npf.conf.5,v 1.44 2015/02/01 22:57:21 rmind Exp $
+.\"    $NetBSD: npf.conf.5,v 1.45 2016/12/27 22:35:33 rmind Exp $
 .\"
 .\" Copyright (c) 2009-2015 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 February 1, 2015
+.Dd December 28, 2016
 .Dt NPF.CONF 5
 .Os
 .Sh NAME
@@ -295,7 +295,8 @@
 
 addr-mask	= addr [ "/" mask ]
 filt-opts	= "from" filt-addr [ port-opts ] "to" filt-addr [ port-opts ]
-filt-addr	= [ interface | var-name | addr-mask | table-id | "any" ]
+filt-addr	= [ "!" ] [ interface | var-name |
+                  addr-mask | table-id | "any" ]
 filt-port	= "port" ( port-num | port-from "-" port-to | var-name )
 .Ed
 .\" -----
--- a/usr.sbin/npf/npfctl/npf_bpf_comp.c	Tue Dec 27 22:20:00 2016 +0000
+++ b/usr.sbin/npf/npfctl/npf_bpf_comp.c	Tue Dec 27 22:35:33 2016 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_bpf_comp.c,v 1.9 2016/12/26 23:05:05 christos Exp $	*/
+/*	$NetBSD: npf_bpf_comp.c,v 1.10 2016/12/27 22:35:33 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2010-2014 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: npf_bpf_comp.c,v 1.9 2016/12/26 23:05:05 christos Exp $");
+__RCSID("$NetBSD: npf_bpf_comp.c,v 1.10 2016/12/27 22:35:33 rmind Exp $");
 
 #include <stdlib.h>
 #include <stdbool.h>
@@ -244,18 +244,29 @@
 }
 
 void
-npfctl_bpf_endgroup(npf_bpf_t *ctx)
+npfctl_bpf_endgroup(npf_bpf_t *ctx, bool invert)
 {
 	struct bpf_program *bp = &ctx->prog;
 	const size_t curoff = bp->bf_len;
 
 	/* If there are no blocks or only one - nothing to do. */
-	if ((ctx->nblocks - ctx->gblock) <= 1) {
+	if (!invert && (ctx->nblocks - ctx->gblock) <= 1) {
 		ctx->goff = ctx->gblock = 0;
 		return;
 	}
 
 	/*
+	 * If inverting, then prepend a jump over the statement below.
+	 * If matching, jump will jump below and the fail will happen.
+	 */
+	if (invert) {
+		struct bpf_insn insns_ret[] = {
+			BPF_STMT(BPF_JMP+BPF_JA, 1),
+		};
+		add_insns(ctx, insns_ret, __arraycount(insns_ret));
+	}
+
+	/*
 	 * Append a failure return as a fall-through i.e. if there is
 	 * no match within the group.
 	 */
@@ -309,7 +320,7 @@
 		 */
 		if (ingroup) {
 			assert(ctx->nblocks == ctx->gblock);
-			npfctl_bpf_endgroup(ctx);
+			npfctl_bpf_endgroup(ctx, false);
 		}
 
 		/*
--- a/usr.sbin/npf/npfctl/npf_build.c	Tue Dec 27 22:20:00 2016 +0000
+++ b/usr.sbin/npf/npfctl/npf_build.c	Tue Dec 27 22:35:33 2016 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_build.c,v 1.41 2016/12/26 23:05:05 christos Exp $	*/
+/*	$NetBSD: npf_build.c,v 1.42 2016/12/27 22:35:33 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2011-2014 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: npf_build.c,v 1.41 2016/12/26 23:05:05 christos Exp $");
+__RCSID("$NetBSD: npf_build.c,v 1.42 2016/12/27 22:35:33 rmind Exp $");
 
 #include <sys/types.h>
 #include <sys/mman.h>
@@ -268,7 +268,7 @@
 			assert(false);
 		}
 	}
-	npfctl_bpf_endgroup(ctx);
+	npfctl_bpf_endgroup(ctx, (opts & MATCH_INVERT) != 0);
 }
 
 static void
@@ -321,6 +321,7 @@
 	const addr_port_t *apto = &fopts->fo_to;
 	const int proto = op->op_proto;
 	npf_bpf_t *bc;
+	unsigned opts;
 	size_t len;
 
 	/* If none specified, then no byte-code. */
@@ -365,8 +366,10 @@
 	}
 
 	/* Build IP address blocks. */
-	npfctl_build_vars(bc, family, apfrom->ap_netaddr, MATCH_SRC);
-	npfctl_build_vars(bc, family, apto->ap_netaddr, MATCH_DST);
+	opts = MATCH_SRC | (fopts->fo_finvert ? MATCH_INVERT : 0);
+	npfctl_build_vars(bc, family, apfrom->ap_netaddr, opts);
+	opts = MATCH_DST | (fopts->fo_tinvert ? MATCH_INVERT : 0);
+	npfctl_build_vars(bc, family, apto->ap_netaddr, opts);
 
 	/* Build port-range blocks. */
 	if (need_tcpudp) {
@@ -374,7 +377,7 @@
 		npfctl_bpf_group(bc);
 		npfctl_bpf_proto(bc, AF_UNSPEC, IPPROTO_TCP);
 		npfctl_bpf_proto(bc, AF_UNSPEC, IPPROTO_UDP);
-		npfctl_bpf_endgroup(bc);
+		npfctl_bpf_endgroup(bc, false);
 	}
 	npfctl_build_vars(bc, family, apfrom->ap_portrange, MATCH_SRC);
 	npfctl_build_vars(bc, family, apto->ap_portrange, MATCH_DST);
--- a/usr.sbin/npf/npfctl/npf_data.c	Tue Dec 27 22:20:00 2016 +0000
+++ b/usr.sbin/npf/npfctl/npf_data.c	Tue Dec 27 22:35:33 2016 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_data.c,v 1.26 2016/12/26 23:05:05 christos Exp $	*/
+/*	$NetBSD: npf_data.c,v 1.27 2016/12/27 22:35:33 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2009-2014 The NetBSD Foundation, Inc.
@@ -31,10 +31,12 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: npf_data.c,v 1.26 2016/12/26 23:05:05 christos Exp $");
+__RCSID("$NetBSD: npf_data.c,v 1.27 2016/12/27 22:35:33 rmind Exp $");
+
+#include <stdlib.h>
+#include <stddef.h>
 
 #include <sys/types.h>
-#include <sys/null.h>
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
 #include <netinet/ip.h>
@@ -46,8 +48,6 @@
 #include <netinet/tcp.h>
 #include <net/if.h>
 
-#include <stdlib.h>
-#include <stddef.h>
 #include <string.h>
 #include <ctype.h>
 #include <err.h>
--- a/usr.sbin/npf/npfctl/npf_parse.y	Tue Dec 27 22:20:00 2016 +0000
+++ b/usr.sbin/npf/npfctl/npf_parse.y	Tue Dec 27 22:35:33 2016 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_parse.y,v 1.38 2015/03/24 20:24:17 christos Exp $	*/
+/*	$NetBSD: npf_parse.y,v 1.39 2016/12/27 22:35:33 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2011-2014 The NetBSD Foundation, Inc.
@@ -105,6 +105,7 @@
 %token			TDYNAMIC
 %token			TSTATIC
 %token			EQ
+%token			EXCL_MARK
 %token			TFILE
 %token			FLAGS
 %token			FROM
@@ -164,7 +165,7 @@
 %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
+%type	<num>		maybe_not, opt_stateful, icmp_type, table_type
 %type	<num>		map_sd, map_algo, map_type
 %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
@@ -526,6 +527,11 @@
 	| INET6			{ $$ = AF_INET6; }
 	;
 
+maybe_not
+	: EXCL_MARK		{ $$ = true; }
+	|			{ $$ = false; }
+	;
+
 opt_family
 	: FAMILY afamily	{ $$ = $2; }
 	|			{ $$ = AF_UNSPEC; }
@@ -567,8 +573,10 @@
 all_or_filt_opts
 	: ALL
 	{
+		$$.fo_finvert = false;
 		$$.fo_from.ap_netaddr = NULL;
 		$$.fo_from.ap_portrange = NULL;
+		$$.fo_tinvert = false;
 		$$.fo_to.ap_netaddr = NULL;
 		$$.fo_to.ap_portrange = NULL;
 	}
@@ -594,26 +602,32 @@
 	;
 
 filt_opts
-	: FROM filt_addr port_range TO filt_addr port_range
+	: FROM maybe_not filt_addr port_range TO maybe_not filt_addr port_range
 	{
-		$$.fo_from.ap_netaddr = $2;
-		$$.fo_from.ap_portrange = $3;
-		$$.fo_to.ap_netaddr = $5;
-		$$.fo_to.ap_portrange = $6;
+		$$.fo_finvert = $2;
+		$$.fo_from.ap_netaddr = $3;
+		$$.fo_from.ap_portrange = $4;
+		$$.fo_tinvert = $6;
+		$$.fo_to.ap_netaddr = $7;
+		$$.fo_to.ap_portrange = $8;
 	}
-	| FROM filt_addr port_range
+	| FROM maybe_not filt_addr port_range
 	{
-		$$.fo_from.ap_netaddr = $2;
-		$$.fo_from.ap_portrange = $3;
+		$$.fo_finvert = $2;
+		$$.fo_from.ap_netaddr = $3;
+		$$.fo_from.ap_portrange = $4;
+		$$.fo_tinvert = false;
 		$$.fo_to.ap_netaddr = NULL;
 		$$.fo_to.ap_portrange = NULL;
 	}
-	| TO filt_addr port_range
+	| TO maybe_not filt_addr port_range
 	{
+		$$.fo_finvert = false;
 		$$.fo_from.ap_netaddr = NULL;
 		$$.fo_from.ap_portrange = NULL;
-		$$.fo_to.ap_netaddr = $2;
-		$$.fo_to.ap_portrange = $3;
+		$$.fo_tinvert = $2;
+		$$.fo_to.ap_netaddr = $3;
+		$$.fo_to.ap_portrange = $4;
 	}
 	;
 
--- a/usr.sbin/npf/npfctl/npf_scan.l	Tue Dec 27 22:20:00 2016 +0000
+++ b/usr.sbin/npf/npfctl/npf_scan.l	Tue Dec 27 22:35:33 2016 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_scan.l,v 1.23 2016/01/22 22:03:54 christos Exp $	*/
+/*	$NetBSD: npf_scan.l,v 1.24 2016/12/27 22:35:33 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2011-2012 The NetBSD Foundation, Inc.
@@ -154,6 +154,7 @@
 ")"			return PAR_CLOSE;
 ","			return COMMA;
 "="			return EQ;
+"!"			return EXCL_MARK;
 
 "0x"{HEXDIG} {
 			char *endp, *buf = ecalloc(1, yyleng + 1);
--- a/usr.sbin/npf/npfctl/npfctl.h	Tue Dec 27 22:20:00 2016 +0000
+++ b/usr.sbin/npf/npfctl/npfctl.h	Tue Dec 27 22:35:33 2016 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npfctl.h,v 1.41 2016/12/27 20:14:35 christos Exp $	*/
+/*	$NetBSD: npfctl.h,v 1.42 2016/12/27 22:35:33 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
@@ -78,6 +78,8 @@
 typedef struct filt_opts {
 	addr_port_t	fo_from;
 	addr_port_t	fo_to;
+	bool		fo_finvert;
+	bool		fo_tinvert;
 } filt_opts_t;
 
 typedef struct opt_proto {
@@ -149,6 +151,7 @@
 
 #define	MATCH_DST	0x01
 #define	MATCH_SRC	0x02
+#define	MATCH_INVERT	0x04
 
 enum {
 	BM_IPVER, BM_PROTO, BM_SRC_CIDR, BM_SRC_TABLE, BM_DST_CIDR,
@@ -162,7 +165,7 @@
 void		npfctl_bpf_destroy(npf_bpf_t *);
 
 void		npfctl_bpf_group(npf_bpf_t *);
-void		npfctl_bpf_endgroup(npf_bpf_t *);
+void		npfctl_bpf_endgroup(npf_bpf_t *, bool);
 
 void		npfctl_bpf_proto(npf_bpf_t *, sa_family_t, int);
 void		npfctl_bpf_cidr(npf_bpf_t *, u_int, sa_family_t,