]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - net/ipv6/addrconf.c
l2tp: lock socket before checking flags in connect()
[mirror_ubuntu-bionic-kernel.git] / net / ipv6 / addrconf.c
index 060dd992201812c7a664cfaf13221a2dc3197c85..4bc5ba3ae452eb99ed3a70c0926f6bb1ed5c001a 100644 (file)
@@ -183,7 +183,7 @@ static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx,
 
 static void addrconf_dad_start(struct inet6_ifaddr *ifp);
 static void addrconf_dad_work(struct work_struct *w);
-static void addrconf_dad_completed(struct inet6_ifaddr *ifp);
+static void addrconf_dad_completed(struct inet6_ifaddr *ifp, bool bump_id);
 static void addrconf_dad_run(struct inet6_dev *idev);
 static void addrconf_rs_timer(unsigned long data);
 static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa);
@@ -2898,6 +2898,7 @@ static void add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
                spin_lock_bh(&ifp->lock);
                ifp->flags &= ~IFA_F_TENTATIVE;
                spin_unlock_bh(&ifp->lock);
+               rt_genid_bump_ipv6(dev_net(idev->dev));
                ipv6_ifa_notify(RTM_NEWADDR, ifp);
                in6_ifa_put(ifp);
        }
@@ -3740,7 +3741,7 @@ static void addrconf_dad_begin(struct inet6_ifaddr *ifp)
 {
        struct inet6_dev *idev = ifp->idev;
        struct net_device *dev = idev->dev;
-       bool notify = false;
+       bool bump_id, notify = false;
 
        addrconf_join_solict(dev, &ifp->addr);
 
@@ -3755,11 +3756,12 @@ static void addrconf_dad_begin(struct inet6_ifaddr *ifp)
            idev->cnf.accept_dad < 1 ||
            !(ifp->flags&IFA_F_TENTATIVE) ||
            ifp->flags & IFA_F_NODAD) {
+               bump_id = ifp->flags & IFA_F_TENTATIVE;
                ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED);
                spin_unlock(&ifp->lock);
                read_unlock_bh(&idev->lock);
 
-               addrconf_dad_completed(ifp);
+               addrconf_dad_completed(ifp, bump_id);
                return;
        }
 
@@ -3819,8 +3821,8 @@ static void addrconf_dad_work(struct work_struct *w)
                                                struct inet6_ifaddr,
                                                dad_work);
        struct inet6_dev *idev = ifp->idev;
+       bool bump_id, disable_ipv6 = false;
        struct in6_addr mcaddr;
-       bool disable_ipv6 = false;
 
        enum {
                DAD_PROCESS,
@@ -3890,11 +3892,12 @@ static void addrconf_dad_work(struct work_struct *w)
                 * DAD was successful
                 */
 
+               bump_id = ifp->flags & IFA_F_TENTATIVE;
                ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED);
                spin_unlock(&ifp->lock);
                write_unlock_bh(&idev->lock);
 
-               addrconf_dad_completed(ifp);
+               addrconf_dad_completed(ifp, bump_id);
 
                goto out;
        }
@@ -3931,7 +3934,7 @@ static bool ipv6_lonely_lladdr(struct inet6_ifaddr *ifp)
        return true;
 }
 
-static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
+static void addrconf_dad_completed(struct inet6_ifaddr *ifp, bool bump_id)
 {
        struct net_device *dev = ifp->idev->dev;
        struct in6_addr lladdr;
@@ -3983,6 +3986,9 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
                spin_unlock(&ifp->lock);
                write_unlock_bh(&ifp->idev->lock);
        }
+
+       if (bump_id)
+               rt_genid_bump_ipv6(dev_net(dev));
 }
 
 static void addrconf_dad_run(struct inet6_dev *idev)