]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/ipv6/route.c
[NETFILTER]: Kill some supper dupper bloatry
[linux-2.6-omap-h63xx.git] / net / ipv6 / route.c
index 6ecb5e6fae2eb9feff63496bd0749d02237af156..b80ef578420727e1208bf811a9081a3933aed05c 100644 (file)
@@ -113,6 +113,7 @@ static struct dst_ops ip6_dst_ops = {
        .negative_advice        =       ip6_negative_advice,
        .link_failure           =       ip6_link_failure,
        .update_pmtu            =       ip6_rt_update_pmtu,
+       .local_out              =       ip6_local_out,
        .entry_size             =       sizeof(struct rt6_info),
 };
 
@@ -152,7 +153,6 @@ struct rt6_info ip6_null_entry = {
 
 static int ip6_pkt_prohibit(struct sk_buff *skb);
 static int ip6_pkt_prohibit_out(struct sk_buff *skb);
-static int ip6_pkt_blk_hole(struct sk_buff *skb);
 
 struct rt6_info ip6_prohibit_entry = {
        .u = {
@@ -181,8 +181,8 @@ struct rt6_info ip6_blk_hole_entry = {
                        .obsolete       = -1,
                        .error          = -EINVAL,
                        .metrics        = { [RTAX_HOPLIMIT - 1] = 255, },
-                       .input          = ip6_pkt_blk_hole,
-                       .output         = ip6_pkt_blk_hole,
+                       .input          = dst_discard,
+                       .output         = dst_discard,
                        .ops            = &ip6_dst_ops,
                        .path           = (struct dst_entry*)&ip6_blk_hole_entry,
                }
@@ -216,9 +216,12 @@ 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;
+       struct net_device *loopback_dev =
+               dev->nd_net->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 (dev != loopback_dev && idev != NULL && idev->dev == dev) {
+               struct inet6_dev *loopback_idev =
+                       in6_dev_get(loopback_dev);
                if (loopback_idev != NULL) {
                        rt->rt6i_idev = loopback_idev;
                        in6_dev_put(idev);
@@ -329,7 +332,7 @@ static inline int rt6_check_dev(struct rt6_info *rt, int oif)
 static inline int rt6_check_neigh(struct rt6_info *rt)
 {
        struct neighbour *neigh = rt->rt6i_nexthop;
-       int m = 0;
+       int m;
        if (rt->rt6i_flags & RTF_NONEXTHOP ||
            !(rt->rt6i_flags & RTF_GATEWAY))
                m = 1;
@@ -337,10 +340,15 @@ static inline int rt6_check_neigh(struct rt6_info *rt)
                read_lock_bh(&neigh->lock);
                if (neigh->nud_state & NUD_VALID)
                        m = 2;
-               else if (!(neigh->nud_state & NUD_FAILED))
+#ifdef CONFIG_IPV6_ROUTER_PREF
+               else if (neigh->nud_state & NUD_FAILED)
+                       m = 0;
+#endif
+               else
                        m = 1;
                read_unlock_bh(&neigh->lock);
-       }
+       } else
+               m = 0;
        return m;
 }
 
@@ -601,7 +609,8 @@ static int __ip6_ins_rt(struct rt6_info *rt, struct nl_info *info)
 
 int ip6_ins_rt(struct rt6_info *rt)
 {
-       return __ip6_ins_rt(rt, NULL);
+       struct nl_info info = {};
+       return __ip6_ins_rt(rt, &info);
 }
 
 static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *daddr,
@@ -777,12 +786,6 @@ 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;
@@ -795,8 +798,8 @@ int ip6_dst_blackhole(struct sock *sk, struct dst_entry **dstp, struct flowi *fl
 
                atomic_set(&new->__refcnt, 1);
                new->__use = 1;
-               new->input = ip6_blackhole_output;
-               new->output = ip6_blackhole_output;
+               new->input = dst_discard;
+               new->output = dst_discard;
 
                memcpy(new->metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32));
                new->dev = ort->u.dst.dev;
@@ -1264,7 +1267,8 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info)
 
 int ip6_del_rt(struct rt6_info *rt)
 {
-       return __ip6_del_rt(rt, NULL);
+       struct nl_info info = {};
+       return __ip6_del_rt(rt, &info);
 }
 
 static int ip6_route_del(struct fib6_config *cfg)
@@ -1660,6 +1664,8 @@ struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *d
        return rt;
 }
 
+EXPORT_SYMBOL(rt6_get_dflt_router);
+
 struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr,
                                     struct net_device *dev,
                                     unsigned int pref)
