diff options
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r-- | net/ipv6/addrconf.c | 133 |
1 files changed, 115 insertions, 18 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 73a23b4130a5..a60585fd85ad 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -137,6 +137,7 @@ static int addrconf_ifdown(struct net_device *dev, int how); | |||
137 | static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags); | 137 | static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags); |
138 | static void addrconf_dad_timer(unsigned long data); | 138 | static void addrconf_dad_timer(unsigned long data); |
139 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp); | 139 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp); |
140 | static void addrconf_dad_run(struct inet6_dev *idev); | ||
140 | static void addrconf_rs_timer(unsigned long data); | 141 | static void addrconf_rs_timer(unsigned long data); |
141 | static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); | 142 | static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); |
142 | static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); | 143 | static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); |
@@ -388,6 +389,9 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
388 | } | 389 | } |
389 | #endif | 390 | #endif |
390 | 391 | ||
392 | if (netif_carrier_ok(dev)) | ||
393 | ndev->if_flags |= IF_READY; | ||
394 | |||
391 | write_lock_bh(&addrconf_lock); | 395 | write_lock_bh(&addrconf_lock); |
392 | dev->ip6_ptr = ndev; | 396 | dev->ip6_ptr = ndev; |
393 | write_unlock_bh(&addrconf_lock); | 397 | write_unlock_bh(&addrconf_lock); |
@@ -415,6 +419,7 @@ static struct inet6_dev * ipv6_find_idev(struct net_device *dev) | |||
415 | if ((idev = ipv6_add_dev(dev)) == NULL) | 419 | if ((idev = ipv6_add_dev(dev)) == NULL) |
416 | return NULL; | 420 | return NULL; |
417 | } | 421 | } |
422 | |||
418 | if (dev->flags&IFF_UP) | 423 | if (dev->flags&IFF_UP) |
419 | ipv6_mc_up(idev); | 424 | ipv6_mc_up(idev); |
420 | return idev; | 425 | return idev; |
@@ -634,8 +639,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
634 | } | 639 | } |
635 | #endif | 640 | #endif |
636 | 641 | ||
637 | for (ifap = &idev->addr_list; (ifa=*ifap) != NULL; | 642 | for (ifap = &idev->addr_list; (ifa=*ifap) != NULL;) { |
638 | ifap = &ifa->if_next) { | ||
639 | if (ifa == ifp) { | 643 | if (ifa == ifp) { |
640 | *ifap = ifa->if_next; | 644 | *ifap = ifa->if_next; |
641 | __in6_ifa_put(ifp); | 645 | __in6_ifa_put(ifp); |
@@ -643,6 +647,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
643 | if (!(ifp->flags & IFA_F_PERMANENT) || onlink > 0) | 647 | if (!(ifp->flags & IFA_F_PERMANENT) || onlink > 0) |
644 | break; | 648 | break; |
645 | deleted = 1; | 649 | deleted = 1; |
650 | continue; | ||
646 | } else if (ifp->flags & IFA_F_PERMANENT) { | 651 | } else if (ifp->flags & IFA_F_PERMANENT) { |
647 | if (ipv6_prefix_equal(&ifa->addr, &ifp->addr, | 652 | if (ipv6_prefix_equal(&ifa->addr, &ifp->addr, |
648 | ifp->prefix_len)) { | 653 | ifp->prefix_len)) { |
@@ -666,6 +671,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
666 | } | 671 | } |
667 | } | 672 | } |
668 | } | 673 | } |
674 | ifap = &ifa->if_next; | ||
669 | } | 675 | } |
670 | write_unlock_bh(&idev->lock); | 676 | write_unlock_bh(&idev->lock); |
671 | 677 | ||
@@ -903,11 +909,18 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
903 | 909 | ||
904 | score.addr_type = __ipv6_addr_type(&ifa->addr); | 910 | score.addr_type = __ipv6_addr_type(&ifa->addr); |
905 | 911 | ||
906 | /* Rule 0: Candidate Source Address (section 4) | 912 | /* Rule 0: |
913 | * - Tentative Address (RFC2462 section 5.4) | ||
914 | * - A tentative address is not considered | ||
915 | * "assigned to an interface" in the traditional | ||
916 | * sense. | ||
917 | * - Candidate Source Address (section 4) | ||
907 | * - In any case, anycast addresses, multicast | 918 | * - In any case, anycast addresses, multicast |
908 | * addresses, and the unspecified address MUST | 919 | * addresses, and the unspecified address MUST |
909 | * NOT be included in a candidate set. | 920 | * NOT be included in a candidate set. |
910 | */ | 921 | */ |
922 | if (ifa->flags & IFA_F_TENTATIVE) | ||
923 | continue; | ||
911 | if (unlikely(score.addr_type == IPV6_ADDR_ANY || | 924 | if (unlikely(score.addr_type == IPV6_ADDR_ANY || |
912 | score.addr_type & IPV6_ADDR_MULTICAST)) { | 925 | score.addr_type & IPV6_ADDR_MULTICAST)) { |
913 | LIMIT_NETDEBUG(KERN_DEBUG | 926 | LIMIT_NETDEBUG(KERN_DEBUG |
@@ -1215,10 +1228,8 @@ int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) | |||
1215 | 1228 | ||
1216 | /* Gets referenced address, destroys ifaddr */ | 1229 | /* Gets referenced address, destroys ifaddr */ |
1217 | 1230 | ||
1218 | void addrconf_dad_failure(struct inet6_ifaddr *ifp) | 1231 | void addrconf_dad_stop(struct inet6_ifaddr *ifp) |
1219 | { | 1232 | { |
1220 | if (net_ratelimit()) | ||
1221 | printk(KERN_INFO "%s: duplicate address detected!\n", ifp->idev->dev->name); | ||
1222 | if (ifp->flags&IFA_F_PERMANENT) { | 1233 | if (ifp->flags&IFA_F_PERMANENT) { |
1223 | spin_lock_bh(&ifp->lock); | 1234 | spin_lock_bh(&ifp->lock); |
1224 | addrconf_del_timer(ifp); | 1235 | addrconf_del_timer(ifp); |
@@ -1244,6 +1255,12 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp) | |||
1244 | ipv6_del_addr(ifp); | 1255 | ipv6_del_addr(ifp); |
1245 | } | 1256 | } |
1246 | 1257 | ||
1258 | void addrconf_dad_failure(struct inet6_ifaddr *ifp) | ||
1259 | { | ||
1260 | if (net_ratelimit()) | ||
1261 | printk(KERN_INFO "%s: duplicate address detected!\n", ifp->idev->dev->name); | ||
1262 | addrconf_dad_stop(ifp); | ||
1263 | } | ||
1247 | 1264 | ||
1248 | /* Join to solicited addr multicast group. */ | 1265 | /* Join to solicited addr multicast group. */ |
1249 | 1266 | ||
@@ -1596,9 +1613,17 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) | |||
1596 | not good. | 1613 | not good. |
1597 | */ | 1614 | */ |
1598 | if (valid_lft >= 0x7FFFFFFF/HZ) | 1615 | if (valid_lft >= 0x7FFFFFFF/HZ) |
1599 | rt_expires = 0; | 1616 | rt_expires = 0x7FFFFFFF - (0x7FFFFFFF % HZ); |
1600 | else | 1617 | else |
1601 | rt_expires = jiffies + valid_lft * HZ; | 1618 | rt_expires = valid_lft * HZ; |
1619 | |||
1620 | /* | ||
1621 | * We convert this (in jiffies) to clock_t later. | ||
1622 | * Avoid arithmetic overflow there as well. | ||
1623 | * Overflow can happen only if HZ < USER_HZ. | ||
1624 | */ | ||
1625 | if (HZ < USER_HZ && rt_expires > 0x7FFFFFFF / USER_HZ) | ||
1626 | rt_expires = 0x7FFFFFFF / USER_HZ; | ||
1602 | 1627 | ||
1603 | if (pinfo->onlink) { | 1628 | if (pinfo->onlink) { |
1604 | struct rt6_info *rt; | 1629 | struct rt6_info *rt; |
@@ -1610,12 +1635,12 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) | |||
1610 | ip6_del_rt(rt, NULL, NULL, NULL); | 1635 | ip6_del_rt(rt, NULL, NULL, NULL); |
1611 | rt = NULL; | 1636 | rt = NULL; |
1612 | } else { | 1637 | } else { |
1613 | rt->rt6i_expires = rt_expires; | 1638 | rt->rt6i_expires = jiffies + rt_expires; |
1614 | } | 1639 | } |
1615 | } | 1640 | } |
1616 | } else if (valid_lft) { | 1641 | } else if (valid_lft) { |
1617 | addrconf_prefix_route(&pinfo->prefix, pinfo->prefix_len, | 1642 | addrconf_prefix_route(&pinfo->prefix, pinfo->prefix_len, |
1618 | dev, rt_expires, RTF_ADDRCONF|RTF_EXPIRES|RTF_PREFIX_RT); | 1643 | dev, jiffies_to_clock_t(rt_expires), RTF_ADDRCONF|RTF_EXPIRES|RTF_PREFIX_RT); |
1619 | } | 1644 | } |
1620 | if (rt) | 1645 | if (rt) |
1621 | dst_release(&rt->u.dst); | 1646 | dst_release(&rt->u.dst); |
@@ -2125,9 +2150,42 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2125 | { | 2150 | { |
2126 | struct net_device *dev = (struct net_device *) data; | 2151 | struct net_device *dev = (struct net_device *) data; |
2127 | struct inet6_dev *idev = __in6_dev_get(dev); | 2152 | struct inet6_dev *idev = __in6_dev_get(dev); |
2153 | int run_pending = 0; | ||
2128 | 2154 | ||
2129 | switch(event) { | 2155 | switch(event) { |
2130 | case NETDEV_UP: | 2156 | case NETDEV_UP: |
2157 | case NETDEV_CHANGE: | ||
2158 | if (event == NETDEV_UP) { | ||
2159 | if (!netif_carrier_ok(dev)) { | ||
2160 | /* device is not ready yet. */ | ||
2161 | printk(KERN_INFO | ||
2162 | "ADDRCONF(NETDEV_UP): %s: " | ||
2163 | "link is not ready\n", | ||
2164 | dev->name); | ||
2165 | break; | ||
2166 | } | ||
2167 | } else { | ||
2168 | if (!netif_carrier_ok(dev)) { | ||
2169 | /* device is still not ready. */ | ||
2170 | break; | ||
2171 | } | ||
2172 | |||
2173 | if (idev) { | ||
2174 | if (idev->if_flags & IF_READY) { | ||
2175 | /* device is already configured. */ | ||
2176 | break; | ||
2177 | } | ||
2178 | idev->if_flags |= IF_READY; | ||
2179 | } | ||
2180 | |||
2181 | printk(KERN_INFO | ||
2182 | "ADDRCONF(NETDEV_CHANGE): %s: " | ||
2183 | "link becomes ready\n", | ||
2184 | dev->name); | ||
2185 | |||
2186 | run_pending = 1; | ||
2187 | } | ||
2188 | |||
2131 | switch(dev->type) { | 2189 | switch(dev->type) { |
2132 | case ARPHRD_SIT: | 2190 | case ARPHRD_SIT: |
2133 | addrconf_sit_config(dev); | 2191 | addrconf_sit_config(dev); |
@@ -2144,6 +2202,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2144 | break; | 2202 | break; |
2145 | }; | 2203 | }; |
2146 | if (idev) { | 2204 | if (idev) { |
2205 | if (run_pending) | ||
2206 | addrconf_dad_run(idev); | ||
2207 | |||
2147 | /* If the MTU changed during the interface down, when the | 2208 | /* If the MTU changed during the interface down, when the |
2148 | interface up, the changed MTU must be reflected in the | 2209 | interface up, the changed MTU must be reflected in the |
2149 | idev as well as routers. | 2210 | idev as well as routers. |
@@ -2178,8 +2239,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2178 | */ | 2239 | */ |
2179 | addrconf_ifdown(dev, event != NETDEV_DOWN); | 2240 | addrconf_ifdown(dev, event != NETDEV_DOWN); |
2180 | break; | 2241 | break; |
2181 | case NETDEV_CHANGE: | 2242 | |
2182 | break; | ||
2183 | case NETDEV_CHANGENAME: | 2243 | case NETDEV_CHANGENAME: |
2184 | #ifdef CONFIG_SYSCTL | 2244 | #ifdef CONFIG_SYSCTL |
2185 | if (idev) { | 2245 | if (idev) { |
@@ -2260,7 +2320,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2260 | 2320 | ||
2261 | /* Step 3: clear flags for stateless addrconf */ | 2321 | /* Step 3: clear flags for stateless addrconf */ |
2262 | if (how != 1) | 2322 | if (how != 1) |
2263 | idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD); | 2323 | idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY); |
2264 | 2324 | ||
2265 | /* Step 4: clear address list */ | 2325 | /* Step 4: clear address list */ |
2266 | #ifdef CONFIG_IPV6_PRIVACY | 2326 | #ifdef CONFIG_IPV6_PRIVACY |
@@ -2369,11 +2429,20 @@ out: | |||
2369 | /* | 2429 | /* |
2370 | * Duplicate Address Detection | 2430 | * Duplicate Address Detection |
2371 | */ | 2431 | */ |
2432 | static void addrconf_dad_kick(struct inet6_ifaddr *ifp) | ||
2433 | { | ||
2434 | unsigned long rand_num; | ||
2435 | struct inet6_dev *idev = ifp->idev; | ||
2436 | |||
2437 | rand_num = net_random() % (idev->cnf.rtr_solicit_delay ? : 1); | ||
2438 | ifp->probes = idev->cnf.dad_transmits; | ||
2439 | addrconf_mod_timer(ifp, AC_DAD, rand_num); | ||
2440 | } | ||
2441 | |||
2372 | static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | 2442 | static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) |
2373 | { | 2443 | { |
2374 | struct inet6_dev *idev = ifp->idev; | 2444 | struct inet6_dev *idev = ifp->idev; |
2375 | struct net_device *dev = idev->dev; | 2445 | struct net_device *dev = idev->dev; |
2376 | unsigned long rand_num; | ||
2377 | 2446 | ||
2378 | addrconf_join_solict(dev, &ifp->addr); | 2447 | addrconf_join_solict(dev, &ifp->addr); |
2379 | 2448 | ||
@@ -2382,7 +2451,6 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | |||
2382 | flags); | 2451 | flags); |
2383 | 2452 | ||
2384 | net_srandom(ifp->addr.s6_addr32[3]); | 2453 | net_srandom(ifp->addr.s6_addr32[3]); |
2385 | rand_num = net_random() % (idev->cnf.rtr_solicit_delay ? : 1); | ||
2386 | 2454 | ||
2387 | read_lock_bh(&idev->lock); | 2455 | read_lock_bh(&idev->lock); |
2388 | if (ifp->dead) | 2456 | if (ifp->dead) |
@@ -2399,9 +2467,19 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | |||
2399 | return; | 2467 | return; |
2400 | } | 2468 | } |
2401 | 2469 | ||
2402 | ifp->probes = idev->cnf.dad_transmits; | 2470 | if (!(idev->if_flags & IF_READY)) { |
2403 | addrconf_mod_timer(ifp, AC_DAD, rand_num); | 2471 | spin_unlock_bh(&ifp->lock); |
2404 | 2472 | read_unlock_bh(&idev->lock); | |
2473 | /* | ||
2474 | * If the defice is not ready: | ||
2475 | * - keep it tentative if it is a permanent address. | ||
2476 | * - otherwise, kill it. | ||
2477 | */ | ||
2478 | in6_ifa_hold(ifp); | ||
2479 | addrconf_dad_stop(ifp); | ||
2480 | return; | ||
2481 | } | ||
2482 | addrconf_dad_kick(ifp); | ||
2405 | spin_unlock_bh(&ifp->lock); | 2483 | spin_unlock_bh(&ifp->lock); |
2406 | out: | 2484 | out: |
2407 | read_unlock_bh(&idev->lock); | 2485 | read_unlock_bh(&idev->lock); |
@@ -2484,6 +2562,22 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp) | |||
2484 | } | 2562 | } |
2485 | } | 2563 | } |
2486 | 2564 | ||
2565 | static void addrconf_dad_run(struct inet6_dev *idev) { | ||
2566 | struct inet6_ifaddr *ifp; | ||
2567 | |||
2568 | read_lock_bh(&idev->lock); | ||
2569 | for (ifp = idev->addr_list; ifp; ifp = ifp->if_next) { | ||
2570 | spin_lock_bh(&ifp->lock); | ||
2571 | if (!(ifp->flags & IFA_F_TENTATIVE)) { | ||
2572 | spin_unlock_bh(&ifp->lock); | ||
2573 | continue; | ||
2574 | } | ||
2575 | spin_unlock_bh(&ifp->lock); | ||
2576 | addrconf_dad_kick(ifp); | ||
2577 | } | ||
2578 | read_unlock_bh(&idev->lock); | ||
2579 | } | ||
2580 | |||
2487 | #ifdef CONFIG_PROC_FS | 2581 | #ifdef CONFIG_PROC_FS |
2488 | struct if6_iter_state { | 2582 | struct if6_iter_state { |
2489 | int bucket; | 2583 | int bucket; |
@@ -2689,6 +2783,9 @@ restart: | |||
2689 | in6_ifa_hold(ifpub); | 2783 | in6_ifa_hold(ifpub); |
2690 | spin_unlock(&ifp->lock); | 2784 | spin_unlock(&ifp->lock); |
2691 | read_unlock(&addrconf_hash_lock); | 2785 | read_unlock(&addrconf_hash_lock); |
2786 | spin_lock(&ifpub->lock); | ||
2787 | ifpub->regen_count = 0; | ||
2788 | spin_unlock(&ifpub->lock); | ||
2692 | ipv6_create_tempaddr(ifpub, ifp); | 2789 | ipv6_create_tempaddr(ifpub, ifp); |
2693 | in6_ifa_put(ifpub); | 2790 | in6_ifa_put(ifpub); |
2694 | in6_ifa_put(ifp); | 2791 | in6_ifa_put(ifp); |