]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
src: mnl: make family specification more strict when listing
authorFlorian Westphal <fw@strlen.de>
Wed, 31 Jul 2024 16:51:02 +0000 (18:51 +0200)
committerFlorian Westphal <fw@strlen.de>
Mon, 19 Aug 2024 12:00:36 +0000 (14:00 +0200)
make "nft list hooks <family>" more strict.

nft list hooks: query/list all NFPROTO_XXX values, i.e.
arp, bridge, ipv4, ipv6.

If a device is also given, then do include the netdev family for
the given device as well.

"nft list hooks arp" will only dump the hooks registered
for NFPROTO_ARP (or nothing at all if none are active).

"bridge", "ip", "ip6" will list the pre/in/forward/output/postrouting
hooks for these families, if any.

"inet" serves as an alias for "ip" and "ip6".

Link: https://lore.kernel.org/netfilter-devel/20240729153211.GA26048@breakpoint.cc/
Signed-off-by: Florian Westphal <fw@strlen.de>
src/mnl.c

index e4bbbcf6d536f42484ad23bde891544376600f3b..88475ef4c25ea5181acbfb5cf095cc75cd80782d 100644 (file)
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -2391,25 +2391,6 @@ static int dump_nf_hooks(const struct nlmsghdr *nlh, void *_data)
 
        hook->family = nfg->nfgen_family;
 
-       /* Netdev hooks potentially interfer with this family datapath. */
-       if (hook->family == NFPROTO_NETDEV) {
-               switch (data->family) {
-               case NFPROTO_IPV4:
-               case NFPROTO_IPV6:
-               case NFPROTO_INET:
-               case NFPROTO_BRIDGE:
-                       hook->family = data->family;
-                       hook->num = NF_INET_INGRESS;
-                       break;
-               case NFPROTO_ARP:
-                       if (hook->chain_family == NFPROTO_NETDEV) {
-                               hook->family = data->family;
-                               hook->num = __NF_ARP_INGRESS;
-                       }
-                       break;
-               }
-       }
-
        basehook_list_add_tail(hook, data->hook_list);
 
        return MNL_CB_OK;
@@ -2523,9 +2504,6 @@ static int mnl_nft_dump_nf(struct netlink_ctx *ctx, int family, int hook,
 {
        int i, err;
 
-       /* show ingress in first place in hook listing. */
-       err = __mnl_nft_dump_nf_hooks(ctx, family, NFPROTO_NETDEV, NF_NETDEV_INGRESS, devname, hook_list);
-
        for (i = 0; i <= NF_INET_POST_ROUTING; i++) {
                int tmp;
 
@@ -2566,6 +2544,12 @@ static void release_hook_list(struct list_head *hook_list)
                basehook_free(hook);
 }
 
+static void warn_if_device(struct nft_ctx *nft, const char *devname)
+{
+       if (devname)
+               nft_print(&nft->output, "# device keyword (%s) unexpected for this family\n", devname);
+}
+
 int mnl_nft_dump_nf_hooks(struct netlink_ctx *ctx, int family, int hook, const char *devname)
 {
        LIST_HEAD(hook_list);
@@ -2576,30 +2560,41 @@ int mnl_nft_dump_nf_hooks(struct netlink_ctx *ctx, int family, int hook, const c
        switch (family) {
        case NFPROTO_UNSPEC:
                ret = mnl_nft_dump_nf_hooks(ctx, NFPROTO_ARP, hook, NULL);
-               tmp = mnl_nft_dump_nf_hooks(ctx, NFPROTO_INET, hook, devname);
+               tmp = mnl_nft_dump_nf_hooks(ctx, NFPROTO_INET, hook, NULL);
                if (tmp == 0)
                        ret = 0;
                tmp = mnl_nft_dump_nf_hooks(ctx, NFPROTO_BRIDGE, hook, NULL);
                if (tmp == 0)
                        ret = 0;
-               tmp = mnl_nft_dump_nf_hooks(ctx, NFPROTO_NETDEV, hook, devname);
-               if (tmp == 0)
-                       ret = 0;
+
+               if (devname) {
+                       tmp = mnl_nft_dump_nf_hooks(ctx, NFPROTO_NETDEV, hook, devname);
+                       if (tmp == 0)
+                               ret = 0;
+               }
 
                return ret;
        case NFPROTO_INET:
-               ret = mnl_nft_dump_nf_hooks(ctx, NFPROTO_IPV4, hook, devname);
-               tmp = mnl_nft_dump_nf_hooks(ctx, NFPROTO_IPV6, hook, devname);
+               ret = 0;
+               if (devname)
+                       ret = __mnl_nft_dump_nf_hooks(ctx, family, NFPROTO_NETDEV,
+                                                     NF_NETDEV_INGRESS, devname, &hook_list);
+               tmp = mnl_nft_dump_nf_hooks(ctx, NFPROTO_IPV4, hook, NULL);
+               if (tmp == 0)
+                       ret = 0;
+               tmp = mnl_nft_dump_nf_hooks(ctx, NFPROTO_IPV6, hook, NULL);
                if (tmp == 0)
                        ret = 0;
 
-               return ret;
+               break;
        case NFPROTO_IPV4:
        case NFPROTO_IPV6:
        case NFPROTO_BRIDGE:
+               warn_if_device(ctx->nft, devname);
                ret = mnl_nft_dump_nf(ctx, family, hook, devname, &hook_list);
                break;
        case NFPROTO_ARP:
+               warn_if_device(ctx->nft, devname);
                ret = mnl_nft_dump_nf_arp(ctx, family, hook, devname, &hook_list);
                break;
        case NFPROTO_NETDEV: