diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ip.cpp | 17 | ||||
-rw-r--r-- | src/ip.hpp | 3 | ||||
-rw-r--r-- | src/tcp_connecter.cpp | 21 | ||||
-rw-r--r-- | src/tcp_listener.cpp | 19 |
4 files changed, 43 insertions, 17 deletions
@@ -457,4 +457,21 @@ void zmq::unblock_socket (fd_t s_) #endif } +void zmq::enable_ipv4_mapping (fd_t s_) +{ +#ifdef IPV6_V6ONLY +#ifdef ZMQ_HAVE_WINDOWS + DWORD flag = 0; +#else + int flag = 0; +#endif + int rc = setsockopt (s_, IPPROTO_IPV6, IPV6_V6ONLY, (const char*) &flag, + sizeof (flag)); +#ifdef ZMQ_HAVE_WINDOWS + wsa_assert (rc != SOCKET_ERROR); +#else + errno_assert (rc == 0); +#endif +#endif +} @@ -68,6 +68,9 @@ namespace zmq // Sets the socket into non-blocking mode. void unblock_socket (fd_t s_); + // Enable IPv4-mapping of addresses in case it is disabled by default. + void enable_ipv4_mapping (fd_t s_); + } #endif diff --git a/src/tcp_connecter.cpp b/src/tcp_connecter.cpp index b3cd563..7531445 100644 --- a/src/tcp_connecter.cpp +++ b/src/tcp_connecter.cpp @@ -199,23 +199,10 @@ int zmq::tcp_connecter_t::open () return -1; #endif - // Enable IPv4-mapping of addresses in case it is disabled by default. -#ifdef IPV6_V6ONLY - if (addr.ss_family == AF_INET6) { -#ifdef ZMQ_HAVE_WINDOWS - DWORD flag = 0; -#else - int flag = 0; -#endif - int rc = setsockopt (s, IPPROTO_IPV6, IPV6_V6ONLY, - (const char*) &flag, sizeof (flag)); -#ifdef ZMQ_HAVE_WINDOWS - wsa_assert (rc != SOCKET_ERROR); -#else - errno_assert (rc == 0); -#endif - } -#endif + // On some systems, IPv4 mapping in IPv6 sockets is disabled by default. + // Switch it on in such cases. + if (addr.ss_family == AF_INET6) + enable_ipv4_mapping (s); // Set the socket to non-blocking mode so that we get async connect(). unblock_socket (s); diff --git a/src/tcp_listener.cpp b/src/tcp_listener.cpp index ef97862..406b4d0 100644 --- a/src/tcp_listener.cpp +++ b/src/tcp_listener.cpp @@ -131,6 +131,20 @@ int zmq::tcp_listener_t::set_address (const char *addr_) // Create a listening socket. s = ::socket (addr.ss_family, SOCK_STREAM, IPPROTO_TCP); #ifdef ZMQ_HAVE_WINDOWS + if (s == INVALID_SOCKET) + wsa_error_to_errno (); +#endif + + // IPv6 address family not supported, try automatic downgrade to IPv4. + if (addr.ss_family == AF_INET6 && errno == EAFNOSUPPORT && + !options.ipv4only) { + rc = resolve_ip_interface (&addr, &addr_len, addr_, true); + if (rc != 0) + return rc; + s = ::socket (addr.ss_family, SOCK_STREAM, IPPROTO_TCP); + } + +#ifdef ZMQ_HAVE_WINDOWS if (s == INVALID_SOCKET) { wsa_error_to_errno (); return -1; @@ -140,6 +154,11 @@ int zmq::tcp_listener_t::set_address (const char *addr_) return -1; #endif + // On some systems, IPv4 mapping in IPv6 sockets is disabled by default. + // Switch it on in such cases. + if (addr.ss_family == AF_INET6) + enable_ipv4_mapping (s); + // Allow reusing of the address. int flag = 1; #ifdef ZMQ_HAVE_WINDOWS |