diff mbox

[nf-next,v4] netfilter: nf_tables: add support for inverted logic in nft_lookup

Message ID CAOkSjBhvhkoA9VTAZjMigSR2wgVo2Q6oKJi=WQCJt2Je9kt4rg@mail.gmail.com
State Changes Requested
Delegated to: Pablo Neira
Headers show

Commit Message

Arturo Borrero June 23, 2016, 8:39 a.m. UTC
On 23 June 2016 at 09:32, Arturo Borrero Gonzalez
<arturo.borrero.glez@gmail.com> wrote:
> On 22 June 2016 at 20:22, Pablo Neira Ayuso <pablo@netfilter.org> wrote:
>> On Wed, Jun 01, 2016 at 05:23:02PM +0200, Arturo Borrero Gonzalez wrote:
>>> Introduce a new configuration option for this expression, which allows users
>>> to invert the logic of set lookups.
>>
>> Any plan to add the missing nftables bits? Let me know, I would like
>> to have all the pieces in places so we can also add automated tests
>> for this.
>
> Eventually yes, but not in the short term.
>

BTW, if you would like to have it done now, I'm attaching the [half]
patch I developed back in May.

AFAIK, this patch implements the user-to-kernel path but the
kernel-to-user path was missing.
diff mbox

Patch

evaluate: add support for set lookups inversion

From: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>

Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
---
 include/expression.h      |    1 +
 src/evaluate.c            |   13 +++++++++++++
 src/expression.c          |    1 +
 src/netlink_delinearize.c |    9 +++++++++
 src/netlink_linearize.c   |    9 +++++++++
 5 files changed, 33 insertions(+)

diff --git a/include/expression.h b/include/expression.h
index 6e5e835..c6c6ef8 100644
--- a/include/expression.h
+++ b/include/expression.h
@@ -82,6 +82,7 @@  enum ops {
 	OP_FLAGCMP,
 	/* Set lookup */
 	OP_LOOKUP,
+	OP_LOOKUP_INV,
 	__OP_MAX
 };
 #define OP_MAX		(__OP_MAX - 1)
diff --git a/src/evaluate.c b/src/evaluate.c
index f24e5f3..e1faa79 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1350,6 +1350,17 @@  static int expr_evaluate_relational(struct eval_ctx *ctx, struct expr **expr)
 		return -1;
 	right = rel->right;
 
+	if (rel->op == OP_NEQ) {
+		switch (right->ops->type) {
+		case EXPR_SET:
+		case EXPR_SET_REF:
+			rel->op = OP_LOOKUP_INV;
+			break;
+		default:
+			break;
+		}
+	}
+
 	if (rel->op == OP_IMPLICIT) {
 		switch (right->ops->type) {
 		case EXPR_RANGE:
@@ -1372,6 +1383,7 @@  static int expr_evaluate_relational(struct eval_ctx *ctx, struct expr **expr)
 		}
 	}
 
+
 	if (!expr_is_constant(right))
 		return expr_binary_error(ctx->msgs, right, rel,
 					 "Right hand side of relational "
@@ -1385,6 +1397,7 @@  static int expr_evaluate_relational(struct eval_ctx *ctx, struct expr **expr)
 
 	switch (rel->op) {
 	case OP_LOOKUP:
+	case OP_LOOKUP_INV:
 		switch (right->ops->type) {
 		case EXPR_SET:
 			/* A literal set expression implicitly declares
diff --git a/src/expression.c b/src/expression.c
index a10af5d..5d6d6b3 100644
--- a/src/expression.c
+++ b/src/expression.c
@@ -451,6 +451,7 @@  const char *expr_op_symbols[] = {
 	[OP_GTE]	= ">=",
 	[OP_RANGE]	= "within range",
 	[OP_LOOKUP]	= NULL,
+	[OP_LOOKUP_INV]	= "!=",
 };
 
 static void unary_expr_print(const struct expr *expr)
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 7735699..35bad01 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -259,6 +259,7 @@  static void netlink_parse_lookup(struct netlink_parse_ctx *ctx,
 	const char *name;
 	struct expr *expr, *left, *right;
 	struct set *set;
+	uint32_t flags;
 
 	name = nftnl_expr_get_str(nle, NFTNL_EXPR_LOOKUP_SET);
 	set  = set_lookup(ctx->table, name);
@@ -281,13 +282,20 @@  static void netlink_parse_lookup(struct netlink_parse_ctx *ctx,
 
 	right = set_ref_expr_alloc(loc, set);
 
+	flags = nftnl_expr_get_u32(nle, NFTNL_EXPR_LOOKUP_FLAGS);
+
 	if (nftnl_expr_is_set(nle, NFTNL_EXPR_LOOKUP_DREG)) {
 		dreg = netlink_parse_register(nle, NFTNL_EXPR_LOOKUP_DREG);
 		expr = map_expr_alloc(loc, left, right);
+		if (flags & NFT_LOOKUP_F_INV)
+			expr->op = OP_LOOKUP_INV;
+
 		if (dreg != NFT_REG_VERDICT)
 			return netlink_set_register(ctx, dreg, expr);
 	} else {
 		expr = relational_expr_alloc(loc, OP_LOOKUP, left, right);
+		if (flags & NFT_LOOKUP_F_INV)
+			expr->op = OP_LOOKUP_INV;
 	}
 
 	ctx->stmt = expr_stmt_alloc(loc, expr);
@@ -1168,6 +1176,7 @@  static void ct_meta_common_postprocess(const struct expr *expr)
 
 	switch (expr->op) {
 	case OP_LOOKUP:
+	case OP_LOOKUP_INV:
 		expr_set_type(right, left->dtype, left->byteorder);
 		if (right->dtype == &integer_type)
 			integer_type_postprocess(right);
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 01a85d0..f6f608c 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -191,6 +191,10 @@  static void netlink_gen_map(struct netlink_linearize_ctx *ctx,
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_LOOKUP_SET_ID,
 			   expr->mappings->set->handle.set_id);
 
+	if (expr->op == OP_LOOKUP_INV)
+		nftnl_expr_set_u32(nle, NFTNL_EXPR_LOOKUP_FLAGS,
+				   NFT_LOOKUP_F_INV);
+
 	if (dreg == NFT_REG_VERDICT)
 		release_register(ctx, expr->map);
 
@@ -217,6 +221,10 @@  static void netlink_gen_lookup(struct netlink_linearize_ctx *ctx,
 	nftnl_expr_set_u32(nle, NFTNL_EXPR_LOOKUP_SET_ID,
 			   expr->right->set->handle.set_id);
 
+	if (expr->op == OP_LOOKUP_INV)
+		nftnl_expr_set_u32(nle, NFTNL_EXPR_LOOKUP_FLAGS,
+				   NFT_LOOKUP_F_INV);
+
 	release_register(ctx, expr->left);
 	nftnl_rule_add_expr(ctx->nlr, nle);
 }
@@ -433,6 +441,7 @@  static void netlink_gen_relational(struct netlink_linearize_ctx *ctx,
 	case OP_FLAGCMP:
 		return netlink_gen_flagcmp(ctx, expr, dreg);
 	case OP_LOOKUP:
+	case OP_LOOKUP_INV:
 		return netlink_gen_lookup(ctx, expr, dreg);
 	default:
 		BUG("invalid relational operation %u\n", expr->op);