[IPV6]: Fix route lifetime.
authorYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Mon, 19 Dec 2005 22:02:45 +0000 (14:02 -0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 19 Dec 2005 22:02:45 +0000 (14:02 -0800)
The route expiration time is stored in rt6i_expires in jiffies.
The argument of rt6_route_add() for adding a route is not the
expiration time in jiffies nor in clock_t, but the lifetime
(or time left before expiration) in clock_t.

Because of the confusion, we sometimes saw several strange errors
(FAILs) in TAHI IPv6 Ready Logo Phase-2 Self Test.
The symptoms were analyzed by Mitsuru Chinen <CHINEN@jp.ibm.com>.

Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv6/addrconf.c
net/ipv6/route.c

index 73a23b4..4ea8cf7 100644 (file)
@@ -1596,9 +1596,17 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
           not good.
         */
        if (valid_lft >= 0x7FFFFFFF/HZ)
-               rt_expires = 0;
+               rt_expires = 0x7FFFFFFF - (0x7FFFFFFF % HZ);
        else
-               rt_expires = jiffies + valid_lft * HZ;
+               rt_expires = valid_lft * HZ;
+
+       /*
+        * We convert this (in jiffies) to clock_t later.
+        * Avoid arithmetic overflow there as well.
+        * Overflow can happen only if HZ < USER_HZ.
+        */
+       if (HZ < USER_HZ && rt_expires > 0x7FFFFFFF / USER_HZ)
+               rt_expires = 0x7FFFFFFF / USER_HZ;
 
        if (pinfo->onlink) {
                struct rt6_info *rt;
@@ -1610,12 +1618,12 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
                                        ip6_del_rt(rt, NULL, NULL, NULL);
                                        rt = NULL;
                                } else {
-                                       rt->rt6i_expires = rt_expires;
+                                       rt->rt6i_expires = jiffies + rt_expires;
                                }
                        }
                } else if (valid_lft) {
                        addrconf_prefix_route(&pinfo->prefix, pinfo->prefix_len,
-                                             dev, rt_expires, RTF_ADDRCONF|RTF_EXPIRES|RTF_PREFIX_RT);
+                                             dev, jiffies_to_clock_t(rt_expires), RTF_ADDRCONF|RTF_EXPIRES|RTF_PREFIX_RT);
                }
                if (rt)
                        dst_release(&rt->u.dst);
index a7a537b..7c68bfb 100644 (file)
@@ -829,7 +829,7 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh,
        }
 
        rt->u.dst.obsolete = -1;
-       rt->rt6i_expires = clock_t_to_jiffies(rtmsg->rtmsg_info);
+       rt->rt6i_expires = jiffies + clock_t_to_jiffies(rtmsg->rtmsg_info);
        if (nlh && (r = NLMSG_DATA(nlh))) {
                rt->rt6i_protocol = r->rtm_protocol;
        } else {