]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
netlink: Allow to invert the ranges
authorÁlvaro Neira Ayuso <alvaroneay@gmail.com>
Wed, 28 May 2014 10:08:22 +0000 (12:08 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 5 Jun 2014 14:55:01 +0000 (16:55 +0200)
This patch fix the bug:

http://bugzilla.netfilter.org/show_bug.cgi?id=924

Before, nftables doesn't permit invert ranges. This patch allows
add rules like this:

nft add rule ip test input ip daddr != 192.168.1.2-192.168.1.55
or
nft add rule ip test input ip daddr == 192.168.1.2-192.168.1.55

Also, we still have the option for adding rules like this:

sudo nft add rule ip test output frag id 33-45

Signed-off-by: Alvaro Neira Ayuso <alvaroneay@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/netlink_linearize.c

index e3f06afe59dbf9e71127cb7c53d5e2d10863954a..19153fd753951ccd7cb7456073d4c91fbd2b4dea 100644 (file)
@@ -182,6 +182,10 @@ static enum nft_cmp_ops netlink_gen_cmp_op(enum ops op)
        }
 }
 
+static void netlink_gen_range(struct netlink_linearize_ctx *ctx,
+                             const struct expr *expr,
+                             enum nft_registers dreg);
+
 static void netlink_gen_cmp(struct netlink_linearize_ctx *ctx,
                            const struct expr *expr,
                            enum nft_registers dreg)
@@ -196,7 +200,8 @@ static void netlink_gen_cmp(struct netlink_linearize_ctx *ctx,
        sreg = get_register(ctx);
        netlink_gen_expr(ctx, expr->left, sreg);
 
-       if (expr->right->ops->type == EXPR_PREFIX) {
+       switch (expr->right->ops->type) {
+       case EXPR_PREFIX: {
                mpz_t mask;
 
                mpz_init(mask);
@@ -216,7 +221,11 @@ static void netlink_gen_cmp(struct netlink_linearize_ctx *ctx,
                nft_rule_add_expr(ctx->nlr, nle);
 
                right = expr->right->prefix;
-       } else {
+               break;
+               }
+       case EXPR_RANGE:
+               return netlink_gen_range(ctx, expr, dreg);
+       default:
                right = expr->right;
        }
 
@@ -247,16 +256,40 @@ static void netlink_gen_range(struct netlink_linearize_ctx *ctx,
 
        nle = alloc_nft_expr("cmp");
        nft_rule_expr_set_u32(nle, NFT_EXPR_CMP_SREG, sreg);
-       nft_rule_expr_set_u32(nle, NFT_EXPR_CMP_OP,
-                             netlink_gen_cmp_op(OP_GTE));
+       switch (expr->op) {
+       case OP_NEQ:
+               nft_rule_expr_set_u32(nle, NFT_EXPR_CMP_OP,
+                                     netlink_gen_cmp_op(OP_LT));
+               break;
+       case OP_RANGE:
+       case OP_EQ:
+               nft_rule_expr_set_u32(nle, NFT_EXPR_CMP_OP,
+                                     netlink_gen_cmp_op(OP_GTE));
+               break;
+       default:
+               BUG("invalid range operation %u\n", expr->op);
+       }
+
        netlink_gen_data(range->left, &nld);
        nft_rule_expr_set(nle, NFT_EXPR_CMP_DATA, nld.value, nld.len);
        nft_rule_add_expr(ctx->nlr, nle);
 
        nle = alloc_nft_expr("cmp");
        nft_rule_expr_set_u32(nle, NFT_EXPR_CMP_SREG, sreg);
-       nft_rule_expr_set_u32(nle, NFT_EXPR_CMP_OP,
-                             netlink_gen_cmp_op(OP_LTE));
+       switch (expr->op) {
+       case OP_NEQ:
+               nft_rule_expr_set_u32(nle, NFT_EXPR_CMP_OP,
+                                     netlink_gen_cmp_op(OP_GT));
+               break;
+       case OP_RANGE:
+       case OP_EQ:
+               nft_rule_expr_set_u32(nle, NFT_EXPR_CMP_OP,
+                                     netlink_gen_cmp_op(OP_LTE));
+               break;
+       default:
+               BUG("invalid range operation %u\n", expr->op);
+       }
+
        netlink_gen_data(range->right, &nld);
        nft_rule_expr_set(nle, NFT_EXPR_CMP_DATA, nld.value, nld.len);
        nft_rule_add_expr(ctx->nlr, nle);