When listing a map with statements with JSON support, the statement list were ignored. Output example: { "map": { "family": "ip", "name": "m", "table": "t", "type": "ipv4_addr", "handle": 1, "map": "mark", "stmt": [ { "counter": { "packets": 0, "bytes": 0 } } ] } } Link: https://bugzilla.netfilter.org/show_bug.cgi?id=1588 Signed-off-by: Fernando Fernandez Mancera <ffmancera@xxxxxxxxxx> --- src/json.c | 70 +++++++++++-------- src/parser_json.c | 5 +- tests/shell/testcases/json/0002table_map_0 | 9 +++ .../testcases/json/dumps/0002table_map_0.nft | 6 ++ 4 files changed, 61 insertions(+), 29 deletions(-) create mode 100755 tests/shell/testcases/json/0002table_map_0 create mode 100644 tests/shell/testcases/json/dumps/0002table_map_0.nft diff --git a/src/json.c b/src/json.c index 55959eea..1f2889c6 100644 --- a/src/json.c +++ b/src/json.c @@ -77,6 +77,34 @@ static json_t *set_dtype_json(const struct expr *key) return root; } +static json_t *stmt_print_json(const struct stmt *stmt, struct output_ctx *octx) +{ + char buf[1024]; + FILE *fp; + + /* XXX: Can't be supported at this point: + * xt_stmt_xlate() ignores output_fp. + */ + if (stmt->ops->type == STMT_XT) + return json_pack("{s:n}", "xt"); + + if (stmt->ops->json) + return stmt->ops->json(stmt, octx); + + fprintf(stderr, "warning: stmt ops %s have no json callback\n", + stmt->ops->name); + + fp = octx->output_fp; + octx->output_fp = fmemopen(buf, 1024, "w"); + + stmt->ops->print(stmt, octx); + + fclose(octx->output_fp); + octx->output_fp = fp; + + return json_pack("s", buf); +} + static json_t *set_print_json(struct output_ctx *octx, const struct set *set) { json_t *root, *tmp; @@ -152,6 +180,20 @@ static json_t *set_print_json(struct output_ctx *octx, const struct set *set) json_object_set_new(root, "elem", array); } + if (!list_empty(&set->stmt_list)) { + json_t *array, *tmp; + struct stmt *stmt; + + array = json_array(); + + list_for_each_entry(stmt, &set->stmt_list, list) { + tmp = stmt_print_json(stmt, octx); + json_array_append_new(array, tmp); + } + + json_object_set_new(root, "stmt", array); + } + return json_pack("{s:o}", type, root); } @@ -168,34 +210,6 @@ static json_t *element_print_json(struct output_ctx *octx, "elem", root); } -static json_t *stmt_print_json(const struct stmt *stmt, struct output_ctx *octx) -{ - char buf[1024]; - FILE *fp; - - /* XXX: Can't be supported at this point: - * xt_stmt_xlate() ignores output_fp. - */ - if (stmt->ops->type == STMT_XT) - return json_pack("{s:n}", "xt"); - - if (stmt->ops->json) - return stmt->ops->json(stmt, octx); - - fprintf(stderr, "warning: stmt ops %s have no json callback\n", - stmt->ops->name); - - fp = octx->output_fp; - octx->output_fp = fmemopen(buf, 1024, "w"); - - stmt->ops->print(stmt, octx); - - fclose(octx->output_fp); - octx->output_fp = fp; - - return json_pack("s", buf); -} - static json_t *rule_print_json(struct output_ctx *octx, const struct rule *rule) { diff --git a/src/parser_json.c b/src/parser_json.c index fc72c25f..7180474e 100644 --- a/src/parser_json.c +++ b/src/parser_json.c @@ -3002,8 +3002,8 @@ static struct cmd *json_parse_cmd_add_set(struct json_ctx *ctx, json_t *root, { struct handle h = { 0 }; const char *family = "", *policy, *dtype_ext = NULL; + json_t *tmp, *stmt_json; struct set *set; - json_t *tmp; if (json_unpack_err(ctx, root, "{s:s, s:s}", "family", &family, @@ -3114,6 +3114,9 @@ static struct cmd *json_parse_cmd_add_set(struct json_ctx *ctx, json_t *root, set->gc_int *= 1000; json_unpack(root, "{s:i}", "size", &set->desc.size); + if (!json_unpack(root, "{s:o}", "stmt", &stmt_json)) + json_parse_set_stmt_list(ctx, &set->stmt_list, stmt_json); + handle_merge(&set->handle, &h); if (op == CMD_ADD) diff --git a/tests/shell/testcases/json/0002table_map_0 b/tests/shell/testcases/json/0002table_map_0 new file mode 100755 index 00000000..4b54527b --- /dev/null +++ b/tests/shell/testcases/json/0002table_map_0 @@ -0,0 +1,9 @@ +#!/bin/bash + +set -e + +$NFT flush ruleset + +RULESET='{"nftables": [{"metainfo": {"version": "1.0.5", "release_name": "Lester Gooch #4", "json_schema_version": 1}}, {"table": {"family": "ip", "name": "t", "handle": 4}}, {"map": {"family": "ip", "name": "m", "table": "t", "type": "ipv4_addr", "handle": 1, "map": "mark", "stmt": [{"counter": {"packets": 0, "bytes": 0}}]}}]}' + +$NFT -j -f - <<< $RULESET diff --git a/tests/shell/testcases/json/dumps/0002table_map_0.nft b/tests/shell/testcases/json/dumps/0002table_map_0.nft new file mode 100644 index 00000000..357e92cc --- /dev/null +++ b/tests/shell/testcases/json/dumps/0002table_map_0.nft @@ -0,0 +1,6 @@ +table ip t { + map m { + type ipv4_addr : mark + counter + } +} -- 2.30.2