]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: mnl: always dump all netdev hooks if no interface name was given
authorFlorian Westphal <fw@strlen.de>
Tue, 20 Aug 2024 22:12:27 +0000 (00:12 +0200)
committerFlorian Westphal <fw@strlen.de>
Wed, 21 Aug 2024 12:22:16 +0000 (14:22 +0200)
Instead of not returning any results for
  nft list hooks netdev

Iterate all interfaces and then query all of them.

Signed-off-by: Florian Westphal <fw@strlen.de>
doc/additional-commands.txt
include/iface.h
src/iface.c
src/mnl.c

index 9ad338f8c7d1bb6bad9a65b160b0ac9c5a16b21b..2ebc2993c5fa04f73c70b5a7832b7d247aafce93 100644 (file)
@@ -8,13 +8,13 @@ registered implicitly by kernel modules such as nf_conntrack. +
 [verse]
 ____
 *list hooks* ['family']
-*list hooks netdev device* 'DEVICE_NAME'
+*list hooks netdev* [ *device* 'DEVICE_NAME' ]
 ____
 
 *list hooks* is enough to display everything that is active
-on the system, however, it does currently omit hooks that are
-tied to a specific network device (netdev family). To obtain
-those, the network device needs to be queried by name.
+on the system.  Hooks in the netdev family are tied to a network
+device.  If no device name is given, nft will query all network
+devices in the current network namespace.
 Example Usage:
 
 .List all active netfilter hooks in either the ip or ip6 stack
index f41ee8be6c8956e3c4c6955762f404db1ad67db0..786b1dfc8f8f5bb33072a989caa9fe1a3d2de2c7 100644 (file)
@@ -2,6 +2,7 @@
 #define _NFTABLES_IFACE_H_
 
 #include <net/if.h>
+#include <list.h>
 
 struct iface {
        struct list_head        list;
@@ -15,4 +16,5 @@ char *nft_if_indextoname(unsigned int ifindex, char *name);
 void iface_cache_update(void);
 void iface_cache_release(void);
 
+const struct iface *iface_cache_get_next_entry(const struct iface *prev);
 #endif
index 428acaae2eac33ff3d60f92efde8da57e71c5c34..a85341a1703adf8e125eed1521789af41dbfda23 100644 (file)
@@ -171,3 +171,20 @@ char *nft_if_indextoname(unsigned int ifindex, char *name)
        }
        return NULL;
 }
+
+const struct iface *iface_cache_get_next_entry(const struct iface *prev)
+{
+       if (!iface_cache_init)
+               iface_cache_update();
+
+       if (list_empty(&iface_list))
+               return NULL;
+
+       if (!prev)
+               return list_first_entry(&iface_list, struct iface, list);
+
+       if (list_is_last(&prev->list, &iface_list))
+               return NULL;
+
+       return list_next_entry(prev, list);
+}
index e585241d939596b013c10e6b00bd02d303b18e79..12e145204ef58073f88201f491079e1554b95165 100644 (file)
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -9,6 +9,7 @@
  */
 
 #include <nft.h>
+#include <iface.h>
 
 #include <libmnl/libmnl.h>
 #include <libnftnl/common.h>
@@ -2205,7 +2206,7 @@ static void basehook_list_add_tail(struct basehook *b, struct list_head *head)
        list_for_each_entry(hook, head, list) {
                if (hook->family != b->family)
                        continue;
-               if (hook->num != b->num)
+               if (!basehook_eq(hook, b))
                        continue;
                if (hook->prio < b->prio)
                        continue;
@@ -2591,11 +2592,9 @@ int mnl_nft_dump_nf_hooks(struct netlink_ctx *ctx, int family, const char *devna
                if (tmp == 0)
                        ret = 0;
 
-               if (devname) {
-                       tmp = mnl_nft_dump_nf_hooks(ctx, NFPROTO_NETDEV, devname);
-                       if (tmp == 0)
-                               ret = 0;
-               }
+               tmp = mnl_nft_dump_nf_hooks(ctx, NFPROTO_NETDEV, devname);
+               if (tmp == 0)
+                       ret = 0;
 
                return ret;
        case NFPROTO_INET:
@@ -2622,7 +2621,23 @@ int mnl_nft_dump_nf_hooks(struct netlink_ctx *ctx, int family, const char *devna
                ret = mnl_nft_dump_nf_arp(ctx, family, devname, &hook_list);
                break;
        case NFPROTO_NETDEV:
-               ret = mnl_nft_dump_nf_netdev(ctx, family, devname, &hook_list);
+               if (devname) {
+                       ret = mnl_nft_dump_nf_netdev(ctx, family, devname, &hook_list);
+               } else {
+                       const struct iface *iface;
+
+                       iface = iface_cache_get_next_entry(NULL);
+                       ret = 0;
+
+                       while (iface) {
+                               tmp = mnl_nft_dump_nf_netdev(ctx, family, iface->name, &hook_list);
+                               if (tmp == 0)
+                                       ret = 0;
+
+                               iface = iface_cache_get_next_entry(iface);
+                       }
+               }
+
                break;
        }