Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 072497e6 authored by Luke Huang's avatar Luke Huang
Browse files

Fix the bug while updating DoH servers

Currently, DoH servers won't be updated correctly when the requested
private DNS server is empty or not in available DoH server list.

Bug: 200786579
Test: atest
Change-Id: Ic6b34e0173ac91924cde14512b1156c0e3fc2e23
parent 9d8426d0
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -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;
@@ -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) {
    {
+1 −0
Original line number Diff line number Diff line
@@ -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);
+56 −0
Original line number Diff line number Diff line
@@ -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);
}