Loading Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -198,6 +198,7 @@ cc_library { "libcutils", "libnetdutils", "libdoh_ffi", "libmodules-utils-build", "libprotobuf-cpp-lite", "libstatslog_resolv", "libstatspush_compat", Loading PrivateDnsConfiguration.cpp +12 −4 Original line number Diff line number Diff line Loading @@ -424,10 +424,13 @@ void PrivateDnsConfiguration::initDohLocked() { int PrivateDnsConfiguration::setDoh(int32_t netId, uint32_t mark, const std::vector<std::string>& servers, const std::string& name, const std::string& caCert) { if (servers.empty()) return 0; LOG(DEBUG) << "PrivateDnsConfiguration::setDoh(" << netId << ", 0x" << std::hex << mark << std::dec << ", " << servers.size() << ", " << name << ")"; std::lock_guard guard(mPrivateDnsLock); if (servers.empty()) { clearDohLocked(netId); return 0; } // Sort the input servers to ensure that we could get the server vector at the same order. std::vector<std::string> sortedServers = servers; Loading Loading @@ -473,16 +476,21 @@ int PrivateDnsConfiguration::setDoh(int32_t netId, uint32_t mark, } LOG(INFO) << __func__ << ": No suitable DoH server found"; clearDohLocked(netId); return 0; } void PrivateDnsConfiguration::clearDoh(unsigned netId) { LOG(DEBUG) << "PrivateDnsConfiguration::clearDoh (" << netId << ")"; std::lock_guard guard(mPrivateDnsLock); void PrivateDnsConfiguration::clearDohLocked(unsigned netId) { LOG(DEBUG) << "PrivateDnsConfiguration::clearDohLocked (" << netId << ")"; if (mDohDispatcher != nullptr) doh_net_delete(mDohDispatcher, netId); mDohTracker.erase(netId); } void PrivateDnsConfiguration::clearDoh(unsigned netId) { std::lock_guard guard(mPrivateDnsLock); clearDohLocked(netId); } ssize_t PrivateDnsConfiguration::dohQuery(unsigned netId, const Slice query, const Slice answer, uint64_t timeoutMs) { { Loading PrivateDnsConfiguration.h +1 −0 Original line number Diff line number Diff line Loading @@ -147,6 +147,7 @@ class PrivateDnsConfiguration { unsigned netId) REQUIRES(mPrivateDnsLock); void initDohLocked() REQUIRES(mPrivateDnsLock); void clearDohLocked(unsigned netId) REQUIRES(mPrivateDnsLock); mutable std::mutex mPrivateDnsLock; std::map<unsigned, PrivateDnsMode> mPrivateDnsModes GUARDED_BY(mPrivateDnsLock); Loading tests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -180,6 +180,7 @@ cc_test { "libbpf_android", "libcrypto_static", "libgmock", "libmodules-utils-build", "libnetd_test_dnsresponder_ndk", "libnetd_test_metrics_listener", "libnetd_test_resolv_utils", Loading tests/resolv_private_dns_test.cpp +56 −0 Original line number Diff line number Diff line Loading @@ -451,3 +451,59 @@ TEST_F(PrivateDnsDohTest, PreferIpv6) { resetNetwork(); } } // Tests that DoH server setting can be replaced/removed correctly. TEST_F(PrivateDnsDohTest, ChangeAndClearPrivateDnsServer) { constexpr char listen_ipv6_addr[] = "::1"; // To simplify the test, set the DoT server broken. dot.stopServer(); test::DNSResponder dns_ipv6{listen_ipv6_addr, "53"}; test::DohFrontend doh_ipv6{listen_ipv6_addr, "443", listen_ipv6_addr, "53"}; dns_ipv6.addMapping(kQueryHostname, ns_type::ns_t_a, kQueryAnswerA); dns_ipv6.addMapping(kQueryHostname, ns_type::ns_t_aaaa, kQueryAnswerAAAA); ASSERT_TRUE(dns_ipv6.startServer()); ASSERT_TRUE(doh_ipv6.startServer()); auto parcel = DnsResponderClient::GetDefaultResolverParamsParcel(); ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel)); // Use v4 DoH server first. EXPECT_TRUE(WaitForDohValidation(test::kDefaultListenAddr, true)); doh.clearQueries(); EXPECT_NO_FAILURE(sendQueryAndCheckResult()); EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 0 /* dot */, 2 /* doh */)); // Change to the v6 DoH server. parcel.servers = {listen_ipv6_addr}; parcel.tlsServers = {listen_ipv6_addr}; ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel)); EXPECT_TRUE(WaitForDohValidation(listen_ipv6_addr, true)); doh.clearQueries(); doh_ipv6.clearQueries(); flushCache(); EXPECT_NO_FAILURE(sendQueryAndCheckResult()); EXPECT_EQ(doh_ipv6.queries(), 2); EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 0 /* dot */, 0 /* doh */)); // Change to an invalid DoH server. parcel.tlsServers = {kHelloExampleComAddrV4}; ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel)); doh_ipv6.clearQueries(); dns_ipv6.clearQueries(); flushCache(); EXPECT_NO_FAILURE(sendQueryAndCheckResult()); EXPECT_EQ(doh_ipv6.queries(), 0); EXPECT_EQ(dns_ipv6.queries().size(), 2U); // Remove private DNS servers. parcel.tlsServers = {}; ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel)); doh_ipv6.clearQueries(); dns_ipv6.clearQueries(); flushCache(); EXPECT_NO_FAILURE(sendQueryAndCheckResult()); EXPECT_EQ(doh_ipv6.queries(), 0); EXPECT_EQ(dns_ipv6.queries().size(), 2U); } Loading
Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -198,6 +198,7 @@ cc_library { "libcutils", "libnetdutils", "libdoh_ffi", "libmodules-utils-build", "libprotobuf-cpp-lite", "libstatslog_resolv", "libstatspush_compat", Loading
PrivateDnsConfiguration.cpp +12 −4 Original line number Diff line number Diff line Loading @@ -424,10 +424,13 @@ void PrivateDnsConfiguration::initDohLocked() { int PrivateDnsConfiguration::setDoh(int32_t netId, uint32_t mark, const std::vector<std::string>& servers, const std::string& name, const std::string& caCert) { if (servers.empty()) return 0; LOG(DEBUG) << "PrivateDnsConfiguration::setDoh(" << netId << ", 0x" << std::hex << mark << std::dec << ", " << servers.size() << ", " << name << ")"; std::lock_guard guard(mPrivateDnsLock); if (servers.empty()) { clearDohLocked(netId); return 0; } // Sort the input servers to ensure that we could get the server vector at the same order. std::vector<std::string> sortedServers = servers; Loading Loading @@ -473,16 +476,21 @@ int PrivateDnsConfiguration::setDoh(int32_t netId, uint32_t mark, } LOG(INFO) << __func__ << ": No suitable DoH server found"; clearDohLocked(netId); return 0; } void PrivateDnsConfiguration::clearDoh(unsigned netId) { LOG(DEBUG) << "PrivateDnsConfiguration::clearDoh (" << netId << ")"; std::lock_guard guard(mPrivateDnsLock); void PrivateDnsConfiguration::clearDohLocked(unsigned netId) { LOG(DEBUG) << "PrivateDnsConfiguration::clearDohLocked (" << netId << ")"; if (mDohDispatcher != nullptr) doh_net_delete(mDohDispatcher, netId); mDohTracker.erase(netId); } void PrivateDnsConfiguration::clearDoh(unsigned netId) { std::lock_guard guard(mPrivateDnsLock); clearDohLocked(netId); } ssize_t PrivateDnsConfiguration::dohQuery(unsigned netId, const Slice query, const Slice answer, uint64_t timeoutMs) { { Loading
PrivateDnsConfiguration.h +1 −0 Original line number Diff line number Diff line Loading @@ -147,6 +147,7 @@ class PrivateDnsConfiguration { unsigned netId) REQUIRES(mPrivateDnsLock); void initDohLocked() REQUIRES(mPrivateDnsLock); void clearDohLocked(unsigned netId) REQUIRES(mPrivateDnsLock); mutable std::mutex mPrivateDnsLock; std::map<unsigned, PrivateDnsMode> mPrivateDnsModes GUARDED_BY(mPrivateDnsLock); Loading
tests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -180,6 +180,7 @@ cc_test { "libbpf_android", "libcrypto_static", "libgmock", "libmodules-utils-build", "libnetd_test_dnsresponder_ndk", "libnetd_test_metrics_listener", "libnetd_test_resolv_utils", Loading
tests/resolv_private_dns_test.cpp +56 −0 Original line number Diff line number Diff line Loading @@ -451,3 +451,59 @@ TEST_F(PrivateDnsDohTest, PreferIpv6) { resetNetwork(); } } // Tests that DoH server setting can be replaced/removed correctly. TEST_F(PrivateDnsDohTest, ChangeAndClearPrivateDnsServer) { constexpr char listen_ipv6_addr[] = "::1"; // To simplify the test, set the DoT server broken. dot.stopServer(); test::DNSResponder dns_ipv6{listen_ipv6_addr, "53"}; test::DohFrontend doh_ipv6{listen_ipv6_addr, "443", listen_ipv6_addr, "53"}; dns_ipv6.addMapping(kQueryHostname, ns_type::ns_t_a, kQueryAnswerA); dns_ipv6.addMapping(kQueryHostname, ns_type::ns_t_aaaa, kQueryAnswerAAAA); ASSERT_TRUE(dns_ipv6.startServer()); ASSERT_TRUE(doh_ipv6.startServer()); auto parcel = DnsResponderClient::GetDefaultResolverParamsParcel(); ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel)); // Use v4 DoH server first. EXPECT_TRUE(WaitForDohValidation(test::kDefaultListenAddr, true)); doh.clearQueries(); EXPECT_NO_FAILURE(sendQueryAndCheckResult()); EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 0 /* dot */, 2 /* doh */)); // Change to the v6 DoH server. parcel.servers = {listen_ipv6_addr}; parcel.tlsServers = {listen_ipv6_addr}; ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel)); EXPECT_TRUE(WaitForDohValidation(listen_ipv6_addr, true)); doh.clearQueries(); doh_ipv6.clearQueries(); flushCache(); EXPECT_NO_FAILURE(sendQueryAndCheckResult()); EXPECT_EQ(doh_ipv6.queries(), 2); EXPECT_NO_FAILURE(expectQueries(0 /* dns */, 0 /* dot */, 0 /* doh */)); // Change to an invalid DoH server. parcel.tlsServers = {kHelloExampleComAddrV4}; ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel)); doh_ipv6.clearQueries(); dns_ipv6.clearQueries(); flushCache(); EXPECT_NO_FAILURE(sendQueryAndCheckResult()); EXPECT_EQ(doh_ipv6.queries(), 0); EXPECT_EQ(dns_ipv6.queries().size(), 2U); // Remove private DNS servers. parcel.tlsServers = {}; ASSERT_TRUE(mDnsClient.SetResolversFromParcel(parcel)); doh_ipv6.clearQueries(); dns_ipv6.clearQueries(); flushCache(); EXPECT_NO_FAILURE(sendQueryAndCheckResult()); EXPECT_EQ(doh_ipv6.queries(), 0); EXPECT_EQ(dns_ipv6.queries().size(), 2U); }