diff options
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r-- | net/ipv6/addrconf.c | 40 |
1 files changed, 18 insertions, 22 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index ec7a91d9e865..b41ce0f0d514 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -836,7 +836,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i | |||
836 | { | 836 | { |
837 | struct inet6_dev *idev = ifp->idev; | 837 | struct inet6_dev *idev = ifp->idev; |
838 | struct in6_addr addr, *tmpaddr; | 838 | struct in6_addr addr, *tmpaddr; |
839 | unsigned long tmp_prefered_lft, tmp_valid_lft, tmp_cstamp, tmp_tstamp; | 839 | unsigned long tmp_prefered_lft, tmp_valid_lft, tmp_cstamp, tmp_tstamp, age; |
840 | unsigned long regen_advance; | 840 | unsigned long regen_advance; |
841 | int tmp_plen; | 841 | int tmp_plen; |
842 | int ret = 0; | 842 | int ret = 0; |
@@ -886,12 +886,13 @@ retry: | |||
886 | goto out; | 886 | goto out; |
887 | } | 887 | } |
888 | memcpy(&addr.s6_addr[8], idev->rndid, 8); | 888 | memcpy(&addr.s6_addr[8], idev->rndid, 8); |
889 | age = (jiffies - ifp->tstamp) / HZ; | ||
889 | tmp_valid_lft = min_t(__u32, | 890 | tmp_valid_lft = min_t(__u32, |
890 | ifp->valid_lft, | 891 | ifp->valid_lft, |
891 | idev->cnf.temp_valid_lft); | 892 | idev->cnf.temp_valid_lft + age); |
892 | tmp_prefered_lft = min_t(__u32, | 893 | tmp_prefered_lft = min_t(__u32, |
893 | ifp->prefered_lft, | 894 | ifp->prefered_lft, |
894 | idev->cnf.temp_prefered_lft - | 895 | idev->cnf.temp_prefered_lft + age - |
895 | idev->cnf.max_desync_factor); | 896 | idev->cnf.max_desync_factor); |
896 | tmp_plen = ifp->prefix_len; | 897 | tmp_plen = ifp->prefix_len; |
897 | max_addresses = idev->cnf.max_addresses; | 898 | max_addresses = idev->cnf.max_addresses; |
@@ -1426,8 +1427,10 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp) | |||
1426 | { | 1427 | { |
1427 | struct inet6_dev *idev = ifp->idev; | 1428 | struct inet6_dev *idev = ifp->idev; |
1428 | 1429 | ||
1429 | if (addrconf_dad_end(ifp)) | 1430 | if (addrconf_dad_end(ifp)) { |
1431 | in6_ifa_put(ifp); | ||
1430 | return; | 1432 | return; |
1433 | } | ||
1431 | 1434 | ||
1432 | if (net_ratelimit()) | 1435 | if (net_ratelimit()) |
1433 | printk(KERN_INFO "%s: IPv6 duplicate address %pI6c detected!\n", | 1436 | printk(KERN_INFO "%s: IPv6 duplicate address %pI6c detected!\n", |
@@ -2021,10 +2024,11 @@ ok: | |||
2021 | ipv6_ifa_notify(0, ift); | 2024 | ipv6_ifa_notify(0, ift); |
2022 | } | 2025 | } |
2023 | 2026 | ||
2024 | if (create && in6_dev->cnf.use_tempaddr > 0) { | 2027 | if ((create || list_empty(&in6_dev->tempaddr_list)) && in6_dev->cnf.use_tempaddr > 0) { |
2025 | /* | 2028 | /* |
2026 | * When a new public address is created as described in [ADDRCONF], | 2029 | * When a new public address is created as described in [ADDRCONF], |
2027 | * also create a new temporary address. | 2030 | * also create a new temporary address. Also create a temporary |
2031 | * address if it's enabled but no temporary address currently exists. | ||
2028 | */ | 2032 | */ |
2029 | read_unlock_bh(&in6_dev->lock); | 2033 | read_unlock_bh(&in6_dev->lock); |
2030 | ipv6_create_tempaddr(ifp, NULL); | 2034 | ipv6_create_tempaddr(ifp, NULL); |
@@ -2736,10 +2740,6 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2736 | /* Flag it for later restoration when link comes up */ | 2740 | /* Flag it for later restoration when link comes up */ |
2737 | ifa->flags |= IFA_F_TENTATIVE; | 2741 | ifa->flags |= IFA_F_TENTATIVE; |
2738 | ifa->state = INET6_IFADDR_STATE_DAD; | 2742 | ifa->state = INET6_IFADDR_STATE_DAD; |
2739 | |||
2740 | write_unlock_bh(&idev->lock); | ||
2741 | |||
2742 | in6_ifa_hold(ifa); | ||
2743 | } else { | 2743 | } else { |
2744 | list_del(&ifa->if_list); | 2744 | list_del(&ifa->if_list); |
2745 | 2745 | ||
@@ -2754,19 +2754,15 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2754 | ifa->state = INET6_IFADDR_STATE_DEAD; | 2754 | ifa->state = INET6_IFADDR_STATE_DEAD; |
2755 | spin_unlock_bh(&ifa->state_lock); | 2755 | spin_unlock_bh(&ifa->state_lock); |
2756 | 2756 | ||
2757 | if (state == INET6_IFADDR_STATE_DEAD) | 2757 | if (state == INET6_IFADDR_STATE_DEAD) { |
2758 | goto put_ifa; | 2758 | in6_ifa_put(ifa); |
2759 | } else { | ||
2760 | __ipv6_ifa_notify(RTM_DELADDR, ifa); | ||
2761 | atomic_notifier_call_chain(&inet6addr_chain, | ||
2762 | NETDEV_DOWN, ifa); | ||
2763 | } | ||
2764 | write_lock_bh(&idev->lock); | ||
2759 | } | 2765 | } |
2760 | |||
2761 | __ipv6_ifa_notify(RTM_DELADDR, ifa); | ||
2762 | if (ifa->state == INET6_IFADDR_STATE_DEAD) | ||
2763 | atomic_notifier_call_chain(&inet6addr_chain, | ||
2764 | NETDEV_DOWN, ifa); | ||
2765 | |||
2766 | put_ifa: | ||
2767 | in6_ifa_put(ifa); | ||
2768 | |||
2769 | write_lock_bh(&idev->lock); | ||
2770 | } | 2766 | } |
2771 | 2767 | ||
2772 | list_splice(&keep_list, &idev->addr_list); | 2768 | list_splice(&keep_list, &idev->addr_list); |