blob: 4a29258d7c9a9eae56d7bd56c3b0b1663d42d1ac [file] [log] [blame]
Mike Yud1ec2542019-06-06 17:17:53 +08001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Luke Huange126fbe2019-07-20 17:36:30 +080017#include <netdb.h>
Mike Yud1ec2542019-06-06 17:17:53 +080018
Mike Yuc7649d12019-05-22 15:28:07 +080019#include <array>
Mike Yud1ec2542019-06-06 17:17:53 +080020#include <atomic>
21#include <chrono>
22#include <ctime>
23#include <thread>
24
25#include <android-base/logging.h>
26#include <android-base/stringprintf.h>
27#include <android/multinetwork.h>
Ken Chen766feae2019-10-30 15:13:44 +080028#include <arpa/inet.h>
Luke Huange126fbe2019-07-20 17:36:30 +080029#include <cutils/properties.h>
30#include <gmock/gmock-matchers.h>
31#include <gtest/gtest.h>
Mike Yud1ec2542019-06-06 17:17:53 +080032
Bernie Innocenti08487112019-10-11 21:14:13 +090033#include "res_init.h"
Mike Yud1ec2542019-06-06 17:17:53 +080034#include "resolv_cache.h"
35#include "resolv_private.h"
Ken Chen99c0b322019-11-20 14:24:09 +080036#include "stats.h"
chenbruceb43ec752019-07-24 20:19:41 +080037#include "tests/dns_responder/dns_responder.h"
Mike Yud1ec2542019-06-06 17:17:53 +080038
39using namespace std::chrono_literals;
40
Mike Yue48f7b52020-02-10 14:55:06 +080041using android::netdutils::IPSockAddr;
42
Mike Yud1ec2542019-06-06 17:17:53 +080043constexpr int TEST_NETID = 30;
44constexpr int TEST_NETID_2 = 31;
Ken Chen766feae2019-10-30 15:13:44 +080045constexpr int DNS_PORT = 53;
Mike Yud1ec2542019-06-06 17:17:53 +080046
47// Constant values sync'd from res_cache.cpp
48constexpr int DNS_HEADER_SIZE = 12;
49constexpr int MAX_ENTRIES = 64 * 2 * 5;
Mike Yud1ec2542019-06-06 17:17:53 +080050
51namespace {
52
53struct CacheEntry {
54 std::vector<char> query;
55 std::vector<char> answer;
56};
57
Mike Yuc7649d12019-05-22 15:28:07 +080058struct SetupParams {
59 std::vector<std::string> servers;
60 std::vector<std::string> domains;
61 res_params params;
62};
63
64struct CacheStats {
65 SetupParams setup;
66 std::vector<res_stats> stats;
67 int pendingReqTimeoutCount;
68};
69
Mike Yud1ec2542019-06-06 17:17:53 +080070std::vector<char> makeQuery(int op, const char* qname, int qclass, int qtype) {
Mike Yud1ec2542019-06-06 17:17:53 +080071 uint8_t buf[MAXPACKET] = {};
Bernie Innocenti08487112019-10-11 21:14:13 +090072 const int len = res_nmkquery(op, qname, qclass, qtype, /*data=*/nullptr, /*datalen=*/0, buf,
73 sizeof(buf),
74 /*netcontext_flags=*/0);
Mike Yud1ec2542019-06-06 17:17:53 +080075 return std::vector<char>(buf, buf + len);
76}
77
78std::vector<char> makeAnswer(const std::vector<char>& query, const char* rdata_str,
79 const unsigned ttl) {
80 test::DNSHeader header;
81 header.read(query.data(), query.data() + query.size());
82
83 for (const test::DNSQuestion& question : header.questions) {
84 std::string rname(question.qname.name);
85 test::DNSRecord record{
86 .name = {.name = question.qname.name},
87 .rtype = question.qtype,
88 .rclass = question.qclass,
89 .ttl = ttl,
90 };
Hungming Chenbb90ab32019-10-28 18:20:31 +080091 test::DNSResponder::fillRdata(rdata_str, record);
Mike Yud1ec2542019-06-06 17:17:53 +080092 header.answers.push_back(std::move(record));
93 }
94
95 char answer[MAXPACKET] = {};
96 char* answer_end = header.write(answer, answer + sizeof(answer));
97 return std::vector<char>(answer, answer_end);
98}
99
100// Get the current time in unix timestamp since the Epoch.
101time_t currentTime() {
102 return std::time(nullptr);
103}
104
Mike Yuc7649d12019-05-22 15:28:07 +0800105// Comparison for res_stats. Simply check the count in the cache test.
106bool operator==(const res_stats& a, const res_stats& b) {
107 return std::tie(a.sample_count, a.sample_next) == std::tie(b.sample_count, b.sample_next);
108}
109
110// Comparison for res_params.
111bool operator==(const res_params& a, const res_params& b) {
112 return std::tie(a.sample_validity, a.success_threshold, a.min_samples, a.max_samples,
113 a.base_timeout_msec, a.retry_count) ==
114 std::tie(b.sample_validity, b.success_threshold, b.min_samples, b.max_samples,
115 b.base_timeout_msec, b.retry_count);
116}
117
Mike Yud1ec2542019-06-06 17:17:53 +0800118} // namespace
119
120class ResolvCacheTest : public ::testing::Test {
121 protected:
Mike Yuc7649d12019-05-22 15:28:07 +0800122 static constexpr res_params kParams = {
123 .sample_validity = 300,
124 .success_threshold = 25,
125 .min_samples = 8,
126 .max_samples = 8,
127 .base_timeout_msec = 1000,
128 .retry_count = 2,
129 };
130
Mike Yud1ec2542019-06-06 17:17:53 +0800131 ResolvCacheTest() {
132 // Store the default one and conceal 10000+ lines of resolver cache logs.
133 defaultLogSeverity = android::base::SetMinimumLogSeverity(
134 static_cast<android::base::LogSeverity>(android::base::WARNING));
135 }
136 ~ResolvCacheTest() {
137 cacheDelete(TEST_NETID);
138 cacheDelete(TEST_NETID_2);
139
140 // Restore the log severity.
141 android::base::SetMinimumLogSeverity(defaultLogSeverity);
142 }
143
144 [[nodiscard]] bool cacheLookup(ResolvCacheStatus expectedCacheStatus, uint32_t netId,
145 const CacheEntry& ce, uint32_t flags = 0) {
146 int anslen = 0;
147 std::vector<char> answer(MAXPACKET);
148 const auto cacheStatus = resolv_cache_lookup(netId, ce.query.data(), ce.query.size(),
149 answer.data(), answer.size(), &anslen, flags);
150 if (cacheStatus != expectedCacheStatus) {
151 ADD_FAILURE() << "cacheStatus: expected = " << expectedCacheStatus
152 << ", actual =" << cacheStatus;
153 return false;
154 }
155
156 if (cacheStatus == RESOLV_CACHE_FOUND) {
157 answer.resize(anslen);
158 if (answer != ce.answer) {
159 ADD_FAILURE() << "The answer from the cache is not as expected.";
160 return false;
161 }
162 }
163 return true;
164 }
165
166 int cacheCreate(uint32_t netId) {
167 return resolv_create_cache_for_net(netId);
168 }
169
170 void cacheDelete(uint32_t netId) {
171 resolv_delete_cache_for_net(netId);
172 }
173
174 int cacheAdd(uint32_t netId, const CacheEntry& ce) {
175 return resolv_cache_add(netId, ce.query.data(), ce.query.size(), ce.answer.data(),
176 ce.answer.size());
177 }
178
179 int cacheAdd(uint32_t netId, const std::vector<char>& query, const std::vector<char>& answer) {
180 return resolv_cache_add(netId, query.data(), query.size(), answer.data(), answer.size());
181 }
182
183 int cacheGetExpiration(uint32_t netId, const std::vector<char>& query, time_t* expiration) {
184 return resolv_cache_get_expiration(netId, query, expiration);
185 }
186
187 void cacheQueryFailed(uint32_t netId, const CacheEntry& ce, uint32_t flags) {
188 _resolv_cache_query_failed(netId, ce.query.data(), ce.query.size(), flags);
189 }
190
Mike Yuc7649d12019-05-22 15:28:07 +0800191 int cacheSetupResolver(uint32_t netId, const SetupParams& setup) {
192 return resolv_set_nameservers(netId, setup.servers, setup.domains, setup.params);
193 }
194
Mike Yue48f7b52020-02-10 14:55:06 +0800195 void cacheAddStats(uint32_t netId, int revision_id, const IPSockAddr& ipsa,
Ken Chen766feae2019-10-30 15:13:44 +0800196 const res_sample& sample, int max_samples) {
Mike Yue48f7b52020-02-10 14:55:06 +0800197 resolv_cache_add_resolver_stats_sample(netId, revision_id, ipsa, sample, max_samples);
Ken Chen766feae2019-10-30 15:13:44 +0800198 }
199
200 int cacheFlush(uint32_t netId) { return resolv_flush_cache_for_net(netId); }
201
Mike Yuc7649d12019-05-22 15:28:07 +0800202 void expectCacheStats(const std::string& msg, uint32_t netId, const CacheStats& expected) {
203 int nscount = -1;
204 sockaddr_storage servers[MAXNS];
205 int dcount = -1;
206 char domains[MAXDNSRCH][MAXDNSRCHPATH];
207 res_stats stats[MAXNS];
208 res_params params = {};
209 int res_wait_for_pending_req_timeout_count;
210 android_net_res_stats_get_info_for_net(netId, &nscount, servers, &dcount, domains, &params,
211 stats, &res_wait_for_pending_req_timeout_count);
212
213 // Server checking.
214 EXPECT_EQ(nscount, static_cast<int>(expected.setup.servers.size())) << msg;
215 for (int i = 0; i < nscount; i++) {
216 EXPECT_EQ(addrToString(&servers[i]), expected.setup.servers[i]) << msg;
217 }
218
219 // Domain checking
220 EXPECT_EQ(dcount, static_cast<int>(expected.setup.domains.size())) << msg;
221 for (int i = 0; i < dcount; i++) {
222 EXPECT_EQ(std::string(domains[i]), expected.setup.domains[i]) << msg;
223 }
224
225 // res_params checking.
226 EXPECT_TRUE(params == expected.setup.params) << msg;
227
228 // res_stats checking.
Ken Chen8cfe5562019-11-03 11:37:06 +0800229 if (expected.stats.size() == 0) {
230 for (int ns = 0; ns < nscount; ns++) {
231 EXPECT_EQ(0U, stats[ns].sample_count) << msg;
232 }
233 }
Mike Yuc7649d12019-05-22 15:28:07 +0800234 for (size_t i = 0; i < expected.stats.size(); i++) {
235 EXPECT_TRUE(stats[i] == expected.stats[i]) << msg;
236 }
237
238 // wait_for_pending_req_timeout_count checking.
239 EXPECT_EQ(res_wait_for_pending_req_timeout_count, expected.pendingReqTimeoutCount) << msg;
240 }
241
Mike Yud1ec2542019-06-06 17:17:53 +0800242 CacheEntry makeCacheEntry(int op, const char* qname, int qclass, int qtype, const char* rdata,
243 std::chrono::seconds ttl = 10s) {
244 CacheEntry ce;
245 ce.query = makeQuery(op, qname, qclass, qtype);
246 ce.answer = makeAnswer(ce.query, rdata, static_cast<unsigned>(ttl.count()));
247 return ce;
248 }
249
250 private:
251 android::base::LogSeverity defaultLogSeverity;
252};
253
254TEST_F(ResolvCacheTest, CreateAndDeleteCache) {
255 // Create the cache for network 1.
256 EXPECT_EQ(0, cacheCreate(TEST_NETID));
257 EXPECT_EQ(-EEXIST, cacheCreate(TEST_NETID));
258 EXPECT_TRUE(has_named_cache(TEST_NETID));
259
260 // Create the cache for network 2.
261 EXPECT_EQ(0, cacheCreate(TEST_NETID_2));
262 EXPECT_EQ(-EEXIST, cacheCreate(TEST_NETID_2));
263 EXPECT_TRUE(has_named_cache(TEST_NETID_2));
264
265 // Delete the cache in network 1.
266 cacheDelete(TEST_NETID);
267 EXPECT_FALSE(has_named_cache(TEST_NETID));
268 EXPECT_TRUE(has_named_cache(TEST_NETID_2));
269}
270
271// Missing checks for the argument 'answer'.
272TEST_F(ResolvCacheTest, CacheAdd_InvalidArgs) {
273 EXPECT_EQ(0, cacheCreate(TEST_NETID));
274
275 const std::vector<char> queryEmpty(MAXPACKET, 0);
276 const std::vector<char> queryTooSmall(DNS_HEADER_SIZE - 1, 0);
277 CacheEntry ce = makeCacheEntry(QUERY, "valid.cache", ns_c_in, ns_t_a, "1.2.3.4");
278
279 EXPECT_EQ(-EINVAL, cacheAdd(TEST_NETID, queryEmpty, ce.answer));
280 EXPECT_EQ(-EINVAL, cacheAdd(TEST_NETID, queryTooSmall, ce.answer));
281
282 // Cache not existent in TEST_NETID_2.
283 EXPECT_EQ(-ENONET, cacheAdd(TEST_NETID_2, ce));
284}
285
286TEST_F(ResolvCacheTest, CacheAdd_DuplicateEntry) {
287 EXPECT_EQ(0, cacheCreate(TEST_NETID));
288 CacheEntry ce = makeCacheEntry(QUERY, "existent.in.cache", ns_c_in, ns_t_a, "1.2.3.4");
289 time_t now = currentTime();
290
291 // Add the cache entry.
292 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce));
293 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
294 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce));
295
296 // Get the expiration time and verify its value is greater than now.
297 time_t expiration1;
298 EXPECT_EQ(0, cacheGetExpiration(TEST_NETID, ce.query, &expiration1));
299 EXPECT_GT(expiration1, now);
300
301 // Adding the duplicate entry will return an error, and the expiration time won't be modified.
302 EXPECT_EQ(-EEXIST, cacheAdd(TEST_NETID, ce));
303 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce));
304 time_t expiration2;
305 EXPECT_EQ(0, cacheGetExpiration(TEST_NETID, ce.query, &expiration2));
306 EXPECT_EQ(expiration1, expiration2);
307}
308
309TEST_F(ResolvCacheTest, CacheLookup) {
310 EXPECT_EQ(0, cacheCreate(TEST_NETID));
311 EXPECT_EQ(0, cacheCreate(TEST_NETID_2));
312 CacheEntry ce = makeCacheEntry(QUERY, "existent.in.cache", ns_c_in, ns_t_a, "1.2.3.4");
313
314 // Cache found in network 1.
315 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce));
316 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
317 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce));
318
319 // No cache found in network 2.
320 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID_2, ce));
321
322 ce = makeCacheEntry(QUERY, "existent.in.cache", ns_c_in, ns_t_aaaa, "2001:db8::1.2.3.4");
323
324 // type A and AAAA are independent.
325 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce));
326 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
327 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce));
328}
329
330TEST_F(ResolvCacheTest, CacheLookup_CacheFlags) {
331 EXPECT_EQ(0, cacheCreate(TEST_NETID));
332 std::vector<char> answerFromCache;
333 CacheEntry ce = makeCacheEntry(QUERY, "existent.in.cache", ns_c_in, ns_t_a, "1.2.3.4");
334
335 // The entry can't be found when only no-cache-lookup bit is carried.
336 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce, ANDROID_RESOLV_NO_CACHE_LOOKUP));
337
338 // Ensure RESOLV_CACHE_SKIP is returned when there's no such the same entry in the cache.
339 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_SKIP, TEST_NETID, ce, ANDROID_RESOLV_NO_CACHE_STORE));
340
341 // Skip the cache lookup if no-cache-lookup and no-cache-store bits are carried
342 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_SKIP, TEST_NETID, ce,
343 ANDROID_RESOLV_NO_CACHE_LOOKUP | ANDROID_RESOLV_NO_CACHE_STORE));
344
345 // Add the cache entry.
346 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce));
347 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
348 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce));
349
350 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce, ANDROID_RESOLV_NO_CACHE_LOOKUP));
351
352 // Now no-cache-store has no effect if a same entry is existent in the cache.
353 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce, ANDROID_RESOLV_NO_CACHE_STORE));
354
355 // Skip the cache lookup again regardless of a same entry being already in the cache.
356 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_SKIP, TEST_NETID, ce,
357 ANDROID_RESOLV_NO_CACHE_LOOKUP | ANDROID_RESOLV_NO_CACHE_STORE));
358}
359
360TEST_F(ResolvCacheTest, CacheLookup_Types) {
361 EXPECT_EQ(0, cacheCreate(TEST_NETID));
362 static const struct QueryTypes {
363 int type;
364 std::string rdata;
365 } Types[] = {
366 {ns_t_a, "1.2.3.4"},
367 {ns_t_aaaa, "2001:db8::1.2.3.4"},
368 {ns_t_ptr, "4.3.2.1.in-addr.arpa."},
369 {ns_t_ptr, "4.0.3.0.2.0.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa."},
370 };
371
372 for (const auto& t : Types) {
373 std::string name = android::base::StringPrintf("cache.lookup.type.%s", t.rdata.c_str());
374 SCOPED_TRACE(name);
375
376 CacheEntry ce = makeCacheEntry(QUERY, name.data(), ns_c_in, t.type, t.rdata.data());
377 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce));
378 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
379 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce));
380 }
381}
382
383TEST_F(ResolvCacheTest, CacheLookup_InvalidArgs) {
384 EXPECT_EQ(0, cacheCreate(TEST_NETID));
385
386 const std::vector<char> queryEmpty(MAXPACKET, 0);
387 const std::vector<char> queryTooSmall(DNS_HEADER_SIZE - 1, 0);
388 std::vector<char> answerTooSmall(DNS_HEADER_SIZE - 1, 0);
389 const CacheEntry ce = makeCacheEntry(QUERY, "valid.cache", ns_c_in, ns_t_a, "1.2.3.4");
390 auto cacheLookupFn = [](const std::vector<char>& query,
391 std::vector<char> answer) -> ResolvCacheStatus {
392 int anslen = 0;
393 return resolv_cache_lookup(TEST_NETID, query.data(), query.size(), answer.data(),
394 answer.size(), &anslen, 0);
395 };
396
397 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
398
399 EXPECT_EQ(RESOLV_CACHE_UNSUPPORTED, cacheLookupFn(queryEmpty, ce.answer));
400 EXPECT_EQ(RESOLV_CACHE_UNSUPPORTED, cacheLookupFn(queryTooSmall, ce.answer));
401 EXPECT_EQ(RESOLV_CACHE_UNSUPPORTED, cacheLookupFn(ce.query, answerTooSmall));
402
403 // It can actually be found with valid arguments.
404 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce));
405
406 // Cache not existent in TEST_NETID_2.
407 EXPECT_EQ(-ENONET, cacheAdd(TEST_NETID_2, ce));
408 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_UNSUPPORTED, TEST_NETID_2, ce));
409}
410
411TEST_F(ResolvCacheTest, CacheLookup_Expired) {
412 EXPECT_EQ(0, cacheCreate(TEST_NETID));
413
414 // An entry with zero ttl won't be stored in the cache.
415 CacheEntry ce = makeCacheEntry(QUERY, "expired.in.0s", ns_c_in, ns_t_a, "1.2.3.4", 0s);
416 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
417 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce));
418
419 // Create an entry expired in 1s.
420 ce = makeCacheEntry(QUERY, "expired.in.1s", ns_c_in, ns_t_a, "1.2.3.4", 1s);
421 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
422
423 // Cache found.
424 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce));
425 time_t expiration;
426 EXPECT_EQ(0, cacheGetExpiration(TEST_NETID, ce.query, &expiration));
427
428 // Wait for the cache expired.
429 std::this_thread::sleep_for(1500ms);
430 EXPECT_GE(currentTime(), expiration);
431 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce));
432}
433
434TEST_F(ResolvCacheTest, PendingRequest_QueryDeferred) {
435 EXPECT_EQ(0, cacheCreate(TEST_NETID));
436 EXPECT_EQ(0, cacheCreate(TEST_NETID_2));
437
438 CacheEntry ce = makeCacheEntry(QUERY, "query.deferred", ns_c_in, ns_t_a, "1.2.3.4");
439 std::atomic_bool done(false);
440
441 // This is the first lookup. The following lookups from other threads will be in the
442 // pending request list.
443 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce));
444
445 std::vector<std::thread> threads(5);
446 for (std::thread& thread : threads) {
447 thread = std::thread([&]() {
448 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce));
449
450 // Ensure this thread gets stuck in lookups before we wake it.
451 EXPECT_TRUE(done);
452 });
453 }
454
455 // Wait for a while for the threads performing lookups.
456 // TODO: Perhaps implement a test-only function to get the number of pending requests
457 // instead of sleep.
458 std::this_thread::sleep_for(100ms);
459
460 // The threads keep waiting regardless of any other networks or even if cache flag is set.
461 EXPECT_EQ(0, cacheAdd(TEST_NETID_2, ce));
462 cacheQueryFailed(TEST_NETID, ce, ANDROID_RESOLV_NO_CACHE_STORE);
463 cacheQueryFailed(TEST_NETID, ce, ANDROID_RESOLV_NO_CACHE_LOOKUP);
464 cacheQueryFailed(TEST_NETID_2, ce, ANDROID_RESOLV_NO_CACHE_STORE);
465 cacheQueryFailed(TEST_NETID_2, ce, ANDROID_RESOLV_NO_CACHE_LOOKUP);
466 cacheDelete(TEST_NETID_2);
467
468 // Ensure none of the threads has finished the lookups.
469 std::this_thread::sleep_for(100ms);
470
471 // Wake up the threads
472 done = true;
473 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
474
475 for (std::thread& thread : threads) {
476 thread.join();
477 }
478}
479
480TEST_F(ResolvCacheTest, PendingRequest_QueryFailed) {
481 EXPECT_EQ(0, cacheCreate(TEST_NETID));
482
483 CacheEntry ce = makeCacheEntry(QUERY, "query.failed", ns_c_in, ns_t_a, "1.2.3.4");
484 std::atomic_bool done(false);
485
486 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce));
487
488 std::vector<std::thread> threads(5);
489 for (std::thread& thread : threads) {
490 thread = std::thread([&]() {
491 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce));
492
493 // Ensure this thread gets stuck in lookups before we wake it.
494 EXPECT_TRUE(done);
495 });
496 }
497
498 // Wait for a while for the threads performing lookups.
499 std::this_thread::sleep_for(100ms);
500
501 // Wake up the threads
502 done = true;
503 cacheQueryFailed(TEST_NETID, ce, 0);
504
505 for (std::thread& thread : threads) {
506 thread.join();
507 }
508}
509
510TEST_F(ResolvCacheTest, PendingRequest_CacheDestroyed) {
511 EXPECT_EQ(0, cacheCreate(TEST_NETID));
512 EXPECT_EQ(0, cacheCreate(TEST_NETID_2));
513
514 CacheEntry ce = makeCacheEntry(QUERY, "query.failed", ns_c_in, ns_t_a, "1.2.3.4");
515 std::atomic_bool done(false);
516
517 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce));
518
519 std::vector<std::thread> threads(5);
520 for (std::thread& thread : threads) {
521 thread = std::thread([&]() {
522 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce));
523
524 // Ensure this thread gets stuck in lookups before we wake it.
525 EXPECT_TRUE(done);
526 });
527 }
528
529 // Wait for a while for the threads performing lookups.
530 std::this_thread::sleep_for(100ms);
531
532 // Deleting another network must not cause the threads to wake up.
533 cacheDelete(TEST_NETID_2);
534
535 // Ensure none of the threads has finished the lookups.
536 std::this_thread::sleep_for(100ms);
537
538 // Wake up the threads
539 done = true;
540 cacheDelete(TEST_NETID);
541
542 for (std::thread& thread : threads) {
543 thread.join();
544 }
545}
546
547TEST_F(ResolvCacheTest, MaxEntries) {
548 EXPECT_EQ(0, cacheCreate(TEST_NETID));
549 std::vector<CacheEntry> ces;
550
551 for (int i = 0; i < 2 * MAX_ENTRIES; i++) {
552 std::string qname = android::base::StringPrintf("cache.%04d", i);
553 SCOPED_TRACE(qname);
554 CacheEntry ce = makeCacheEntry(QUERY, qname.data(), ns_c_in, ns_t_a, "1.2.3.4");
555 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
556 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce));
557 ces.emplace_back(ce);
558 }
559
560 for (int i = 0; i < 2 * MAX_ENTRIES; i++) {
561 std::string qname = android::base::StringPrintf("cache.%04d", i);
562 SCOPED_TRACE(qname);
563 if (i < MAX_ENTRIES) {
564 // Because the cache is LRU, the oldest queries should have been purged,
565 // and the most recent MAX_ENTRIES ones should still be present.
566 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ces[i]));
567 } else {
568 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ces[i]));
569 }
570 }
571}
572
573TEST_F(ResolvCacheTest, CacheFull) {
574 EXPECT_EQ(0, cacheCreate(TEST_NETID));
575
576 CacheEntry ce1 = makeCacheEntry(QUERY, "cache.0000", ns_c_in, ns_t_a, "1.2.3.4", 100s);
577 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce1));
578 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce1));
579
580 CacheEntry ce2 = makeCacheEntry(QUERY, "cache.0001", ns_c_in, ns_t_a, "1.2.3.4", 1s);
581 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce2));
582 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce2));
583
584 // Stuff the resolver cache.
585 for (int i = 2; i < MAX_ENTRIES; i++) {
586 std::string qname = android::base::StringPrintf("cache.%04d", i);
587 SCOPED_TRACE(qname);
588 CacheEntry ce = makeCacheEntry(QUERY, qname.data(), ns_c_in, ns_t_a, "1.2.3.4", 50s);
589 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
590 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce));
591 }
592
593 // Wait for ce2 expired.
594 std::this_thread::sleep_for(1500ms);
595
596 // The cache is full now, and the expired ce2 will be removed first.
597 CacheEntry ce3 = makeCacheEntry(QUERY, "cache.overfilled.1", ns_c_in, ns_t_a, "1.2.3.4", 50s);
598 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce3));
599 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce3));
600 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce2));
601
602 // The cache is full again but there's no one expired, so the oldest ce1 will be removed.
603 CacheEntry ce4 = makeCacheEntry(QUERY, "cache.overfilled.2", ns_c_in, ns_t_a, "1.2.3.4", 50s);
604 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce4));
605 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_FOUND, TEST_NETID, ce4));
606 EXPECT_TRUE(cacheLookup(RESOLV_CACHE_NOTFOUND, TEST_NETID, ce1));
607}
608
Mike Yuc7649d12019-05-22 15:28:07 +0800609TEST_F(ResolvCacheTest, ResolverSetup) {
610 const SetupParams setup = {
611 .servers = {"127.0.0.1", "::127.0.0.2", "fe80::3"},
612 .domains = {"domain1.com", "domain2.com"},
613 .params = kParams,
614 };
615
616 // Failed to setup resolver because of the cache not created.
617 EXPECT_EQ(-ENONET, cacheSetupResolver(TEST_NETID, setup));
618 EXPECT_FALSE(resolv_has_nameservers(TEST_NETID));
619
620 // The cache is created now.
621 EXPECT_EQ(0, cacheCreate(TEST_NETID));
622 EXPECT_EQ(0, cacheSetupResolver(TEST_NETID, setup));
623 EXPECT_TRUE(resolv_has_nameservers(TEST_NETID));
624}
625
626TEST_F(ResolvCacheTest, ResolverSetup_InvalidNameServers) {
627 EXPECT_EQ(0, cacheCreate(TEST_NETID));
628 const std::string invalidServers[]{
629 "127.A.b.1",
630 "127.^.0",
631 "::^:1",
632 "",
633 };
634 SetupParams setup = {
635 .servers = {},
636 .domains = {"domain1.com"},
637 .params = kParams,
638 };
639
640 // Failed to setup resolver because of invalid name servers.
641 for (const auto& server : invalidServers) {
642 SCOPED_TRACE(server);
643 setup.servers = {"127.0.0.1", server, "127.0.0.2"};
644 EXPECT_EQ(-EINVAL, cacheSetupResolver(TEST_NETID, setup));
645 EXPECT_FALSE(resolv_has_nameservers(TEST_NETID));
646 }
647}
648
649TEST_F(ResolvCacheTest, ResolverSetup_DropDomain) {
650 EXPECT_EQ(0, cacheCreate(TEST_NETID));
651
652 // Setup with one domain which is too long.
653 const std::vector<std::string> servers = {"127.0.0.1", "fe80::1"};
654 const std::string domainTooLong(MAXDNSRCHPATH, '1');
655 const std::string validDomain1(MAXDNSRCHPATH - 1, '2');
656 const std::string validDomain2(MAXDNSRCHPATH - 1, '3');
657 SetupParams setup = {
658 .servers = servers,
659 .domains = {},
660 .params = kParams,
661 };
662 CacheStats expect = {
663 .setup = setup,
664 .stats = {},
665 .pendingReqTimeoutCount = 0,
666 };
667
668 // Overlength domains are dropped.
669 setup.domains = {validDomain1, domainTooLong, validDomain2};
670 expect.setup.domains = {validDomain1, validDomain2};
671 EXPECT_EQ(0, cacheSetupResolver(TEST_NETID, setup));
672 EXPECT_TRUE(resolv_has_nameservers(TEST_NETID));
673 expectCacheStats("ResolverSetup_Domains drop overlength", TEST_NETID, expect);
674
675 // Duplicate domains are dropped.
676 setup.domains = {validDomain1, validDomain2, validDomain1, validDomain2};
677 expect.setup.domains = {validDomain1, validDomain2};
678 EXPECT_EQ(0, cacheSetupResolver(TEST_NETID, setup));
679 EXPECT_TRUE(resolv_has_nameservers(TEST_NETID));
680 expectCacheStats("ResolverSetup_Domains drop duplicates", TEST_NETID, expect);
681}
682
683TEST_F(ResolvCacheTest, ResolverSetup_Prune) {
684 EXPECT_EQ(0, cacheCreate(TEST_NETID));
685 const std::vector<std::string> servers = {"127.0.0.1", "::127.0.0.2", "fe80::1", "fe80::2",
686 "fe80::3"};
687 const std::vector<std::string> domains = {"d1.com", "d2.com", "d3.com", "d4.com",
688 "d5.com", "d6.com", "d7.com"};
689 const SetupParams setup = {
690 .servers = servers,
691 .domains = domains,
692 .params = kParams,
693 };
694
695 EXPECT_EQ(0, cacheSetupResolver(TEST_NETID, setup));
696 EXPECT_TRUE(resolv_has_nameservers(TEST_NETID));
697
698 const CacheStats cacheStats = {
699 .setup = {.servers = std::vector(servers.begin(), servers.begin() + MAXNS),
700 .domains = std::vector(domains.begin(), domains.begin() + MAXDNSRCH),
701 .params = setup.params},
702 .stats = {},
703 .pendingReqTimeoutCount = 0,
704 };
705 expectCacheStats("ResolverSetup_Prune", TEST_NETID, cacheStats);
706}
707
708TEST_F(ResolvCacheTest, GetStats) {
709 EXPECT_EQ(0, cacheCreate(TEST_NETID));
710 const SetupParams setup = {
711 .servers = {"127.0.0.1", "::127.0.0.2", "fe80::3"},
712 .domains = {"domain1.com", "domain2.com"},
713 .params = kParams,
714 };
715
716 EXPECT_EQ(0, cacheSetupResolver(TEST_NETID, setup));
717 EXPECT_TRUE(resolv_has_nameservers(TEST_NETID));
718
719 const CacheStats cacheStats = {
720 .setup = setup,
721 .stats = {},
722 .pendingReqTimeoutCount = 0,
723 };
724 expectCacheStats("GetStats", TEST_NETID, cacheStats);
725}
726
Ken Chen766feae2019-10-30 15:13:44 +0800727TEST_F(ResolvCacheTest, FlushCache) {
728 EXPECT_EQ(0, cacheCreate(TEST_NETID));
729 const SetupParams setup = {
730 .servers = {"127.0.0.1", "::127.0.0.2", "fe80::3"},
731 .domains = {"domain1.com", "domain2.com"},
732 .params = kParams,
733 };
734 EXPECT_EQ(0, cacheSetupResolver(TEST_NETID, setup));
735 EXPECT_TRUE(resolv_has_nameservers(TEST_NETID));
736
737 res_sample sample = {.at = time(NULL), .rtt = 100, .rcode = ns_r_noerror};
738 sockaddr_in sin = {.sin_family = AF_INET, .sin_port = htons(DNS_PORT)};
739 ASSERT_TRUE(inet_pton(AF_INET, setup.servers[0].c_str(), &sin.sin_addr));
Mike Yue48f7b52020-02-10 14:55:06 +0800740 cacheAddStats(TEST_NETID, 1 /*revision_id*/, IPSockAddr(sin), sample, setup.params.max_samples);
Ken Chen766feae2019-10-30 15:13:44 +0800741
742 const CacheStats cacheStats = {
743 .setup = setup,
744 .stats = {{{sample}, 1 /*sample_count*/, 1 /*sample_next*/}},
745 .pendingReqTimeoutCount = 0,
746 };
747 expectCacheStats("FlushCache: a record in cache stats", TEST_NETID, cacheStats);
748
749 EXPECT_EQ(0, cacheFlush(TEST_NETID));
750 const CacheStats cacheStats_empty = {
751 .setup = setup,
752 .stats = {},
753 .pendingReqTimeoutCount = 0,
754 };
755 expectCacheStats("FlushCache: no record in cache stats", TEST_NETID, cacheStats_empty);
756}
757
Ken Chen0d08fbe2019-10-22 21:38:20 +0800758TEST_F(ResolvCacheTest, GetHostByAddrFromCache_InvalidArgs) {
759 char domain_name[NS_MAXDNAME] = {};
760 const char query_v4[] = "1.2.3.5";
761
762 // invalid buffer size
763 EXPECT_FALSE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME + 1, nullptr,
764 AF_INET));
765 EXPECT_STREQ("", domain_name);
766
767 // invalid query
768 EXPECT_FALSE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME, nullptr,
769 AF_INET));
770 EXPECT_STREQ("", domain_name);
771
772 // unsupported AF
773 EXPECT_FALSE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME, query_v4,
774 AF_UNSPEC));
775 EXPECT_STREQ("", domain_name);
776}
777
778TEST_F(ResolvCacheTest, GetHostByAddrFromCache) {
779 char domain_name[NS_MAXDNAME] = {};
780 const char query_v4[] = "1.2.3.5";
781 const char query_v6[] = "2001:db8::102:304";
782 const char query_v6_unabbreviated[] = "2001:0db8:0000:0000:0000:0000:0102:0304";
783 const char query_v6_mixed[] = "2001:db8::1.2.3.4";
784 const char answer[] = "existent.in.cache";
785
786 // cache does not exist
787 EXPECT_FALSE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME, query_v4,
788 AF_INET));
789 EXPECT_STREQ("", domain_name);
790
791 // cache is empty
792 EXPECT_EQ(0, cacheCreate(TEST_NETID));
793 EXPECT_FALSE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME, query_v4,
794 AF_INET));
795 EXPECT_STREQ("", domain_name);
796
797 // no v4 match in cache
798 CacheEntry ce = makeCacheEntry(QUERY, "any.data", ns_c_in, ns_t_a, "1.2.3.4");
799 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
800 EXPECT_FALSE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME, query_v4,
801 AF_INET));
802 EXPECT_STREQ("", domain_name);
803
804 // v4 match
805 ce = makeCacheEntry(QUERY, answer, ns_c_in, ns_t_a, query_v4);
806 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
807 EXPECT_TRUE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME, query_v4,
808 AF_INET));
809 EXPECT_STREQ(answer, domain_name);
810
811 // no v6 match in cache
812 memset(domain_name, 0, NS_MAXDNAME);
813 EXPECT_FALSE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME, query_v6,
814 AF_INET6));
815 EXPECT_STREQ("", domain_name);
816
817 // v6 match
818 ce = makeCacheEntry(QUERY, answer, ns_c_in, ns_t_aaaa, query_v6);
819 EXPECT_EQ(0, cacheAdd(TEST_NETID, ce));
820 EXPECT_TRUE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME, query_v6,
821 AF_INET6));
822 EXPECT_STREQ(answer, domain_name);
823
824 // v6 match with unabbreviated address format
825 memset(domain_name, 0, NS_MAXDNAME);
826 EXPECT_TRUE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME,
827 query_v6_unabbreviated, AF_INET6));
828 EXPECT_STREQ(answer, domain_name);
829
830 // v6 with mixed address format
831 memset(domain_name, 0, NS_MAXDNAME);
832 EXPECT_TRUE(resolv_gethostbyaddr_from_cache(TEST_NETID, domain_name, NS_MAXDNAME,
833 query_v6_mixed, AF_INET6));
834 EXPECT_STREQ(answer, domain_name);
835}
836
Luke Huange126fbe2019-07-20 17:36:30 +0800837namespace {
838
839constexpr int EAI_OK = 0;
840constexpr char DNS_EVENT_SUBSAMPLING_MAP_FLAG[] =
841 "persist.device_config.netd_native.dns_event_subsample_map";
842
843class ScopedCacheCreate {
844 public:
845 explicit ScopedCacheCreate(unsigned netid, const char* subsampling_map,
846 const char* property = DNS_EVENT_SUBSAMPLING_MAP_FLAG)
847 : mStoredNetId(netid), mStoredProperty(property) {
848 property_get(property, mStoredMap, "");
849 property_set(property, subsampling_map);
850 EXPECT_EQ(0, resolv_create_cache_for_net(netid));
851 }
852 ~ScopedCacheCreate() {
853 resolv_delete_cache_for_net(mStoredNetId);
854 property_set(mStoredProperty, mStoredMap);
855 }
856
857 private:
858 unsigned mStoredNetId;
859 const char* mStoredProperty;
860 char mStoredMap[PROPERTY_VALUE_MAX]{};
861};
862
863} // namespace
864
865TEST_F(ResolvCacheTest, DnsEventSubsampling) {
866 // Test defaults, default flag is "default:1 0:100 7:10" if no experiment flag is set
867 {
868 ScopedCacheCreate scopedCacheCreate(TEST_NETID, "");
869 EXPECT_EQ(resolv_cache_get_subsampling_denom(TEST_NETID, EAI_NODATA), 10U);
870 EXPECT_EQ(resolv_cache_get_subsampling_denom(TEST_NETID, EAI_OK), 100U);
871 EXPECT_EQ(resolv_cache_get_subsampling_denom(TEST_NETID, EAI_BADFLAGS),
872 1U); // default
873 EXPECT_THAT(resolv_cache_dump_subsampling_map(TEST_NETID),
874 testing::UnorderedElementsAreArray({"default:1", "0:100", "7:10"}));
875 }
876 // Now change the experiment flag to "0:42 default:666"
877 {
878 ScopedCacheCreate scopedCacheCreate(TEST_NETID, "0:42 default:666");
879 EXPECT_EQ(resolv_cache_get_subsampling_denom(TEST_NETID, EAI_OK), 42U);
880 EXPECT_EQ(resolv_cache_get_subsampling_denom(TEST_NETID, EAI_NODATA),
881 666U); // default
882 EXPECT_THAT(resolv_cache_dump_subsampling_map(TEST_NETID),
883 testing::UnorderedElementsAreArray({"default:666", "0:42"}));
884 }
885 // Now change the experiment flag to something illegal
886 {
887 ScopedCacheCreate scopedCacheCreate(TEST_NETID, "asvaxx");
888 // 0(disable log) is the default value if experiment flag is invalid.
889 EXPECT_EQ(resolv_cache_get_subsampling_denom(TEST_NETID, EAI_OK), 0U);
890 EXPECT_EQ(resolv_cache_get_subsampling_denom(TEST_NETID, EAI_NODATA), 0U);
891 EXPECT_TRUE(resolv_cache_dump_subsampling_map(TEST_NETID).empty());
892 }
893 // Test negative and zero denom
894 {
895 ScopedCacheCreate scopedCacheCreate(TEST_NETID, "0:-42 default:-666 7:10 10:0");
896 // 0(disable log) is the default value if no valid denom is set
897 EXPECT_EQ(resolv_cache_get_subsampling_denom(TEST_NETID, EAI_OK), 0U);
898 EXPECT_EQ(resolv_cache_get_subsampling_denom(TEST_NETID, EAI_BADFLAGS), 0U);
899 EXPECT_EQ(resolv_cache_get_subsampling_denom(TEST_NETID, EAI_NODATA), 10U);
900 EXPECT_EQ(resolv_cache_get_subsampling_denom(TEST_NETID, EAI_SOCKTYPE), 0U);
901 EXPECT_THAT(resolv_cache_dump_subsampling_map(TEST_NETID),
902 testing::UnorderedElementsAreArray({"7:10", "10:0"}));
903 }
904}
905
Mike Yud5918e62019-10-25 18:51:04 +0800906// TODO: Tests for NetConfig, including:
Mike Yud1ec2542019-06-06 17:17:53 +0800907// - res_params
908// -- resolv_cache_get_resolver_stats()
909// - res_stats
910// -- _resolv_cache_add_resolver_stats_sample()
911// -- android_net_res_stats_get_info_for_net()
912// TODO: inject a mock timer into the cache to make TTL tests pass instantly
913// TODO: test TTL of RFC 2308 negative caching