summaryrefslogtreecommitdiffstats
path: root/src/evaluate.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/evaluate.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/evaluate.c')
-rw-r--r--src/evaluate.c114
1 files changed, 17 insertions, 97 deletions
diff --git a/src/evaluate.c b/src/evaluate.c
index b71b67b9..114c831f 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1565,28 +1565,6 @@ static int expr_evaluate_relational(struct eval_ctx *ctx, struct expr **expr)
return -1;
right = rel->right;
- if (rel->op == OP_IMPLICIT) {
- switch (right->ops->type) {
- case EXPR_RANGE:
- rel->op = OP_RANGE;
- break;
- case EXPR_SET:
- case EXPR_SET_REF:
- rel->op = OP_LOOKUP;
- break;
- case EXPR_LIST:
- rel->op = OP_FLAGCMP;
- break;
- default:
- if (right->dtype->basetype != NULL &&
- right->dtype->basetype->type == TYPE_BITMASK)
- rel->op = OP_FLAGCMP;
- else
- rel->op = OP_EQ;
- break;
- }
- }
-
if (!expr_is_constant(right))
return expr_binary_error(ctx->msgs, right, rel,
"Right hand side of relational "
@@ -1598,56 +1576,34 @@ static int expr_evaluate_relational(struct eval_ctx *ctx, struct expr **expr)
"constant value",
expr_op_symbols[rel->op]);
+ if (!datatype_equal(left->dtype, right->dtype))
+ return expr_binary_error(ctx->msgs, right, left,
+ "datatype mismatch, expected %s, "
+ "expression has type %s",
+ left->dtype->desc,
+ right->dtype->desc);
+
switch (rel->op) {
- case OP_LOOKUP:
- /* A literal set expression implicitly declares the set */
- if (right->ops->type == EXPR_SET)
- right = rel->right =
- implicit_set_declaration(ctx, "__set%d",
- left, right);
- else if (!datatype_equal(left->dtype, right->dtype))
- return expr_binary_error(ctx->msgs, right, left,
- "datatype mismatch, expected %s, "
- "set has type %s",
- left->dtype->desc,
- right->dtype->desc);
-
- /* Data for range lookups needs to be in big endian order */
- if (right->set->flags & NFT_SET_INTERVAL &&
- byteorder_conversion(ctx, &rel->left,
- BYTEORDER_BIG_ENDIAN) < 0)
- return -1;
- left = rel->left;
- break;
case OP_EQ:
- if (!datatype_equal(left->dtype, right->dtype))
- return expr_binary_error(ctx->msgs, right, left,
- "datatype mismatch, expected %s, "
- "expression has type %s",
- left->dtype->desc,
- right->dtype->desc);
+ case OP_IMPLICIT:
/*
* Update protocol context for payload and meta iiftype
* equality expressions.
*/
- relational_expr_pctx_update(&ctx->pctx, rel);
-
- if (left->ops->type == EXPR_CONCAT)
- return 0;
+ if (expr_is_singleton(right))
+ relational_expr_pctx_update(&ctx->pctx, rel);
/* fall through */
case OP_NEQ:
- case OP_FLAGCMP:
- if (!datatype_equal(left->dtype, right->dtype))
- return expr_binary_error(ctx->msgs, right, left,
- "datatype mismatch, expected %s, "
- "expression has type %s",
- left->dtype->desc,
- right->dtype->desc);
-
switch (right->ops->type) {
case EXPR_RANGE:
- goto range;
+ if (byteorder_conversion(ctx, &rel->left, BYTEORDER_BIG_ENDIAN) < 0)
+ return -1;
+ if (byteorder_conversion(ctx, &right->left, BYTEORDER_BIG_ENDIAN) < 0)
+ return -1;
+ if (byteorder_conversion(ctx, &right->right, BYTEORDER_BIG_ENDIAN) < 0)
+ return -1;
+ break;
case EXPR_PREFIX:
if (byteorder_conversion(ctx, &right->prefix, left->byteorder) < 0)
return -1;
@@ -1657,12 +1613,10 @@ static int expr_evaluate_relational(struct eval_ctx *ctx, struct expr **expr)
return -1;
break;
case EXPR_SET:
- assert(rel->op == OP_NEQ);
right = rel->right =
implicit_set_declaration(ctx, "__set%d", left, right);
/* fall through */
case EXPR_SET_REF:
- assert(rel->op == OP_NEQ);
/* Data for range lookups needs to be in big endian order */
if (right->set->flags & NFT_SET_INTERVAL &&
byteorder_conversion(ctx, &rel->left, BYTEORDER_BIG_ENDIAN) < 0)
@@ -1676,13 +1630,6 @@ static int expr_evaluate_relational(struct eval_ctx *ctx, struct expr **expr)
case OP_GT:
case OP_LTE:
case OP_GTE:
- if (!datatype_equal(left->dtype, right->dtype))
- return expr_binary_error(ctx->msgs, right, left,
- "datatype mismatch, expected %s, "
- "expression has type %s",
- left->dtype->desc,
- right->dtype->desc);
-
switch (left->ops->type) {
case EXPR_CONCAT:
return expr_binary_error(ctx->msgs, left, rel,
@@ -1706,33 +1653,6 @@ static int expr_evaluate_relational(struct eval_ctx *ctx, struct expr **expr)
if (byteorder_conversion(ctx, &rel->right, BYTEORDER_BIG_ENDIAN) < 0)
return -1;
break;
- case OP_RANGE:
- if (!datatype_equal(left->dtype, right->dtype))
- return expr_binary_error(ctx->msgs, right, left,
- "datatype mismatch, expected %s, "
- "expression has type %s",
- left->dtype->desc,
- right->dtype->desc);
-
-range:
- switch (left->ops->type) {
- case EXPR_CONCAT:
- return expr_binary_error(ctx->msgs, left, rel,
- "Relational expression (%s) is undefined"
- "for %s expressions",
- expr_op_symbols[rel->op],
- left->ops->name);
- default:
- break;
- }
-
- if (byteorder_conversion(ctx, &rel->left, BYTEORDER_BIG_ENDIAN) < 0)
- return -1;
- if (byteorder_conversion(ctx, &right->left, BYTEORDER_BIG_ENDIAN) < 0)
- return -1;
- if (byteorder_conversion(ctx, &right->right, BYTEORDER_BIG_ENDIAN) < 0)
- return -1;
- break;
default:
BUG("invalid relational operation %u\n", rel->op);
}