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: Florian Westphal <fw@strlen.de> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
ef11db3310
commit
d519e8708b
@ -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)
|
int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b)
|
||||||
{
|
{
|
||||||
|
const struct in_ifaddr *ifa;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
for_primary_ifa(in_dev) {
|
in_dev_for_each_ifa_rcu(ifa, in_dev) {
|
||||||
if (inet_ifa_match(a, ifa)) {
|
if (inet_ifa_match(a, ifa)) {
|
||||||
if (!b || inet_ifa_match(b, ifa)) {
|
if (!b || inet_ifa_match(b, ifa)) {
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} endfor_ifa(in_dev);
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -580,12 +582,14 @@ EXPORT_SYMBOL(inetdev_by_index);
|
|||||||
struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, __be32 prefix,
|
struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, __be32 prefix,
|
||||||
__be32 mask)
|
__be32 mask)
|
||||||
{
|
{
|
||||||
|
struct in_ifaddr *ifa;
|
||||||
|
|
||||||
ASSERT_RTNL();
|
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))
|
if (ifa->ifa_mask == mask && inet_ifa_match(prefix, ifa))
|
||||||
return ifa;
|
return ifa;
|
||||||
} endfor_ifa(in_dev);
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1245,17 +1249,22 @@ out:
|
|||||||
static __be32 in_dev_select_addr(const struct in_device *in_dev,
|
static __be32 in_dev_select_addr(const struct in_device *in_dev,
|
||||||
int scope)
|
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 &&
|
if (ifa->ifa_scope != RT_SCOPE_LINK &&
|
||||||
ifa->ifa_scope <= scope)
|
ifa->ifa_scope <= scope)
|
||||||
return ifa->ifa_local;
|
return ifa->ifa_local;
|
||||||
} endfor_ifa(in_dev);
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
__be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope)
|
__be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope)
|
||||||
{
|
{
|
||||||
|
const struct in_ifaddr *ifa;
|
||||||
__be32 addr = 0;
|
__be32 addr = 0;
|
||||||
struct in_device *in_dev;
|
struct in_device *in_dev;
|
||||||
struct net *net = dev_net(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)
|
if (!in_dev)
|
||||||
goto no_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)
|
if (ifa->ifa_scope > scope)
|
||||||
continue;
|
continue;
|
||||||
if (!dst || inet_ifa_match(dst, ifa)) {
|
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)
|
if (!addr)
|
||||||
addr = ifa->ifa_local;
|
addr = ifa->ifa_local;
|
||||||
} endfor_ifa(in_dev);
|
}
|
||||||
|
|
||||||
if (addr)
|
if (addr)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user