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