]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
monitor: Inform JSON printer when reporting an object delete event
authorPhil Sutter <phil@nwl.cc>
Thu, 28 Aug 2025 23:07:05 +0000 (01:07 +0200)
committerPhil Sutter <phil@nwl.cc>
Thu, 11 Sep 2025 16:03:02 +0000 (18:03 +0200)
Since kernel commit a1050dd07168 ("netfilter: nf_tables: Reintroduce
shortened deletion notifications"), type-specific data is no longer
dumped when notifying for a deleted object. JSON output was not aware of
this and tried to print bogus data.

Fixes: 9e88aae28e9f4 ("monitor: Use libnftables JSON output")
Signed-off-by: Phil Sutter <phil@nwl.cc>
Reviewed-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/json.h
src/json.c
src/monitor.c
tests/monitor/testcases/object.t

index 42e1c8616c975f642fae98727facc4c030126575..3b8d045f87bbccdabedf8bd6a4c8693615b5dffc 100644 (file)
@@ -113,7 +113,7 @@ void monitor_print_set_json(struct netlink_mon_handler *monh,
 void monitor_print_element_json(struct netlink_mon_handler *monh,
                                const char *cmd, struct set *s);
 void monitor_print_obj_json(struct netlink_mon_handler *monh,
-                           const char *cmd, struct obj *o);
+                           const char *cmd, struct obj *o, bool delete);
 void monitor_print_flowtable_json(struct netlink_mon_handler *monh,
                                  const char *cmd, struct flowtable *ft);
 void monitor_print_rule_json(struct netlink_mon_handler *monh,
@@ -252,7 +252,8 @@ static inline void monitor_print_element_json(struct netlink_mon_handler *monh,
 }
 
 static inline void monitor_print_obj_json(struct netlink_mon_handler *monh,
-                                         const char *cmd, struct obj *o)
+                                         const char *cmd, struct obj *o,
+                                         bool delete)
 {
        /* empty */
 }
index d06fd040271407b08a3bc24cefa3c448c332721a..0afce5415f541d69b7a6de8222477f1f2bf132fc 100644 (file)
@@ -397,7 +397,8 @@ static json_t *tunnel_erspan_print_json(const struct obj *obj)
        return tunnel;
 }
 
-static json_t *obj_print_json(struct output_ctx *octx, const struct obj *obj)
+static json_t *obj_print_json(struct output_ctx *octx, const struct obj *obj,
+                             bool delete)
 {
        const char *rate_unit = NULL, *burst_unit = NULL;
        const char *type = obj_type_name(obj->type);
@@ -410,6 +411,9 @@ static json_t *obj_print_json(struct output_ctx *octx, const struct obj *obj)
                        "table", obj->handle.table.name,
                        "handle", obj->handle.handle.id);
 
+       if (delete)
+               goto out;
+
        if (obj->comment) {
                tmp = nft_json_pack("{s:s}", "comment", obj->comment);
                json_object_update(root, tmp);
@@ -570,6 +574,7 @@ static json_t *obj_print_json(struct output_ctx *octx, const struct obj *obj)
                break;
        }
 
+out:
        return nft_json_pack("{s:o}", type, root);
 }
 
@@ -1815,7 +1820,7 @@ static json_t *table_print_json_full(struct netlink_ctx *ctx,
                json_array_append_new(root, tmp);
        }
        list_for_each_entry(obj, &table->obj_cache.list, cache.list) {
-               tmp = obj_print_json(&ctx->nft->output, obj);
+               tmp = obj_print_json(&ctx->nft->output, obj, false);
                json_array_append_new(root, tmp);
        }
        list_for_each_entry(set, &table->set_cache.list, cache.list) {
@@ -1971,7 +1976,7 @@ static json_t *do_list_sets_json(struct netlink_ctx *ctx, struct cmd *cmd)
 static json_t *do_list_obj_json(struct netlink_ctx *ctx,
                                struct cmd *cmd, uint32_t type)
 {
-       json_t *root = json_array();
+       json_t *root = json_array(), *tmp;
        struct table *table;
        struct obj *obj;
 
@@ -1990,7 +1995,8 @@ static json_t *do_list_obj_json(struct netlink_ctx *ctx,
                             strcmp(cmd->handle.obj.name, obj->handle.obj.name)))
                                continue;
 
-                       json_array_append_new(root, obj_print_json(&ctx->nft->output, obj));
+                       tmp = obj_print_json(&ctx->nft->output, obj, false);
+                       json_array_append_new(root, tmp);
                }
        }
 
