summaryrefslogtreecommitdiffstats
path: root/src/netlink_delinearize.c
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2021-09-28 21:34:30 +0200
committerFlorian Westphal <fw@strlen.de>2021-09-29 18:31:34 +0200
commitef6cd93ecb8413c9bfea547783207c39b84fc682 (patch)
treea990a709ee5b59a6fd79098a9448ea429b249fdf /src/netlink_delinearize.c
parent8a9762dbf15433b6dc361ec03cb3d6f0db652a85 (diff)
netlink: dynset: set compound expr dtype based on set key definition
"nft add rule ... add @t { ip saddr . 22 ..." will be listed as 'ip saddr . 0x16 [ invalid type]". This is a display bug, the compound expression created during netlink deserialization lacks correct datatypes for the value expression. Avoid this by setting the individual expressions' datatype. The set key has the needed information, so walk over the types and set them in the dynset statment. Also add a test case. Reported-by: Paulo Ricardo Bruck <paulobruck1@gmail.com> Signed-off-by: Florian Westphal <fw@strlen.de>
Diffstat (limited to 'src/netlink_delinearize.c')
-rw-r--r--src/netlink_delinearize.c46
1 files changed, 45 insertions, 1 deletions
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index bd75ad5c..0c2b439e 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -134,6 +134,50 @@ err:
return NULL;
}
+static struct expr *netlink_parse_concat_key(struct netlink_parse_ctx *ctx,
+ const struct location *loc,
+ unsigned int reg,
+ const struct expr *key)
+{
+ uint32_t type = key->dtype->type;
+ unsigned int n, len = key->len;
+ struct expr *concat, *expr;
+ unsigned int consumed;
+
+ concat = concat_expr_alloc(loc);
+ n = div_round_up(fls(type), TYPE_BITS);
+
+ while (len > 0) {
+ const struct datatype *i;
+
+ expr = netlink_get_register(ctx, loc, reg);
+ if (expr == NULL) {
+ netlink_error(ctx, loc,
+ "Concat expression size mismatch");
+ goto err;
+ }
+
+ if (n > 0 && concat_subtype_id(type, --n)) {
+ i = concat_subtype_lookup(type, n);
+
+ expr_set_type(expr, i, i->byteorder);
+ }
+
+ compound_expr_add(concat, expr);
+
+ consumed = netlink_padded_len(expr->len);
+ assert(consumed > 0);
+ len -= consumed;
+ reg += netlink_register_space(expr->len);
+ }
+
+ return concat;
+
+err:
+ expr_free(concat);
+ return NULL;
+}
+
static struct expr *netlink_parse_concat_data(struct netlink_parse_ctx *ctx,
const struct location *loc,
unsigned int reg,
@@ -1572,7 +1616,7 @@ static void netlink_parse_dynset(struct netlink_parse_ctx *ctx,
if (expr->len < set->key->len) {
expr_free(expr);
- expr = netlink_parse_concat_expr(ctx, loc, sreg, set->key->len);
+ expr = netlink_parse_concat_key(ctx, loc, sreg, set->key);
if (expr == NULL)
return;
}