All of lore.kernel.org
 help / color / mirror / Atom feed
* [nft PATCH 0/5] Introduce boolean type and existence checks
@ 2017-03-10 17:13 Phil Sutter
  2017-03-10 17:13 ` [nft PATCH 1/5] Introduce boolean datatype and boolean expression Phil Sutter
                   ` (5 more replies)
  0 siblings, 6 replies; 10+ messages in thread
From: Phil Sutter @ 2017-03-10 17:13 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

The following patch series implements a boolean datatype for use in a
boolean expression as right-hand side of a relational. Based upon that,
header existence matches are implemented for IPv6 extension and TCP
option headers as well as an existence match of a FIB entry.

Phil Sutter (5):
  Introduce boolean datatype and boolean expression
  exthdr: Add support for exthdr specific flags
  exthdr: Implement existence check
  fib: Support existence check
  doc: Document boolean type and applications

 doc/nft.xml                         | 134 ++++++++++++++++++++++++++++++++++++
 include/datatype.h                  |   2 +
 include/expression.h                |   3 +
 include/exthdr.h                    |   4 +-
 include/linux/netfilter/nf_tables.h |   1 +
 include/tcpopt.h                    |   3 +-
 src/datatype.c                      |  19 +++++
 src/evaluate.c                      |  17 ++++-
 src/expression.c                    |   4 ++
 src/exthdr.c                        |  39 ++++++++---
 src/fib.c                           |   5 +-
 src/netlink_delinearize.c           |   5 +-
 src/netlink_linearize.c             |   1 +
 src/parser_bison.y                  |  54 +++++++++++++++
 src/scanner.l                       |   5 ++
 src/tcpopt.c                        |  11 ++-
 tests/py/inet/fib.t                 |   3 +
 tests/py/inet/fib.t.payload         |  10 +++
 tests/py/inet/tcpopt.t              |   3 +
 tests/py/inet/tcpopt.t.payload.inet |  14 ++++
 tests/py/ip6/exthdr.t               |  19 +++++
 tests/py/ip6/exthdr.t.payload.ip6   |  60 ++++++++++++++++
 22 files changed, 399 insertions(+), 17 deletions(-)
 create mode 100644 tests/py/ip6/exthdr.t
 create mode 100644 tests/py/ip6/exthdr.t.payload.ip6

-- 
2.11.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [nft PATCH 1/5] Introduce boolean datatype and boolean expression
  2017-03-10 17:13 [nft PATCH 0/5] Introduce boolean type and existence checks Phil Sutter
@ 2017-03-10 17:13 ` Phil Sutter
  2017-03-10 17:13 ` [nft PATCH 2/5] exthdr: Add support for exthdr specific flags Phil Sutter
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Phil Sutter @ 2017-03-10 17:13 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 include/datatype.h |  2 ++
 src/datatype.c     | 19 +++++++++++++++++++
 src/parser_bison.y | 20 ++++++++++++++++++++
 src/scanner.l      |  3 +++
 4 files changed, 44 insertions(+)

diff --git a/include/datatype.h b/include/datatype.h
index b78d76f78f76c..e614b96e880bf 100644
--- a/include/datatype.h
+++ b/include/datatype.h
@@ -82,6 +82,7 @@ enum datatypes {
 	TYPE_DSCP,
 	TYPE_ECN,
 	TYPE_FIB_ADDR,
+	TYPE_BOOLEAN,
 	__TYPE_MAX
 };
 #define TYPE_MAX		(__TYPE_MAX - 1)
@@ -233,6 +234,7 @@ extern const struct datatype icmp_code_type;
 extern const struct datatype icmpv6_code_type;
 extern const struct datatype icmpx_code_type;
 extern const struct datatype time_type;
+extern const struct datatype boolean_type;
 
 extern const struct datatype *concat_type_alloc(uint32_t type);
 extern void concat_type_destroy(const struct datatype *dtype);
diff --git a/src/datatype.c b/src/datatype.c
index 6b1dd4a09abbc..c61c4245c3868 100644
--- a/src/datatype.c
+++ b/src/datatype.c
@@ -48,6 +48,7 @@ static const struct datatype *datatypes[TYPE_MAX + 1] = {
 	[TYPE_ICMP_CODE]	= &icmp_code_type,
 	[TYPE_ICMPV6_CODE]	= &icmpv6_code_type,
 	[TYPE_ICMPX_CODE]	= &icmpx_code_type,
+	[TYPE_BOOLEAN]		= &boolean_type,
 };
 
 void datatype_register(const struct datatype *dtype)
@@ -1104,3 +1105,21 @@ struct error_record *rate_parse(const struct location *loc, const char *str,
 
 	return NULL;
 }
+
+static const struct symbol_table boolean_tbl = {
+	.base		= BASE_DECIMAL,
+	.symbols	= {
+		SYMBOL("exists",	true),
+		SYMBOL("missing",	false),
+		SYMBOL_LIST_END
+	},
+};
+
+const struct datatype boolean_type = {
+	.type		= TYPE_BOOLEAN,
+	.name		= "boolean",
+	.desc		= "boolean type",
+	.size		= 1,
+	.basetype	= &integer_type,
+	.sym_tbl	= &boolean_tbl,
+};
diff --git a/src/parser_bison.y b/src/parser_bison.y
index dff8a5ab90ace..f2ae82f471dd6 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -448,6 +448,9 @@ static void location_update(struct location *loc, struct location *rhs, int n)
 
 %token NOTRACK			"notrack"
 
+%token EXISTS			"exists"
+%token MISSING			"missing"
+
 %type <string>			identifier type_identifier string comment_spec
 %destructor { xfree($$); }	identifier type_identifier string comment_spec
 
@@ -651,6 +654,10 @@ static void location_update(struct location *loc, struct location *rhs, int n)
 %type <val>			tcp_hdr_field
 %type <val>			tcp_hdr_option_type tcp_hdr_option_field
 
+%type <expr>			boolean_expr
+%destructor { expr_free($$); }	boolean_expr
+%type <val>			boolean_keys
+
 %%
 
 input			:	/* empty */
@@ -2655,8 +2662,21 @@ concat_rhs_expr		:	basic_rhs_expr
 			}
 			;
 
+boolean_keys		:	EXISTS		{ $$ = true; }
+			|	MISSING		{ $$ = false; }
+			;
+
+boolean_expr		:	boolean_keys
+			{
+				$$ = constant_expr_alloc(&@$, &boolean_type,
+							 BYTEORDER_HOST_ENDIAN,
+							 1, &$1);
+			}
+			;
+
 primary_rhs_expr	:	symbol_expr		{ $$ = $1; }
 			|	integer_expr		{ $$ = $1; }
