reduce code duplication and will simplify follow-up patch

Signed-off-by: Paolo Abeni <pab...@redhat.com>
---
 net/ipv6/addrconf.c | 65 +++++++++++++++++++++++++----------------------------
 1 file changed, 31 insertions(+), 34 deletions(-)

diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index c2e2a78787ec..5940062cac8d 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1796,35 +1796,46 @@ int ipv6_chk_addr(struct net *net, const struct 
in6_addr *addr,
 }
 EXPORT_SYMBOL(ipv6_chk_addr);
 
+/* called under RCU lock with bh disabled */
+static struct inet6_ifaddr *ipv6_lookup_ifaddr_rcu_bh(struct net *net,
+                                                   const struct in6_addr *addr)
+{
+       unsigned int hash = inet6_addr_hash(addr);
+       struct inet6_ifaddr *ifp;
+
+       hlist_for_each_entry_rcu_bh(ifp, &inet6_addr_lst[hash], addr_lst)
+               if (net_eq(dev_net(ifp->idev->dev), net) &&
+                   ipv6_addr_equal(&ifp->addr, addr))
+                       return ifp;
+
+       return NULL;
+}
+
 int ipv6_chk_addr_and_flags(struct net *net, const struct in6_addr *addr,
                            const struct net_device *dev, int strict,
                            u32 banned_flags)
 {
        struct inet6_ifaddr *ifp;
-       unsigned int hash = inet6_addr_hash(addr);
        u32 ifp_flags;
+       int ret = 0;
 
        rcu_read_lock_bh();
-       hlist_for_each_entry_rcu(ifp, &inet6_addr_lst[hash], addr_lst) {
-               if (!net_eq(dev_net(ifp->idev->dev), net))
-                       continue;
+       ifp = ipv6_lookup_ifaddr_rcu_bh(net, addr);
+       if (ifp) {
                /* Decouple optimistic from tentative for evaluation here.
                 * Ban optimistic addresses explicitly, when required.
                 */
                ifp_flags = (ifp->flags&IFA_F_OPTIMISTIC)
                            ? (ifp->flags&~IFA_F_TENTATIVE)
                            : ifp->flags;
-               if (ipv6_addr_equal(&ifp->addr, addr) &&
-                   !(ifp_flags&banned_flags) &&
+               if (!(ifp_flags&banned_flags) &&
                    (!dev || ifp->idev->dev == dev ||
-                    !(ifp->scope&(IFA_LINK|IFA_HOST) || strict))) {
-                       rcu_read_unlock_bh();
-                       return 1;
-               }
+                    !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)))
+                       ret = 1;
        }
 
        rcu_read_unlock_bh();
-       return 0;
+       return ret;
 }
 EXPORT_SYMBOL(ipv6_chk_addr_and_flags);
 
@@ -1900,20 +1911,13 @@ struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, 
const struct in6_addr *add
                                     struct net_device *dev, int strict)
 {
        struct inet6_ifaddr *ifp, *result = NULL;
-       unsigned int hash = inet6_addr_hash(addr);
 
        rcu_read_lock_bh();
-       hlist_for_each_entry_rcu_bh(ifp, &inet6_addr_lst[hash], addr_lst) {
-               if (!net_eq(dev_net(ifp->idev->dev), net))
-                       continue;
-               if (ipv6_addr_equal(&ifp->addr, addr)) {
-                       if (!dev || ifp->idev->dev == dev ||
-                           !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) {
-                               result = ifp;
-                               in6_ifa_hold(ifp);
-                               break;
-                       }
-               }
+       ifp = ipv6_lookup_ifaddr_rcu_bh(net, addr);
+       if (ifp && (!dev || ifp->idev->dev == dev ||
+                   !(ifp->scope & (IFA_LINK|IFA_HOST) || strict))) {
+               result = ifp;
+               in6_ifa_hold(ifp);
        }
        rcu_read_unlock_bh();
 
@@ -4226,20 +4230,13 @@ void if6_proc_exit(void)
 /* Check if address is a home address configured on any interface. */
 int ipv6_chk_home_addr(struct net *net, const struct in6_addr *addr)
 {
-       int ret = 0;
        struct inet6_ifaddr *ifp = NULL;
-       unsigned int hash = inet6_addr_hash(addr);
+       int ret = 0;
 
        rcu_read_lock_bh();
-       hlist_for_each_entry_rcu_bh(ifp, &inet6_addr_lst[hash], addr_lst) {
-               if (!net_eq(dev_net(ifp->idev->dev), net))
-                       continue;
-               if (ipv6_addr_equal(&ifp->addr, addr) &&
-                   (ifp->flags & IFA_F_HOMEADDRESS)) {
-                       ret = 1;
-                       break;
-               }
-       }
+       ifp = ipv6_lookup_ifaddr_rcu_bh(net, addr);
+       if (ifp && ifp->flags & IFA_F_HOMEADDRESS)
+               ret = 1;
        rcu_read_unlock_bh();
        return ret;
 }
-- 
2.13.5

Reply via email to