Fix async DNS flag NO_CACHE_STORE doesn't work as expected
The stale cache case isn't handled correctly while performing
cahce_lookup with flag NO_CACHE_STORE, which caused this problem.
Fix it and add a test to ensure it won't happen again.
Test: atest
Bug: 148842821
Change-Id: I72a2211a636cadc72009a5542f7c755c30329c43
diff --git a/res_cache.cpp b/res_cache.cpp
index 5f87cca..4c7e187 100644
--- a/res_cache.cpp
+++ b/res_cache.cpp
@@ -1261,7 +1261,7 @@
LOG(INFO) << __func__ << ": NOT IN CACHE (STALE ENTRY " << *lookup << "DISCARDED)";
res_pquery(e->query, e->querylen);
_cache_remove_p(cache, lookup);
- return RESOLV_CACHE_NOTFOUND;
+ return (flags & ANDROID_RESOLV_NO_CACHE_STORE) ? RESOLV_CACHE_SKIP : RESOLV_CACHE_NOTFOUND;
}
*answerlen = e->answerlen;
diff --git a/tests/dns_responder/dns_responder.cpp b/tests/dns_responder/dns_responder.cpp
index 62b783c..89e7b19 100644
--- a/tests/dns_responder/dns_responder.cpp
+++ b/tests/dns_responder/dns_responder.cpp
@@ -547,6 +547,10 @@
edns_ = edns;
}
+void DNSResponder::setTtl(unsigned ttl) {
+ answer_record_ttl_sec_ = ttl;
+}
+
bool DNSResponder::running() const {
return (udp_socket_.ok()) && (tcp_socket_.ok());
}
@@ -783,7 +787,7 @@
.name = {.name = it->first.name},
.rtype = it->first.type,
.rclass = ns_class::ns_c_in,
- .ttl = kAnswerRecordTtlSec, // seconds
+ .ttl = answer_record_ttl_sec_, // seconds
};
if (!fillRdata(it->second, record)) return false;
answers->push_back(std::move(record));
diff --git a/tests/dns_responder/dns_responder.h b/tests/dns_responder/dns_responder.h
index 7382364..4153a7f 100644
--- a/tests/dns_responder/dns_responder.h
+++ b/tests/dns_responder/dns_responder.h
@@ -175,6 +175,7 @@
void setResponseProbability(double response_probability);
void setResponseProbability(double response_probability, int protocol);
void setEdns(Edns edns);
+ void setTtl(unsigned ttl);
bool running() const;
bool startServer();
bool stopServer();
@@ -293,6 +294,8 @@
// returning error_rcode_ or no response.
std::atomic<double> response_probability_udp_ = 1.0;
+ std::atomic<unsigned> answer_record_ttl_sec_ = kAnswerRecordTtlSec;
+
// Maximum number of fds for epoll.
const int EPOLL_MAX_EVENTS = 2;
diff --git a/tests/resolv_integration_test.cpp b/tests/resolv_integration_test.cpp
index 6ea88da..b78395c 100644
--- a/tests/resolv_integration_test.cpp
+++ b/tests/resolv_integration_test.cpp
@@ -2235,6 +2235,52 @@
EXPECT_EQ(4U, GetNumQueries(dns, another_host_name));
}
+TEST_F(ResolverTest, Async_NoCacheStoreFlagDoesNotRefreshStaleCacheEntry) {
+ constexpr char listen_addr[] = "127.0.0.4";
+ constexpr char host_name[] = "howdy.example.com.";
+ const std::vector<DnsRecord> records = {
+ {host_name, ns_type::ns_t_a, "1.2.3.4"},
+ };
+
+ test::DNSResponder dns(listen_addr);
+ StartDns(dns, records);
+ std::vector<std::string> servers = {listen_addr};
+ ASSERT_TRUE(mDnsClient.SetResolversForNetwork(servers));
+
+ const unsigned SHORT_TTL_SEC = 1;
+ dns.setTtl(SHORT_TTL_SEC);
+
+ // Refer to b/148842821 for the purpose of below test steps.
+ // Basically, this test is used to ensure stale cache case is handled
+ // correctly with ANDROID_RESOLV_NO_CACHE_STORE.
+ int fd = resNetworkQuery(TEST_NETID, "howdy.example.com", ns_c_in, ns_t_a, 0);
+ EXPECT_TRUE(fd != -1);
+ expectAnswersValid(fd, AF_INET, "1.2.3.4");
+
+ EXPECT_EQ(1U, GetNumQueries(dns, host_name));
+ dns.clearQueries();
+
+ // Wait until cache expired
+ sleep(SHORT_TTL_SEC + 0.5);
+
+ // Now request the same hostname again.
+ // We should see a new DNS query because the entry in cache has become stale.
+ // Due to ANDROID_RESOLV_NO_CACHE_STORE, this query must *not* refresh that stale entry.
+ fd = resNetworkQuery(TEST_NETID, "howdy.example.com", ns_c_in, ns_t_a,
+ ANDROID_RESOLV_NO_CACHE_STORE);
+ EXPECT_TRUE(fd != -1);
+ expectAnswersValid(fd, AF_INET, "1.2.3.4");
+ EXPECT_EQ(1U, GetNumQueries(dns, host_name));
+ dns.clearQueries();
+
+ // If the cache is still stale, we expect to see one more DNS query
+ // (this time the cache will be refreshed, but we're not checking for it).
+ fd = resNetworkQuery(TEST_NETID, "howdy.example.com", ns_c_in, ns_t_a, 0);
+ EXPECT_TRUE(fd != -1);
+ expectAnswersValid(fd, AF_INET, "1.2.3.4");
+ EXPECT_EQ(1U, GetNumQueries(dns, host_name));
+}
+
TEST_F(ResolverTest, Async_NoRetryFlag) {
constexpr char listen_addr0[] = "127.0.0.4";
constexpr char listen_addr1[] = "127.0.0.6";