diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2021-02-01 22:21:41 +0100 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2021-02-05 13:38:20 +0100 |
commit | e6c32b2fa0b820bc81cbb99e8ed601eabbbfac69 (patch) | |
tree | 47e56d582bde34804b3913716a6c7745faa3c582 /src | |
parent | 0c189656148d834b17aa9d98b0b11018bc9d2465 (diff) |
src: add negation match on singleton bitmask value
This patch provides a shortcut for:
ct status and dnat == 0
which allows to check for the packet whose dnat bit is unset:
# nft add rule x y ct status ! dnat counter
This operation is only available for expression with a bitmask basetype, eg.
# nft describe ct status
ct expression, datatype ct_status (conntrack status) (basetype bitmask, integer), 32 bits
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/evaluate.c | 8 | ||||
-rw-r--r-- | src/expression.c | 1 | ||||
-rw-r--r-- | src/netlink_delinearize.c | 14 | ||||
-rw-r--r-- | src/netlink_linearize.c | 9 | ||||
-rw-r--r-- | src/parser_bison.y | 1 |
5 files changed, 28 insertions, 5 deletions
diff --git a/src/evaluate.c b/src/evaluate.c index ccee7e21..030bbde4 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -1958,6 +1958,14 @@ static int expr_evaluate_relational(struct eval_ctx *ctx, struct expr **expr) /* fall through */ case OP_NEQ: + case OP_NEG: + if (rel->op == OP_NEG && + (right->etype != EXPR_VALUE || + right->dtype->basetype == NULL || + right->dtype->basetype->type != TYPE_BITMASK)) + return expr_binary_error(ctx->msgs, left, right, + "negation can only be used with singleton bitmask values"); + switch (right->etype) { case EXPR_RANGE: if (byteorder_conversion(ctx, &rel->left, BYTEORDER_BIG_ENDIAN) < 0) diff --git a/src/expression.c b/src/expression.c index 58d73e95..a90a89ca 100644 --- a/src/expression.c +++ b/src/expression.c @@ -560,6 +560,7 @@ const char *expr_op_symbols[] = { [OP_GT] = ">", [OP_LTE] = "<=", [OP_GTE] = ">=", + [OP_NEG] = "!", }; static void unary_expr_print(const struct expr *expr, struct output_ctx *octx) diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c index 04560b97..7cd7d403 100644 --- a/src/netlink_delinearize.c +++ b/src/netlink_delinearize.c @@ -2167,7 +2167,7 @@ static void relational_binop_postprocess(struct rule_pp_ctx *ctx, struct expr *e { struct expr *binop = expr->left, *value = expr->right; - if (binop->op == OP_AND && expr->op == OP_NEQ && + if (binop->op == OP_AND && (expr->op == OP_NEQ || expr->op == OP_EQ) && value->dtype->basetype && value->dtype->basetype->type == TYPE_BITMASK && !mpz_cmp_ui(value->value, 0)) { @@ -2180,8 +2180,16 @@ static void relational_binop_postprocess(struct rule_pp_ctx *ctx, struct expr *e expr->left = expr_get(binop->left); expr->right = binop_tree_to_list(NULL, binop->right); - expr->op = OP_IMPLICIT; - + switch (expr->op) { + case OP_NEQ: + expr->op = OP_IMPLICIT; + break; + case OP_EQ: + expr->op = OP_NEG; + break; + default: + BUG("unknown operation type %d\n", expr->op); + } expr_free(binop); } else if (binop->left->dtype->flags & DTYPE_F_PREFIX && binop->op == OP_AND && expr->right->etype == EXPR_VALUE && diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c index f1b3ff69..21bc492e 100644 --- a/src/netlink_linearize.c +++ b/src/netlink_linearize.c @@ -490,7 +490,11 @@ static void netlink_gen_flagcmp(struct netlink_linearize_ctx *ctx, nle = alloc_nft_expr("cmp"); netlink_put_register(nle, NFTNL_EXPR_CMP_SREG, sreg); - nftnl_expr_set_u32(nle, NFTNL_EXPR_CMP_OP, NFT_CMP_NEQ); + if (expr->op == OP_NEG) + nftnl_expr_set_u32(nle, NFTNL_EXPR_CMP_OP, NFT_CMP_EQ); + else + nftnl_expr_set_u32(nle, NFTNL_EXPR_CMP_OP, NFT_CMP_NEQ); + nftnl_expr_set(nle, NFTNL_EXPR_CMP_DATA, nld.value, nld.len); nft_rule_add_expr(ctx, nle, &expr->location); @@ -518,6 +522,7 @@ static void netlink_gen_relational(struct netlink_linearize_ctx *ctx, case OP_GT: case OP_LTE: case OP_GTE: + case OP_NEG: break; default: BUG("invalid relational operation %u\n", expr->op); @@ -547,7 +552,7 @@ static void netlink_gen_relational(struct netlink_linearize_ctx *ctx, } break; default: - if (expr->op == OP_IMPLICIT && + if ((expr->op == OP_IMPLICIT || expr->op == OP_NEG) && expr->right->dtype->basetype != NULL && expr->right->dtype->basetype->type == TYPE_BITMASK) return netlink_gen_flagcmp(ctx, expr, dreg); diff --git a/src/parser_bison.y b/src/parser_bison.y index 519e8efe..11e899ff 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -4639,6 +4639,7 @@ relational_op : EQ { $$ = OP_EQ; } | GT { $$ = OP_GT; } | GTE { $$ = OP_GTE; } | LTE { $$ = OP_LTE; } + | NOT { $$ = OP_NEG; } ; verdict_expr : ACCEPT |