summaryrefslogtreecommitdiffstats
path: root/src/netlink_delinearize.c
diff options
context:
space:
mode:
authorJeremy Sowden <jeremy@azazel.net>2022-04-04 13:13:47 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2023-02-07 12:40:18 +0100
commitb3d4028a27edff0684a47356b13da494f7ec08ff (patch)
tree215589ec7a4a56434407788f489932cb3913f0bd /src/netlink_delinearize.c
parent9be404a153bc9525d52afabed622843717c37851 (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>
Diffstat (limited to 'src/netlink_delinearize.c')
-rw-r--r--src/netlink_delinearize.c39
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: