On 23 June 2016 at 09:32, Arturo Borrero Gonzalez <arturo.borrero.glez@xxxxxxxxx> wrote: > On 22 June 2016 at 20:22, Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx> 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. -- Arturo Borrero González
evaluate: add support for set lookups inversion From: Arturo Borrero Gonzalez <arturo.borrero.glez@xxxxxxxxx> Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@xxxxxxxxx> --- 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);