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