]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: enable json echo output when reading native syntax
authorJose M. Guisado Gomez <guigom@riseup.net>
Tue, 4 Aug 2020 10:38:46 +0000 (12:38 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 2 Dec 2020 09:45:15 +0000 (10:45 +0100)
This patch fixes a bug in which nft did not print any output when
specifying --echo and --json and reading nft native syntax.

This patch respects behavior when input is json, in which the output
would be the identical input plus the handles.

Adds a json_echo member inside struct nft_ctx to build and store the json object
containing the json command objects, the object is built using a mock
monitor to reuse monitor json code. This json object is only used when
we are sure we have not read json from input.

[ added json_alloc_echo() to compile without json support --pablo ]

Fixes: https://bugzilla.netfilter.org/show_bug.cgi?id=1446
Signed-off-by: Jose M. Guisado Gomez <guigom@riseup.net>
Tested-by: Eric Garver <eric@garver.life>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/json.h
include/nftables.h
src/json.c
src/monitor.c
src/parser_json.c

index 20d6c2a4a8e77784467612b77d1ff237931eda8c..411422082dc8208a088e5574a6fab6002560740c 100644 (file)
@@ -111,6 +111,7 @@ void monitor_print_rule_json(struct netlink_mon_handler *monh,
 
 int json_events_cb(const struct nlmsghdr *nlh,
                   struct netlink_mon_handler *monh);
+void json_alloc_echo(struct nft_ctx *ctx);
 void json_print_echo(struct nft_ctx *ctx);
 
 #else /* ! HAVE_LIBJANSSON */
@@ -251,6 +252,11 @@ static inline int json_events_cb(const struct nlmsghdr *nlh,
        return -1;
 }
 
+static inline void json_alloc_echo(struct nft_ctx *ctx)
+{
+       /* empty */
+}
+
 static inline void json_print_echo(struct nft_ctx *ctx)
 {
        /* empty */
index 3556728de6f9b7b9b2ce30c0c1cd23c430419f03..9095ff3d0b79c363d269ebfe4924669c28fc3040 100644 (file)
@@ -122,6 +122,7 @@ struct nft_ctx {
        void                    *scanner;
        struct scope            *top_scope;
        void                    *json_root;
+       json_t                  *json_echo;
 };
 
 enum nftables_exit_codes {
index ac3b1c833d864a8115e40dcc85aff43e1554f1b0..0b398bf0b25d3e671c12a287f5f65d92541285b6 100644 (file)
@@ -1895,9 +1895,15 @@ int do_command_list_json(struct netlink_ctx *ctx, struct cmd *cmd)
 static void monitor_print_json(struct netlink_mon_handler *monh,
                               const char *cmd, json_t *obj)
 {
+       struct nft_ctx *nft = monh->ctx->nft;
+
        obj = json_pack("{s:o}", cmd, obj);
-       json_dumpf(obj, monh->ctx->nft->output.output_fp, 0);
-       json_decref(obj);
+       if (nft_output_echo(&nft->output) && !nft->json_root) {
+               json_array_append_new(nft->json_echo, obj);
+       } else {
+               json_dumpf(obj, nft->output.output_fp, 0);
+               json_decref(obj);
+       }
 }
 
 void monitor_print_table_json(struct netlink_mon_handler *monh,
@@ -1941,3 +1947,10 @@ void monitor_print_rule_json(struct netlink_mon_handler *monh,
 
        monitor_print_json(monh, cmd, rule_print_json(octx, r));
 }
+
+void json_alloc_echo(struct nft_ctx *nft)
+{
+       nft->json_echo = json_array();
+       if (!nft->json_echo)
+               memory_allocation_error();
+}
index 3872ebcfbdaf649febc10cfba4f5b910e45d2425..a733a9f0a3ad82b8fd2bb85a8236b7385a1ac5ad 100644 (file)
@@ -221,12 +221,14 @@ static int netlink_events_table_cb(const struct nlmsghdr *nlh, int type,
                if (nft_output_handle(&monh->ctx->nft->output))
                        nft_mon_print(monh, " # handle %" PRIu64 "",
                                      t->handle.handle.id);
+               nft_mon_print(monh, "\n");
                break;
        case NFTNL_OUTPUT_JSON:
                monitor_print_table_json(monh, cmd, t);
+               if(!nft_output_echo(&monh->ctx->nft->output))
+                       nft_mon_print(monh, "\n");
                break;
        }
-       nft_mon_print(monh, "\n");
        table_free(t);
        nftnl_table_free(nlt);
        return MNL_CB_OK;
@@ -258,12 +260,14 @@ static int netlink_events_chain_cb(const struct nlmsghdr *nlh, int type,
                                      c->handle.chain.name);
                        break;
                }
+               nft_mon_print(monh, "\n");
                break;
        case NFTNL_OUTPUT_JSON:
                monitor_print_chain_json(monh, cmd, c);
+               if(!nft_output_echo(&monh->ctx->nft->output))
+                       nft_mon_print(monh, "\n");
                break;
        }
-       nft_mon_print(monh, "\n");
        chain_free(c);
        nftnl_chain_free(nlc);
        return MNL_CB_OK;
@@ -304,12 +308,14 @@ static int netlink_events_set_cb(const struct nlmsghdr *nlh, int type,
                                      set->handle.set.name);
                        break;
                }
+               nft_mon_print(monh, "\n");
                break;
        case NFTNL_OUTPUT_JSON:
                monitor_print_set_json(monh, cmd, set);
+               if(!nft_output_echo(&monh->ctx->nft->output))
+                       nft_mon_print(monh, "\n");
                break;
        }
-       nft_mon_print(monh, "\n");
        set_free(set);
 out:
        nftnl_set_free(nls);
@@ -441,6 +447,7 @@ static int netlink_events_setelem_cb(const struct nlmsghdr *nlh, int type,
                nft_mon_print(monh, "%s element %s %s %s ",
                              cmd, family2str(family), table, setname);
                expr_print(dummyset->init, &monh->ctx->nft->output);
+               nft_mon_print(monh, "\n");
                break;
        case NFTNL_OUTPUT_JSON:
                dummyset->handle.family = family;
@@ -450,9 +457,10 @@ static int netlink_events_setelem_cb(const struct nlmsghdr *nlh, int type,
                /* prevent set_free() from trying to free those */
                dummyset->handle.set.name = NULL;
                dummyset->handle.table.name = NULL;
+               if(!nft_output_echo(&monh->ctx->nft->output))
+                       nft_mon_print(monh, "\n");
                break;
        }
-       nft_mon_print(monh, "\n");
        set_free(dummyset);
 out:
        nftnl_set_free(nls);
@@ -492,12 +500,14 @@ static int netlink_events_obj_cb(const struct nlmsghdr *nlh, int type,
                               obj->handle.obj.name);
                        break;
                }
+               nft_mon_print(monh, "\n");
                break;
        case NFTNL_OUTPUT_JSON:
                monitor_print_obj_json(monh, cmd, obj);
+               if(!nft_output_echo(&monh->ctx->nft->output))
+                       nft_mon_print(monh, "\n");
                break;
        }
