Skip to content

Commit

Permalink
Fix: pacemaker_remote: allow remote clients to timeout/reconnect
Browse files Browse the repository at this point in the history
  • Loading branch information
wenningerk committed Aug 29, 2016
1 parent 2f214a6 commit 462c7fa
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 50 deletions.
1 change: 1 addition & 0 deletions include/crm_internal.h
Expand Up @@ -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
/*!
Expand Down
81 changes: 81 additions & 0 deletions lib/common/remote.c
Expand Up @@ -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>
Expand Down Expand Up @@ -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;
}
52 changes: 2 additions & 50 deletions lrmd/tls_backend.c
Expand Up @@ -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;

Expand All @@ -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;
}

Expand Down

0 comments on commit 462c7fa

Please sign in to comment.