diff options
Diffstat (limited to 'net/ipv6/addrconf.c')
| -rw-r--r-- | net/ipv6/addrconf.c | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 101e0e70ba27..a65935a9afd9 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -776,6 +776,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i | |||
| 776 | struct inet6_dev *idev = ifp->idev; | 776 | struct inet6_dev *idev = ifp->idev; |
| 777 | struct in6_addr addr, *tmpaddr; | 777 | struct in6_addr addr, *tmpaddr; |
| 778 | unsigned long tmp_prefered_lft, tmp_valid_lft, tmp_cstamp, tmp_tstamp; | 778 | unsigned long tmp_prefered_lft, tmp_valid_lft, tmp_cstamp, tmp_tstamp; |
| 779 | unsigned long regen_advance; | ||
| 779 | int tmp_plen; | 780 | int tmp_plen; |
| 780 | int ret = 0; | 781 | int ret = 0; |
| 781 | int max_addresses; | 782 | int max_addresses; |
| @@ -836,8 +837,23 @@ retry: | |||
| 836 | tmp_tstamp = ifp->tstamp; | 837 | tmp_tstamp = ifp->tstamp; |
| 837 | spin_unlock_bh(&ifp->lock); | 838 | spin_unlock_bh(&ifp->lock); |
| 838 | 839 | ||
| 840 | regen_advance = idev->cnf.regen_max_retry * | ||
| 841 | idev->cnf.dad_transmits * | ||
| 842 | idev->nd_parms->retrans_time / HZ; | ||
| 839 | write_unlock(&idev->lock); | 843 | write_unlock(&idev->lock); |
| 840 | 844 | ||
| 845 | /* A temporary address is created only if this calculated Preferred | ||
| 846 | * Lifetime is greater than REGEN_ADVANCE time units. In particular, | ||
| 847 | * an implementation must not create a temporary address with a zero | ||
| 848 | * Preferred Lifetime. | ||
| 849 | */ | ||
| 850 | if (tmp_prefered_lft <= regen_advance) { | ||
| 851 | in6_ifa_put(ifp); | ||
| 852 | in6_dev_put(idev); | ||
| 853 | ret = -1; | ||
| 854 | goto out; | ||
| 855 | } | ||
| 856 | |||
| 841 | addr_flags = IFA_F_TEMPORARY; | 857 | addr_flags = IFA_F_TEMPORARY; |
| 842 | /* set in addrconf_prefix_rcv() */ | 858 | /* set in addrconf_prefix_rcv() */ |
| 843 | if (ifp->flags & IFA_F_OPTIMISTIC) | 859 | if (ifp->flags & IFA_F_OPTIMISTIC) |
| @@ -1831,6 +1847,9 @@ ok: | |||
| 1831 | * lifetimes of an existing temporary address | 1847 | * lifetimes of an existing temporary address |
| 1832 | * when processing a Prefix Information Option. | 1848 | * when processing a Prefix Information Option. |
| 1833 | */ | 1849 | */ |
| 1850 | if (ifp != ift->ifpub) | ||
| 1851 | continue; | ||
| 1852 | |||
| 1834 | spin_lock(&ift->lock); | 1853 | spin_lock(&ift->lock); |
| 1835 | flags = ift->flags; | 1854 | flags = ift->flags; |
| 1836 | if (ift->valid_lft > valid_lft && | 1855 | if (ift->valid_lft > valid_lft && |
| @@ -2437,7 +2456,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
| 2437 | 2456 | ||
| 2438 | ASSERT_RTNL(); | 2457 | ASSERT_RTNL(); |
| 2439 | 2458 | ||
| 2440 | if (dev == init_net.loopback_dev && how == 1) | 2459 | if ((dev->flags & IFF_LOOPBACK) && how == 1) |
| 2441 | how = 0; | 2460 | how = 0; |
| 2442 | 2461 | ||
| 2443 | rt6_ifdown(dev); | 2462 | rt6_ifdown(dev); |
| @@ -2450,7 +2469,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
| 2450 | /* Step 1: remove reference to ipv6 device from parent device. | 2469 | /* Step 1: remove reference to ipv6 device from parent device. |
| 2451 | Do not dev_put! | 2470 | Do not dev_put! |
| 2452 | */ | 2471 | */ |
| 2453 | if (how == 1) { | 2472 | if (how) { |
| 2454 | idev->dead = 1; | 2473 | idev->dead = 1; |
| 2455 | 2474 | ||
| 2456 | /* protected by rtnl_lock */ | 2475 | /* protected by rtnl_lock */ |
| @@ -2482,12 +2501,12 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
| 2482 | write_lock_bh(&idev->lock); | 2501 | write_lock_bh(&idev->lock); |
| 2483 | 2502 | ||
| 2484 | /* Step 3: clear flags for stateless addrconf */ | 2503 | /* Step 3: clear flags for stateless addrconf */ |
| 2485 | if (how != 1) | 2504 | if (!how) |
| 2486 | idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY); | 2505 | idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY); |
| 2487 | 2506 | ||
| 2488 | /* Step 4: clear address list */ | 2507 | /* Step 4: clear address list */ |
| 2489 | #ifdef CONFIG_IPV6_PRIVACY | 2508 | #ifdef CONFIG_IPV6_PRIVACY |
| 2490 | if (how == 1 && del_timer(&idev->regen_timer)) | 2509 | if (how && del_timer(&idev->regen_timer)) |
| 2491 | in6_dev_put(idev); | 2510 | in6_dev_put(idev); |
| 2492 | 2511 | ||
| 2493 | /* clear tempaddr list */ | 2512 | /* clear tempaddr list */ |
| @@ -2524,7 +2543,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
| 2524 | 2543 | ||
| 2525 | /* Step 5: Discard multicast list */ | 2544 | /* Step 5: Discard multicast list */ |
| 2526 | 2545 | ||
| 2527 | if (how == 1) | 2546 | if (how) |
| 2528 | ipv6_mc_destroy_dev(idev); | 2547 | ipv6_mc_destroy_dev(idev); |
| 2529 | else | 2548 | else |
| 2530 | ipv6_mc_down(idev); | 2549 | ipv6_mc_down(idev); |
| @@ -2533,7 +2552,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
| 2533 | 2552 | ||
| 2534 | /* Shot the device (if unregistered) */ | 2553 | /* Shot the device (if unregistered) */ |
| 2535 | 2554 | ||
| 2536 | if (how == 1) { | 2555 | if (how) { |
| 2537 | addrconf_sysctl_unregister(idev); | 2556 | addrconf_sysctl_unregister(idev); |
| 2538 | neigh_parms_release(&nd_tbl, idev->nd_parms); | 2557 | neigh_parms_release(&nd_tbl, idev->nd_parms); |
| 2539 | neigh_ifdown(&nd_tbl, dev); | 2558 | neigh_ifdown(&nd_tbl, dev); |
