From: Gert Doering Date: Sat, 28 May 2011 20:50:40 +0000 (+0200) Subject: Replace 32-bit-based add_in6_addr() implementation by an 8-bit based one X-Git-Tag: v2.3-alpha1~192 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1ffdb2c9662c3af1f992183435b1afb006dfdc6c;p=thirdparty%2Fopenvpn.git Replace 32-bit-based add_in6_addr() implementation by an 8-bit based one Windows has no 32-bit accessor to the union inside "struct in6_addr", and the 8-bit accessor is the only common denominator across BSD, Solaris, Linux and Windows... Signed-off-by: Gert Doering Acked-by: Samuli Seppänen Signed-off-by: David Sommerseth --- diff --git a/socket.c b/socket.c index 364585d17..302c39f83 100644 --- a/socket.c +++ b/socket.c @@ -2620,32 +2620,30 @@ print_in6_addr (struct in6_addr a6, unsigned int flags, struct gc_arena *gc) return BSTR (&out); } +#ifndef UINT8_MAX +# define UINT8_MAX 0xff +#endif + /* add some offset to an ipv6 address - * (add in steps of 32 bits, taking overflow into next round) + * (add in steps of 8 bits, taking overflow into next round) */ -#ifndef s6_addr32 -# ifdef TARGET_SOLARIS -# define s6_addr32 _S6_un._S6_u32 -# else -# define s6_addr32 __u6_addr.__u6_addr32 -# endif -#endif -#ifndef UINT32_MAX -# define UINT32_MAX (4294967295U) -#endif struct in6_addr add_in6_addr( struct in6_addr base, uint32_t add ) { int i; - uint32_t h; - for( i=3; i>=0 && add > 0 ; i-- ) + for( i=15; i>=0 && add > 0 ; i-- ) { - h = ntohl( base.s6_addr32[i] ); - base.s6_addr32[i] = htonl( (h+add) & UINT32_MAX ); - /* 32-bit overrun? - * caveat: can't do "h+add > UINT32_MAX" with 32bit math! + register int carry; + register uint32_t h; + + h = (unsigned char) base.s6_addr[i]; + base.s6_addr[i] = (h+add) & UINT8_MAX; + + /* using explicit carry for the 8-bit additions will catch + * 8-bit and(!) 32-bit overruns nicely */ - add = ( h > UINT32_MAX - add )? 1: 0; + carry = ((h & 0xff) + (add & 0xff)) >> 8; + add = (add>>8) + carry; } return base; }