Hi,

On Wed, Aug 10, 2011 at 12:55:08PM +0000, Heiko Hund wrote:
> The s6_addr32 member of struct in6_addr is not available when building
> for WIN32. To work around this, a local union is defined that allows
> accessing 32 bit chunks of the IPv6 address passed to add_in6_addr().

NAK, that's massively ugly.  

I've changed the code to do 8-bit rounds.  While somewhat slower, the 
code is actually more readable that way, and since this is only called 
once per connecting client, the few microseconds are well-spent.

My patch attached again.  David?

gert
-- 
USENET is *not* the non-clickable part of WWW!
                                                           //www.muc.de/~gert/
Gert Doering - Munich, Germany                             g...@greenie.muc.de
fax: +49-89-35655025                        g...@net.informatik.tu-muenchen.de
From 1e3c114d655f65dfc3528b1d8884a026ba8bad6b Mon Sep 17 00:00:00 2001
From: Gert Doering <g...@greenie.muc.de>
List-Post: openvpn-devel@lists.sourceforge.net
Date: Sat, 28 May 2011 22:50:40 +0200
Subject: [PATCH] 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 <g...@greenie.muc.de>
---
 socket.c |   34 ++++++++++++++++------------------
 1 files changed, 16 insertions(+), 18 deletions(-)

diff --git a/socket.c b/socket.c
index 6b855c0..7903c26 100644
--- a/socket.c
+++ b/socket.c
@@ -2619,32 +2619,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;
 }
-- 
1.7.3.4

Attachment: pgpVjkQ2HkbPE.pgp
Description: PGP signature

Reply via email to