diff options
author | Al Viro <viro@ftp.linux.org.uk> | 2007-07-26 17:33:29 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-26 11:11:56 -0700 |
commit | 704eae1f32274c0435f7f3924077afdb811edd1d (patch) | |
tree | 211d333d6f50ea078b6f4f29f0734eadcecdc37b /net/ipv6/ip6_tunnel.c | |
parent | a34c45896a723ee7b13128ac8bf564ea42fcd1eb (diff) | |
download | lwn-704eae1f32274c0435f7f3924077afdb811edd1d.tar.gz lwn-704eae1f32274c0435f7f3924077afdb811edd1d.zip |
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/ip6_tunnel.c')
-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) static int ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt, - int *type, int *code, int *msg, __be32 *info, int offset) + int *type, int *code, int *msg, __u32 *info, int offset) { struct ipv6hdr *ipv6h = (struct ipv6hdr *) skb->data; struct ip6_tnl *t; @@ -435,7 +435,7 @@ ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt, if ((*code) == ICMPV6_HDR_FIELD) teli = parse_tlv_tnl_enc_lim(skb, skb->data); - if (teli && teli == ntohl(*info) - 2) { + if (teli && teli == *info - 2) { tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->data[teli]; if (tel->encap_limit == 0) { if (net_ratelimit()) @@ -452,7 +452,7 @@ ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt, } break; case ICMPV6_PKT_TOOBIG: - mtu = ntohl(*info) - offset; + mtu = *info - offset; if (mtu < IPV6_MIN_MTU) mtu = IPV6_MIN_MTU; t->dev->mtu = mtu; @@ -478,12 +478,12 @@ out: static int ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __u32 info) + int type, int code, int offset, __be32 info) { int rel_msg = 0; int rel_type = type; int rel_code = code; - __u32 rel_info = info; + __u32 rel_info = ntohl(info); int err; struct sk_buff *skb2; struct iphdr *eiph; @@ -564,10 +564,9 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, goto out; skb2->dst->ops->update_pmtu(skb2->dst, rel_info); - rel_info = htonl(rel_info); } - icmp_send(skb2, rel_type, rel_code, rel_info); + icmp_send(skb2, rel_type, rel_code, htonl(rel_info)); out: kfree_skb(skb2); @@ -576,12 +575,12 @@ out: static int ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __u32 info) + int type, int code, int offset, __be32 info) { int rel_msg = 0; int rel_type = type; int rel_code = code; - __u32 rel_info = info; + __u32 rel_info = ntohl(info); int err; err = ip6_tnl_err(skb, IPPROTO_IPV6, opt, &rel_type, &rel_code, |