summaryrefslogtreecommitdiffstats
path: root/src/netlink_delinearize.c
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2018-03-16 00:03:19 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2018-03-16 09:58:39 +0100
commit6979625686ec8d915f5ad5fdc28f24f55b6be3f7 (patch)
treee358bb0c0335622f99c374386ba2f1d8d2dbf20d /src/netlink_delinearize.c
parent70b31b1ce73e704d4387b1262e8b97785ffe64f7 (diff)
relational: Eliminate meta OPs
With a bit of code reorganization, relational meta OPs OP_RANGE, OP_FLAGCMP and OP_LOOKUP become unused and can be removed. The only meta OP left is OP_IMPLICIT which is usually treated as alias to OP_EQ. Though it needs to stay in place for one reason: When matching against a bitmask (e.g. TCP flags or conntrack states), it has a different meaning: | nft --debug=netlink add rule ip t c tcp flags syn | ip t c | [ meta load l4proto => reg 1 ] | [ cmp eq reg 1 0x00000006 ] | [ payload load 1b @ transport header + 13 => reg 1 ] | [ bitwise reg 1 = (reg=1 & 0x00000002 ) ^ 0x00000000 ] | [ cmp neq reg 1 0x00000000 ] | nft --debug=netlink add rule ip t c tcp flags == syn | ip t c | [ meta load l4proto => reg 1 ] | [ cmp eq reg 1 0x00000006 ] | [ payload load 1b @ transport header + 13 => reg 1 ] | [ cmp eq reg 1 0x00000002 ] OP_IMPLICIT creates a match which just checks the given flag is present, while OP_EQ creates a match which ensures the given flag and no other is present. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/netlink_delinearize.c')
-rw-r--r--src/netlink_delinearize.c21
1 files changed, 9 insertions, 12 deletions
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index d225b3e4..997fb53b 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -323,7 +323,7 @@ static void netlink_parse_lookup(struct netlink_parse_ctx *ctx,
if (dreg != NFT_REG_VERDICT)
return netlink_set_register(ctx, dreg, expr);
} else {
- expr = relational_expr_alloc(loc, OP_LOOKUP, left, right);
+ expr = relational_expr_alloc(loc, OP_EQ, left, right);
}
if (nftnl_expr_is_set(nle, NFTNL_EXPR_LOOKUP_FLAGS)) {
@@ -1524,9 +1524,14 @@ static void ct_meta_common_postprocess(struct rule_pp_ctx *ctx,
const struct expr *left = expr->left;
struct expr *right = expr->right;
+ if (right->ops->type == EXPR_SET || right->ops->type == EXPR_SET_REF)
+ expr_set_type(right, left->dtype, left->byteorder);
+
switch (expr->op) {
case OP_EQ:
- if (expr->right->ops->type == EXPR_RANGE)
+ if (expr->right->ops->type == EXPR_RANGE ||
+ expr->right->ops->type == EXPR_SET ||
+ expr->right->ops->type == EXPR_SET_REF)
break;
relational_expr_pctx_update(&ctx->pctx, expr);
@@ -1543,14 +1548,6 @@ static void ct_meta_common_postprocess(struct rule_pp_ctx *ctx,
payload_dependency_store(&ctx->pdctx, ctx->stmt, base);
}
break;
- case OP_NEQ:
- if (right->ops->type != EXPR_SET && right->ops->type != EXPR_SET_REF)
- break;
- /* fall through */
- case OP_LOOKUP:
- expr_set_type(right, left->dtype, left->byteorder);
- break;
-
default:
break;
}
@@ -1729,13 +1726,13 @@ static void relational_binop_postprocess(struct rule_pp_ctx *ctx, struct expr *e
/* Flag comparison: data & flags != 0
*
* Split the flags into a list of flag values and convert the
- * op to OP_FLAGCMP.
+ * op to OP_EQ.
*/
expr_free(value);
expr->left = expr_get(binop->left);
expr->right = binop_tree_to_list(NULL, binop->right);
- expr->op = OP_FLAGCMP;
+ expr->op = OP_EQ;
expr_free(binop);
} else if (binop->left->dtype->flags & DTYPE_F_PREFIX &&