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