]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
devinet: use in_dev_for_each_ifa_rcu in more places
authorFlorian Westphal <fw@strlen.de>
Fri, 31 May 2019 16:27:05 +0000 (18:27 +0200)
committerDavid S. Miller <davem@davemloft.net>
Mon, 3 Jun 2019 01:06:26 +0000 (18:06 -0700)
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>
net/ipv4/devinet.c

index 7803a4d2951c8acf8b0a59b961dcc6d6c0c17601..b45421b2b734d72ecd8b6f684c05093505a5563a 100644 (file)
@@ -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 @@ static int inet_gifconf(struct net_device *dev, char __user *buf, int len, int s
 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;