]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/ipv6/route.c
Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
[linux-2.6-omap-h63xx.git] / net / ipv6 / route.c
index b46ad53044bac791e48cb164002a48f9455f1195..6ff19f9eb9ee43c85633ab391fa45cdb42ff5ccf 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/seq_file.h>
 #endif
 
+#include <net/net_namespace.h>
 #include <net/snmp.h>
 #include <net/ipv6.h>
 #include <net/ip6_fib.h>
@@ -119,12 +120,24 @@ static struct dst_ops ip6_dst_ops = {
        .entry_size             =       sizeof(struct rt6_info),
 };
 
+static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu)
+{
+}
+
+static struct dst_ops ip6_dst_blackhole_ops = {
+       .family                 =       AF_INET6,
+       .protocol               =       __constant_htons(ETH_P_IPV6),
+       .destroy                =       ip6_dst_destroy,
+       .check                  =       ip6_dst_check,
+       .update_pmtu            =       ip6_rt_blackhole_update_pmtu,
+       .entry_size             =       sizeof(struct rt6_info),
+};
+
 struct rt6_info ip6_null_entry = {
        .u = {
                .dst = {
                        .__refcnt       = ATOMIC_INIT(1),
                        .__use          = 1,
-                       .dev            = &loopback_dev,
                        .obsolete       = -1,
                        .error          = -ENETUNREACH,
                        .metrics        = { [RTAX_HOPLIMIT - 1] = 255, },
@@ -150,7 +163,6 @@ struct rt6_info ip6_prohibit_entry = {
                .dst = {
                        .__refcnt       = ATOMIC_INIT(1),
                        .__use          = 1,
-                       .dev            = &loopback_dev,
                        .obsolete       = -1,
                        .error          = -EACCES,
                        .metrics        = { [RTAX_HOPLIMIT - 1] = 255, },
@@ -170,7 +182,6 @@ struct rt6_info ip6_blk_hole_entry = {
                .dst = {
                        .__refcnt       = ATOMIC_INIT(1),
                        .__use          = 1,
-                       .dev            = &loopback_dev,
                        .obsolete       = -1,
                        .error          = -EINVAL,
                        .metrics        = { [RTAX_HOPLIMIT - 1] = 255, },
@@ -210,8 +221,8 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
        struct rt6_info *rt = (struct rt6_info *)dst;
        struct inet6_dev *idev = rt->rt6i_idev;
 
-       if (dev != &loopback_dev && idev != NULL && idev->dev == dev) {
-               struct inet6_dev *loopback_idev = in6_dev_get(&loopback_dev);
+       if (dev != init_net.loopback_dev && idev != NULL && idev->dev == dev) {
+               struct inet6_dev *loopback_idev = in6_dev_get(init_net.loopback_dev);
                if (loopback_idev != NULL) {
                        rt->rt6i_idev = loopback_idev;
                        in6_dev_put(idev);
@@ -833,6 +844,54 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl)
 
 EXPORT_SYMBOL(ip6_route_output);
 
+static int ip6_blackhole_output(struct sk_buff *skb)
+{
+       kfree_skb(skb);
+       return 0;
+}
+
+int ip6_dst_blackhole(struct sock *sk, struct dst_entry **dstp, struct flowi *fl)
+{
+       struct rt6_info *ort = (struct rt6_info *) *dstp;
+       struct rt6_info *rt = (struct rt6_info *)
+               dst_alloc(&ip6_dst_blackhole_ops);
+       struct dst_entry *new = NULL;
+
+       if (rt) {
+               new = &rt->u.dst;
+
+               atomic_set(&new->__refcnt, 1);
+               new->__use = 1;
+               new->input = ip6_blackhole_output;
+               new->output = ip6_blackhole_output;
+
+               memcpy(new->metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32));
+               new->dev = ort->u.dst.dev;
+               if (new->dev)
+                       dev_hold(new->dev);
+               rt->rt6i_idev = ort->rt6i_idev;
+               if (rt->rt6i_idev)
+                       in6_dev_hold(rt->rt6i_idev);
+               rt->rt6i_expires = 0;
+
+               ipv6_addr_copy(&rt->rt6i_gateway, &ort->rt6i_gateway);
+               rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES;
+               rt->rt6i_metric = 0;
+
+               memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key));
+#ifdef CONFIG_IPV6_SUBTREES
+               memcpy(&rt->rt6i_src, &ort->rt6i_src, sizeof(struct rt6key));
+#endif
+
+               dst_free(new);
+       }
+
+       dst_release(*dstp);
+       *dstp = new;
+       return (new ? 0 : -ENOMEM);
+}
+EXPORT_SYMBOL_GPL(ip6_dst_blackhole);
+
 /*
  *     Destination cache support functions
  */
@@ -1068,7 +1127,7 @@ int ip6_route_add(struct fib6_config *cfg)
 #endif
        if (cfg->fc_ifindex) {
                err = -ENODEV;
-               dev = dev_get_by_index(cfg->fc_ifindex);
+               dev = dev_get_by_index(&init_net, cfg->fc_ifindex);
                if (!dev)
                        goto out;
                idev = in6_dev_get(dev);
@@ -1126,12 +1185,12 @@ int ip6_route_add(struct fib6_config *cfg)
        if ((cfg->fc_flags & RTF_REJECT) ||
            (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK))) {
                /* hold loopback dev/idev if we haven't done so. */
-               if (dev != &loopback_dev) {
+               if (dev != init_net.loopback_dev) {
                        if (dev) {
                                dev_put(dev);
                                in6_dev_put(idev);
                        }
-                       dev = &loopback_dev;
+                       dev = init_net.loopback_dev;
                        dev_hold(dev);
                        idev = in6_dev_get(dev);
                        if (!idev) {
@@ -1217,7 +1276,7 @@ install_route:
                int remaining;
 
                nla_for_each_attr(nla, cfg->fc_mx, cfg->fc_mx_len, remaining) {
-                       int type = nla->nla_type;
+                       int type = nla_type(nla);
 
                        if (type) {
                                if (type > RTAX_MAX) {
@@ -1835,13 +1894,13 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
        if (rt == NULL)
                return ERR_PTR(-ENOMEM);
 
-       dev_hold(&loopback_dev);
+       dev_hold(init_net.loopback_dev);
        in6_dev_hold(idev);
 
        rt->u.dst.flags = DST_HOST;
        rt->u.dst.input = ip6_input;
        rt->u.dst.output = ip6_output;
-       rt->rt6i_dev = &loopback_dev;
+       rt->rt6i_dev = init_net.loopback_dev;
        rt->rt6i_idev = idev;
        rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev);
        rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst));
@@ -1922,9 +1981,10 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg)
            !dst_metric_locked(&rt->u.dst, RTAX_MTU) &&
            (dst_mtu(&rt->u.dst) > arg->mtu ||
             (dst_mtu(&rt->u.dst) < arg->mtu &&
-             dst_mtu(&rt->u.dst) == idev->cnf.mtu6)))
+             dst_mtu(&rt->u.dst) == idev->cnf.mtu6))) {
                rt->u.dst.metrics[RTAX_MTU-1] = arg->mtu;
-       rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(arg->mtu);
+               rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(arg->mtu);
+       }
        return 0;
 }
 
@@ -1938,7 +1998,7 @@ void rt6_mtu_change(struct net_device *dev, unsigned mtu)
        fib6_clean_all(rt6_mtu_change_route, 0, &arg);
 }
 
-static struct nla_policy rtm_ipv6_policy[RTA_MAX+1] __read_mostly = {
+static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = {
        [RTA_GATEWAY]           = { .len = sizeof(struct in6_addr) },
        [RTA_OIF]               = { .type = NLA_U32 },
        [RTA_IIF]               = { .type = NLA_U32 },
@@ -2202,7 +2262,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
 
        if (iif) {
                struct net_device *dev;
-               dev = __dev_get_by_index(iif);
+               dev = __dev_get_by_index(&init_net, iif);
                if (!dev) {
                        err = -ENODEV;
                        goto errout;
@@ -2494,14 +2554,16 @@ void __init ip6_route_init(void)
 #endif
        ip6_dst_ops.kmem_cachep =
                kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0,
-                                 SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
+                                 SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
+       ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops.kmem_cachep;
+
        fib6_init();
 #ifdef         CONFIG_PROC_FS
-       p = proc_net_create("ipv6_route", 0, rt6_proc_info);
+       p = proc_net_create(&init_net, "ipv6_route", 0, rt6_proc_info);
        if (p)
                p->owner = THIS_MODULE;
 
-       proc_net_fops_create("rt6_stats", S_IRUGO, &rt6_stats_seq_fops);
+       proc_net_fops_create(&init_net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops);
 #endif
 #ifdef CONFIG_XFRM
        xfrm6_init();
@@ -2521,8 +2583,8 @@ void ip6_route_cleanup(void)
        fib6_rules_cleanup();
 #endif
 #ifdef CONFIG_PROC_FS
-       proc_net_remove("ipv6_route");
-       proc_net_remove("rt6_stats");
+       proc_net_remove(&init_net, "ipv6_route");
+       proc_net_remove(&init_net, "rt6_stats");
 #endif
 #ifdef CONFIG_XFRM
        xfrm6_fini();