From 792ee7690ed74798213011998934830e70e9fcd2 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Wed, 6 Apr 2016 17:15:39 +0100 Subject: [PATCH 1/4] Problem: zmq_bind IPv4 fallback still tries IPv6 Solution: if opening an IPv6 TCP socket fails because IPv6 is not available, try to open an IPv4 socket instead when creating and binding a TCP endpoint. --- src/tcp_listener.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tcp_listener.cpp b/src/tcp_listener.cpp index 89e146b6..fe929a8e 100644 --- a/src/tcp_listener.cpp +++ b/src/tcp_listener.cpp @@ -159,13 +159,13 @@ int zmq::tcp_listener_t::set_address (const char *addr_) #endif // IPv6 address family not supported, try automatic downgrade to IPv4. - if (address.family () == AF_INET6 + if (s == -1 && address.family () == AF_INET6 && errno == EAFNOSUPPORT && options.ipv6) { - rc = address.resolve (addr_, true, true); + rc = address.resolve (addr_, true, false); if (rc != 0) return rc; - s = ::socket (address.family (), SOCK_STREAM, IPPROTO_TCP); + s = open_socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); } #ifdef ZMQ_HAVE_WINDOWS From 6892b7b60d39d3bccdd6d5ed452811f1003094a3 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Thu, 7 Apr 2016 13:15:41 +0100 Subject: [PATCH 2/4] Problem: zmq_connect (TCP) has no IPv4 fallback Solution: if opening an IPv6 TCP socket fails because IPv6 is not available, try to open an IPv4 socket instead when creating and connecting a TCP endpoint. --- src/tcp_connecter.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/tcp_connecter.cpp b/src/tcp_connecter.cpp index 97009e61..878ba4ff 100644 --- a/src/tcp_connecter.cpp +++ b/src/tcp_connecter.cpp @@ -209,6 +209,18 @@ int zmq::tcp_connecter_t::open () // Create the socket. s = open_socket (addr->resolved.tcp_addr->family (), SOCK_STREAM, IPPROTO_TCP); + + // IPv6 address family not supported, try automatic downgrade to IPv4. + if (s == -1 && addr->resolved.tcp_addr->family () == AF_INET6 + && errno == EAFNOSUPPORT + && options.ipv6) { + int rc = addr->resolved.tcp_addr->resolve ( + addr->address.c_str (), false, false); + if (rc != 0) + return -1; + s = open_socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); + } + #ifdef ZMQ_HAVE_WINDOWS if (s == INVALID_SOCKET) { errno = wsa_error_to_errno (WSAGetLastError ()); From 0c66618e405169dcd9f622775c40711c32e93854 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Thu, 7 Apr 2016 13:17:08 +0100 Subject: [PATCH 3/4] Problem: redundant Windows errno conversion Solution: in the Windows-specific ifdef in tcp_listener set_address, check for error and set errno only after the IPv4 fallback has failed too, to avoid setting errno when the socket creation succeeds through the fallback. --- src/tcp_listener.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/tcp_listener.cpp b/src/tcp_listener.cpp index fe929a8e..b41d0b3c 100644 --- a/src/tcp_listener.cpp +++ b/src/tcp_listener.cpp @@ -153,10 +153,6 @@ int zmq::tcp_listener_t::set_address (const char *addr_) // Create a listening socket. s = open_socket (address.family (), SOCK_STREAM, IPPROTO_TCP); -#ifdef ZMQ_HAVE_WINDOWS - if (s == INVALID_SOCKET) - errno = wsa_error_to_errno (WSAGetLastError ()); -#endif // IPv6 address family not supported, try automatic downgrade to IPv4. if (s == -1 && address.family () == AF_INET6 From 8cddc9122be40ff55fa06972e9b08f014cdd29ef Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Thu, 7 Apr 2016 17:11:48 +0100 Subject: [PATCH 4/4] Update NEWS for fix #1887 --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index 2de97395..69d9d1b1 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,8 @@ * Fixed #1877 - Avoid terminating connections prematurely +* Fixed #1887 - zmq_bind IPv4 fallback still tries IPv6 + 0MQ version 4.0.7 stable, released on 2015/06/15 ================================================