Commit e225376d authored by Phil Sutter's avatar Phil Sutter Committed by Pablo Neira Ayuso
Browse files

netfilter: nf_tables: Introduce nft_hook_find_ops{,_rcu}()



Also a pretty dull wrapper around the hook->ops.dev comparison for now.
Will search the embedded nf_hook_ops list in future. The ugly cast to
eliminate the const qualifier will vanish then, too.

Since this future list will be RCU-protected, also introduce an _rcu()
variant here.

Signed-off-by: default avatarPhil Sutter <phil@nwl.cc>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 75e20bcd
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -1205,6 +1205,11 @@ struct nft_hook {
	u8			ifnamelen;
};

struct nf_hook_ops *nft_hook_find_ops(const struct nft_hook *hook,
				      const struct net_device *dev);
struct nf_hook_ops *nft_hook_find_ops_rcu(const struct nft_hook *hook,
					  const struct net_device *dev);

/**
 *	struct nft_base_chain - nf_tables base chain
 *
+20 −1
Original line number Diff line number Diff line
@@ -9600,13 +9600,32 @@ static int nf_tables_fill_gen_info(struct sk_buff *skb, struct net *net,
	return -EMSGSIZE;
}

struct nf_hook_ops *nft_hook_find_ops(const struct nft_hook *hook,
				      const struct net_device *dev)
{
	if (hook->ops.dev == dev)
		return (struct nf_hook_ops *)&hook->ops;

	return NULL;
}
EXPORT_SYMBOL_GPL(nft_hook_find_ops);

struct nf_hook_ops *nft_hook_find_ops_rcu(const struct nft_hook *hook,
					  const struct net_device *dev)
{
	return nft_hook_find_ops(hook, dev);
}
EXPORT_SYMBOL_GPL(nft_hook_find_ops_rcu);

static void nft_flowtable_event(unsigned long event, struct net_device *dev,
				struct nft_flowtable *flowtable)
{
	struct nf_hook_ops *ops;
	struct nft_hook *hook;

	list_for_each_entry(hook, &flowtable->hook_list, list) {
		if (hook->ops.dev != dev)
		ops = nft_hook_find_ops(hook, dev);
		if (!ops)
			continue;

		/* flow_offload_netdev_event() cleans up entries for us. */
+1 −1
Original line number Diff line number Diff line
@@ -638,7 +638,7 @@ static struct nft_chain *__nft_offload_get_chain(const struct nftables_pernet *n
			found = NULL;
			basechain = nft_base_chain(chain);
			list_for_each_entry(hook, &basechain->hook_list, list) {
				if (hook->ops.dev != dev)
				if (!nft_hook_find_ops(hook, dev))
					continue;

				found = hook;
+4 −2
Original line number Diff line number Diff line
@@ -321,14 +321,16 @@ static const struct nft_chain_type nft_chain_filter_netdev = {
static void nft_netdev_event(unsigned long event, struct net_device *dev,
			     struct nft_base_chain *basechain)
{
	struct nf_hook_ops *ops;
	struct nft_hook *hook;

	list_for_each_entry(hook, &basechain->hook_list, list) {
		if (hook->ops.dev != dev)
		ops = nft_hook_find_ops(hook, dev);
		if (!ops)
			continue;

		if (!(basechain->chain.table->flags & NFT_TABLE_F_DORMANT))
			nf_unregister_net_hook(dev_net(dev), &hook->ops);
			nf_unregister_net_hook(dev_net(dev), ops);

		list_del_rcu(&hook->list);
		kfree_rcu(hook, rcu);
+1 −1
Original line number Diff line number Diff line
@@ -175,7 +175,7 @@ static bool nft_flowtable_find_dev(const struct net_device *dev,
	bool found = false;

	list_for_each_entry_rcu(hook, &ft->hook_list, list) {
		if (hook->ops.dev != dev)
		if (!nft_hook_find_ops_rcu(hook, dev))
			continue;

		found = true;