diff options
Diffstat (limited to 'net/ipv4/ipip.c')
| -rw-r--r-- | net/ipv4/ipip.c | 130 |
1 files changed, 1 insertions, 129 deletions
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 149111f08e8d..af5cb53da5cc 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c | |||
| @@ -278,9 +278,8 @@ static void ipip_tunnel_uninit(struct net_device *dev) | |||
| 278 | 278 | ||
| 279 | static int ipip_err(struct sk_buff *skb, u32 info) | 279 | static int ipip_err(struct sk_buff *skb, u32 info) |
| 280 | { | 280 | { |
| 281 | #ifndef I_WISH_WORLD_WERE_PERFECT | ||
| 282 | 281 | ||
| 283 | /* It is not :-( All the routers (except for Linux) return only | 282 | /* All the routers (except for Linux) return only |
| 284 | 8 bytes of packet payload. It means, that precise relaying of | 283 | 8 bytes of packet payload. It means, that precise relaying of |
| 285 | ICMP in the real Internet is absolutely infeasible. | 284 | ICMP in the real Internet is absolutely infeasible. |
| 286 | */ | 285 | */ |
| @@ -337,133 +336,6 @@ static int ipip_err(struct sk_buff *skb, u32 info) | |||
| 337 | out: | 336 | out: |
| 338 | read_unlock(&ipip_lock); | 337 | read_unlock(&ipip_lock); |
| 339 | return err; | 338 | return err; |
| 340 | #else | ||
| 341 | struct iphdr *iph = (struct iphdr*)dp; | ||
| 342 | int hlen = iph->ihl<<2; | ||
| 343 | struct iphdr *eiph; | ||
| 344 | const int type = icmp_hdr(skb)->type; | ||
| 345 | const int code = icmp_hdr(skb)->code; | ||
| 346 | int rel_type = 0; | ||
| 347 | int rel_code = 0; | ||
| 348 | __be32 rel_info = 0; | ||
| 349 | __u32 n = 0; | ||
| 350 | struct sk_buff *skb2; | ||
| 351 | struct flowi fl; | ||
| 352 | struct rtable *rt; | ||
| 353 | |||
| 354 | if (len < hlen + sizeof(struct iphdr)) | ||
| 355 | return 0; | ||
| 356 | eiph = (struct iphdr*)(dp + hlen); | ||
| 357 | |||
| 358 | switch (type) { | ||
| 359 | default: | ||
| 360 | return 0; | ||
| 361 | case ICMP_PARAMETERPROB: | ||
| 362 | n = ntohl(icmp_hdr(skb)->un.gateway) >> 24; | ||
| 363 | if (n < hlen) | ||
| 364 | return 0; | ||
| 365 | |||
| 366 | /* So... This guy found something strange INSIDE encapsulated | ||
| 367 | packet. Well, he is fool, but what can we do ? | ||
| 368 | */ | ||
| 369 | rel_type = ICMP_PARAMETERPROB; | ||
| 370 | rel_info = htonl((n - hlen) << 24); | ||
| 371 | break; | ||
| 372 | |||
| 373 | case ICMP_DEST_UNREACH: | ||
| 374 | switch (code) { | ||
| 375 | case ICMP_SR_FAILED: | ||
| 376 | case ICMP_PORT_UNREACH: | ||
| 377 | /* Impossible event. */ | ||
| 378 | return 0; | ||
| 379 | case ICMP_FRAG_NEEDED: | ||
| 380 | /* And it is the only really necessary thing :-) */ | ||
| 381 | n = ntohs(icmp_hdr(skb)->un.frag.mtu); | ||
| 382 | if (n < hlen+68) | ||
| 383 | return 0; | ||
| 384 | n -= hlen; | ||
| 385 | /* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */ | ||
| 386 | if (n > ntohs(eiph->tot_len)) | ||
| 387 | return 0; | ||
| 388 | rel_info = htonl(n); | ||
| 389 | break; | ||
| 390 | default: | ||
| 391 | /* All others are translated to HOST_UNREACH. | ||
| 392 | rfc2003 contains "deep thoughts" about NET_UNREACH, | ||
| 393 | I believe, it is just ether pollution. --ANK | ||
| 394 | */ | ||
| 395 | rel_type = ICMP_DEST_UNREACH; | ||
| 396 | rel_code = ICMP_HOST_UNREACH; | ||
| 397 | break; | ||
| 398 | } | ||
| 399 | break; | ||
| 400 | case ICMP_TIME_EXCEEDED: | ||
| 401 | if (code != ICMP_EXC_TTL) | ||
| 402 | return 0; | ||
| 403 | break; | ||
| 404 | } | ||
| 405 | |||
| 406 | /* Prepare fake skb to feed it to icmp_send */ | ||
| 407 | skb2 = skb_clone(skb, GFP_ATOMIC); | ||
| 408 | if (skb2 == NULL) | ||
| 409 | return 0; | ||
| 410 | dst_release(skb2->dst); | ||
| 411 | skb2->dst = NULL; | ||
| 412 | skb_pull(skb2, skb->data - (u8*)eiph); | ||
| 413 | skb_reset_network_header(skb2); | ||
| 414 | |||
| 415 | /* Try to guess incoming interface */ | ||
| 416 | memset(&fl, 0, sizeof(fl)); | ||
| 417 | fl.fl4_daddr = eiph->saddr; | ||
| 418 | fl.fl4_tos = RT_TOS(eiph->tos); | ||
| 419 | fl.proto = IPPROTO_IPIP; | ||
| 420 | if (ip_route_output_key(dev_net(skb->dev), &rt, &key)) { | ||
| 421 | kfree_skb(skb2); | ||
| 422 | return 0; | ||
| 423 | } | ||
| 424 | skb2->dev = rt->u.dst.dev; | ||
| 425 | |||
| 426 | /* route "incoming" packet */ | ||
| 427 | if (rt->rt_flags&RTCF_LOCAL) { | ||
| 428 | ip_rt_put(rt); | ||
| 429 | rt = NULL; | ||
| 430 | fl.fl4_daddr = eiph->daddr; | ||
| 431 | fl.fl4_src = eiph->saddr; | ||
| 432 | fl.fl4_tos = eiph->tos; | ||
| 433 | if (ip_route_output_key(dev_net(skb->dev), &rt, &fl) || | ||
| 434 | rt->u.dst.dev->type != ARPHRD_TUNNEL) { | ||
| 435 | ip_rt_put(rt); | ||
| 436 | kfree_skb(skb2); | ||
| 437 | return 0; | ||
| 438 | } | ||
| 439 | } else { | ||
| 440 | ip_rt_put(rt); | ||
| 441 | if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, skb2->dev) || | ||
| 442 | skb2->dst->dev->type != ARPHRD_TUNNEL) { | ||
| 443 | kfree_skb(skb2); | ||
| 444 | return 0; | ||
| 445 | } | ||
| 446 | } | ||
| 447 | |||
| 448 | /* change mtu on this route */ | ||
| 449 | if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { | ||
| 450 | if (n > dst_mtu(skb2->dst)) { | ||
| 451 | kfree_skb(skb2); | ||
| 452 | return 0; | ||
| 453 | } | ||
| 454 | skb2->dst->ops->update_pmtu(skb2->dst, n); | ||
| 455 | } else if (type == ICMP_TIME_EXCEEDED) { | ||
| 456 | struct ip_tunnel *t = netdev_priv(skb2->dev); | ||
| 457 | if (t->parms.iph.ttl) { | ||
| 458 | rel_type = ICMP_DEST_UNREACH; | ||
| 459 | rel_code = ICMP_HOST_UNREACH; | ||
| 460 | } | ||
| 461 | } | ||
| 462 | |||
| 463 | icmp_send(skb2, rel_type, rel_code, rel_info); | ||
| 464 | kfree_skb(skb2); | ||
| 465 | return 0; | ||
| 466 | #endif | ||
| 467 | } | 339 | } |
| 468 | 340 | ||
| 469 | static inline void ipip_ecn_decapsulate(const struct iphdr *outer_iph, | 341 | static inline void ipip_ecn_decapsulate(const struct iphdr *outer_iph, |
