File pacemaker-remote-clients-timeout-reconnect.patch of Package pacemaker.14737

commit 462c7facd8a9c6e167ed00d8d71d1cdfbad0198b
Author: Klaus Wenninger <klaus.wenninger@aon.at>
Date:   Mon Aug 29 15:26:45 2016 +0200

    Fix: pacemaker_remote: allow remote clients to timeout/reconnect

diff --git a/include/crm_internal.h b/include/crm_internal.h
index b41dfdc..a8fee47 100644
--- a/include/crm_internal.h
+++ b/include/crm_internal.h
@@ -203,6 +203,7 @@ xmlNode *crm_remote_parse_buffer(crm_remote_t * remote);
 int crm_remote_tcp_connect(const char *host, int port);
 int crm_remote_tcp_connect_async(const char *host, int port, int timeout,       /*ms */
                                  int *timer_id, void *userdata, void (*callback) (void *userdata, int sock));
+int crm_remote_accept(int ssock);
 
 #  ifdef HAVE_GNUTLS_GNUTLS_H
 /*!
diff --git a/lib/common/remote.c b/lib/common/remote.c
index 915453d..dcacb07 100644
--- a/lib/common/remote.c
+++ b/lib/common/remote.c
@@ -28,6 +28,7 @@
 #include <arpa/inet.h>
 #include <netinet/in.h>
 #include <netinet/ip.h>
+#include <netinet/tcp.h>
 #include <netdb.h>
 
 #include <stdlib.h>
@@ -928,3 +929,83 @@ crm_remote_tcp_connect(const char *host, int port)
 {
     return crm_remote_tcp_connect_async(host, port, -1, NULL, NULL, NULL);
 }
+
+
+/* Convert a struct sockaddr address to a string, IPv4 and IPv6: */
+
+static char *
+get_ip_str(const struct sockaddr_storage * sa, char * s, size_t maxlen)
+{
+    switch(((struct sockaddr *)sa)->sa_family) {
+        case AF_INET:
+            inet_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr),
+                      s, maxlen);
+            break;
+
+        case AF_INET6:
+            inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr),
+                      s, maxlen);
+            break;
+
+        default:
+            strncpy(s, "Unknown AF", maxlen);
+            return NULL;
+    }
+
+    return s;
+}
+
+int
+crm_remote_accept(int ssock)
+{
+    int csock = 0;
+    int rc = 0;
+    int flag = 0;
+    unsigned laddr = 0;
+    struct sockaddr_storage addr;
+    char addr_str[INET6_ADDRSTRLEN];
+#ifdef TCP_USER_TIMEOUT
+    int optval;
+    long sbd_timeout = crm_get_sbd_timeout();
+#endif
+
+    /* accept the connection */
+    laddr = sizeof(addr);
+    memset(&addr, 0, sizeof(addr));
+    csock = accept(ssock, (struct sockaddr *)&addr, &laddr);
+    get_ip_str(&addr, addr_str, INET6_ADDRSTRLEN);
+    crm_info("New remote connection from %s", addr_str);
+
+    if (csock == -1) {
+        crm_err("accept socket failed");
+        return -1;
+    }
+
+    if ((flag = fcntl(csock, F_GETFL)) >= 0) {
+        if ((rc = fcntl(csock, F_SETFL, flag | O_NONBLOCK)) < 0) {
+            crm_err("fcntl() write failed");
+            close(csock);
+            return rc;
+        }
+    } else {
+        crm_err("fcntl() read failed");
+        close(csock);
+        return flag;
+    }
+
+#ifdef TCP_USER_TIMEOUT
+    if (sbd_timeout > 0) {
+        optval = sbd_timeout / 2; /* time to fail and retry before watchdog */
+        rc = setsockopt(csock, SOL_TCP, TCP_USER_TIMEOUT,
+                        &optval, sizeof(optval));
+        if (rc < 0) {
+            crm_err("setting TCP_USER_TIMEOUT (%d) on client socket failed",
+                    optval);
+            close(csock);
+            return rc;
+        }
+    }
+#endif
+
+    return csock;
+}
diff --git a/lrmd/tls_backend.c b/lrmd/tls_backend.c
index 1909fdf..552b1d2 100644
--- a/lrmd/tls_backend.c
+++ b/lrmd/tls_backend.c
@@ -188,38 +188,10 @@ lrmd_auth_timeout_cb(gpointer data)
     return FALSE;
 }
 
-/* Convert a struct sockaddr address to a string, IPv4 and IPv6: */
-
-static char *
-get_ip_str(const struct sockaddr_storage * sa, char * s, size_t maxlen)
-{
-    switch(((struct sockaddr *)sa)->sa_family) {
-        case AF_INET:
-            inet_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr),
-                      s, maxlen);
-            break;
-
-        case AF_INET6:
-            inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr),
-                      s, maxlen);
-            break;
-
-        default:
-            strncpy(s, "Unknown AF", maxlen);
-            return NULL;
-    }
-
-    return s;
-}
-
 static int
 lrmd_remote_listen(gpointer data)
 {
     int csock = 0;
-    int flag = 0;
-    unsigned laddr = 0;
-    struct sockaddr_storage addr;
-    char addr_str[INET6_ADDRSTRLEN];
     gnutls_session_t *session = NULL;
     crm_client_t *new_client = NULL;
 
@@ -228,28 +200,8 @@ lrmd_remote_listen(gpointer data)
         .destroy = lrmd_remote_client_destroy,
     };
 
-    /* accept the connection */
-    laddr = sizeof(addr);
-    memset(&addr, 0, sizeof(addr));
-    csock = accept(ssock, (struct sockaddr *)&addr, &laddr);
-
-    get_ip_str(&addr, addr_str, INET6_ADDRSTRLEN);
-    crm_info("New remote connection from %s", addr_str);
-
-    if (csock == -1) {
-        crm_err("accept socket failed");
-        return TRUE;
-    }
-
-    if ((flag = fcntl(csock, F_GETFL)) >= 0) {
-        if (fcntl(csock, F_SETFL, flag | O_NONBLOCK) < 0) {
-            crm_err("fcntl() write failed");
-            close(csock);
-            return TRUE;
-        }
-    } else {
-        crm_err("fcntl() read failed");
-        close(csock);
+    csock = crm_remote_accept(ssock);
+    if (csock < 0) {
         return TRUE;
     }
 
openSUSE Build Service is sponsored by