diff --git a/Makefile b/Makefile index b42ab57cee8..dece13bdd69 100644 --- a/Makefile +++ b/Makefile @@ -1013,7 +1013,6 @@ LIBGRPC_TEST_UTIL_SRC = \ test/core/statistics/census_log_tests.c \ test/core/transport/transport_end2end_tests.c \ test/core/util/grpc_profiler.c \ - test/core/util/ipv6_posix.c \ test/core/util/parse_hexstring.c \ test/core/util/port_posix.c \ test/core/util/slice_splitter.c \ diff --git a/build.json b/build.json index 64a1df266b2..07e2318e4b0 100644 --- a/build.json +++ b/build.json @@ -289,7 +289,6 @@ "test/core/statistics/census_log_tests.c", "test/core/transport/transport_end2end_tests.c", "test/core/util/grpc_profiler.c", - "test/core/util/ipv6_posix.c", "test/core/util/parse_hexstring.c", "test/core/util/port_posix.c", "test/core/util/slice_splitter.c", diff --git a/src/core/iomgr/socket_utils_common_posix.c b/src/core/iomgr/socket_utils_common_posix.c index 0767d6f9180..7f2b43f2cad 100644 --- a/src/core/iomgr/socket_utils_common_posix.c +++ b/src/core/iomgr/socket_utils_common_posix.c @@ -50,6 +50,7 @@ #include #include #include +#include /* set a socket to non blocking mode */ int grpc_set_socket_nonblocking(int fd, int non_blocking) { @@ -111,6 +112,34 @@ int grpc_set_socket_low_latency(int fd, int low_latency) { newval == val; } +static gpr_once g_probe_ipv6_once = GPR_ONCE_INIT; +static int g_ipv6_loopback_available; + +static void probe_ipv6_once() { + int fd = socket(AF_INET6, SOCK_STREAM, 0); + g_ipv6_loopback_available = 0; + if (fd < 0) { + gpr_log(GPR_INFO, "Disabling AF_INET6 sockets because socket() failed."); + } else { + struct sockaddr_in6 addr; + memset(&addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + addr.sin6_addr.s6_addr[15] = 1; /* [::1]:0 */ + if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == 0) { + g_ipv6_loopback_available = 1; + } else { + gpr_log(GPR_INFO, + "Disabling AF_INET6 sockets because ::1 is not available."); + } + close(fd); + } +} + +int grpc_ipv6_loopback_available() { + gpr_once_init(&g_probe_ipv6_once, probe_ipv6_once); + return g_ipv6_loopback_available; +} + /* This should be 0 in production, but it may be enabled for testing or debugging purposes, to simulate an environment where IPv6 sockets can't also speak IPv4. */ @@ -132,7 +161,13 @@ int grpc_create_dualstack_socket(const struct sockaddr *addr, int type, int protocol, grpc_dualstack_mode *dsmode) { int family = addr->sa_family; if (family == AF_INET6) { - int fd = socket(family, type, protocol); + int fd; + if (grpc_ipv6_loopback_available()) { + fd = socket(family, type, protocol); + } else { + fd = -1; + errno = EAFNOSUPPORT; + } /* Check if we've got a valid dualstack socket. */ if (fd >= 0 && set_socket_dualstack(fd)) { *dsmode = GRPC_DSMODE_DUALSTACK; diff --git a/src/core/iomgr/socket_utils_posix.h b/src/core/iomgr/socket_utils_posix.h index 5c31e5e6d88..9c5d93c2b4b 100644 --- a/src/core/iomgr/socket_utils_posix.h +++ b/src/core/iomgr/socket_utils_posix.h @@ -53,6 +53,16 @@ int grpc_set_socket_reuse_addr(int fd, int reuse); /* disable nagle */ int grpc_set_socket_low_latency(int fd, int low_latency); +/* Returns true if this system can create AF_INET6 sockets bound to ::1. + The value is probed once, and cached for the life of the process. + + This is more restrictive than checking for socket(AF_INET6) to succeed, + because Linux with "net.ipv6.conf.all.disable_ipv6 = 1" is able to create + and bind IPv6 sockets, but cannot connect to a getsockname() of [::]:port + without a valid loopback interface. Rather than expose this half-broken + state to library users, we turn off IPv6 sockets. */ +int grpc_ipv6_loopback_available(); + /* An enum to keep track of IPv4/IPv6 socket modes. Currently, this information is only used when a socket is first created, but diff --git a/test/core/echo/echo_test.c b/test/core/echo/echo_test.c index cc265cadbf0..748e8bc0ef0 100644 --- a/test/core/echo/echo_test.c +++ b/test/core/echo/echo_test.c @@ -40,11 +40,11 @@ #include #include +#include "src/core/iomgr/socket_utils_posix.h" #include #include #include #include -#include "test/core/util/ipv6.h" #include "test/core/util/port.h" int test_client(const char *root, const char *host, int port) { diff --git a/test/core/end2end/dualstack_socket_test.c b/test/core/end2end/dualstack_socket_test.c index 808fcbd65d2..b443caa2a67 100644 --- a/test/core/end2end/dualstack_socket_test.c +++ b/test/core/end2end/dualstack_socket_test.c @@ -37,7 +37,6 @@ #include #include #include "test/core/end2end/cq_verifier.h" -#include "test/core/util/ipv6.h" #include "test/core/util/port.h" #include "test/core/util/test_config.h" diff --git a/test/core/util/ipv6.h b/test/core/util/ipv6.h deleted file mode 100644 index bb536645b87..00000000000 --- a/test/core/util/ipv6.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * - * Copyright 2014, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef __GRPC_TEST_UTIL_IPV6_H__ -#define __GRPC_TEST_UTIL_IPV6_H__ - -/* Returns true if we're able to create an AF_INET6 socket bound to ::1 on an - arbitrary port. */ -int grpc_ipv6_loopback_available(); - -#endif /* __GRPC_TEST_UTIL_IPV6_H__ */ diff --git a/test/core/util/ipv6_posix.c b/test/core/util/ipv6_posix.c deleted file mode 100644 index 25758f59fea..00000000000 --- a/test/core/util/ipv6_posix.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * - * Copyright 2014, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include -#ifdef GPR_POSIX_SOCKET - -#include "test/core/util/ipv6.h" - -#include -#include -#include -#include - -int grpc_ipv6_loopback_available() { - int ok = 0; - int fd = socket(AF_INET6, SOCK_STREAM, 0); - if (fd >= 0) { - struct sockaddr_in6 addr; - memset(&addr, 0, sizeof(addr)); - addr.sin6_family = AF_INET6; - addr.sin6_addr.s6_addr[15] = 1; /* [::1]:0 */ - if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == 0) { - ok = 1; - } - close(fd); - } - return ok; -} - -#endif /* GPR_POSIX_SOCKET */ diff --git a/vsprojects/vs2013/grpc_test_util.vcxproj b/vsprojects/vs2013/grpc_test_util.vcxproj index 9a118cf590c..a86d415cc6e 100644 --- a/vsprojects/vs2013/grpc_test_util.vcxproj +++ b/vsprojects/vs2013/grpc_test_util.vcxproj @@ -89,8 +89,6 @@ - -