diff options
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r-- | net/ipv6/addrconf.c | 193 |
1 files changed, 142 insertions, 51 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 344e972426df..6c7fa0853fc7 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -133,10 +133,12 @@ static int ipv6_count_addresses(struct inet6_dev *idev); | |||
133 | static struct hlist_head inet6_addr_lst[IN6_ADDR_HSIZE]; | 133 | static struct hlist_head inet6_addr_lst[IN6_ADDR_HSIZE]; |
134 | static DEFINE_SPINLOCK(addrconf_hash_lock); | 134 | static DEFINE_SPINLOCK(addrconf_hash_lock); |
135 | 135 | ||
136 | static void addrconf_verify(unsigned long); | 136 | static void addrconf_verify(void); |
137 | static void addrconf_verify_rtnl(void); | ||
138 | static void addrconf_verify_work(struct work_struct *); | ||
137 | 139 | ||
138 | static DEFINE_TIMER(addr_chk_timer, addrconf_verify, 0, 0); | 140 | static struct workqueue_struct *addrconf_wq; |
139 | static DEFINE_SPINLOCK(addrconf_verify_lock); | 141 | static DECLARE_DELAYED_WORK(addr_chk_work, addrconf_verify_work); |
140 | 142 | ||
141 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp); | 143 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp); |
142 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp); | 144 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp); |
@@ -151,7 +153,7 @@ static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx, | |||
151 | u32 flags, u32 noflags); | 153 | u32 flags, u32 noflags); |
152 | 154 | ||
153 | static void addrconf_dad_start(struct inet6_ifaddr *ifp); | 155 | static void addrconf_dad_start(struct inet6_ifaddr *ifp); |
154 | static void addrconf_dad_timer(unsigned long data); | 156 | static void addrconf_dad_work(struct work_struct *w); |
155 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp); | 157 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp); |
156 | static void addrconf_dad_run(struct inet6_dev *idev); | 158 | static void addrconf_dad_run(struct inet6_dev *idev); |
157 | static void addrconf_rs_timer(unsigned long data); | 159 | static void addrconf_rs_timer(unsigned long data); |
@@ -247,9 +249,9 @@ static void addrconf_del_rs_timer(struct inet6_dev *idev) | |||
247 | __in6_dev_put(idev); | 249 | __in6_dev_put(idev); |
248 | } | 250 | } |
249 | 251 | ||
250 | static void addrconf_del_dad_timer(struct inet6_ifaddr *ifp) | 252 | static void addrconf_del_dad_work(struct inet6_ifaddr *ifp) |
251 | { | 253 | { |
252 | if (del_timer(&ifp->dad_timer)) | 254 | if (cancel_delayed_work(&ifp->dad_work)) |
253 | __in6_ifa_put(ifp); | 255 | __in6_ifa_put(ifp); |
254 | } | 256 | } |
255 | 257 | ||
@@ -261,12 +263,12 @@ static void addrconf_mod_rs_timer(struct inet6_dev *idev, | |||
261 | mod_timer(&idev->rs_timer, jiffies + when); | 263 | mod_timer(&idev->rs_timer, jiffies + when); |
262 | } | 264 | } |
263 | 265 | ||
264 | static void addrconf_mod_dad_timer(struct inet6_ifaddr *ifp, | 266 | static void addrconf_mod_dad_work(struct inet6_ifaddr *ifp, |
265 | unsigned long when) | 267 | unsigned long delay) |
266 | { | 268 | { |
267 | if (!timer_pending(&ifp->dad_timer)) | 269 | if (!delayed_work_pending(&ifp->dad_work)) |
268 | in6_ifa_hold(ifp); | 270 | in6_ifa_hold(ifp); |
269 | mod_timer(&ifp->dad_timer, jiffies + when); | 271 | mod_delayed_work(addrconf_wq, &ifp->dad_work, delay); |
270 | } | 272 | } |
271 | 273 | ||
272 | static int snmp6_alloc_dev(struct inet6_dev *idev) | 274 | static int snmp6_alloc_dev(struct inet6_dev *idev) |
@@ -751,8 +753,9 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) | |||
751 | 753 | ||
752 | in6_dev_put(ifp->idev); | 754 | in6_dev_put(ifp->idev); |
753 | 755 | ||
754 | if (del_timer(&ifp->dad_timer)) | 756 | if (cancel_delayed_work(&ifp->dad_work)) |
755 | pr_notice("Timer is still running, when freeing ifa=%p\n", ifp); | 757 | pr_notice("delayed DAD work was pending while freeing ifa=%p\n", |
758 | ifp); | ||
756 | 759 | ||
757 | if (ifp->state != INET6_IFADDR_STATE_DEAD) { | 760 | if (ifp->state != INET6_IFADDR_STATE_DEAD) { |
758 | pr_warn("Freeing alive inet6 address %p\n", ifp); | 761 | pr_warn("Freeing alive inet6 address %p\n", ifp); |
@@ -849,8 +852,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, | |||
849 | 852 | ||
850 | spin_lock_init(&ifa->lock); | 853 | spin_lock_init(&ifa->lock); |
851 | spin_lock_init(&ifa->state_lock); | 854 | spin_lock_init(&ifa->state_lock); |
852 | setup_timer(&ifa->dad_timer, addrconf_dad_timer, | 855 | INIT_DELAYED_WORK(&ifa->dad_work, addrconf_dad_work); |
853 | (unsigned long)ifa); | ||
854 | INIT_HLIST_NODE(&ifa->addr_lst); | 856 | INIT_HLIST_NODE(&ifa->addr_lst); |
855 | ifa->scope = scope; | 857 | ifa->scope = scope; |
856 | ifa->prefix_len = pfxlen; | 858 | ifa->prefix_len = pfxlen; |
@@ -990,6 +992,8 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
990 | enum cleanup_prefix_rt_t action = CLEANUP_PREFIX_RT_NOP; | 992 | enum cleanup_prefix_rt_t action = CLEANUP_PREFIX_RT_NOP; |
991 | unsigned long expires; | 993 | unsigned long expires; |
992 | 994 | ||
995 | ASSERT_RTNL(); | ||
996 | |||
993 | spin_lock_bh(&ifp->state_lock); | 997 | spin_lock_bh(&ifp->state_lock); |
994 | state = ifp->state; | 998 | state = ifp->state; |
995 | ifp->state = INET6_IFADDR_STATE_DEAD; | 999 | ifp->state = INET6_IFADDR_STATE_DEAD; |
@@ -1021,7 +1025,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
1021 | 1025 | ||
1022 | write_unlock_bh(&ifp->idev->lock); | 1026 | write_unlock_bh(&ifp->idev->lock); |
1023 | 1027 | ||
1024 | addrconf_del_dad_timer(ifp); | 1028 | addrconf_del_dad_work(ifp); |
1025 | 1029 | ||
1026 | ipv6_ifa_notify(RTM_DELADDR, ifp); | 1030 | ipv6_ifa_notify(RTM_DELADDR, ifp); |
1027 | 1031 | ||
@@ -1604,7 +1608,7 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed) | |||
1604 | { | 1608 | { |
1605 | if (ifp->flags&IFA_F_PERMANENT) { | 1609 | if (ifp->flags&IFA_F_PERMANENT) { |
1606 | spin_lock_bh(&ifp->lock); | 1610 | spin_lock_bh(&ifp->lock); |
1607 | addrconf_del_dad_timer(ifp); | 1611 | addrconf_del_dad_work(ifp); |
1608 | ifp->flags |= IFA_F_TENTATIVE; | 1612 | ifp->flags |= IFA_F_TENTATIVE; |
1609 | if (dad_failed) | 1613 | if (dad_failed) |
1610 | ifp->flags |= IFA_F_DADFAILED; | 1614 | ifp->flags |= IFA_F_DADFAILED; |
@@ -1625,20 +1629,21 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed) | |||
1625 | spin_unlock_bh(&ifp->lock); | 1629 | spin_unlock_bh(&ifp->lock); |
1626 | } | 1630 | } |
1627 | ipv6_del_addr(ifp); | 1631 | ipv6_del_addr(ifp); |
1628 | } else | 1632 | } else { |
1629 | ipv6_del_addr(ifp); | 1633 | ipv6_del_addr(ifp); |
1634 | } | ||
1630 | } | 1635 | } |
1631 | 1636 | ||
1632 | static int addrconf_dad_end(struct inet6_ifaddr *ifp) | 1637 | static int addrconf_dad_end(struct inet6_ifaddr *ifp) |
1633 | { | 1638 | { |
1634 | int err = -ENOENT; | 1639 | int err = -ENOENT; |
1635 | 1640 | ||
1636 | spin_lock(&ifp->state_lock); | 1641 | spin_lock_bh(&ifp->state_lock); |
1637 | if (ifp->state == INET6_IFADDR_STATE_DAD) { | 1642 | if (ifp->state == INET6_IFADDR_STATE_DAD) { |
1638 | ifp->state = INET6_IFADDR_STATE_POSTDAD; | 1643 | ifp->state = INET6_IFADDR_STATE_POSTDAD; |
1639 | err = 0; | 1644 | err = 0; |
1640 | } | 1645 | } |
1641 | spin_unlock(&ifp->state_lock); | 1646 | spin_unlock_bh(&ifp->state_lock); |
1642 | 1647 | ||
1643 | return err; | 1648 | return err; |
1644 | } | 1649 | } |
@@ -1671,7 +1676,12 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp) | |||
1671 | } | 1676 | } |
1672 | } | 1677 | } |
1673 | 1678 | ||
1674 | addrconf_dad_stop(ifp, 1); | 1679 | spin_lock_bh(&ifp->state_lock); |
1680 | /* transition from _POSTDAD to _ERRDAD */ | ||
1681 | ifp->state = INET6_IFADDR_STATE_ERRDAD; | ||
1682 | spin_unlock_bh(&ifp->state_lock); | ||
1683 | |||
1684 | addrconf_mod_dad_work(ifp, 0); | ||
1675 | } | 1685 | } |
1676 | 1686 | ||
1677 | /* Join to solicited addr multicast group. */ | 1687 | /* Join to solicited addr multicast group. */ |
@@ -1680,6 +1690,8 @@ void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr) | |||
1680 | { | 1690 | { |
1681 | struct in6_addr maddr; | 1691 | struct in6_addr maddr; |
1682 | 1692 | ||
1693 | ASSERT_RTNL(); | ||
1694 | |||
1683 | if (dev->flags&(IFF_LOOPBACK|IFF_NOARP)) | 1695 | if (dev->flags&(IFF_LOOPBACK|IFF_NOARP)) |
1684 | return; | 1696 | return; |
1685 | 1697 | ||
@@ -1691,6 +1703,8 @@ void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr) | |||
1691 | { | 1703 | { |
1692 | struct in6_addr maddr; | 1704 | struct in6_addr maddr; |
1693 | 1705 | ||
1706 | ASSERT_RTNL(); | ||
1707 | |||
1694 | if (idev->dev->flags&(IFF_LOOPBACK|IFF_NOARP)) | 1708 | if (idev->dev->flags&(IFF_LOOPBACK|IFF_NOARP)) |
1695 | return; | 1709 | return; |
1696 | 1710 | ||
@@ -1701,6 +1715,9 @@ void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr) | |||
1701 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp) | 1715 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp) |
1702 | { | 1716 | { |
1703 | struct in6_addr addr; | 1717 | struct in6_addr addr; |
1718 | |||
1719 | ASSERT_RTNL(); | ||
1720 | |||
1704 | if (ifp->prefix_len >= 127) /* RFC 6164 */ | 1721 | if (ifp->prefix_len >= 127) /* RFC 6164 */ |
1705 | return; | 1722 | return; |
1706 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); | 1723 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); |
@@ -1712,6 +1729,9 @@ static void addrconf_join_anycast(struct inet6_ifaddr *ifp) | |||
1712 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp) | 1729 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp) |
1713 | { | 1730 | { |
1714 | struct in6_addr addr; | 1731 | struct in6_addr addr; |
1732 | |||
1733 | ASSERT_RTNL(); | ||
1734 | |||
1715 | if (ifp->prefix_len >= 127) /* RFC 6164 */ | 1735 | if (ifp->prefix_len >= 127) /* RFC 6164 */ |
1716 | return; | 1736 | return; |
1717 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); | 1737 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); |
@@ -2271,11 +2291,13 @@ ok: | |||
2271 | return; | 2291 | return; |
2272 | } | 2292 | } |
2273 | 2293 | ||
2274 | ifp->flags |= IFA_F_MANAGETEMPADDR; | ||
2275 | update_lft = 0; | 2294 | update_lft = 0; |
2276 | create = 1; | 2295 | create = 1; |
2296 | spin_lock_bh(&ifp->lock); | ||
2297 | ifp->flags |= IFA_F_MANAGETEMPADDR; | ||
2277 | ifp->cstamp = jiffies; | 2298 | ifp->cstamp = jiffies; |
2278 | ifp->tokenized = tokenized; | 2299 | ifp->tokenized = tokenized; |
2300 | spin_unlock_bh(&ifp->lock); | ||
2279 | addrconf_dad_start(ifp); | 2301 | addrconf_dad_start(ifp); |
2280 | } | 2302 | } |
2281 | 2303 | ||
@@ -2326,7 +2348,7 @@ ok: | |||
2326 | create, now); | 2348 | create, now); |
2327 | 2349 | ||
2328 | in6_ifa_put(ifp); | 2350 | in6_ifa_put(ifp); |
2329 | addrconf_verify(0); | 2351 | addrconf_verify(); |
2330 | } | 2352 | } |
2331 | } | 2353 | } |
2332 | inet6_prefix_notify(RTM_NEWPREFIX, in6_dev, pinfo); | 2354 | inet6_prefix_notify(RTM_NEWPREFIX, in6_dev, pinfo); |
@@ -2475,7 +2497,7 @@ static int inet6_addr_add(struct net *net, int ifindex, | |||
2475 | manage_tempaddrs(idev, ifp, valid_lft, prefered_lft, | 2497 | manage_tempaddrs(idev, ifp, valid_lft, prefered_lft, |
2476 | true, jiffies); | 2498 | true, jiffies); |
2477 | in6_ifa_put(ifp); | 2499 | in6_ifa_put(ifp); |
2478 | addrconf_verify(0); | 2500 | addrconf_verify_rtnl(); |
2479 | return 0; | 2501 | return 0; |
2480 | } | 2502 | } |
2481 | 2503 | ||
@@ -3011,7 +3033,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
3011 | hlist_for_each_entry_rcu(ifa, h, addr_lst) { | 3033 | hlist_for_each_entry_rcu(ifa, h, addr_lst) { |
3012 | if (ifa->idev == idev) { | 3034 | if (ifa->idev == idev) { |
3013 | hlist_del_init_rcu(&ifa->addr_lst); | 3035 | hlist_del_init_rcu(&ifa->addr_lst); |
3014 | addrconf_del_dad_timer(ifa); | 3036 | addrconf_del_dad_work(ifa); |
3015 | goto restart; | 3037 | goto restart; |
3016 | } | 3038 | } |
3017 | } | 3039 | } |
@@ -3049,7 +3071,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
3049 | while (!list_empty(&idev->addr_list)) { | 3071 | while (!list_empty(&idev->addr_list)) { |
3050 | ifa = list_first_entry(&idev->addr_list, | 3072 | ifa = list_first_entry(&idev->addr_list, |
3051 | struct inet6_ifaddr, if_list); | 3073 | struct inet6_ifaddr, if_list); |
3052 | addrconf_del_dad_timer(ifa); | 3074 | addrconf_del_dad_work(ifa); |
3053 | 3075 | ||
3054 | list_del(&ifa->if_list); | 3076 | list_del(&ifa->if_list); |
3055 | 3077 | ||
@@ -3148,10 +3170,10 @@ static void addrconf_dad_kick(struct inet6_ifaddr *ifp) | |||
3148 | rand_num = prandom_u32() % (idev->cnf.rtr_solicit_delay ? : 1); | 3170 | rand_num = prandom_u32() % (idev->cnf.rtr_solicit_delay ? : 1); |
3149 | 3171 | ||
3150 | ifp->dad_probes = idev->cnf.dad_transmits; | 3172 | ifp->dad_probes = idev->cnf.dad_transmits; |
3151 | addrconf_mod_dad_timer(ifp, rand_num); | 3173 | addrconf_mod_dad_work(ifp, rand_num); |
3152 | } | 3174 | } |
3153 | 3175 | ||
3154 | static void addrconf_dad_start(struct inet6_ifaddr *ifp) | 3176 | static void addrconf_dad_begin(struct inet6_ifaddr *ifp) |
3155 | { | 3177 | { |
3156 | struct inet6_dev *idev = ifp->idev; | 3178 | struct inet6_dev *idev = ifp->idev; |
3157 | struct net_device *dev = idev->dev; | 3179 | struct net_device *dev = idev->dev; |
@@ -3203,25 +3225,68 @@ out: | |||
3203 | read_unlock_bh(&idev->lock); | 3225 | read_unlock_bh(&idev->lock); |
3204 | } | 3226 | } |
3205 | 3227 | ||
3206 | static void addrconf_dad_timer(unsigned long data) | 3228 | static void addrconf_dad_start(struct inet6_ifaddr *ifp) |
3207 | { | 3229 | { |
3208 | struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data; | 3230 | bool begin_dad = false; |
3231 | |||
3232 | spin_lock_bh(&ifp->state_lock); | ||
3233 | if (ifp->state != INET6_IFADDR_STATE_DEAD) { | ||
3234 | ifp->state = INET6_IFADDR_STATE_PREDAD; | ||
3235 | begin_dad = true; | ||
3236 | } | ||
3237 | spin_unlock_bh(&ifp->state_lock); | ||
3238 | |||
3239 | if (begin_dad) | ||
3240 | addrconf_mod_dad_work(ifp, 0); | ||
3241 | } | ||
3242 | |||
3243 | static void addrconf_dad_work(struct work_struct *w) | ||
3244 | { | ||
3245 | struct inet6_ifaddr *ifp = container_of(to_delayed_work(w), | ||
3246 | struct inet6_ifaddr, | ||
3247 | dad_work); | ||
3209 | struct inet6_dev *idev = ifp->idev; | 3248 | struct inet6_dev *idev = ifp->idev; |
3210 | struct in6_addr mcaddr; | 3249 | struct in6_addr mcaddr; |
3211 | 3250 | ||
3251 | enum { | ||
3252 | DAD_PROCESS, | ||
3253 | DAD_BEGIN, | ||
3254 | DAD_ABORT, | ||
3255 | } action = DAD_PROCESS; | ||
3256 | |||
3257 | rtnl_lock(); | ||
3258 | |||
3259 | spin_lock_bh(&ifp->state_lock); | ||
3260 | if (ifp->state == INET6_IFADDR_STATE_PREDAD) { | ||
3261 | action = DAD_BEGIN; | ||
3262 | ifp->state = INET6_IFADDR_STATE_DAD; | ||
3263 | } else if (ifp->state == INET6_IFADDR_STATE_ERRDAD) { | ||
3264 | action = DAD_ABORT; | ||
3265 | ifp->state = INET6_IFADDR_STATE_POSTDAD; | ||
3266 | } | ||
3267 | spin_unlock_bh(&ifp->state_lock); | ||
3268 | |||
3269 | if (action == DAD_BEGIN) { | ||
3270 | addrconf_dad_begin(ifp); | ||
3271 | goto out; | ||
3272 | } else if (action == DAD_ABORT) { | ||
3273 | addrconf_dad_stop(ifp, 1); | ||
3274 | goto out; | ||
3275 | } | ||
3276 | |||
3212 | if (!ifp->dad_probes && addrconf_dad_end(ifp)) | 3277 | if (!ifp->dad_probes && addrconf_dad_end(ifp)) |
3213 | goto out; | 3278 | goto out; |
3214 | 3279 | ||
3215 | write_lock(&idev->lock); | 3280 | write_lock_bh(&idev->lock); |
3216 | if (idev->dead || !(idev->if_flags & IF_READY)) { | 3281 | if (idev->dead || !(idev->if_flags & IF_READY)) { |
3217 | write_unlock(&idev->lock); | 3282 | write_unlock_bh(&idev->lock); |
3218 | goto out; | 3283 | goto out; |
3219 | } | 3284 | } |
3220 | 3285 | ||
3221 | spin_lock(&ifp->lock); | 3286 | spin_lock(&ifp->lock); |
3222 | if (ifp->state == INET6_IFADDR_STATE_DEAD) { | 3287 | if (ifp->state == INET6_IFADDR_STATE_DEAD) { |
3223 | spin_unlock(&ifp->lock); | 3288 | spin_unlock(&ifp->lock); |
3224 | write_unlock(&idev->lock); | 3289 | write_unlock_bh(&idev->lock); |
3225 | goto out; | 3290 | goto out; |
3226 | } | 3291 | } |
3227 | 3292 | ||
@@ -3232,7 +3297,7 @@ static void addrconf_dad_timer(unsigned long data) | |||
3232 | 3297 | ||
3233 | ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); | 3298 | ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); |
3234 | spin_unlock(&ifp->lock); | 3299 | spin_unlock(&ifp->lock); |
3235 | write_unlock(&idev->lock); | 3300 | write_unlock_bh(&idev->lock); |
3236 | 3301 | ||
3237 | addrconf_dad_completed(ifp); | 3302 | addrconf_dad_completed(ifp); |
3238 | 3303 | ||
@@ -3240,16 +3305,17 @@ static void addrconf_dad_timer(unsigned long data) | |||
3240 | } | 3305 | } |
3241 | 3306 | ||
3242 | ifp->dad_probes--; | 3307 | ifp->dad_probes--; |
3243 | addrconf_mod_dad_timer(ifp, | 3308 | addrconf_mod_dad_work(ifp, |
3244 | NEIGH_VAR(ifp->idev->nd_parms, RETRANS_TIME)); | 3309 | NEIGH_VAR(ifp->idev->nd_parms, RETRANS_TIME)); |
3245 | spin_unlock(&ifp->lock); | 3310 | spin_unlock(&ifp->lock); |
3246 | write_unlock(&idev->lock); | 3311 | write_unlock_bh(&idev->lock); |
3247 | 3312 | ||
3248 | /* send a neighbour solicitation for our addr */ | 3313 | /* send a neighbour solicitation for our addr */ |
3249 | addrconf_addr_solict_mult(&ifp->addr, &mcaddr); | 3314 | addrconf_addr_solict_mult(&ifp->addr, &mcaddr); |
3250 | ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &in6addr_any); | 3315 | ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &in6addr_any); |
3251 | out: | 3316 | out: |
3252 | in6_ifa_put(ifp); | 3317 | in6_ifa_put(ifp); |
3318 | rtnl_unlock(); | ||
3253 | } | 3319 | } |
3254 | 3320 | ||
3255 | /* ifp->idev must be at least read locked */ | 3321 | /* ifp->idev must be at least read locked */ |
@@ -3276,7 +3342,7 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp) | |||
3276 | struct in6_addr lladdr; | 3342 | struct in6_addr lladdr; |
3277 | bool send_rs, send_mld; | 3343 | bool send_rs, send_mld; |
3278 | 3344 | ||
3279 | addrconf_del_dad_timer(ifp); | 3345 | addrconf_del_dad_work(ifp); |
3280 | 3346 | ||
3281 | /* | 3347 | /* |
3282 | * Configure the address for reception. Now it is valid. | 3348 | * Configure the address for reception. Now it is valid. |
@@ -3517,23 +3583,23 @@ int ipv6_chk_home_addr(struct net *net, const struct in6_addr *addr) | |||
3517 | * Periodic address status verification | 3583 | * Periodic address status verification |
3518 | */ | 3584 | */ |
3519 | 3585 | ||
3520 | static void addrconf_verify(unsigned long foo) | 3586 | static void addrconf_verify_rtnl(void) |
3521 | { | 3587 | { |
3522 | unsigned long now, next, next_sec, next_sched; | 3588 | unsigned long now, next, next_sec, next_sched; |
3523 | struct inet6_ifaddr *ifp; | 3589 | struct inet6_ifaddr *ifp; |
3524 | int i; | 3590 | int i; |
3525 | 3591 | ||
3592 | ASSERT_RTNL(); | ||
3593 | |||
3526 | rcu_read_lock_bh(); | 3594 | rcu_read_lock_bh(); |
3527 | spin_lock(&addrconf_verify_lock); | ||
3528 | now = jiffies; | 3595 | now = jiffies; |
3529 | next = round_jiffies_up(now + ADDR_CHECK_FREQUENCY); | 3596 | next = round_jiffies_up(now + ADDR_CHECK_FREQUENCY); |
3530 | 3597 | ||
3531 | del_timer(&addr_chk_timer); | 3598 | cancel_delayed_work(&addr_chk_work); |
3532 | 3599 | ||
3533 | for (i = 0; i < IN6_ADDR_HSIZE; i++) { | 3600 | for (i = 0; i < IN6_ADDR_HSIZE; i++) { |
3534 | restart: | 3601 | restart: |
3535 | hlist_for_each_entry_rcu_bh(ifp, | 3602 | hlist_for_each_entry_rcu_bh(ifp, &inet6_addr_lst[i], addr_lst) { |
3536 | &inet6_addr_lst[i], addr_lst) { | ||
3537 | unsigned long age; | 3603 | unsigned long age; |
3538 | 3604 | ||
3539 | /* When setting preferred_lft to a value not zero or | 3605 | /* When setting preferred_lft to a value not zero or |
@@ -3628,13 +3694,22 @@ restart: | |||
3628 | 3694 | ||
3629 | ADBG(KERN_DEBUG "now = %lu, schedule = %lu, rounded schedule = %lu => %lu\n", | 3695 | ADBG(KERN_DEBUG "now = %lu, schedule = %lu, rounded schedule = %lu => %lu\n", |
3630 | now, next, next_sec, next_sched); | 3696 | now, next, next_sec, next_sched); |
3631 | 3697 | mod_delayed_work(addrconf_wq, &addr_chk_work, next_sched - now); | |
3632 | addr_chk_timer.expires = next_sched; | ||
3633 | add_timer(&addr_chk_timer); | ||
3634 | spin_unlock(&addrconf_verify_lock); | ||
3635 | rcu_read_unlock_bh(); | 3698 | rcu_read_unlock_bh(); |
3636 | } | 3699 | } |
3637 | 3700 | ||
3701 | static void addrconf_verify_work(struct work_struct *w) | ||
3702 | { | ||
3703 | rtnl_lock(); | ||
3704 | addrconf_verify_rtnl(); | ||
3705 | rtnl_unlock(); | ||
3706 | } | ||
3707 | |||
3708 | static void addrconf_verify(void) | ||
3709 | { | ||
3710 | mod_delayed_work(addrconf_wq, &addr_chk_work, 0); | ||
3711 | } | ||
3712 | |||
3638 | static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local, | 3713 | static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local, |
3639 | struct in6_addr **peer_pfx) | 3714 | struct in6_addr **peer_pfx) |
3640 | { | 3715 | { |
@@ -3691,6 +3766,8 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u32 ifa_flags, | |||
3691 | bool was_managetempaddr; | 3766 | bool was_managetempaddr; |
3692 | bool had_prefixroute; | 3767 | bool had_prefixroute; |
3693 | 3768 | ||
3769 | ASSERT_RTNL(); | ||
3770 | |||
3694 | if (!valid_lft || (prefered_lft > valid_lft)) | 3771 | if (!valid_lft || (prefered_lft > valid_lft)) |
3695 | return -EINVAL; | 3772 | return -EINVAL; |
3696 | 3773 | ||
@@ -3756,7 +3833,7 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u32 ifa_flags, | |||
3756 | !was_managetempaddr, jiffies); | 3833 | !was_managetempaddr, jiffies); |
3757 | } | 3834 | } |
3758 | 3835 | ||
3759 | addrconf_verify(0); | 3836 | addrconf_verify_rtnl(); |
3760 | 3837 | ||
3761 | return 0; | 3838 | return 0; |
3762 | } | 3839 | } |
@@ -4386,6 +4463,8 @@ static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token) | |||
4386 | bool update_rs = false; | 4463 | bool update_rs = false; |
4387 | struct in6_addr ll_addr; | 4464 | struct in6_addr ll_addr; |
4388 | 4465 | ||
4466 | ASSERT_RTNL(); | ||
4467 | |||
4389 | if (token == NULL) | 4468 | if (token == NULL) |
4390 | return -EINVAL; | 4469 | return -EINVAL; |
4391 | if (ipv6_addr_any(token)) | 4470 | if (ipv6_addr_any(token)) |
@@ -4434,7 +4513,7 @@ static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token) | |||
4434 | } | 4513 | } |
4435 | 4514 | ||
4436 | write_unlock_bh(&idev->lock); | 4515 | write_unlock_bh(&idev->lock); |
4437 | addrconf_verify(0); | 4516 | addrconf_verify_rtnl(); |
4438 | return 0; | 4517 | return 0; |
4439 | } | 4518 | } |
4440 | 4519 | ||
@@ -4636,6 +4715,9 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | |||
4636 | { | 4715 | { |
4637 | struct net *net = dev_net(ifp->idev->dev); | 4716 | struct net *net = dev_net(ifp->idev->dev); |
4638 | 4717 | ||
4718 | if (event) | ||
4719 | ASSERT_RTNL(); | ||
4720 | |||
4639 | inet6_ifa_notify(event ? : RTM_NEWADDR, ifp); | 4721 | inet6_ifa_notify(event ? : RTM_NEWADDR, ifp); |
4640 | 4722 | ||
4641 | switch (event) { | 4723 | switch (event) { |
@@ -5244,6 +5326,12 @@ int __init addrconf_init(void) | |||
5244 | if (err < 0) | 5326 | if (err < 0) |
5245 | goto out_addrlabel; | 5327 | goto out_addrlabel; |
5246 | 5328 | ||
5329 | addrconf_wq = create_workqueue("ipv6_addrconf"); | ||
5330 | if (!addrconf_wq) { | ||
5331 | err = -ENOMEM; | ||
5332 | goto out_nowq; | ||
5333 | } | ||
5334 | |||
5247 | /* The addrconf netdev notifier requires that loopback_dev | 5335 | /* The addrconf netdev notifier requires that loopback_dev |
5248 | * has it's ipv6 private information allocated and setup | 5336 | * has it's ipv6 private information allocated and setup |
5249 | * before it can bring up and give link-local addresses | 5337 | * before it can bring up and give link-local addresses |
@@ -5274,7 +5362,7 @@ int __init addrconf_init(void) | |||
5274 | 5362 | ||
5275 | register_netdevice_notifier(&ipv6_dev_notf); | 5363 | register_netdevice_notifier(&ipv6_dev_notf); |
5276 | 5364 | ||
5277 | addrconf_verify(0); | 5365 | addrconf_verify(); |
5278 | 5366 | ||
5279 | rtnl_af_register(&inet6_ops); | 5367 | rtnl_af_register(&inet6_ops); |
5280 | 5368 | ||
@@ -5302,6 +5390,8 @@ errout: | |||
5302 | rtnl_af_unregister(&inet6_ops); | 5390 | rtnl_af_unregister(&inet6_ops); |
5303 | unregister_netdevice_notifier(&ipv6_dev_notf); | 5391 | unregister_netdevice_notifier(&ipv6_dev_notf); |
5304 | errlo: | 5392 | errlo: |
5393 | destroy_workqueue(addrconf_wq); | ||
5394 | out_nowq: | ||
5305 | unregister_pernet_subsys(&addrconf_ops); | 5395 | unregister_pernet_subsys(&addrconf_ops); |
5306 | out_addrlabel: | 5396 | out_addrlabel: |
5307 | ipv6_addr_label_cleanup(); | 5397 | ipv6_addr_label_cleanup(); |
@@ -5337,7 +5427,8 @@ void addrconf_cleanup(void) | |||
5337 | for (i = 0; i < IN6_ADDR_HSIZE; i++) | 5427 | for (i = 0; i < IN6_ADDR_HSIZE; i++) |
5338 | WARN_ON(!hlist_empty(&inet6_addr_lst[i])); | 5428 | WARN_ON(!hlist_empty(&inet6_addr_lst[i])); |
5339 | spin_unlock_bh(&addrconf_hash_lock); | 5429 | spin_unlock_bh(&addrconf_hash_lock); |
5340 | 5430 | cancel_delayed_work(&addr_chk_work); | |
5341 | del_timer(&addr_chk_timer); | ||
5342 | rtnl_unlock(); | 5431 | rtnl_unlock(); |
5432 | |||
5433 | destroy_workqueue(addrconf_wq); | ||
5343 | } | 5434 | } |