+			|	boolean_expr		{ $$ = $1; }
 			|	ETHER
 			{
 				$$ = symbol_expr_alloc(&@$, SYMBOL_VALUE,
diff --git a/src/scanner.l b/src/scanner.l
index 003f15eb1c3c2..b0d571988650a 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -504,6 +504,9 @@ addrstring	({macaddr}|{ip4addr}|{ip6addr})
 "xml"			{ return XML; }
 "json"			{ return JSON; }
 
+"exists"		{ return EXISTS; }
+"missing"		{ return MISSING; }
+
 {addrstring}		{
 				yylval->string = xstrdup(yytext);
 				return STRING;
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [nft PATCH 2/5] exthdr: Add support for exthdr specific flags
  2017-03-10 17:13 [nft PATCH 0/5] Introduce boolean type and existence checks Phil Sutter
  2017-03-10 17:13 ` [nft PATCH 1/5] Introduce boolean datatype and boolean expression Phil Sutter
@ 2017-03-10 17:13 ` Phil Sutter
  2017-03-10 17:13 ` [nft PATCH 3/5] exthdr: Implement existence check Phil Sutter
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Phil Sutter @ 2017-03-10 17:13 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

This allows to have custom flags in exthdr expression, which is
necessary for upcoming existence checks (of both IPv6 extension headers
as well as TCP options).

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 include/expression.h      |  1 +
 include/exthdr.h          |  2 +-
 include/tcpopt.h          |  3 ++-
 src/exthdr.c              | 11 +++++++----
 src/netlink_delinearize.c |  5 +++--
 src/netlink_linearize.c   |  1 +
 src/tcpopt.c              |  5 +++--
 7 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/include/expression.h b/include/expression.h
index 4f2948cc002be..423eae7128f5c 100644
--- a/include/expression.h
+++ b/include/expression.h
@@ -282,6 +282,7 @@ struct expr {
 			const struct proto_hdr_template	*tmpl;
 			unsigned int			offset;
 			enum nft_exthdr_op		op;
+			unsigned int			flags;
 		} exthdr;
 		struct {
 			/* EXPR_META */
diff --git a/include/exthdr.h b/include/exthdr.h
index cdcc2b9537972..c7f806ebb2fa2 100644
--- a/include/exthdr.h
+++ b/include/exthdr.h
@@ -23,7 +23,7 @@ extern struct expr *exthdr_expr_alloc(const struct location *loc,
 
 extern void exthdr_init_raw(struct expr *expr, uint8_t type,
 			    unsigned int offset, unsigned int len,
-			    enum nft_exthdr_op op);
+			    enum nft_exthdr_op op, uint32_t flags);
 
 extern bool exthdr_find_template(struct expr *expr, const struct expr *mask,
 				 unsigned int *shift);
diff --git a/include/tcpopt.h b/include/tcpopt.h
index f43a7eb703fed..412d02e7ba80f 100644
--- a/include/tcpopt.h
+++ b/include/tcpopt.h
@@ -8,7 +8,8 @@ extern struct expr *tcpopt_expr_alloc(const struct location *loc,
 				      uint8_t type, uint8_t field);
 
 extern void tcpopt_init_raw(struct expr *expr, uint8_t type,
-			    unsigned int offset, unsigned int len);
+			    unsigned int offset, unsigned int len,
+			    uint32_t flags);
 
 extern bool tcpopt_find_template(struct expr *expr, const struct expr *mask,
 				 unsigned int *shift);
diff --git a/src/exthdr.c b/src/exthdr.c
index ddda1b870310f..21fe734f8fc15 100644
--- a/src/exthdr.c
+++ b/src/exthdr.c
@@ -46,7 +46,8 @@ static bool exthdr_expr_cmp(const struct expr *e1, const struct expr *e2)
 {
 	return e1->exthdr.desc == e2->exthdr.desc &&
 	       e1->exthdr.tmpl == e2->exthdr.tmpl &&
-	       e1->exthdr.op == e2->exthdr.op;
+	       e1->exthdr.op == e2->exthdr.op &&
+	       e1->exthdr.flags == e2->exthdr.flags;
 }
 
 static void exthdr_expr_clone(struct expr *new, const struct expr *expr)
@@ -55,6 +56,7 @@ static void exthdr_expr_clone(struct expr *new, const struct expr *expr)
 	new->exthdr.tmpl = expr->exthdr.tmpl;
 	new->exthdr.offset = expr->exthdr.offset;
 	new->exthdr.op = expr->exthdr.op;
+	new->exthdr.flags = expr->exthdr.flags;
 }
 
 const struct expr_ops exthdr_expr_ops = {
@@ -97,16 +99,17 @@ static const struct exthdr_desc *exthdr_protocols[IPPROTO_MAX] = {
 
 void exthdr_init_raw(struct expr *expr, uint8_t type,
 		     unsigned int offset, unsigned int len,
-		     enum nft_exthdr_op op)
+		     enum nft_exthdr_op op, uint32_t flags)
 {
 	const struct proto_hdr_template *tmpl;
 	unsigned int i;
 
 	assert(expr->ops->type == EXPR_EXTHDR);
 	if (op == NFT_EXTHDR_OP_TCPOPT)
-		return tcpopt_init_raw(expr, type, offset, len);
+		return tcpopt_init_raw(expr, type, offset, len, flags);
 
 	expr->len = len;
+	expr->exthdr.flags = flags;
 	expr->exthdr.offset = offset;
 	expr->exthdr.desc = exthdr_protocols[type];
 	assert(expr->exthdr.desc != NULL);
@@ -149,7 +152,7 @@ bool exthdr_find_template(struct expr *expr, const struct expr *mask, unsigned i
 	off += round_up(mask->len, BITS_PER_BYTE) - mask_len;
 
 	exthdr_init_raw(expr, expr->exthdr.desc->type,
-			off, mask_len - mask_offset, NFT_EXTHDR_OP_IPV6);
+			off, mask_len - mask_offset, NFT_EXTHDR_OP_IPV6, 0);
 
 	/* still failed to find a template... Bug. */
 	if (expr->exthdr.tmpl == &exthdr_unknown_template)
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 36e8fe3c4337b..9ad1e2c681c64 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -498,9 +498,9 @@ static void netlink_parse_exthdr(struct netlink_parse_ctx *ctx,
 				 const struct location *loc,
 				 const struct nftnl_expr *nle)
 {
+	uint32_t offset, len, flags;
 	enum nft_registers dreg;
 	enum nft_exthdr_op op;
-	uint32_t offset, len;
 	uint8_t type;
 	struct expr *expr;
 
@@ -508,9 +508,10 @@ static void netlink_parse_exthdr(struct netlink_parse_ctx *ctx,
 	offset = nftnl_expr_get_u32(nle, NFTNL_EXPR_EXTHDR_OFFSET) * BITS_PER_BYTE;
 	len    = nftnl_expr_get_u32(nle, NFTNL_EXPR_EXTHDR_LEN) * BITS_PER_BYTE;
 	op     = nftnl_expr_get_u32(nle, NFTNL_EXPR_EXTHDR_OP);
+	flags  = nftnl_expr_get_u32(nle, NFTNL_EXPR_EXTHDR_FLAGS);
 
 	expr = exthdr_expr_alloc(loc, NULL, 0);
-	exthdr_init_raw(expr, type, offset, len, op);
+	exthdr_init_raw(expr, type, offset, len, op, flags);
 
 	dreg = netlink_parse_register(nle, NFTNL_EXPR_EXTHDR_DREG);
 	netlink_set_register(ctx, dreg, expr);
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 293150e2d0155..b2f27b7a35855 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -178,6 +178,7 @@ static void netlink_gen_exthdr(struct netlink_linearize_ctx *ctx,
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_EXTHDR_LEN,
 			   div_round_up(expr->len, BITS_PER_BYTE));
 	nftnl_expr_set_u8(nle, NFTNL_EXPR_EXTHDR_OP, expr->exthdr.op);
+	nftnl_expr_set_u32(nle, NFTNL_EXPR_EXTHDR_FLAGS, expr->exthdr.flags);
 	nftnl_rule_add_expr(ctx->nlr, nle);
 }
 
diff --git a/src/tcpopt.c b/src/tcpopt.c
index f861214117a18..d34dfd459f415 100644
--- a/src/tcpopt.c
+++ b/src/tcpopt.c
@@ -192,7 +192,7 @@ struct expr *tcpopt_expr_alloc(const struct location *loc, uint8_t type,
 }
 
 void tcpopt_init_raw(struct expr *expr, uint8_t type, unsigned int offset,
-		     unsigned int len)
+		     unsigned int len, uint32_t flags)
 {
 	const struct proto_hdr_template *tmpl;
 	unsigned int i, off;
@@ -200,6 +200,7 @@ void tcpopt_init_raw(struct expr *expr, uint8_t type, unsigned int offset,
 	assert(expr->ops->type == EXPR_EXTHDR);
 
 	expr->len = len;
+	expr->exthdr.flags = flags;
 	expr->exthdr.offset = offset;
 
 	assert(type < array_size(tcpopt_protocols));
@@ -229,7 +230,7 @@ bool tcpopt_find_template(struct expr *expr, const struct expr *mask,
 		return false;
 
 	tcpopt_init_raw(expr, expr->exthdr.desc->type, expr->exthdr.offset,
-			expr->len);
+			expr->len, 0);
 
 	if (expr->exthdr.tmpl == &tcpopt_unknown_template)
 		return false;
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [nft PATCH 3/5] exthdr: Implement existence check
  2017-03-10 17:13 [nft PATCH 0/5] Introduce boolean type and existence checks Phil Sutter
  2017-03-10 17:13 ` [nft PATCH 1/5] Introduce boolean datatype and boolean expression Phil Sutter
  2017-03-10 17:13 ` [nft PATCH 2/5] exthdr: Add support for exthdr specific flags Phil Sutter
@ 2017-03-10 17:13 ` Phil Sutter
  2017-03-10 17:13 ` [nft PATCH 4/5] fib: Support " Phil Sutter
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Phil Sutter @ 2017-03-10 17:13 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

This allows to check for existence of an IPv6 extension or TCP
option header by using the following syntax:

| exthdr frag exists
| tcpopt window exists

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 include/exthdr.h                    |  2 ++
 src/evaluate.c                      |  3 ++
 src/exthdr.c                        | 28 ++++++++++++++---
 src/parser_bison.y                  | 34 +++++++++++++++++++++
 src/scanner.l                       |  2 ++
 src/tcpopt.c                        |  6 +++-
 tests/py/inet/tcpopt.t              |  3 ++
 tests/py/inet/tcpopt.t.payload.inet | 14 +++++++++
 tests/py/ip6/exthdr.t               | 19 ++++++++++++
 tests/py/ip6/exthdr.t.payload.ip6   | 60 +++++++++++++++++++++++++++++++++++++
 10 files changed, 166 insertions(+), 5 deletions(-)
 create mode 100644 tests/py/ip6/exthdr.t
 create mode 100644 tests/py/ip6/exthdr.t.payload.ip6

diff --git a/include/exthdr.h b/include/exthdr.h
index c7f806ebb2fa2..a2647ee142dcd 100644
--- a/include/exthdr.h
+++ b/include/exthdr.h
@@ -21,6 +21,8 @@ extern struct expr *exthdr_expr_alloc(const struct location *loc,
 				      const struct exthdr_desc *desc,
 				      uint8_t type);
 
+extern const struct exthdr_desc *exthdr_find_proto(uint8_t proto);
+
 extern void exthdr_init_raw(struct expr *expr, uint8_t type,
 			    unsigned int offset, unsigned int len,
 			    enum nft_exthdr_op op, uint32_t flags);
diff --git a/src/evaluate.c b/src/evaluate.c
index efcafc7249bfc..7c039cbab5ec3 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -432,6 +432,9 @@ static int __expr_evaluate_exthdr(struct eval_ctx *ctx, struct expr **exprp)
 {
 	struct expr *expr = *exprp;
 
+	if (expr->exthdr.flags & NFT_EXTHDR_F_PRESENT)
+		expr->dtype = &boolean_type;
+
 	if (expr_evaluate_primary(ctx, exprp) < 0)
 		return -1;
 
diff --git a/src/exthdr.c b/src/exthdr.c
index 21fe734f8fc15..375e18fce46da 100644
--- a/src/exthdr.c
+++ b/src/exthdr.c
@@ -32,14 +32,22 @@ static void exthdr_expr_print(const struct expr *expr)
 		unsigned int offset = expr->exthdr.offset / 64;
 		char buf[3] = {0};
 
+		if (expr->exthdr.flags & NFT_EXTHDR_F_PRESENT) {
+			printf("tcp option %s", expr->exthdr.desc->name);
+			return;
+		}
+
 		if (offset)
 			snprintf(buf, sizeof buf, "%d", offset);
 		printf("tcp option %s%s %s", expr->exthdr.desc->name, buf,
 					     expr->exthdr.tmpl->token);
+	} else {
+		if (expr->exthdr.flags & NFT_EXTHDR_F_PRESENT)
+			printf("exthdr %s", expr->exthdr.desc->name);
+		else
+			printf("%s %s", expr->exthdr.desc->name,
+					expr->exthdr.tmpl->token);
 	}
-	else
-		printf("%s %s", expr->exthdr.desc->name,
-				expr->exthdr.tmpl->token);
 }
 
 static bool exthdr_expr_cmp(const struct expr *e1, const struct expr *e2)
@@ -97,6 +105,13 @@ static const struct exthdr_desc *exthdr_protocols[IPPROTO_MAX] = {
 	[IPPROTO_MH]		= &exthdr_mh,
 };
 
+const struct exthdr_desc *exthdr_find_proto(uint8_t proto)
+{
+	assert(exthdr_protocols[proto]);
+
+	return exthdr_protocols[proto];
+}
+
 void exthdr_init_raw(struct expr *expr, uint8_t type,
 		     unsigned int offset, unsigned int len,
 		     enum nft_exthdr_op op, uint32_t flags)
@@ -119,7 +134,12 @@ void exthdr_init_raw(struct expr *expr, uint8_t type,
 		if (tmpl->offset != offset ||
 		    tmpl->len    != len)
 			continue;
-		expr->dtype	  = tmpl->dtype;
+
+		if (flags & NFT_EXTHDR_F_PRESENT)
+			expr->dtype = &boolean_type;
+		else
+			expr->dtype = tmpl->dtype;
+
 		expr->exthdr.tmpl = tmpl;
 		return;
 	}
diff --git a/src/parser_bison.y b/src/parser_bison.y
index f2ae82f471dd6..12a6e64645fa0 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -139,6 +139,7 @@ static void location_update(struct location *loc, struct location *rhs, int n)
 	const struct datatype	*datatype;
 	struct handle_spec	handle_spec;
 	struct position_spec	position_spec;
+	const struct exthdr_desc *exthdr_desc;
 }
 
 %token TOKEN_EOF 0		"end of file"
@@ -451,6 +452,8 @@ static void location_update(struct location *loc, struct location *rhs, int n)
 %token EXISTS			"exists"
 %token MISSING			"missing"
 
+%token EXTHDR			"exthdr"
+
 %type <string>			identifier type_identifier string comment_spec
 %destructor { xfree($$); }	identifier type_identifier string comment_spec
 
@@ -658,6 +661,10 @@ static void location_update(struct location *loc, struct location *rhs, int n)
 %destructor { expr_free($$); }	boolean_expr
 %type <val>			boolean_keys
 
+%type <expr>			exthdr_exists_expr
+%destructor { expr_free($$); }	exthdr_exists_expr
+%type <val>			exthdr_key
+
 %%
 
 input			:	/* empty */
@@ -2291,6 +2298,7 @@ primary_expr		:	symbol_expr			{ $$ = $1; }
 			|	integer_expr			{ $$ = $1; }
 			|	payload_expr			{ $$ = $1; }
 			|	exthdr_expr			{ $$ = $1; }
+			|	exthdr_exists_expr		{ $$ = $1; }
 			|	meta_expr			{ $$ = $1; }
 			|	rt_expr				{ $$ = $1; }
 			|	ct_expr				{ $$ = $1; }
@@ -3254,6 +3262,11 @@ tcp_hdr_expr		:	TCP	tcp_hdr_field
 			{
 				$$ = tcpopt_expr_alloc(&@$, $3, $4);
 			}
+			|	TCP	OPTION	tcp_hdr_option_type
+			{
+				$$ = tcpopt_expr_alloc(&@$, $3, TCPOPTHDR_FIELD_KIND);
+				$$->exthdr.flags = NFT_EXTHDR_F_PRESENT;
+			}
 			;
 
 tcp_hdr_field		:	SPORT		{ $$ = TCPHDR_SPORT; }
@@ -3404,4 +3417,25 @@ mh_hdr_field		:	NEXTHDR		{ $$ = MHHDR_NEXTHDR; }
 			|	CHECKSUM	{ $$ = MHHDR_CHECKSUM; }
 			;
 
+exthdr_exists_expr	:	EXTHDR	exthdr_key
+			{
+				const struct exthdr_desc *desc;
+
+				desc = exthdr_find_proto($2);
+
+				/* Assume that NEXTHDR template is always
+				 * the fist one in list of templates.
+				 */
+				$$ = exthdr_expr_alloc(&@$, desc, 1);
+				$$->exthdr.flags = NFT_EXTHDR_F_PRESENT;
+			}
+			;
+
+exthdr_key		:	HBH	{ $$ = IPPROTO_HOPOPTS; }
+			|	RT	{ $$ = IPPROTO_ROUTING; }
+			|	FRAG	{ $$ = IPPROTO_FRAGMENT; }
+			|	DST	{ $$ = IPPROTO_DSTOPTS; }
+			|	MH	{ $$ = IPPROTO_MH; }
+			;
+
 %%
diff --git a/src/scanner.l b/src/scanner.l
index b0d571988650a..c2c008d6d611c 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -507,6 +507,8 @@ addrstring	({macaddr}|{ip4addr}|{ip6addr})
 "exists"		{ return EXISTS; }
 "missing"		{ return MISSING; }
 
+"exthdr"		{ return EXTHDR; }
+
 {addrstring}		{
 				yylval->string = xstrdup(yytext);
 				return STRING;
diff --git a/src/tcpopt.c b/src/tcpopt.c
index d34dfd459f415..dac4fdb90915a 100644
--- a/src/tcpopt.c
+++ b/src/tcpopt.c
@@ -205,6 +205,7 @@ void tcpopt_init_raw(struct expr *expr, uint8_t type, unsigned int offset,
 
 	assert(type < array_size(tcpopt_protocols));
 	expr->exthdr.desc = tcpopt_protocols[type];
+	expr->exthdr.flags = flags;
 	assert(expr->exthdr.desc != TCPOPT_OBSOLETE);
 
 	for (i = 0; i < array_size(expr->exthdr.desc->templates); ++i) {
@@ -216,7 +217,10 @@ void tcpopt_init_raw(struct expr *expr, uint8_t type, unsigned int offset,
 		if (tmpl->offset != off || tmpl->len != len)
 			continue;
 
-		expr->dtype       = tmpl->dtype;
+		if (flags & NFT_EXTHDR_F_PRESENT)
+			expr->dtype = &boolean_type;
+		else
+			expr->dtype = tmpl->dtype;
 		expr->exthdr.tmpl = tmpl;
 		expr->exthdr.op   = NFT_EXTHDR_OP_TCPOPT;
 		break;
diff --git a/tests/py/inet/tcpopt.t b/tests/py/inet/tcpopt.t
index 59452b48fce54..a42ecd250a9c1 100644
--- a/tests/py/inet/tcpopt.t
+++ b/tests/py/inet/tcpopt.t
@@ -35,3 +35,6 @@ tcp option eol left 1;fail
 tcp option eol left 1;fail
 tcp option sack window;fail
 tcp option sack window 1;fail
+
+tcp option window exists;ok
+tcp option window missing;ok
diff --git a/tests/py/inet/tcpopt.t.payload.inet b/tests/py/inet/tcpopt.t.payload.inet
index 12deab8c920ff..0d14e77929cca 100644
--- a/tests/py/inet/tcpopt.t.payload.inet
+++ b/tests/py/inet/tcpopt.t.payload.inet
@@ -179,3 +179,17 @@ inet test-inet input
   [ cmp eq reg 1 0x00000006 ]
   [ exthdr load tcpopt 4b @ 8 + 6 => reg 1 ]
   [ cmp eq reg 1 0x01000000 ]
+
+# tcp option window exists
+inet test-inet input
+  [ meta load l4proto => reg 1 ]
+  [ cmp eq reg 1 0x00000006 ]
+  [ exthdr load tcpopt 1b @ 3 + 0 => reg 1 ]
+  [ cmp eq reg 1 0x00000001 ]
+
+# tcp option window missing
+inet test-inet input
+  [ meta load l4proto => reg 1 ]
+  [ cmp eq reg 1 0x00000006 ]
+  [ exthdr load tcpopt 1b @ 3 + 0 => reg 1 ]
+  [ cmp eq reg 1 0x00000000 ]
diff --git a/tests/py/ip6/exthdr.t b/tests/py/ip6/exthdr.t
new file mode 100644
index 0000000000000..a6c2d2be179ca
--- /dev/null
+++ b/tests/py/ip6/exthdr.t
@@ -0,0 +1,19 @@
+:input;type filter hook input priority 0
+
+*ip6;test-ip6;input
+
+exthdr hbh exists;ok
+exthdr rt exists;ok
+exthdr frag exists;ok
+exthdr dst exists;ok
+exthdr mh exists;ok
+
+exthdr hbh missing;ok
+
+exthdr hbh == exists;ok;exthdr hbh exists
+exthdr hbh == missing;ok;exthdr hbh missing
+exthdr hbh != exists;ok
+exthdr hbh != missing;ok
+
+exthdr hbh 1;ok;exthdr hbh exists
+exthdr hbh 0;ok;exthdr hbh missing
diff --git a/tests/py/ip6/exthdr.t.payload.ip6 b/tests/py/ip6/exthdr.t.payload.ip6
new file mode 100644
index 0000000000000..b45eb8e74272f
--- /dev/null
+++ b/tests/py/ip6/exthdr.t.payload.ip6
@@ -0,0 +1,60 @@
+# exthdr hbh exists
+ip6 test-ip6 input
+  [ exthdr load 1b @ 0 + 0 => reg 1 ]
+  [ cmp eq reg 1 0x00000001 ]
+
+# exthdr rt exists
+ip6 test-ip6 input
+  [ exthdr load 1b @ 43 + 0 => reg 1 ]
+  [ cmp eq reg 1 0x00000001 ]
+
+# exthdr frag exists
+ip6 test-ip6 input
+  [ exthdr load 1b @ 44 + 0 => reg 1 ]
+  [ cmp eq reg 1 0x00000001 ]
+
+# exthdr dst exists
+ip6 test-ip6 input
+  [ exthdr load 1b @ 60 + 0 => reg 1 ]
+  [ cmp eq reg 1 0x00000001 ]
+
+# exthdr mh exists
+ip6 test-ip6 input
+  [ exthdr load 1b @ 135 + 0 => reg 1 ]
+  [ cmp eq reg 1 0x00000001 ]
+
+# exthdr hbh missing
+ip6 test-ip6 input
+  [ exthdr load 1b @ 0 + 0 => reg 1 ]
+  [ cmp eq reg 1 0x00000000 ]
+
+# exthdr hbh == exists
+ip6 test-ip6 input
+  [ exthdr load 1b @ 0 + 0 => reg 1 ]
+  [ cmp eq reg 1 0x00000001 ]
+
+# exthdr hbh == missing
+ip6 test-ip6 input
+  [ exthdr load 1b @ 0 + 0 => reg 1 ]
+  [ cmp eq reg 1 0x00000000 ]
+
+# exthdr hbh != exists
+ip6 test-ip6 input
+  [ exthdr load 1b @ 0 + 0 => reg 1 ]
+  [ cmp neq reg 1 0x00000001 ]
+
+# exthdr hbh != missing
+ip6 test-ip6 input
+  [ exthdr load 1b @ 0 + 0 => reg 1 ]
+  [ cmp neq reg 1 0x00000000 ]
+
+# exthdr hbh 1
+ip6 test-ip6 input
+  [ exthdr load 1b @ 0 + 0 => reg 1 ]
+  [ cmp eq reg 1 0x00000001 ]
+
+# exthdr hbh 0
+ip6 test-ip6 input
+  [ exthdr load 1b @ 0 + 0 => reg 1 ]
+  [ cmp eq reg 1 0x00000000 ]
+
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [nft PATCH 4/5] fib: Support existence check
  2017-03-10 17:13 [nft PATCH 0/5] Introduce boolean type and existence checks Phil Sutter
                   ` (2 preceding siblings ...)
  2017-03-10 17:13 ` [nft PATCH 3/5] exthdr: Implement existence check Phil Sutter
@ 2017-03-10 17:13 ` Phil Sutter
  2017-03-10 18:07   ` Pablo Neira Ayuso
  2017-03-10 17:13 ` [nft PATCH 5/5] doc: Document boolean type and applications Phil Sutter
  2017-03-10 18:02 ` [nft PATCH 0/5] Introduce boolean type and existence checks Pablo Neira Ayuso
  5 siblings, 1 reply; 10+ messages in thread
From: Phil Sutter @ 2017-03-10 17:13 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

This allows to check whether a FIB entry exists for a given packet by
comparing the expression with a boolean keyword like so:

| fib daddr oif exists

The implementation requires introduction of a generic expression flag
EXPR_F_BOOLEAN which allows relational expression to signal it's LHS
that a boolean comparison is being done (indicated by boolean type on
RHS). In contrast to exthdr existence checks, fib expression can't know
this in beforehand because the LHS syntax is absolutely identical to a
non-boolean comparison.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 include/expression.h                |  2 ++
 include/linux/netfilter/nf_tables.h |  1 +
 src/evaluate.c                      | 14 +++++++++++++-
 src/expression.c                    |  4 ++++
 src/fib.c                           |  5 ++++-
 tests/py/inet/fib.t                 |  3 +++
 tests/py/inet/fib.t.payload         | 10 ++++++++++
 7 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/include/expression.h b/include/expression.h
index 423eae7128f5c..94573de087ad7 100644
--- a/include/expression.h
+++ b/include/expression.h
@@ -171,12 +171,14 @@ struct expr_ops {
  * @EXPR_F_SINGLETON:		singleton (implies primary and constant)
  * @EXPR_F_PROTOCOL:		expressions describes upper layer protocol
  * @EXPR_F_INTERVAL_END:	set member ends an open interval
+ * @EXPR_F_BOOLEAN:		expression is boolean (set by relational expr on LHS)
  */
 enum expr_flags {
 	EXPR_F_CONSTANT		= 0x1,
 	EXPR_F_SINGLETON	= 0x2,
 	EXPR_F_PROTOCOL		= 0x4,
 	EXPR_F_INTERVAL_END	= 0x8,
+	EXPR_F_BOOLEAN		= 0x10,
 };
 
 #include <payload.h>
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index 4f7d75682c591..a9280a6541ac6 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -1257,6 +1257,7 @@ enum nft_fib_flags {
 	NFTA_FIB_F_MARK		= 1 << 2,	/* use skb->mark */
 	NFTA_FIB_F_IIF		= 1 << 3,	/* restrict to iif */
 	NFTA_FIB_F_OIF		= 1 << 4,	/* restrict to oif */
+	NFTA_FIB_F_PRESENT	= 1 << 5,	/* check existence only */
 };
 
 #define NFT_OBJECT_UNSPEC	0
diff --git a/src/evaluate.c b/src/evaluate.c
index 7c039cbab5ec3..7ddbb658f96fa 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1658,6 +1658,17 @@ range:
 	return 0;
 }
 
+static int expr_evaluate_fib(struct eval_ctx *ctx, struct expr **exprp)
+{
+	struct expr *expr = *exprp;
+
+	if (expr->flags & EXPR_F_BOOLEAN) {
+		expr->fib.flags |= NFTA_FIB_F_PRESENT;
+		expr->dtype = &boolean_type;
+	}
+	return expr_evaluate_primary(ctx, exprp);
+}
+
 static int expr_evaluate(struct eval_ctx *ctx, struct expr **expr)
 {
 #ifdef DEBUG
@@ -1680,8 +1691,9 @@ static int expr_evaluate(struct eval_ctx *ctx, struct expr **expr)
 		return expr_evaluate_exthdr(ctx, expr);
 	case EXPR_VERDICT:
 	case EXPR_META:
-	case EXPR_FIB:
 		return expr_evaluate_primary(ctx, expr);
+	case EXPR_FIB:
+		return expr_evaluate_fib(ctx, expr);
 	case EXPR_PAYLOAD:
 		return expr_evaluate_payload(ctx, expr);
 	case EXPR_RT:
diff --git a/src/expression.c b/src/expression.c
index da94b79f1d913..a6065524f8be8 100644
--- a/src/expression.c
+++ b/src/expression.c
@@ -592,6 +592,10 @@ struct expr *relational_expr_alloc(const struct location *loc, enum ops op,
 	expr->left  = left;
 	expr->op    = op;
 	expr->right = right;
+
+	if (right->dtype == &boolean_type)
+		left->flags |= EXPR_F_BOOLEAN;
+
 	return expr;
 }
 
diff --git a/src/fib.c b/src/fib.c
index c65677c811abc..28ef4b50b3ea3 100644
--- a/src/fib.c
+++ b/src/fib.c
@@ -73,7 +73,7 @@ static void __fib_expr_print_f(unsigned int *flags, unsigned int f, const char *
 
 static void fib_expr_print(const struct expr *expr)
 {
-	unsigned int flags = expr->fib.flags;
+	unsigned int flags = expr->fib.flags & ~NFTA_FIB_F_PRESENT;
 
 	printf("fib ");
 	__fib_expr_print_f(&flags, NFTA_FIB_F_SADDR, "saddr");
@@ -130,6 +130,9 @@ struct expr *fib_expr_alloc(const struct location *loc,
 		BUG("Unknown result %d\n", result);
 	}
 
+	if (flags & NFTA_FIB_F_PRESENT)
+		type = &boolean_type;
+
 	expr = expr_alloc(loc, &fib_expr_ops, type,
 			  BYTEORDER_HOST_ENDIAN, len);
 
diff --git a/tests/py/inet/fib.t b/tests/py/inet/fib.t
index 9ee282ab1c93d..dbe45d95b4cfe 100644
--- a/tests/py/inet/fib.t
+++ b/tests/py/inet/fib.t
@@ -12,3 +12,6 @@ fib saddr . iif oifname "lo";ok
 fib daddr . iif type local;ok
 fib daddr . iif type vmap { blackhole : drop, prohibit : drop, unicast : accept };ok
 fib daddr . oif type local;fail
+
+fib daddr oif exists;ok
+fib daddr oif missing;ok
diff --git a/tests/py/inet/fib.t.payload b/tests/py/inet/fib.t.payload
index f5258165384dc..e928a19649133 100644
--- a/tests/py/inet/fib.t.payload
+++ b/tests/py/inet/fib.t.payload
@@ -20,3 +20,13 @@ __map%d test-ip 0
 ip test-ip prerouting
   [ fib daddr . iif type => reg 1 ]
   [ lookup reg 1 set __map%d dreg 0 ]
+
+# fib daddr oif exists
+ip test-ip prerouting
+  [ fib daddr oif => reg 1 ]
+  [ cmp eq reg 1 0x00000001 ]
+
+# fib daddr oif missing
+ip test-ip prerouting
+  [ fib daddr oif => reg 1 ]
+  [ cmp eq reg 1 0x00000000 ]
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [nft PATCH 5/5] doc: Document boolean type and applications
  2017-03-10 17:13 [nft PATCH 0/5] Introduce boolean type and existence checks Phil Sutter
                   ` (3 preceding siblings ...)
  2017-03-10 17:13 ` [nft PATCH 4/5] fib: Support " Phil Sutter
@ 2017-03-10 17:13 ` Phil Sutter
  2017-03-10 18:14   ` Pablo Neira Ayuso
  2017-03-10 18:02 ` [nft PATCH 0/5] Introduce boolean type and existence checks Pablo Neira Ayuso
  5 siblings, 1 reply; 10+ messages in thread
From: Phil Sutter @ 2017-03-10 17:13 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 doc/nft.xml | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 134 insertions(+)

diff --git a/doc/nft.xml b/doc/nft.xml
index 990b93684c9c4..de86d2a18258f 100644
--- a/doc/nft.xml
+++ b/doc/nft.xml
@@ -1329,6 +1329,110 @@ filter output ip6 daddr ::1
 				</programlisting>
 			</example>
 		</refsect2>
+
+		<refsect2>
+			<title>Boolean type</title>
+			<para>
+				<table frame="all">
+					<tgroup cols='4' align='left' colsep='1' rowsep='1'>
+						<colspec colname='c1'/>
+						<colspec colname='c2'/>
+						<colspec colname='c3'/>
+						<colspec colname='c4'/>
+						<thead>
+							<row>
+								<entry>Name</entry>
+								<entry>Keyword</entry>
+								<entry>Size</entry>
+								<entry>Base type</entry>
+							</row>
+						</thead>
+						<tbody>
+							<row>
+								<entry>Boolean</entry>
+								<entry>boolean</entry>
+								<entry>1 bit</entry>
+								<entry>integer</entry>
+							</row>
+						</tbody>
+					</tgroup>
+				</table>
+			</para>
+			<para>
+				The boolean type is a syntactical helper type in user space.
+				It's use is in the right-hand side of a (typically implicit)
+				relational expression to change the expression on the left-hand
+				side into a boolean check (usually for existence).
+			</para>
+			<para>
+				The following keywords will automatically resolve into a boolean
+				type with given value:
+				<table frame="all">
+					<tgroup cols='2' align='left' colsep='1' rowsep='1'>
+						<colspec colname='c1'/>
+						<colspec colname='c2'/>
+						<thead>
+							<row>
+								<entry>Keyword</entry>
+								<entry>Value</entry>
+							</row>
+						</thead>
+						<tbody>
+							<row>
+								<entry>exists</entry>
+								<entry>1</entry>
+							</row>
+							<row>
+								<entry>missing</entry>
+								<entry>0</entry>
+							</row>
+						</tbody>
+					</tgroup>
+				</table>
+			</para>
+			<example>
+				<title>Boolean specification</title>
+				<para>
+					The following expressions support a boolean comparison:
+					<table frame="all">
+						<tgroup cols='2' align='left' colsep='1' rowsep='1'>
+							<colspec colname='c1'/>
+							<colspec colname='c2'/>
+							<thead>
+								<row>
+									<entry>Expression</entry>
+									<entry>Behaviour</entry>
+								</row>
+							</thead>
+							<tbody>
+								<row>
+									<entry>fib</entry>
+									<entry>Check route existence.</entry>
+								</row>
+								<row>
+									<entry>exthdr</entry>
+									<entry>Check IPv6 extension header existence.</entry>
+								</row>
+								<row>
+									<entry>tcp option</entry>
+									<entry>Check TCP option header existence.</entry>
+								</row>
+							</tbody>
+						</tgroup>
+					</table>
+				</para>
+				<programlisting>
+# match if route exists
+filter input fib iif saddr exists
+
+# match only non-fragmented packets in IPv6 traffic
+filter input exthdr frag missing
+
+# match if TCP timestamp option is present
+filter input tcp option timestamp exists
+				</programlisting>
+			</example>
+		</refsect2>
 	</refsect1>
 
 	<refsect1>
@@ -2536,6 +2640,36 @@ inet filter meta nfproto ipv6 output rt nexthop fd00::1
 				<arg choice="none"><replaceable>tcp_option_field</replaceable></arg>
 			</cmdsynopsis>
 			<para>
+				The following syntaxes are valid only in a relational expression
+				with boolean type on right-hand side for checking header existence only:
+			</para>
+			<cmdsynopsis>
+				<command>exthdr</command>
+				<group choice="req">
+					<arg>hbh</arg>
+					<arg>frag</arg>
+					<arg>rt</arg>
+					<arg>dst</arg>
+					<arg>mh</arg>
+				</group>
+			</cmdsynopsis>
+			<cmdsynopsis>
+				<command>tcp option</command>
+				<group choice="req">
+					<arg>eol</arg>
+					<arg>noop</arg>
+					<arg>maxseg</arg>
+					<arg>window</arg>
+					<arg>sack-permitted</arg>
+					<arg>sack</arg>
+					<arg>sack0</arg>
+					<arg>sack1</arg>
+					<arg>sack2</arg>
+					<arg>sack3</arg>
+					<arg>timestamp</arg>
+				</group>
+			</cmdsynopsis>
+			<para>
 				<table frame="all">
 					<title>IPv6 extension headers</title>
 					<tgroup cols='2' align='left' colsep='1' rowsep='1'>
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [nft PATCH 0/5] Introduce boolean type and existence checks
  2017-03-10 17:13 [nft PATCH 0/5] Introduce boolean type and existence checks Phil Sutter
                   ` (4 preceding siblings ...)
  2017-03-10 17:13 ` [nft PATCH 5/5] doc: Document boolean type and applications Phil Sutter
@ 2017-03-10 18:02 ` Pablo Neira Ayuso
  5 siblings, 0 replies; 10+ messages in thread
From: Pablo Neira Ayuso @ 2017-03-10 18:02 UTC (permalink / raw)
  To: Phil Sutter; +Cc: netfilter-devel

On Fri, Mar 10, 2017 at 06:13:48PM +0100, Phil Sutter wrote:
> The following patch series implements a boolean datatype for use in a
> boolean expression as right-hand side of a relational. Based upon that,
> header existence matches are implemented for IPv6 extension and TCP
> option headers as well as an existence match of a FIB entry.

Nice series Phil, applied from patch 1/5 to 3/5.

Please see comment on 4/5. Thanks!

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [nft PATCH 4/5] fib: Support existence check
  2017-03-10 17:13 ` [nft PATCH 4/5] fib: Support " Phil Sutter
@ 2017-03-10 18:07   ` Pablo Neira Ayuso
  2017-03-10 21:41     ` Phil Sutter
  0 siblings, 1 reply; 10+ messages in thread
From: Pablo Neira Ayuso @ 2017-03-10 18:07 UTC (permalink / raw)
  To: Phil Sutter; +Cc: netfilter-devel

On Fri, Mar 10, 2017 at 06:13:52PM +0100, Phil Sutter wrote:
[...]
> diff --git a/tests/py/inet/fib.t.payload b/tests/py/inet/fib.t.payload
> index f5258165384dc..e928a19649133 100644
> --- a/tests/py/inet/fib.t.payload
> +++ b/tests/py/inet/fib.t.payload
> @@ -20,3 +20,13 @@ __map%d test-ip 0
>  ip test-ip prerouting
>    [ fib daddr . iif type => reg 1 ]
>    [ lookup reg 1 set __map%d dreg 0 ]
> +
> +# fib daddr oif exists
> +ip test-ip prerouting
> +  [ fib daddr oif => reg 1 ]

Instead of casting out the flag like this:

@@ -173,7 +173,7 @@  nftnl_expr_fib_snprintf_default(char *buf, size_t size,
 {
        struct nftnl_expr_fib *fib = nftnl_expr_data(e);
        int len = size, offset = 0, ret, i;
-       uint32_t flags = fib->flags;
+       uint32_t flags = fib->flags & ~NFTA_FIB_F_PRESENT;
        static const struct {
                int bit;
                const char *name;

I think it would be better if we have a different fib output for the
present case, eg.

        [ fib daddr oif present => reg 1 ]

So we can see from --debug=netlink this generates bytecode to check
the presence.

Same thing applies to:

# exthdr hbh exists
ip6 test-ip6 input
  [ exthdr load 1b @ 43 + 0 => reg 1 ]
  [ cmp eq reg 1 0x00000001 ]

Instead, I'd suggest something like:

  [ exthdr 43 present => reg 1 ]
  [ cmp eq reg 1 0x00000001 ]

You would need to send a follow up to amend test for 3/5, but that
should be no problem.

Thanks!

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [nft PATCH 5/5] doc: Document boolean type and applications
  2017-03-10 17:13 ` [nft PATCH 5/5] doc: Document boolean type and applications Phil Sutter
@ 2017-03-10 18:14   ` Pablo Neira Ayuso
  0 siblings, 0 replies; 10+ messages in thread
From: Pablo Neira Ayuso @ 2017-03-10 18:14 UTC (permalink / raw)
  To: Phil Sutter; +Cc: netfilter-devel

I can place this doc updates now, even if the fib part will be out of
sync for a little while until you follow up with the requested
changes. Or keep it back for a little while until we get this in sync.

Either way, I'll be fine, so let me know what you prefer.

Thanks.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [nft PATCH 4/5] fib: Support existence check
  2017-03-10 18:07   ` Pablo Neira Ayuso
@ 2017-03-10 21:41     ` Phil Sutter
  0 siblings, 0 replies; 10+ messages in thread
From: Phil Sutter @ 2017-03-10 21:41 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: netfilter-devel

Hi,

On Fri, Mar 10, 2017 at 07:07:25PM +0100, Pablo Neira Ayuso wrote:
> On Fri, Mar 10, 2017 at 06:13:52PM +0100, Phil Sutter wrote:
> [...]
> > diff --git a/tests/py/inet/fib.t.payload b/tests/py/inet/fib.t.payload
> > index f5258165384dc..e928a19649133 100644
> > --- a/tests/py/inet/fib.t.payload
> > +++ b/tests/py/inet/fib.t.payload
> > @@ -20,3 +20,13 @@ __map%d test-ip 0
> >  ip test-ip prerouting
> >    [ fib daddr . iif type => reg 1 ]
> >    [ lookup reg 1 set __map%d dreg 0 ]
> > +
> > +# fib daddr oif exists
> > +ip test-ip prerouting
> > +  [ fib daddr oif => reg 1 ]
> 
> Instead of casting out the flag like this:
> 
> @@ -173,7 +173,7 @@  nftnl_expr_fib_snprintf_default(char *buf, size_t size,
>  {
>         struct nftnl_expr_fib *fib = nftnl_expr_data(e);
>         int len = size, offset = 0, ret, i;
> -       uint32_t flags = fib->flags;
> +       uint32_t flags = fib->flags & ~NFTA_FIB_F_PRESENT;
>         static const struct {
>                 int bit;
>                 const char *name;
> 
> I think it would be better if we have a different fib output for the
> present case, eg.
> 
>         [ fib daddr oif present => reg 1 ]

Yes, this is a good point! Thanks for suggesting the output format - I
was tempted to adjust it but had no good idea and so left it as-is. And
indeed, exthdr netlink debug output hiding the existence check detail is
ugly as well.

I'll implement the missing bits and then respin, including the man page
patch - so no need to apply it now.

Thanks, Phil

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2017-03-10 21:41 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-10 17:13 [nft PATCH 0/5] Introduce boolean type and existence checks Phil Sutter
2017-03-10 17:13 ` [nft PATCH 1/5] Introduce boolean datatype and boolean expression Phil Sutter
2017-03-10 17:13 ` [nft PATCH 2/5] exthdr: Add support for exthdr specific flags Phil Sutter
2017-03-10 17:13 ` [nft PATCH 3/5] exthdr: Implement existence check Phil Sutter
2017-03-10 17:13 ` [nft PATCH 4/5] fib: Support " Phil Sutter
2017-03-10 18:07   ` Pablo Neira Ayuso
2017-03-10 21:41     ` Phil Sutter
2017-03-10 17:13 ` [nft PATCH 5/5] doc: Document boolean type and applications Phil Sutter
2017-03-10 18:14   ` Pablo Neira Ayuso
2017-03-10 18:02 ` [nft PATCH 0/5] Introduce boolean type and existence checks Pablo Neira Ayuso

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.