aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ipip.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/ipip.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/ipip.c')
-rw-r--r--net/ipv4/ipip.c22
1 files changed, 12 insertions, 10 deletions
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 76ab50b0d6ef..0c4556529228 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -341,7 +341,8 @@ out:
341 int code = skb->h.icmph->code; 341 int code = skb->h.icmph->code;
342 int rel_type = 0; 342 int rel_type = 0;
343 int rel_code = 0; 343 int rel_code = 0;
344 int rel_info = 0; 344 __be32 rel_info = 0;
345 __u32 n = 0;
345 struct sk_buff *skb2; 346 struct sk_buff *skb2;
346 struct flowi fl; 347 struct flowi fl;
347 struct rtable *rt; 348 struct rtable *rt;
@@ -354,14 +355,15 @@ out:
354 default: 355 default:
355 return 0; 356 return 0;
356 case ICMP_PARAMETERPROB: 357 case ICMP_PARAMETERPROB:
357 if (skb->h.icmph->un.gateway < hlen) 358 n = ntohl(skb->h.icmph->un.gateway) >> 24;
359 if (n < hlen)
358 return 0; 360 return 0;
359 361
360 /* So... This guy found something strange INSIDE encapsulated 362 /* So... This guy found something strange INSIDE encapsulated
361 packet. Well, he is fool, but what can we do ? 363 packet. Well, he is fool, but what can we do ?
362 */ 364 */
363 rel_type = ICMP_PARAMETERPROB; 365 rel_type = ICMP_PARAMETERPROB;
364 rel_info = skb->h.icmph->un.gateway - hlen; 366 rel_info = htonl((n - hlen) << 24);
365 break; 367 break;
366 368
367 case ICMP_DEST_UNREACH: 369 case ICMP_DEST_UNREACH:
@@ -372,13 +374,14 @@ out:
372 return 0; 374 return 0;
373 case ICMP_FRAG_NEEDED: 375 case ICMP_FRAG_NEEDED:
374 /* And it is the only really necessary thing :-) */ 376 /* And it is the only really necessary thing :-) */
375 rel_info = ntohs(skb->h.icmph->un.frag.mtu); 377 n = ntohs(skb->h.icmph->un.frag.mtu);
376 if (rel_info < hlen+68) 378 if (n < hlen+68)
377 return 0; 379 return 0;
378 rel_info -= hlen; 380 n -= hlen;
379 /* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */ 381 /* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */
380 if (rel_info > ntohs(eiph->tot_len)) 382 if (n > ntohs(eiph->tot_len))
381 return 0; 383 return 0;
384 rel_info = htonl(n);
382 break; 385 break;
383 default: 386 default:
384 /* All others are translated to HOST_UNREACH. 387 /* All others are translated to HOST_UNREACH.
@@ -440,12 +443,11 @@ out:
440 443
441 /* change mtu on this route */ 444 /* change mtu on this route */
442 if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { 445 if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
443 if (rel_info > dst_mtu(skb2->dst)) { 446 if (n > dst_mtu(skb2->dst)) {
444 kfree_skb(skb2); 447 kfree_skb(skb2);
445 return 0; 448 return 0;
446 } 449 }
447 skb2->dst->ops->update_pmtu(skb2->dst, rel_info); 450 skb2->dst->ops->update_pmtu(skb2->dst, n);
448 rel_info = htonl(rel_info);
449 } else if (type == ICMP_TIME_EXCEEDED) { 451 } else if (type == ICMP_TIME_EXCEEDED) {
450 struct ip_tunnel *t = netdev_priv(skb2->dev); 452 struct ip_tunnel *t = netdev_priv(skb2->dev);
451 if (t->parms.iph.ttl) { 453 if (t->parms.iph.ttl) {