diff options
author | Jeremy Sowden <jeremy@azazel.net> | 2022-04-04 13:13:47 +0100 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2023-02-07 12:40:18 +0100 |
commit | b3d4028a27edff0684a47356b13da494f7ec08ff (patch) | |
tree | 215589ec7a4a56434407788f489932cb3913f0bd | |
parent | 9be404a153bc9525d52afabed622843717c37851 (diff) |
netlink_delinearize: add postprocessing for payload binops
If a user uses a payload expression as a statement argument:
nft add rule t c meta mark set ip dscp lshift 2 or 0x10
we may need to undo munging during delinearization.
Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
-rw-r--r-- | src/netlink_delinearize.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c index 4cd6cc3a..f4ab476e 100644 --- a/src/netlink_delinearize.c +++ b/src/netlink_delinearize.c @@ -2603,6 +2603,42 @@ static void relational_binop_postprocess(struct rule_pp_ctx *ctx, } } +static bool payload_binop_postprocess(struct rule_pp_ctx *ctx, + struct expr **exprp) +{ + struct expr *expr = *exprp; + + if (expr->op != OP_RSHIFT) + return false; + + if (expr->left->etype == EXPR_UNARY) { + /* + * If the payload value was originally in a different byte-order + * from the payload expression, there will be a byte-order + * conversion to remove. + */ + struct expr *left = expr_get(expr->left->arg); + expr_free(expr->left); + expr->left = left; + } + + if (expr->left->etype != EXPR_BINOP || expr->left->op != OP_AND) + return false; + + if (expr->left->left->etype != EXPR_PAYLOAD) + return false; + + expr_set_type(expr->right, &integer_type, + BYTEORDER_HOST_ENDIAN); + expr_postprocess(ctx, &expr->right); + + binop_postprocess(ctx, expr, &expr->left); + *exprp = expr_get(expr->left); + expr_free(expr); + + return true; +} + static struct expr *string_wildcard_expr_alloc(struct location *loc, const struct expr *mask, const struct expr *expr) @@ -2723,6 +2759,9 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp) expr_set_type(expr, expr->arg->dtype, !expr->arg->byteorder); break; case EXPR_BINOP: + if (payload_binop_postprocess(ctx, exprp)) + break; + expr_postprocess(ctx, &expr->left); switch (expr->op) { case OP_LSHIFT: |