summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2016-09-20 19:25:25 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2016-10-17 17:55:56 +0200
commit3ed932917cc744b489bd2706a55a1778b0b50c0e (patch)
tree96f226969cab52a9c29510378612751713f78d98 /src
parentf55ccf9ea1061f8e50065c0cc6b3ed93523f0b97 (diff)
src: use new range expression for != [a,b] intervals
Use new range expression in the kernel to fix wrong bytecode generation. This patch also adjust tests so we don't hit problems there. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src')
-rw-r--r--src/netlink_delinearize.c45
-rw-r--r--src/netlink_linearize.c46
2 files changed, 66 insertions, 25 deletions
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 6bb27b6f..d8d1d7d7 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -186,6 +186,46 @@ static void netlink_parse_immediate(struct netlink_parse_ctx *ctx,
netlink_set_register(ctx, dreg, expr);
}
+static enum ops netlink_parse_range_op(const struct nftnl_expr *nle)
+{
+ switch (nftnl_expr_get_u32(nle, NFTNL_EXPR_RANGE_OP)) {
+ case NFT_RANGE_EQ:
+ return OP_EQ;
+ case NFT_RANGE_NEQ:
+ return OP_NEQ;
+ default:
+ return OP_INVALID;
+ }
+}
+
+static void netlink_parse_range(struct netlink_parse_ctx *ctx,
+ const struct location *loc,
+ const struct nftnl_expr *nle)
+{
+ struct expr *expr, *left, *right, *from, *to;
+ struct nft_data_delinearize nld;
+ enum nft_registers sreg;
+ enum ops op;
+
+ sreg = netlink_parse_register(nle, NFTNL_EXPR_RANGE_SREG);
+ left = netlink_get_register(ctx, loc, sreg);
+ if (left == NULL)
+ return netlink_error(ctx, loc,
+ "Relational expression has no left hand side");
+
+ op = netlink_parse_range_op(nle);
+
+ nld.value = nftnl_expr_get(nle, NFTNL_EXPR_RANGE_FROM_DATA, &nld.len);
+ from = netlink_alloc_value(loc, &nld);
+
+ nld.value = nftnl_expr_get(nle, NFTNL_EXPR_RANGE_TO_DATA, &nld.len);
+ to = netlink_alloc_value(loc, &nld);
+
+ right = range_expr_alloc(loc, from, to);
+ expr = relational_expr_alloc(loc, op, left, right);
+ ctx->stmt = expr_stmt_alloc(loc, expr);
+}
+
static enum ops netlink_parse_cmp_op(const struct nftnl_expr *nle)
{
switch (nftnl_expr_get_u32(nle, NFTNL_EXPR_CMP_OP)) {
@@ -1049,6 +1089,7 @@ static const struct {
{ .name = "counter", .parse = netlink_parse_counter },
{ .name = "log", .parse = netlink_parse_log },
{ .name = "limit", .parse = netlink_parse_limit },
+ { .name = "range", .parse = netlink_parse_range },
{ .name = "reject", .parse = netlink_parse_reject },
{ .name = "nat", .parse = netlink_parse_nat },
{ .name = "masq", .parse = netlink_parse_masq },
@@ -1363,6 +1404,10 @@ static void __binop_adjust(const struct expr *binop, struct expr *right,
}
}
break;
+ case EXPR_RANGE:
+ binop_adjust_one(binop, right->left, shift);
+ binop_adjust_one(binop, right->right, shift);
+ break;
default:
BUG("unknown expression type %s\n", right->ops->name);
break;
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 558deb23..0072dca0 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -368,45 +368,41 @@ static void netlink_gen_range(struct netlink_linearize_ctx *ctx,
sreg = get_register(ctx, expr->left);
netlink_gen_expr(ctx, expr->left, sreg);
- nle = alloc_nft_expr("cmp");
- netlink_put_register(nle, NFTNL_EXPR_CMP_SREG, sreg);
switch (expr->op) {
case OP_NEQ:
- nftnl_expr_set_u32(nle, NFTNL_EXPR_CMP_OP,
- netlink_gen_cmp_op(OP_LT));
+ nle = alloc_nft_expr("range");
+ netlink_put_register(nle, NFTNL_EXPR_RANGE_SREG, sreg);
+ nftnl_expr_set_u32(nle, NFTNL_EXPR_RANGE_OP, NFT_RANGE_NEQ);
+ netlink_gen_data(range->left, &nld);
+ nftnl_expr_set(nle, NFTNL_EXPR_RANGE_FROM_DATA,
+ nld.value, nld.len);
+ netlink_gen_data(range->right, &nld);
+ nftnl_expr_set(nle, NFTNL_EXPR_RANGE_TO_DATA,
+ nld.value, nld.len);
+ nftnl_rule_add_expr(ctx->nlr, nle);
break;
case OP_RANGE:
case OP_EQ:
+ nle = alloc_nft_expr("cmp");
+ netlink_put_register(nle, NFTNL_EXPR_CMP_SREG, sreg);
nftnl_expr_set_u32(nle, NFTNL_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);
- nftnl_expr_set(nle, NFTNL_EXPR_CMP_DATA, nld.value, nld.len);
- nftnl_rule_add_expr(ctx->nlr, nle);
+ netlink_gen_data(range->left, &nld);
+ nftnl_expr_set(nle, NFTNL_EXPR_CMP_DATA, nld.value, nld.len);
+ nftnl_rule_add_expr(ctx->nlr, nle);
- nle = alloc_nft_expr("cmp");
- netlink_put_register(nle, NFTNL_EXPR_CMP_SREG, sreg);
- switch (expr->op) {
- case OP_NEQ:
- nftnl_expr_set_u32(nle, NFTNL_EXPR_CMP_OP,
- netlink_gen_cmp_op(OP_GT));
- break;
- case OP_RANGE:
- case OP_EQ:
+ nle = alloc_nft_expr("cmp");
+ netlink_put_register(nle, NFTNL_EXPR_CMP_SREG, sreg);
nftnl_expr_set_u32(nle, NFTNL_EXPR_CMP_OP,
netlink_gen_cmp_op(OP_LTE));
+ netlink_gen_data(range->right, &nld);
+ nftnl_expr_set(nle, NFTNL_EXPR_CMP_DATA, nld.value, nld.len);
+ nftnl_rule_add_expr(ctx->nlr, nle);
break;
default:
BUG("invalid range operation %u\n", expr->op);
- }
- netlink_gen_data(range->right, &nld);
- nftnl_expr_set(nle, NFTNL_EXPR_CMP_DATA, nld.value, nld.len);
- nftnl_rule_add_expr(ctx->nlr, nle);
+ }
release_register(ctx, expr->left);
}