Loading DnsProxyListener.cpp +6 −2 Original line number Diff line number Diff line Loading @@ -1159,7 +1159,9 @@ void DnsProxyListener::GetHostByNameHandler::run() { event.set_latency_micros(latencyUs); event.set_event_type(EVENT_GETHOSTBYNAME); LOG(DEBUG) << "GetHostByNameHandler::run: result: " << gai_strerror(rv); if (rv) { LOG(DEBUG) << "GetHostByNameHandler::run: result failed: " << gai_strerror(rv); } bool success = true; if (hp) { Loading Loading @@ -1314,7 +1316,9 @@ void DnsProxyListener::GetHostByAddrHandler::run() { event.set_latency_micros(latencyUs); event.set_event_type(EVENT_GETHOSTBYADDR); LOG(DEBUG) << "GetHostByAddrHandler::run: result: " << gai_strerror(rv); if (rv) { LOG(DEBUG) << "GetHostByAddrHandler::run: result failed: " << gai_strerror(rv); } bool success = true; if (hp) { Loading apex/Android.bp +2 −4 Original line number Diff line number Diff line Loading @@ -24,7 +24,6 @@ package { apex { name: "com.android.resolv", updatable: true, manifest: "manifest.json", multilib: { first: { Loading @@ -41,14 +40,13 @@ apex { // Whether it actually will be compressed is controlled on per-device basis. compressible: true, // IMPORTANT: For the APEX to be installed on Android 10, // min_sdk_version should be 29. This enables the build system to make // IMPORTANT: q-launched-apex-module enables the build system to make // sure the package compatible to Android 10 in two ways: // - build the APEX package compatible to Android 10 // so that the package can be installed. // - build artifacts (lib/javalib/bin) against Android 10 SDK // so that the artifacts can run. min_sdk_version: "29", defaults: ["q-launched-apex-module"], } apex_key { Loading doh/boot_time.rs +16 −0 Original line number Diff line number Diff line Loading @@ -123,6 +123,7 @@ impl TimerFd { } fn set(&self, duration: Duration) { assert_ne!(duration, Duration::from_millis(0)); let timer = libc::itimerspec { it_interval: libc::timespec { tv_sec: 0, tv_nsec: 0 }, it_value: libc::timespec { Loading @@ -147,6 +148,13 @@ pub async fn timeout<T>(duration: Duration, future: impl Future<Output = T>) -> // Ideally, all timeouts in a runtime would share a timerfd. That will be much more // straightforwards to implement when moving this functionality into `tokio`. // According to timerfd_settime(), setting zero duration will disarm the timer, so // we return immediate timeout here. // Can't use is_zero() for now because sc-mainline-prod's Rust version is below 1.53. if duration == Duration::from_millis(0) { return Err(Elapsed(())); } // The failure conditions for this are rare (see `man 2 timerfd_create`) and the caller would // not be able to do much in response to them. When integrated into tokio, this would be called // during runtime setup. Loading Loading @@ -204,3 +212,11 @@ async fn timeout_drift() { assert!(drift < Duration::from_millis(5)); } } #[tokio::test] async fn timeout_duration_zero() { let start = BootTime::now(); assert!(timeout(Duration::from_millis(0), pending::<()>()).await.is_err()); let taken = start.elapsed(); assert!(taken < Duration::from_millis(5)); } res_send.cpp +7 −9 Original line number Diff line number Diff line Loading @@ -483,11 +483,8 @@ int res_nsend(ResState* statp, span<const uint8_t> msg, span<uint8_t> ans, int* mDnsQueryEvent->set_linux_errno(static_cast<LinuxErrno>(terrno)); resolv_stats_add(statp->netid, receivedMdnsAddr, mDnsQueryEvent); if (resplen <= 0) { _resolv_cache_query_failed(statp->netid, msg, flags); return -terrno; } LOG(DEBUG) << __func__ << ": got answer:"; if (resplen > 0) { LOG(DEBUG) << __func__ << ": got answer from mDNS:"; res_pquery(ans.first(resplen)); if (cache_status == RESOLV_CACHE_NOTFOUND) { Loading @@ -495,6 +492,7 @@ int res_nsend(ResState* statp, span<const uint8_t> msg, span<uint8_t> ans, int* } return resplen; } } if (statp->nameserverCount() == 0) { // We have no nameservers configured and it's not a MDNS resolution, so there's no Loading tests/resolv_integration_test.cpp +59 −60 Original line number Diff line number Diff line Loading @@ -383,66 +383,6 @@ class ResolverTest : public ::testing::Test { return fmt::format("127.0.100.{}", (++counter & 0xff)); } int WaitChild(pid_t pid) { int status; const pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0)); if (got_pid != pid) { PLOG(WARNING) << __func__ << ": waitpid failed: wanted " << pid << ", got " << got_pid; return 1; } if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { return 0; } else { return status; } } int ForkAndRun(const std::vector<std::string>& args) { std::vector<const char*> argv; argv.resize(args.size() + 1, nullptr); std::transform(args.begin(), args.end(), argv.begin(), [](const std::string& in) { return in.c_str(); }); pid_t pid = fork(); if (pid == -1) { // Fork failed. PLOG(ERROR) << __func__ << ": Unable to fork"; return -1; } if (pid == 0) { execv(argv[0], const_cast<char**>(argv.data())); PLOG(ERROR) << __func__ << ": execv failed"; _exit(1); } int rc = WaitChild(pid); if (rc != 0) { PLOG(ERROR) << __func__ << ": Failed run: status=" << rc; } return rc; } // Add routing rules for MDNS packets, or MDNS packets won't know the destination is MDNS // muticast address "224.0.0.251". void SetMdnsRoute() { const std::vector<std::string> args = { "system/bin/ip", "route", "add", "local", "224.0.0.251", "dev", "lo", "proto", "static", "scope", "host", "src", "127.0.0.1", }; EXPECT_EQ(0, ForkAndRun(args)); } void RemoveMdnsRoute() { const std::vector<std::string> args = { "system/bin/ip", "route", "del", "local", "224.0.0.251", "dev", "lo", "proto", "static", "scope", "host", "src", "127.0.0.1", }; EXPECT_EQ(0, ForkAndRun(args)); } DnsResponderClient mDnsClient; bool mIsResolverOptionIPCSupported = false; Loading Loading @@ -6579,6 +6519,65 @@ TEST_F(ResolverTest, MdnsGetAddrInfo_cnamesIllegalRdata) { EXPECT_TRUE(result == nullptr); } // Test if .local resolution will try unicast when multicast is failed. TEST_F(ResolverTest, MdnsGetAddrInfo_fallback) { constexpr char v6addr[] = "::1.2.3.4"; constexpr char v4addr[] = "1.2.3.4"; constexpr char host_name[] = "hello.local."; test::DNSResponder mdnsv4("127.0.0.3", test::kDefaultMdnsListenService, static_cast<ns_rcode>(-1)); test::DNSResponder mdnsv6("::1", test::kDefaultMdnsListenService, static_cast<ns_rcode>(-1)); // Set unresponsive on multicast. mdnsv4.setResponseProbability(0.0); mdnsv6.setResponseProbability(0.0); ASSERT_TRUE(mdnsv4.startServer()); ASSERT_TRUE(mdnsv6.startServer()); const std::vector<DnsRecord> records = { {host_name, ns_type::ns_t_a, v4addr}, {host_name, ns_type::ns_t_aaaa, v6addr}, }; test::DNSResponder dns("127.0.0.3"); StartDns(dns, records); ASSERT_TRUE(mDnsClient.SetResolversForNetwork()); static const struct TestConfig { int ai_family; const std::vector<std::string> expected_addr; } testConfigs[]{ {AF_INET, {v4addr}}, {AF_INET6, {v6addr}}, {AF_UNSPEC, {v4addr, v6addr}}, }; for (const auto& config : testConfigs) { SCOPED_TRACE(fmt::format("family: {}", config.ai_family)); addrinfo hints = {.ai_family = config.ai_family, .ai_socktype = SOCK_DGRAM}; ScopedAddrinfo result = safe_getaddrinfo("hello.local", nullptr, &hints); EXPECT_TRUE(result != nullptr); if (config.ai_family == AF_INET) { EXPECT_EQ(1U, GetNumQueries(mdnsv4, host_name)); EXPECT_EQ(0U, GetNumQueries(mdnsv6, host_name)); EXPECT_EQ(1U, GetNumQueries(dns, host_name)); } else if (config.ai_family == AF_INET6) { EXPECT_EQ(0U, GetNumQueries(mdnsv4, host_name)); EXPECT_EQ(1U, GetNumQueries(mdnsv6, host_name)); EXPECT_EQ(1U, GetNumQueries(dns, host_name)); } else { EXPECT_EQ(1U, GetNumQueries(mdnsv4, host_name)); EXPECT_EQ(1U, GetNumQueries(mdnsv6, host_name)); EXPECT_EQ(2U, GetNumQueries(dns, host_name)); } std::string result_str = ToString(result); EXPECT_THAT(ToStrings(result), testing::UnorderedElementsAreArray(config.expected_addr)); mdnsv4.clearQueries(); mdnsv6.clearQueries(); dns.clearQueries(); ASSERT_TRUE(mDnsClient.resolvService()->flushNetworkCache(TEST_NETID).isOk()); } } // ResolverMultinetworkTest is used to verify multinetwork functionality. Here's how it works: // The resolver sends queries to address A, and then there will be a TunForwarder helping forward // the packets to address B, which is the address on which the testing server is listening. The Loading Loading
DnsProxyListener.cpp +6 −2 Original line number Diff line number Diff line Loading @@ -1159,7 +1159,9 @@ void DnsProxyListener::GetHostByNameHandler::run() { event.set_latency_micros(latencyUs); event.set_event_type(EVENT_GETHOSTBYNAME); LOG(DEBUG) << "GetHostByNameHandler::run: result: " << gai_strerror(rv); if (rv) { LOG(DEBUG) << "GetHostByNameHandler::run: result failed: " << gai_strerror(rv); } bool success = true; if (hp) { Loading Loading @@ -1314,7 +1316,9 @@ void DnsProxyListener::GetHostByAddrHandler::run() { event.set_latency_micros(latencyUs); event.set_event_type(EVENT_GETHOSTBYADDR); LOG(DEBUG) << "GetHostByAddrHandler::run: result: " << gai_strerror(rv); if (rv) { LOG(DEBUG) << "GetHostByAddrHandler::run: result failed: " << gai_strerror(rv); } bool success = true; if (hp) { Loading
apex/Android.bp +2 −4 Original line number Diff line number Diff line Loading @@ -24,7 +24,6 @@ package { apex { name: "com.android.resolv", updatable: true, manifest: "manifest.json", multilib: { first: { Loading @@ -41,14 +40,13 @@ apex { // Whether it actually will be compressed is controlled on per-device basis. compressible: true, // IMPORTANT: For the APEX to be installed on Android 10, // min_sdk_version should be 29. This enables the build system to make // IMPORTANT: q-launched-apex-module enables the build system to make // sure the package compatible to Android 10 in two ways: // - build the APEX package compatible to Android 10 // so that the package can be installed. // - build artifacts (lib/javalib/bin) against Android 10 SDK // so that the artifacts can run. min_sdk_version: "29", defaults: ["q-launched-apex-module"], } apex_key { Loading
doh/boot_time.rs +16 −0 Original line number Diff line number Diff line Loading @@ -123,6 +123,7 @@ impl TimerFd { } fn set(&self, duration: Duration) { assert_ne!(duration, Duration::from_millis(0)); let timer = libc::itimerspec { it_interval: libc::timespec { tv_sec: 0, tv_nsec: 0 }, it_value: libc::timespec { Loading @@ -147,6 +148,13 @@ pub async fn timeout<T>(duration: Duration, future: impl Future<Output = T>) -> // Ideally, all timeouts in a runtime would share a timerfd. That will be much more // straightforwards to implement when moving this functionality into `tokio`. // According to timerfd_settime(), setting zero duration will disarm the timer, so // we return immediate timeout here. // Can't use is_zero() for now because sc-mainline-prod's Rust version is below 1.53. if duration == Duration::from_millis(0) { return Err(Elapsed(())); } // The failure conditions for this are rare (see `man 2 timerfd_create`) and the caller would // not be able to do much in response to them. When integrated into tokio, this would be called // during runtime setup. Loading Loading @@ -204,3 +212,11 @@ async fn timeout_drift() { assert!(drift < Duration::from_millis(5)); } } #[tokio::test] async fn timeout_duration_zero() { let start = BootTime::now(); assert!(timeout(Duration::from_millis(0), pending::<()>()).await.is_err()); let taken = start.elapsed(); assert!(taken < Duration::from_millis(5)); }
res_send.cpp +7 −9 Original line number Diff line number Diff line Loading @@ -483,11 +483,8 @@ int res_nsend(ResState* statp, span<const uint8_t> msg, span<uint8_t> ans, int* mDnsQueryEvent->set_linux_errno(static_cast<LinuxErrno>(terrno)); resolv_stats_add(statp->netid, receivedMdnsAddr, mDnsQueryEvent); if (resplen <= 0) { _resolv_cache_query_failed(statp->netid, msg, flags); return -terrno; } LOG(DEBUG) << __func__ << ": got answer:"; if (resplen > 0) { LOG(DEBUG) << __func__ << ": got answer from mDNS:"; res_pquery(ans.first(resplen)); if (cache_status == RESOLV_CACHE_NOTFOUND) { Loading @@ -495,6 +492,7 @@ int res_nsend(ResState* statp, span<const uint8_t> msg, span<uint8_t> ans, int* } return resplen; } } if (statp->nameserverCount() == 0) { // We have no nameservers configured and it's not a MDNS resolution, so there's no Loading
tests/resolv_integration_test.cpp +59 −60 Original line number Diff line number Diff line Loading @@ -383,66 +383,6 @@ class ResolverTest : public ::testing::Test { return fmt::format("127.0.100.{}", (++counter & 0xff)); } int WaitChild(pid_t pid) { int status; const pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0)); if (got_pid != pid) { PLOG(WARNING) << __func__ << ": waitpid failed: wanted " << pid << ", got " << got_pid; return 1; } if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { return 0; } else { return status; } } int ForkAndRun(const std::vector<std::string>& args) { std::vector<const char*> argv; argv.resize(args.size() + 1, nullptr); std::transform(args.begin(), args.end(), argv.begin(), [](const std::string& in) { return in.c_str(); }); pid_t pid = fork(); if (pid == -1) { // Fork failed. PLOG(ERROR) << __func__ << ": Unable to fork"; return -1; } if (pid == 0) { execv(argv[0], const_cast<char**>(argv.data())); PLOG(ERROR) << __func__ << ": execv failed"; _exit(1); } int rc = WaitChild(pid); if (rc != 0) { PLOG(ERROR) << __func__ << ": Failed run: status=" << rc; } return rc; } // Add routing rules for MDNS packets, or MDNS packets won't know the destination is MDNS // muticast address "224.0.0.251". void SetMdnsRoute() { const std::vector<std::string> args = { "system/bin/ip", "route", "add", "local", "224.0.0.251", "dev", "lo", "proto", "static", "scope", "host", "src", "127.0.0.1", }; EXPECT_EQ(0, ForkAndRun(args)); } void RemoveMdnsRoute() { const std::vector<std::string> args = { "system/bin/ip", "route", "del", "local", "224.0.0.251", "dev", "lo", "proto", "static", "scope", "host", "src", "127.0.0.1", }; EXPECT_EQ(0, ForkAndRun(args)); } DnsResponderClient mDnsClient; bool mIsResolverOptionIPCSupported = false; Loading Loading @@ -6579,6 +6519,65 @@ TEST_F(ResolverTest, MdnsGetAddrInfo_cnamesIllegalRdata) { EXPECT_TRUE(result == nullptr); } // Test if .local resolution will try unicast when multicast is failed. TEST_F(ResolverTest, MdnsGetAddrInfo_fallback) { constexpr char v6addr[] = "::1.2.3.4"; constexpr char v4addr[] = "1.2.3.4"; constexpr char host_name[] = "hello.local."; test::DNSResponder mdnsv4("127.0.0.3", test::kDefaultMdnsListenService, static_cast<ns_rcode>(-1)); test::DNSResponder mdnsv6("::1", test::kDefaultMdnsListenService, static_cast<ns_rcode>(-1)); // Set unresponsive on multicast. mdnsv4.setResponseProbability(0.0); mdnsv6.setResponseProbability(0.0); ASSERT_TRUE(mdnsv4.startServer()); ASSERT_TRUE(mdnsv6.startServer()); const std::vector<DnsRecord> records = { {host_name, ns_type::ns_t_a, v4addr}, {host_name, ns_type::ns_t_aaaa, v6addr}, }; test::DNSResponder dns("127.0.0.3"); StartDns(dns, records); ASSERT_TRUE(mDnsClient.SetResolversForNetwork()); static const struct TestConfig { int ai_family; const std::vector<std::string> expected_addr; } testConfigs[]{ {AF_INET, {v4addr}}, {AF_INET6, {v6addr}}, {AF_UNSPEC, {v4addr, v6addr}}, }; for (const auto& config : testConfigs) { SCOPED_TRACE(fmt::format("family: {}", config.ai_family)); addrinfo hints = {.ai_family = config.ai_family, .ai_socktype = SOCK_DGRAM}; ScopedAddrinfo result = safe_getaddrinfo("hello.local", nullptr, &hints); EXPECT_TRUE(result != nullptr); if (config.ai_family == AF_INET) { EXPECT_EQ(1U, GetNumQueries(mdnsv4, host_name)); EXPECT_EQ(0U, GetNumQueries(mdnsv6, host_name)); EXPECT_EQ(1U, GetNumQueries(dns, host_name)); } else if (config.ai_family == AF_INET6) { EXPECT_EQ(0U, GetNumQueries(mdnsv4, host_name)); EXPECT_EQ(1U, GetNumQueries(mdnsv6, host_name)); EXPECT_EQ(1U, GetNumQueries(dns, host_name)); } else { EXPECT_EQ(1U, GetNumQueries(mdnsv4, host_name)); EXPECT_EQ(1U, GetNumQueries(mdnsv6, host_name)); EXPECT_EQ(2U, GetNumQueries(dns, host_name)); } std::string result_str = ToString(result); EXPECT_THAT(ToStrings(result), testing::UnorderedElementsAreArray(config.expected_addr)); mdnsv4.clearQueries(); mdnsv6.clearQueries(); dns.clearQueries(); ASSERT_TRUE(mDnsClient.resolvService()->flushNetworkCache(TEST_NETID).isOk()); } } // ResolverMultinetworkTest is used to verify multinetwork functionality. Here's how it works: // The resolver sends queries to address A, and then there will be a TunForwarder helping forward // the packets to address B, which is the address on which the testing server is listening. The Loading