# HG changeset patch
# User Philipp Kolmann <philipp@kolmann.at>
# Date 1235094639 -39600
# Node ID 6d5f0f600c0b2147490af0c5e592fc995336902a
# Parent  4a4773bb2ea42046e24f6d6c3b6ff2eb6f105c41
IPv6addr fails on /64 prefixes

Hi Simon,

it seems I am the one unlucky guy who uses heartbeat with IPv6....

I started updateing my cluster today to lenny and IPv6addr fails again:

scs1:/etc/heartbeat/resource.d# ./IPv6addr 2001:629:3800:33:0:0:0:122 start
2009/02/16_20:19:50 ERROR:  Generic error
ERROR:  Generic error


I dug into the source of IPv6addr.c and it seems that the mask is too long
and therefore the scan_if isn't matching.

I have a 2001:629:3800:33::/64 subnet but it seems from my debug output
that IPv6addr tries to match /96 bits of the IP address which fails.

My C knowledge is sadly too little to fix this myself.

I would greatly be happy if you could help me with that.

------------------------------------------------------------------------------

Hi,

we found some discussion about this issue here:

http://www.velocityreviews.com/forums/t283343-shifting-bits-shift-32-bits-on-32-bit-int.html

In post #4 it reads:
The behaviour of shifts defined only if the value of the right operand
is less than the number of bits in the left operand. So shifting a
32-bit value by 32 or more is undefined...

further info in #7:

Better yet, read the first part of section 5.8 of the ISO/IEC 14882:2003
standard:

The behavior is undefined if the right operand is negative,
or greater than or equal to the length in bits of the
promoted left operand.

So it seems that my patch is the proper fix in the end after all.
Attached as file, since BT distroyed the formatting.

-------------------------------------------------------------------------------

This bug was reported as Debian bug #515662
http://bugs.debian.org/515662

Signed-off-by: Simon Horman <horms@verge.net.au>

diff -r 4a4773bb2ea4 -r 6d5f0f600c0b resources/OCF/IPv6addr.c
--- a/resources/OCF/IPv6addr.c	Tue Feb 17 13:34:34 2009 +0100
+++ b/resources/OCF/IPv6addr.c	Fri Feb 20 12:50:39 2009 +1100
@@ -499,7 +499,10 @@
 			n = plen / 32;
 			memset(mask.s6_addr32 + n + 1, 0, (3 - n) * 4);
 			s = 32 - plen % 32;
-			mask.s6_addr32[n] = 0xffffffff << s;
+			if (s == 32) 
+				mask.s6_addr32[n] = 0x0;
+			else
+				mask.s6_addr32[n] = 0xffffffff << s;
 			mask.s6_addr32[n] = htonl(mask.s6_addr32[n]);
 		}
 
