Hi,

I would like to upload a(nother) fresh version of heartbeat to fix
a long-standing bug in the IPv6addr code. There appear to be few users
of this code which is why it has taken so long to come to light.

The fix itself is quite trivial and is neccessary becase
bit-shifting a 32bit entity by by 32bits is undefined.

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]);
                }
 

This problem is being tracked as #515662

The debdiff between 2.1.3-6lenny2 and 2.1.3-6lenny0, the
version in lenny, is below. 2.1.3-6lenny1 has already been
uploaded to stable-proposed-updates but I don't believe
that it has been accepted.

The packages are available for anyone who is intersted at
http://packages.vergenet.net/stable-proposed-updates/heartbeat/

diff -u heartbeat-2.1.3/version.Debian heartbeat-2.1.3/version.Debian
--- heartbeat-2.1.3/version.Debian
+++ heartbeat-2.1.3/version.Debian
@@ -1 +1 @@
-2.1.3-5
+2.1.3-6lenny2
diff -u heartbeat-2.1.3/debian/changelog heartbeat-2.1.3/debian/changelog
--- heartbeat-2.1.3/debian/changelog
+++ heartbeat-2.1.3/debian/changelog
@@ -1,3 +1,23 @@
+heartbeat (2.1.3-6lenny2) stable-proposed-updates; urgency=low
+
+  * IPv6addr: Fix handling of /64 prefixes
+    Upstream-Status: commit 6d5f0f600c0b2147490af0c5e592fc995336902a
+                     "IPv6addr fails on /64 prefixes"
+    (closes: #515662)
+
+ -- Simon Horman <ho...@debian.org>  Fri, 20 Feb 2009 02:34:29 +0000
+
+heartbeat (2.1.3-6lenny1) stable-proposed-updates; urgency=low
+
+  * dopd: fix basic failover; fix hb message corruption by fprintf(stderr)
+    Patch: fix-basic-failover-fix-hb-message-corruption-by-fprintf.patch
+    Upstream-Status: commit 47f60bebe7b25abd88ea7b5488e66dfe187416ae
+                     "dopd: fix basic failover; fix hb message corruption by
+                      fprintf(stderr)"
+    (closes: #486071)
+
+ -- Simon Horman <ho...@debian.org>  Mon, 16 Feb 2009 02:54:43 +0000
+
 heartbeat (2.1.3-6lenny0) testing-proposed-updates; urgency=low
 
   * heartbeat-gui dependancy on python-xml
only in patch2:
unchanged:
--- heartbeat-2.1.3.orig/resources/OCF/IPv6addr.c
+++ heartbeat-2.1.3/resources/OCF/IPv6addr.c
@@ -487,7 +487,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]);
                }
 
