160 lines
5.0 KiB
Diff
160 lines
5.0 KiB
Diff
From 29f041b93d7fc4e23c62c2e2e3cbbeaafa83b4ef Mon Sep 17 00:00:00 2001
|
|
From: Phil Sutter <psutter@redhat.com>
|
|
Date: Thu, 9 Feb 2023 10:27:57 +0100
|
|
Subject: [PATCH] netlink_delinearize: postprocess binary ands in
|
|
concatenations
|
|
|
|
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2094887
|
|
Upstream Status: nftables commit 89688c947efc3
|
|
|
|
commit 89688c947efc36d25c58c85650414fa3a491732e
|
|
Author: Florian Westphal <fw@strlen.de>
|
|
Date: Tue Jun 14 21:56:48 2022 +0200
|
|
|
|
netlink_delinearize: postprocess binary ands in concatenations
|
|
|
|
Input:
|
|
update ether saddr . vlan id timeout 5s @macset
|
|
ether saddr . vlan id @macset
|
|
|
|
Before this patch, gets rendered as:
|
|
update @macset { @ll,48,48 . @ll,112,16 & 0xfff timeout 5s }
|
|
@ll,48,48 . @ll,112,16 & 0xfff @macset
|
|
|
|
After this, listing will show:
|
|
update @macset { @ll,48,48 . vlan id timeout 5s }
|
|
@ll,48,48 . vlan id @macset
|
|
|
|
The @ll, ... is due to vlan description replacing the ethernet one,
|
|
so payload decode fails to take the concatenation apart (the ethernet
|
|
header payload info is matched vs. vlan template).
|
|
|
|
This will be adjusted by a followup patch.
|
|
|
|
Signed-off-by: Florian Westphal <fw@strlen.de>
|
|
|
|
Signed-off-by: Phil Sutter <psutter@redhat.com>
|
|
---
|
|
include/netlink.h | 6 ++++++
|
|
src/netlink_delinearize.c | 45 ++++++++++++++++++++++++++++++++++-----
|
|
2 files changed, 46 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/include/netlink.h b/include/netlink.h
|
|
index e8e0f68..71c888f 100644
|
|
--- a/include/netlink.h
|
|
+++ b/include/netlink.h
|
|
@@ -42,10 +42,16 @@ struct netlink_parse_ctx {
|
|
struct netlink_ctx *nlctx;
|
|
};
|
|
|
|
+
|
|
+#define RULE_PP_IN_CONCATENATION (1 << 0)
|
|
+
|
|
+#define RULE_PP_REMOVE_OP_AND (RULE_PP_IN_CONCATENATION)
|
|
+
|
|
struct rule_pp_ctx {
|
|
struct proto_ctx pctx;
|
|
struct payload_dep_ctx pdctx;
|
|
struct stmt *stmt;
|
|
+ unsigned int flags;
|
|
};
|
|
|
|
extern const struct input_descriptor indesc_netlink;
|
|
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
|
|
index 2f13990..cba419d 100644
|
|
--- a/src/netlink_delinearize.c
|
|
+++ b/src/netlink_delinearize.c
|
|
@@ -2259,12 +2259,13 @@ static void binop_adjust(const struct expr *binop, struct expr *right,
|
|
}
|
|
}
|
|
|
|
-static void binop_postprocess(struct rule_pp_ctx *ctx, struct expr *expr,
|
|
- struct expr **expr_binop)
|
|
+static void __binop_postprocess(struct rule_pp_ctx *ctx,
|
|
+ struct expr *expr,
|
|
+ struct expr *left,
|
|
+ struct expr *mask,
|
|
+ struct expr **expr_binop)
|
|
{
|
|
struct expr *binop = *expr_binop;
|
|
- struct expr *left = binop->left;
|
|
- struct expr *mask = binop->right;
|
|
unsigned int shift;
|
|
|
|
assert(binop->etype == EXPR_BINOP);
|
|
@@ -2300,15 +2301,26 @@ static void binop_postprocess(struct rule_pp_ctx *ctx, struct expr *expr,
|
|
|
|
assert(binop->left == left);
|
|
*expr_binop = expr_get(left);
|
|
- expr_free(binop);
|
|
|
|
if (left->etype == EXPR_PAYLOAD)
|
|
payload_match_postprocess(ctx, expr, left);
|
|
else if (left->etype == EXPR_EXTHDR && right)
|
|
expr_set_type(right, left->dtype, left->byteorder);
|
|
+
|
|
+ expr_free(binop);
|
|
}
|
|
}
|
|
|
|
+static void binop_postprocess(struct rule_pp_ctx *ctx, struct expr *expr,
|
|
+ struct expr **expr_binop)
|
|
+{
|
|
+ struct expr *binop = *expr_binop;
|
|
+ struct expr *left = binop->left;
|
|
+ struct expr *mask = binop->right;
|
|
+
|
|
+ __binop_postprocess(ctx, expr, left, mask, expr_binop);
|
|
+}
|
|
+
|
|
static void map_binop_postprocess(struct rule_pp_ctx *ctx, struct expr *expr)
|
|
{
|
|
struct expr *binop = expr->map;
|
|
@@ -2541,6 +2553,7 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp)
|
|
LIST_HEAD(tmp);
|
|
struct expr *n;
|
|
|
|
+ ctx->flags |= RULE_PP_IN_CONCATENATION;
|
|
list_for_each_entry_safe(i, n, &expr->expressions, list) {
|
|
if (type) {
|
|
dtype = concat_subtype_lookup(type, --off);
|
|
@@ -2552,6 +2565,7 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp)
|
|
|
|
ntype = concat_subtype_add(ntype, i->dtype->type);
|
|
}
|
|
+ ctx->flags &= ~RULE_PP_IN_CONCATENATION;
|
|
list_splice(&tmp, &expr->expressions);
|
|
datatype_set(expr, concat_type_alloc(ntype));
|
|
break;
|
|
@@ -2568,6 +2582,27 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp)
|
|
expr_set_type(expr->right, &integer_type,
|
|
BYTEORDER_HOST_ENDIAN);
|
|
break;
|
|
+ case OP_AND:
|
|
+ expr_set_type(expr->right, expr->left->dtype,
|
|
+ expr->left->byteorder);
|
|
+
|
|
+ /* Do not process OP_AND in ordinary rule context.
|
|
+ *
|
|
+ * Removal needs to be performed as part of the relational
|
|
+ * operation because the RHS constant might need to be adjusted
|
|
+ * (shifted).
|
|
+ *
|
|
+ * This is different in set element context or concatenations:
|
|
+ * There is no relational operation (eq, neq and so on), thus
|
|
+ * it needs to be processed right away.
|
|
+ */
|
|
+ if ((ctx->flags & RULE_PP_REMOVE_OP_AND) &&
|
|
+ expr->left->etype == EXPR_PAYLOAD &&
|
|
+ expr->right->etype == EXPR_VALUE) {
|
|
+ __binop_postprocess(ctx, expr, expr->left, expr->right, exprp);
|
|
+ return;
|
|
+ }
|
|
+ break;
|
|
default:
|
|
expr_set_type(expr->right, expr->left->dtype,
|
|
expr->left->byteorder);
|
|
--
|
|
2.39.1
|
|
|