@@ -1806,12 +1812,6 @@ static int ip6_pkt_prohibit_out(struct sk_buff *skb)
        return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES);
 }
 
-static int ip6_pkt_blk_hole(struct sk_buff *skb)
-{
-       kfree_skb(skb);
-       return 0;
-}
-
 #endif
 
 /*
@@ -2010,9 +2010,13 @@ errout:
 
 static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 {
+       struct net *net = skb->sk->sk_net;
        struct fib6_config cfg;
        int err;
 
+       if (net != &init_net)
+               return -EINVAL;
+
        err = rtm_to_fib6_config(skb, nlh, &cfg);
        if (err < 0)
                return err;
@@ -2022,9 +2026,13 @@ static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *a
 
 static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 {
+       struct net *net = skb->sk->sk_net;
        struct fib6_config cfg;
        int err;
 
+       if (net != &init_net)
+               return -EINVAL;
+
        err = rtm_to_fib6_config(skb, nlh, &cfg);
        if (err < 0)
                return err;
@@ -2159,6 +2167,7 @@ int rt6_dump_route(struct rt6_info *rt, void *p_arg)
 
 static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
 {
+       struct net *net = in_skb->sk->sk_net;
        struct nlattr *tb[RTA_MAX+1];
        struct rt6_info *rt;
        struct sk_buff *skb;
@@ -2166,6 +2175,9 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
        struct flowi fl;
        int err, iif = 0;
 
+       if (net != &init_net)
+               return -EINVAL;
+
        err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy);
        if (err < 0)
                goto errout;
@@ -2225,7 +2237,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
                goto errout;
        }
 
-       err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
+       err = rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).pid);
 errout:
        return err;
 }
@@ -2233,32 +2245,29 @@ errout:
 void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)
 {
        struct sk_buff *skb;
-       u32 pid = 0, seq = 0;
-       struct nlmsghdr *nlh = NULL;
-       int err = -ENOBUFS;
-
-       if (info) {
-               pid = info->pid;
-               nlh = info->nlh;
-               if (nlh)
-                       seq = nlh->nlmsg_seq;
-       }
+       u32 seq;
+       int err;
+
+       err = -ENOBUFS;
+       seq = info->nlh != NULL ? info->nlh->nlmsg_seq : 0;
 
        skb = nlmsg_new(rt6_nlmsg_size(), gfp_any());
        if (skb == NULL)
                goto errout;
 
-       err = rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0);
+       err = rt6_fill_node(skb, rt, NULL, NULL, 0,
+                               event, info->pid, seq, 0, 0);
        if (err < 0) {
                /* -EMSGSIZE implies BUG in rt6_nlmsg_size() */
                WARN_ON(err == -EMSGSIZE);
                kfree_skb(skb);
                goto errout;
        }
-       err = rtnl_notify(skb, pid, RTNLGRP_IPV6_ROUTE, nlh, gfp_any());
+       err = rtnl_notify(skb, &init_net, info->pid,
+                               RTNLGRP_IPV6_ROUTE, info->nlh, gfp_any());
 errout:
        if (err < 0)