only in patch2:
unchanged:
--- heartbeat-2.1.3.orig/debian/patches/IPv6addr-64.patch
+++ heartbeat-2.1.3/debian/patches/IPv6addr-64.patch
@@ -0,0 +1,75 @@
+# HG changeset patch
+# User Philipp Kolmann <phil...@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 <ho...@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]);
+               }
+ 
only in patch2:
unchanged:
--- 
heartbeat-2.1.3.orig/debian/patches/dopd-fix-basic-failover-fix-hb-message-corruption-by-fprintf_stderr_.patch
+++ 
heartbeat-2.1.3/debian/patches/dopd-fix-basic-failover-fix-hb-message-corruption-by-fprintf_stderr_.patch
@@ -0,0 +1,110 @@
+# HG changeset patch
+# User Rasto Levrinc <ra...@linbit.com>
+# Date 1206539836 -3600
+# Node ID 47f60bebe7b25abd88ea7b5488e66dfe187416ae
+# Parent  17c0cf487322287d0689a036c32f21b900ce5a80
+dopd: fix basic failover; fix hb message corruption by fprintf(stderr)
+
+check_drbd_peer() used to return FALSE for "node name not in node list",
+so drbd-peer-outdater returned "invalid nodename".
+Then the semantic changed, and check_drbd_peer learned about "dead" peers
+and returned FALSE for them as well. Which made basic failover impossible :(
+
+The return code was now changed to "peer unreachable" for a dead peer.
+And even for nodes which really are not in the host list (and thus could be
+classified as invalide), because, after all, thats what they are.
+unreachable.
+
+Node name comparison needs to be case insensitive; fixed.
+
+During testing with 15 concurrent drbd resources several dopd crashes have been
+observed, which after some debugging turned out to be simply a wrong assumption
+about the global availability of stderr: some fprintf(stderr, "debug message")
+had accidentally used the heartbeat communication channel file descriptor,
+which seriously confused the comm layer.
+All those fprintfs have now been changed to use cl_log.
+
+diff -r 17c0cf487322 -r 47f60bebe7b2 contrib/drbd-outdate-peer/dopd.c
+--- a/contrib/drbd-outdate-peer/dopd.c Mon Mar 24 16:14:12 2008 +0100
++++ b/contrib/drbd-outdate-peer/dopd.c Wed Mar 26 14:57:16 2008 +0100
+@@ -202,14 +202,17 @@
+ }
+ 
+ /* check_drbd_peer()
+- * walk the nodes and return TRUE if peer is not this node and it exists.
++ * walk the nodes and return
++ *  FALSE if peer is not found, not a "normal" node, or "dead"
++ *    (no point in trying to reach those nodes).
++ *  TRUE if peer is found to be alive and "normal".
+  */
+ gboolean
+ check_drbd_peer(const char *drbd_peer)
+ {
+       const char *node;
+       gboolean found = FALSE;
+-      if (!strcmp(drbd_peer, node_name)) {
++      if (!strcasecmp(drbd_peer, node_name)) {
+               cl_log(LOG_WARNING, "drbd peer node %s is me!\n", drbd_peer);
+               return FALSE;
+       }
+@@ -306,9 +309,9 @@
+                       } else
+                               pthread_mutex_unlock(&conn_mutex);
+               } else {
+-                      /* wrong peer was specified,
+-                         send return code 20 to the client */
+-                      send_to_client(curr_client, "20");
++                      /* peer "dead" or not in node list.
++                       * return "peer could not be reached" */
++                      send_to_client(curr_client, "5");
+               }
+ 
+               ha_msg_del(msg);
+diff -r 17c0cf487322 -r 47f60bebe7b2 
contrib/drbd-outdate-peer/drbd-peer-outdater.c
+--- a/contrib/drbd-outdate-peer/drbd-peer-outdater.c   Mon Mar 24 16:14:12 
2008 +0100
++++ b/contrib/drbd-outdate-peer/drbd-peer-outdater.c   Wed Mar 26 14:57:16 
2008 +0100
+@@ -76,7 +76,7 @@
+ 
+       msg = msgfromIPC_noauth(server);
+       if (!msg) {
+-              fprintf(stderr, "no message from server or other "
++              cl_log(LOG_WARNING, "no message from server or other "
+                               "instance is running\n");
+               if (client->mainloop != NULL &&
+                   g_main_is_running(client->mainloop))
+@@ -92,7 +92,7 @@
+       errno = 0;
+       rc = strtol(rc_string, &ep, 10);
+       if (errno != 0 || *ep != EOS) {
+-              fprintf(stderr, "unknown message: %s from server", rc_string);
++              cl_log(LOG_WARNING, "unknown message: %s from server", 
rc_string);
+               client->rc = 20; /* "officially undefined", unspecified error */
+               ha_msg_del(msg);
+               if (client->mainloop != NULL &&
+@@ -124,7 +124,7 @@
+ outdater_timeout_dispatch(gpointer user_data)
+ {
+       dop_client_t *client = (dop_client_t *)user_data;
+-      fprintf(stderr, "error: could not connect to dopd after %i seconds"
++      cl_log(LOG_WARNING, "error: could not connect to dopd after %i seconds"
+                       ": timeout reached\n", client->timeout);
+       if (client->mainloop != NULL && g_main_is_running(client->mainloop))
+               g_main_quit(client->mainloop);
+@@ -255,7 +255,7 @@
+                                        (gpointer)new_client, &ipc_server);
+ 
+       if (ipc_server == NULL) {
+-              fprintf(stderr, "Could not connect to "T_OUTDATER" channel\n");
++              cl_log(LOG_WARNING, "Could not connect to "T_OUTDATER" 
channel\n");
+               dop_exit(new_client); /* unreachable */
+       }
+ 
+@@ -267,7 +267,7 @@
+       ha_msg_add(update, F_OUTDATER_RES, drbd_resource);
+ 
+       if (msg2ipcchan(update, ipc_server) != HA_OK) {
+-              fprintf(stderr, "Could not send message\n");
++              cl_log(LOG_WARNING, "Could not send message\n");
+               dop_exit(new_client);
+       }
+ 
only in patch2:
unchanged:
--- heartbeat-2.1.3.orig/debian/patches/series/2.1.3-6lenny2
+++ heartbeat-2.1.3/debian/patches/series/2.1.3-6lenny2
@@ -0,0 +1 @@
++ IPv6addr-64.patch
only in patch2:
unchanged:
--- heartbeat-2.1.3.orig/debian/patches/series/2.1.3-6lenny1
+++ heartbeat-2.1.3/debian/patches/series/2.1.3-6lenny1
@@ -0,0 +1 @@
++ dopd-fix-basic-failover-fix-hb-message-corruption-by-fprintf_stderr_.patch
only in patch2:
unchanged:
--- heartbeat-2.1.3.orig/contrib/drbd-outdate-peer/drbd-peer-outdater.c
+++ heartbeat-2.1.3/contrib/drbd-outdate-peer/drbd-peer-outdater.c
@@ -76,7 +76,7 @@
 
        msg = msgfromIPC_noauth(server);
        if (!msg) {
-               fprintf(stderr, "no message from server or other "
+               cl_log(LOG_WARNING, "no message from server or other "
                                "instance is running\n");
                if (client->mainloop != NULL &&
                    g_main_is_running(client->mainloop))
@@ -92,7 +92,7 @@
        errno = 0;
        rc = strtol(rc_string, &ep, 10);
        if (errno != 0 || *ep != EOS) {
-               fprintf(stderr, "unknown message: %s from server", rc_string);
+               cl_log(LOG_WARNING, "unknown message: %s from server", 
rc_string);
                client->rc = 20; /* "officially undefined", unspecified error */
                ha_msg_del(msg);
                if (client->mainloop != NULL &&
@@ -124,7 +124,7 @@
 outdater_timeout_dispatch(gpointer user_data)
 {
        dop_client_t *client = (dop_client_t *)user_data;
-       fprintf(stderr, "error: could not connect to dopd after %i seconds"
+       cl_log(LOG_WARNING, "error: could not connect to dopd after %i seconds"
                        ": timeout reached\n", client->timeout);
        if (client->mainloop != NULL && g_main_is_running(client->mainloop))
                g_main_quit(client->mainloop);
@@ -255,7 +255,7 @@
                                         (gpointer)new_client, &ipc_server);
 
        if (ipc_server == NULL) {
-               fprintf(stderr, "Could not connect to "T_OUTDATER" channel\n");
+               cl_log(LOG_WARNING, "Could not connect to "T_OUTDATER" 
channel\n");
                dop_exit(new_client); /* unreachable */
        }
 
@@ -267,7 +267,7 @@
        ha_msg_add(update, F_OUTDATER_RES, drbd_resource);
 
        if (msg2ipcchan(update, ipc_server) != HA_OK) {
-               fprintf(stderr, "Could not send message\n");
+               cl_log(LOG_WARNING, "Could not send message\n");
                dop_exit(new_client);
        }
 
only in patch2:
unchanged:
--- heartbeat-2.1.3.orig/contrib/drbd-outdate-peer/dopd.c
+++ heartbeat-2.1.3/contrib/drbd-outdate-peer/dopd.c
@@ -202,14 +202,17 @@
 }
 
 /* check_drbd_peer()
- * walk the nodes and return TRUE if peer is not this node and it exists.
+ * walk the nodes and return
+ *  FALSE if peer is not found, not a "normal" node, or "dead"
+ *    (no point in trying to reach those nodes).
+ *  TRUE if peer is found to be alive and "normal".
  */
 gboolean
 check_drbd_peer(const char *drbd_peer)
 {
        const char *node;
        gboolean found = FALSE;
-       if (!strcmp(drbd_peer, node_name)) {
+       if (!strcasecmp(drbd_peer, node_name)) {
                cl_log(LOG_WARNING, "drbd peer node %s is me!\n", drbd_peer);
                return FALSE;
        }
@@ -306,9 +309,9 @@
                        } else
                                pthread_mutex_unlock(&conn_mutex);
                } else {
-                       /* wrong peer was specified,
-                          send return code 20 to the client */
-                       send_to_client(curr_client, "20");
+                       /* peer "dead" or not in node list.
+                        * return "peer could not be reached" */
+                       send_to_client(curr_client, "5");
                }
 
                ha_msg_del(msg);



-- 
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org

Reply via email to