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, APP_SOCKET_NONE, &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 APP_SOCKET_NONE, &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 APP_SOCKET_NONE, &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,
270 APP_SOCKET_NONE, &result, &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 APP_SOCKET_NONE, &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,
395 APP_SOCKET_NONE, &result, &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, APP_SOCKET_NONE, &result,
473 &event);
474 EXPECT_THAT(event, NetworkDnsEventEq(fromNetworkDnsEventReportedStr(event_ipv6)));
475 ScopedAddrinfo result_cleanup(result);
476 EXPECT_LE(1U, GetNumQueries(dns, v4_host_name));
477 EXPECT_EQ(nullptr, result);
478 EXPECT_EQ(EAI_NODATA, rv);
479 }
480
TEST_F(ResolvGetAddrInfoTest,AlphabeticalHostname)481 TEST_F(ResolvGetAddrInfoTest, AlphabeticalHostname) {
482 constexpr char host_name[] = "sawadee.example.com.";
483 constexpr char v4addr[] = "1.2.3.4";
484 constexpr char v6addr[] = "::1.2.3.4";
485 // Following fields will not be verified during the test in proto NetworkDnsEventReported.
486 // So don't need to config those values: event_type, return_code, latency_micros,
487 // hints_ai_flags, res_nsend_flags, network_type, private_dns_modes.
488 constexpr char event_ipv4[] = R"Event(
489 NetworkDnsEventReported {
490 dns_query_events:
491 {
492 dns_query_event:[
493 {
494 rcode: 0,
495 type: 1,
496 cache_hit: 1,
497 ip_version: 1,
498 protocol: 1,
499 retry_times: 0,
500 dns_server_index: 0,
501 connected: 0,
502 linux_errno: 0,
503 },
504 {
505 rcode: 0,
506 type: 1,
507 cache_hit: 2,
508 ip_version: 0,
509 protocol: 0,
510 retry_times: 0,
511 dns_server_index: 0,
512 connected: 0,
513 linux_errno: 0,
514 }
515 ]
516 }
517 })Event";
518
519 constexpr char event_ipv6[] = R"Event(
520 NetworkDnsEventReported {
521 dns_query_events:
522 {
523 dns_query_event:[
524 {
525 rcode: 0,
526 type: 28,
527 cache_hit: 1,
528 ip_version: 1,
529 protocol: 1,
530 retry_times: 0,
531 dns_server_index: 0,
532 connected: 0,
533 linux_errno: 0,
534 },
535 {
536 rcode: 0,
537 type: 28,
538 cache_hit: 2,
539 ip_version: 0,
540 protocol: 0,
541 retry_times: 0,
542 dns_server_index: 0,
543 connected: 0,
544 linux_errno: 0,
545 }
546 ]
547 }
548 })Event";
549 test::DNSResponder dns;
550 dns.addMapping(host_name, ns_type::ns_t_a, v4addr);
551 dns.addMapping(host_name, ns_type::ns_t_aaaa, v6addr);
552 ASSERT_TRUE(dns.startServer());
553 ASSERT_EQ(0, SetResolvers());
554
555 static const struct TestConfig {
556 int ai_family;
557 const std::string expected_addr;
558 const std::string expected_event;
559 } testConfigs[]{
560 {AF_INET, v4addr, event_ipv4},
561 {AF_INET6, v6addr, event_ipv6},
562 };
563
564 for (const auto& config : testConfigs) {
565 SCOPED_TRACE(fmt::format("family: {}", config.ai_family));
566 dns.clearQueries();
567
568 addrinfo* result = nullptr;
569 const addrinfo hints = {.ai_family = config.ai_family};
570 NetworkDnsEventReported event;
571 int rv = resolv_getaddrinfo("sawadee", nullptr, &hints, &mNetcontext, APP_SOCKET_NONE,
572 &result, &event);
573 EXPECT_THAT(event,
574 NetworkDnsEventEq(fromNetworkDnsEventReportedStr(config.expected_event)));
575 ScopedAddrinfo result_cleanup(result);
576 EXPECT_EQ(0, rv);
577 EXPECT_TRUE(result != nullptr);
578 EXPECT_EQ(1U, GetNumQueries(dns, host_name));
579 EXPECT_EQ(config.expected_addr, ToString(result));
580 }
581 }
582
TEST_F(ResolvGetAddrInfoTest,IllegalHostname)583 TEST_F(ResolvGetAddrInfoTest, IllegalHostname) {
584 test::DNSResponder dns;
585 ASSERT_TRUE(dns.startServer());
586 ASSERT_EQ(0, SetResolvers());
587
588 // Illegal hostname is verified by res_hnok() in system/netd/resolv/res_comp.cpp.
589 static constexpr char const* illegalHostnames[] = {
590 kBadCharAfterPeriodHost,
591 kBadCharBeforePeriodHost,
592 kBadCharAtTheEndHost,
593 kBadCharInTheMiddleOfLabelHost,
594 };
595
596 for (const auto& hostname : illegalHostnames) {
597 // Expect to get no address because hostname format is illegal.
598 //
599 // Ex:
600 // ANSWER SECTION:
601 // a.ex^ample.com. IN A 1.2.3.3
602 // a.ex^ample.com. IN AAAA 2001:db8::42
603 //
604 // In this example, querying "a.ex^ample.com" should get no address because
605 // "a.ex^ample.com" has an illegal char '^' in the middle of label.
606 dns.addMapping(hostname, ns_type::ns_t_a, "1.2.3.3");
607 dns.addMapping(hostname, ns_type::ns_t_aaaa, "2001:db8::42");
608
609 for (const auto& family : {AF_INET, AF_INET6, AF_UNSPEC}) {
610 SCOPED_TRACE(fmt::format("family: {}, config.name: {}", family, hostname));
611
612 addrinfo* res = nullptr;
613 const addrinfo hints = {.ai_family = family};
614 NetworkDnsEventReported event;
615 int rv = resolv_getaddrinfo(hostname, nullptr, &hints, &mNetcontext, APP_SOCKET_NONE,
616 &res, &event);
617 ScopedAddrinfo result(res);
618 EXPECT_EQ(nullptr, result);
619 EXPECT_EQ(EAI_FAIL, rv);
620 }
621 }
622 }
623
TEST_F(ResolvGetAddrInfoTest,ServerResponseError)624 TEST_F(ResolvGetAddrInfoTest, ServerResponseError) {
625 constexpr char host_name[] = "hello.example.com.";
626
627 static const struct TestConfig {
628 ns_rcode rcode;
629 int expected_eai_error;
630
631 // Only test failure RCODE [1..5] in RFC 1035 section 4.1.1 and skip successful RCODE 0
632 // which means no error.
633 } testConfigs[]{
634 // clang-format off
635 {ns_rcode::ns_r_formerr, EAI_FAIL},
636 {ns_rcode::ns_r_servfail, EAI_AGAIN},
637 {ns_rcode::ns_r_nxdomain, EAI_NODATA},
638 {ns_rcode::ns_r_notimpl, EAI_FAIL},
639 {ns_rcode::ns_r_refused, EAI_FAIL},
640 // clang-format on
641 };
642
643 for (const auto& config : testConfigs) {
644 SCOPED_TRACE(fmt::format("rcode: {}", static_cast<int>(config.rcode)));
645
646 test::DNSResponder dns(config.rcode);
647 dns.addMapping(host_name, ns_type::ns_t_a, "1.2.3.4");
648 dns.setResponseProbability(0.0); // always ignore requests and response preset rcode
649 ASSERT_TRUE(dns.startServer());
650 ASSERT_EQ(0, SetResolvers());
651
652 addrinfo* result = nullptr;
653 const addrinfo hints = {.ai_family = AF_UNSPEC};
654 NetworkDnsEventReported event;
655 int rv = resolv_getaddrinfo(host_name, nullptr, &hints, &mNetcontext, APP_SOCKET_NONE,
656 &result, &event);
657 EXPECT_EQ(config.expected_eai_error, rv);
658 }
659 }
660
661 // TODO: Add private DNS server timeout test.
TEST_F(ResolvGetAddrInfoTest,ServerTimeout)662 TEST_F(ResolvGetAddrInfoTest, ServerTimeout) {
663 constexpr char host_name[] = "hello.example.com.";
664 // Following fields will not be verified during the test in proto NetworkDnsEventReported.
665 // So don't need to config those values: event_type, return_code, latency_micros,
666 // hints_ai_flags, res_nsend_flags, network_type, private_dns_modes.
667 // Expected_event is 16 DNS queries and only "type" and "retry_times" fields are changed.
668 // 2(T_AAAA + T_A) * 2(w/ retry) * 2(query w/ and w/o domain) * 2(SOCK_DGRAM and SOCK_STREAM)
669 constexpr char expected_event[] = R"Event(
670 NetworkDnsEventReported {
671 dns_query_events:
672 {
673 dns_query_event:[
674 {
675 rcode: 255,
676 type: 28,
677 cache_hit: 1,
678 ip_version: 1,
679 protocol: 1,
680 retry_times: 0,
681 dns_server_index: 0,
682 connected: 0,
683 linux_errno: 110,
684 },
685 {
686 rcode: 255,
687 type: 28,
688 cache_hit: 1,
689 ip_version: 1,
690 protocol: 1,
691 retry_times: 1,
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: 0,
703 dns_server_index: 0,
704 connected: 0,
705 linux_errno: 110,
706 },
707 {
708 rcode: 255,
709 type: 1,
710 cache_hit: 1,
711 ip_version: 1,
712 protocol: 1,
713 retry_times: 1,
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: 0,
725 dns_server_index: 0,
726 connected: 0,
727 linux_errno: 110,
728 },
729 {
730 rcode: 255,
731 type: 28,
732 cache_hit: 1,
733 ip_version: 1,
734 protocol: 1,
735 retry_times: 1,
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: 0,
747 dns_server_index: 0,
748 connected: 0,
749 linux_errno: 110,
750 },
751 {
752 rcode: 255,
753 type: 1,
754 cache_hit: 1,
755 ip_version: 1,
756 protocol: 1,
757 retry_times: 1,
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: 0,
769 dns_server_index: 0,
770 connected: 0,
771 linux_errno: 110,
772 },
773 {
774 rcode: 255,
775 type: 28,
776 cache_hit: 1,
777 ip_version: 1,
778 protocol: 1,
779 retry_times: 1,
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: 0,
791 dns_server_index: 0,
792 connected: 0,
793 linux_errno: 110,
794 },
795 {
796 rcode: 255,
797 type: 1,
798 cache_hit: 1,
799 ip_version: 1,
800 protocol: 1,
801 retry_times: 1,
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: 0,
813 dns_server_index: 0,
814 connected: 0,
815 linux_errno: 110,
816 },
817 {
818 rcode: 255,
819 type: 28,
820 cache_hit: 1,
821 ip_version: 1,
822 protocol: 1,
823 retry_times: 1,
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: 0,
835 dns_server_index: 0,
836 connected: 0,
837 linux_errno: 110,
838 },
839 {
840 rcode: 255,
841 type: 1,
842 cache_hit: 1,
843 ip_version: 1,
844 protocol: 1,
845 retry_times: 1,
846 dns_server_index: 0,
847 connected: 0,
848 linux_errno: 110,
849 },
850 ]
851 }
852 })Event";
853 test::DNSResponder dns(static_cast<ns_rcode>(-1) /*no response*/);
854 dns.addMapping(host_name, ns_type::ns_t_a, "1.2.3.4");
855 dns.setResponseProbability(0.0); // always ignore requests and don't respond
856 ASSERT_TRUE(dns.startServer());
857 ASSERT_EQ(0, SetResolvers());
858
859 addrinfo* result = nullptr;
860 const addrinfo hints = {.ai_family = AF_UNSPEC};
861 NetworkDnsEventReported event;
862 int rv = resolv_getaddrinfo("hello", nullptr, &hints, &mNetcontext, APP_SOCKET_NONE, &result,
863 &event);
864 EXPECT_THAT(event, NetworkDnsEventEq(fromNetworkDnsEventReportedStr(expected_event)));
865 EXPECT_EQ(NETD_RESOLV_TIMEOUT, rv);
866 }
867
TEST_F(ResolvGetAddrInfoTest,MdnsAlphabeticalHostname)868 TEST_F(ResolvGetAddrInfoTest, MdnsAlphabeticalHostname) {
869 constexpr char v4addr[] = "127.0.0.3";
870 constexpr char v6addr[] = "::127.0.0.3";
871 constexpr char host_name[] = "hello.local.";
872 // Following fields will not be verified during the test in proto NetworkDnsEventReported.
873 // So don't need to config those values: event_type, return_code, latency_micros,
874 // hints_ai_flags, res_nsend_flags, network_type, private_dns_modes.
875
876 constexpr char event_ipv4[] = R"Event(
877 NetworkDnsEventReported {
878 dns_query_events:
879 {
880 dns_query_event:[
881 {
882 rcode: 0,
883 type: 1,
884 cache_hit: 1,
885 ip_version: 2,
886 protocol: 5,
887 retry_times: 0,
888 dns_server_index: 0,
889 connected: 0,
890 linux_errno: 0,
891 },
892 ]
893 }
894 })Event";
895
896 constexpr char event_ipv6[] = R"Event(
897 NetworkDnsEventReported {
898 dns_query_events:
899 {
900 dns_query_event:[
901 {
902 rcode: 0,
903 type: 28,
904 cache_hit: 1,
905 ip_version: 2,
906 protocol: 5,
907 retry_times: 0,
908 dns_server_index: 0,
909 connected: 0,
910 linux_errno: 0,
911 },
912 ]
913 }
914 })Event";
915
916 constexpr char event_ipv4v6[] = R"Event(
917 NetworkDnsEventReported {
918 dns_query_events:
919 {
920 dns_query_event:[
921 {
922 rcode: 0,
923 type: 28,
924 cache_hit: 1,
925 ip_version: 2,
926 protocol: 5,
927 retry_times: 0,
928 dns_server_index: 0,
929 connected: 0,
930 linux_errno: 0,
931 },
932 {
933 rcode: 0,
934 type: 1,
935 cache_hit: 1,
936 ip_version: 2,
937 protocol: 5,
938 retry_times: 0,
939 dns_server_index: 0,
940 connected: 0,
941 linux_errno: 0,
942 }
943 ]
944 }
945 })Event";
946
947 test::DNSResponder mdnsv6("::1", test::kDefaultMdnsListenService);
948 mdnsv6.addMapping(host_name, ns_type::ns_t_a, v4addr);
949 mdnsv6.addMapping(host_name, ns_type::ns_t_aaaa, v6addr);
950 ASSERT_TRUE(mdnsv6.startServer());
951 ASSERT_EQ(0, SetResolvers());
952
953 static const struct TestConfig {
954 int ai_family;
955 const std::vector<std::string> expected_addr;
956 const std::string expected_event;
957 } testConfigs[]{
958 {AF_UNSPEC, {v4addr, v6addr}, event_ipv4v6},
959 {AF_INET, {v4addr}, event_ipv4},
960 {AF_INET6, {v6addr}, event_ipv6},
961 };
962
963 for (const auto& config : testConfigs) {
964 SCOPED_TRACE(fmt::format("family: {}", config.ai_family));
965 mdnsv6.clearQueries();
966
967 addrinfo* result = nullptr;
968 const addrinfo hints = {.ai_family = config.ai_family, .ai_socktype = SOCK_DGRAM};
969 NetworkDnsEventReported event;
970 int rv = resolv_getaddrinfo("hello.local", nullptr, &hints, &mNetcontext, APP_SOCKET_NONE,
971 &result, &event);
972 EXPECT_THAT(event,
973 NetworkDnsEventEq(fromNetworkDnsEventReportedStr(config.expected_event)));
974 ScopedAddrinfo result_cleanup(result);
975
976 if (config.ai_family == AF_UNSPEC) {
977 EXPECT_EQ(0, rv);
978 EXPECT_EQ(2U, GetNumQueries(mdnsv6, host_name));
979 const std::vector<std::string> result_strs = ToStrings(result);
980 EXPECT_THAT(result_strs, testing::UnorderedElementsAreArray(config.expected_addr));
981 } else if (config.ai_family == AF_INET) {
982 EXPECT_EQ(0, rv);
983 EXPECT_EQ(1U, GetNumQueries(mdnsv6, host_name));
984 const std::vector<std::string> result_strs = ToStrings(result);
985 EXPECT_THAT(result_strs, testing::UnorderedElementsAreArray(config.expected_addr));
986 } else if (config.ai_family == AF_INET6) {
987 EXPECT_EQ(0, rv);
988 EXPECT_EQ(1U, GetNumQueries(mdnsv6, host_name));
989 const std::vector<std::string> result_strs = ToStrings(result);
990 EXPECT_THAT(result_strs, testing::UnorderedElementsAreArray(config.expected_addr));
991 }
992 resolv_flush_cache_for_net(TEST_NETID);
993 }
994 }
995
TEST_F(ResolvGetAddrInfoTest,MdnsIllegalHostname)996 TEST_F(ResolvGetAddrInfoTest, MdnsIllegalHostname) {
997 constexpr char v6addr[] = "::127.0.0.3";
998 constexpr char v4addr[] = "127.0.0.3";
999
1000 test::DNSResponder mdnsv6("::1", test::kDefaultMdnsListenService);
1001 ASSERT_TRUE(mdnsv6.startServer());
1002 ASSERT_EQ(0, SetResolvers());
1003 mdnsv6.clearQueries();
1004
1005 constexpr char illegalHostname[] = "hello^.local.";
1006 // Expect to get no address because hostname format is illegal.
1007 //
1008 // Ex:
1009 // ANSWER SECTION:
1010 // hello^.local. IN A 127.0.0.3
1011 // hello^.local. IN AAAA ::127.0.0.3
1012 //
1013 // In this example, querying "hello^.local" should get no address because
1014 // "hello^.local" has an illegal char '^' in the middle of label.
1015 mdnsv6.addMapping(illegalHostname, ns_type::ns_t_a, v4addr);
1016 mdnsv6.addMapping(illegalHostname, ns_type::ns_t_aaaa, v6addr);
1017
1018 for (const auto& family : {AF_INET, AF_INET6, AF_UNSPEC}) {
1019 SCOPED_TRACE(fmt::format("family: {}, illegalHostname: {}", family, illegalHostname));
1020 addrinfo* result = nullptr;
1021 const addrinfo hints = {.ai_family = family};
1022 NetworkDnsEventReported event;
1023 int rv = resolv_getaddrinfo("hello^.local", nullptr, &hints, &mNetcontext, APP_SOCKET_NONE,
1024 &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, APP_SOCKET_NONE,
1051 &result, &event);
1052 EXPECT_EQ(NETD_RESOLV_TIMEOUT, rv);
1053 }
1054 }
1055
TEST_F(ResolvGetAddrInfoTest,CnamesNoIpAddress)1056 TEST_F(ResolvGetAddrInfoTest, CnamesNoIpAddress) {
1057 constexpr char ACNAME[] = "acname"; // expect a cname in answer
1058 constexpr char CNAMES[] = "cnames"; // expect cname chain in answer
1059
1060 test::DNSResponder dns;
1061 dns.addMapping("cnames.example.com.", ns_type::ns_t_cname, "acname.example.com.");
1062 dns.addMapping("acname.example.com.", ns_type::ns_t_cname, "hello.example.com.");
1063 ASSERT_TRUE(dns.startServer());
1064 ASSERT_EQ(0, SetResolvers());
1065
1066 static const struct TestConfig {
1067 const char* name;
1068 int family;
1069 } testConfigs[]{
1070 // clang-format off
1071 {ACNAME, AF_INET},
1072 {ACNAME, AF_INET6},
1073 {ACNAME, AF_UNSPEC},
1074 {CNAMES, AF_INET},
1075 {CNAMES, AF_INET6},
1076 {CNAMES, AF_UNSPEC},
1077 // clang-format on
1078 };
1079
1080 for (const auto& config : testConfigs) {
1081 SCOPED_TRACE(fmt::format("config.family: {}, config.name: {}", config.family, config.name));
1082
1083 addrinfo* res = nullptr;
1084 const addrinfo hints = {.ai_family = config.family};
1085 NetworkDnsEventReported event;
1086 int rv = resolv_getaddrinfo(config.name, nullptr, &hints, &mNetcontext, APP_SOCKET_NONE,
1087 &res, &event);
1088 ScopedAddrinfo result(res);
1089 EXPECT_EQ(nullptr, result);
1090 EXPECT_EQ(EAI_FAIL, rv);
1091 }
1092 }
1093
TEST_F(ResolvGetAddrInfoTest,CnamesBrokenChainByIllegalCname)1094 TEST_F(ResolvGetAddrInfoTest, CnamesBrokenChainByIllegalCname) {
1095 test::DNSResponder dns;
1096 ASSERT_TRUE(dns.startServer());
1097 ASSERT_EQ(0, SetResolvers());
1098
1099 static const struct TestConfig {
1100 const char* name;
1101 const char* cname;
1102 std::string asHostName() const { return fmt::format("{}.example.com.", name); }
1103
1104 // Illegal cname is verified by res_hnok() in system/netd/resolv/res_comp.cpp.
1105 } testConfigs[]{
1106 // clang-format off
1107 {NAME(kBadCharAfterPeriodHost), kBadCharAfterPeriodHost},
1108 {NAME(kBadCharBeforePeriodHost), kBadCharBeforePeriodHost},
1109 {NAME(kBadCharAtTheEndHost), kBadCharAtTheEndHost},
1110 {NAME(kBadCharInTheMiddleOfLabelHost), kBadCharInTheMiddleOfLabelHost},
1111 // clang-format on
1112 };
1113
1114 for (const auto& config : testConfigs) {
1115 const std::string testHostName = config.asHostName();
1116
1117 // Expect to get no address because the cname chain is broken by an illegal cname format.
1118 //
1119 // Ex:
1120 // ANSWER SECTION:
1121 // hello.example.com. IN CNAME a.ex^ample.com.
1122 // a.ex^ample.com. IN A 1.2.3.3
1123 // a.ex^ample.com. IN AAAA 2001:db8::42
1124 //
1125 // In this example, querying hello.example.com should get no address because
1126 // "a.ex^ample.com" has an illegal char '^' in the middle of label.
1127 dns.addMapping(testHostName.c_str(), ns_type::ns_t_cname, config.cname);
1128 dns.addMapping(config.cname, ns_type::ns_t_a, "1.2.3.3");
1129 dns.addMapping(config.cname, ns_type::ns_t_aaaa, "2001:db8::42");
1130
1131 for (const auto& family : {AF_INET, AF_INET6, AF_UNSPEC}) {
1132 SCOPED_TRACE(fmt::format("family: {}, testHostName: {}", family, testHostName));
1133
1134 addrinfo* res = nullptr;
1135 const addrinfo hints = {.ai_family = family};
1136 NetworkDnsEventReported event;
1137 int rv = resolv_getaddrinfo(config.name, nullptr, &hints, &mNetcontext, APP_SOCKET_NONE,
1138 &res, &event);
1139 ScopedAddrinfo result(res);
1140 EXPECT_EQ(nullptr, result);
1141 EXPECT_EQ(EAI_FAIL, rv);
1142 }
1143 }
1144 }
1145
TEST_F(ResolvGetAddrInfoTest,CnamesInfiniteLoop)1146 TEST_F(ResolvGetAddrInfoTest, CnamesInfiniteLoop) {
1147 test::DNSResponder dns;
1148 dns.addMapping("hello.example.com.", ns_type::ns_t_cname, "a.example.com.");
1149 dns.addMapping("a.example.com.", ns_type::ns_t_cname, "hello.example.com.");
1150 ASSERT_TRUE(dns.startServer());
1151 ASSERT_EQ(0, SetResolvers());
1152
1153 for (const auto& family : {AF_INET, AF_INET6, AF_UNSPEC}) {
1154 SCOPED_TRACE(fmt::format("family: {}", family));
1155
1156 addrinfo* res = nullptr;
1157 const addrinfo hints = {.ai_family = family};
1158 NetworkDnsEventReported event;
1159 int rv = resolv_getaddrinfo("hello", nullptr, &hints, &mNetcontext, APP_SOCKET_NONE, &res,
1160 &event);
1161 ScopedAddrinfo result(res);
1162 EXPECT_EQ(nullptr, result);
1163 EXPECT_EQ(EAI_FAIL, rv);
1164 }
1165 }
1166
TEST_F(ResolvGetAddrInfoTest,MultiAnswerSections)1167 TEST_F(ResolvGetAddrInfoTest, MultiAnswerSections) {
1168 test::DNSResponder dns(test::DNSResponder::MappingType::DNS_HEADER);
1169 // Answer section for query type {A, AAAA}
1170 // Type A:
1171 // hello.example.com. IN A 1.2.3.1
1172 // hello.example.com. IN A 1.2.3.2
1173 // Type AAAA:
1174 // hello.example.com. IN AAAA 2001:db8::41
1175 // hello.example.com. IN AAAA 2001:db8::42
1176 StartDns(dns, {MakeDnsMessage(kHelloExampleCom, ns_type::ns_t_a, {"1.2.3.1", "1.2.3.2"}),
1177 MakeDnsMessage(kHelloExampleCom, ns_type::ns_t_aaaa,
1178 {"2001:db8::41", "2001:db8::42"})});
1179 ASSERT_EQ(0, SetResolvers());
1180
1181 for (const auto& family : {AF_INET, AF_INET6, AF_UNSPEC}) {
1182 SCOPED_TRACE(fmt::format("family: {}", family));
1183
1184 addrinfo* res = nullptr;
1185 // If the socket type is not specified, every address will appear twice, once for
1186 // SOCK_STREAM and one for SOCK_DGRAM. Just pick one because the addresses for
1187 // the second query of different socket type are responded by the cache.
1188 const addrinfo hints = {.ai_family = family, .ai_socktype = SOCK_STREAM};
1189 NetworkDnsEventReported event;
1190 int rv = resolv_getaddrinfo("hello", nullptr, &hints, &mNetcontext, APP_SOCKET_NONE, &res,
1191 &event);
1192 ScopedAddrinfo result(res);
1193 ASSERT_NE(nullptr, result);
1194 ASSERT_EQ(0, rv);
1195
1196 const std::vector<std::string> result_strs = ToStrings(result);
1197 if (family == AF_INET) {
1198 EXPECT_EQ(1U, GetNumQueries(dns, kHelloExampleCom));
1199 EXPECT_THAT(result_strs, testing::UnorderedElementsAreArray({"1.2.3.1", "1.2.3.2"}));
1200 } else if (family == AF_INET6) {
1201 EXPECT_EQ(1U, GetNumQueries(dns, kHelloExampleCom));
1202 EXPECT_THAT(result_strs,
1203 testing::UnorderedElementsAreArray({"2001:db8::41", "2001:db8::42"}));
1204 } else if (family == AF_UNSPEC) {
1205 EXPECT_EQ(0U, GetNumQueries(dns, kHelloExampleCom)); // no query because of the cache
1206 EXPECT_THAT(result_strs,
1207 testing::UnorderedElementsAreArray(
1208 {"1.2.3.1", "1.2.3.2", "2001:db8::41", "2001:db8::42"}));
1209 }
1210 dns.clearQueries();
1211 }
1212 }
1213
TEST_F(ResolvGetAddrInfoTest,TruncatedResponse)1214 TEST_F(ResolvGetAddrInfoTest, TruncatedResponse) {
1215 // Following fields will not be verified during the test in proto NetworkDnsEventReported.
1216 // So don't need to config those values: event_type, return_code, latency_micros,
1217 // hints_ai_flags, res_nsend_flags, network_type, private_dns_modes.
1218 constexpr char event_ipv4[] = R"Event(
1219 NetworkDnsEventReported {
1220 dns_query_events:
1221 {
1222 dns_query_event:[
1223 {
1224 rcode: 254,
1225 type: 1,
1226 cache_hit: 1,
1227 ip_version: 1,
1228 protocol: 1,
1229 retry_times: 0,
1230 dns_server_index: 0,
1231 connected: 0,
1232 linux_errno: 7,
1233 },
1234 {
1235 rcode: 0,
1236 type: 1,
1237 cache_hit: 1,
1238 ip_version: 1,
1239 protocol: 2,
1240 retry_times: 0,
1241 dns_server_index: 0,
1242 connected: 0,
1243 linux_errno: 0,
1244 },
1245 {
1246 rcode: 0,
1247 type: 1,
1248 cache_hit: 2,
1249 ip_version: 0,
1250 protocol: 0,
1251 retry_times: 0,
1252 dns_server_index: 0,
1253 connected: 0,
1254 linux_errno: 0,
1255 }
1256 ]
1257 }
1258 })Event";
1259
1260 constexpr char event_ipv6[] = R"Event(
1261 NetworkDnsEventReported {
1262 dns_query_events:
1263 {
1264 dns_query_event:[
1265 {
1266 rcode: 254,
1267 type: 28,
1268 cache_hit: 1,
1269 ip_version: 1,
1270 protocol: 1,
1271 retry_times: 0,
1272 dns_server_index: 0,
1273 connected: 0,
1274 linux_errno: 7,
1275 },
1276 {
1277 rcode: 0,
1278 type: 28,
1279 cache_hit: 1,
1280 ip_version: 1,
1281 protocol: 2,
1282 retry_times: 0,
1283 dns_server_index: 0,
1284 connected: 0,
1285 linux_errno: 0,
1286 },
1287 {
1288 rcode: 0,
1289 type: 28,
1290 cache_hit: 2,
1291 ip_version: 0,
1292 protocol: 0,
1293 retry_times: 0,
1294 dns_server_index: 0,
1295 connected: 0,
1296 linux_errno: 0,
1297 }
1298 ]
1299 }
1300 })Event";
1301
1302 test::DNSResponder dns;
1303 dns.addMapping(kHelloExampleCom, ns_type::ns_t_cname, kCnameA);
1304 dns.addMapping(kCnameA, ns_type::ns_t_cname, kCnameB);
1305 dns.addMapping(kCnameB, ns_type::ns_t_cname, kCnameC);
1306 dns.addMapping(kCnameC, ns_type::ns_t_cname, kCnameD);
1307 dns.addMapping(kCnameD, ns_type::ns_t_a, kHelloExampleComAddrV4);
1308 dns.addMapping(kCnameD, ns_type::ns_t_aaaa, kHelloExampleComAddrV6);
1309 ASSERT_TRUE(dns.startServer());
1310 ASSERT_EQ(0, SetResolvers());
1311
1312 static const struct TestConfig {
1313 int ai_family;
1314 const std::string expected_addr;
1315 const std::string expected_event;
1316 } testConfigs[]{
1317 {AF_INET, kHelloExampleComAddrV4, event_ipv4},
1318 {AF_INET6, kHelloExampleComAddrV6, event_ipv6},
1319 };
1320
1321 for (const auto& config : testConfigs) {
1322 SCOPED_TRACE(fmt::format("family: {}", config.ai_family));
1323 dns.clearQueries();
1324
1325 addrinfo* result = nullptr;
1326 const addrinfo hints = {.ai_family = config.ai_family};
1327 NetworkDnsEventReported event;
1328 int rv = resolv_getaddrinfo("hello", nullptr, &hints, &mNetcontext, APP_SOCKET_NONE,
1329 &result, &event);
1330 EXPECT_THAT(event,
1331 NetworkDnsEventEq(fromNetworkDnsEventReportedStr(config.expected_event)));
1332 ScopedAddrinfo result_cleanup(result);
1333 EXPECT_EQ(rv, 0);
1334 EXPECT_TRUE(result != nullptr);
1335 // Expect UDP response is truncated. The resolver retries over TCP. See RFC 1035
1336 // section 4.2.1.
1337 EXPECT_EQ(GetNumQueriesForProtocol(dns, IPPROTO_UDP, kHelloExampleCom), 1U);
1338 EXPECT_EQ(GetNumQueriesForProtocol(dns, IPPROTO_TCP, kHelloExampleCom), 1U);
1339 EXPECT_EQ(ToString(result), config.expected_addr);
1340 }
1341 }
1342
1343 // Audit if Resolver read out of bounds, which needs HWAddressSanitizer build to trigger SIGABRT.
TEST_F(ResolvGetAddrInfoTest,OverlengthResp)1344 TEST_F(ResolvGetAddrInfoTest, OverlengthResp) {
1345 std::vector<std::string> nameList;
1346 // Construct a long enough record that exceeds 8192 bytes (the maximum buffer size):
1347 // Header: (Transaction ID, Flags, ...) = 12 bytes
1348 // Query: 19(Name)+2(Type)+2(Class) = 23 bytes
1349 // The 1st answer RR: 19(Name)+2(Type)+2(Class)+4(TTL)+2(Len)+77(CNAME) = 106 bytes
1350 // 2nd-50th answer RRs: 49*(77(Name)+2(Type)+2(Class)+4(TTL)+2(Len)+77(CNAME)) = 8036 bytes
1351 // The last answer RR: 77(Name)+2(Type)+2(Class)+4(TTL)+2(Len)+4(Address) = 91 bytes
1352 // ----------------------------------------------------------------------------------------
1353 // Sum: 8268 bytes
1354 for (int i = 0; i < 10; i++) {
1355 std::string domain(kMaxmiumLabelSize / 2, 'a' + i);
1356 for (int j = 0; j < 5; j++) {
1357 nameList.push_back(domain + std::string(kMaxmiumLabelSize / 2 + 1, '0' + j) +
1358 kExampleComDomain + ".");
1359 }
1360 }
1361 test::DNSResponder dns;
1362 dns.addMapping(kHelloExampleCom, ns_type::ns_t_cname, nameList[0]);
1363 for (size_t i = 0; i < nameList.size() - 1; i++) {
1364 dns.addMapping(nameList[i], ns_type::ns_t_cname, nameList[i + 1]);
1365 }
1366 dns.addMapping(nameList[nameList.size() - 1], ns_type::ns_t_a, kHelloExampleComAddrV4);
1367
1368 ASSERT_TRUE(dns.startServer());
1369 ASSERT_EQ(0, SetResolvers());
1370 addrinfo* result = nullptr;
1371 const addrinfo hints = {.ai_family = AF_INET};
1372 NetworkDnsEventReported event;
1373 int rv = resolv_getaddrinfo("hello", nullptr, &hints, &mNetcontext, APP_SOCKET_NONE, &result,
1374 &event);
1375 ScopedAddrinfo result_cleanup(result);
1376 EXPECT_EQ(rv, EAI_FAIL);
1377 EXPECT_TRUE(result == nullptr);
1378 EXPECT_EQ(GetNumQueriesForProtocol(dns, IPPROTO_UDP, kHelloExampleCom), 2U);
1379 EXPECT_EQ(GetNumQueriesForProtocol(dns, IPPROTO_TCP, kHelloExampleCom), 2U);
1380 }
1381
TEST_F(GetHostByNameForNetContextTest,AlphabeticalHostname)1382 TEST_F(GetHostByNameForNetContextTest, AlphabeticalHostname) {
1383 constexpr char host_name[] = "jiababuei.example.com.";
1384 constexpr char v4addr[] = "1.2.3.4";
1385 constexpr char v6addr[] = "::1.2.3.4";
1386 // Following fields will not be verified during the test in proto NetworkDnsEventReported.
1387 // So don't need to config those values: event_type, return_code, latency_micros,
1388 // hints_ai_flags, res_nsend_flags, network_type, private_dns_modes.
1389 constexpr char event_ipv4[] = R"Event(
1390 NetworkDnsEventReported {
1391 dns_query_events:
1392 {
1393 dns_query_event:[
1394 {
1395 rcode: 0,
1396 type: 1,
1397 cache_hit: 1,
1398 ip_version: 1,
1399 protocol: 1,
1400 retry_times: 0,
1401 dns_server_index: 0,
1402 connected: 0,
1403 latency_micros: 0,
1404 linux_errno: 0,
1405 }
1406 ]
1407 }
1408 })Event";
1409
1410 constexpr char event_ipv6[] = R"Event(
1411 NetworkDnsEventReported {
1412 dns_query_events:
1413 {
1414 dns_query_event:[
1415 {
1416 rcode: 0,
1417 type: 28,
1418 cache_hit: 1,
1419 ip_version: 1,
1420 protocol: 1,
1421 retry_times: 0,
1422 dns_server_index: 0,
1423 connected: 0,
1424 latency_micros: 0,
1425 linux_errno: 0,
1426 }
1427 ]
1428 }
1429 })Event";
1430 test::DNSResponder dns;
1431 dns.addMapping(host_name, ns_type::ns_t_a, v4addr);
1432 dns.addMapping(host_name, ns_type::ns_t_aaaa, v6addr);
1433 ASSERT_TRUE(dns.startServer());
1434 ASSERT_EQ(0, SetResolvers());
1435
1436 static const struct TestConfig {
1437 int ai_family;
1438 const std::string expected_addr;
1439 const std::string expected_event;
1440 } testConfigs[]{
1441 {AF_INET, v4addr, event_ipv4},
1442 {AF_INET6, v6addr, event_ipv6},
1443 };
1444
1445 for (const auto& config : testConfigs) {
1446 SCOPED_TRACE(fmt::format("family: {}", config.ai_family));
1447 dns.clearQueries();
1448
1449 hostent* hp = nullptr;
1450 hostent hbuf;
1451 char tmpbuf[MAXPACKET];
1452 NetworkDnsEventReported event;
1453 int rv = resolv_gethostbyname("jiababuei", config.ai_family, &hbuf, tmpbuf, sizeof(tmpbuf),
1454 &mNetcontext, APP_SOCKET_NONE, &hp, &event);
1455 EXPECT_THAT(event,
1456 NetworkDnsEventEq(fromNetworkDnsEventReportedStr(config.expected_event)));
1457 EXPECT_EQ(0, rv);
1458 EXPECT_TRUE(hp != nullptr);
1459 EXPECT_EQ(1U, GetNumQueries(dns, host_name));
1460 EXPECT_EQ(config.expected_addr, ToString(hp));
1461 }
1462 }
1463
TEST_F(GetHostByNameForNetContextTest,IllegalHostname)1464 TEST_F(GetHostByNameForNetContextTest, IllegalHostname) {
1465 test::DNSResponder dns;
1466 ASSERT_TRUE(dns.startServer());
1467 ASSERT_EQ(0, SetResolvers());
1468
1469 // Illegal hostname is verified by res_hnok() in system/netd/resolv/res_comp.cpp.
1470 static constexpr char const* illegalHostnames[] = {
1471 kBadCharAfterPeriodHost,
1472 kBadCharBeforePeriodHost,
1473 kBadCharAtTheEndHost,
1474 kBadCharInTheMiddleOfLabelHost,
1475 };
1476
1477 for (const auto& hostname : illegalHostnames) {
1478 // Expect to get no address because hostname format is illegal.
1479 //
1480 // Ex:
1481 // ANSWER SECTION:
1482 // a.ex^ample.com. IN A 1.2.3.3
1483 // a.ex^ample.com. IN AAAA 2001:db8::42
1484 //
1485 // In this example, querying "a.ex^ample.com" should get no address because
1486 // "a.ex^ample.com" has an illegal char '^' in the middle of label.
1487 dns.addMapping(hostname, ns_type::ns_t_a, "1.2.3.3");
1488 dns.addMapping(hostname, ns_type::ns_t_aaaa, "2001:db8::42");
1489
1490 for (const auto& family : {AF_INET, AF_INET6}) {
1491 SCOPED_TRACE(fmt::format("family: {}, config.name: {}", family, hostname));
1492
1493 struct hostent* hp = nullptr;
1494 hostent hbuf;
1495 char tmpbuf[MAXPACKET];
1496 NetworkDnsEventReported event;
1497 int rv = resolv_gethostbyname(hostname, family, &hbuf, tmpbuf, sizeof(tmpbuf),
1498 &mNetcontext, APP_SOCKET_NONE, &hp, &event);
1499 EXPECT_EQ(nullptr, hp);
1500 EXPECT_EQ(EAI_FAIL, rv);
1501 }
1502 }
1503 }
1504
TEST_F(GetHostByNameForNetContextTest,NoData)1505 TEST_F(GetHostByNameForNetContextTest, NoData) {
1506 constexpr char v4_host_name[] = "v4only.example.com.";
1507
1508 test::DNSResponder dns;
1509 dns.addMapping(v4_host_name, ns_type::ns_t_a, "1.2.3.3");
1510 ASSERT_TRUE(dns.startServer());
1511 ASSERT_EQ(0, SetResolvers());
1512 dns.clearQueries();
1513
1514 // Want AAAA answer but DNS server has A answer only.
1515 hostent* hp = nullptr;
1516 hostent hbuf;
1517 char tmpbuf[MAXPACKET];
1518 NetworkDnsEventReported event;
1519 int rv = resolv_gethostbyname("v4only", AF_INET6, &hbuf, tmpbuf, sizeof tmpbuf, &mNetcontext,
1520 APP_SOCKET_NONE, &hp, &event);
1521 EXPECT_LE(1U, GetNumQueries(dns, v4_host_name));
1522 EXPECT_EQ(nullptr, hp);
1523 EXPECT_EQ(EAI_NODATA, rv);
1524 }
1525
TEST_F(GetHostByNameForNetContextTest,ServerResponseError)1526 TEST_F(GetHostByNameForNetContextTest, ServerResponseError) {
1527 constexpr char host_name[] = "hello.example.com.";
1528
1529 static const struct TestConfig {
1530 ns_rcode rcode;
1531 int expected_eai_error; // expected result
1532
1533 // Only test failure RCODE [1..5] in RFC 1035 section 4.1.1 and skip successful RCODE 0
1534 // which means no error. Note that the return error codes aren't mapped by rcode in the
1535 // test case SERVFAIL, NOTIMP and REFUSED. See the comment of res_nsend()
1536 // in system\netd\resolv\res_query.cpp for more detail.
1537 } testConfigs[]{
1538 // clang-format off
1539 {ns_rcode::ns_r_formerr, EAI_FAIL},
1540 {ns_rcode::ns_r_servfail, EAI_AGAIN}, // Not mapped by rcode.
1541 {ns_rcode::ns_r_nxdomain, EAI_NODATA},
1542 {ns_rcode::ns_r_notimpl, EAI_AGAIN}, // Not mapped by rcode.
1543 {ns_rcode::ns_r_refused, EAI_AGAIN}, // Not mapped by rcode.
1544 // clang-format on
1545 };
1546
1547 for (const auto& config : testConfigs) {
1548 SCOPED_TRACE(fmt::format("rcode: {}", static_cast<int>(config.rcode)));
1549
1550 test::DNSResponder dns(config.rcode);
1551 dns.addMapping(host_name, ns_type::ns_t_a, "1.2.3.4");
1552 dns.setResponseProbability(0.0); // always ignore requests and response preset rcode
1553 ASSERT_TRUE(dns.startServer());
1554 ASSERT_EQ(0, SetResolvers());
1555
1556 hostent* hp = nullptr;
1557 hostent hbuf;
1558 char tmpbuf[MAXPACKET];
1559 NetworkDnsEventReported event;
1560 int rv = resolv_gethostbyname(host_name, AF_INET, &hbuf, tmpbuf, sizeof tmpbuf,
1561 &mNetcontext, APP_SOCKET_NONE, &hp, &event);
1562 EXPECT_EQ(nullptr, hp);
1563 EXPECT_EQ(config.expected_eai_error, rv);
1564 }
1565 }
1566
1567 // TODO: Add private DNS server timeout test.
TEST_F(GetHostByNameForNetContextTest,ServerTimeout)1568 TEST_F(GetHostByNameForNetContextTest, ServerTimeout) {
1569 constexpr char host_name[] = "hello.example.com.";
1570 test::DNSResponder dns(static_cast<ns_rcode>(-1) /*no response*/);
1571 dns.addMapping(host_name, ns_type::ns_t_a, "1.2.3.4");
1572 dns.setResponseProbability(0.0); // always ignore requests and don't respond
1573 ASSERT_TRUE(dns.startServer());
1574 ASSERT_EQ(0, SetResolvers());
1575
1576 hostent* hp = nullptr;
1577 hostent hbuf;
1578 char tmpbuf[MAXPACKET];
1579 NetworkDnsEventReported event;
1580 int rv = resolv_gethostbyname(host_name, AF_INET, &hbuf, tmpbuf, sizeof tmpbuf, &mNetcontext,
1581 APP_SOCKET_NONE, &hp, &event);
1582 EXPECT_EQ(NETD_RESOLV_TIMEOUT, rv);
1583 }
1584
TEST_F(GetHostByNameForNetContextTest,CnamesNoIpAddress)1585 TEST_F(GetHostByNameForNetContextTest, CnamesNoIpAddress) {
1586 constexpr char ACNAME[] = "acname"; // expect a cname in answer
1587 constexpr char CNAMES[] = "cnames"; // expect cname chain in answer
1588
1589 test::DNSResponder dns;
1590 dns.addMapping("cnames.example.com.", ns_type::ns_t_cname, "acname.example.com.");
1591 dns.addMapping("acname.example.com.", ns_type::ns_t_cname, "hello.example.com.");
1592 ASSERT_TRUE(dns.startServer());
1593 ASSERT_EQ(0, SetResolvers());
1594
1595 static const struct TestConfig {
1596 const char* name;
1597 int family;
1598 } testConfigs[]{
1599 {ACNAME, AF_INET},
1600 {ACNAME, AF_INET6},
1601 {CNAMES, AF_INET},
1602 {CNAMES, AF_INET6},
1603 };
1604
1605 for (const auto& config : testConfigs) {
1606 SCOPED_TRACE(fmt::format("config.family: {}, config.name: {}", config.family, config.name));
1607
1608 struct hostent* hp = nullptr;
1609 hostent hbuf;
1610 char tmpbuf[MAXPACKET];
1611 NetworkDnsEventReported event;
1612 int rv = resolv_gethostbyname(config.name, config.family, &hbuf, tmpbuf, sizeof tmpbuf,
1613 &mNetcontext, APP_SOCKET_NONE, &hp, &event);
1614 EXPECT_EQ(nullptr, hp);
1615 EXPECT_EQ(EAI_FAIL, rv);
1616 }
1617 }
1618
TEST_F(GetHostByNameForNetContextTest,CnamesBrokenChainByIllegalCname)1619 TEST_F(GetHostByNameForNetContextTest, CnamesBrokenChainByIllegalCname) {
1620 test::DNSResponder dns;
1621 ASSERT_TRUE(dns.startServer());
1622 ASSERT_EQ(0, SetResolvers());
1623
1624 static const struct TestConfig {
1625 const char* name;
1626 const char* cname;
1627 std::string asHostName() const { return fmt::format("{}.example.com.", name); }
1628
1629 // Illegal cname is verified by res_hnok() in system/netd/resolv/res_comp.cpp
1630 } testConfigs[]{
1631 // clang-format off
1632 {NAME(kBadCharAfterPeriodHost), kBadCharAfterPeriodHost},
1633 {NAME(kBadCharBeforePeriodHost), kBadCharBeforePeriodHost},
1634 {NAME(kBadCharAtTheEndHost), kBadCharAtTheEndHost},
1635 {NAME(kBadCharInTheMiddleOfLabelHost), kBadCharInTheMiddleOfLabelHost},
1636 // clang-format on
1637 };
1638
1639 for (const auto& config : testConfigs) {
1640 const std::string testHostName = config.asHostName();
1641
1642 // Expect to get no address because the cname chain is broken by an illegal cname format.
1643 //
1644 // Ex:
1645 // ANSWER SECTION:
1646 // hello.example.com. IN CNAME a.ex^ample.com.
1647 // a.ex^ample.com. IN A 1.2.3.3
1648 // a.ex^ample.com. IN AAAA 2001:db8::42
1649 //
1650 // In this example, querying hello.example.com should get no address because
1651 // "a.ex^ample.com" has an illegal char '^' in the middle of label.
1652 dns.addMapping(testHostName.c_str(), ns_type::ns_t_cname, config.cname);
1653 dns.addMapping(config.cname, ns_type::ns_t_a, "1.2.3.3");
1654 dns.addMapping(config.cname, ns_type::ns_t_aaaa, "2001:db8::42");
1655
1656 for (const auto& family : {AF_INET, AF_INET6}) {
1657 SCOPED_TRACE(fmt::format("family: {}, testHostName: {}", family, testHostName));
1658
1659 struct hostent* hp = nullptr;
1660 hostent hbuf;
1661 char tmpbuf[MAXPACKET];
1662 NetworkDnsEventReported event;
1663 int rv = resolv_gethostbyname(config.name, family, &hbuf, tmpbuf, sizeof tmpbuf,
1664 &mNetcontext, APP_SOCKET_NONE, &hp, &event);
1665 EXPECT_EQ(nullptr, hp);
1666 EXPECT_EQ(EAI_FAIL, rv);
1667 }
1668 }
1669 }
1670
TEST_F(GetHostByNameForNetContextTest,CnamesInfiniteLoop)1671 TEST_F(GetHostByNameForNetContextTest, CnamesInfiniteLoop) {
1672 test::DNSResponder dns;
1673 dns.addMapping("hello.example.com.", ns_type::ns_t_cname, "a.example.com.");
1674 dns.addMapping("a.example.com.", ns_type::ns_t_cname, "hello.example.com.");
1675 ASSERT_TRUE(dns.startServer());
1676 ASSERT_EQ(0, SetResolvers());
1677
1678 for (const auto& family : {AF_INET, AF_INET6}) {
1679 SCOPED_TRACE(fmt::format("family: {}", family));
1680
1681 struct hostent* hp = nullptr;
1682 hostent hbuf;
1683 char tmpbuf[MAXPACKET];
1684 NetworkDnsEventReported event;
1685 int rv = resolv_gethostbyname("hello", family, &hbuf, tmpbuf, sizeof tmpbuf, &mNetcontext,
1686 APP_SOCKET_NONE, &hp, &event);
1687 EXPECT_EQ(nullptr, hp);
1688 EXPECT_EQ(EAI_FAIL, rv);
1689 }
1690 }
1691
TEST_F(GetHostByNameForNetContextTest,MdnsAlphabeticalHostname)1692 TEST_F(GetHostByNameForNetContextTest, MdnsAlphabeticalHostname) {
1693 constexpr char v4addr[] = "127.0.0.3";
1694 constexpr char v6addr[] = "::127.0.0.3";
1695 constexpr char host_name[] = "hello.local.";
1696
1697 // Following fields will not be verified during the test in proto NetworkDnsEventReported.
1698 // So don't need to config those values: event_type, return_code, latency_micros,
1699 // hints_ai_flags, res_nsend_flags, network_type, private_dns_modes.
1700 constexpr char event_ipv4[] = R"Event(
1701 NetworkDnsEventReported {
1702 dns_query_events:
1703 {
1704 dns_query_event:[
1705 {
1706 rcode: 0,
1707 type: 1,
1708 cache_hit: 1,
1709 ip_version: 2,
1710 protocol: 5,
1711 retry_times: 0,
1712 dns_server_index: 0,
1713 connected: 0,
1714 latency_micros: 0,
1715 linux_errno: 0,
1716 }
1717 ]
1718 }
1719 })Event";
1720
1721 constexpr char event_ipv6[] = R"Event(
1722 NetworkDnsEventReported {
1723 dns_query_events:
1724 {
1725 dns_query_event:[
1726 {
1727 rcode: 0,
1728 type: 28,
1729 cache_hit: 1,
1730 ip_version: 2,
1731 protocol: 5,
1732 retry_times: 0,
1733 dns_server_index: 0,
1734 connected: 0,
1735 latency_micros: 0,
1736 linux_errno: 0,
1737 }
1738 ]
1739 }
1740 })Event";
1741
1742 test::DNSResponder mdnsv6("::1", test::kDefaultMdnsListenService);
1743
1744 mdnsv6.addMapping(host_name, ns_type::ns_t_a, v4addr);
1745 mdnsv6.addMapping(host_name, ns_type::ns_t_aaaa, v6addr);
1746
1747 ASSERT_TRUE(mdnsv6.startServer());
1748 ASSERT_EQ(0, SetResolvers());
1749
1750 static const struct TestConfig {
1751 int ai_family;
1752 const std::vector<std::string> expected_addr;
1753 const std::string expected_event;
1754 } testConfigs[]{
1755 {AF_INET, {v4addr}, event_ipv4},
1756 {AF_INET6, {v6addr}, event_ipv6},
1757 };
1758
1759 for (const auto& config : testConfigs) {
1760 SCOPED_TRACE(fmt::format("family: {}", config.ai_family));
1761 hostent* result = nullptr;
1762 hostent hbuf;
1763 char tmpbuf[MAXPACKET];
1764 NetworkDnsEventReported event;
1765 mdnsv6.clearQueries();
1766 int rv =
1767 resolv_gethostbyname("hello.local", config.ai_family, &hbuf, tmpbuf, sizeof(tmpbuf),
1768 &mNetcontext, APP_SOCKET_NONE, &result, &event);
1769 EXPECT_THAT(event,
1770 NetworkDnsEventEq(fromNetworkDnsEventReportedStr(config.expected_event)));
1771 EXPECT_EQ(0, rv);
1772 EXPECT_EQ(1U, GetNumQueries(mdnsv6, host_name));
1773 std::vector<std::string> result_strs = ToStrings(result);
1774 EXPECT_THAT(result_strs, testing::UnorderedElementsAreArray(config.expected_addr));
1775
1776 // Ensure the query result is still cached.
1777 // TODO(b/394031336): caching is currently disabled while we work on a cache that supports
1778 // keying by interface. Update values once re-enabled.
1779 mdnsv6.clearQueries();
1780 rv = resolv_gethostbyname("hello.local", config.ai_family, &hbuf, tmpbuf, sizeof(tmpbuf),
1781 &mNetcontext, APP_SOCKET_NONE, &result, &event);
1782 EXPECT_EQ(0, rv);
1783 EXPECT_EQ(1U, GetNumQueries(mdnsv6, host_name));
1784 result_strs = ToStrings(result);
1785 EXPECT_THAT(result_strs, testing::UnorderedElementsAreArray(config.expected_addr));
1786 }
1787 }
1788
TEST_F(GetHostByNameForNetContextTest,MdnsIllegalHostname)1789 TEST_F(GetHostByNameForNetContextTest, MdnsIllegalHostname) {
1790 constexpr char v6addr[] = "::127.0.0.3";
1791 constexpr char v4addr[] = "127.0.0.3";
1792 test::DNSResponder mdnsv6("::1", test::kDefaultMdnsListenService);
1793 ASSERT_TRUE(mdnsv6.startServer());
1794 ASSERT_EQ(0, SetResolvers());
1795 mdnsv6.clearQueries();
1796
1797 constexpr char illegalHostname[] = "hello^.local.";
1798 // Expect to get no address because hostname format is illegal.
1799 //
1800 // Ex:
1801 // ANSWER SECTION:
1802 // hello^.local. IN A 127.0.0.3
1803 // hello^.local. IN AAAA ::127.0.0.3
1804 //
1805 // In this example, querying "hello^.local" should get no address because
1806 // "hello^.local" has an illegal char '^' in the middle of label.
1807 mdnsv6.addMapping(illegalHostname, ns_type::ns_t_a, v4addr);
1808 mdnsv6.addMapping(illegalHostname, ns_type::ns_t_aaaa, v6addr);
1809
1810 SCOPED_TRACE(fmt::format("family: {}, illegalHostname: {}", AF_INET6, illegalHostname));
1811 struct hostent* result = nullptr;
1812 hostent hbuf;
1813 char tmpbuf[MAXPACKET];
1814 NetworkDnsEventReported event;
1815 int rv = resolv_gethostbyname("hello^.local", AF_INET6, &hbuf, tmpbuf, sizeof(tmpbuf),
1816 &mNetcontext, APP_SOCKET_NONE, &result, &event);
1817 EXPECT_EQ(nullptr, result);
1818 EXPECT_EQ(EAI_FAIL, rv);
1819
1820 SCOPED_TRACE(fmt::format("family: {}, illegalHostname: {}", AF_INET, illegalHostname));
1821 rv = resolv_gethostbyname("hello^.local", AF_INET, &hbuf, tmpbuf, sizeof(tmpbuf), &mNetcontext,
1822 APP_SOCKET_NONE, &result, &event);
1823 EXPECT_EQ(nullptr, result);
1824 EXPECT_EQ(EAI_FAIL, rv);
1825 }
1826
TEST_F(GetHostByNameForNetContextTest,MdnsResponderTimeout)1827 TEST_F(GetHostByNameForNetContextTest, MdnsResponderTimeout) {
1828 constexpr char host_name[] = "hello.local.";
1829 test::DNSResponder mdnsv4("127.0.0.3", test::kDefaultMdnsListenService,
1830 static_cast<ns_rcode>(-1));
1831 mdnsv4.setResponseProbability(0.0); // always ignore requests and don't respond
1832 test::DNSResponder mdnsv6("::1", test::kDefaultMdnsListenService, static_cast<ns_rcode>(-1));
1833 mdnsv6.setResponseProbability(0.0);
1834 ASSERT_TRUE(mdnsv4.startServer());
1835 ASSERT_TRUE(mdnsv6.startServer());
1836 ASSERT_EQ(0, SetResolvers());
1837 test::DNSResponder dns("127.0.0.3", test::kDefaultListenService, static_cast<ns_rcode>(-1));
1838 dns.setResponseProbability(0.0);
1839 ASSERT_TRUE(dns.startServer());
1840
1841 for (const auto& family : {AF_INET, AF_INET6}) {
1842 SCOPED_TRACE(fmt::format("family: {}, host_name: {}", family, host_name));
1843 hostent* result = nullptr;
1844 hostent hbuf;
1845 char tmpbuf[MAXPACKET];
1846 NetworkDnsEventReported event;
1847 int rv = resolv_gethostbyname("hello.local", family, &hbuf, tmpbuf, sizeof tmpbuf,
1848 &mNetcontext, APP_SOCKET_NONE, &result, &event);
1849 EXPECT_EQ(NETD_RESOLV_TIMEOUT, rv);
1850 }
1851 }
1852
TEST_F(ResolvCommonFunctionTest,GetCustTableByName)1853 TEST_F(ResolvCommonFunctionTest, GetCustTableByName) {
1854 const char custAddrV4[] = "1.2.3.4";
1855 const char custAddrV6[] = "::1.2.3.4";
1856 const char hostnameV4V6[] = "v4v6.example.com.";
1857 const aidl::android::net::ResolverOptionsParcel& resolverOptions = {
1858 {
1859 {custAddrV4, hostnameV4V6},
1860 {custAddrV6, hostnameV4V6},
1861 },
1862 aidl::android::net::IDnsResolver::TC_MODE_DEFAULT};
1863 const std::vector<int32_t>& transportTypes = {IDnsResolver::TRANSPORT_WIFI};
1864 EXPECT_EQ(0, resolv_set_nameservers(TEST_NETID, servers, domains, params, resolverOptions,
1865 transportTypes));
1866 EXPECT_THAT(getCustomizedTableByName(TEST_NETID, hostnameV4V6),
1867 testing::UnorderedElementsAreArray({custAddrV4, custAddrV6}));
1868
1869 // Query address by mismatch hostname.
1870 ASSERT_TRUE(getCustomizedTableByName(TEST_NETID, "not.in.cust.table").empty());
1871
1872 // Query address by different netid.
1873 ASSERT_TRUE(getCustomizedTableByName(TEST_NETID + 1, hostnameV4V6).empty());
1874 resolv_create_cache_for_net(TEST_NETID + 1);
1875 EXPECT_EQ(0, resolv_set_nameservers(TEST_NETID + 1, servers, domains, params, resolverOptions,
1876 transportTypes));
1877 EXPECT_THAT(getCustomizedTableByName(TEST_NETID + 1, hostnameV4V6),
1878 testing::UnorderedElementsAreArray({custAddrV4, custAddrV6}));
1879 }
1880
TEST_F(ResolvCommonFunctionTest,GetNetworkTypesForNet)1881 TEST_F(ResolvCommonFunctionTest, GetNetworkTypesForNet) {
1882 const aidl::android::net::ResolverOptionsParcel& resolverOptions = {
1883 {} /* hosts */, aidl::android::net::IDnsResolver::TC_MODE_DEFAULT};
1884 const std::vector<int32_t>& transportTypes = {IDnsResolver::TRANSPORT_WIFI,
1885 IDnsResolver::TRANSPORT_VPN};
1886 EXPECT_EQ(0, resolv_set_nameservers(TEST_NETID, servers, domains, params, resolverOptions,
1887 transportTypes));
1888 EXPECT_EQ(android::net::NT_WIFI_VPN, resolv_get_network_types_for_net(TEST_NETID));
1889 }
1890
TEST_F(ResolvCommonFunctionTest,ConvertTransportsToNetworkType)1891 TEST_F(ResolvCommonFunctionTest, ConvertTransportsToNetworkType) {
1892 static const struct TestConfig {
1893 int32_t networkType;
1894 std::vector<int32_t> transportTypes;
1895 } testConfigs[] = {
1896 {android::net::NT_CELLULAR, {IDnsResolver::TRANSPORT_CELLULAR}},
1897 {android::net::NT_WIFI, {IDnsResolver::TRANSPORT_WIFI}},
1898 {android::net::NT_BLUETOOTH, {IDnsResolver::TRANSPORT_BLUETOOTH}},
1899 {android::net::NT_ETHERNET, {IDnsResolver::TRANSPORT_ETHERNET}},
1900 {android::net::NT_VPN, {IDnsResolver::TRANSPORT_VPN}},
1901 {android::net::NT_WIFI_AWARE, {IDnsResolver::TRANSPORT_WIFI_AWARE}},
1902 {android::net::NT_LOWPAN, {IDnsResolver::TRANSPORT_LOWPAN}},
1903 {android::net::NT_SATELLITE, {IDnsResolver::TRANSPORT_SATELLITE}},
1904 {android::net::NT_CELLULAR_VPN,
1905 {IDnsResolver::TRANSPORT_CELLULAR, IDnsResolver::TRANSPORT_VPN}},
1906 {android::net::NT_CELLULAR_VPN,
1907 {IDnsResolver::TRANSPORT_VPN, IDnsResolver::TRANSPORT_CELLULAR}},
1908 {android::net::NT_WIFI_VPN,
1909 {IDnsResolver::TRANSPORT_WIFI, IDnsResolver::TRANSPORT_VPN}},
1910 {android::net::NT_WIFI_VPN,
1911 {IDnsResolver::TRANSPORT_VPN, IDnsResolver::TRANSPORT_WIFI}},
1912 {android::net::NT_BLUETOOTH_VPN,
1913 {IDnsResolver::TRANSPORT_BLUETOOTH, IDnsResolver::TRANSPORT_VPN}},
1914 {android::net::NT_BLUETOOTH_VPN,
1915 {IDnsResolver::TRANSPORT_VPN, IDnsResolver::TRANSPORT_BLUETOOTH}},
1916 {android::net::NT_ETHERNET_VPN,
1917 {IDnsResolver::TRANSPORT_ETHERNET, IDnsResolver::TRANSPORT_VPN}},
1918 {android::net::NT_ETHERNET_VPN,
1919 {IDnsResolver::TRANSPORT_VPN, IDnsResolver::TRANSPORT_ETHERNET}},
1920 {android::net::NT_UNKNOWN, {IDnsResolver::TRANSPORT_VPN, IDnsResolver::TRANSPORT_VPN}},
1921 {android::net::NT_UNKNOWN,
1922 {IDnsResolver::TRANSPORT_WIFI, IDnsResolver::TRANSPORT_LOWPAN}},
1923 {android::net::NT_UNKNOWN, {}},
1924 {android::net::NT_UNKNOWN,
1925 {IDnsResolver::TRANSPORT_CELLULAR, IDnsResolver::TRANSPORT_BLUETOOTH,
1926 IDnsResolver::TRANSPORT_VPN}},
1927 {android::net::NT_WIFI_CELLULAR_VPN,
1928 {IDnsResolver::TRANSPORT_CELLULAR, IDnsResolver::TRANSPORT_WIFI,
1929 IDnsResolver::TRANSPORT_VPN}},
1930 {android::net::NT_WIFI_CELLULAR_VPN,
1931 {IDnsResolver::TRANSPORT_VPN, IDnsResolver::TRANSPORT_WIFI,
1932 IDnsResolver::TRANSPORT_CELLULAR}},
1933 };
1934 for (const auto& config : testConfigs) {
1935 EXPECT_EQ(config.networkType, convert_network_type(config.transportTypes));
1936 }
1937 }
1938
1939 // Note that local host file function, files_getaddrinfo(), of resolv_getaddrinfo()
1940 // is not tested because it only returns a boolean (success or failure) without any error number.
1941
1942 // TODO: Add test for resolv_getaddrinfo().
1943 // - DNS response message parsing.
1944 // - Unexpected type of resource record (RR).
1945 // - Invalid length CNAME, or QNAME.
1946 // - Unexpected amount of questions.
1947 // - CNAME RDATA with the domain name which has null label(s).
1948 // TODO: Add test for resolv_gethostbyname().
1949 // - Invalid parameters.
1950 // - DNS response message parsing.
1951 // - Unexpected type of resource record (RR).
1952 // - Invalid length CNAME, or QNAME.
1953 // - Unexpected amount of questions.
1954 // - CNAME RDATA with the domain name which has null label(s).
1955 // TODO: Add test for resolv_gethostbyaddr().
1956
1957 } // end of namespace net
1958 } // end of namespace android
1959