• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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