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); |