]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/ipv6/route.c
[XFRM]: Allow packet drops during larval state resolution.
[net-next-2.6.git] / net / ipv6 / route.c
index b46ad53044bac791e48cb164002a48f9455f1195..1324b06796c0b10aeb8915daebece85e55c854ed 100644 (file)
@@ -119,6 +119,19 @@ 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 = {
@@ -833,6 +846,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
  */
@@ -2495,6 +2556,8 @@ void __init ip6_route_init(void)
        ip6_dst_ops.kmem_cachep =
                kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0,
                                  SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, 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);