summaryrefslogtreecommitdiffstats
path: root/src/evaluate.c
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2022-04-17 22:27:41 +0200
committerFlorian Westphal <fw@strlen.de>2022-04-18 15:32:09 +0200
commit22b750aa6dc9780c19b9dbe00f9a9e5bb83ea08b (patch)
treeabb88c537f558152b6102eb58e4bc63d87a95fbe /src/evaluate.c
parent3ed9fadaab95943146ae0095dfaf868b63d09599 (diff)
src: allow use of base integer types as set keys in concatenations
"typeof ip saddr . ipsec in reqid" won't work because reqid uses integer type, i.e. dtype->size is 0. With "typeof", the size can be derived from the expression length, via set->key. This computes the concat length based either on dtype->size or expression length. It also updates concat evaluation to permit a zero datatype size if the subkey expression has nonzero length (i.e., typeof was used). Signed-off-by: Florian Westphal <fw@strlen.de>
Diffstat (limited to 'src/evaluate.c')
-rw-r--r--src/evaluate.c24
1 files changed, 17 insertions, 7 deletions
diff --git a/src/evaluate.c b/src/evaluate.c
index 503b4f03..b5f74d2f 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1270,7 +1270,8 @@ static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr)
}
list_for_each_entry_safe(i, next, &(*expr)->expressions, list) {
- unsigned dsize_bytes;
+ enum byteorder bo = BYTEORDER_INVALID;
+ unsigned dsize_bytes, dsize = 0;
if (i->etype == EXPR_CT &&
(i->ct.key == NFT_CT_SRC ||
@@ -1286,14 +1287,18 @@ static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr)
if (key) {
tmp = key->dtype;
+ dsize = key->len;
+ bo = key->byteorder;
off--;
} else if (dtype == NULL) {
tmp = datatype_lookup(TYPE_INVALID);
} else {
tmp = concat_subtype_lookup(type, --off);
+ dsize = tmp->size;
+ bo = tmp->byteorder;
}
- expr_set_context(&ctx->ectx, tmp, tmp->size);
+ __expr_set_context(&ctx->ectx, tmp, bo, dsize, 0);
if (list_member_evaluate(ctx, &i) < 0)
return -1;
@@ -1315,12 +1320,14 @@ static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr)
"data types (%s) in concat "
"expressions",
i->dtype->name);
+ if (dsize == 0) /* reload after evaluation or clone above */
+ dsize = i->dtype->size;
ntype = concat_subtype_add(ntype, i->dtype->type);
- dsize_bytes = div_round_up(i->dtype->size, BITS_PER_BYTE);
+ dsize_bytes = div_round_up(dsize, BITS_PER_BYTE);
(*expr)->field_len[(*expr)->field_count++] = dsize_bytes;
- size += netlink_padded_len(i->dtype->size);
+ size += netlink_padded_len(dsize);
if (key)
key = list_next_entry(key, list);
}
@@ -4046,20 +4053,23 @@ static int set_expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr)
i->dtype = dtype;
}
- if (i->dtype->size == 0)
+ if (i->dtype->size == 0 && i->len == 0)
return expr_binary_error(ctx->msgs, i, *expr,
"can not use variable sized "
"data types (%s) in concat "
"expressions",
i->dtype->name);
+ if (i->dtype->size)
+ assert(i->len == i->dtype->size);
+
flags &= i->flags;
ntype = concat_subtype_add(ntype, i->dtype->type);
- dsize_bytes = div_round_up(i->dtype->size, BITS_PER_BYTE);
+ dsize_bytes = div_round_up(i->len, BITS_PER_BYTE);
(*expr)->field_len[(*expr)->field_count++] = dsize_bytes;
- size += netlink_padded_len(i->dtype->size);
+ size += netlink_padded_len(i->len);
}
(*expr)->flags |= flags;