Merge branch 'kbuild' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild-2.6
[pandora-kernel.git] / net / ipv6 / addrconf.c
index ec7a91d..e048ec6 100644 (file)
@@ -836,7 +836,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i
 {
        struct inet6_dev *idev = ifp->idev;
        struct in6_addr addr, *tmpaddr;
-       unsigned long tmp_prefered_lft, tmp_valid_lft, tmp_cstamp, tmp_tstamp;
+       unsigned long tmp_prefered_lft, tmp_valid_lft, tmp_cstamp, tmp_tstamp, age;
        unsigned long regen_advance;
        int tmp_plen;
        int ret = 0;
@@ -886,12 +886,13 @@ retry:
                goto out;
        }
        memcpy(&addr.s6_addr[8], idev->rndid, 8);
+       age = (jiffies - ifp->tstamp) / HZ;
        tmp_valid_lft = min_t(__u32,
                              ifp->valid_lft,
-                             idev->cnf.temp_valid_lft);
+                             idev->cnf.temp_valid_lft + age);
        tmp_prefered_lft = min_t(__u32,
                                 ifp->prefered_lft,
-                                idev->cnf.temp_prefered_lft -
+                                idev->cnf.temp_prefered_lft + age -
                                 idev->cnf.max_desync_factor);
        tmp_plen = ifp->prefix_len;
        max_addresses = idev->cnf.max_addresses;
@@ -1426,8 +1427,10 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp)
 {
        struct inet6_dev *idev = ifp->idev;
 
-       if (addrconf_dad_end(ifp))
+       if (addrconf_dad_end(ifp)) {
+               in6_ifa_put(ifp);
                return;
+       }
 
        if (net_ratelimit())
                printk(KERN_INFO "%s: IPv6 duplicate address %pI6c detected!\n",
@@ -2021,10 +2024,11 @@ ok:
                                        ipv6_ifa_notify(0, ift);
                        }
 
-                       if (create && in6_dev->cnf.use_tempaddr > 0) {
+                       if ((create || list_empty(&in6_dev->tempaddr_list)) && in6_dev->cnf.use_tempaddr > 0) {
                                /*
                                 * When a new public address is created as described in [ADDRCONF],
-                                * also create a new temporary address.
+                                * also create a new temporary address. Also create a temporary
+                                * address if it's enabled but no temporary address currently exists.
                                 */
                                read_unlock_bh(&in6_dev->lock);
                                ipv6_create_tempaddr(ifp, NULL);