From 2ab4d4188670356dcb82a80f2fc4598f5145c77d Mon Sep 17 00:00:00 2001
From: Jan Friesse <jfriesse@redhat.com>
Date: Thu, 10 Jan 2019 15:06:20 +0100
Subject: [PATCH] totemip: Use AF_UNSPEC for ipv4-6 and ipv6-4
AF_UNSPEC returns different results than AF_INET/AF_INET6, because of
nsswitch.conf search is in order and it stops asking other
modules once current module success.
Example of difference between previous and new code when ipv6-4 is used:
- /etc/hosts contains test_name with an ipv4
- previous code called AF_INET6 where /etc/hosts failed so other methods
were used which may return IPv6 addr -> result was ether fail or IPv6
address.
- new code calls AF_UNSPEC returning IPv4 defined in /etc/hosts ->
result is IPv4 address
New code behavior should solve problems caused by nss-myhostname.
Signed-off-by: Jan Friesse <jfriesse@redhat.com>
Reviewed-by: Fabio M. Di Nitto <fdinitto@redhat.com>
---
exec/totemip.c | 106 +++++++++++++++++++++++++++-----------
include/corosync/totem/totemip.h | 6 +-
man/corosync.conf.5 | 8 ++-
3 files changed, 83 insertions(+), 37 deletions(-)
diff --git a/exec/totemip.c b/exec/totemip.c
index 9d96e1b..36d0a72 100644
--- a/exec/totemip.c
+++ b/exec/totemip.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2011 Red Hat, Inc.
+ * Copyright (c) 2005-2019 Red Hat, Inc.
*
* All rights reserved.
*
@@ -288,69 +288,113 @@ int totemip_parse(struct totem_ip_address *totemip, const char *addr,
enum totem_ip_version_enum ip_version)
{
struct addrinfo *ainfo;
+ struct addrinfo *ainfo_iter;
+ struct addrinfo *ainfo_ipv4;
+ struct addrinfo *ainfo_ipv6;
+ struct addrinfo *ainfo_final;
struct addrinfo ahints;
struct sockaddr_in *sa;
struct sockaddr_in6 *sa6;
int ret;
int debug_ip_family;
- int ai_family1, ai_family2;
+ int ai_family;
memset(&ahints, 0, sizeof(ahints));
ahints.ai_socktype = SOCK_DGRAM;
ahints.ai_protocol = IPPROTO_UDP;
- ai_family1 = ai_family2 = -1;
+ ai_family = AF_UNSPEC;
+ debug_ip_family = 0;
switch (ip_version) {
case TOTEM_IP_VERSION_4:
- ai_family1 = AF_INET;
+ ai_family = AF_INET;
+ debug_ip_family = 4;
break;
case TOTEM_IP_VERSION_6:
- ai_family1 = AF_INET6;
- break;
- case TOTEM_IP_VERSION_4_6:
- ai_family1 = AF_INET;
- ai_family2 = AF_INET6;
+ ai_family = AF_INET6;
+ debug_ip_family = 6;
break;
case TOTEM_IP_VERSION_6_4:
- ai_family1 = AF_INET6;
- ai_family2 = AF_INET;
+ case TOTEM_IP_VERSION_4_6:
+ /*
+ * ai_family and debug_ip_family are already set correctly
+ */
break;
}
- ahints.ai_family = ai_family1;
+ ahints.ai_family = ai_family;
+
ret = getaddrinfo(addr, NULL, &ahints, &ainfo);
- if (ret && ai_family2 != -1) {
- ahints.ai_family = ai_family2;
- ret = getaddrinfo(addr, NULL, &ahints, &ainfo);
- }
- debug_ip_family = 4;
- if (ahints.ai_family == AF_INET6) {
- debug_ip_family = 6;
- }
+ if (ret == 0 && ai_family == AF_UNSPEC) {
+ ainfo_ipv4 = ainfo_ipv6 = NULL;
- if (ret) {
- log_printf (LOGSYS_LEVEL_DEBUG, "totemip_parse: IPv%u address of %s not resolvable",
- debug_ip_family, addr);
+ /*
+ * Walk thru results and store first AF_INET and AF_INET6
+ */
+ for (ainfo_iter = ainfo; ainfo_iter != NULL; ainfo_iter = ainfo_iter->ai_next) {
+ if (ainfo_iter->ai_family == AF_INET && ainfo_ipv4 == NULL) {
+ ainfo_ipv4 = ainfo_iter;
+ }
- return -1;
+ if (ainfo_iter->ai_family == AF_INET6 && ainfo_ipv6 == NULL) {
+ ainfo_ipv6 = ainfo_iter;
+ }
+ }
+
+ if (ip_version == TOTEM_IP_VERSION_6_4) {
+ if (ainfo_ipv6 != NULL) {
+ ainfo_final = ainfo_ipv6;
+ } else {
+ ainfo_final = ainfo_ipv4;
+ }
+ } else {
+ if (ainfo_ipv4 != NULL) {
+ ainfo_final = ainfo_ipv4;
+ } else {
+ ainfo_final = ainfo_ipv6;
+ }
+ }
+ } else if (ret == 0) {
+ ainfo_final = ainfo;
+ } else {
+ ainfo_final = NULL;
}
- sa = (struct sockaddr_in *)ainfo->ai_addr;
- sa6 = (struct sockaddr_in6 *)ainfo->ai_addr;
- totemip->family = ainfo->ai_family;
+ if (ainfo_final == NULL) {
+ if (ret == 0) {
+ freeaddrinfo(ainfo);
+ }
+
+ if (debug_ip_family == 0) {
+ log_printf(LOGSYS_LEVEL_DEBUG, "totemip_parse: IP address of %s not resolvable",
+ addr);
+ } else {
+ log_printf(LOGSYS_LEVEL_DEBUG, "totemip_parse: IPv%u address of %s not resolvable",
+ debug_ip_family, addr);
+ }
+
+ return (-1);
+ }
- if (ainfo->ai_family == AF_INET)
+ totemip->family = ainfo_final->ai_family;
+ if (ainfo_final->ai_family == AF_INET) {
+ sa = (struct sockaddr_in *)ainfo_final->ai_addr;
memcpy(totemip->addr, &sa->sin_addr, sizeof(struct in_addr));
- else
+ debug_ip_family = 4;
+ } else {
+ sa6 = (struct sockaddr_in6 *)ainfo_final->ai_addr;
memcpy(totemip->addr, &sa6->sin6_addr, sizeof(struct in6_addr));
+ debug_ip_family = 6;
+ }
- log_printf (LOGSYS_LEVEL_DEBUG, "totemip_parse: IPv%u address of %s resolved as %s",
+ log_printf(LOGSYS_LEVEL_DEBUG, "totemip_parse: IPv%u address of %s resolved as %s",
debug_ip_family, addr, totemip_print(totemip));
freeaddrinfo(ainfo);
- return 0;
+
+ return (0);
}
/* Make a sockaddr_* into a totem_ip_address */
diff --git a/include/corosync/totem/totemip.h b/include/corosync/totem/totemip.h
index de22461..b8da3c9 100644
--- a/include/corosync/totem/totemip.h
+++ b/include/corosync/totem/totemip.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005-2010 Red Hat, Inc.
+ * Copyright (c) 2005-2019 Red Hat, Inc.
*
* All rights reserved.
*
@@ -70,8 +70,8 @@ struct totem_ip_address
enum totem_ip_version_enum {
TOTEM_IP_VERSION_4, /* Use only AF_INET */
TOTEM_IP_VERSION_6, /* Use only AF_INET6 */
- TOTEM_IP_VERSION_4_6, /* Use AF_INET and if it fails, use AF_INET6 */
- TOTEM_IP_VERSION_6_4 /* Use AF_INET6 and if it fails, use AF_INET */
+ TOTEM_IP_VERSION_4_6, /* Use AF_UNSPEC and filter result preferring AF_INET */
+ TOTEM_IP_VERSION_6_4 /* Use AF_UNSPEC and filter result preferring AF_INET6 */
};
struct totem_ip_if_address
diff --git a/man/corosync.conf.5 b/man/corosync.conf.5
index 790f434..0e752bc 100644
--- a/man/corosync.conf.5
+++ b/man/corosync.conf.5
@@ -32,7 +32,7 @@
.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
.\" * THE POSSIBILITY OF SUCH DAMAGE.
.\" */
-.TH COROSYNC_CONF 5 2018-12-14 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
+.TH COROSYNC_CONF 5 2019-01-10 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
corosync.conf - corosync executive configuration file
@@ -314,9 +314,11 @@ The value can be one of
(check only IPv6 address)
,
.B ipv4-6
-(first check IPv4 address, if that fails then look for an IPv6 address) and
+(look for all address families and use first IPv4 address found in the list if there is such address,
+otherwise use first IPv6 address) and
.B ipv6-4
-(first check IPv6 address, if that fails then look for an IPv4 address).
+(look for all address families and use first IPv6 address found in the list if there is such address,
+otherwise use first IPv4 address).
Default (if unspecified) is ipv6-4 for knet and udpu transports and ipv4 for udp.
--
1.7.1