diff options
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r-- | net/ipv6/addrconf.c | 40 |
1 files changed, 17 insertions, 23 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 0b239fc1816e..3e118dfddd02 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -1690,14 +1690,12 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp) | |||
1690 | addrconf_mod_dad_work(ifp, 0); | 1690 | addrconf_mod_dad_work(ifp, 0); |
1691 | } | 1691 | } |
1692 | 1692 | ||
1693 | /* Join to solicited addr multicast group. */ | 1693 | /* Join to solicited addr multicast group. |
1694 | 1694 | * caller must hold RTNL */ | |
1695 | void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr) | 1695 | void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr) |
1696 | { | 1696 | { |
1697 | struct in6_addr maddr; | 1697 | struct in6_addr maddr; |
1698 | 1698 | ||
1699 | ASSERT_RTNL(); | ||
1700 | |||
1701 | if (dev->flags&(IFF_LOOPBACK|IFF_NOARP)) | 1699 | if (dev->flags&(IFF_LOOPBACK|IFF_NOARP)) |
1702 | return; | 1700 | return; |
1703 | 1701 | ||
@@ -1705,12 +1703,11 @@ void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr) | |||
1705 | ipv6_dev_mc_inc(dev, &maddr); | 1703 | ipv6_dev_mc_inc(dev, &maddr); |
1706 | } | 1704 | } |
1707 | 1705 | ||
1706 | /* caller must hold RTNL */ | ||
1708 | void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr) | 1707 | void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr) |
1709 | { | 1708 | { |
1710 | struct in6_addr maddr; | 1709 | struct in6_addr maddr; |
1711 | 1710 | ||
1712 | ASSERT_RTNL(); | ||
1713 | |||
1714 | if (idev->dev->flags&(IFF_LOOPBACK|IFF_NOARP)) | 1711 | if (idev->dev->flags&(IFF_LOOPBACK|IFF_NOARP)) |
1715 | return; | 1712 | return; |
1716 | 1713 | ||
@@ -1718,12 +1715,11 @@ void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr) | |||
1718 | __ipv6_dev_mc_dec(idev, &maddr); | 1715 | __ipv6_dev_mc_dec(idev, &maddr); |
1719 | } | 1716 | } |
1720 | 1717 | ||
1718 | /* caller must hold RTNL */ | ||
1721 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp) | 1719 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp) |
1722 | { | 1720 | { |
1723 | struct in6_addr addr; | 1721 | struct in6_addr addr; |
1724 | 1722 | ||
1725 | ASSERT_RTNL(); | ||
1726 | |||
1727 | if (ifp->prefix_len >= 127) /* RFC 6164 */ | 1723 | if (ifp->prefix_len >= 127) /* RFC 6164 */ |
1728 | return; | 1724 | return; |
1729 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); | 1725 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); |
@@ -1732,12 +1728,11 @@ static void addrconf_join_anycast(struct inet6_ifaddr *ifp) | |||
1732 | ipv6_dev_ac_inc(ifp->idev->dev, &addr); | 1728 | ipv6_dev_ac_inc(ifp->idev->dev, &addr); |
1733 | } | 1729 | } |
1734 | 1730 | ||
1731 | /* caller must hold RTNL */ | ||
1735 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp) | 1732 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp) |
1736 | { | 1733 | { |
1737 | struct in6_addr addr; | 1734 | struct in6_addr addr; |
1738 | 1735 | ||
1739 | ASSERT_RTNL(); | ||
1740 | |||
1741 | if (ifp->prefix_len >= 127) /* RFC 6164 */ | 1736 | if (ifp->prefix_len >= 127) /* RFC 6164 */ |
1742 | return; | 1737 | return; |
1743 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); | 1738 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); |
@@ -3099,11 +3094,13 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
3099 | 3094 | ||
3100 | write_unlock_bh(&idev->lock); | 3095 | write_unlock_bh(&idev->lock); |
3101 | 3096 | ||
3102 | /* Step 5: Discard multicast list */ | 3097 | /* Step 5: Discard anycast and multicast list */ |
3103 | if (how) | 3098 | if (how) { |
3099 | ipv6_ac_destroy_dev(idev); | ||
3104 | ipv6_mc_destroy_dev(idev); | 3100 | ipv6_mc_destroy_dev(idev); |
3105 | else | 3101 | } else { |
3106 | ipv6_mc_down(idev); | 3102 | ipv6_mc_down(idev); |
3103 | } | ||
3107 | 3104 | ||
3108 | idev->tstamp = jiffies; | 3105 | idev->tstamp = jiffies; |
3109 | 3106 | ||
@@ -4773,24 +4770,21 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | |||
4773 | addrconf_leave_solict(ifp->idev, &ifp->addr); | 4770 | addrconf_leave_solict(ifp->idev, &ifp->addr); |
4774 | if (!ipv6_addr_any(&ifp->peer_addr)) { | 4771 | if (!ipv6_addr_any(&ifp->peer_addr)) { |
4775 | struct rt6_info *rt; | 4772 | struct rt6_info *rt; |
4776 | struct net_device *dev = ifp->idev->dev; | 4773 | |
4777 | 4774 | rt = addrconf_get_prefix_route(&ifp->peer_addr, 128, | |
4778 | rt = rt6_lookup(dev_net(dev), &ifp->peer_addr, NULL, | 4775 | ifp->idev->dev, 0, 0); |
4779 | dev->ifindex, 1); | 4776 | if (rt && ip6_del_rt(rt)) |
4780 | if (rt) { | 4777 | dst_free(&rt->dst); |
4781 | dst_hold(&rt->dst); | ||
4782 | if (ip6_del_rt(rt)) | ||
4783 | dst_free(&rt->dst); | ||
4784 | } | ||
4785 | } | 4778 | } |
4786 | dst_hold(&ifp->rt->dst); | 4779 | dst_hold(&ifp->rt->dst); |
4787 | 4780 | ||
4788 | if (ip6_del_rt(ifp->rt)) | 4781 | if (ip6_del_rt(ifp->rt)) |
4789 | dst_free(&ifp->rt->dst); | 4782 | dst_free(&ifp->rt->dst); |
4783 | |||
4784 | rt_genid_bump_ipv6(net); | ||
4790 | break; | 4785 | break; |
4791 | } | 4786 | } |
4792 | atomic_inc(&net->ipv6.dev_addr_genid); | 4787 | atomic_inc(&net->ipv6.dev_addr_genid); |
4793 | rt_genid_bump_ipv6(net); | ||
4794 | } | 4788 | } |
4795 | 4789 | ||
4796 | static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | 4790 | static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) |