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