diff options
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r-- | net/ipv6/route.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index b46ad53044ba..1324b06796c0 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -119,6 +119,19 @@ static struct dst_ops ip6_dst_ops = { | |||
119 | .entry_size = sizeof(struct rt6_info), | 119 | .entry_size = sizeof(struct rt6_info), |
120 | }; | 120 | }; |
121 | 121 | ||
122 | static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) | ||
123 | { | ||
124 | } | ||
125 | |||
126 | static struct dst_ops ip6_dst_blackhole_ops = { | ||
127 | .family = AF_INET6, | ||
128 | .protocol = __constant_htons(ETH_P_IPV6), | ||
129 | .destroy = ip6_dst_destroy, | ||
130 | .check = ip6_dst_check, | ||
131 | .update_pmtu = ip6_rt_blackhole_update_pmtu, | ||
132 | .entry_size = sizeof(struct rt6_info), | ||
133 | }; | ||
134 | |||
122 | struct rt6_info ip6_null_entry = { | 135 | struct rt6_info ip6_null_entry = { |
123 | .u = { | 136 | .u = { |
124 | .dst = { | 137 | .dst = { |
@@ -833,6 +846,54 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) | |||
833 | 846 | ||
834 | EXPORT_SYMBOL(ip6_route_output); | 847 | EXPORT_SYMBOL(ip6_route_output); |
835 | 848 | ||
849 | static int ip6_blackhole_output(struct sk_buff *skb) | ||
850 | { | ||
851 | kfree_skb(skb); | ||
852 | return 0; | ||
853 | } | ||
854 | |||
855 | int ip6_dst_blackhole(struct sock *sk, struct dst_entry **dstp, struct flowi *fl) | ||
856 | { | ||
857 | struct rt6_info *ort = (struct rt6_info *) *dstp; | ||
858 | struct rt6_info *rt = (struct rt6_info *) | ||
859 | dst_alloc(&ip6_dst_blackhole_ops); | ||
860 | struct dst_entry *new = NULL; | ||
861 | |||
862 | if (rt) { | ||
863 | new = &rt->u.dst; | ||
864 | |||
865 | atomic_set(&new->__refcnt, 1); | ||
866 | new->__use = 1; | ||
867 | new->input = ip6_blackhole_output; | ||
868 | new->output = ip6_blackhole_output; | ||
869 | |||
870 | memcpy(new->metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32)); | ||
871 | new->dev = ort->u.dst.dev; | ||
872 | if (new->dev) | ||
873 | dev_hold(new->dev); | ||
874 | rt->rt6i_idev = ort->rt6i_idev; | ||
875 | if (rt->rt6i_idev) | ||
876 | in6_dev_hold(rt->rt6i_idev); | ||
877 | rt->rt6i_expires = 0; | ||
878 | |||
879 | ipv6_addr_copy(&rt->rt6i_gateway, &ort->rt6i_gateway); | ||
880 | rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES; | ||
881 | rt->rt6i_metric = 0; | ||
882 | |||
883 | memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key)); | ||
884 | #ifdef CONFIG_IPV6_SUBTREES | ||
885 | memcpy(&rt->rt6i_src, &ort->rt6i_src, sizeof(struct rt6key)); | ||
886 | #endif | ||
887 | |||
888 | dst_free(new); | ||
889 | } | ||
890 | |||
891 | dst_release(*dstp); | ||
892 | *dstp = new; | ||
893 | return (new ? 0 : -ENOMEM); | ||
894 | } | ||
895 | EXPORT_SYMBOL_GPL(ip6_dst_blackhole); | ||
896 | |||
836 | /* | 897 | /* |
837 | * Destination cache support functions | 898 | * Destination cache support functions |
838 | */ | 899 | */ |
@@ -2495,6 +2556,8 @@ void __init ip6_route_init(void) | |||
2495 | ip6_dst_ops.kmem_cachep = | 2556 | ip6_dst_ops.kmem_cachep = |
2496 | kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0, | 2557 | kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0, |
2497 | SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL); | 2558 | SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL); |
2559 | ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops.kmem_cachep; | ||
2560 | |||
2498 | fib6_init(); | 2561 | fib6_init(); |
2499 | #ifdef CONFIG_PROC_FS | 2562 | #ifdef CONFIG_PROC_FS |
2500 | p = proc_net_create("ipv6_route", 0, rt6_proc_info); | 2563 | p = proc_net_create("ipv6_route", 0, rt6_proc_info); |