]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: Interpret OP_NEQ against a set as OP_LOOKUP
authorAnatole Denis <anatole@rezel.net>
Thu, 24 Nov 2016 14:16:20 +0000 (15:16 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Tue, 29 Nov 2016 21:49:01 +0000 (22:49 +0100)
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 <anatole@rezel.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/evaluate.c
src/netlink_delinearize.c
src/netlink_linearize.c

index 51d644fe55f912af8b7ebc19a30f18e28189f3ea..c841aafd98a01b2fc75733f0facc71c7026b9958 100644 (file)
@@ -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);
                }
index 0ebe368391bd5d2661d5fc1368b29da7db8276cb..cb0f6ac7b1a21101dc7fd570a63738af02789a57 100644 (file)
@@ -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)
index 2945392b1d8cee48f2f17a01bcd695897d6c19bc..6bc0bee8340d14ed8670c42a80c60577df1840bf 100644 (file)
@@ -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);