diff options
Diffstat (limited to 'net/ipv4/ipip.c')
| -rw-r--r-- | net/ipv4/ipip.c | 79 |
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 | ||
| 277 | static void ipip_err(struct sk_buff *skb, u32 info) | 276 | static 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; |
| 330 | out: | 334 | out: |
| 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 | ||
| 859 | static struct xfrm_tunnel ipip_handler = { | 862 | static 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 | ||
| 864 | static inline int ipip_register(void) | ||
| 865 | { | ||
| 866 | return xfrm4_tunnel_register(&ipip_handler); | ||
| 867 | } | ||
| 868 | |||
| 869 | static inline int ipip_unregister(void) | ||
| 870 | { | ||
| 871 | return xfrm4_tunnel_deregister(&ipip_handler); | ||
| 872 | } | ||
| 873 | #else | ||
| 874 | static struct net_protocol ipip_protocol = { | ||
| 875 | .handler = ipip_rcv, | ||
| 876 | .err_handler = ipip_err, | ||
| 877 | .no_policy = 1, | ||
| 878 | }; | ||
| 879 | |||
| 880 | static inline int ipip_register(void) | ||
| 881 | { | ||
| 882 | return inet_add_protocol(&ipip_protocol, IPPROTO_IPIP); | ||
| 883 | } | ||
| 884 | |||
| 885 | static inline int ipip_unregister(void) | ||
| 886 | { | ||
| 887 | return inet_del_protocol(&ipip_protocol, IPPROTO_IPIP); | ||
| 888 | } | ||
| 889 | #endif | ||
| 890 | |||
| 891 | static char banner[] __initdata = | 868 | static 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 | ||
| 940 | static void __exit ipip_fini(void) | 917 | static 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(); |
