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