diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 31 | ||||
-rw-r--r-- | net/ipv6/datagram.c | 8 | ||||
-rw-r--r-- | net/ipv6/raw.c | 8 | ||||
-rw-r--r-- | net/ipv6/route.c | 63 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 8 | ||||
-rw-r--r-- | net/ipv6/udp.c | 8 |
6 files changed, 108 insertions, 18 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index c7ea248fae2e..329de679ac38 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -2154,15 +2154,6 @@ static void addrconf_dev_config(struct net_device *dev) | |||
2154 | 2154 | ||
2155 | ASSERT_RTNL(); | 2155 | ASSERT_RTNL(); |
2156 | 2156 | ||
2157 | if ((dev->type != ARPHRD_ETHER) && | ||
2158 | (dev->type != ARPHRD_FDDI) && | ||
2159 | (dev->type != ARPHRD_IEEE802_TR) && | ||
2160 | (dev->type != ARPHRD_ARCNET) && | ||
2161 | (dev->type != ARPHRD_INFINIBAND)) { | ||
2162 | /* Alas, we support only Ethernet autoconfiguration. */ | ||
2163 | return; | ||
2164 | } | ||
2165 | |||
2166 | idev = addrconf_add_dev(dev); | 2157 | idev = addrconf_add_dev(dev); |
2167 | if (idev == NULL) | 2158 | if (idev == NULL) |
2168 | return; | 2159 | return; |
@@ -2250,13 +2241,33 @@ static void addrconf_ip6_tnl_config(struct net_device *dev) | |||
2250 | ip6_tnl_add_linklocal(idev); | 2241 | ip6_tnl_add_linklocal(idev); |
2251 | } | 2242 | } |
2252 | 2243 | ||
2244 | static int ipv6_hwtype(struct net_device *dev) | ||
2245 | { | ||
2246 | if ((dev->type == ARPHRD_ETHER) || | ||
2247 | (dev->type == ARPHRD_LOOPBACK) || | ||
2248 | (dev->type == ARPHRD_SIT) || | ||
2249 | (dev->type == ARPHRD_TUNNEL6) || | ||
2250 | (dev->type == ARPHRD_FDDI) || | ||
2251 | (dev->type == ARPHRD_IEEE802_TR) || | ||
2252 | (dev->type == ARPHRD_ARCNET) || | ||
2253 | (dev->type == ARPHRD_INFINIBAND)) | ||
2254 | return 1; | ||
2255 | |||
2256 | return 0; | ||
2257 | } | ||
2258 | |||
2253 | static int addrconf_notify(struct notifier_block *this, unsigned long event, | 2259 | static int addrconf_notify(struct notifier_block *this, unsigned long event, |
2254 | void * data) | 2260 | void * data) |
2255 | { | 2261 | { |
2256 | struct net_device *dev = (struct net_device *) data; | 2262 | struct net_device *dev = (struct net_device *) data; |
2257 | struct inet6_dev *idev = __in6_dev_get(dev); | 2263 | struct inet6_dev *idev; |
2258 | int run_pending = 0; | 2264 | int run_pending = 0; |
2259 | 2265 | ||
2266 | if (!ipv6_hwtype(dev)) | ||
2267 | return NOTIFY_OK; | ||
2268 | |||
2269 | idev = __in6_dev_get(dev); | ||
2270 | |||
2260 | switch(event) { | 2271 | switch(event) { |
2261 | case NETDEV_REGISTER: | 2272 | case NETDEV_REGISTER: |
2262 | if (!idev) { | 2273 | if (!idev) { |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 403eee66b9c5..b1fe7ac5dc90 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -177,8 +177,12 @@ ipv4_connected: | |||
177 | if (final_p) | 177 | if (final_p) |
178 | ipv6_addr_copy(&fl.fl6_dst, final_p); | 178 | ipv6_addr_copy(&fl.fl6_dst, final_p); |
179 | 179 | ||
180 | if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0) | 180 | if ((err = __xfrm_lookup(&dst, &fl, sk, 1)) < 0) { |
181 | goto out; | 181 | if (err == -EREMOTE) |
182 | err = ip6_dst_blackhole(sk, &dst, &fl); | ||
183 | if (err < 0) | ||
184 | goto out; | ||
185 | } | ||
182 | 186 | ||
183 | /* source address lookup done in ip6_dst_lookup */ | 187 | /* source address lookup done in ip6_dst_lookup */ |
184 | 188 | ||
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 009a1047fc3f..a58459a76684 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -818,8 +818,12 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
818 | if (final_p) | 818 | if (final_p) |
819 | ipv6_addr_copy(&fl.fl6_dst, final_p); | 819 | ipv6_addr_copy(&fl.fl6_dst, final_p); |
820 | 820 | ||
821 | if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0) | 821 | if ((err = __xfrm_lookup(&dst, &fl, sk, 1)) < 0) { |
822 | goto out; | 822 | if (err == -EREMOTE) |
823 | err = ip6_dst_blackhole(sk, &dst, &fl); | ||
824 | if (err < 0) | ||
825 | goto out; | ||
826 | } | ||
823 | 827 | ||
824 | if (hlimit < 0) { | 828 | if (hlimit < 0) { |
825 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) | 829 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) |
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); |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index e2f25ea43b68..4f06a51ad4fd 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -265,8 +265,12 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
265 | if (final_p) | 265 | if (final_p) |
266 | ipv6_addr_copy(&fl.fl6_dst, final_p); | 266 | ipv6_addr_copy(&fl.fl6_dst, final_p); |
267 | 267 | ||
268 | if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0) | 268 | if ((err = __xfrm_lookup(&dst, &fl, sk, 1)) < 0) { |
269 | goto failure; | 269 | if (err == -EREMOTE) |
270 | err = ip6_dst_blackhole(sk, &dst, &fl); | ||
271 | if (err < 0) | ||
272 | goto failure; | ||
273 | } | ||
270 | 274 | ||
271 | if (saddr == NULL) { | 275 | if (saddr == NULL) { |
272 | saddr = &fl.fl6_src; | 276 | saddr = &fl.fl6_src; |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index a7ae59c954d5..d1fbddd172e7 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -767,8 +767,12 @@ do_udp_sendmsg: | |||
767 | if (final_p) | 767 | if (final_p) |
768 | ipv6_addr_copy(&fl.fl6_dst, final_p); | 768 | ipv6_addr_copy(&fl.fl6_dst, final_p); |
769 | 769 | ||
770 | if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0) | 770 | if ((err = __xfrm_lookup(&dst, &fl, sk, 1)) < 0) { |
771 | goto out; | 771 | if (err == -EREMOTE) |
772 | err = ip6_dst_blackhole(sk, &dst, &fl); | ||
773 | if (err < 0) | ||
774 | goto out; | ||
775 | } | ||
772 | 776 | ||
773 | if (hlimit < 0) { | 777 | if (hlimit < 0) { |
774 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) | 778 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) |