diff --git a/envoy b/envoy index 23e5fc2939..70a5f295da 160000 --- a/envoy +++ b/envoy @@ -1 +1 @@ -Subproject commit 23e5fc2939e1782416155509edfca323150e8a59 +Subproject commit 70a5f295da789610b9d078015f43e39c6a76d4b6 diff --git a/library/common/engine.cc b/library/common/engine.cc index 08cfa031ad..92042d9f4c 100644 --- a/library/common/engine.cc +++ b/library/common/engine.cc @@ -7,6 +7,7 @@ #include "library/common/bridge/utility.h" #include "library/common/config/internal.h" #include "library/common/data/utility.h" +#include "library/common/network/android.h" #include "library/common/stats/utility.h" namespace Envoy { @@ -104,6 +105,7 @@ envoy_status_t Engine::main(const std::string config, const std::string log_leve network_configurator_ = Network::ConfiguratorFactory{server_->serverFactoryContext()}.get(); + Envoy::Network::Android::Utility::setAlternateGetifaddrs(); auto v4_interfaces = network_configurator_->enumerateV4Interfaces(); auto v6_interfaces = network_configurator_->enumerateV6Interfaces(); logInterfaces("netconf_get_v4_interfaces", v4_interfaces); diff --git a/library/common/http/header_utility.cc b/library/common/http/header_utility.cc index ddb4c54c19..09449de6f1 100644 --- a/library/common/http/header_utility.cc +++ b/library/common/http/header_utility.cc @@ -26,7 +26,7 @@ RequestHeaderMapPtr toRequestHeaders(envoy_headers headers) { auto transformed_headers = RequestHeaderMapImpl::create(); transformed_headers->setFormatter( std::make_unique< - Extensions::Http::HeaderFormatters::PreserveCase::PreserveCaseHeaderFormatter>()); + Extensions::Http::HeaderFormatters::PreserveCase::PreserveCaseHeaderFormatter>(false)); toEnvoyHeaders(*transformed_headers, headers); return transformed_headers; } diff --git a/library/common/network/BUILD b/library/common/network/BUILD index 79bbb2df6b..e7d023b0b1 100644 --- a/library/common/network/BUILD +++ b/library/common/network/BUILD @@ -8,6 +8,7 @@ envoy_cc_library( name = "configurator_lib", srcs = [ "configurator.cc", + "android.cc", ] + select({ "//bazel:include_ifaddrs": [ "//third_party:android/ifaddrs-android.h", @@ -16,7 +17,10 @@ envoy_cc_library( ], "//conditions:default": [], }), - hdrs = ["configurator.h"], + hdrs = [ + "android.h", + "configurator.h", + ], copts = select({ "//bazel:include_ifaddrs": ["-DINCLUDE_IFADDRS"], "//conditions:default": [], diff --git a/library/common/network/android.cc b/library/common/network/android.cc new file mode 100644 index 0000000000..5c9a5ec8bd --- /dev/null +++ b/library/common/network/android.cc @@ -0,0 +1,78 @@ +#include "library/common/network/android.h" + +#include + +#include "envoy/common/platform.h" + +#include "source/common/api/os_sys_calls_impl.h" +#include "source/common/common/assert.h" +#include "source/common/common/scalar_to_byte_vector.h" +#include "source/common/common/utility.h" +#include "source/common/network/addr_family_aware_socket_option_impl.h" +#include "source/common/network/address_impl.h" +#include "source/extensions/common/dynamic_forward_proxy/dns_cache_manager_impl.h" + +#include "library/common/network/src_addr_socket_option_impl.h" + +namespace Envoy { +namespace Network { +namespace Android { +namespace Utility { + +#if defined(INCLUDE_IFADDRS) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wold-style-cast" +namespace { +#include "third_party/android/ifaddrs-android.h" +} +#pragma clang diagnostic pop +#endif + +void setAlternateGetifaddrs() { +#if defined(INCLUDE_IFADDRS) + auto& os_syscalls = Api::OsSysCallsSingleton::get(); + ENVOY_BUG(!os_syscalls.supportsGetifaddrs(), + "setAlternateGetifaddrs should only be called when supportsGetifaddrs is false"); + + Api::AlternateGetifaddrs android_getifaddrs = + [](Api::InterfaceAddressVector& interfaces) -> Api::SysCallIntResult { + struct ifaddrs* ifaddr; + struct ifaddrs* ifa; + + const int rc = getifaddrs(&ifaddr); + if (rc == -1) { + return {rc, errno}; + } + + for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) { + if (ifa->ifa_addr == nullptr) { + continue; + } + + if (ifa->ifa_addr->sa_family == AF_INET || ifa->ifa_addr->sa_family == AF_INET6) { + const sockaddr_storage* ss = reinterpret_cast(ifa->ifa_addr); + size_t ss_len = + ifa->ifa_addr->sa_family == AF_INET ? sizeof(sockaddr_in) : sizeof(sockaddr_in6); + StatusOr address = + Address::addressFromSockAddr(*ss, ss_len, ifa->ifa_addr->sa_family == AF_INET6); + if (address.ok()) { + interfaces.emplace_back(ifa->ifa_name, ifa->ifa_flags, *address); + } + } + } + + if (ifaddr) { + freeifaddrs(ifaddr); + } + + return {rc, 0}; + }; + + os_syscalls.setAlternateGetifaddrs(android_getifaddrs); +#endif +} + +} // namespace Utility +} // namespace Android +} // namespace Network +} // namespace Envoy diff --git a/library/common/network/android.h b/library/common/network/android.h new file mode 100644 index 0000000000..148cbcb97e --- /dev/null +++ b/library/common/network/android.h @@ -0,0 +1,15 @@ +#pragma once + +namespace Envoy { +namespace Network { +namespace Android { +namespace Utility { +/** + * Sets an alternate `getifaddrs` implementation than the one defined + * in Envoy by default. + */ +void setAlternateGetifaddrs(); +} // namespace Utility +} // namespace Android +} // namespace Network +} // namespace Envoy diff --git a/library/common/network/configurator.cc b/library/common/network/configurator.cc index 60c93942d7..981c9682b0 100644 --- a/library/common/network/configurator.cc +++ b/library/common/network/configurator.cc @@ -4,6 +4,7 @@ #include "envoy/common/platform.h" +#include "source/common/api/os_sys_calls_impl.h" #include "source/common/common/assert.h" #include "source/common/common/scalar_to_byte_vector.h" #include "source/common/common/utility.h" @@ -49,10 +50,6 @@ #define DEFAULT_IP_TTL 64 -#ifdef SUPPORTS_GETIFADDRS -#include -#endif - // Prefixes used to prefer well-known interface names. #if defined(__APPLE__) constexpr absl::string_view WlanPrefix = "en"; @@ -69,16 +66,6 @@ constexpr absl::string_view WwanPrefix = ""; namespace Envoy { namespace Network { -#if !defined(SUPPORTS_GETIFADDRS) && defined(INCLUDE_IFADDRS) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wold-style-cast" -namespace { -#include "third_party/android/ifaddrs-android.h" -} -#pragma clang diagnostic pop -#define SUPPORTS_GETIFADDRS -#endif - SINGLETON_MANAGER_REGISTRATION(network_configurator); constexpr absl::string_view BaseDnsCache = "base_dns_cache"; @@ -329,33 +316,28 @@ Configurator::enumerateInterfaces([[maybe_unused]] unsigned short family, [[maybe_unused]] unsigned int reject_flags) { std::vector pairs{}; -#ifdef SUPPORTS_GETIFADDRS - struct ifaddrs* interfaces = nullptr; - struct ifaddrs* ifa = nullptr; + if (!Api::OsSysCallsSingleton::get().supportsGetifaddrs()) { + return pairs; + } - const int rc = getifaddrs(&interfaces); - RELEASE_ASSERT(!rc, "getifaddrs failed"); + Api::InterfaceAddressVector interface_addresses{}; + const Api::SysCallIntResult rc = Api::OsSysCallsSingleton::get().getifaddrs(interface_addresses); + RELEASE_ASSERT(!rc.return_value_, fmt::format("getiffaddrs error: {}", rc.errno_)); - for (ifa = interfaces; ifa != nullptr; ifa = ifa->ifa_next) { - if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != family) { - continue; - } - if ((ifa->ifa_flags & (select_flags ^ reject_flags)) != select_flags) { + for (const auto& interface_address : interface_addresses) { + const auto family_version = family == AF_INET ? Envoy::Network::Address::IpVersion::v4 + : Envoy::Network::Address::IpVersion::v6; + if (interface_address.interface_addr_->ip()->version() != family_version) { continue; } - const sockaddr_storage* ss = reinterpret_cast(ifa->ifa_addr); - size_t ss_len = family == AF_INET ? sizeof(sockaddr_in) : sizeof(sockaddr_in6); - StatusOr address = - Address::addressFromSockAddr(*ss, ss_len, family == AF_INET6); - if (!address.ok()) { + if ((interface_address.interface_flags_ & (select_flags ^ reject_flags)) != select_flags) { continue; } - pairs.push_back(std::make_pair(std::string{ifa->ifa_name}, *address)); - } - freeifaddrs(interfaces); -#endif // SUPPORTS_GETIFADDRS + pairs.push_back( + std::make_pair(interface_address.interface_name_, interface_address.interface_addr_)); + } return pairs; } diff --git a/test/common/integration/client_integration_test.cc b/test/common/integration/client_integration_test.cc index 52480f7e67..6e104cd2bb 100644 --- a/test/common/integration/client_integration_test.cc +++ b/test/common/integration/client_integration_test.cc @@ -25,7 +25,7 @@ Http::ResponseHeaderMapPtr toResponseHeaders(envoy_headers headers) { Http::ResponseHeaderMapImpl::create(); transformed_headers->setFormatter( std::make_unique< - Extensions::Http::HeaderFormatters::PreserveCase::PreserveCaseHeaderFormatter>()); + Extensions::Http::HeaderFormatters::PreserveCase::PreserveCaseHeaderFormatter>(false)); Http::Utility::toEnvoyHeaders(*transformed_headers, headers); return transformed_headers; } @@ -335,7 +335,7 @@ TEST_P(ClientIntegrationTest, CaseSensitive) { Http::TestRequestHeaderMapImpl headers{{"FoO", "bar"}}; headers.header_map_->setFormatter( std::make_unique< - Extensions::Http::HeaderFormatters::PreserveCase::PreserveCaseHeaderFormatter>()); + Extensions::Http::HeaderFormatters::PreserveCase::PreserveCaseHeaderFormatter>(false)); headers.header_map_->formatter().value().get().processKey("FoO"); HttpTestUtility::addDefaultHeaders(headers); envoy_headers c_headers = Http::Utility::toBridgeHeaders(headers); diff --git a/test/common/network/configurator_test.cc b/test/common/network/configurator_test.cc index d0f6f532f9..d3bd529c63 100644 --- a/test/common/network/configurator_test.cc +++ b/test/common/network/configurator_test.cc @@ -124,6 +124,7 @@ TEST_F(ConfiguratorTest, ReportNetworkUsageDisregardsCallsWithStaleConfiguration TEST_F(ConfiguratorTest, EnumerateInterfacesFiltersByFlags) { // Select loopback. auto loopbacks = configurator_->enumerateInterfaces(AF_INET, IFF_LOOPBACK, 0); + EXPECT_EQ(loopbacks.size(), 1); EXPECT_EQ(std::get(loopbacks[0]).rfind("lo", 0), 0); // Reject loopback.