Commit 4709b4fd authored by Hideaki Yoshifuji's avatar Hideaki Yoshifuji

[IPV6] Stop DAD during shutting down the interface.

Signed-off-by: default avatarHideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
parent fed20f2d
...@@ -2130,11 +2130,10 @@ static void addrconf_rs_timer(unsigned long data) ...@@ -2130,11 +2130,10 @@ static void addrconf_rs_timer(unsigned long data)
*/ */
static void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags) static void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags)
{ {
struct net_device *dev; struct inet6_dev *idev = ifp->idev;
struct net_device *dev = idev->dev;
unsigned long rand_num; unsigned long rand_num;
dev = ifp->idev->dev;
addrconf_join_solict(dev, &ifp->addr); addrconf_join_solict(dev, &ifp->addr);
if (ifp->prefix_len != 128 && (ifp->flags&IFA_F_PERMANENT)) if (ifp->prefix_len != 128 && (ifp->flags&IFA_F_PERMANENT))
...@@ -2142,31 +2141,43 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags) ...@@ -2142,31 +2141,43 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags)
flags); flags);
net_srandom(ifp->addr.s6_addr32[3]); net_srandom(ifp->addr.s6_addr32[3]);
rand_num = net_random() % (ifp->idev->cnf.rtr_solicit_delay ? : 1); rand_num = net_random() % (idev->cnf.rtr_solicit_delay ? : 1);
read_lock_bh(&idev->lock);
if (ifp->dead)
goto out;
spin_lock_bh(&ifp->lock); spin_lock_bh(&ifp->lock);
if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) ||
!(ifp->flags&IFA_F_TENTATIVE)) { !(ifp->flags&IFA_F_TENTATIVE)) {
ifp->flags &= ~IFA_F_TENTATIVE; ifp->flags &= ~IFA_F_TENTATIVE;
spin_unlock_bh(&ifp->lock); spin_unlock_bh(&ifp->lock);
read_unlock_bh(&idev->lock);
addrconf_dad_completed(ifp); addrconf_dad_completed(ifp);
return; return;
} }
ifp->probes = ifp->idev->cnf.dad_transmits; ifp->probes = idev->cnf.dad_transmits;
addrconf_mod_timer(ifp, AC_DAD, rand_num); addrconf_mod_timer(ifp, AC_DAD, rand_num);
spin_unlock_bh(&ifp->lock); spin_unlock_bh(&ifp->lock);
out:
read_unlock_bh(&idev->lock);
} }
static void addrconf_dad_timer(unsigned long data) static void addrconf_dad_timer(unsigned long data)
{ {
struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data; struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data;
struct inet6_dev *idev = ifp->idev;
struct in6_addr unspec; struct in6_addr unspec;
struct in6_addr mcaddr; struct in6_addr mcaddr;
read_lock_bh(&idev->lock);
if (idev->dead) {
read_unlock_bh(&idev->lock);
goto out;
}
spin_lock_bh(&ifp->lock); spin_lock_bh(&ifp->lock);
if (ifp->probes == 0) { if (ifp->probes == 0) {
/* /*
...@@ -2175,22 +2186,23 @@ static void addrconf_dad_timer(unsigned long data) ...@@ -2175,22 +2186,23 @@ static void addrconf_dad_timer(unsigned long data)
ifp->flags &= ~IFA_F_TENTATIVE; ifp->flags &= ~IFA_F_TENTATIVE;
spin_unlock_bh(&ifp->lock); spin_unlock_bh(&ifp->lock);
read_unlock_bh(&idev->lock);
addrconf_dad_completed(ifp); addrconf_dad_completed(ifp);
in6_ifa_put(ifp); goto out;
return;
} }
ifp->probes--; ifp->probes--;
addrconf_mod_timer(ifp, AC_DAD, ifp->idev->nd_parms->retrans_time); addrconf_mod_timer(ifp, AC_DAD, ifp->idev->nd_parms->retrans_time);
spin_unlock_bh(&ifp->lock); spin_unlock_bh(&ifp->lock);
read_unlock_bh(&idev->lock);
/* send a neighbour solicitation for our addr */ /* send a neighbour solicitation for our addr */
memset(&unspec, 0, sizeof(unspec)); memset(&unspec, 0, sizeof(unspec));
addrconf_addr_solict_mult(&ifp->addr, &mcaddr); addrconf_addr_solict_mult(&ifp->addr, &mcaddr);
ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &unspec); ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &unspec);
out:
in6_ifa_put(ifp); in6_ifa_put(ifp);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment