1 /*
2 * Copyright (C) 2018 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
17 #define LOG_TAG "resolv"
18
19 #include <aidl/android/net/IDnsResolver.h>
20 #include <android-base/stringprintf.h>
21 #include <arpa/inet.h>
22 #include <gmock/gmock-matchers.h>
23 #include <gtest/gtest.h>
24 #include <netdb.h>
25 #include <netdutils/InternetAddresses.h>
26 #include <resolv_stats_test_utils.h>
27
28 #include "dns_responder.h"
29 #include "getaddrinfo.h"
30 #include "gethnamaddr.h"
31 #include "resolv_cache.h"
32 #include "stats.pb.h"
33 #include "tests/resolv_test_utils.h"
34
35 #define NAME(variable) #variable
36
37 namespace android {
38 namespace net {
39
40 using aidl::android::net::IDnsResolver;
41 using android::base::StringPrintf;
42 using android::net::NetworkDnsEventReported;
43 using android::netdutils::ScopedAddrinfo;
44
45 // The buffer size of resolv_gethostbyname().
46 constexpr unsigned int MAXPACKET = 8 * 1024;
47
48 // Specifying 0 in ai_socktype or ai_protocol of struct addrinfo indicates
49 // that any type or protocol can be returned by getaddrinfo().
50 constexpr unsigned int ANY = 0;
51
52 class TestBase : public ::testing::Test {
53 protected:
54 struct DnsMessage {
55 std::string host_name; // host name
56 ns_type type; // record type
57 test::DNSHeader header; // dns header
58 };
59
SetUp()60 void SetUp() override {
61 // Create cache for test
62 resolv_create_cache_for_net(TEST_NETID);
63 }
TearDown()64 void TearDown() override {
65 // Delete cache for test
66 resolv_delete_cache_for_net(TEST_NETID);
67 }
68
MakeAnswerRecord(const std::string & name,unsigned rclass,unsigned rtype,const std::string & rdata,unsigned ttl=kAnswerRecordTtlSec)69 test::DNSRecord MakeAnswerRecord(const std::string& name, unsigned rclass, unsigned rtype,
70 const std::string& rdata, unsigned ttl = kAnswerRecordTtlSec) {
71 test::DNSRecord record{
72 .name = {.name = name},
73 .rtype = rtype,
74 .rclass = rclass,
75 .ttl = ttl,
76 };
77 EXPECT_TRUE(test::DNSResponder::fillRdata(rdata, record));
78 return record;
79 }
80
MakeDnsMessage(const std::string & qname,ns_type qtype,const std::vector<std::string> & rdata)81 DnsMessage MakeDnsMessage(const std::string& qname, ns_type qtype,
82 const std::vector<std::string>& rdata) {
83 const unsigned qclass = ns_c_in;
84 // Build a DNSHeader in the following format.
85 // Question
86 // <qname> IN <qtype>
87 // Answer
88 // <qname> IN <qtype> <rdata[0]>
89 // ..
90 // <qname> IN <qtype> <rdata[n]>
91 //
92 // Example:
93 // Question
94 // hello.example.com. IN A
95 // Answer
96 // hello.example.com. IN A 1.2.3.1
97 // ..
98 // hello.example.com. IN A 1.2.3.9
99 test::DNSHeader header(kDefaultDnsHeader);
100
101 // Question section
102 test::DNSQuestion question{
103 .qname = {.name = qname},
104 .qtype = qtype,
105 .qclass = qclass,
106 };
107 header.questions.push_back(std::move(question));
108
109 // Answer section
110 for (const auto& r : rdata) {
111 test::DNSRecord record = MakeAnswerRecord(qname, qclass, qtype, r);
112 header.answers.push_back(std::move(record));
113 }
114 // TODO: Perhaps add support for authority RRs and additional RRs.
115 return {qname, qtype, header};
116 }
117
StartDns(test::DNSResponder & dns,const std::vector<DnsMessage> & messages)118 void StartDns(test::DNSResponder& dns, const std::vector<DnsMessage>& messages) {
119 for (const auto& m : messages) {
120 dns.addMappingDnsHeader(m.host_name, m.type, m.header);
121 }
122 ASSERT_TRUE(dns.startServer());
123 dns.clearQueries();
124 }
125
SetResolvers()126 int SetResolvers() { return SetResolvers(servers); }
127
SetResolvers(std::vector<std::string> servers)128 int SetResolvers(std::vector<std::string> servers) {
129 return resolv_set_nameservers(TEST_NETID, servers, domains, params, std::nullopt);
130 }
131
132 const android_net_context mNetcontext = {
133 .app_netid = TEST_NETID,
134 .app_mark = MARK_UNSET,
135 .dns_netid = TEST_NETID,
136 .dns_mark = MARK_UNSET,
137 .uid = NET_CONTEXT_INVALID_UID,
138 };
139 const std::vector<std::string> servers = {test::kDefaultListenAddr};
140 const std::vector<std::string> domains = {"example.com"};
141 const res_params params = {
142 .sample_validity = 300,
143 .success_threshold = 25,
144 .min_samples = 8,
145 .max_samples = 8,
146 .base_timeout_msec = 1000,
147 .retry_count = 2,
148 };
149 };
150
151 class ResolvGetAddrInfoTest : public TestBase {};
152 class GetHostByNameForNetContextTest : public TestBase {};
153 class ResolvCommonFunctionTest : public TestBase {};
154
TEST_F(ResolvGetAddrInfoTest,InvalidParameters)155 TEST_F(ResolvGetAddrInfoTest, InvalidParameters) {
156 // Both null "netcontext" and null "res" of resolv_getaddrinfo() are not tested
157 // here because they are checked by assert() without returning any error number.
158
159 // Invalid hostname and servname.
160 // Both hostname and servname are null pointers. Expect error number EAI_NONAME.
161 {
162 addrinfo* result = nullptr;
163 NetworkDnsEventReported event;
164 int rv = resolv_getaddrinfo(nullptr /*hostname*/, nullptr /*servname*/, nullptr /*hints*/,
165 &mNetcontext, &result, &event);
166 ScopedAddrinfo result_cleanup(result);
167 EXPECT_EQ(EAI_NONAME, rv);
168 }
169
170 // Invalid hints.
171 // These place holders are used to test function call with unrequired parameters.
172 // The content is not important because function call returns error directly if
173 // there have any unrequired parameter.
174 char placeholder_cname[] = "invalid_cname";
175 sockaddr placeholder_addr = {};
176 addrinfo placeholder_next = {};
177 static const struct TestConfig {
178 int ai_flags;
179 socklen_t ai_addrlen;
180 char* ai_canonname;
181 sockaddr* ai_addr;
182 addrinfo* ai_next;
183
184 int expected_eai_error;
185
186 std::string asParameters() const {
187 return StringPrintf("0x%x/%u/%s/%p/%p", ai_flags, ai_addrlen,
188 ai_canonname ? ai_canonname : "(null)", (void*)ai_addr,
189 (void*)ai_next);
190 }
191 } testConfigs[]{
192 {0, sizeof(in_addr) /*bad*/, nullptr, nullptr, nullptr, EAI_BADHINTS},
193 {0, 0, placeholder_cname /*bad*/, nullptr, nullptr, EAI_BADHINTS},
194 {0, 0, nullptr, &placeholder_addr /*bad*/, nullptr, EAI_BADHINTS},
195 {0, 0, nullptr, nullptr, &placeholder_next /*bad*/, EAI_BADHINTS},
196 {AI_ALL /*bad*/, 0, nullptr, nullptr, nullptr, EAI_BADFLAGS},
197 {AI_V4MAPPED_CFG /*bad*/, 0, nullptr, nullptr, nullptr, EAI_BADFLAGS},
198 {AI_V4MAPPED /*bad*/, 0, nullptr, nullptr, nullptr, EAI_BADFLAGS},
199 {AI_DEFAULT /*bad*/, 0, nullptr, nullptr, nullptr, EAI_BADFLAGS},
200 };
201
202 for (const auto& config : testConfigs) {
203 SCOPED_TRACE(config.asParameters());
204
205 addrinfo* result = nullptr;
206 // In current test configuration set, ai_family, ai_protocol and ai_socktype are not
207 // checked because other fields cause hints error check failed first.
208 const addrinfo hints = {
209 .ai_flags = config.ai_flags,
210 .ai_family = AF_UNSPEC,
211 .ai_socktype = ANY,
212 .ai_protocol = ANY,
213 .ai_addrlen = config.ai_addrlen,
214 .ai_canonname = config.ai_canonname,
215 .ai_addr = config.ai_addr,
216 .ai_next = config.ai_next,
217 };
218 NetworkDnsEventReported event;
219 int rv = resolv_getaddrinfo("localhost", nullptr /*servname*/, &hints, &mNetcontext,
220 &result, &event);
221 ScopedAddrinfo result_cleanup(result);
222 EXPECT_EQ(config.expected_eai_error, rv);
223 }
224 }
225
TEST_F(ResolvGetAddrInfoTest,InvalidParameters_Family)226 TEST_F(ResolvGetAddrInfoTest, InvalidParameters_Family) {
227 for (int family = 0; family < AF_MAX; ++family) {
228 if (family == AF_UNSPEC || family == AF_INET || family == AF_INET6) {
229 continue; // skip supported family
230 }
231 SCOPED_TRACE(StringPrintf("family: %d", family));
232
233 addrinfo* result = nullptr;
234 const addrinfo hints = {
235 .ai_family = family, // unsupported family
236 };
237 NetworkDnsEventReported event;
238 int rv = resolv_getaddrinfo("localhost", nullptr /*servname*/, &hints, &mNetcontext,
239 &result, &event);
240 ScopedAddrinfo result_cleanup(result);
241 EXPECT_EQ(EAI_FAMILY, rv);
242 }
243 }
244
TEST_F(ResolvGetAddrInfoTest,InvalidParameters_SocketType)245 TEST_F(ResolvGetAddrInfoTest, InvalidParameters_SocketType) {
246 for (const auto& family : {AF_INET, AF_INET6, AF_UNSPEC}) {
247 for (int protocol = 0; protocol < IPPROTO_MAX; ++protocol) {
248 // Socket types which are not in explore_options.
249 for (const auto& socktype : {SOCK_RDM, SOCK_SEQPACKET, SOCK_DCCP, SOCK_PACKET}) {
250 const addrinfo hints = {
251 .ai_family = family,
252 .ai_socktype = socktype,
253 .ai_protocol = protocol,
254 };
255 for (const char* service : {static_cast<const char*>(nullptr), // service is null
256 "80",
257 "", // empty service name
258 "ftp",
259 "65536", // out of valid port range from 0 to 65535
260 "invalid"}) {
261 SCOPED_TRACE(StringPrintf("family: %d, socktype: %d, protocol: %d, service: %s",
262 family, socktype, protocol,
263 service ? service : "service is nullptr"));
264 addrinfo* result = nullptr;
265 NetworkDnsEventReported event;
266 int rv = resolv_getaddrinfo("localhost", service, &hints, &mNetcontext, &result,
267 &event);
268 ScopedAddrinfo result_cleanup(result);
269 EXPECT_EQ(EAI_SOCKTYPE, rv);
270 }
271 }
272 }
273 }
274 }
275
TEST_F(ResolvGetAddrInfoTest,InvalidParameters_MeaningfulSocktypeAndProtocolCombination)276 TEST_F(ResolvGetAddrInfoTest, InvalidParameters_MeaningfulSocktypeAndProtocolCombination) {
277 static const int families[] = {PF_INET, PF_INET6, PF_UNSPEC};
278 // Skip to test socket type SOCK_RAW in meaningful combination (explore_options[]) of
279 // system\netd\resolv\getaddrinfo.cpp. In explore_options[], the socket type SOCK_RAW always
280 // comes with protocol ANY which causes skipping meaningful socktype/protocol combination
281 // check. So it nerver returns error number EAI_BADHINTS which we want to test in this test
282 // case.
283 static const int socktypes[] = {SOCK_STREAM, SOCK_DGRAM};
284
285 // If both socktype/protocol are specified, check non-meaningful combination returns
286 // expected error number EAI_BADHINTS. See meaningful combination in explore_options[] of
287 // system\netd\resolv\getaddrinfo.cpp.
288 for (const auto& family : families) {
289 for (const auto& socktype : socktypes) {
290 for (int protocol = 0; protocol < IPPROTO_MAX; ++protocol) {
291 SCOPED_TRACE(StringPrintf("family: %d, socktype: %d, protocol: %d", family,
292 socktype, protocol));
293
294 // Both socktype/protocol need to be specified.
295 if (!socktype || !protocol) continue;
296
297 // Skip meaningful combination in explore_options[] of
298 // system\netd\resolv\getaddrinfo.cpp.
299 if ((family == AF_INET6 && socktype == SOCK_DGRAM && protocol == IPPROTO_UDP) ||
300 (family == AF_INET6 && socktype == SOCK_STREAM && protocol == IPPROTO_TCP) ||
301 (family == AF_INET && socktype == SOCK_DGRAM && protocol == IPPROTO_UDP) ||
302 (family == AF_INET && socktype == SOCK_STREAM && protocol == IPPROTO_TCP) ||
303 (family == AF_UNSPEC && socktype == SOCK_DGRAM && protocol == IPPROTO_UDP) ||
304 (family == AF_UNSPEC && socktype == SOCK_STREAM && protocol == IPPROTO_TCP)) {
305 continue;
306 }
307
308 addrinfo* result = nullptr;
309 const addrinfo hints = {
310 .ai_family = family,
311 .ai_socktype = socktype,
312 .ai_protocol = protocol,
313 };
314 NetworkDnsEventReported event;
315 int rv = resolv_getaddrinfo("localhost", nullptr /*servname*/, &hints, &mNetcontext,
316 &result, &event);
317 ScopedAddrinfo result_cleanup(result);
318 EXPECT_EQ(EAI_BADHINTS, rv);
319 }
320 }
321 }
322 }
323
324 // The test configs are used for verifying the error path of get_port().
325 // Note that the EAI_SOCKTYPE verification are moved to an independent
326 // test case because validateHints() verify invalid socket type early now.
327 // See also InvalidParameters_SocketType.
TEST_F(ResolvGetAddrInfoTest,InvalidParameters_PortNameAndNumber)328 TEST_F(ResolvGetAddrInfoTest, InvalidParameters_PortNameAndNumber) {
329 constexpr char http_portno[] = "80";
330 constexpr char invalid_portno[] = "65536"; // out of valid port range from 0 to 65535
331 constexpr char http_portname[] = "http";
332 constexpr char invalid_portname[] = "invalid_portname";
333
334 static const struct TestConfig {
335 int ai_flags;
336 int ai_family;
337 int ai_socktype;
338 const char* servname;
339
340 int expected_eai_error;
341
342 std::string asParameters() const {
343 return StringPrintf("0x%x/%d/%d/%s", ai_flags, ai_family, ai_socktype,
344 servname ? servname : "(null)");
345 }
346 } testConfigs[]{
347 {0, AF_INET, SOCK_RAW /*bad*/, http_portno, EAI_SERVICE},
348 {0, AF_INET6, SOCK_RAW /*bad*/, http_portno, EAI_SERVICE},
349 {0, AF_UNSPEC, SOCK_RAW /*bad*/, http_portno, EAI_SERVICE},
350 {0, AF_INET, ANY, invalid_portno /*bad*/, EAI_SERVICE},
351 {0, AF_INET, SOCK_STREAM, invalid_portno /*bad*/, EAI_SERVICE},
352 {0, AF_INET, SOCK_DGRAM, invalid_portno /*bad*/, EAI_SERVICE},
353 {0, AF_INET6, ANY, invalid_portno /*bad*/, EAI_SERVICE},
354 {0, AF_INET6, SOCK_STREAM, invalid_portno /*bad*/, EAI_SERVICE},
355 {0, AF_INET6, SOCK_DGRAM, invalid_portno /*bad*/, EAI_SERVICE},
356 {0, AF_UNSPEC, ANY, invalid_portno /*bad*/, EAI_SERVICE},
357 {0, AF_UNSPEC, SOCK_STREAM, invalid_portno /*bad*/, EAI_SERVICE},
358 {0, AF_UNSPEC, SOCK_DGRAM, invalid_portno /*bad*/, EAI_SERVICE},
359 {AI_NUMERICSERV, AF_INET, ANY, http_portname /*bad*/, EAI_NONAME},
360 {AI_NUMERICSERV, AF_INET, SOCK_STREAM, http_portname /*bad*/, EAI_NONAME},
361 {AI_NUMERICSERV, AF_INET, SOCK_DGRAM, http_portname /*bad*/, EAI_NONAME},
362 {AI_NUMERICSERV, AF_INET6, ANY, http_portname /*bad*/, EAI_NONAME},
363 {AI_NUMERICSERV, AF_INET6, SOCK_STREAM, http_portname /*bad*/, EAI_NONAME},
364 {AI_NUMERICSERV, AF_INET6, SOCK_DGRAM, http_portname /*bad*/, EAI_NONAME},
365 {AI_NUMERICSERV, AF_UNSPEC, ANY, http_portname /*bad*/, EAI_NONAME},
366 {AI_NUMERICSERV, AF_UNSPEC, SOCK_STREAM, http_portname /*bad*/, EAI_NONAME},
367 {AI_NUMERICSERV, AF_UNSPEC, SOCK_DGRAM, http_portname /*bad*/, EAI_NONAME},
368 {0, AF_INET, ANY, invalid_portname /*bad*/, EAI_SERVICE},
369 {0, AF_INET, SOCK_STREAM, invalid_portname /*bad*/, EAI_SERVICE},
370 {0, AF_INET, SOCK_DGRAM, invalid_portname /*bad*/, EAI_SERVICE},
371 {0, AF_INET6, ANY, invalid_portname /*bad*/, EAI_SERVICE},
372 {0, AF_INET6, SOCK_STREAM, invalid_portname /*bad*/, EAI_SERVICE},
373 {0, AF_INET6, SOCK_DGRAM, invalid_portname /*bad*/, EAI_SERVICE},
374 {0, AF_UNSPEC, ANY, invalid_portname /*bad*/, EAI_SERVICE},
375 {0, AF_UNSPEC, SOCK_STREAM, invalid_portname /*bad*/, EAI_SERVICE},
376 {0, AF_UNSPEC, SOCK_DGRAM, invalid_portname /*bad*/, EAI_SERVICE},
377 };
378
379 for (const auto& config : testConfigs) {
380 const std::string testParameters = config.asParameters();
381 SCOPED_TRACE(testParameters);
382
383 const addrinfo hints = {
384 .ai_flags = config.ai_flags,
385 .ai_family = config.ai_family,
386 .ai_socktype = config.ai_socktype,
387 };
388
389 addrinfo* result = nullptr;
390 NetworkDnsEventReported event;
391 int rv = resolv_getaddrinfo("localhost", config.servname, &hints, &mNetcontext, &result,
392 &event);
393 ScopedAddrinfo result_cleanup(result);
394 EXPECT_EQ(config.expected_eai_error, rv);
395 }
396 }
397
TEST_F(ResolvGetAddrInfoTest,AlphabeticalHostname_NoData)398 TEST_F(ResolvGetAddrInfoTest, AlphabeticalHostname_NoData) {
399 constexpr char v4_host_name[] = "v4only.example.com.";
400 // Following fields will not be verified during the test in proto NetworkDnsEventReported.
401 // So don't need to config those values: event_type, return_code, latency_micros,
402 // hints_ai_flags, res_nsend_flags, network_type, private_dns_modes.
403 constexpr char event_ipv6[] = R"Event(
404 NetworkDnsEventReported {
405 dns_query_events:
406 {
407 dns_query_event:[
408 {
409 rcode: 0,
410 type: 28,
411 cache_hit: 1,
412 ip_version: 1,
413 protocol: 1,
414 retry_times: 0,
415 dns_server_index: 0,
416 connected: 0,
417 latency_micros: 0,
418 linux_errno: 0,
419 },
420 {
421 rcode: 0,
422 type: 28,
423 cache_hit: 1,
424 ip_version: 1,
425 protocol: 1,
426 retry_times: 0,
427 dns_server_index: 0,
428 connected: 0,
429 latency_micros: 0,
430 linux_errno: 0,
431 },
432 {
433 rcode: 0,
434 type: 28,
435 cache_hit: 1,
436 ip_version: 1,
437 protocol: 1,
438 retry_times: 0,
439 dns_server_index: 0,
440 connected: 0,
441 latency_micros: 0,
442 linux_errno: 0,
443 },
444 {
445 rcode: 0,
446 type: 28,
447 cache_hit: 1,
448 ip_version: 1,
449 protocol: 1,
450 retry_times: 0,
451 dns_server_index: 0,
452 connected: 0,
453 latency_micros: 0,
454 linux_errno: 0,
455 }
456 ]
457 }
458 })Event";
459
460 test::DNSResponder dns;
461 dns.addMapping(v4_host_name, ns_type::ns_t_a, "1.2.3.3");
462 ASSERT_TRUE(dns.startServer());
463 ASSERT_EQ(0, SetResolvers());
464
465 // Want AAAA answer but DNS server has A answer only.
466 addrinfo* result = nullptr;
467 const addrinfo hints = {.ai_family = AF_INET6};
468 NetworkDnsEventReported event;
469 int rv = resolv_getaddrinfo("v4only", nullptr, &hints, &mNetcontext, &result, &event);
470 EXPECT_THAT(event, NetworkDnsEventEq(fromNetworkDnsEventReportedStr(event_ipv6)));
471 ScopedAddrinfo result_cleanup(result);
472 EXPECT_LE(1U, GetNumQueries(dns, v4_host_name));
473 EXPECT_EQ(nullptr, result);
474 EXPECT_EQ(EAI_NODATA, rv);
475 }
476
TEST_F(ResolvGetAddrInfoTest,AlphabeticalHostname)477 TEST_F(ResolvGetAddrInfoTest, AlphabeticalHostname) {
478 constexpr char host_name[] = "sawadee.example.com.";
479 constexpr char v4addr[] = "1.2.3.4";
480 constexpr char v6addr[] = "::1.2.3.4";
481 // Following fields will not be verified during the test in proto NetworkDnsEventReported.
482 // So don't need to config those values: event_type, return_code, latency_micros,
483 // hints_ai_flags, res_nsend_flags, network_type, private_dns_modes.
484 constexpr char event_ipv4[] = R"Event(
485 NetworkDnsEventReported {
486 dns_query_events:
487 {
488 dns_query_event:[
489 {
490 rcode: 0,
491 type: 1,
492 cache_hit: 1,
493 ip_version: 1,
494 protocol: 1,
495 retry_times: 0,
496 dns_server_index: 0,
497 connected: 0,
498 linux_errno: 0,
499 },
500 {
501 rcode: 0,
502 type: 1,
503 cache_hit: 2,
504 ip_version: 0,
505 protocol: 0,
506 retry_times: 0,
507 dns_server_index: 0,
508 connected: 0,
509 linux_errno: 0,
510 }
511 ]
512 }
513 })Event";
514
515 constexpr char event_ipv6[] = R"Event(
516 NetworkDnsEventReported {
517 dns_query_events:
518 {
519 dns_query_event:[
520 {
521 rcode: 0,
522 type: 28,
523 cache_hit: 1,
524 ip_version: 1,
525 protocol: 1,
526 retry_times: 0,
527 dns_server_index: 0,
528 connected: 0,
529 linux_errno: 0,
530 },
531 {
532 rcode: 0,
533 type: 28,
534 cache_hit: 2,
535 ip_version: 0,
536 protocol: 0,
537 retry_times: 0,
538 dns_server_index: 0,
539 connected: 0,
540 linux_errno: 0,
541 }
542 ]
543 }
544 })Event";
545 test::DNSResponder dns;
546 dns.addMapping(host_name, ns_type::ns_t_a, v4addr);
547 dns.addMapping(host_name, ns_type::ns_t_aaaa, v6addr);
548 ASSERT_TRUE(dns.startServer());
549 ASSERT_EQ(0, SetResolvers());
550
551 static const struct TestConfig {
552 int ai_family;
553 const std::string expected_addr;
554 const std::string expected_event;
555 } testConfigs[]{
556 {AF_INET, v4addr, event_ipv4},
557 {AF_INET6, v6addr, event_ipv6},
558 };
559
560 for (const auto& config : testConfigs) {
561 SCOPED_TRACE(StringPrintf("family: %d", config.ai_family));
562 dns.clearQueries();
563
564 addrinfo* result = nullptr;
565 const addrinfo hints = {.ai_family = config.ai_family};
566 NetworkDnsEventReported event;
567 int rv = resolv_getaddrinfo("sawadee", nullptr, &hints, &mNetcontext, &result, &event);
568 EXPECT_THAT(event,
569 NetworkDnsEventEq(fromNetworkDnsEventReportedStr(config.expected_event)));
570 ScopedAddrinfo result_cleanup(result);
571 EXPECT_EQ(0, rv);
572 EXPECT_TRUE(result != nullptr);
573 EXPECT_EQ(1U, GetNumQueries(dns, host_name));
574 EXPECT_EQ(config.expected_addr, ToString(result));
575 }
576 }
577
TEST_F(ResolvGetAddrInfoTest,IllegalHostname)578 TEST_F(ResolvGetAddrInfoTest, IllegalHostname) {
579 test::DNSResponder dns;
580 ASSERT_TRUE(dns.startServer());
581 ASSERT_EQ(0, SetResolvers());
582
583 // Illegal hostname is verified by res_hnok() in system/netd/resolv/res_comp.cpp.
584 static constexpr char const* illegalHostnames[] = {
585 kBadCharAfterPeriodHost,
586 kBadCharBeforePeriodHost,
587 kBadCharAtTheEndHost,
588 kBadCharInTheMiddleOfLabelHost,
589 };
590
591 for (const auto& hostname : illegalHostnames) {
592 // Expect to get no address because hostname format is illegal.
593 //
594 // Ex:
595 // ANSWER SECTION:
596 // a.ex^ample.com. IN A 1.2.3.3
597 // a.ex^ample.com. IN AAAA 2001:db8::42
598 //
599 // In this example, querying "a.ex^ample.com" should get no address because
600 // "a.ex^ample.com" has an illegal char '^' in the middle of label.
601 dns.addMapping(hostname, ns_type::ns_t_a, "1.2.3.3");
602 dns.addMapping(hostname, ns_type::ns_t_aaaa, "2001:db8::42");
603
604 for (const auto& family : {AF_INET, AF_INET6, AF_UNSPEC}) {
605 SCOPED_TRACE(StringPrintf("family: %d, config.name: %s", family, hostname));
606
607 addrinfo* res = nullptr;
608 const addrinfo hints = {.ai_family = family};
609 NetworkDnsEventReported event;
610 int rv = resolv_getaddrinfo(hostname, nullptr, &hints, &mNetcontext, &res, &event);
611 ScopedAddrinfo result(res);
612 EXPECT_EQ(nullptr, result);
613 EXPECT_EQ(EAI_FAIL, rv);
614 }
615 }
616 }
617
TEST_F(ResolvGetAddrInfoTest,ServerResponseError)618 TEST_F(ResolvGetAddrInfoTest, ServerResponseError) {
619 constexpr char host_name[] = "hello.example.com.";
620
621 static const struct TestConfig {
622 ns_rcode rcode;
623 int expected_eai_error;
624
625 // Only test failure RCODE [1..5] in RFC 1035 section 4.1.1 and skip successful RCODE 0
626 // which means no error.
627 } testConfigs[]{
628 // clang-format off
629 {ns_rcode::ns_r_formerr, EAI_FAIL},
630 {ns_rcode::ns_r_servfail, EAI_AGAIN},
631 {ns_rcode::ns_r_nxdomain, EAI_NODATA},
632 {ns_rcode::ns_r_notimpl, EAI_FAIL},
633 {ns_rcode::ns_r_refused, EAI_FAIL},
634 // clang-format on
635 };
636
637 for (const auto& config : testConfigs) {
638 SCOPED_TRACE(StringPrintf("rcode: %d", config.rcode));
639
640 test::DNSResponder dns(config.rcode);
641 dns.addMapping(host_name, ns_type::ns_t_a, "1.2.3.4");
642 dns.setResponseProbability(0.0); // always ignore requests and response preset rcode
643 ASSERT_TRUE(dns.startServer());
644 ASSERT_EQ(0, SetResolvers());
645
646 addrinfo* result = nullptr;
647 const addrinfo hints = {.ai_family = AF_UNSPEC};
648 NetworkDnsEventReported event;
649 int rv = resolv_getaddrinfo(host_name, nullptr, &hints, &mNetcontext, &result, &event);
650 EXPECT_EQ(config.expected_eai_error, rv);
651 }
652 }
653
654 // TODO: Add private DNS server timeout test.
TEST_F(ResolvGetAddrInfoTest,ServerTimeout)655 TEST_F(ResolvGetAddrInfoTest, ServerTimeout) {
656 constexpr char host_name[] = "hello.example.com.";
657 // Following fields will not be verified during the test in proto NetworkDnsEventReported.
658 // So don't need to config those values: event_type, return_code, latency_micros,
659 // hints_ai_flags, res_nsend_flags, network_type, private_dns_modes.
660 // Expected_event is 16 DNS queries and only "type" and "retry_times" fields are changed.
661 // 2(T_AAAA + T_A) * 2(w/ retry) * 2(query w/ and w/o domain) * 2(SOCK_DGRAM and SOCK_STREAM)
662 constexpr char expected_event[] = R"Event(
663 NetworkDnsEventReported {
664 dns_query_events:
665 {
666 dns_query_event:[
667 {
668 rcode: 255,
669 type: 28,
670 cache_hit: 1,
671 ip_version: 1,
672 protocol: 1,
673 retry_times: 0,
674 dns_server_index: 0,
675 connected: 0,
676 linux_errno: 110,
677 },
678 {
679 rcode: 255,
680 type: 28,
681 cache_hit: 1,
682 ip_version: 1,
683 protocol: 1,
684 retry_times: 1,
685 dns_server_index: 0,
686 connected: 0,
687 linux_errno: 110,
688 }
689 {
690 rcode: 255,
691 type: 1,
692 cache_hit: 1,
693 ip_version: 1,
694 protocol: 1,
695 retry_times: 0,
696 dns_server_index: 0,
697 connected: 0,
698 linux_errno: 110,
699 },
700 {
701 rcode: 255,
702 type: 1,
703 cache_hit: 1,
704 ip_version: 1,
705 protocol: 1,
706 retry_times: 1,
707 dns_server_index: 0,
708 connected: 0,
709 linux_errno: 110,
710 },
711 {
712 rcode: 255,
713 type: 28,
714 cache_hit: 1,
715 ip_version: 1,
716 protocol: 1,
717 retry_times: 0,
718 dns_server_index: 0,
719 connected: 0,
720 linux_errno: 110,
721 },
722 {
723 rcode: 255,
724 type: 28,
725 cache_hit: 1,
726 ip_version: 1,
727 protocol: 1,
728 retry_times: 1,
729 dns_server_index: 0,
730 connected: 0,
731 linux_errno: 110,
732 }
733 {
734 rcode: 255,
735 type: 1,
736 cache_hit: 1,
737 ip_version: 1,
738 protocol: 1,
739 retry_times: 0,
740 dns_server_index: 0,
741 connected: 0,
742 linux_errno: 110,
743 },
744 {
745 rcode: 255,
746 type: 1,
747 cache_hit: 1,
748 ip_version: 1,
749 protocol: 1,
750 retry_times: 1,
751 dns_server_index: 0,
752 connected: 0,
753 linux_errno: 110,
754 },
755 {
756 rcode: 255,
757 type: 28,
758 cache_hit: 1,
759 ip_version: 1,
760 protocol: 1,
761 retry_times: 0,
762 dns_server_index: 0,
763 connected: 0,
764 linux_errno: 110,
765 },
766 {
767 rcode: 255,
768 type: 28,
769 cache_hit: 1,
770 ip_version: 1,
771 protocol: 1,
772 retry_times: 1,
773 dns_server_index: 0,
774 connected: 0,
775 linux_errno: 110,
776 }
777 {
778 rcode: 255,
779 type: 1,
780 cache_hit: 1,
781 ip_version: 1,
782 protocol: 1,
783 retry_times: 0,
784 dns_server_index: 0,
785 connected: 0,
786 linux_errno: 110,
787 },
788 {
789 rcode: 255,
790 type: 1,
791 cache_hit: 1,
792 ip_version: 1,
793 protocol: 1,
794 retry_times: 1,
795 dns_server_index: 0,
796 connected: 0,
797 linux_errno: 110,
798 },
799 {
800 rcode: 255,
801 type: 28,
802 cache_hit: 1,
803 ip_version: 1,
804 protocol: 1,
805 retry_times: 0,
806 dns_server_index: 0,
807 connected: 0,
808 linux_errno: 110,
809 },
810 {
811 rcode: 255,
812 type: 28,
813 cache_hit: 1,
814 ip_version: 1,
815 protocol: 1,
816 retry_times: 1,
817 dns_server_index: 0,
818 connected: 0,
819 linux_errno: 110,
820 }
821 {
822 rcode: 255,
823 type: 1,
824 cache_hit: 1,
825 ip_version: 1,
826 protocol: 1,
827 retry_times: 0,
828 dns_server_index: 0,
829 connected: 0,
830 linux_errno: 110,
831 },
832 {
833 rcode: 255,
834 type: 1,
835 cache_hit: 1,
836 ip_version: 1,
837 protocol: 1,
838 retry_times: 1,
839 dns_server_index: 0,
840 connected: 0,
841 linux_errno: 110,
842 },
843 ]
844 }
845 })Event";
846 test::DNSResponder dns(static_cast<ns_rcode>(-1) /*no response*/);
847 dns.addMapping(host_name, ns_type::ns_t_a, "1.2.3.4");
848 dns.setResponseProbability(0.0); // always ignore requests and don't response
849 ASSERT_TRUE(dns.startServer());
850 ASSERT_EQ(0, SetResolvers());
851
852 addrinfo* result = nullptr;
853 const addrinfo hints = {.ai_family = AF_UNSPEC};
854 NetworkDnsEventReported event;
855 int rv = resolv_getaddrinfo("hello", nullptr, &hints, &mNetcontext, &result, &event);
856 EXPECT_THAT(event, NetworkDnsEventEq(fromNetworkDnsEventReportedStr(expected_event)));
857 EXPECT_EQ(NETD_RESOLV_TIMEOUT, rv);
858 }
859
TEST_F(ResolvGetAddrInfoTest,CnamesNoIpAddress)860 TEST_F(ResolvGetAddrInfoTest, CnamesNoIpAddress) {
861 constexpr char ACNAME[] = "acname"; // expect a cname in answer
862 constexpr char CNAMES[] = "cnames"; // expect cname chain in answer
863
864 test::DNSResponder dns;
865 dns.addMapping("cnames.example.com.", ns_type::ns_t_cname, "acname.example.com.");
866 dns.addMapping("acname.example.com.", ns_type::ns_t_cname, "hello.example.com.");
867 ASSERT_TRUE(dns.startServer());
868 ASSERT_EQ(0, SetResolvers());
869
870 static const struct TestConfig {
871 const char* name;
872 int family;
873 } testConfigs[]{
874 // clang-format off
875 {ACNAME, AF_INET},
876 {ACNAME, AF_INET6},
877 {ACNAME, AF_UNSPEC},
878 {CNAMES, AF_INET},
879 {CNAMES, AF_INET6},
880 {CNAMES, AF_UNSPEC},
881 // clang-format on
882 };
883
884 for (const auto& config : testConfigs) {
885 SCOPED_TRACE(
886 StringPrintf("config.family: %d, config.name: %s", config.family, config.name));
887
888 addrinfo* res = nullptr;
889 const addrinfo hints = {.ai_family = config.family};
890 NetworkDnsEventReported event;
891 int rv = resolv_getaddrinfo(config.name, nullptr, &hints, &mNetcontext, &res, &event);
892 ScopedAddrinfo result(res);
893 EXPECT_EQ(nullptr, result);
894 EXPECT_EQ(EAI_FAIL, rv);
895 }
896 }
897
TEST_F(ResolvGetAddrInfoTest,CnamesBrokenChainByIllegalCname)898 TEST_F(ResolvGetAddrInfoTest, CnamesBrokenChainByIllegalCname) {
899 test::DNSResponder dns;
900 ASSERT_TRUE(dns.startServer());
901 ASSERT_EQ(0, SetResolvers());
902
903 static const struct TestConfig {
904 const char* name;
905 const char* cname;
906 std::string asHostName() const { return StringPrintf("%s.example.com.", name); }
907
908 // Illegal cname is verified by res_hnok() in system/netd/resolv/res_comp.cpp.
909 } testConfigs[]{
910 // clang-format off
911 {NAME(kBadCharAfterPeriodHost), kBadCharAfterPeriodHost},
912 {NAME(kBadCharBeforePeriodHost), kBadCharBeforePeriodHost},
913 {NAME(kBadCharAtTheEndHost), kBadCharAtTheEndHost},
914 {NAME(kBadCharInTheMiddleOfLabelHost), kBadCharInTheMiddleOfLabelHost},
915 // clang-format on
916 };
917
918 for (const auto& config : testConfigs) {
919 const std::string testHostName = config.asHostName();
920
921 // Expect to get no address because the cname chain is broken by an illegal cname format.
922 //
923 // Ex:
924 // ANSWER SECTION:
925 // hello.example.com. IN CNAME a.ex^ample.com.
926 // a.ex^ample.com. IN A 1.2.3.3
927 // a.ex^ample.com. IN AAAA 2001:db8::42
928 //
929 // In this example, querying hello.example.com should get no address because
930 // "a.ex^ample.com" has an illegal char '^' in the middle of label.
931 dns.addMapping(testHostName.c_str(), ns_type::ns_t_cname, config.cname);
932 dns.addMapping(config.cname, ns_type::ns_t_a, "1.2.3.3");
933 dns.addMapping(config.cname, ns_type::ns_t_aaaa, "2001:db8::42");
934
935 for (const auto& family : {AF_INET, AF_INET6, AF_UNSPEC}) {
936 SCOPED_TRACE(
937 StringPrintf("family: %d, testHostName: %s", family, testHostName.c_str()));
938
939 addrinfo* res = nullptr;
940 const addrinfo hints = {.ai_family = family};
941 NetworkDnsEventReported event;
942 int rv = resolv_getaddrinfo(config.name, nullptr, &hints, &mNetcontext, &res, &event);
943 ScopedAddrinfo result(res);
944 EXPECT_EQ(nullptr, result);
945 EXPECT_EQ(EAI_FAIL, rv);
946 }
947 }
948 }
949
TEST_F(ResolvGetAddrInfoTest,CnamesInfiniteLoop)950 TEST_F(ResolvGetAddrInfoTest, CnamesInfiniteLoop) {
951 test::DNSResponder dns;
952 dns.addMapping("hello.example.com.", ns_type::ns_t_cname, "a.example.com.");
953 dns.addMapping("a.example.com.", ns_type::ns_t_cname, "hello.example.com.");
954 ASSERT_TRUE(dns.startServer());
955 ASSERT_EQ(0, SetResolvers());
956
957 for (const auto& family : {AF_INET, AF_INET6, AF_UNSPEC}) {
958 SCOPED_TRACE(StringPrintf("family: %d", family));
959
960 addrinfo* res = nullptr;
961 const addrinfo hints = {.ai_family = family};
962 NetworkDnsEventReported event;
963 int rv = resolv_getaddrinfo("hello", nullptr, &hints, &mNetcontext, &res, &event);
964 ScopedAddrinfo result(res);
965 EXPECT_EQ(nullptr, result);
966 EXPECT_EQ(EAI_FAIL, rv);
967 }
968 }
969
TEST_F(ResolvGetAddrInfoTest,MultiAnswerSections)970 TEST_F(ResolvGetAddrInfoTest, MultiAnswerSections) {
971 test::DNSResponder dns(test::DNSResponder::MappingType::DNS_HEADER);
972 // Answer section for query type {A, AAAA}
973 // Type A:
974 // hello.example.com. IN A 1.2.3.1
975 // hello.example.com. IN A 1.2.3.2
976 // Type AAAA:
977 // hello.example.com. IN AAAA 2001:db8::41
978 // hello.example.com. IN AAAA 2001:db8::42
979 StartDns(dns, {MakeDnsMessage(kHelloExampleCom, ns_type::ns_t_a, {"1.2.3.1", "1.2.3.2"}),
980 MakeDnsMessage(kHelloExampleCom, ns_type::ns_t_aaaa,
981 {"2001:db8::41", "2001:db8::42"})});
982 ASSERT_EQ(0, SetResolvers());
983
984 for (const auto& family : {AF_INET, AF_INET6, AF_UNSPEC}) {
985 SCOPED_TRACE(StringPrintf("family: %d", family));
986
987 addrinfo* res = nullptr;
988 // If the socket type is not specified, every address will appear twice, once for
989 // SOCK_STREAM and one for SOCK_DGRAM. Just pick one because the addresses for
990 // the second query of different socket type are responded by the cache.
991 const addrinfo hints = {.ai_family = family, .ai_socktype = SOCK_STREAM};
992 NetworkDnsEventReported event;
993 int rv = resolv_getaddrinfo("hello", nullptr, &hints, &mNetcontext, &res, &event);
994 ScopedAddrinfo result(res);
995 ASSERT_NE(nullptr, result);
996 ASSERT_EQ(0, rv);
997
998 const std::vector<std::string> result_strs = ToStrings(result);
999 if (family == AF_INET) {
1000 EXPECT_EQ(1U, GetNumQueries(dns, kHelloExampleCom));
1001 EXPECT_THAT(result_strs, testing::UnorderedElementsAreArray({"1.2.3.1", "1.2.3.2"}));
1002 } else if (family == AF_INET6) {
1003 EXPECT_EQ(1U, GetNumQueries(dns, kHelloExampleCom));
1004 EXPECT_THAT(result_strs,
1005 testing::UnorderedElementsAreArray({"2001:db8::41", "2001:db8::42"}));
1006 } else if (family == AF_UNSPEC) {
1007 EXPECT_EQ(0U, GetNumQueries(dns, kHelloExampleCom)); // no query because of the cache
1008 EXPECT_THAT(result_strs,
1009 testing::UnorderedElementsAreArray(
1010 {"1.2.3.1", "1.2.3.2", "2001:db8::41", "2001:db8::42"}));
1011 }
1012 dns.clearQueries();
1013 }
1014 }
1015
TEST_F(ResolvGetAddrInfoTest,TruncatedResponse)1016 TEST_F(ResolvGetAddrInfoTest, TruncatedResponse) {
1017 // Following fields will not be verified during the test in proto NetworkDnsEventReported.
1018 // So don't need to config those values: event_type, return_code, latency_micros,
1019 // hints_ai_flags, res_nsend_flags, network_type, private_dns_modes.
1020 constexpr char event_ipv4[] = R"Event(
1021 NetworkDnsEventReported {
1022 dns_query_events:
1023 {
1024 dns_query_event:[
1025 {
1026 rcode: 254,
1027 type: 1,
1028 cache_hit: 1,
1029 ip_version: 1,
1030 protocol: 1,
1031 retry_times: 0,
1032 dns_server_index: 0,
1033 connected: 0,
1034 linux_errno: 7,
1035 },
1036 {
1037 rcode: 0,
1038 type: 1,
1039 cache_hit: 1,
1040 ip_version: 1,
1041 protocol: 2,
1042 retry_times: 0,
1043 dns_server_index: 0,
1044 connected: 0,
1045 linux_errno: 0,
1046 },
1047 {
1048 rcode: 0,
1049 type: 1,
1050 cache_hit: 2,
1051 ip_version: 0,
1052 protocol: 0,
1053 retry_times: 0,
1054 dns_server_index: 0,
1055 connected: 0,
1056 linux_errno: 0,
1057 }
1058 ]
1059 }
1060 })Event";
1061
1062 constexpr char event_ipv6[] = R"Event(
1063 NetworkDnsEventReported {
1064 dns_query_events:
1065 {
1066 dns_query_event:[
1067 {
1068 rcode: 254,
1069 type: 28,
1070 cache_hit: 1,
1071 ip_version: 1,
1072 protocol: 1,
1073 retry_times: 0,
1074 dns_server_index: 0,
1075 connected: 0,
1076 linux_errno: 7,
1077 },
1078 {
1079 rcode: 0,
1080 type: 28,
1081 cache_hit: 1,
1082 ip_version: 1,
1083 protocol: 2,
1084 retry_times: 0,
1085 dns_server_index: 0,
1086 connected: 0,
1087 linux_errno: 0,
1088 },
1089 {
1090 rcode: 0,
1091 type: 28,
1092 cache_hit: 2,
1093 ip_version: 0,
1094 protocol: 0,
1095 retry_times: 0,
1096 dns_server_index: 0,
1097 connected: 0,
1098 linux_errno: 0,
1099 }
1100 ]
1101 }
1102 })Event";
1103
1104 test::DNSResponder dns;
1105 dns.addMapping(kHelloExampleCom, ns_type::ns_t_cname, kCnameA);
1106 dns.addMapping(kCnameA, ns_type::ns_t_cname, kCnameB);
1107 dns.addMapping(kCnameB, ns_type::ns_t_cname, kCnameC);
1108 dns.addMapping(kCnameC, ns_type::ns_t_cname, kCnameD);
1109 dns.addMapping(kCnameD, ns_type::ns_t_a, kHelloExampleComAddrV4);
1110 dns.addMapping(kCnameD, ns_type::ns_t_aaaa, kHelloExampleComAddrV6);
1111 ASSERT_TRUE(dns.startServer());
1112 ASSERT_EQ(0, SetResolvers());
1113
1114 static const struct TestConfig {
1115 int ai_family;
1116 const std::string expected_addr;
1117 const std::string expected_event;
1118 } testConfigs[]{
1119 {AF_INET, kHelloExampleComAddrV4, event_ipv4},
1120 {AF_INET6, kHelloExampleComAddrV6, event_ipv6},
1121 };
1122
1123 for (const auto& config : testConfigs) {
1124 SCOPED_TRACE(StringPrintf("family: %d", config.ai_family));
1125 dns.clearQueries();
1126
1127 addrinfo* result = nullptr;
1128 const addrinfo hints = {.ai_family = config.ai_family};
1129 NetworkDnsEventReported event;
1130 int rv = resolv_getaddrinfo("hello", nullptr, &hints, &mNetcontext, &result, &event);
1131 EXPECT_THAT(event,
1132 NetworkDnsEventEq(fromNetworkDnsEventReportedStr(config.expected_event)));
1133 ScopedAddrinfo result_cleanup(result);
1134 EXPECT_EQ(rv, 0);
1135 EXPECT_TRUE(result != nullptr);
1136 // Expect UDP response is truncated. The resolver retries over TCP. See RFC 1035
1137 // section 4.2.1.
1138 EXPECT_EQ(GetNumQueriesForProtocol(dns, IPPROTO_UDP, kHelloExampleCom), 1U);
1139 EXPECT_EQ(GetNumQueriesForProtocol(dns, IPPROTO_TCP, kHelloExampleCom), 1U);
1140 EXPECT_EQ(ToString(result), config.expected_addr);
1141 }
1142 }
1143
1144 // Audit if Resolver read out of bounds, which needs HWAddressSanitizer build to trigger SIGABRT.
TEST_F(ResolvGetAddrInfoTest,OverlengthResp)1145 TEST_F(ResolvGetAddrInfoTest, OverlengthResp) {
1146 std::vector<std::string> nameList;
1147 // Construct a long enough record that exceeds 8192 bytes (the maximum buffer size):
1148 // Header: (Transaction ID, Flags, ...) = 12 bytes
1149 // Query: 19(Name)+2(Type)+2(Class) = 23 bytes
1150 // The 1st answer RR: 19(Name)+2(Type)+2(Class)+4(TTL)+2(Len)+77(CNAME) = 106 bytes
1151 // 2nd-50th answer RRs: 49*(77(Name)+2(Type)+2(Class)+4(TTL)+2(Len)+77(CNAME)) = 8036 bytes
1152 // The last answer RR: 77(Name)+2(Type)+2(Class)+4(TTL)+2(Len)+4(Address) = 91 bytes
1153 // ----------------------------------------------------------------------------------------
1154 // Sum: 8268 bytes
1155 for (int i = 0; i < 10; i++) {
1156 std::string domain(kMaxmiumLabelSize / 2, 'a' + i);
1157 for (int j = 0; j < 5; j++) {
1158 nameList.push_back(domain + std::string(kMaxmiumLabelSize / 2 + 1, '0' + j) +
1159 kExampleComDomain + ".");
1160 }
1161 }
1162 test::DNSResponder dns;
1163 dns.addMapping(kHelloExampleCom, ns_type::ns_t_cname, nameList[0]);
1164 for (size_t i = 0; i < nameList.size() - 1; i++) {
1165 dns.addMapping(nameList[i], ns_type::ns_t_cname, nameList[i + 1]);
1166 }
1167 dns.addMapping(nameList[nameList.size() - 1], ns_type::ns_t_a, kHelloExampleComAddrV4);
1168
1169 ASSERT_TRUE(dns.startServer());
1170 ASSERT_EQ(0, SetResolvers());
1171 addrinfo* result = nullptr;
1172 const addrinfo hints = {.ai_family = AF_INET};
1173 NetworkDnsEventReported event;
1174 int rv = resolv_getaddrinfo("hello", nullptr, &hints, &mNetcontext, &result, &event);
1175 ScopedAddrinfo result_cleanup(result);
1176 EXPECT_EQ(rv, EAI_FAIL);
1177 EXPECT_TRUE(result == nullptr);
1178 EXPECT_EQ(GetNumQueriesForProtocol(dns, IPPROTO_UDP, kHelloExampleCom), 2U);
1179 EXPECT_EQ(GetNumQueriesForProtocol(dns, IPPROTO_TCP, kHelloExampleCom), 2U);
1180 }
1181
TEST_F(GetHostByNameForNetContextTest,AlphabeticalHostname)1182 TEST_F(GetHostByNameForNetContextTest, AlphabeticalHostname) {
1183 constexpr char host_name[] = "jiababuei.example.com.";
1184 constexpr char v4addr[] = "1.2.3.4";
1185 constexpr char v6addr[] = "::1.2.3.4";
1186 // Following fields will not be verified during the test in proto NetworkDnsEventReported.
1187 // So don't need to config those values: event_type, return_code, latency_micros,
1188 // hints_ai_flags, res_nsend_flags, network_type, private_dns_modes.
1189 constexpr char event_ipv4[] = R"Event(
1190 NetworkDnsEventReported {
1191 dns_query_events:
1192 {
1193 dns_query_event:[
1194 {
1195 rcode: 0,
1196 type: 1,
1197 cache_hit: 1,
1198 ip_version: 1,
1199 protocol: 1,
1200 retry_times: 0,
1201 dns_server_index: 0,
1202 connected: 0,
1203 latency_micros: 0,
1204 linux_errno: 0,
1205 }
1206 ]
1207 }
1208 })Event";
1209
1210 constexpr char event_ipv6[] = R"Event(
1211 NetworkDnsEventReported {
1212 dns_query_events:
1213 {
1214 dns_query_event:[
1215 {
1216 rcode: 0,
1217 type: 28,
1218 cache_hit: 1,
1219 ip_version: 1,
1220 protocol: 1,
1221 retry_times: 0,
1222 dns_server_index: 0,
1223 connected: 0,
1224 latency_micros: 0,
1225 linux_errno: 0,
1226 }
1227 ]
1228 }
1229 })Event";
1230 test::DNSResponder dns;
1231 dns.addMapping(host_name, ns_type::ns_t_a, v4addr);
1232 dns.addMapping(host_name, ns_type::ns_t_aaaa, v6addr);
1233 ASSERT_TRUE(dns.startServer());
1234 ASSERT_EQ(0, SetResolvers());
1235
1236 static const struct TestConfig {
1237 int ai_family;
1238 const std::string expected_addr;
1239 const std::string expected_event;
1240 } testConfigs[]{
1241 {AF_INET, v4addr, event_ipv4},
1242 {AF_INET6, v6addr, event_ipv6},
1243 };
1244
1245 for (const auto& config : testConfigs) {
1246 SCOPED_TRACE(StringPrintf("family: %d", config.ai_family));
1247 dns.clearQueries();
1248
1249 hostent* hp = nullptr;
1250 hostent hbuf;
1251 char tmpbuf[MAXPACKET];
1252 NetworkDnsEventReported event;
1253 int rv = resolv_gethostbyname("jiababuei", config.ai_family, &hbuf, tmpbuf, sizeof(tmpbuf),
1254 &mNetcontext, &hp, &event);
1255 EXPECT_THAT(event,
1256 NetworkDnsEventEq(fromNetworkDnsEventReportedStr(config.expected_event)));
1257 EXPECT_EQ(0, rv);
1258 EXPECT_TRUE(hp != nullptr);
1259 EXPECT_EQ(1U, GetNumQueries(dns, host_name));
1260 EXPECT_EQ(config.expected_addr, ToString(hp));
1261 }
1262 }
1263
TEST_F(GetHostByNameForNetContextTest,IllegalHostname)1264 TEST_F(GetHostByNameForNetContextTest, IllegalHostname) {
1265 test::DNSResponder dns;
1266 ASSERT_TRUE(dns.startServer());
1267 ASSERT_EQ(0, SetResolvers());
1268
1269 // Illegal hostname is verified by res_hnok() in system/netd/resolv/res_comp.cpp.
1270 static constexpr char const* illegalHostnames[] = {
1271 kBadCharAfterPeriodHost,
1272 kBadCharBeforePeriodHost,
1273 kBadCharAtTheEndHost,
1274 kBadCharInTheMiddleOfLabelHost,
1275 };
1276
1277 for (const auto& hostname : illegalHostnames) {
1278 // Expect to get no address because hostname format is illegal.
1279 //
1280 // Ex:
1281 // ANSWER SECTION:
1282 // a.ex^ample.com. IN A 1.2.3.3
1283 // a.ex^ample.com. IN AAAA 2001:db8::42
1284 //
1285 // In this example, querying "a.ex^ample.com" should get no address because
1286 // "a.ex^ample.com" has an illegal char '^' in the middle of label.
1287 dns.addMapping(hostname, ns_type::ns_t_a, "1.2.3.3");
1288 dns.addMapping(hostname, ns_type::ns_t_aaaa, "2001:db8::42");
1289
1290 for (const auto& family : {AF_INET, AF_INET6}) {
1291 SCOPED_TRACE(StringPrintf("family: %d, config.name: %s", family, hostname));
1292
1293 struct hostent* hp = nullptr;
1294 hostent hbuf;
1295 char tmpbuf[MAXPACKET];
1296 NetworkDnsEventReported event;
1297 int rv = resolv_gethostbyname(hostname, family, &hbuf, tmpbuf, sizeof(tmpbuf),
1298 &mNetcontext, &hp, &event);
1299 EXPECT_EQ(nullptr, hp);
1300 EXPECT_EQ(EAI_FAIL, rv);
1301 }
1302 }
1303 }
1304
TEST_F(GetHostByNameForNetContextTest,NoData)1305 TEST_F(GetHostByNameForNetContextTest, NoData) {
1306 constexpr char v4_host_name[] = "v4only.example.com.";
1307
1308 test::DNSResponder dns;
1309 dns.addMapping(v4_host_name, ns_type::ns_t_a, "1.2.3.3");
1310 ASSERT_TRUE(dns.startServer());
1311 ASSERT_EQ(0, SetResolvers());
1312 dns.clearQueries();
1313
1314 // Want AAAA answer but DNS server has A answer only.
1315 hostent* hp = nullptr;
1316 hostent hbuf;
1317 char tmpbuf[MAXPACKET];
1318 NetworkDnsEventReported event;
1319 int rv = resolv_gethostbyname("v4only", AF_INET6, &hbuf, tmpbuf, sizeof tmpbuf, &mNetcontext,
1320 &hp, &event);
1321 EXPECT_LE(1U, GetNumQueries(dns, v4_host_name));
1322 EXPECT_EQ(nullptr, hp);
1323 EXPECT_EQ(EAI_NODATA, rv);
1324 }
1325
TEST_F(GetHostByNameForNetContextTest,ServerResponseError)1326 TEST_F(GetHostByNameForNetContextTest, ServerResponseError) {
1327 constexpr char host_name[] = "hello.example.com.";
1328
1329 static const struct TestConfig {
1330 ns_rcode rcode;
1331 int expected_eai_error; // expected result
1332
1333 // Only test failure RCODE [1..5] in RFC 1035 section 4.1.1 and skip successful RCODE 0
1334 // which means no error. Note that the return error codes aren't mapped by rcode in the
1335 // test case SERVFAIL, NOTIMP and REFUSED. See the comment of res_nsend()
1336 // in system\netd\resolv\res_query.cpp for more detail.
1337 } testConfigs[]{
1338 // clang-format off
1339 {ns_rcode::ns_r_formerr, EAI_FAIL},
1340 {ns_rcode::ns_r_servfail, EAI_AGAIN}, // Not mapped by rcode.
1341 {ns_rcode::ns_r_nxdomain, EAI_NODATA},
1342 {ns_rcode::ns_r_notimpl, EAI_AGAIN}, // Not mapped by rcode.
1343 {ns_rcode::ns_r_refused, EAI_AGAIN}, // Not mapped by rcode.
1344 // clang-format on
1345 };
1346
1347 for (const auto& config : testConfigs) {
1348 SCOPED_TRACE(StringPrintf("rcode: %d", config.rcode));
1349
1350 test::DNSResponder dns(config.rcode);
1351 dns.addMapping(host_name, ns_type::ns_t_a, "1.2.3.4");
1352 dns.setResponseProbability(0.0); // always ignore requests and response preset rcode
1353 ASSERT_TRUE(dns.startServer());
1354 ASSERT_EQ(0, SetResolvers());
1355
1356 hostent* hp = nullptr;
1357 hostent hbuf;
1358 char tmpbuf[MAXPACKET];
1359 NetworkDnsEventReported event;
1360 int rv = resolv_gethostbyname(host_name, AF_INET, &hbuf, tmpbuf, sizeof tmpbuf,
1361 &mNetcontext, &hp, &event);
1362 EXPECT_EQ(nullptr, hp);
1363 EXPECT_EQ(config.expected_eai_error, rv);
1364 }
1365 }
1366
1367 // TODO: Add private DNS server timeout test.
TEST_F(GetHostByNameForNetContextTest,ServerTimeout)1368 TEST_F(GetHostByNameForNetContextTest, ServerTimeout) {
1369 constexpr char host_name[] = "hello.example.com.";
1370 test::DNSResponder dns(static_cast<ns_rcode>(-1) /*no response*/);
1371 dns.addMapping(host_name, ns_type::ns_t_a, "1.2.3.4");
1372 dns.setResponseProbability(0.0); // always ignore requests and don't response
1373 ASSERT_TRUE(dns.startServer());
1374 ASSERT_EQ(0, SetResolvers());
1375
1376 hostent* hp = nullptr;
1377 hostent hbuf;
1378 char tmpbuf[MAXPACKET];
1379 NetworkDnsEventReported event;
1380 int rv = resolv_gethostbyname(host_name, AF_INET, &hbuf, tmpbuf, sizeof tmpbuf, &mNetcontext,
1381 &hp, &event);
1382 EXPECT_EQ(NETD_RESOLV_TIMEOUT, rv);
1383 }
1384
TEST_F(GetHostByNameForNetContextTest,CnamesNoIpAddress)1385 TEST_F(GetHostByNameForNetContextTest, CnamesNoIpAddress) {
1386 constexpr char ACNAME[] = "acname"; // expect a cname in answer
1387 constexpr char CNAMES[] = "cnames"; // expect cname chain in answer
1388
1389 test::DNSResponder dns;
1390 dns.addMapping("cnames.example.com.", ns_type::ns_t_cname, "acname.example.com.");
1391 dns.addMapping("acname.example.com.", ns_type::ns_t_cname, "hello.example.com.");
1392 ASSERT_TRUE(dns.startServer());
1393 ASSERT_EQ(0, SetResolvers());
1394
1395 static const struct TestConfig {
1396 const char* name;
1397 int family;
1398 } testConfigs[]{
1399 {ACNAME, AF_INET},
1400 {ACNAME, AF_INET6},
1401 {CNAMES, AF_INET},
1402 {CNAMES, AF_INET6},
1403 };
1404
1405 for (const auto& config : testConfigs) {
1406 SCOPED_TRACE(
1407 StringPrintf("config.family: %d, config.name: %s", config.family, config.name));
1408
1409 struct hostent* hp = nullptr;
1410 hostent hbuf;
1411 char tmpbuf[MAXPACKET];
1412 NetworkDnsEventReported event;
1413 int rv = resolv_gethostbyname(config.name, config.family, &hbuf, tmpbuf, sizeof tmpbuf,
1414 &mNetcontext, &hp, &event);
1415 EXPECT_EQ(nullptr, hp);
1416 EXPECT_EQ(EAI_FAIL, rv);
1417 }
1418 }
1419
TEST_F(GetHostByNameForNetContextTest,CnamesBrokenChainByIllegalCname)1420 TEST_F(GetHostByNameForNetContextTest, CnamesBrokenChainByIllegalCname) {
1421 test::DNSResponder dns;
1422 ASSERT_TRUE(dns.startServer());
1423 ASSERT_EQ(0, SetResolvers());
1424
1425 static const struct TestConfig {
1426 const char* name;
1427 const char* cname;
1428 std::string asHostName() const { return StringPrintf("%s.example.com.", name); }
1429
1430 // Illegal cname is verified by res_hnok() in system/netd/resolv/res_comp.cpp
1431 } testConfigs[]{
1432 // clang-format off
1433 {NAME(kBadCharAfterPeriodHost), kBadCharAfterPeriodHost},
1434 {NAME(kBadCharBeforePeriodHost), kBadCharBeforePeriodHost},
1435 {NAME(kBadCharAtTheEndHost), kBadCharAtTheEndHost},
1436 {NAME(kBadCharInTheMiddleOfLabelHost), kBadCharInTheMiddleOfLabelHost},
1437 // clang-format on
1438 };
1439
1440 for (const auto& config : testConfigs) {
1441 const std::string testHostName = config.asHostName();
1442
1443 // Expect to get no address because the cname chain is broken by an illegal cname format.
1444 //
1445 // Ex:
1446 // ANSWER SECTION:
1447 // hello.example.com. IN CNAME a.ex^ample.com.
1448 // a.ex^ample.com. IN A 1.2.3.3
1449 // a.ex^ample.com. IN AAAA 2001:db8::42
1450 //
1451 // In this example, querying hello.example.com should get no address because
1452 // "a.ex^ample.com" has an illegal char '^' in the middle of label.
1453 dns.addMapping(testHostName.c_str(), ns_type::ns_t_cname, config.cname);
1454 dns.addMapping(config.cname, ns_type::ns_t_a, "1.2.3.3");
1455 dns.addMapping(config.cname, ns_type::ns_t_aaaa, "2001:db8::42");
1456
1457 for (const auto& family : {AF_INET, AF_INET6}) {
1458 SCOPED_TRACE(
1459 StringPrintf("family: %d, testHostName: %s", family, testHostName.c_str()));
1460
1461 struct hostent* hp = nullptr;
1462 hostent hbuf;
1463 char tmpbuf[MAXPACKET];
1464 NetworkDnsEventReported event;
1465 int rv = resolv_gethostbyname(config.name, family, &hbuf, tmpbuf, sizeof tmpbuf,
1466 &mNetcontext, &hp, &event);
1467 EXPECT_EQ(nullptr, hp);
1468 EXPECT_EQ(EAI_FAIL, rv);
1469 }
1470 }
1471 }
1472
TEST_F(GetHostByNameForNetContextTest,CnamesInfiniteLoop)1473 TEST_F(GetHostByNameForNetContextTest, CnamesInfiniteLoop) {
1474 test::DNSResponder dns;
1475 dns.addMapping("hello.example.com.", ns_type::ns_t_cname, "a.example.com.");
1476 dns.addMapping("a.example.com.", ns_type::ns_t_cname, "hello.example.com.");
1477 ASSERT_TRUE(dns.startServer());
1478 ASSERT_EQ(0, SetResolvers());
1479
1480 for (const auto& family : {AF_INET, AF_INET6}) {
1481 SCOPED_TRACE(StringPrintf("family: %d", family));
1482
1483 struct hostent* hp = nullptr;
1484 hostent hbuf;
1485 char tmpbuf[MAXPACKET];
1486 NetworkDnsEventReported event;
1487 int rv = resolv_gethostbyname("hello", family, &hbuf, tmpbuf, sizeof tmpbuf, &mNetcontext,
1488 &hp, &event);
1489 EXPECT_EQ(nullptr, hp);
1490 EXPECT_EQ(EAI_FAIL, rv);
1491 }
1492 }
1493
TEST_F(ResolvCommonFunctionTest,GetCustTableByName)1494 TEST_F(ResolvCommonFunctionTest, GetCustTableByName) {
1495 const char custAddrV4[] = "1.2.3.4";
1496 const char custAddrV6[] = "::1.2.3.4";
1497 const char hostnameV4V6[] = "v4v6.example.com.";
1498 const aidl::android::net::ResolverOptionsParcel& resolverOptions = {
1499 {
1500 {custAddrV4, hostnameV4V6},
1501 {custAddrV6, hostnameV4V6},
1502 },
1503 aidl::android::net::IDnsResolver::TC_MODE_DEFAULT};
1504 const std::vector<int32_t>& transportTypes = {IDnsResolver::TRANSPORT_WIFI};
1505 EXPECT_EQ(0, resolv_set_nameservers(TEST_NETID, servers, domains, params, resolverOptions,
1506 transportTypes));
1507 EXPECT_THAT(getCustomizedTableByName(TEST_NETID, hostnameV4V6),
1508 testing::UnorderedElementsAreArray({custAddrV4, custAddrV6}));
1509
1510 // Query address by mismatch hostname.
1511 ASSERT_TRUE(getCustomizedTableByName(TEST_NETID, "not.in.cust.table").empty());
1512
1513 // Query address by different netid.
1514 ASSERT_TRUE(getCustomizedTableByName(TEST_NETID + 1, hostnameV4V6).empty());
1515 resolv_create_cache_for_net(TEST_NETID + 1);
1516 EXPECT_EQ(0, resolv_set_nameservers(TEST_NETID + 1, servers, domains, params, resolverOptions,
1517 transportTypes));
1518 EXPECT_THAT(getCustomizedTableByName(TEST_NETID + 1, hostnameV4V6),
1519 testing::UnorderedElementsAreArray({custAddrV4, custAddrV6}));
1520 }
1521
TEST_F(ResolvCommonFunctionTest,GetNetworkTypesForNet)1522 TEST_F(ResolvCommonFunctionTest, GetNetworkTypesForNet) {
1523 const aidl::android::net::ResolverOptionsParcel& resolverOptions = {
1524 {} /* hosts */, aidl::android::net::IDnsResolver::TC_MODE_DEFAULT};
1525 const std::vector<int32_t>& transportTypes = {IDnsResolver::TRANSPORT_WIFI,
1526 IDnsResolver::TRANSPORT_VPN};
1527 EXPECT_EQ(0, resolv_set_nameservers(TEST_NETID, servers, domains, params, resolverOptions,
1528 transportTypes));
1529 EXPECT_EQ(android::net::NT_WIFI_VPN, resolv_get_network_types_for_net(TEST_NETID));
1530 }
1531
TEST_F(ResolvCommonFunctionTest,ConvertTransportsToNetworkType)1532 TEST_F(ResolvCommonFunctionTest, ConvertTransportsToNetworkType) {
1533 static const struct TestConfig {
1534 int32_t networkType;
1535 std::vector<int32_t> transportTypes;
1536 } testConfigs[] = {
1537 {android::net::NT_CELLULAR, {IDnsResolver::TRANSPORT_CELLULAR}},
1538 {android::net::NT_WIFI, {IDnsResolver::TRANSPORT_WIFI}},
1539 {android::net::NT_BLUETOOTH, {IDnsResolver::TRANSPORT_BLUETOOTH}},
1540 {android::net::NT_ETHERNET, {IDnsResolver::TRANSPORT_ETHERNET}},
1541 {android::net::NT_VPN, {IDnsResolver::TRANSPORT_VPN}},
1542 {android::net::NT_WIFI_AWARE, {IDnsResolver::TRANSPORT_WIFI_AWARE}},
1543 {android::net::NT_LOWPAN, {IDnsResolver::TRANSPORT_LOWPAN}},
1544 {android::net::NT_CELLULAR_VPN,
1545 {IDnsResolver::TRANSPORT_CELLULAR, IDnsResolver::TRANSPORT_VPN}},
1546 {android::net::NT_CELLULAR_VPN,
1547 {IDnsResolver::TRANSPORT_VPN, IDnsResolver::TRANSPORT_CELLULAR}},
1548 {android::net::NT_WIFI_VPN,
1549 {IDnsResolver::TRANSPORT_WIFI, IDnsResolver::TRANSPORT_VPN}},
1550 {android::net::NT_WIFI_VPN,
1551 {IDnsResolver::TRANSPORT_VPN, IDnsResolver::TRANSPORT_WIFI}},
1552 {android::net::NT_BLUETOOTH_VPN,
1553 {IDnsResolver::TRANSPORT_BLUETOOTH, IDnsResolver::TRANSPORT_VPN}},
1554 {android::net::NT_BLUETOOTH_VPN,
1555 {IDnsResolver::TRANSPORT_VPN, IDnsResolver::TRANSPORT_BLUETOOTH}},
1556 {android::net::NT_ETHERNET_VPN,
1557 {IDnsResolver::TRANSPORT_ETHERNET, IDnsResolver::TRANSPORT_VPN}},
1558 {android::net::NT_ETHERNET_VPN,
1559 {IDnsResolver::TRANSPORT_VPN, IDnsResolver::TRANSPORT_ETHERNET}},
1560 {android::net::NT_UNKNOWN, {IDnsResolver::TRANSPORT_VPN, IDnsResolver::TRANSPORT_VPN}},
1561 {android::net::NT_UNKNOWN,
1562 {IDnsResolver::TRANSPORT_WIFI, IDnsResolver::TRANSPORT_LOWPAN}},
1563 {android::net::NT_UNKNOWN, {}},
1564 {android::net::NT_UNKNOWN,
1565 {IDnsResolver::TRANSPORT_CELLULAR, IDnsResolver::TRANSPORT_BLUETOOTH,
1566 IDnsResolver::TRANSPORT_VPN}},
1567 {android::net::NT_WIFI_CELLULAR_VPN,
1568 {IDnsResolver::TRANSPORT_CELLULAR, IDnsResolver::TRANSPORT_WIFI,
1569 IDnsResolver::TRANSPORT_VPN}},
1570 {android::net::NT_WIFI_CELLULAR_VPN,
1571 {IDnsResolver::TRANSPORT_VPN, IDnsResolver::TRANSPORT_WIFI,
1572 IDnsResolver::TRANSPORT_CELLULAR}},
1573 };
1574 for (const auto& config : testConfigs) {
1575 EXPECT_EQ(config.networkType, convert_network_type(config.transportTypes));
1576 }
1577 }
1578
1579 // Note that local host file function, files_getaddrinfo(), of resolv_getaddrinfo()
1580 // is not tested because it only returns a boolean (success or failure) without any error number.
1581
1582 // TODO: Add test for resolv_getaddrinfo().
1583 // - DNS response message parsing.
1584 // - Unexpected type of resource record (RR).
1585 // - Invalid length CNAME, or QNAME.
1586 // - Unexpected amount of questions.
1587 // - CNAME RDATA with the domain name which has null label(s).
1588 // TODO: Add test for resolv_gethostbyname().
1589 // - Invalid parameters.
1590 // - DNS response message parsing.
1591 // - Unexpected type of resource record (RR).
1592 // - Invalid length CNAME, or QNAME.
1593 // - Unexpected amount of questions.
1594 // - CNAME RDATA with the domain name which has null label(s).
1595 // TODO: Add test for resolv_gethostbyaddr().
1596
1597 } // end of namespace net
1598 } // end of namespace android
1599