diff options
author | Al Viro <viro@ftp.linux.org.uk> | 2007-07-26 12:33:29 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-26 14:11:56 -0400 |
commit | 704eae1f32274c0435f7f3924077afdb811edd1d (patch) | |
tree | 211d333d6f50ea078b6f4f29f0734eadcecdc37b /net/ipv6 | |
parent | a34c45896a723ee7b13128ac8bf564ea42fcd1eb (diff) |
ip6_tunnel - endianness annotations
Convert rel_info to host-endian before calling ip6_tnl_err().
The things become much more straightforward that way.
The key observation (and the reason why that code actually
worked) is that after ip6_tnl_err() we either immediately
bailed out or had rel_info set to 0 or had it set to host-endian
and guaranteed to hit
(rel_type == ICMP_DEST_UNREACH && rel_code == ICMP_FRAG_NEEDED)
case. So inconsistent endianness didn't really lead to bugs,
but it had been subtle and prone to breakage. New variant is
saner and obviously safe.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/ip6_tunnel.c | 17 |
1 files changed, 8 insertions, 9 deletions
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index df30976f6dfd..ca774d8e3be3 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -385,7 +385,7 @@ parse_tlv_tnl_enc_lim(struct sk_buff *skb, __u8 * raw) | |||
385 | 385 | ||
386 | static int | 386 | static int |
387 | ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt, | 387 | ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt, |
388 | int *type, int *code, int *msg, __be32 *info, int offset) | 388 | int *type, int *code, int *msg, __u32 *info, int offset) |
389 | { | 389 | { |
390 | struct ipv6hdr *ipv6h = (struct ipv6hdr *) skb->data; | 390 | struct ipv6hdr *ipv6h = (struct ipv6hdr *) skb->data; |
391 | struct ip6_tnl *t; | 391 | struct ip6_tnl *t; |
@@ -435,7 +435,7 @@ ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt, | |||
435 | if ((*code) == ICMPV6_HDR_FIELD) | 435 | if ((*code) == ICMPV6_HDR_FIELD) |
436 | teli = parse_tlv_tnl_enc_lim(skb, skb->data); | 436 | teli = parse_tlv_tnl_enc_lim(skb, skb->data); |
437 | 437 | ||
438 | if (teli && teli == ntohl(*info) - 2) { | 438 | if (teli && teli == *info - 2) { |
439 | tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->data[teli]; | 439 | tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->data[teli]; |
440 | if (tel->encap_limit == 0) { | 440 | if (tel->encap_limit == 0) { |
441 | if (net_ratelimit()) | 441 | if (net_ratelimit()) |
@@ -452,7 +452,7 @@ ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt, | |||
452 | } | 452 | } |
453 | break; | 453 | break; |
454 | case ICMPV6_PKT_TOOBIG: | 454 | case ICMPV6_PKT_TOOBIG: |
455 | mtu = ntohl(*info) - offset; | 455 | mtu = *info - offset; |
456 | if (mtu < IPV6_MIN_MTU) | 456 | if (mtu < IPV6_MIN_MTU) |
457 | mtu = IPV6_MIN_MTU; | 457 | mtu = IPV6_MIN_MTU; |
458 | t->dev->mtu = mtu; | 458 | t->dev->mtu = mtu; |
@@ -478,12 +478,12 @@ out: | |||
478 | 478 | ||
479 | static int | 479 | static int |
480 | ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 480 | ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
481 | int type, int code, int offset, __u32 info) | 481 | int type, int code, int offset, __be32 info) |
482 | { | 482 | { |
483 | int rel_msg = 0; | 483 | int rel_msg = 0; |
484 | int rel_type = type; | 484 | int rel_type = type; |
485 | int rel_code = code; | 485 | int rel_code = code; |
486 | __u32 rel_info = info; | 486 | __u32 rel_info = ntohl(info); |
487 | int err; | 487 | int err; |
488 | struct sk_buff *skb2; | 488 | struct sk_buff *skb2; |
489 | struct iphdr *eiph; | 489 | struct iphdr *eiph; |
@@ -564,10 +564,9 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
564 | goto out; | 564 | goto out; |
565 | 565 | ||
566 | skb2->dst->ops->update_pmtu(skb2->dst, rel_info); | 566 | skb2->dst->ops->update_pmtu(skb2->dst, rel_info); |
567 | rel_info = htonl(rel_info); | ||
568 | } | 567 | } |
569 | 568 | ||
570 | icmp_send(skb2, rel_type, rel_code, rel_info); | 569 | icmp_send(skb2, rel_type, rel_code, htonl(rel_info)); |
571 | 570 | ||
572 | out: | 571 | out: |
573 | kfree_skb(skb2); | 572 | kfree_skb(skb2); |
@@ -576,12 +575,12 @@ out: | |||
576 | 575 | ||
577 | static int | 576 | static int |
578 | ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 577 | ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
579 | int type, int code, int offset, __u32 info) | 578 | int type, int code, int offset, __be32 info) |
580 | { | 579 | { |
581 | int rel_msg = 0; | 580 | int rel_msg = 0; |
582 | int rel_type = type; | 581 | int rel_type = type; |
583 | int rel_code = code; | 582 | int rel_code = code; |
584 | __u32 rel_info = info; | 583 | __u32 rel_info = ntohl(info); |
585 | int err; | 584 | int err; |
586 | 585 | ||
587 | err = ip6_tnl_err(skb, IPPROTO_IPV6, opt, &rel_type, &rel_code, | 586 | err = ip6_tnl_err(skb, IPPROTO_IPV6, opt, &rel_type, &rel_code, |