blob: 6c7fdac0a6f79ee1f6aba24a9a0f27546faeaa25 [file] [log] [blame]
Pierre Imai904ce3a2016-02-18 13:13:12 +09001/*
2 * Copyright (C) 2016 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 requied 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 */
17
18#include <arpa/inet.h>
19#include <errno.h>
20#include <netdb.h>
21#include <stdarg.h>
22#include <stdio.h>
23#include <stdlib.h>
Pierre Imai95f5f942016-03-09 18:09:25 +090024#include <unistd.h>
Pierre Imai904ce3a2016-02-18 13:13:12 +090025
26#include <cutils/sockets.h>
Pierre Imai95f5f942016-03-09 18:09:25 +090027#include <android-base/stringprintf.h>
Pierre Imai904ce3a2016-02-18 13:13:12 +090028#include <private/android_filesystem_config.h>
Pierre Imai95f5f942016-03-09 18:09:25 +090029
Pierre Imaibeedec32016-04-13 06:44:51 +090030#include <algorithm>
31#include <chrono>
32#include <iterator>
33#include <numeric>
Pierre Imai95f5f942016-03-09 18:09:25 +090034#include <thread>
35
Pierre Imaibeedec32016-04-13 06:44:51 +090036#define LOG_TAG "netd_test"
37// TODO: make this dynamic and stop depending on implementation details.
38#define TEST_OEM_NETWORK "oem29"
39#define TEST_NETID 30
40
Pierre Imai904ce3a2016-02-18 13:13:12 +090041#include "NetdClient.h"
42
43#include <gtest/gtest.h>
Pierre Imaibeedec32016-04-13 06:44:51 +090044
Pierre Imai904ce3a2016-02-18 13:13:12 +090045#include <utils/Log.h>
Pierre Imaibeedec32016-04-13 06:44:51 +090046
Pierre Imai904ce3a2016-02-18 13:13:12 +090047#include <testUtil.h>
48
49#include "dns_responder.h"
Robin Lee2cf56172016-09-13 18:55:42 +090050#include "dns_responder_client.h"
Pierre Imai95f5f942016-03-09 18:09:25 +090051#include "resolv_params.h"
Pierre Imaibeedec32016-04-13 06:44:51 +090052#include "ResolverStats.h"
53
54#include "android/net/INetd.h"
55#include "binder/IServiceManager.h"
Pierre Imai95f5f942016-03-09 18:09:25 +090056
57using android::base::StringPrintf;
58using android::base::StringAppendF;
Pierre Imaibeedec32016-04-13 06:44:51 +090059using android::net::ResolverStats;
Pierre Imai904ce3a2016-02-18 13:13:12 +090060
Pierre Imaibeedec32016-04-13 06:44:51 +090061// Emulates the behavior of UnorderedElementsAreArray, which currently cannot be used.
62// TODO: Use UnorderedElementsAreArray, which depends on being able to compile libgmock_host,
63// if that is not possible, improve this hacky algorithm, which is O(n**2)
64template <class A, class B>
65bool UnorderedCompareArray(const A& a, const B& b) {
66 if (a.size() != b.size()) return false;
67 for (const auto& a_elem : a) {
68 size_t a_count = 0;
69 for (const auto& a_elem2 : a) {
70 if (a_elem == a_elem2) {
71 ++a_count;
72 }
73 }
74 size_t b_count = 0;
75 for (const auto& b_elem : b) {
76 if (a_elem == b_elem) ++b_count;
77 }
78 if (a_count != b_count) return false;
79 }
80 return true;
81}
Pierre Imai904ce3a2016-02-18 13:13:12 +090082
Pierre Imai3a272072016-04-19 16:17:07 +090083class AddrInfo {
84 public:
85 AddrInfo() : ai_(nullptr), error_(0) {}
86
87 AddrInfo(const char* node, const char* service, const addrinfo& hints) : ai_(nullptr) {
88 init(node, service, hints);
89 }
90
91 AddrInfo(const char* node, const char* service) : ai_(nullptr) {
92 init(node, service);
93 }
94
95 ~AddrInfo() { clear(); }
96
97 int init(const char* node, const char* service, const addrinfo& hints) {
98 clear();
99 error_ = getaddrinfo(node, service, &hints, &ai_);
100 return error_;
101 }
102
103 int init(const char* node, const char* service) {
104 clear();
105 error_ = getaddrinfo(node, service, nullptr, &ai_);
106 return error_;
107 }
108
109 void clear() {
110 if (ai_ != nullptr) {
111 freeaddrinfo(ai_);
112 ai_ = nullptr;
113 error_ = 0;
114 }
115 }
116
117 const addrinfo& operator*() const { return *ai_; }
118 const addrinfo* get() const { return ai_; }
119 const addrinfo* operator&() const { return ai_; }
120 int error() const { return error_; }
121
122 private:
123 addrinfo* ai_;
124 int error_;
125};
126
Robin Lee2cf56172016-09-13 18:55:42 +0900127class ResolverTest : public ::testing::Test, public DnsResponderClient {
Pierre Imai904ce3a2016-02-18 13:13:12 +0900128protected:
129 virtual void SetUp() {
130 // Ensure resolutions go via proxy.
Robin Lee2cf56172016-09-13 18:55:42 +0900131 DnsResponderClient::SetUp();
Pierre Imai904ce3a2016-02-18 13:13:12 +0900132 }
133
134 virtual void TearDown() {
Robin Lee2cf56172016-09-13 18:55:42 +0900135 DnsResponderClient::TearDown();
Pierre Imai904ce3a2016-02-18 13:13:12 +0900136 }
137
Pierre Imaibeedec32016-04-13 06:44:51 +0900138 bool GetResolverInfo(std::vector<std::string>* servers, std::vector<std::string>* domains,
139 __res_params* params, std::vector<ResolverStats>* stats) {
140 using android::net::INetd;
141 std::vector<int32_t> params32;
142 std::vector<int32_t> stats32;
143 auto rv = mNetdSrv->getResolverInfo(TEST_NETID, servers, domains, &params32, &stats32);
144 if (!rv.isOk() || params32.size() != INetd::RESOLVER_PARAMS_COUNT) {
145 return false;
146 }
147 *params = __res_params {
148 .sample_validity = static_cast<uint16_t>(
149 params32[INetd::RESOLVER_PARAMS_SAMPLE_VALIDITY]),
150 .success_threshold = static_cast<uint8_t>(
151 params32[INetd::RESOLVER_PARAMS_SUCCESS_THRESHOLD]),
152 .min_samples = static_cast<uint8_t>(
153 params32[INetd::RESOLVER_PARAMS_MIN_SAMPLES]),
154 .max_samples = static_cast<uint8_t>(
155 params32[INetd::RESOLVER_PARAMS_MAX_SAMPLES])
156 };
157 return ResolverStats::decodeAll(stats32, stats);
158 }
159
Pierre Imai95f5f942016-03-09 18:09:25 +0900160 std::string ToString(const hostent* he) const {
161 if (he == nullptr) return "<null>";
162 char buffer[INET6_ADDRSTRLEN];
163 if (!inet_ntop(he->h_addrtype, he->h_addr_list[0], buffer, sizeof(buffer))) {
164 return "<invalid>";
165 }
166 return buffer;
Pierre Imaiccf7b992016-02-25 16:34:29 +0900167 }
168
Pierre Imai95f5f942016-03-09 18:09:25 +0900169 std::string ToString(const addrinfo* ai) const {
170 if (!ai)
Pierre Imai904ce3a2016-02-18 13:13:12 +0900171 return "<null>";
Pierre Imai95f5f942016-03-09 18:09:25 +0900172 for (const auto* aip = ai ; aip != nullptr ; aip = aip->ai_next) {
173 char host[NI_MAXHOST];
174 int rv = getnameinfo(aip->ai_addr, aip->ai_addrlen, host, sizeof(host), nullptr, 0,
175 NI_NUMERICHOST);
176 if (rv != 0)
177 return gai_strerror(rv);
178 return host;
179 }
180 return "<invalid>";
181 }
182
183 size_t GetNumQueries(const test::DNSResponder& dns, const char* name) const {
184 auto queries = dns.queries();
185 size_t found = 0;
186 for (const auto& p : queries) {
Pierre Imai95f5f942016-03-09 18:09:25 +0900187 if (p.first == name) {
188 ++found;
189 }
190 }
191 return found;
192 }
193
194 size_t GetNumQueriesForType(const test::DNSResponder& dns, ns_type type,
195 const char* name) const {
196 auto queries = dns.queries();
197 size_t found = 0;
198 for (const auto& p : queries) {
Pierre Imai95f5f942016-03-09 18:09:25 +0900199 if (p.second == type && p.first == name) {
200 ++found;
201 }
202 }
203 return found;
Pierre Imai904ce3a2016-02-18 13:13:12 +0900204 }
205
Pierre Imaibeedec32016-04-13 06:44:51 +0900206 void RunGetAddrInfoStressTest_Binder(unsigned num_hosts, unsigned num_threads,
207 unsigned num_queries) {
208 std::vector<std::string> domains = { "example.com" };
209 std::vector<std::unique_ptr<test::DNSResponder>> dns;
210 std::vector<std::string> servers;
Robin Lee2cf56172016-09-13 18:55:42 +0900211 std::vector<DnsResponderClient::Mapping> mappings;
Pierre Imaibeedec32016-04-13 06:44:51 +0900212 ASSERT_NO_FATAL_FAILURE(SetupMappings(num_hosts, domains, &mappings));
213 ASSERT_NO_FATAL_FAILURE(SetupDNSServers(MAXNS, mappings, &dns, &servers));
214
Pierre Imai0452cb52016-05-30 16:42:34 +0900215 ASSERT_TRUE(SetResolversForNetwork(servers, domains, mDefaultParams_Binder));
Pierre Imaibeedec32016-04-13 06:44:51 +0900216
217 auto t0 = std::chrono::steady_clock::now();
218 std::vector<std::thread> threads(num_threads);
219 for (std::thread& thread : threads) {
220 thread = std::thread([this, &servers, &dns, &mappings, num_queries]() {
221 for (unsigned i = 0 ; i < num_queries ; ++i) {
222 uint32_t ofs = arc4random_uniform(mappings.size());
Robin Leed67c77f2016-09-15 10:55:25 +0900223 auto& mapping = mappings[ofs];
Pierre Imaibeedec32016-04-13 06:44:51 +0900224 addrinfo* result = nullptr;
225 int rv = getaddrinfo(mapping.host.c_str(), nullptr, nullptr, &result);
226 EXPECT_EQ(0, rv) << "error [" << rv << "] " << gai_strerror(rv);
227 if (rv == 0) {
228 std::string result_str = ToString(result);
229 EXPECT_TRUE(result_str == mapping.ip4 || result_str == mapping.ip6)
230 << "result='" << result_str << "', ip4='" << mapping.ip4
231 << "', ip6='" << mapping.ip6;
232 }
233 if (result) {
234 freeaddrinfo(result);
235 result = nullptr;
236 }
237 }
238 });
239 }
240
241 for (std::thread& thread : threads) {
242 thread.join();
243 }
244 auto t1 = std::chrono::steady_clock::now();
245 ALOGI("%u hosts, %u threads, %u queries, %Es", num_hosts, num_threads, num_queries,
246 std::chrono::duration<double>(t1 - t0).count());
247 ASSERT_NO_FATAL_FAILURE(ShutdownDNSServers(&dns));
248 }
249
Pierre Imai95f5f942016-03-09 18:09:25 +0900250 const std::vector<std::string> mDefaultSearchDomains = { "example.com" };
251 // <sample validity in s> <success threshold in percent> <min samples> <max samples>
252 const std::string mDefaultParams = "300 25 8 8";
Pierre Imai0452cb52016-05-30 16:42:34 +0900253 const std::vector<int> mDefaultParams_Binder = { 300, 25, 8, 8 };
Pierre Imai904ce3a2016-02-18 13:13:12 +0900254};
255
Pierre Imai904ce3a2016-02-18 13:13:12 +0900256TEST_F(ResolverTest, GetHostByName) {
257 const char* listen_addr = "127.0.0.3";
258 const char* listen_srv = "53";
Pierre Imai95f5f942016-03-09 18:09:25 +0900259 const char* host_name = "hello.example.com.";
260 test::DNSResponder dns(listen_addr, listen_srv, 250, ns_rcode::ns_r_servfail, 1.0);
261 dns.addMapping(host_name, ns_type::ns_t_a, "1.2.3.3");
262 ASSERT_TRUE(dns.startServer());
263 std::vector<std::string> servers = { listen_addr };
264 ASSERT_TRUE(SetResolversForNetwork(mDefaultSearchDomains, servers, mDefaultParams));
Pierre Imai904ce3a2016-02-18 13:13:12 +0900265
Pierre Imai95f5f942016-03-09 18:09:25 +0900266 dns.clearQueries();
Pierre Imai904ce3a2016-02-18 13:13:12 +0900267 const hostent* result = gethostbyname("hello");
Pierre Imai95f5f942016-03-09 18:09:25 +0900268 EXPECT_EQ(1U, GetNumQueriesForType(dns, ns_type::ns_t_a, host_name));
Pierre Imai904ce3a2016-02-18 13:13:12 +0900269 ASSERT_FALSE(result == nullptr);
270 ASSERT_EQ(4, result->h_length);
271 ASSERT_FALSE(result->h_addr_list[0] == nullptr);
Pierre Imai95f5f942016-03-09 18:09:25 +0900272 EXPECT_EQ("1.2.3.3", ToString(result));
Pierre Imai904ce3a2016-02-18 13:13:12 +0900273 EXPECT_TRUE(result->h_addr_list[1] == nullptr);
Pierre Imai95f5f942016-03-09 18:09:25 +0900274 dns.stopServer();
Pierre Imai904ce3a2016-02-18 13:13:12 +0900275}
276
Pierre Imaibeedec32016-04-13 06:44:51 +0900277TEST_F(ResolverTest, TestBinderSerialization) {
278 using android::net::INetd;
279 std::vector<int> params_offsets = {
280 INetd::RESOLVER_PARAMS_SAMPLE_VALIDITY,
281 INetd::RESOLVER_PARAMS_SUCCESS_THRESHOLD,
282 INetd::RESOLVER_PARAMS_MIN_SAMPLES,
283 INetd::RESOLVER_PARAMS_MAX_SAMPLES
284 };
285 int size = static_cast<int>(params_offsets.size());
286 EXPECT_EQ(size, INetd::RESOLVER_PARAMS_COUNT);
287 std::sort(params_offsets.begin(), params_offsets.end());
288 for (int i = 0 ; i < size ; ++i) {
289 EXPECT_EQ(params_offsets[i], i);
290 }
291}
292
293TEST_F(ResolverTest, GetHostByName_Binder) {
294 using android::net::INetd;
295
296 std::vector<std::string> domains = { "example.com" };
297 std::vector<std::unique_ptr<test::DNSResponder>> dns;
298 std::vector<std::string> servers;
299 std::vector<Mapping> mappings;
300 ASSERT_NO_FATAL_FAILURE(SetupMappings(1, domains, &mappings));
301 ASSERT_NO_FATAL_FAILURE(SetupDNSServers(4, mappings, &dns, &servers));
302 ASSERT_EQ(1U, mappings.size());
303 const Mapping& mapping = mappings[0];
304
Pierre Imai0452cb52016-05-30 16:42:34 +0900305 ASSERT_TRUE(SetResolversForNetwork(servers, domains, mDefaultParams_Binder));
Pierre Imaibeedec32016-04-13 06:44:51 +0900306
307 const hostent* result = gethostbyname(mapping.host.c_str());
308 size_t total_queries = std::accumulate(dns.begin(), dns.end(), 0,
309 [this, &mapping](size_t total, auto& d) {
310 return total + GetNumQueriesForType(*d, ns_type::ns_t_a, mapping.entry.c_str());
311 });
312
313 EXPECT_LE(1U, total_queries);
314 ASSERT_FALSE(result == nullptr);
315 ASSERT_EQ(4, result->h_length);
316 ASSERT_FALSE(result->h_addr_list[0] == nullptr);
317 EXPECT_EQ(mapping.ip4, ToString(result));
318 EXPECT_TRUE(result->h_addr_list[1] == nullptr);
319
320 std::vector<std::string> res_servers;
321 std::vector<std::string> res_domains;
322 __res_params res_params;
323 std::vector<ResolverStats> res_stats;
324 ASSERT_TRUE(GetResolverInfo(&res_servers, &res_domains, &res_params, &res_stats));
325 EXPECT_EQ(servers.size(), res_servers.size());
326 EXPECT_EQ(domains.size(), res_domains.size());
Pierre Imai0452cb52016-05-30 16:42:34 +0900327 ASSERT_EQ(INetd::RESOLVER_PARAMS_COUNT, mDefaultParams_Binder.size());
328 EXPECT_EQ(mDefaultParams_Binder[INetd::RESOLVER_PARAMS_SAMPLE_VALIDITY],
329 res_params.sample_validity);
330 EXPECT_EQ(mDefaultParams_Binder[INetd::RESOLVER_PARAMS_SUCCESS_THRESHOLD],
331 res_params.success_threshold);
332 EXPECT_EQ(mDefaultParams_Binder[INetd::RESOLVER_PARAMS_MIN_SAMPLES], res_params.min_samples);
333 EXPECT_EQ(mDefaultParams_Binder[INetd::RESOLVER_PARAMS_MAX_SAMPLES], res_params.max_samples);
Pierre Imaibeedec32016-04-13 06:44:51 +0900334 EXPECT_EQ(servers.size(), res_stats.size());
335
336 EXPECT_TRUE(UnorderedCompareArray(res_servers, servers));
337 EXPECT_TRUE(UnorderedCompareArray(res_domains, domains));
338
339 ASSERT_NO_FATAL_FAILURE(ShutdownDNSServers(&dns));
340}
341
Pierre Imai904ce3a2016-02-18 13:13:12 +0900342TEST_F(ResolverTest, GetAddrInfo) {
343 addrinfo* result = nullptr;
344
345 const char* listen_addr = "127.0.0.4";
Pierre Imai6f4f86d2016-04-08 13:15:27 +0900346 const char* listen_addr2 = "127.0.0.5";
Pierre Imai904ce3a2016-02-18 13:13:12 +0900347 const char* listen_srv = "53";
Pierre Imaibeedec32016-04-13 06:44:51 +0900348 const char* host_name = "howdy.example.com.";
Pierre Imai95f5f942016-03-09 18:09:25 +0900349 test::DNSResponder dns(listen_addr, listen_srv, 250,
350 ns_rcode::ns_r_servfail, 1.0);
351 dns.addMapping(host_name, ns_type::ns_t_a, "1.2.3.4");
352 dns.addMapping(host_name, ns_type::ns_t_aaaa, "::1.2.3.4");
353 ASSERT_TRUE(dns.startServer());
Pierre Imai904ce3a2016-02-18 13:13:12 +0900354
Pierre Imai6f4f86d2016-04-08 13:15:27 +0900355 test::DNSResponder dns2(listen_addr2, listen_srv, 250,
356 ns_rcode::ns_r_servfail, 1.0);
357 dns2.addMapping(host_name, ns_type::ns_t_a, "1.2.3.4");
358 dns2.addMapping(host_name, ns_type::ns_t_aaaa, "::1.2.3.4");
359 ASSERT_TRUE(dns2.startServer());
Pierre Imai6f4f86d2016-04-08 13:15:27 +0900360
Pierre Imai3a272072016-04-19 16:17:07 +0900361 for (size_t i = 0 ; i < 1000 ; ++i) {
362 std::vector<std::string> servers = { listen_addr };
363 ASSERT_TRUE(SetResolversForNetwork(mDefaultSearchDomains, servers, mDefaultParams));
364 dns.clearQueries();
365 dns2.clearQueries();
366
367 EXPECT_EQ(0, getaddrinfo("howdy", nullptr, nullptr, &result));
368 size_t found = GetNumQueries(dns, host_name);
369 EXPECT_LE(1U, found);
370 // Could be A or AAAA
371 std::string result_str = ToString(result);
372 EXPECT_TRUE(result_str == "1.2.3.4" || result_str == "::1.2.3.4")
373 << ", result_str='" << result_str << "'";
374 // TODO: Use ScopedAddrinfo or similar once it is available in a common header file.
375 if (result) {
376 freeaddrinfo(result);
377 result = nullptr;
378 }
379
380 // Verify that the name is cached.
381 size_t old_found = found;
382 EXPECT_EQ(0, getaddrinfo("howdy", nullptr, nullptr, &result));
383 found = GetNumQueries(dns, host_name);
384 EXPECT_LE(1U, found);
385 EXPECT_EQ(old_found, found);
386 result_str = ToString(result);
387 EXPECT_TRUE(result_str == "1.2.3.4" || result_str == "::1.2.3.4")
388 << result_str;
389 if (result) {
390 freeaddrinfo(result);
391 result = nullptr;
392 }
393
394 // Change the DNS resolver, ensure that queries are no longer cached.
395 servers = { listen_addr2 };
396 ASSERT_TRUE(SetResolversForNetwork(mDefaultSearchDomains, servers, mDefaultParams));
397 dns.clearQueries();
398 dns2.clearQueries();
399
400 EXPECT_EQ(0, getaddrinfo("howdy", nullptr, nullptr, &result));
401 found = GetNumQueries(dns, host_name);
402 size_t found2 = GetNumQueries(dns2, host_name);
403 EXPECT_EQ(0U, found);
404 EXPECT_LE(1U, found2);
405
406 // Could be A or AAAA
407 result_str = ToString(result);
408 EXPECT_TRUE(result_str == "1.2.3.4" || result_str == "::1.2.3.4")
409 << ", result_str='" << result_str << "'";
410 if (result) {
411 freeaddrinfo(result);
412 result = nullptr;
413 }
Pierre Imaibeedec32016-04-13 06:44:51 +0900414 }
Pierre Imai6f4f86d2016-04-08 13:15:27 +0900415 dns.stopServer();
416 dns2.stopServer();
Pierre Imai904ce3a2016-02-18 13:13:12 +0900417}
418
419TEST_F(ResolverTest, GetAddrInfoV4) {
420 addrinfo* result = nullptr;
421
422 const char* listen_addr = "127.0.0.5";
423 const char* listen_srv = "53";
Pierre Imai95f5f942016-03-09 18:09:25 +0900424 const char* host_name = "hola.example.com.";
425 test::DNSResponder dns(listen_addr, listen_srv, 250,
426 ns_rcode::ns_r_servfail, 1.0);
427 dns.addMapping(host_name, ns_type::ns_t_a, "1.2.3.5");
428 ASSERT_TRUE(dns.startServer());
429 std::vector<std::string> servers = { listen_addr };
430 ASSERT_TRUE(SetResolversForNetwork(mDefaultSearchDomains, servers, mDefaultParams));
Pierre Imai904ce3a2016-02-18 13:13:12 +0900431
432 addrinfo hints;
433 memset(&hints, 0, sizeof(hints));
434 hints.ai_family = AF_INET;
435 EXPECT_EQ(0, getaddrinfo("hola", nullptr, &hints, &result));
Pierre Imai95f5f942016-03-09 18:09:25 +0900436 EXPECT_EQ(1U, GetNumQueries(dns, host_name));
Pierre Imaiccf7b992016-02-25 16:34:29 +0900437 EXPECT_EQ("1.2.3.5", ToString(result));
Pierre Imaibeedec32016-04-13 06:44:51 +0900438 if (result) {
439 freeaddrinfo(result);
440 result = nullptr;
441 }
Pierre Imai904ce3a2016-02-18 13:13:12 +0900442}
Pierre Imai95f5f942016-03-09 18:09:25 +0900443
444TEST_F(ResolverTest, MultidomainResolution) {
445 std::vector<std::string> searchDomains = { "example1.com", "example2.com", "example3.com" };
446 const char* listen_addr = "127.0.0.6";
447 const char* listen_srv = "53";
448 const char* host_name = "nihao.example2.com.";
449 test::DNSResponder dns(listen_addr, listen_srv, 250,
450 ns_rcode::ns_r_servfail, 1.0);
451 dns.addMapping(host_name, ns_type::ns_t_a, "1.2.3.3");
452 ASSERT_TRUE(dns.startServer());
453 std::vector<std::string> servers = { listen_addr };
454 ASSERT_TRUE(SetResolversForNetwork(searchDomains, servers, mDefaultParams));
455
456 dns.clearQueries();
457 const hostent* result = gethostbyname("nihao");
458 EXPECT_EQ(1U, GetNumQueriesForType(dns, ns_type::ns_t_a, host_name));
459 ASSERT_FALSE(result == nullptr);
460 ASSERT_EQ(4, result->h_length);
461 ASSERT_FALSE(result->h_addr_list[0] == nullptr);
462 EXPECT_EQ("1.2.3.3", ToString(result));
463 EXPECT_TRUE(result->h_addr_list[1] == nullptr);
464 dns.stopServer();
465}
466
467TEST_F(ResolverTest, GetAddrInfoV6_failing) {
468 addrinfo* result = nullptr;
469
470 const char* listen_addr0 = "127.0.0.7";
471 const char* listen_addr1 = "127.0.0.8";
472 const char* listen_srv = "53";
473 const char* host_name = "ohayou.example.com.";
474 test::DNSResponder dns0(listen_addr0, listen_srv, 250,
475 ns_rcode::ns_r_servfail, 0.0);
476 test::DNSResponder dns1(listen_addr1, listen_srv, 250,
477 ns_rcode::ns_r_servfail, 1.0);
478 dns0.addMapping(host_name, ns_type::ns_t_aaaa, "2001:db8::5");
479 dns1.addMapping(host_name, ns_type::ns_t_aaaa, "2001:db8::6");
480 ASSERT_TRUE(dns0.startServer());
481 ASSERT_TRUE(dns1.startServer());
482 std::vector<std::string> servers = { listen_addr0, listen_addr1 };
483 // <sample validity in s> <success threshold in percent> <min samples> <max samples>
484 unsigned sample_validity = 300;
485 int success_threshold = 25;
486 int sample_count = 8;
487 std::string params = StringPrintf("%u %d %d %d", sample_validity, success_threshold,
488 sample_count, sample_count);
489 ASSERT_TRUE(SetResolversForNetwork(mDefaultSearchDomains, servers, params));
490
491 // Repeatedly perform resolutions for non-existing domains until MAXNSSAMPLES resolutions have
492 // reached the dns0, which is set to fail. No more requests should then arrive at that server
493 // for the next sample_lifetime seconds.
494 // TODO: This approach is implementation-dependent, change once metrics reporting is available.
495 addrinfo hints;
496 memset(&hints, 0, sizeof(hints));
497 hints.ai_family = AF_INET6;
498 for (int i = 0 ; i < sample_count ; ++i) {
499 std::string domain = StringPrintf("nonexistent%d", i);
500 getaddrinfo(domain.c_str(), nullptr, &hints, &result);
Pierre Imaibeedec32016-04-13 06:44:51 +0900501 if (result) {
502 freeaddrinfo(result);
503 result = nullptr;
504 }
Pierre Imai95f5f942016-03-09 18:09:25 +0900505 }
506 // Due to 100% errors for all possible samples, the server should be ignored from now on and
507 // only the second one used for all following queries, until NSSAMPLE_VALIDITY is reached.
508 dns0.clearQueries();
509 dns1.clearQueries();
510 EXPECT_EQ(0, getaddrinfo("ohayou", nullptr, &hints, &result));
511 EXPECT_EQ(0U, GetNumQueries(dns0, host_name));
512 EXPECT_EQ(1U, GetNumQueries(dns1, host_name));
Pierre Imaibeedec32016-04-13 06:44:51 +0900513 if (result) {
514 freeaddrinfo(result);
515 result = nullptr;
516 }
Pierre Imai95f5f942016-03-09 18:09:25 +0900517}
518
519TEST_F(ResolverTest, GetAddrInfoV6_concurrent) {
520 const char* listen_addr0 = "127.0.0.9";
521 const char* listen_addr1 = "127.0.0.10";
522 const char* listen_addr2 = "127.0.0.11";
523 const char* listen_srv = "53";
524 const char* host_name = "konbanha.example.com.";
525 test::DNSResponder dns0(listen_addr0, listen_srv, 250,
526 ns_rcode::ns_r_servfail, 1.0);
527 test::DNSResponder dns1(listen_addr1, listen_srv, 250,
528 ns_rcode::ns_r_servfail, 1.0);
529 test::DNSResponder dns2(listen_addr2, listen_srv, 250,
530 ns_rcode::ns_r_servfail, 1.0);
531 dns0.addMapping(host_name, ns_type::ns_t_aaaa, "2001:db8::5");
532 dns1.addMapping(host_name, ns_type::ns_t_aaaa, "2001:db8::6");
533 dns2.addMapping(host_name, ns_type::ns_t_aaaa, "2001:db8::7");
534 ASSERT_TRUE(dns0.startServer());
535 ASSERT_TRUE(dns1.startServer());
536 ASSERT_TRUE(dns2.startServer());
537 const std::vector<std::string> servers = { listen_addr0, listen_addr1, listen_addr2 };
538 std::vector<std::thread> threads(10);
539 for (std::thread& thread : threads) {
540 thread = std::thread([this, &servers, &dns0, &dns1, &dns2]() {
541 unsigned delay = arc4random_uniform(1*1000*1000); // <= 1s
542 usleep(delay);
543 std::vector<std::string> serverSubset;
544 for (const auto& server : servers) {
545 if (arc4random_uniform(2)) {
546 serverSubset.push_back(server);
547 }
548 }
549 if (serverSubset.empty()) serverSubset = servers;
550 ASSERT_TRUE(SetResolversForNetwork(mDefaultSearchDomains, serverSubset,
551 mDefaultParams));
552 addrinfo hints;
553 memset(&hints, 0, sizeof(hints));
554 hints.ai_family = AF_INET6;
555 addrinfo* result = nullptr;
556 int rv = getaddrinfo("konbanha", nullptr, &hints, &result);
557 EXPECT_EQ(0, rv) << "error [" << rv << "] " << gai_strerror(rv);
Pierre Imaibeedec32016-04-13 06:44:51 +0900558 if (result) {
559 freeaddrinfo(result);
560 result = nullptr;
561 }
Pierre Imai95f5f942016-03-09 18:09:25 +0900562 });
563 }
564 for (std::thread& thread : threads) {
565 thread.join();
566 }
567}
Pierre Imaibeedec32016-04-13 06:44:51 +0900568
569TEST_F(ResolverTest, GetAddrInfoStressTest_Binder_100) {
570 const unsigned num_hosts = 100;
571 const unsigned num_threads = 100;
572 const unsigned num_queries = 100;
573 ASSERT_NO_FATAL_FAILURE(RunGetAddrInfoStressTest_Binder(num_hosts, num_threads, num_queries));
574}
575
576TEST_F(ResolverTest, GetAddrInfoStressTest_Binder_100000) {
577 const unsigned num_hosts = 100000;
578 const unsigned num_threads = 100;
579 const unsigned num_queries = 100;
580 ASSERT_NO_FATAL_FAILURE(RunGetAddrInfoStressTest_Binder(num_hosts, num_threads, num_queries));
581}
582
583TEST_F(ResolverTest, EmptySetup) {
584 using android::net::INetd;
585 std::vector<std::string> servers;
586 std::vector<std::string> domains;
Pierre Imai0452cb52016-05-30 16:42:34 +0900587 ASSERT_TRUE(SetResolversForNetwork(servers, domains, mDefaultParams_Binder));
Pierre Imaibeedec32016-04-13 06:44:51 +0900588 std::vector<std::string> res_servers;
589 std::vector<std::string> res_domains;
590 __res_params res_params;
591 std::vector<ResolverStats> res_stats;
592 ASSERT_TRUE(GetResolverInfo(&res_servers, &res_domains, &res_params, &res_stats));
593 EXPECT_EQ(0U, res_servers.size());
594 EXPECT_EQ(0U, res_domains.size());
Pierre Imai0452cb52016-05-30 16:42:34 +0900595 ASSERT_EQ(INetd::RESOLVER_PARAMS_COUNT, mDefaultParams_Binder.size());
596 EXPECT_EQ(mDefaultParams_Binder[INetd::RESOLVER_PARAMS_SAMPLE_VALIDITY],
597 res_params.sample_validity);
598 EXPECT_EQ(mDefaultParams_Binder[INetd::RESOLVER_PARAMS_SUCCESS_THRESHOLD],
599 res_params.success_threshold);
600 EXPECT_EQ(mDefaultParams_Binder[INetd::RESOLVER_PARAMS_MIN_SAMPLES], res_params.min_samples);
601 EXPECT_EQ(mDefaultParams_Binder[INetd::RESOLVER_PARAMS_MAX_SAMPLES], res_params.max_samples);
Pierre Imaibeedec32016-04-13 06:44:51 +0900602}
Pierre Imaiee335ef2016-05-06 11:56:45 +0900603
604TEST_F(ResolverTest, SearchPathChange) {
605 addrinfo* result = nullptr;
606
607 const char* listen_addr = "127.0.0.13";
608 const char* listen_srv = "53";
609 const char* host_name1 = "test13.domain1.org.";
610 const char* host_name2 = "test13.domain2.org.";
611 test::DNSResponder dns(listen_addr, listen_srv, 250,
612 ns_rcode::ns_r_servfail, 1.0);
613 dns.addMapping(host_name1, ns_type::ns_t_aaaa, "2001:db8::13");
614 dns.addMapping(host_name2, ns_type::ns_t_aaaa, "2001:db8::1:13");
615 ASSERT_TRUE(dns.startServer());
616 std::vector<std::string> servers = { listen_addr };
617 std::vector<std::string> domains = { "domain1.org" };
618 ASSERT_TRUE(SetResolversForNetwork(domains, servers, mDefaultParams));
619
620 addrinfo hints;
621 memset(&hints, 0, sizeof(hints));
622 hints.ai_family = AF_INET6;
623 EXPECT_EQ(0, getaddrinfo("test13", nullptr, &hints, &result));
624 EXPECT_EQ(1U, dns.queries().size());
625 EXPECT_EQ(1U, GetNumQueries(dns, host_name1));
626 EXPECT_EQ("2001:db8::13", ToString(result));
627 if (result) freeaddrinfo(result);
628
629 // Test that changing the domain search path on its own works.
630 domains = { "domain2.org" };
631 ASSERT_TRUE(SetResolversForNetwork(domains, servers, mDefaultParams));
632 dns.clearQueries();
633
634 EXPECT_EQ(0, getaddrinfo("test13", nullptr, &hints, &result));
635 EXPECT_EQ(1U, dns.queries().size());
636 EXPECT_EQ(1U, GetNumQueries(dns, host_name2));
637 EXPECT_EQ("2001:db8::1:13", ToString(result));
638 if (result) freeaddrinfo(result);
639}
Pierre Imai0452cb52016-05-30 16:42:34 +0900640
641TEST_F(ResolverTest, MaxServerPrune_Binder) {
642 using android::net::INetd;
643
644 std::vector<std::string> domains = { "example.com" };
645 std::vector<std::unique_ptr<test::DNSResponder>> dns;
646 std::vector<std::string> servers;
647 std::vector<Mapping> mappings;
648 ASSERT_NO_FATAL_FAILURE(SetupMappings(1, domains, &mappings));
649 ASSERT_NO_FATAL_FAILURE(SetupDNSServers(MAXNS + 1, mappings, &dns, &servers));
650
651 ASSERT_TRUE(SetResolversForNetwork(servers, domains, mDefaultParams_Binder));
652
653 std::vector<std::string> res_servers;
654 std::vector<std::string> res_domains;
655 __res_params res_params;
656 std::vector<ResolverStats> res_stats;
657 ASSERT_TRUE(GetResolverInfo(&res_servers, &res_domains, &res_params, &res_stats));
658 EXPECT_EQ(static_cast<size_t>(MAXNS), res_servers.size());
659
660 ASSERT_NO_FATAL_FAILURE(ShutdownDNSServers(&dns));
661}