aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ipip.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2006-03-28 04:12:13 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-03-28 20:02:46 -0500
commitd2acc3479cbccd5cfbca6c787be713ef1de12ec6 (patch)
treeaa348e19e15027db9abdd2da175a0c9055047858 /net/ipv4/ipip.c
parentf0088a50e7c49d1ba285c88fe06345f223652fd3 (diff)
[INET]: Introduce tunnel4/tunnel6
Basically this patch moves the generic tunnel protocol stuff out of xfrm4_tunnel/xfrm6_tunnel and moves it into the new files of tunnel4.c and tunnel6 respectively. The reason for this is that the problem that Hugo uncovered is only the tip of the iceberg. The real problem is that when we removed the dependency of ipip on xfrm4_tunnel we didn't really consider the module case at all. For instance, as it is it's possible to build both ipip and xfrm4_tunnel as modules and if the latter is loaded then ipip simply won't load. After considering the alternatives I've decided that the best way out of this is to restore the dependency of ipip on the non-xfrm-specific part of xfrm4_tunnel. This is acceptable IMHO because the intention of the removal was really to be able to use ipip without the xfrm subsystem. This is still preserved by this patch. So now both ipip/xfrm4_tunnel depend on the new tunnel4.c which handles the arbitration between the two. The order of processing is determined by a simple integer which ensures that ipip gets processed before xfrm4_tunnel. The situation for ICMP handling is a little bit more complicated since we may not have enough information to determine who it's for. It's not a big deal at the moment since the xfrm ICMP handlers are basically no-ops. In future we can deal with this when we look at ICMP caching in general. The user-visible change to this is the removal of the TUNNEL Kconfig prompts. This makes sense because it can only be used through IPCOMP as it stands. The addition of the new modules shouldn't introduce any problems since module dependency will cause them to be loaded. Oh and I also turned some unnecessary pskb's in IPv6 related to this patch to skb's. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/ipip.c')
-rw-r--r--net/ipv4/ipip.c79
1 files changed, 28 insertions, 51 deletions
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 03d13742a4b8..eef07b0916a3 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -114,7 +114,6 @@
114#include <net/sock.h> 114#include <net/sock.h>
115#include <net/ip.h> 115#include <net/ip.h>
116#include <net/icmp.h> 116#include <net/icmp.h>
117#include <net/protocol.h>
118#include <net/ipip.h> 117#include <net/ipip.h>
119#include <net/inet_ecn.h> 118#include <net/inet_ecn.h>
120#include <net/xfrm.h> 119#include <net/xfrm.h>
@@ -274,7 +273,7 @@ static void ipip_tunnel_uninit(struct net_device *dev)
274 dev_put(dev); 273 dev_put(dev);
275} 274}
276 275
277static void ipip_err(struct sk_buff *skb, u32 info) 276static int ipip_err(struct sk_buff *skb, u32 info)
278{ 277{
279#ifndef I_WISH_WORLD_WERE_PERFECT 278#ifndef I_WISH_WORLD_WERE_PERFECT
280 279
@@ -286,21 +285,22 @@ static void ipip_err(struct sk_buff *skb, u32 info)
286 int type = skb->h.icmph->type; 285 int type = skb->h.icmph->type;
287 int code = skb->h.icmph->code; 286 int code = skb->h.icmph->code;
288 struct ip_tunnel *t; 287 struct ip_tunnel *t;
288 int err;
289 289
290 switch (type) { 290 switch (type) {
291 default: 291 default:
292 case ICMP_PARAMETERPROB: 292 case ICMP_PARAMETERPROB:
293 return; 293 return 0;
294 294
295 case ICMP_DEST_UNREACH: 295 case ICMP_DEST_UNREACH:
296 switch (code) { 296 switch (code) {
297 case ICMP_SR_FAILED: 297 case ICMP_SR_FAILED:
298 case ICMP_PORT_UNREACH: 298 case ICMP_PORT_UNREACH:
299 /* Impossible event. */ 299 /* Impossible event. */
300 return; 300 return 0;
301 case ICMP_FRAG_NEEDED: 301 case ICMP_FRAG_NEEDED:
302 /* Soft state for pmtu is maintained by IP core. */ 302 /* Soft state for pmtu is maintained by IP core. */
303 return; 303 return 0;
304 default: 304 default:
305 /* All others are translated to HOST_UNREACH. 305 /* All others are translated to HOST_UNREACH.
306 rfc2003 contains "deep thoughts" about NET_UNREACH, 306 rfc2003 contains "deep thoughts" about NET_UNREACH,
@@ -311,14 +311,18 @@ static void ipip_err(struct sk_buff *skb, u32 info)
311 break; 311 break;
312 case ICMP_TIME_EXCEEDED: 312 case ICMP_TIME_EXCEEDED:
313 if (code != ICMP_EXC_TTL) 313 if (code != ICMP_EXC_TTL)
314 return; 314 return 0;
315 break; 315 break;
316 } 316 }
317 317
318 err = -ENOENT;
319
318 read_lock(&ipip_lock); 320 read_lock(&ipip_lock);
319 t = ipip_tunnel_lookup(iph->daddr, iph->saddr); 321 t = ipip_tunnel_lookup(iph->daddr, iph->saddr);
320 if (t == NULL || t->parms.iph.daddr == 0) 322 if (t == NULL || t->parms.iph.daddr == 0)
321 goto out; 323 goto out;
324
325 err = 0;
322 if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) 326 if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
323 goto out; 327 goto out;
324 328
@@ -329,7 +333,7 @@ static void ipip_err(struct sk_buff *skb, u32 info)
329 t->err_time = jiffies; 333 t->err_time = jiffies;
330out: 334out:
331 read_unlock(&ipip_lock); 335 read_unlock(&ipip_lock);
332 return; 336 return err;
333#else 337#else
334 struct iphdr *iph = (struct iphdr*)dp; 338 struct iphdr *iph = (struct iphdr*)dp;
335 int hlen = iph->ihl<<2; 339 int hlen = iph->ihl<<2;
@@ -344,15 +348,15 @@ out:
344 struct rtable *rt; 348 struct rtable *rt;
345 349
346 if (len < hlen + sizeof(struct iphdr)) 350 if (len < hlen + sizeof(struct iphdr))
347 return; 351 return 0;
348 eiph = (struct iphdr*)(dp + hlen); 352 eiph = (struct iphdr*)(dp + hlen);
349 353
350 switch (type) { 354 switch (type) {
351 default: 355 default:
352 return; 356 return 0;
353 case ICMP_PARAMETERPROB: 357 case ICMP_PARAMETERPROB:
354 if (skb->h.icmph->un.gateway < hlen) 358 if (skb->h.icmph->un.gateway < hlen)
355 return; 359 return 0;
356 360
357 /* So... This guy found something strange INSIDE encapsulated 361 /* So... This guy found something strange INSIDE encapsulated
358 packet. Well, he is fool, but what can we do ? 362 packet. Well, he is fool, but what can we do ?
@@ -366,16 +370,16 @@ out:
366 case ICMP_SR_FAILED: 370 case ICMP_SR_FAILED:
367 case ICMP_PORT_UNREACH: 371 case ICMP_PORT_UNREACH:
368 /* Impossible event. */ 372 /* Impossible event. */
369 return; 373 return 0;
370 case ICMP_FRAG_NEEDED: 374 case ICMP_FRAG_NEEDED:
371 /* And it is the only really necessary thing :-) */ 375 /* And it is the only really necessary thing :-) */
372 rel_info = ntohs(skb->h.icmph->un.frag.mtu); 376 rel_info = ntohs(skb->h.icmph->un.frag.mtu);
373 if (rel_info < hlen+68) 377 if (rel_info < hlen+68)
374 return; 378 return 0;
375 rel_info -= hlen; 379 rel_info -= hlen;
376 /* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */ 380 /* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */
377 if (rel_info > ntohs(eiph->tot_len)) 381 if (rel_info > ntohs(eiph->tot_len))
378 return; 382 return 0;
379 break; 383 break;
380 default: 384 default:
381 /* All others are translated to HOST_UNREACH. 385 /* All others are translated to HOST_UNREACH.
@@ -389,14 +393,14 @@ out:
389 break; 393 break;
390 case ICMP_TIME_EXCEEDED: 394 case ICMP_TIME_EXCEEDED:
391 if (code != ICMP_EXC_TTL) 395 if (code != ICMP_EXC_TTL)
392 return; 396 return 0;
393 break; 397 break;
394 } 398 }
395 399
396 /* Prepare fake skb to feed it to icmp_send */ 400 /* Prepare fake skb to feed it to icmp_send */
397 skb2 = skb_clone(skb, GFP_ATOMIC); 401 skb2 = skb_clone(skb, GFP_ATOMIC);
398 if (skb2 == NULL) 402 if (skb2 == NULL)
399 return; 403 return 0;
400 dst_release(skb2->dst); 404 dst_release(skb2->dst);
401 skb2->dst = NULL; 405 skb2->dst = NULL;
402 skb_pull(skb2, skb->data - (u8*)eiph); 406 skb_pull(skb2, skb->data - (u8*)eiph);
@@ -409,7 +413,7 @@ out:
409 fl.proto = IPPROTO_IPIP; 413 fl.proto = IPPROTO_IPIP;
410 if (ip_route_output_key(&rt, &key)) { 414 if (ip_route_output_key(&rt, &key)) {
411 kfree_skb(skb2); 415 kfree_skb(skb2);
412 return; 416 return 0;
413 } 417 }
414 skb2->dev = rt->u.dst.dev; 418 skb2->dev = rt->u.dst.dev;
415 419
@@ -424,14 +428,14 @@ out:
424 rt->u.dst.dev->type != ARPHRD_TUNNEL) { 428 rt->u.dst.dev->type != ARPHRD_TUNNEL) {
425 ip_rt_put(rt); 429 ip_rt_put(rt);
426 kfree_skb(skb2); 430 kfree_skb(skb2);
427 return; 431 return 0;
428 } 432 }
429 } else { 433 } else {
430 ip_rt_put(rt); 434 ip_rt_put(rt);
431 if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, skb2->dev) || 435 if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, skb2->dev) ||
432 skb2->dst->dev->type != ARPHRD_TUNNEL) { 436 skb2->dst->dev->type != ARPHRD_TUNNEL) {
433 kfree_skb(skb2); 437 kfree_skb(skb2);
434 return; 438 return 0;
435 } 439 }
436 } 440 }
437 441
@@ -439,7 +443,7 @@ out:
439 if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { 443 if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
440 if (rel_info > dst_mtu(skb2->dst)) { 444 if (rel_info > dst_mtu(skb2->dst)) {
441 kfree_skb(skb2); 445 kfree_skb(skb2);
442 return; 446 return 0;
443 } 447 }
444 skb2->dst->ops->update_pmtu(skb2->dst, rel_info); 448 skb2->dst->ops->update_pmtu(skb2->dst, rel_info);
445 rel_info = htonl(rel_info); 449 rel_info = htonl(rel_info);
@@ -453,7 +457,7 @@ out:
453 457
454 icmp_send(skb2, rel_type, rel_code, rel_info); 458 icmp_send(skb2, rel_type, rel_code, rel_info);
455 kfree_skb(skb2); 459 kfree_skb(skb2);
456 return; 460 return 0;
457#endif 461#endif
458} 462}
459 463
@@ -855,39 +859,12 @@ static int __init ipip_fb_tunnel_init(struct net_device *dev)
855 return 0; 859 return 0;
856} 860}
857 861
858#ifdef CONFIG_INET_TUNNEL
859static struct xfrm_tunnel ipip_handler = { 862static struct xfrm_tunnel ipip_handler = {
860 .handler = ipip_rcv, 863 .handler = ipip_rcv,
861 .err_handler = ipip_err, 864 .err_handler = ipip_err,
865 .priority = 1,
862}; 866};
863 867
864static inline int ipip_register(void)
865{
866 return xfrm4_tunnel_register(&ipip_handler);
867}
868
869static inline int ipip_unregister(void)
870{
871 return xfrm4_tunnel_deregister(&ipip_handler);
872}
873#else
874static struct net_protocol ipip_protocol = {
875 .handler = ipip_rcv,
876 .err_handler = ipip_err,
877 .no_policy = 1,
878};
879
880static inline int ipip_register(void)
881{
882 return inet_add_protocol(&ipip_protocol, IPPROTO_IPIP);
883}
884
885static inline int ipip_unregister(void)
886{
887 return inet_del_protocol(&ipip_protocol, IPPROTO_IPIP);
888}
889#endif
890
891static char banner[] __initdata = 868static char banner[] __initdata =
892 KERN_INFO "IPv4 over IPv4 tunneling driver\n"; 869 KERN_INFO "IPv4 over IPv4 tunneling driver\n";
893 870
@@ -897,7 +874,7 @@ static int __init ipip_init(void)
897 874
898 printk(banner); 875 printk(banner);
899 876
900 if (ipip_register() < 0) { 877 if (xfrm4_tunnel_register(&ipip_handler)) {
901 printk(KERN_INFO "ipip init: can't register tunnel\n"); 878 printk(KERN_INFO "ipip init: can't register tunnel\n");
902 return -EAGAIN; 879 return -EAGAIN;
903 } 880 }
@@ -919,7 +896,7 @@ static int __init ipip_init(void)
919 err2: 896 err2:
920 free_netdev(ipip_fb_tunnel_dev); 897 free_netdev(ipip_fb_tunnel_dev);
921 err1: 898 err1:
922 ipip_unregister(); 899 xfrm4_tunnel_deregister(&ipip_handler);
923 goto out; 900 goto out;
924} 901}
925 902
@@ -939,7 +916,7 @@ static void __exit ipip_destroy_tunnels(void)
939 916
940static void __exit ipip_fini(void) 917static void __exit ipip_fini(void)
941{ 918{
942 if (ipip_unregister() < 0) 919 if (xfrm4_tunnel_deregister(&ipip_handler))
943 printk(KERN_INFO "ipip close: can't deregister tunnel\n"); 920 printk(KERN_INFO "ipip close: can't deregister tunnel\n");
944 921
945 rtnl_lock(); 922 rtnl_lock();