|
|
ed0026 |
commit edabd027144c2a9fcd44a997f47981b836b53b77
|
|
|
ed0026 |
Author: David Vossel <dvossel@redhat.com>
|
|
|
ed0026 |
Date: Wed Nov 6 13:27:11 2013 -0500
|
|
|
ed0026 |
|
|
|
ed0026 |
High: remote: Add support for ipv6 into pacemaker_remote daemon
|
|
|
ed0026 |
(cherry picked from commit 1595263ff56ac14cc697d9866b532c14267d708f)
|
|
|
ed0026 |
|
|
|
ed0026 |
diff --git a/lrmd/tls_backend.c b/lrmd/tls_backend.c
|
|
|
ed0026 |
index 780d17b..46e7f27 100644
|
|
|
ed0026 |
--- a/lrmd/tls_backend.c
|
|
|
ed0026 |
+++ b/lrmd/tls_backend.c
|
|
|
ed0026 |
@@ -30,6 +30,7 @@
|
|
|
ed0026 |
|
|
|
ed0026 |
#include <lrmd_private.h>
|
|
|
ed0026 |
|
|
|
ed0026 |
+#include <netdb.h>
|
|
|
ed0026 |
#include <sys/socket.h>
|
|
|
ed0026 |
#include <netinet/ip.h>
|
|
|
ed0026 |
#include <arpa/inet.h>
|
|
|
ed0026 |
@@ -38,7 +39,7 @@
|
|
|
ed0026 |
# define LRMD_REMOTE_AUTH_TIMEOUT 10000
|
|
|
ed0026 |
gnutls_psk_server_credentials_t psk_cred_s;
|
|
|
ed0026 |
gnutls_dh_params_t dh_params;
|
|
|
ed0026 |
-static int ssock = 0;
|
|
|
ed0026 |
+static int ssock = -1;
|
|
|
ed0026 |
extern int lrmd_call_id;
|
|
|
ed0026 |
|
|
|
ed0026 |
static void
|
|
|
ed0026 |
@@ -253,12 +254,72 @@ lrmd_tls_server_key_cb(gnutls_session_t session, const char *username, gnutls_da
|
|
|
ed0026 |
return lrmd_tls_set_key(key);
|
|
|
ed0026 |
}
|
|
|
ed0026 |
|
|
|
ed0026 |
+static int
|
|
|
ed0026 |
+bind_and_listen(struct addrinfo *addr)
|
|
|
ed0026 |
+{
|
|
|
ed0026 |
+ int optval;
|
|
|
ed0026 |
+ int fd;
|
|
|
ed0026 |
+ int rc;
|
|
|
ed0026 |
+ char buffer[256] = { 0, };
|
|
|
ed0026 |
+
|
|
|
ed0026 |
+ if (addr->ai_family == AF_INET6) {
|
|
|
ed0026 |
+ struct sockaddr_in6 *addr_in = (struct sockaddr_in6 *)addr->ai_addr;
|
|
|
ed0026 |
+ inet_ntop(addr->ai_family, &addr_in->sin6_addr, buffer, DIMOF(buffer));
|
|
|
ed0026 |
+
|
|
|
ed0026 |
+ } else {
|
|
|
ed0026 |
+ struct sockaddr_in *addr_in = (struct sockaddr_in *)addr->ai_addr;
|
|
|
ed0026 |
+ inet_ntop(addr->ai_family, &addr_in->sin_addr, buffer, DIMOF(buffer));
|
|
|
ed0026 |
+ }
|
|
|
ed0026 |
+
|
|
|
ed0026 |
+ crm_trace("Attempting to bind on address %s", buffer);
|
|
|
ed0026 |
+
|
|
|
ed0026 |
+ fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
|
|
ed0026 |
+ if (fd < 0) {
|
|
|
ed0026 |
+ return -1;
|
|
|
ed0026 |
+ }
|
|
|
ed0026 |
+
|
|
|
ed0026 |
+ /* reuse address */
|
|
|
ed0026 |
+ optval = 1;
|
|
|
ed0026 |
+ rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
|
|
|
ed0026 |
+ if (rc < 0) {
|
|
|
ed0026 |
+ crm_perror(LOG_INFO, "Couldn't allow the reuse of local addresses by our remote listener, bind address %s", buffer);
|
|
|
ed0026 |
+ close(fd);
|
|
|
ed0026 |
+ return -1;
|
|
|
ed0026 |
+ }
|
|
|
ed0026 |
+
|
|
|
ed0026 |
+ if (addr->ai_family == AF_INET6) {
|
|
|
ed0026 |
+ optval = 0;
|
|
|
ed0026 |
+ rc = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval));
|
|
|
ed0026 |
+ if (rc < 0) {
|
|
|
ed0026 |
+ crm_perror(LOG_INFO, "Couldn't disable IPV6 only on address %s", buffer);
|
|
|
ed0026 |
+ close(fd);
|
|
|
ed0026 |
+ return -1;
|
|
|
ed0026 |
+ }
|
|
|
ed0026 |
+ }
|
|
|
ed0026 |
+
|
|
|
ed0026 |
+ if (bind(fd, addr->ai_addr, addr->ai_addrlen) != 0) {
|
|
|
ed0026 |
+ close(fd);
|
|
|
ed0026 |
+ return -1;
|
|
|
ed0026 |
+ }
|
|
|
ed0026 |
+
|
|
|
ed0026 |
+ if (listen(fd, 10) == -1) {
|
|
|
ed0026 |
+ crm_err("Can not start listen on address %s", buffer);
|
|
|
ed0026 |
+ close(fd);
|
|
|
ed0026 |
+ return -1;
|
|
|
ed0026 |
+ }
|
|
|
ed0026 |
+
|
|
|
ed0026 |
+ crm_notice("Listening on address %s", buffer);
|
|
|
ed0026 |
+
|
|
|
ed0026 |
+ return fd;
|
|
|
ed0026 |
+}
|
|
|
ed0026 |
+
|
|
|
ed0026 |
int
|
|
|
ed0026 |
lrmd_init_remote_tls_server(int port)
|
|
|
ed0026 |
{
|
|
|
ed0026 |
int rc;
|
|
|
ed0026 |
- struct sockaddr_in saddr;
|
|
|
ed0026 |
- int optval;
|
|
|
ed0026 |
+ int filter;
|
|
|
ed0026 |
+ struct addrinfo hints, *res = NULL, *iter;
|
|
|
ed0026 |
+ char port_str[16];
|
|
|
ed0026 |
|
|
|
ed0026 |
static struct mainloop_fd_callbacks remote_listen_fd_callbacks = {
|
|
|
ed0026 |
.dispatch = lrmd_remote_listen,
|
|
|
ed0026 |
@@ -275,34 +336,39 @@ lrmd_init_remote_tls_server(int port)
|
|
|
ed0026 |
gnutls_psk_set_server_credentials_function(psk_cred_s, lrmd_tls_server_key_cb);
|
|
|
ed0026 |
gnutls_psk_set_server_dh_params(psk_cred_s, dh_params);
|
|
|
ed0026 |
|
|
|
ed0026 |
- /* create server socket */
|
|
|
ed0026 |
- ssock = socket(AF_INET, SOCK_STREAM, 0);
|
|
|
ed0026 |
- if (ssock == -1) {
|
|
|
ed0026 |
- crm_err("Can not create server socket.");
|
|
|
ed0026 |
- return -1;
|
|
|
ed0026 |
- }
|
|
|
ed0026 |
+ memset(&hints, 0, sizeof(struct addrinfo));
|
|
|
ed0026 |
+ hints.ai_flags = AI_PASSIVE; /* Only return socket addresses with wildcard INADDR_ANY or IN6ADDR_ANY_INIT */
|
|
|
ed0026 |
+ hints.ai_family = AF_UNSPEC; /* Return IPv6 or IPv4 */
|
|
|
ed0026 |
+ hints.ai_socktype = SOCK_STREAM;
|
|
|
ed0026 |
+ hints.ai_protocol = IPPROTO_TCP;
|
|
|
ed0026 |
|
|
|
ed0026 |
- /* reuse address */
|
|
|
ed0026 |
- optval = 1;
|
|
|
ed0026 |
- rc = setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
|
|
|
ed0026 |
- if (rc < 0) {
|
|
|
ed0026 |
- crm_perror(LOG_INFO, "Couldn't allow the reuse of local addresses by our remote listener");
|
|
|
ed0026 |
+ snprintf(port_str, sizeof(port_str), "%d", port);
|
|
|
ed0026 |
+ rc = getaddrinfo(NULL, port_str, &hints, &res;;
|
|
|
ed0026 |
+ if (rc) {
|
|
|
ed0026 |
+ crm_err("getaddrinfo: %s", gai_strerror(rc));
|
|
|
ed0026 |
+ return -1;
|
|
|
ed0026 |
}
|
|
|
ed0026 |
|
|
|
ed0026 |
- rc = -1;
|
|
|
ed0026 |
+ iter = res;
|
|
|
ed0026 |
+ filter = AF_INET6;
|
|
|
ed0026 |
+ /* Try IPv6 addresses first, then IPv4 */
|
|
|
ed0026 |
+ while (iter) {
|
|
|
ed0026 |
+ if (iter->ai_family == filter) {
|
|
|
ed0026 |
+ ssock = bind_and_listen(iter);
|
|
|
ed0026 |
+ }
|
|
|
ed0026 |
+ if (ssock != -1) {
|
|
|
ed0026 |
+ break;
|
|
|
ed0026 |
+ }
|
|
|
ed0026 |
|
|
|
ed0026 |
- /* bind server socket */
|
|
|
ed0026 |
- memset(&saddr, '\0', sizeof(saddr));
|
|
|
ed0026 |
- saddr.sin_family = AF_INET;
|
|
|
ed0026 |
- saddr.sin_addr.s_addr = INADDR_ANY;
|
|
|
ed0026 |
- saddr.sin_port = htons(port);
|
|
|
ed0026 |
- if (bind(ssock, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) {
|
|
|
ed0026 |
- crm_err("Can not bind server socket.");
|
|
|
ed0026 |
- goto init_remote_cleanup;
|
|
|
ed0026 |
+ iter = iter->ai_next;
|
|
|
ed0026 |
+ if (iter == NULL && filter == AF_INET6) {
|
|
|
ed0026 |
+ iter = res;
|
|
|
ed0026 |
+ filter = AF_INET;
|
|
|
ed0026 |
+ }
|
|
|
ed0026 |
}
|
|
|
ed0026 |
|
|
|
ed0026 |
- if (listen(ssock, 10) == -1) {
|
|
|
ed0026 |
- crm_err("Can not start listen.");
|
|
|
ed0026 |
+ if (ssock < 0) {
|
|
|
ed0026 |
+ crm_err("unable to bind to address");
|
|
|
ed0026 |
goto init_remote_cleanup;
|
|
|
ed0026 |
}
|
|
|
ed0026 |
|
|
|
ed0026 |
@@ -314,6 +380,7 @@ lrmd_init_remote_tls_server(int port)
|
|
|
ed0026 |
close(ssock);
|
|
|
ed0026 |
ssock = 0;
|
|
|
ed0026 |
}
|
|
|
ed0026 |
+ freeaddrinfo(res);
|
|
|
ed0026 |
return rc;
|
|
|
ed0026 |
|
|
|
ed0026 |
}
|