]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
netfilter: nfnetlink_hook: Dump flowtable info
authorPhil Sutter <phil@nwl.cc>
Tue, 8 Jul 2025 13:04:02 +0000 (15:04 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Fri, 25 Jul 2025 16:40:01 +0000 (18:40 +0200)
Introduce NFNL_HOOK_TYPE_NFT_FLOWTABLE to distinguish flowtable hooks
from base chain ones. Nested attributes are shared with the old NFTABLES
hook info type since they fit apart from their misleading name.

Old nftables in user space will ignore this new hook type and thus
continue to print flowtable hooks just like before, e.g.:

| family netdev {
|  hook ingress device test0 {
|   0000000000 nf_flow_offload_ip_hook [nf_flow_table]
|  }
| }

With this patch in place and support for the new hook info type, output
becomes more useful:

| family netdev {
|  hook ingress device test0 {
|   0000000000 flowtable ip mytable myft [nf_flow_table]
|  }
| }

Suggested-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Phil Sutter <phil@nwl.cc>
Reviewed-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/linux/netfilter.h
include/uapi/linux/netfilter/nfnetlink_hook.h
net/netfilter/nf_tables_api.c
net/netfilter/nfnetlink_hook.c

index 5f896fcc074d67108a331ff5db6be641de2b64d4..efbbfa770d6617a14145f68596610edb6e5ffda1 100644 (file)
@@ -92,6 +92,7 @@ enum nf_hook_ops_type {
        NF_HOOK_OP_UNDEFINED,
        NF_HOOK_OP_NF_TABLES,
        NF_HOOK_OP_BPF,
+       NF_HOOK_OP_NFT_FT,
 };
 
 struct nf_hook_ops {
index 84a561a74b9820edc5d037e986fb46ad948ef903..1a2c4d6424b5fbb9498b0d29dd18b31970d5bc13 100644 (file)
@@ -61,10 +61,12 @@ enum nfnl_hook_chain_desc_attributes {
  *
  * @NFNL_HOOK_TYPE_NFTABLES: nf_tables base chain
  * @NFNL_HOOK_TYPE_BPF: bpf program
+ * @NFNL_HOOK_TYPE_NFT_FLOWTABLE: nf_tables flowtable
  */
 enum nfnl_hook_chaintype {
        NFNL_HOOK_TYPE_NFTABLES = 0x1,
        NFNL_HOOK_TYPE_BPF,
+       NFNL_HOOK_TYPE_NFT_FLOWTABLE,
 };
 
 /**
index 04795af6e586835a0b9322aa3ae27833dfed69c7..13d0ed9d18954e74354a80f5dd513e63bb608035 100644 (file)
@@ -8895,11 +8895,12 @@ static int nft_flowtable_parse_hook(const struct nft_ctx *ctx,
 
        list_for_each_entry(hook, &flowtable_hook->list, list) {
                list_for_each_entry(ops, &hook->ops_list, list) {
-                       ops->pf         = NFPROTO_NETDEV;
-                       ops->hooknum    = flowtable_hook->num;
-                       ops->priority   = flowtable_hook->priority;
-                       ops->priv       = &flowtable->data;
-                       ops->hook       = flowtable->data.type->hook;
+                       ops->pf                 = NFPROTO_NETDEV;
+                       ops->hooknum            = flowtable_hook->num;
+                       ops->priority           = flowtable_hook->priority;
+                       ops->priv               = &flowtable->data;
+                       ops->hook               = flowtable->data.type->hook;
+                       ops->hook_ops_type      = NF_HOOK_OP_NFT_FT;
                }
        }
 
@@ -9727,12 +9728,13 @@ static int nft_flowtable_event(unsigned long event, struct net_device *dev,
                        if (!ops)
                                return 1;
 
-                       ops->pf         = NFPROTO_NETDEV;
-                       ops->hooknum    = flowtable->hooknum;
-                       ops->priority   = flowtable->data.priority;
-                       ops->priv       = &flowtable->data;
-                       ops->hook       = flowtable->data.type->hook;
-                       ops->dev        = dev;
+                       ops->pf                 = NFPROTO_NETDEV;
+                       ops->hooknum            = flowtable->hooknum;
+                       ops->priority           = flowtable->data.priority;
+                       ops->priv               = &flowtable->data;
+                       ops->hook               = flowtable->data.type->hook;
+                       ops->hook_ops_type      = NF_HOOK_OP_NFT_FT;
+                       ops->dev                = dev;
                        if (nft_register_flowtable_ops(dev_net(dev),
                                                       flowtable, ops)) {
                                kfree(ops);
index cd4056527ede7b87eee2435441050dfd08097cf5..92d869317cba5e57e0d45fed3bc03cd8a253cad4 100644 (file)
@@ -156,6 +156,38 @@ static int nfnl_hook_put_nft_chain_info(struct sk_buff *nlskb,
        return 0;
 }
 
+static int nfnl_hook_put_nft_ft_info(struct sk_buff *nlskb,
+                                    const struct nfnl_dump_hook_data *ctx,
+                                    unsigned int seq,
+                                    struct nf_flowtable *nf_ft)
+{
+       struct nft_flowtable *ft =
+               container_of(nf_ft, struct nft_flowtable, data);
+       struct net *net = sock_net(nlskb->sk);
+       struct nlattr *nest;
+       int ret = 0;
+
+       if (WARN_ON_ONCE(!nf_ft))
+               return 0;
+
+       if (!nft_is_active(net, ft))
+               return 0;
+
+       nest = nfnl_start_info_type(nlskb, NFNL_HOOK_TYPE_NFT_FLOWTABLE);
+       if (!nest)
+               return -EMSGSIZE;
+
+       ret = nfnl_hook_put_nft_info_desc(nlskb, ft->table->name,
+                                         ft->name, ft->table->family);
+       if (ret) {
+               nla_nest_cancel(nlskb, nest);
+               return ret;
+       }
+
+       nla_nest_end(nlskb, nest);
+       return 0;
+}
+
 static int nfnl_hook_dump_one(struct sk_buff *nlskb,
                              const struct nfnl_dump_hook_data *ctx,
                              const struct nf_hook_ops *ops,
@@ -223,6 +255,9 @@ static int nfnl_hook_dump_one(struct sk_buff *nlskb,
        case NF_HOOK_OP_BPF:
                ret = nfnl_hook_put_bpf_prog_info(nlskb, ctx, seq, ops->priv);
                break;
+       case NF_HOOK_OP_NFT_FT:
+               ret = nfnl_hook_put_nft_ft_info(nlskb, ctx, seq, ops->priv);
+               break;
        case NF_HOOK_OP_UNDEFINED:
                break;
        default: