Instead of using the map expression, store dynamic key and data
separately since they need special handling than constant maps.

Signed-off-by: Pablo Neira Ayuso <[email protected]>
---
 include/statement.h       |  3 ++-
 src/evaluate.c            | 25 ++++++++++++++++++++++++-
 src/netlink_delinearize.c |  7 ++++++-
 src/netlink_linearize.c   | 21 +++++++++++----------
 src/parser_bison.y        |  3 ++-
 src/statement.c           |  7 ++++---
 6 files changed, 49 insertions(+), 17 deletions(-)

diff --git a/include/statement.h b/include/statement.h
index 7840e9d261da..6c583a918eb9 100644
--- a/include/statement.h
+++ b/include/statement.h
@@ -193,7 +193,8 @@ extern struct stmt *set_stmt_alloc(const struct location 
*loc);
 
 struct map_stmt {
        struct expr             *set;
-       struct expr             *map;
+       struct expr             *key;
+       struct expr             *data;
        enum nft_dynset_ops     op;
 };
 
diff --git a/src/evaluate.c b/src/evaluate.c
index 3f15b322d503..9bc67d8f71f1 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -2714,8 +2714,31 @@ static int stmt_evaluate_set(struct eval_ctx *ctx, 
struct stmt *stmt)
 
 static int stmt_evaluate_map(struct eval_ctx *ctx, struct stmt *stmt)
 {
-       if (expr_evaluate(ctx, &stmt->map.map->map) < 0)
+       expr_set_context(&ctx->ectx, NULL, 0);
+       if (expr_evaluate(ctx, &stmt->map.set) < 0)
                return -1;
+       if (stmt->map.set->ops->type != EXPR_SET_REF)
+               return expr_error(ctx->msgs, stmt->map.set,
+                                 "Expression does not refer to a set");
+
+       if (stmt_evaluate_arg(ctx, stmt,
+                             stmt->map.set->set->key->dtype,
+                             stmt->map.set->set->key->len,
+                             stmt->map.set->set->key->byteorder,
+                             &stmt->map.key) < 0)
+               return -1;
+       if (expr_is_constant(stmt->map.key))
+               return expr_error(ctx->msgs, stmt->map.key,
+                                 "Key expression can not be constant");
+       if (stmt->map.key->comment != NULL)
+               return expr_error(ctx->msgs, stmt->map.key,
+                                 "Key expression comments are not supported");
+       if (expr_is_constant(stmt->map.data))
+               return expr_error(ctx->msgs, stmt->map.data,
+                                 "Data expression can not be constant");
+       if (stmt->map.data->comment != NULL)
+               return expr_error(ctx->msgs, stmt->map.data,
+                                 "Data expression comments are not supported");
 
        return 0;
 }
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index dbf1f6186a3d..898c737f9b28 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -1321,7 +1321,8 @@ static void netlink_parse_dynset(struct netlink_parse_ctx 
*ctx,
        } else if (expr_data != NULL) {
                stmt = map_stmt_alloc(loc);
                stmt->map.set   = set_ref_expr_alloc(loc, set);
-               stmt->map.map   = map_expr_alloc(loc, expr, expr_data);
+               stmt->map.key   = expr;
+               stmt->map.data  = expr_data;
                stmt->map.op    = nftnl_expr_get_u32(nle, NFTNL_EXPR_DYNSET_OP);
        } else {
                stmt = set_stmt_alloc(loc);
@@ -2508,6 +2509,10 @@ static void rule_parse_postprocess(struct 
netlink_parse_ctx *ctx, struct rule *r
                case STMT_SET:
                        expr_postprocess(&rctx, &stmt->set.key);
                        break;
+               case STMT_MAP:
+                       expr_postprocess(&rctx, &stmt->map.key);
+                       expr_postprocess(&rctx, &stmt->map.data);
+                       break;
                case STMT_DUP:
                        if (stmt->dup.to != NULL)
                                expr_postprocess(&rctx, &stmt->dup.to);
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 442c5a940bc3..821fcd0a6377 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -1274,26 +1274,27 @@ static void netlink_gen_set_stmt(struct 
netlink_linearize_ctx *ctx,
 static void netlink_gen_map_stmt(struct netlink_linearize_ctx *ctx,
                                 const struct stmt *stmt)
 {
-       struct nftnl_expr *nle;
-       enum nft_registers sreg_key;
+       struct set *set = stmt->map.set->set;
        enum nft_registers sreg_data;
+       enum nft_registers sreg_key;
+       struct nftnl_expr *nle;
 
-       sreg_key = get_register(ctx, stmt->map.map->map->key);
-       netlink_gen_expr(ctx, stmt->map.map->map->key, sreg_key);
+       sreg_key = get_register(ctx, stmt->map.key);
+       netlink_gen_expr(ctx, stmt->map.key, sreg_key);
 
-       sreg_data = get_register(ctx, stmt->map.map->mappings);
-       netlink_gen_expr(ctx, stmt->map.map->mappings, sreg_data);
+       sreg_data = get_register(ctx, stmt->map.data);
+       netlink_gen_expr(ctx, stmt->map.data, sreg_data);
 
-       release_register(ctx, stmt->map.map->map->key);
-       release_register(ctx, stmt->map.map->mappings);
+       release_register(ctx, stmt->map.key);
+       release_register(ctx, stmt->map.data);
 
        nle = alloc_nft_expr("dynset");
        netlink_put_register(nle, NFTNL_EXPR_DYNSET_SREG_KEY, sreg_key);
        netlink_put_register(nle, NFTNL_EXPR_DYNSET_SREG_DATA, sreg_data);
 
        nftnl_expr_set_u32(nle, NFTNL_EXPR_DYNSET_OP, stmt->map.op);
-       nftnl_expr_set_str(nle, NFTNL_EXPR_DYNSET_SET_NAME, 
stmt->map.set->identifier);
-       nftnl_expr_set_u32(nle, NFTNL_EXPR_DYNSET_SET_ID, 
stmt->map.set->set->handle.set_id);
+       nftnl_expr_set_str(nle, NFTNL_EXPR_DYNSET_SET_NAME, 
set->handle.set.name);
+       nftnl_expr_set_u32(nle, NFTNL_EXPR_DYNSET_SET_ID, set->handle.set_id);
 
        nftnl_rule_add_expr(ctx->nlr, nle);
 }
diff --git a/src/parser_bison.y b/src/parser_bison.y
index bc6f72779dd7..199ef13d8c1d 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -2872,7 +2872,8 @@ map_stmt          :       set_stmt_op     symbol_expr '{' 
set_elem_expr_stmt      COLON   set_elem_expr_s
                        {
                                $$ = map_stmt_alloc(&@$);
                                $$->map.op  = $1;
-                               $$->map.map = map_expr_alloc(&@$, $4, $6);
+                               $$->map.key = $4;
+                               $$->map.data = $6;
                                $$->map.set = $2;
                        }
                        ;
diff --git a/src/statement.c b/src/statement.c
index cec83c19e529..039ca943e92c 100644
--- a/src/statement.c
+++ b/src/statement.c
@@ -657,15 +657,16 @@ static void map_stmt_print(const struct stmt *stmt, 
struct output_ctx *octx)
        nft_print(octx, "%s ", set_stmt_op_names[stmt->map.op]);
        expr_print(stmt->map.set, octx);
        nft_print(octx, " { ");
-       expr_print(stmt->map.map->map->key, octx);
+       expr_print(stmt->map.key, octx);
        nft_print(octx, " : ");
-       expr_print(stmt->map.map->mappings, octx);
+       expr_print(stmt->map.data, octx);
        nft_print(octx, " }");
 }
 
 static void map_stmt_destroy(struct stmt *stmt)
 {
-       expr_free(stmt->map.map);
+       expr_free(stmt->map.key);
+       expr_free(stmt->map.data);
        expr_free(stmt->map.set);
 }
 
-- 
2.11.0

Reply via email to