aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ip_gre.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2006-09-19 16:23:19 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 18:19:43 -0400
commitc55e2f4997a104d66b59bdf1aa8ab125d09ae00a (patch)
tree51c92b1085e5a3067a14386c0b449ac33036bb7a /net/ipv4/ip_gre.c
parent593f16aa627d61da447c76ee5a159450174627f6 (diff)
[IPV4]: ipip and ip_gre encapsulation bugs
Handling of ipip and ip_gre ICMP error relaying is b0rken; it accesses 8bit field + 3 reserved octets as host-endian 32bit, does comparison, subtraction and stuffs the result back. That breaks on big-endian. Fixed, made endian-clean. [ Note that this effected code is permanently commented out with and ifdef, so this error couldn't actually cause problems for anyone. -DaveM ] Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/ip_gre.c')
-rw-r--r--net/ipv4/ip_gre.c23
1 files changed, 13 insertions, 10 deletions
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index e66f6ff2e198..f5fba051df3d 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -393,7 +393,8 @@ out:
393 int code = skb->h.icmph->code; 393 int code = skb->h.icmph->code;
394 int rel_type = 0; 394 int rel_type = 0;
395 int rel_code = 0; 395 int rel_code = 0;
396 int rel_info = 0; 396 __be32 rel_info = 0;
397 __u32 n = 0;
397 u16 flags; 398 u16 flags;
398 int grehlen = (iph->ihl<<2) + 4; 399 int grehlen = (iph->ihl<<2) + 4;
399 struct sk_buff *skb2; 400 struct sk_buff *skb2;
@@ -422,14 +423,16 @@ out:
422 default: 423 default:
423 return; 424 return;
424 case ICMP_PARAMETERPROB: 425 case ICMP_PARAMETERPROB:
425 if (skb->h.icmph->un.gateway < (iph->ihl<<2)) 426 n = ntohl(skb->h.icmph->un.gateway) >> 24;
427 if (n < (iph->ihl<<2))
426 return; 428 return;
427 429
428 /* So... This guy found something strange INSIDE encapsulated 430 /* So... This guy found something strange INSIDE encapsulated
429 packet. Well, he is fool, but what can we do ? 431 packet. Well, he is fool, but what can we do ?
430 */ 432 */
431 rel_type = ICMP_PARAMETERPROB; 433 rel_type = ICMP_PARAMETERPROB;
432 rel_info = skb->h.icmph->un.gateway - grehlen; 434 n -= grehlen;
435 rel_info = htonl(n << 24);
433 break; 436 break;
434 437
435 case ICMP_DEST_UNREACH: 438 case ICMP_DEST_UNREACH:
@@ -440,13 +443,14 @@ out:
440 return; 443 return;
441 case ICMP_FRAG_NEEDED: 444 case ICMP_FRAG_NEEDED:
442 /* And it is the only really necessary thing :-) */ 445 /* And it is the only really necessary thing :-) */
443 rel_info = ntohs(skb->h.icmph->un.frag.mtu); 446 n = ntohs(skb->h.icmph->un.frag.mtu);
444 if (rel_info < grehlen+68) 447 if (n < grehlen+68)
445 return; 448 return;
446 rel_info -= grehlen; 449 n -= grehlen;
447 /* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */ 450 /* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */
448 if (rel_info > ntohs(eiph->tot_len)) 451 if (n > ntohs(eiph->tot_len))
449 return; 452 return;
453 rel_info = htonl(n);
450 break; 454 break;
451 default: 455 default:
452 /* All others are translated to HOST_UNREACH. 456 /* All others are translated to HOST_UNREACH.
@@ -508,12 +512,11 @@ out:
508 512
509 /* change mtu on this route */ 513 /* change mtu on this route */
510 if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { 514 if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
511 if (rel_info > dst_mtu(skb2->dst)) { 515 if (n > dst_mtu(skb2->dst)) {
512 kfree_skb(skb2); 516 kfree_skb(skb2);
513 return; 517 return;
514 } 518 }
515 skb2->dst->ops->update_pmtu(skb2->dst, rel_info); 519 skb2->dst->ops->update_pmtu(skb2->dst, n);
516 rel_info = htonl(rel_info);
517 } else if (type == ICMP_TIME_EXCEEDED) { 520 } else if (type == ICMP_TIME_EXCEEDED) {
518 struct ip_tunnel *t = netdev_priv(skb2->dev); 521 struct ip_tunnel *t = netdev_priv(skb2->dev);
519 if (t->parms.iph.ttl) { 522 if (t->parms.iph.ttl) {