diff options
author | Phil Sutter <phil@nwl.cc> | 2018-03-16 00:03:19 +0100 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2018-03-16 09:58:39 +0100 |
commit | 6979625686ec8d915f5ad5fdc28f24f55b6be3f7 (patch) | |
tree | e358bb0c0335622f99c374386ba2f1d8d2dbf20d /src/netlink_delinearize.c | |
parent | 70b31b1ce73e704d4387b1262e8b97785ffe64f7 (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.c | 21 |
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 && |