diff mbox series

[nf-next,v3,12/16] netfilter: nf_tables: flowtable: Respect NETDEV_REGISTER events

Message ID 20240912122148.12159-13-phil@nwl.cc
State Superseded, archived
Headers show
Series Dynamic hook interface binding | expand

Commit Message

Phil Sutter Sept. 12, 2024, 12:21 p.m. UTC
Hook into new devices if their name matches the hook spec.

Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 net/netfilter/nf_tables_api.c | 47 +++++++++++++++++++++++++++--------
 1 file changed, 37 insertions(+), 10 deletions(-)
diff mbox series

Patch

diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 64f8305189f1..40cff8539c74 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -9314,15 +9314,41 @@  static void nft_flowtable_event(unsigned long event, struct net_device *dev,
 	struct nft_hook *hook;
 
 	list_for_each_entry(hook, &flowtable->hook_list, list) {
-		ops = nft_hook_find_ops(hook, dev);
-		if (!ops)
-			continue;
+		switch (event) {
+		case NETDEV_UNREGISTER:
+			ops = nft_hook_find_ops(hook, dev);
+			if (!ops)
+				continue;
 
-		/* flow_offload_netdev_event() cleans up entries for us. */
-		nft_unregister_flowtable_ops(dev_net(dev), flowtable, ops);
-		list_del(&ops->list);
-		kfree(ops);
-		break;
+			/* flow_offload_netdev_event() cleans up entries for us. */
+			nft_unregister_flowtable_ops(dev_net(dev),
+						     flowtable, ops);
+			list_del(&ops->list);
+			kfree(ops);
+			break;
+		case NETDEV_REGISTER:
+			if (strcmp(hook->ifname, dev->name))
+				continue;
+			ops = kzalloc(sizeof(struct nf_hook_ops),
+				      GFP_KERNEL_ACCOUNT);
+			if (ops) {
+				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;
+			}
+			if (ops && !nft_register_flowtable_ops(dev_net(dev),
+							       flowtable, ops)) {
+				list_add_tail(&ops->list, &hook->ops_list);
+				break;
+			}
+			printk(KERN_ERR "flowtable %s: Can't hook into device %s\n",
+			       flowtable->name, dev->name);
+			kfree(ops);
+			continue;
+		}
 	}
 }
 
@@ -9335,8 +9361,9 @@  static int nf_tables_flowtable_event(struct notifier_block *this,
 	struct nft_table *table;
 	struct net *net;
 
-	if (event != NETDEV_UNREGISTER)
-		return 0;
+	if (event != NETDEV_REGISTER &&
+	    event != NETDEV_UNREGISTER)
+		return NOTIFY_DONE;
 
 	net = dev_net(dev);
 	nft_net = nft_pernet(net);