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