summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorÁlvaro Neira Ayuso <alvaroneay@gmail.com>2014-05-28 12:08:22 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2014-06-05 16:55:01 +0200
commitc000b14c35bf7722225a334ea3461976e78561dd (patch)
treebd7623b217aafd44c44372e9621fc6f69741bbe9
parent0c512cf7f26363713b8c76a6a826e2401e21907f (diff)
netlink: Allow to invert the ranges
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>
-rw-r--r--src/netlink_linearize.c45
1 files changed, 39 insertions, 6 deletions
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index e3f06afe..19153fd7 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -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);