]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
json: add table map statement support
authorFernando Fernandez Mancera <ffmancera@riseup.net>
Fri, 2 Sep 2022 10:52:04 +0000 (12:52 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Sat, 3 Sep 2022 13:54:26 +0000 (15:54 +0200)
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@riseup.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
src/json.c
src/parser_json.c
tests/shell/testcases/json/0002table_map_0 [new file with mode: 0755]
tests/shell/testcases/json/dumps/0002table_map_0.nft [new file with mode: 0644]

index 55959eea94f9f45963cdd78328ef46669c46d828..1f2889c62e62c4103d8188de6b6df6e8f0f19b01 100644 (file)
@@ -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)
 {
index fc72c25ff69132a994aa66c14c6b430904507ab1..7180474e76454da658619c1328c8217f7d08b245 100644 (file)
@@ -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 (executable)
index 0000000..4b54527
--- /dev/null
@@ -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 (file)
index 0000000..357e92c
--- /dev/null
@@ -0,0 +1,6 @@
+table ip t {
+       map m {
+               type ipv4_addr : mark
+               counter
+       }
+}