Loading ResolverController.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -100,6 +100,7 @@ int getDnsInfo(unsigned netId, std::vector<std::string>* servers, std::vector<st domains->clear(); *params = res_params{}; stats->clear(); wait_for_pending_req_timeout_count->clear(); int res_wait_for_pending_req_timeout_count; int revision_id = android_net_res_stats_get_info_for_net( netId, &nscount, res_servers, &dcount, res_domains, params, res_stats, Loading Loading @@ -149,7 +150,7 @@ int getDnsInfo(unsigned netId, std::vector<std::string>* servers, std::vector<st domains->push_back(res_domains[i]); } (*wait_for_pending_req_timeout_count)[0] = res_wait_for_pending_req_timeout_count; wait_for_pending_req_timeout_count->push_back(res_wait_for_pending_req_timeout_count); return 0; } Loading tests/Android.bp +11 −3 Original line number Diff line number Diff line Loading @@ -114,9 +114,17 @@ cc_test { "server_configurable_flags", "stats_proto", ], // MTS test binary can't be built under compile_multilib = "both" and having test data. // However, MTS coverage requires 32 bit test binary to run. compile_multilib: "prefer32", // TODO: Remove multilib after coverage test switched to 64-bit device. // See comments in target "resolv_test_mts_coverage_defaults". compile_multilib: "both", multilib: { lib32: { suffix: "32", }, lib64: { suffix: "64", }, }, } cc_test { Loading tests/dns_responder/dns_responder.cpp +15 −18 Original line number Diff line number Diff line Loading @@ -41,6 +41,8 @@ #include <netdutils/InternetAddresses.h> #include <netdutils/SocketOption.h> using android::base::ErrnoError; using android::base::Result; using android::base::unique_fd; using android::netdutils::BackoffSequence; using android::netdutils::enableSockopt; Loading Loading @@ -76,7 +78,7 @@ std::string bytesToHexStr(std::span<const uint8_t> bytes) { // Because The address might still being set up (b/186181084), This is a wrapper function // that retries bind() if errno is EADDRNOTAVAIL int bindSocket(int socket, const sockaddr* address, socklen_t address_len) { Result<void> bindSocket(int socket, const sockaddr* address, socklen_t address_len) { // Set the wrapper to try bind() at most 6 times with backoff time // (100 ms, 200 ms, ..., 1600 ms). auto backoff = BackoffSequence<milliseconds>::Builder() Loading @@ -85,20 +87,13 @@ int bindSocket(int socket, const sockaddr* address, socklen_t address_len) { .build(); while (true) { int ret = bind(socket, address, address_len); if (ret == 0 || errno != EADDRNOTAVAIL) { return ret; } if (!backoff.hasNextTimeout()) break; if (0 == bind(socket, address, address_len)) return {}; if (errno != EADDRNOTAVAIL) return ErrnoError(); if (!backoff.hasNextTimeout()) return ErrnoError(); LOG(WARNING) << "Retry to bind " << addr2str(address, address_len); std::this_thread::sleep_for(backoff.getNextTimeout()); } // Set errno before return since it might have been changed somewhere. errno = EADDRNOTAVAIL; return -1; } /* DNS struct helpers */ Loading Loading @@ -1257,8 +1252,9 @@ unique_fd DNSResponder::createListeningSocket(int socket_type) { struct sockaddr_in addr = {.sin_family = AF_INET, .sin_port = htons(mdns_port), .sin_addr = {INADDR_ANY}}; if (bindSocket(fd.get(), (struct sockaddr*)&addr, sizeof(addr))) { LOG(ERROR) << "Unable to bind socket to interface."; if (auto result = bindSocket(fd.get(), (struct sockaddr*)&addr, sizeof(addr)); !result.ok()) { LOG(ERROR) << "failed to bind. MDNS IPv4: " << result.error().message(); return {}; } } else if (ai_res->ai_family == AF_INET6) { Loading @@ -1276,17 +1272,18 @@ unique_fd DNSResponder::createListeningSocket(int socket_type) { .sin6_port = htons(mdns_port), .sin6_addr = IN6ADDR_ANY_INIT, }; if (bindSocket(fd.get(), (struct sockaddr*)&addr, sizeof(addr))) { LOG(ERROR) << "Unable to bind socket to interface.MDNS IPV6"; if (auto result = bindSocket(fd.get(), (struct sockaddr*)&addr, sizeof(addr)); !result.ok()) { LOG(ERROR) << "failed to bind. MDNS IPV6: " << result.error().message(); return {}; } } return fd; } else { const char* socket_str = (socket_type == SOCK_STREAM) ? "TCP" : "UDP"; if (bindSocket(fd.get(), ai->ai_addr, ai->ai_addrlen)) { PLOG(ERROR) << "failed to bind " << socket_str << " " << host_str << ":" << listen_service_; if (auto result = bindSocket(fd.get(), ai->ai_addr, ai->ai_addrlen); !result.ok()) { LOG(ERROR) << "failed to bind " << socket_str << " " << host_str << ":" << listen_service_ << " " << result.error().message(); continue; } LOG(INFO) << "bound to " << socket_str << " " << host_str << ":" << listen_service_; Loading tests/dns_responder/dns_responder_client_ndk.cpp +45 −28 Original line number Diff line number Diff line Loading @@ -30,6 +30,8 @@ using aidl::android::net::IDnsResolver; using aidl::android::net::INetd; using aidl::android::net::ResolverOptionsParcel; using aidl::android::net::ResolverParamsParcel; using android::base::Error; using android::base::Result; using android::net::ResolverStats; ResolverParams::Builder::Builder() { Loading Loading @@ -66,36 +68,51 @@ void DnsResponderClient::SetupMappings(unsigned numHosts, const std::vector<std: } } bool DnsResponderClient::GetResolverInfo(aidl::android::net::IDnsResolver* dnsResolverService, unsigned netId, std::vector<std::string>* servers, std::vector<std::string>* domains, std::vector<std::string>* tlsServers, res_params* params, std::vector<ResolverStats>* stats, int* waitForPendingReqTimeoutCount) { using aidl::android::net::IDnsResolver; std::vector<int32_t> params32; std::vector<int32_t> stats32; std::vector<int32_t> waitForPendingReqTimeoutCount32{0}; auto rv = dnsResolverService->getResolverInfo(netId, servers, domains, tlsServers, ¶ms32, &stats32, &waitForPendingReqTimeoutCount32); if (!rv.isOk() || params32.size() != static_cast<size_t>(IDnsResolver::RESOLVER_PARAMS_COUNT)) { return false; } *params = res_params{ .sample_validity = static_cast<uint16_t>(params32[IDnsResolver::RESOLVER_PARAMS_SAMPLE_VALIDITY]), .success_threshold = static_cast<uint8_t>(params32[IDnsResolver::RESOLVER_PARAMS_SUCCESS_THRESHOLD]), Result<ResolverInfo> DnsResponderClient::getResolverInfo() { std::vector<std::string> dnsServers; std::vector<std::string> domains; std::vector<std::string> dotServers; std::vector<int32_t> params; std::vector<int32_t> stats; std::vector<int32_t> waitForPendingReqTimeoutCount; auto rv = mDnsResolvSrv->getResolverInfo(TEST_NETID, &dnsServers, &domains, &dotServers, ¶ms, &stats, &waitForPendingReqTimeoutCount); if (!rv.isOk()) { return Error() << "getResolverInfo failed: " << rv.getMessage(); } if (stats.size() % IDnsResolver::RESOLVER_STATS_COUNT != 0) { return Error() << "Unexpected stats size: " << stats.size(); } if (params.size() != IDnsResolver::RESOLVER_PARAMS_COUNT) { return Error() << "Unexpected params size: " << params.size(); } if (waitForPendingReqTimeoutCount.size() != 1) { return Error() << "Unexpected waitForPendingReqTimeoutCount size: " << waitForPendingReqTimeoutCount.size(); } ResolverInfo out = { .dnsServers = std::move(dnsServers), .domains = std::move(domains), .dotServers = std::move(dotServers), .params{ .sample_validity = static_cast<uint16_t>( params[IDnsResolver::RESOLVER_PARAMS_SAMPLE_VALIDITY]), .success_threshold = static_cast<uint8_t>( params[IDnsResolver::RESOLVER_PARAMS_SUCCESS_THRESHOLD]), .min_samples = static_cast<uint8_t>(params32[IDnsResolver::RESOLVER_PARAMS_MIN_SAMPLES]), static_cast<uint8_t>(params[IDnsResolver::RESOLVER_PARAMS_MIN_SAMPLES]), .max_samples = static_cast<uint8_t>(params32[IDnsResolver::RESOLVER_PARAMS_MAX_SAMPLES]), .base_timeout_msec = params32[IDnsResolver::RESOLVER_PARAMS_BASE_TIMEOUT_MSEC], .retry_count = params32[IDnsResolver::RESOLVER_PARAMS_RETRY_COUNT], static_cast<uint8_t>(params[IDnsResolver::RESOLVER_PARAMS_MAX_SAMPLES]), .base_timeout_msec = params[IDnsResolver::RESOLVER_PARAMS_BASE_TIMEOUT_MSEC], .retry_count = params[IDnsResolver::RESOLVER_PARAMS_RETRY_COUNT], }, .stats = {}, .waitForPendingReqTimeoutCount = waitForPendingReqTimeoutCount[0], }; *waitForPendingReqTimeoutCount = waitForPendingReqTimeoutCount32[0]; return ResolverStats::decodeAll(stats32, stats); ResolverStats::decodeAll(stats, &out.stats); return std::move(out); } bool DnsResponderClient::SetResolversForNetwork(const std::vector<std::string>& servers, Loading tests/dns_responder/dns_responder_client_ndk.h +12 −6 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <android-base/format.h> #include <android-base/logging.h> #include <android-base/result.h> #include <aidl/android/net/IDnsResolver.h> #include <aidl/android/net/INetd.h> Loading @@ -47,6 +48,16 @@ inline constexpr char kDefaultSearchDomain[] = "example.com"; } \ } while (0) // A thin wrapper to store the outputs of DnsResolver::getResolverInfo(). struct ResolverInfo { std::vector<std::string> dnsServers; std::vector<std::string> domains; std::vector<std::string> dotServers; res_params params; std::vector<android::net::ResolverStats> stats; int waitForPendingReqTimeoutCount; }; class ResolverParams { public: class Builder { Loading Loading @@ -132,12 +143,7 @@ class DnsResponderClient { static NativeNetworkConfig makeNativeNetworkConfig(int netId, NativeNetworkType networkType, int permission, bool secure); static bool GetResolverInfo(aidl::android::net::IDnsResolver* dnsResolverService, unsigned netId, std::vector<std::string>* servers, std::vector<std::string>* domains, std::vector<std::string>* tlsServers, res_params* params, std::vector<android::net::ResolverStats>* stats, int* waitForPendingReqTimeoutCount); android::base::Result<ResolverInfo> getResolverInfo(); // Return a default resolver configuration for opportunistic mode. static aidl::android::net::ResolverParamsParcel GetDefaultResolverParamsParcel(); Loading Loading
ResolverController.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -100,6 +100,7 @@ int getDnsInfo(unsigned netId, std::vector<std::string>* servers, std::vector<st domains->clear(); *params = res_params{}; stats->clear(); wait_for_pending_req_timeout_count->clear(); int res_wait_for_pending_req_timeout_count; int revision_id = android_net_res_stats_get_info_for_net( netId, &nscount, res_servers, &dcount, res_domains, params, res_stats, Loading Loading @@ -149,7 +150,7 @@ int getDnsInfo(unsigned netId, std::vector<std::string>* servers, std::vector<st domains->push_back(res_domains[i]); } (*wait_for_pending_req_timeout_count)[0] = res_wait_for_pending_req_timeout_count; wait_for_pending_req_timeout_count->push_back(res_wait_for_pending_req_timeout_count); return 0; } Loading
tests/Android.bp +11 −3 Original line number Diff line number Diff line Loading @@ -114,9 +114,17 @@ cc_test { "server_configurable_flags", "stats_proto", ], // MTS test binary can't be built under compile_multilib = "both" and having test data. // However, MTS coverage requires 32 bit test binary to run. compile_multilib: "prefer32", // TODO: Remove multilib after coverage test switched to 64-bit device. // See comments in target "resolv_test_mts_coverage_defaults". compile_multilib: "both", multilib: { lib32: { suffix: "32", }, lib64: { suffix: "64", }, }, } cc_test { Loading
tests/dns_responder/dns_responder.cpp +15 −18 Original line number Diff line number Diff line Loading @@ -41,6 +41,8 @@ #include <netdutils/InternetAddresses.h> #include <netdutils/SocketOption.h> using android::base::ErrnoError; using android::base::Result; using android::base::unique_fd; using android::netdutils::BackoffSequence; using android::netdutils::enableSockopt; Loading Loading @@ -76,7 +78,7 @@ std::string bytesToHexStr(std::span<const uint8_t> bytes) { // Because The address might still being set up (b/186181084), This is a wrapper function // that retries bind() if errno is EADDRNOTAVAIL int bindSocket(int socket, const sockaddr* address, socklen_t address_len) { Result<void> bindSocket(int socket, const sockaddr* address, socklen_t address_len) { // Set the wrapper to try bind() at most 6 times with backoff time // (100 ms, 200 ms, ..., 1600 ms). auto backoff = BackoffSequence<milliseconds>::Builder() Loading @@ -85,20 +87,13 @@ int bindSocket(int socket, const sockaddr* address, socklen_t address_len) { .build(); while (true) { int ret = bind(socket, address, address_len); if (ret == 0 || errno != EADDRNOTAVAIL) { return ret; } if (!backoff.hasNextTimeout()) break; if (0 == bind(socket, address, address_len)) return {}; if (errno != EADDRNOTAVAIL) return ErrnoError(); if (!backoff.hasNextTimeout()) return ErrnoError(); LOG(WARNING) << "Retry to bind " << addr2str(address, address_len); std::this_thread::sleep_for(backoff.getNextTimeout()); } // Set errno before return since it might have been changed somewhere. errno = EADDRNOTAVAIL; return -1; } /* DNS struct helpers */ Loading Loading @@ -1257,8 +1252,9 @@ unique_fd DNSResponder::createListeningSocket(int socket_type) { struct sockaddr_in addr = {.sin_family = AF_INET, .sin_port = htons(mdns_port), .sin_addr = {INADDR_ANY}}; if (bindSocket(fd.get(), (struct sockaddr*)&addr, sizeof(addr))) { LOG(ERROR) << "Unable to bind socket to interface."; if (auto result = bindSocket(fd.get(), (struct sockaddr*)&addr, sizeof(addr)); !result.ok()) { LOG(ERROR) << "failed to bind. MDNS IPv4: " << result.error().message(); return {}; } } else if (ai_res->ai_family == AF_INET6) { Loading @@ -1276,17 +1272,18 @@ unique_fd DNSResponder::createListeningSocket(int socket_type) { .sin6_port = htons(mdns_port), .sin6_addr = IN6ADDR_ANY_INIT, }; if (bindSocket(fd.get(), (struct sockaddr*)&addr, sizeof(addr))) { LOG(ERROR) << "Unable to bind socket to interface.MDNS IPV6"; if (auto result = bindSocket(fd.get(), (struct sockaddr*)&addr, sizeof(addr)); !result.ok()) { LOG(ERROR) << "failed to bind. MDNS IPV6: " << result.error().message(); return {}; } } return fd; } else { const char* socket_str = (socket_type == SOCK_STREAM) ? "TCP" : "UDP"; if (bindSocket(fd.get(), ai->ai_addr, ai->ai_addrlen)) { PLOG(ERROR) << "failed to bind " << socket_str << " " << host_str << ":" << listen_service_; if (auto result = bindSocket(fd.get(), ai->ai_addr, ai->ai_addrlen); !result.ok()) { LOG(ERROR) << "failed to bind " << socket_str << " " << host_str << ":" << listen_service_ << " " << result.error().message(); continue; } LOG(INFO) << "bound to " << socket_str << " " << host_str << ":" << listen_service_; Loading
tests/dns_responder/dns_responder_client_ndk.cpp +45 −28 Original line number Diff line number Diff line Loading @@ -30,6 +30,8 @@ using aidl::android::net::IDnsResolver; using aidl::android::net::INetd; using aidl::android::net::ResolverOptionsParcel; using aidl::android::net::ResolverParamsParcel; using android::base::Error; using android::base::Result; using android::net::ResolverStats; ResolverParams::Builder::Builder() { Loading Loading @@ -66,36 +68,51 @@ void DnsResponderClient::SetupMappings(unsigned numHosts, const std::vector<std: } } bool DnsResponderClient::GetResolverInfo(aidl::android::net::IDnsResolver* dnsResolverService, unsigned netId, std::vector<std::string>* servers, std::vector<std::string>* domains, std::vector<std::string>* tlsServers, res_params* params, std::vector<ResolverStats>* stats, int* waitForPendingReqTimeoutCount) { using aidl::android::net::IDnsResolver; std::vector<int32_t> params32; std::vector<int32_t> stats32; std::vector<int32_t> waitForPendingReqTimeoutCount32{0}; auto rv = dnsResolverService->getResolverInfo(netId, servers, domains, tlsServers, ¶ms32, &stats32, &waitForPendingReqTimeoutCount32); if (!rv.isOk() || params32.size() != static_cast<size_t>(IDnsResolver::RESOLVER_PARAMS_COUNT)) { return false; } *params = res_params{ .sample_validity = static_cast<uint16_t>(params32[IDnsResolver::RESOLVER_PARAMS_SAMPLE_VALIDITY]), .success_threshold = static_cast<uint8_t>(params32[IDnsResolver::RESOLVER_PARAMS_SUCCESS_THRESHOLD]), Result<ResolverInfo> DnsResponderClient::getResolverInfo() { std::vector<std::string> dnsServers; std::vector<std::string> domains; std::vector<std::string> dotServers; std::vector<int32_t> params; std::vector<int32_t> stats; std::vector<int32_t> waitForPendingReqTimeoutCount; auto rv = mDnsResolvSrv->getResolverInfo(TEST_NETID, &dnsServers, &domains, &dotServers, ¶ms, &stats, &waitForPendingReqTimeoutCount); if (!rv.isOk()) { return Error() << "getResolverInfo failed: " << rv.getMessage(); } if (stats.size() % IDnsResolver::RESOLVER_STATS_COUNT != 0) { return Error() << "Unexpected stats size: " << stats.size(); } if (params.size() != IDnsResolver::RESOLVER_PARAMS_COUNT) { return Error() << "Unexpected params size: " << params.size(); } if (waitForPendingReqTimeoutCount.size() != 1) { return Error() << "Unexpected waitForPendingReqTimeoutCount size: " << waitForPendingReqTimeoutCount.size(); } ResolverInfo out = { .dnsServers = std::move(dnsServers), .domains = std::move(domains), .dotServers = std::move(dotServers), .params{ .sample_validity = static_cast<uint16_t>( params[IDnsResolver::RESOLVER_PARAMS_SAMPLE_VALIDITY]), .success_threshold = static_cast<uint8_t>( params[IDnsResolver::RESOLVER_PARAMS_SUCCESS_THRESHOLD]), .min_samples = static_cast<uint8_t>(params32[IDnsResolver::RESOLVER_PARAMS_MIN_SAMPLES]), static_cast<uint8_t>(params[IDnsResolver::RESOLVER_PARAMS_MIN_SAMPLES]), .max_samples = static_cast<uint8_t>(params32[IDnsResolver::RESOLVER_PARAMS_MAX_SAMPLES]), .base_timeout_msec = params32[IDnsResolver::RESOLVER_PARAMS_BASE_TIMEOUT_MSEC], .retry_count = params32[IDnsResolver::RESOLVER_PARAMS_RETRY_COUNT], static_cast<uint8_t>(params[IDnsResolver::RESOLVER_PARAMS_MAX_SAMPLES]), .base_timeout_msec = params[IDnsResolver::RESOLVER_PARAMS_BASE_TIMEOUT_MSEC], .retry_count = params[IDnsResolver::RESOLVER_PARAMS_RETRY_COUNT], }, .stats = {}, .waitForPendingReqTimeoutCount = waitForPendingReqTimeoutCount[0], }; *waitForPendingReqTimeoutCount = waitForPendingReqTimeoutCount32[0]; return ResolverStats::decodeAll(stats32, stats); ResolverStats::decodeAll(stats, &out.stats); return std::move(out); } bool DnsResponderClient::SetResolversForNetwork(const std::vector<std::string>& servers, Loading
tests/dns_responder/dns_responder_client_ndk.h +12 −6 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <android-base/format.h> #include <android-base/logging.h> #include <android-base/result.h> #include <aidl/android/net/IDnsResolver.h> #include <aidl/android/net/INetd.h> Loading @@ -47,6 +48,16 @@ inline constexpr char kDefaultSearchDomain[] = "example.com"; } \ } while (0) // A thin wrapper to store the outputs of DnsResolver::getResolverInfo(). struct ResolverInfo { std::vector<std::string> dnsServers; std::vector<std::string> domains; std::vector<std::string> dotServers; res_params params; std::vector<android::net::ResolverStats> stats; int waitForPendingReqTimeoutCount; }; class ResolverParams { public: class Builder { Loading Loading @@ -132,12 +143,7 @@ class DnsResponderClient { static NativeNetworkConfig makeNativeNetworkConfig(int netId, NativeNetworkType networkType, int permission, bool secure); static bool GetResolverInfo(aidl::android::net::IDnsResolver* dnsResolverService, unsigned netId, std::vector<std::string>* servers, std::vector<std::string>* domains, std::vector<std::string>* tlsServers, res_params* params, std::vector<android::net::ResolverStats>* stats, int* waitForPendingReqTimeoutCount); android::base::Result<ResolverInfo> getResolverInfo(); // Return a default resolver configuration for opportunistic mode. static aidl::android::net::ResolverParamsParcel GetDefaultResolverParamsParcel(); Loading