Loading DnsStats.cpp +3 −4 Original line number Diff line number Diff line Loading @@ -81,8 +81,7 @@ int StatsData::averageLatencyMs() const { } std::string StatsData::toString() const { if (total == 0) return fmt::format("{}:{} <no data>", sockAddr.ip().toString(), sockAddr.port()); if (total == 0) return fmt::format("{} <no data>", sockAddr.toString()); const auto now = std::chrono::steady_clock::now(); const int lastUpdateSec = duration_cast<seconds>(now - lastUpdate).count(); Loading @@ -92,8 +91,8 @@ std::string StatsData::toString() const { buf += fmt::format("{}:{} ", rcodeToName(rcode), counts); } } return fmt::format("{}:{} ({}, {}ms, [{}], {}s)", sockAddr.ip().toString(), sockAddr.port(), total, averageLatencyMs(), buf, lastUpdateSec); return fmt::format("{} ({}, {}ms, [{}], {}s)", sockAddr.toString(), total, averageLatencyMs(), buf, lastUpdateSec); } StatsRecords::StatsRecords(const IPSockAddr& ipSockAddr, size_t size) Loading DnsStatsTest.cpp +2 −3 Original line number Diff line number Diff line Loading @@ -121,7 +121,7 @@ class DnsStatsTest : public ::testing::Test { const std::vector<StatsData>& dohData) { // A pattern to capture three matches: // server address (empty allowed), the statistics, and the score. const std::regex pattern(R"(\s{4,}([0-9a-fA-F:\.]*)[ ]?([<(].*[>)])[ ]?(\S*))"); const std::regex pattern(R"(\s{4,}([0-9a-fA-F:\.\]\[]*)[ ]?([<(].*[>)])[ ]?(\S*))"); std::string dumpString = captureDumpOutput(); const auto check = [&](const std::vector<StatsData>& statsData, const std::string& protocol, Loading @@ -142,8 +142,7 @@ class DnsStatsTest : public ::testing::Test { for (const auto& stats : statsData) { ASSERT_TRUE(std::regex_search(*dumpString, sm, pattern)); EXPECT_EQ(sm[1], stats.sockAddr.ip().toString() + ":" + std::to_string(stats.sockAddr.port())); EXPECT_EQ(sm[1], stats.sockAddr.toString()); EXPECT_FALSE(sm[2].str().empty()); EXPECT_FALSE(sm[3].str().empty()); *dumpString = sm.suffix(); Loading PrivateDnsConfiguration.cpp +3 −2 Original line number Diff line number Diff line Loading @@ -461,8 +461,9 @@ int PrivateDnsConfiguration::setDoh(int32_t netId, uint32_t mark, const auto& doh = entry.getDohIdentity(sortedServers, name); if (!doh.ok()) continue; // The internal tests are supposed to have root permission. if (entry.forTesting && AIBinder_getCallingUid() != AID_ROOT) continue; // Since the DnsResolver is expected to be configured by the system server, add the // restriction to prevent ResolverTestProvider from being used other than testing. if (entry.requireRootPermission && AIBinder_getCallingUid() != AID_ROOT) continue; auto it = mDohTracker.find(netId); // Skip if the same server already exists and its status == success. Loading PrivateDnsConfiguration.h +10 −3 Original line number Diff line number Diff line Loading @@ -207,7 +207,7 @@ class PrivateDnsConfiguration { std::set<std::string> ips; std::string host; std::string httpsTemplate; bool forTesting; bool requireRootPermission; base::Result<DohIdentity> getDohIdentity(const std::vector<std::string>& ips, const std::string& host) const { if (!host.empty() && this->host != host) return Errorf("host {} not matched", host); Loading @@ -223,7 +223,7 @@ class PrivateDnsConfiguration { // TODO: Move below DoH relevant stuff into Rust implementation. std::map<unsigned, DohIdentity> mDohTracker GUARDED_BY(mPrivateDnsLock); std::array<DohProviderEntry, 3> mAvailableDoHProviders = {{ std::array<DohProviderEntry, 4> mAvailableDoHProviders = {{ {"Google", {"2001:4860:4860::8888", "2001:4860:4860::8844", "8.8.8.8", "8.8.4.4"}, "dns.google", Loading @@ -235,12 +235,19 @@ class PrivateDnsConfiguration { "https://cloudflare-dns.com/dns-query", false}, // The DoH provider for testing. // The DoH providers for testing only. // Using ResolverTestProvider requires that the DnsResolver is configured by someone // who has root permission, which should be run by tests only. {"ResolverTestProvider", {"127.0.0.3", "::1"}, "example.com", "https://example.com/dns-query", true}, {"AndroidTesting", {"192.0.2.100"}, "dns.androidtesting.org", "https://dns.androidtesting.org/dns-query", false}, }}; struct RecordEntry { Loading tests/resolv_private_dns_test.cpp +7 −5 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ using aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener; using android::base::ReadFdToString; using android::base::unique_fd; using android::net::resolv::aidl::UnsolicitedEventListener; using android::netdutils::IPSockAddr; using android::netdutils::ScopedAddrinfo; using android::netdutils::Stopwatch; using std::chrono::milliseconds; Loading Loading @@ -171,21 +172,22 @@ class BaseTest : public ::testing::Test { serverAddr, IDnsResolverUnsolicitedEventListener::PROTOCOL_DOH); } bool expectLog(const std::string& serverAddr, const std::string& listen_address) { bool expectLog(const std::string& ipAddrOrNoData, const std::string& port) { ndk::SpAIBinder resolvBinder = ndk::SpAIBinder(AServiceManager_getService("dnsresolver")); assert(nullptr != resolvBinder.get()); std::vector<std::string> lines = dumpService(resolvBinder); const std::string ipAddr = listen_address.empty() ? serverAddr : serverAddr + ":" + listen_address; const std::regex pattern(R"(^\s{4,}([0-9a-fA-F:\.]*)[ ]?([<(].*[>)])[ ]?(\S*)$)"); const std::string expectedLog = port.empty() ? ipAddrOrNoData : IPSockAddr::toIPSockAddr(ipAddrOrNoData, std::stoi(port)).toString(); const std::regex pattern(R"(^\s{4,}([0-9a-fA-F:\.\]\[]*)[ ]?([<(].*[>)])[ ]?(\S*)$)"); for (const auto& line : lines) { if (line.empty()) continue; std::smatch match; if (std::regex_match(line, match, pattern)) { if (match[1] == ipAddr || match[2] == ipAddr) return true; if (match[1] == expectedLog || match[2] == expectedLog) return true; } } return false; Loading Loading
DnsStats.cpp +3 −4 Original line number Diff line number Diff line Loading @@ -81,8 +81,7 @@ int StatsData::averageLatencyMs() const { } std::string StatsData::toString() const { if (total == 0) return fmt::format("{}:{} <no data>", sockAddr.ip().toString(), sockAddr.port()); if (total == 0) return fmt::format("{} <no data>", sockAddr.toString()); const auto now = std::chrono::steady_clock::now(); const int lastUpdateSec = duration_cast<seconds>(now - lastUpdate).count(); Loading @@ -92,8 +91,8 @@ std::string StatsData::toString() const { buf += fmt::format("{}:{} ", rcodeToName(rcode), counts); } } return fmt::format("{}:{} ({}, {}ms, [{}], {}s)", sockAddr.ip().toString(), sockAddr.port(), total, averageLatencyMs(), buf, lastUpdateSec); return fmt::format("{} ({}, {}ms, [{}], {}s)", sockAddr.toString(), total, averageLatencyMs(), buf, lastUpdateSec); } StatsRecords::StatsRecords(const IPSockAddr& ipSockAddr, size_t size) Loading
DnsStatsTest.cpp +2 −3 Original line number Diff line number Diff line Loading @@ -121,7 +121,7 @@ class DnsStatsTest : public ::testing::Test { const std::vector<StatsData>& dohData) { // A pattern to capture three matches: // server address (empty allowed), the statistics, and the score. const std::regex pattern(R"(\s{4,}([0-9a-fA-F:\.]*)[ ]?([<(].*[>)])[ ]?(\S*))"); const std::regex pattern(R"(\s{4,}([0-9a-fA-F:\.\]\[]*)[ ]?([<(].*[>)])[ ]?(\S*))"); std::string dumpString = captureDumpOutput(); const auto check = [&](const std::vector<StatsData>& statsData, const std::string& protocol, Loading @@ -142,8 +142,7 @@ class DnsStatsTest : public ::testing::Test { for (const auto& stats : statsData) { ASSERT_TRUE(std::regex_search(*dumpString, sm, pattern)); EXPECT_EQ(sm[1], stats.sockAddr.ip().toString() + ":" + std::to_string(stats.sockAddr.port())); EXPECT_EQ(sm[1], stats.sockAddr.toString()); EXPECT_FALSE(sm[2].str().empty()); EXPECT_FALSE(sm[3].str().empty()); *dumpString = sm.suffix(); Loading
PrivateDnsConfiguration.cpp +3 −2 Original line number Diff line number Diff line Loading @@ -461,8 +461,9 @@ int PrivateDnsConfiguration::setDoh(int32_t netId, uint32_t mark, const auto& doh = entry.getDohIdentity(sortedServers, name); if (!doh.ok()) continue; // The internal tests are supposed to have root permission. if (entry.forTesting && AIBinder_getCallingUid() != AID_ROOT) continue; // Since the DnsResolver is expected to be configured by the system server, add the // restriction to prevent ResolverTestProvider from being used other than testing. if (entry.requireRootPermission && AIBinder_getCallingUid() != AID_ROOT) continue; auto it = mDohTracker.find(netId); // Skip if the same server already exists and its status == success. Loading
PrivateDnsConfiguration.h +10 −3 Original line number Diff line number Diff line Loading @@ -207,7 +207,7 @@ class PrivateDnsConfiguration { std::set<std::string> ips; std::string host; std::string httpsTemplate; bool forTesting; bool requireRootPermission; base::Result<DohIdentity> getDohIdentity(const std::vector<std::string>& ips, const std::string& host) const { if (!host.empty() && this->host != host) return Errorf("host {} not matched", host); Loading @@ -223,7 +223,7 @@ class PrivateDnsConfiguration { // TODO: Move below DoH relevant stuff into Rust implementation. std::map<unsigned, DohIdentity> mDohTracker GUARDED_BY(mPrivateDnsLock); std::array<DohProviderEntry, 3> mAvailableDoHProviders = {{ std::array<DohProviderEntry, 4> mAvailableDoHProviders = {{ {"Google", {"2001:4860:4860::8888", "2001:4860:4860::8844", "8.8.8.8", "8.8.4.4"}, "dns.google", Loading @@ -235,12 +235,19 @@ class PrivateDnsConfiguration { "https://cloudflare-dns.com/dns-query", false}, // The DoH provider for testing. // The DoH providers for testing only. // Using ResolverTestProvider requires that the DnsResolver is configured by someone // who has root permission, which should be run by tests only. {"ResolverTestProvider", {"127.0.0.3", "::1"}, "example.com", "https://example.com/dns-query", true}, {"AndroidTesting", {"192.0.2.100"}, "dns.androidtesting.org", "https://dns.androidtesting.org/dns-query", false}, }}; struct RecordEntry { Loading
tests/resolv_private_dns_test.cpp +7 −5 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ using aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener; using android::base::ReadFdToString; using android::base::unique_fd; using android::net::resolv::aidl::UnsolicitedEventListener; using android::netdutils::IPSockAddr; using android::netdutils::ScopedAddrinfo; using android::netdutils::Stopwatch; using std::chrono::milliseconds; Loading Loading @@ -171,21 +172,22 @@ class BaseTest : public ::testing::Test { serverAddr, IDnsResolverUnsolicitedEventListener::PROTOCOL_DOH); } bool expectLog(const std::string& serverAddr, const std::string& listen_address) { bool expectLog(const std::string& ipAddrOrNoData, const std::string& port) { ndk::SpAIBinder resolvBinder = ndk::SpAIBinder(AServiceManager_getService("dnsresolver")); assert(nullptr != resolvBinder.get()); std::vector<std::string> lines = dumpService(resolvBinder); const std::string ipAddr = listen_address.empty() ? serverAddr : serverAddr + ":" + listen_address; const std::regex pattern(R"(^\s{4,}([0-9a-fA-F:\.]*)[ ]?([<(].*[>)])[ ]?(\S*)$)"); const std::string expectedLog = port.empty() ? ipAddrOrNoData : IPSockAddr::toIPSockAddr(ipAddrOrNoData, std::stoi(port)).toString(); const std::regex pattern(R"(^\s{4,}([0-9a-fA-F:\.\]\[]*)[ ]?([<(].*[>)])[ ]?(\S*)$)"); for (const auto& line : lines) { if (line.empty()) continue; std::smatch match; if (std::regex_match(line, match, pattern)) { if (match[1] == ipAddr || match[2] == ipAddr) return true; if (match[1] == expectedLog || match[2] == expectedLog) return true; } } return false; Loading