@@ -2207,11 +2213,11 @@ void monitor_print_element_json(struct netlink_mon_handler *monh,
 }
 
 void monitor_print_obj_json(struct netlink_mon_handler *monh,
-                           const char *cmd, struct obj *o)
+                           const char *cmd, struct obj *o, bool delete)
 {
        struct output_ctx *octx = &monh->ctx->nft->output;
 
-       monitor_print_json(monh, cmd, obj_print_json(octx, o));
+       monitor_print_json(monh, cmd, obj_print_json(octx, o, delete));
 }
 
 void monitor_print_flowtable_json(struct netlink_mon_handler *monh,
index e58f62252ca2d27906dce9e7a24aad029c1dd37d..fafeeebe914b8b9901d584171106424a2d65f1e8 100644 (file)
@@ -549,7 +549,7 @@ static int netlink_events_obj_cb(const struct nlmsghdr *nlh, int type,
                nft_mon_print(monh, "\n");
                break;
        case NFTNL_OUTPUT_JSON:
-               monitor_print_obj_json(monh, cmd, obj);
+               monitor_print_obj_json(monh, cmd, obj, type == NFT_MSG_DELOBJ);
                if (!nft_output_echo(&monh->ctx->nft->output))
                        nft_mon_print(monh, "\n");
                break;
index 53a9f8c59836b69057b88da6865306106241b4cd..b60dc9899ab2a2878b442f91a12c1b553ecb84f2 100644 (file)
@@ -9,7 +9,7 @@ J {"add": {"counter": {"family": "ip", "name": "c", "table": "t", "handle": 0, "
 
 I delete counter ip t c
 O -
-J {"delete": {"counter": {"family": "ip", "name": "c", "table": "t", "handle": 0, "packets": 0, "bytes": 0}}}
+J {"delete": {"counter": {"family": "ip", "name": "c", "table": "t", "handle": 0}}}
 
 # FIXME: input/output shouldn't be asynchronous here
 I add quota ip t q 25 mbytes
@@ -18,7 +18,7 @@ J {"add": {"quota": {"family": "ip", "name": "q", "table": "t", "handle": 0, "by
 
 I delete quota ip t q
 O -
-J {"delete": {"quota": {"family": "ip", "name": "q", "table": "t", "handle": 0, "bytes": 26214400, "used": 0, "inv": false}}}
+J {"delete": {"quota": {"family": "ip", "name": "q", "table": "t", "handle": 0}}}
 
 # FIXME: input/output shouldn't be asynchronous here
 I add limit ip t l rate 1/second
@@ -27,7 +27,7 @@ J {"add": {"limit": {"family": "ip", "name": "l", "table": "t", "handle": 0, "ra
 
 I delete limit ip t l
 O -
-J {"delete": {"limit": {"family": "ip", "name": "l", "table": "t", "handle": 0, "rate": 1, "per": "second", "burst": 5}}}
+J {"delete": {"limit": {"family": "ip", "name": "l", "table": "t", "handle": 0}}}
 
 I add ct helper ip t cth { type "sip" protocol tcp; l3proto ip; }
 O -
@@ -35,7 +35,7 @@ J {"add": {"ct helper": {"family": "ip", "name": "cth", "table": "t", "handle":
 
 I delete ct helper ip t cth
 O -
-J {"delete": {"ct helper": {"family": "ip", "name": "cth", "table": "t", "handle": 0, "type": "sip", "protocol": "tcp", "l3proto": "ip"}}}
+J {"delete": {"ct helper": {"family": "ip", "name": "cth", "table": "t", "handle": 0}}}
 
 I add ct timeout ip t ctt { protocol udp; l3proto ip; policy = { unreplied : 15s, replied : 12s }; }
 O -
@@ -43,4 +43,4 @@ J {"add": {"ct timeout": {"family": "ip", "name": "ctt", "table": "t", "handle":
 
 I delete ct timeout ip t ctt
 O -
-J {"delete": {"ct timeout": {"family": "ip", "name": "ctt", "table": "t", "handle": 0, "protocol": "udp", "l3proto": "ip", "policy": {"unreplied": 15, "replied": 12}}}}
+J {"delete": {"ct timeout": {"family": "ip", "name": "ctt", "table": "t", "handle": 0}}}