From cc7b37d18a687d53e8724b3104b042e6767a9cef Mon Sep 17 00:00:00 2001 From: Anatole Denis Date: Thu, 24 Nov 2016 15:16:20 +0100 Subject: src: Interpret OP_NEQ against a set as OP_LOOKUP Now that the support for inverted matching is in the kernel and in libnftnl, add it to nftables too. This fixes bug #888 Signed-off-by: Anatole Denis Signed-off-by: Pablo Neira Ayuso --- src/evaluate.c | 14 ++++++++++++++ src/netlink_delinearize.c | 10 ++++++++++ src/netlink_linearize.c | 14 +++++++++----- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/evaluate.c b/src/evaluate.c index 51d644fe..c841aafd 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -1526,6 +1526,20 @@ static int expr_evaluate_relational(struct eval_ctx *ctx, struct expr **expr) if (byteorder_conversion(ctx, &rel->right, left->byteorder) < 0) return -1; break; + case EXPR_SET: + assert(rel->op == OP_NEQ); + right = rel->right = + implicit_set_declaration(ctx, "__set%d", + left->dtype, left->len, + right); + /* fall through */ + case EXPR_SET_REF: + assert(rel->op == OP_NEQ); + /* Data for range lookups needs to be in big endian order */ + if (right->set->flags & SET_F_INTERVAL && + byteorder_conversion(ctx, &rel->left, BYTEORDER_BIG_ENDIAN) < 0) + return -1; + break; default: BUG("invalid expression type %s\n", right->ops->name); } diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c index 0ebe3683..cb0f6ac7 100644 --- a/src/netlink_delinearize.c +++ b/src/netlink_delinearize.c @@ -292,6 +292,7 @@ static void netlink_parse_lookup(struct netlink_parse_ctx *ctx, const char *name; struct expr *expr, *left, *right; struct set *set; + uint32_t flag; name = nftnl_expr_get_str(nle, NFTNL_EXPR_LOOKUP_SET); set = set_lookup(ctx->table, name); @@ -323,6 +324,12 @@ static void netlink_parse_lookup(struct netlink_parse_ctx *ctx, expr = relational_expr_alloc(loc, OP_LOOKUP, left, right); } + if (nftnl_expr_is_set(nle, NFTNL_EXPR_LOOKUP_FLAGS)) { + flag = nftnl_expr_get_u32(nle, NFTNL_EXPR_LOOKUP_FLAGS); + if (flag & NFT_LOOKUP_F_INV) + expr->op = OP_NEQ; + } + ctx->stmt = expr_stmt_alloc(loc, expr); } @@ -1316,6 +1323,9 @@ static void ct_meta_common_postprocess(const struct expr *expr) struct expr *right = expr->right; switch (expr->op) { + case OP_NEQ: + if (right->ops->type != EXPR_SET && right->ops->type != EXPR_SET_REF) + break; case OP_LOOKUP: expr_set_type(right, left->dtype, left->byteorder); if (right->dtype == &integer_type) diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c index 2945392b..6bc0bee8 100644 --- a/src/netlink_linearize.c +++ b/src/netlink_linearize.c @@ -278,6 +278,8 @@ static void netlink_gen_lookup(struct netlink_linearize_ctx *ctx, expr->right->set->handle.set); nftnl_expr_set_u32(nle, NFTNL_EXPR_LOOKUP_SET_ID, expr->right->set->handle.set_id); + if (expr->op == OP_NEQ) + 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); @@ -346,13 +348,14 @@ static void netlink_gen_cmp(struct netlink_linearize_ctx *ctx, assert(dreg == NFT_REG_VERDICT); - if (expr->right->ops->type == EXPR_RANGE) - return netlink_gen_range(ctx, expr, dreg); - - sreg = get_register(ctx, expr->left); - switch (expr->right->ops->type) { + case EXPR_RANGE: + return netlink_gen_range(ctx, expr, dreg); + case EXPR_SET: + case EXPR_SET_REF: + return netlink_gen_lookup(ctx, expr, dreg); case EXPR_PREFIX: + sreg = get_register(ctx, expr->left); if (expr->left->dtype->type != TYPE_STRING) { len = div_round_up(expr->right->len, BITS_PER_BYTE); netlink_gen_expr(ctx, expr->left, sreg); @@ -365,6 +368,7 @@ static void netlink_gen_cmp(struct netlink_linearize_ctx *ctx, } break; default: + sreg = get_register(ctx, expr->left); len = div_round_up(expr->right->len, BITS_PER_BYTE); right = expr->right; netlink_gen_expr(ctx, expr->left, sreg); -- cgit v1.2.3