-               rtnl_set_sk_err(RTNLGRP_IPV6_ROUTE, err);
+               rtnl_set_sk_err(&init_net, RTNLGRP_IPV6_ROUTE, err);
 }
 
 /*
@@ -2348,6 +2357,40 @@ static const struct file_operations rt6_stats_seq_fops = {
        .llseek  = seq_lseek,
        .release = single_release,
 };
+
+static int ipv6_route_proc_init(struct net *net)
+{
+       int ret = -ENOMEM;
+       if (!proc_net_fops_create(net, "ipv6_route",
+                                 0, &ipv6_route_proc_fops))
+               goto out;
+
+       if (!proc_net_fops_create(net, "rt6_stats",
+                                 S_IRUGO, &rt6_stats_seq_fops))
+               goto out_ipv6_route;
+
+       ret = 0;
+out:
+       return ret;
+out_ipv6_route:
+       proc_net_remove(net, "ipv6_route");
+       goto out;
+}
+
+static void ipv6_route_proc_fini(struct net *net)
+{
+       proc_net_remove(net, "ipv6_route");
+       proc_net_remove(net, "rt6_stats");
+}
+#else
+static inline int ipv6_route_proc_init(struct net *net)
+{
+       return 0;
+}
+static inline void ipv6_route_proc_fini(struct net *net)
+{
+       return ;
+}
 #endif /* CONFIG_PROC_FS */
 
 #ifdef CONFIG_SYSCTL
@@ -2458,40 +2501,63 @@ ctl_table ipv6_route_table[] = {
 
 #endif
 
-void __init ip6_route_init(void)
+int __init ip6_route_init(void)
 {
+       int ret;
+
        ip6_dst_ops.kmem_cachep =
                kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0,
-                                 SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
+                                 SLAB_HWCACHE_ALIGN, NULL);
+       if (!ip6_dst_ops.kmem_cachep)
+               return -ENOMEM;
+
        ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops.kmem_cachep;
 
-       fib6_init();
-       proc_net_fops_create(&init_net, "ipv6_route", 0, &ipv6_route_proc_fops);
-       proc_net_fops_create(&init_net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops);
-#ifdef CONFIG_XFRM
-       xfrm6_init();
-#endif
-#ifdef CONFIG_IPV6_MULTIPLE_TABLES
-       fib6_rules_init();
-#endif
+       ret = fib6_init();
+       if (ret)
+               goto out_kmem_cache;
+
+       ret = ipv6_route_proc_init(&init_net);
+       if (ret)
+               goto out_fib6_init;
 
-       __rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL);
-       __rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL);
-       __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL);
+       ret = xfrm6_init();
+       if (ret)
+               goto out_proc_init;
+
+       ret = fib6_rules_init();
+       if (ret)
+               goto xfrm6_init;
+
+       ret = -ENOBUFS;
+       if (__rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL) ||
+           __rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL) ||
+           __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL))
+               goto fib6_rules_init;
+
+       ret = 0;
+out:
+       return ret;
+
+fib6_rules_init:
+       fib6_rules_cleanup();
+xfrm6_init:
+       xfrm6_fini();
+out_proc_init:
+       ipv6_route_proc_fini(&init_net);
+out_fib6_init:
+       rt6_ifdown(NULL);
+       fib6_gc_cleanup();
+out_kmem_cache:
+       kmem_cache_destroy(ip6_dst_ops.kmem_cachep);
+       goto out;
 }
 
 void ip6_route_cleanup(void)
 {
-#ifdef CONFIG_IPV6_MULTIPLE_TABLES
        fib6_rules_cleanup();
-#endif
-#ifdef CONFIG_PROC_FS
-       proc_net_remove(&init_net, "ipv6_route");
-       proc_net_remove(&init_net, "rt6_stats");
-#endif
-#ifdef CONFIG_XFRM
+       ipv6_route_proc_fini(&init_net);
        xfrm6_fini();
-#endif
        rt6_ifdown(NULL);
        fib6_gc_cleanup();
        kmem_cache_destroy(ip6_dst_ops.kmem_cachep);