From 3ed932917cc744b489bd2706a55a1778b0b50c0e Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 20 Sep 2016 19:25:25 +0200 Subject: 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 --- src/netlink_delinearize.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ src/netlink_linearize.c | 46 +++++++++++++++++++++------------------------- 2 files changed, 66 insertions(+), 25 deletions(-) (limited to 'src') 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); } -- cgit v1.2.3