Commit d519e870 authored by Florian Westphal's avatar Florian Westphal Committed by David S. Miller
Browse files

devinet: use in_dev_for_each_ifa_rcu in more places



This also replaces spots that used for_primary_ifa().

for_primary_ifa() aborts the loop on the first secondary address seen.

Replace it with either the rcu or rtnl variant of in_dev_for_each_ifa(),
but two places will now also consider secondary addresses too:
inet_addr_onlink() and inet_ifa_byprefix().

I do not understand why they should ignore secondary addresses.

Why would a secondary address not be considered 'on link'?
When matching a prefix, why ignore a matching secondary address?

Other places get converted as well, but gain "->flags & SECONDARY" check.

Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ef11db33
Loading
Loading
Loading
Loading
+19 −8
Original line number Diff line number Diff line
@@ -327,15 +327,17 @@ static void inetdev_destroy(struct in_device *in_dev)

int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b)
{
	const struct in_ifaddr *ifa;

	rcu_read_lock();
	for_primary_ifa(in_dev) {
	in_dev_for_each_ifa_rcu(ifa, in_dev) {
		if (inet_ifa_match(a, ifa)) {
			if (!b || inet_ifa_match(b, ifa)) {
				rcu_read_unlock();
				return 1;
			}
		}
	} endfor_ifa(in_dev);
	}
	rcu_read_unlock();
	return 0;
}
@@ -580,12 +582,14 @@ EXPORT_SYMBOL(inetdev_by_index);
struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, __be32 prefix,
				    __be32 mask)
{
	struct in_ifaddr *ifa;

	ASSERT_RTNL();

	for_primary_ifa(in_dev) {
	in_dev_for_each_ifa_rtnl(ifa, in_dev) {
		if (ifa->ifa_mask == mask && inet_ifa_match(prefix, ifa))
			return ifa;
	} endfor_ifa(in_dev);
	}
	return NULL;
}

@@ -1245,17 +1249,22 @@ out:
static __be32 in_dev_select_addr(const struct in_device *in_dev,
				 int scope)
{
	for_primary_ifa(in_dev) {
	const struct in_ifaddr *ifa;

	in_dev_for_each_ifa_rcu(ifa, in_dev) {
		if (ifa->ifa_flags & IFA_F_SECONDARY)
			continue;
		if (ifa->ifa_scope != RT_SCOPE_LINK &&
		    ifa->ifa_scope <= scope)
			return ifa->ifa_local;
	} endfor_ifa(in_dev);
	}

	return 0;
}

__be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope)
{
	const struct in_ifaddr *ifa;
	__be32 addr = 0;
	struct in_device *in_dev;
	struct net *net = dev_net(dev);
@@ -1266,7 +1275,9 @@ __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope)
	if (!in_dev)
		goto no_in_dev;

	for_primary_ifa(in_dev) {
	in_dev_for_each_ifa_rcu(ifa, in_dev) {
		if (ifa->ifa_flags & IFA_F_SECONDARY)
			continue;
		if (ifa->ifa_scope > scope)
			continue;
		if (!dst || inet_ifa_match(dst, ifa)) {
@@ -1275,7 +1286,7 @@ __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope)
		}
		if (!addr)
			addr = ifa->ifa_local;
	} endfor_ifa(in_dev);
	}

	if (addr)
		goto out_unlock;