From 1586f3f25ebb4b479e4334eccb551634425bcb0f Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Mon, 18 Apr 2016 17:12:01 +0100 Subject: [PATCH] Problem: can't test if IPv6 is available in tests Solution: add helper function is_ipv6_available to testutil.hpp to test if IPv6 is available on the building platform. This function will try to open and bind a socket to ::1:*, as it's the ultimate way of knowing if, at least on the loopback, IPv6 is enabled. --- tests/testutil.hpp | 52 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/tests/testutil.hpp b/tests/testutil.hpp index 1bf77dd8..bbb24fc8 100644 --- a/tests/testutil.hpp +++ b/tests/testutil.hpp @@ -47,6 +47,7 @@ #include #if defined _WIN32 +# include "windows.hpp" # if defined _MSC_VER # include # pragma warning(disable:4996) @@ -56,6 +57,9 @@ # include # include # include +# include +# include +# include #endif // Bounce a message from client to server and back @@ -299,5 +303,53 @@ void msleep (int milliseconds) #endif } +// check if IPv6 is available (0/false if not, 1/true if it is) +// only way to reliably check is to actually open a socket and try to bind it +int +is_ipv6_available(void) +{ + int rc, ipv6 = 1; + struct sockaddr_in6 test_addr; + + memset (&test_addr, 0, sizeof (test_addr)); + test_addr.sin6_family = AF_INET6; + inet_pton (AF_INET6, "::1", &(test_addr.sin6_addr)); + +#ifdef ZMQ_HAVE_WINDOWS + SOCKET fd = socket (AF_INET6, SOCK_STREAM, IPPROTO_IP); + if (fd == INVALID_SOCKET) + ipv6 = 0; + else { + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&ipv6, sizeof(int)); + rc = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&ipv6, sizeof(int)); + if (rc == SOCKET_ERROR) + ipv6 = 0; + else { + rc = bind (fd, (struct sockaddr *)&test_addr, sizeof (test_addr)); + if (rc == SOCKET_ERROR) + ipv6 = 0; + } + closesocket (fd); + } +#else + int fd = socket (AF_INET6, SOCK_STREAM, IPPROTO_IP); + if (fd == -1) + ipv6 = 0; + else { + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &ipv6, sizeof(int)); + rc = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6, sizeof(int)); + if (rc != 0) + ipv6 = 0; + else { + rc = bind (fd, (struct sockaddr *)&test_addr, sizeof (test_addr)); + if (rc != 0) + ipv6 = 0; + } + close (fd); + } +#endif + + return ipv6; +} #endif