]> err.no Git - linux-2.6/blobdiff - net/ipv6/route.c
ipv6 addrconf: Allow infinite prefix lifetime.
[linux-2.6] / net / ipv6 / route.c
index 6293cb91ed1d49aca560c255c04ea545a1247026..b7a4a875a26a366707cdb733d00f1d0a1905894a 100644 (file)
@@ -150,7 +150,7 @@ static struct rt6_info ip6_null_entry_template = {
 static int ip6_pkt_prohibit(struct sk_buff *skb);
 static int ip6_pkt_prohibit_out(struct sk_buff *skb);
 
-struct rt6_info ip6_prohibit_entry_template = {
+static struct rt6_info ip6_prohibit_entry_template = {
        .u = {
                .dst = {
                        .__refcnt       = ATOMIC_INIT(1),
@@ -475,7 +475,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
        lifetime = ntohl(rinfo->lifetime);
        if (lifetime == 0xffffffff) {
                /* infinity */
-       } else if (lifetime > 0x7fffffff/HZ) {
+       } else if (lifetime > 0x7fffffff/HZ - 1) {
                /* Avoid arithmetic overflow */
                lifetime = 0x7fffffff/HZ - 1;
        }
@@ -1106,7 +1106,9 @@ int ip6_route_add(struct fib6_config *cfg)
        }
 
        rt->u.dst.obsolete = -1;
-       rt->rt6i_expires = jiffies + clock_t_to_jiffies(cfg->fc_expires);
+       rt->rt6i_expires = (cfg->fc_flags & RTF_EXPIRES) ?
+                               jiffies + clock_t_to_jiffies(cfg->fc_expires) :
+                               0;
 
        if (cfg->fc_protocol == RTPROT_UNSPEC)
                cfg->fc_protocol = RTPROT_BOOT;
@@ -1243,11 +1245,11 @@ install_route:
                }
        }
 
-       if (rt->u.dst.metrics[RTAX_HOPLIMIT-1] == 0)
+       if (dst_metric(&rt->u.dst, RTAX_HOPLIMIT) == 0)
                rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1;
-       if (!rt->u.dst.metrics[RTAX_MTU-1])
+       if (!dst_metric(&rt->u.dst, RTAX_MTU))
                rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev);
-       if (!rt->u.dst.metrics[RTAX_ADVMSS-1])
+       if (!dst_metric(&rt->u.dst, RTAX_ADVMSS))
                rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst));
        rt->u.dst.dev = dev;
        rt->rt6i_idev = idev;
@@ -2200,7 +2202,9 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
 
        NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric);
 
-       expires = rt->rt6i_expires ? rt->rt6i_expires - jiffies : 0;
+       expires = (rt->rt6i_flags & RTF_EXPIRES) ?
+                       rt->rt6i_expires - jiffies : 0;
+
        if (rtnl_put_cacheinfo(skb, &rt->u.dst, 0, 0, 0,
                               expires, rt->u.dst.error) < 0)
                goto nla_put_failure;
@@ -2614,15 +2618,14 @@ struct ctl_table *ipv6_route_sysctl_init(struct net *net)
 
 static int ip6_route_net_init(struct net *net)
 {
-       int ret = 0;
+       int ret = -ENOMEM;
 
-       ret = -ENOMEM;
        net->ipv6.ip6_dst_ops = kmemdup(&ip6_dst_ops_template,
                                        sizeof(*net->ipv6.ip6_dst_ops),
                                        GFP_KERNEL);
        if (!net->ipv6.ip6_dst_ops)
                goto out;
-       net->ipv6.ip6_dst_ops->dst_net = net;
+       net->ipv6.ip6_dst_ops->dst_net = hold_net(net);
 
        net->ipv6.ip6_null_entry = kmemdup(&ip6_null_entry_template,
                                           sizeof(*net->ipv6.ip6_null_entry),
@@ -2669,6 +2672,7 @@ out:
        return ret;
 
 out_ip6_dst_ops:
+       release_net(net->ipv6.ip6_dst_ops->dst_net);
        kfree(net->ipv6.ip6_dst_ops);
        goto out;
 }
@@ -2684,6 +2688,7 @@ static void ip6_route_net_exit(struct net *net)
        kfree(net->ipv6.ip6_prohibit_entry);
        kfree(net->ipv6.ip6_blk_hole_entry);
 #endif
+       release_net(net->ipv6.ip6_dst_ops->dst_net);
        kfree(net->ipv6.ip6_dst_ops);
 }