summaryrefslogtreecommitdiffstats
path: root/src/evaluate.c
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2021-06-22 21:38:18 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2021-06-23 13:04:24 +0200
commitdd084d6bfc32ce492084bed9d5e90aeef171503a (patch)
tree9a0f85bb3842845a97589ec189f8033968f2b65e /src/evaluate.c
parentf8bf621362cc7fa45731c87ef485f7fb298e1e13 (diff)
evaluate: fix maps with key and data concatenations
expr_evaluate_concat() is overloaded, it deals with two cases: #1 set key and data definitions, this case uses the special dynamically created concatenation datatype which is taken from the context. #2 set elements, this case iterates over the set key and data expressions that are components of the concatenation tuple, to fetch the corresponding datatype. Add a new function to deal with case #1 specifically. This patch is implicitly fixing up map that include arbitrary concatenations. This is failing with a spurious error report such as: # cat bug.nft table x { map test { type ipv4_addr . inet_proto . inet_service : ipv4_addr . inet_service } } # nft -f bug.nft bug.nft:3:48-71: Error: datatype mismatch, expected concatenation of (IPv4 address, Internet protocol, internet network service), expression has type concatenation of (IPv4 address, internet network service) type ipv4_addr . inet_proto . inet_service : ipv4_addr . inet_service ^^^^^^^^^^^^^^^^^^^^^^^^ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/evaluate.c')
-rw-r--r--src/evaluate.c50
1 files changed, 44 insertions, 6 deletions
diff --git a/src/evaluate.c b/src/evaluate.c
index 4f19dc43..dbc773d1 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1240,8 +1240,7 @@ static int list_member_evaluate(struct eval_ctx *ctx, struct expr **expr)
return err;
}
-static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr,
- bool eval)
+static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr)
{
const struct datatype *dtype = ctx->ectx.dtype, *tmp;
uint32_t type = dtype ? dtype->type : 0, ntype = 0;
@@ -1270,7 +1269,7 @@ static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr,
tmp = concat_subtype_lookup(type, --off);
expr_set_context(&ctx->ectx, tmp, tmp->size);
- if (eval && list_member_evaluate(ctx, &i) < 0)
+ if (list_member_evaluate(ctx, &i) < 0)
return -1;
flags &= i->flags;
@@ -2240,7 +2239,7 @@ static int expr_evaluate(struct eval_ctx *ctx, struct expr **expr)
case EXPR_BINOP:
return expr_evaluate_binop(ctx, expr);
case EXPR_CONCAT:
- return expr_evaluate_concat(ctx, expr, true);
+ return expr_evaluate_concat(ctx, expr);
case EXPR_LIST:
return expr_evaluate_list(ctx, expr);
case EXPR_SET:
@@ -3797,6 +3796,45 @@ static int set_key_data_error(struct eval_ctx *ctx, const struct set *set,
dtype->name, name, hint);
}
+static int set_expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr)
+{
+ unsigned int flags = EXPR_F_CONSTANT | EXPR_F_SINGLETON;
+ struct expr *i, *next;
+ uint32_t ntype = 0;
+
+ list_for_each_entry_safe(i, next, &(*expr)->expressions, list) {
+ unsigned dsize_bytes;
+
+ if (i->etype == EXPR_CT &&
+ (i->ct.key == NFT_CT_SRC ||
+ i->ct.key == NFT_CT_DST))
+ return expr_error(ctx->msgs, i,
+ "specify either ip or ip6 for address matching");
+
+ if (i->dtype->size == 0)
+ return expr_binary_error(ctx->msgs, i, *expr,
+ "can not use variable sized "
+ "data types (%s) in concat "
+ "expressions",
+ i->dtype->name);
+
+ flags &= i->flags;
+
+ ntype = concat_subtype_add(ntype, i->dtype->type);
+
+ dsize_bytes = div_round_up(i->dtype->size, BITS_PER_BYTE);
+ (*expr)->field_len[(*expr)->field_count++] = dsize_bytes;
+ }
+
+ (*expr)->flags |= flags;
+ datatype_set(*expr, concat_type_alloc(ntype));
+ (*expr)->len = (*expr)->dtype->size;
+
+ expr_set_context(&ctx->ectx, (*expr)->dtype, (*expr)->len);
+
+ return 0;
+}
+
static int set_evaluate(struct eval_ctx *ctx, struct set *set)
{
unsigned int num_stmts = 0;
@@ -3826,7 +3864,7 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set)
if (set->key->len == 0) {
if (set->key->etype == EXPR_CONCAT &&
- expr_evaluate_concat(ctx, &set->key, false) < 0)
+ set_expr_evaluate_concat(ctx, &set->key) < 0)
return -1;
if (set->key->len == 0)
@@ -3850,7 +3888,7 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set)
set->data->len *= 2;
if (set->data->etype == EXPR_CONCAT &&
- expr_evaluate_concat(ctx, &set->data, false) < 0)
+ set_expr_evaluate_concat(ctx, &set->data) < 0)
return -1;
if (set->data->len == 0 && set->data->dtype->type != TYPE_VERDICT)