-       nft_mon_print(monh, "\n");
        obj_free(obj);
        nftnl_obj_free(nlo);
        return MNL_CB_OK;
@@ -542,12 +552,14 @@ static int netlink_events_rule_cb(const struct nlmsghdr *nlh, int type,
                                      r->handle.handle.id);
                        break;
                }
+               nft_mon_print(monh, "\n");
                break;
        case NFTNL_OUTPUT_JSON:
                monitor_print_rule_json(monh, cmd, r);
+               if(!nft_output_echo(&monh->ctx->nft->output))
+                       nft_mon_print(monh, "\n");
                break;
        }
-       nft_mon_print(monh, "\n");
        rule_free(r);
        nftnl_rule_free(nlr);
        return MNL_CB_OK;
@@ -912,6 +924,8 @@ int netlink_echo_callback(const struct nlmsghdr *nlh, void *data)
 {
        struct netlink_cb_data *nl_cb_data = data;
        struct netlink_ctx *ctx = nl_cb_data->nl_ctx;
+       struct nft_ctx *nft = ctx->nft;
+
        struct netlink_mon_handler echo_monh = {
                .format = NFTNL_OUTPUT_DEFAULT,
                .ctx = ctx,
@@ -922,8 +936,13 @@ int netlink_echo_callback(const struct nlmsghdr *nlh, void *data)
        if (!nft_output_echo(&echo_monh.ctx->nft->output))
                return MNL_CB_OK;
 
-       if (nft_output_json(&ctx->nft->output))
-               return json_events_cb(nlh, &echo_monh);
+       if (nft_output_json(&nft->output)) {
+               if (nft->json_root)
+                       return json_events_cb(nlh, &echo_monh);
+
+               json_alloc_echo(nft);
+               echo_monh.format = NFTNL_OUTPUT_JSON;
+       }
 
        return netlink_events_cb(nlh, &echo_monh);
 }
index 6ebbb408d68390ac2eed76f56ae6efdcb2c4132f..2de109938121997270b5960a0cc562e8838fe77b 100644 (file)
@@ -4008,11 +4008,20 @@ int json_events_cb(const struct nlmsghdr *nlh, struct netlink_mon_handler *monh)
 
 void json_print_echo(struct nft_ctx *ctx)
 {
-       if (!ctx->json_root)
-               return;
-
-       json_dumpf(ctx->json_root, ctx->output.output_fp, JSON_PRESERVE_ORDER);
-       json_cmd_assoc_free();
-       json_decref(ctx->json_root);
-       ctx->json_root = NULL;
+       if (!ctx->json_root) {
+               if (!ctx->json_echo)
+                       return;
+
+               ctx->json_echo = json_pack("{s:o}", "nftables", ctx->json_echo);
+               json_dumpf(ctx->json_echo, ctx->output.output_fp, JSON_PRESERVE_ORDER);
+               json_decref(ctx->json_echo);
+               ctx->json_echo = NULL;
+               fprintf(ctx->output.output_fp, "\n");
+               fflush(ctx->output.output_fp);
+       } else {
+               json_dumpf(ctx->json_root, ctx->output.output_fp, JSON_PRESERVE_ORDER);
+               json_cmd_assoc_free();
+               json_decref(ctx->json_root);
+               ctx->json_root = NULL;
+       }
 }