• 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 "libnetd_resolv_test"
18 
19 #include <gtest/gtest.h>
20 
21 #include <android-base/stringprintf.h>
22 #include <arpa/inet.h>
23 #include <netdb.h>
24 
25 #include "dns_responder.h"
26 #include "getaddrinfo.h"
27 #include "gethnamaddr.h"
28 #include "resolv_cache.h"
29 
30 // TODO: make this dynamic and stop depending on implementation details.
31 constexpr unsigned int TEST_NETID = 30;
32 
33 // Specifying 0 in ai_socktype or ai_protocol of struct addrinfo indicates that any type or
34 // protocol can be returned by getaddrinfo().
35 constexpr unsigned int ANY = 0;
36 
37 using android::base::StringPrintf;
38 
39 namespace android {
40 namespace net {
41 
42 // Minimize class ResolverTest to be class TestBase because class TestBase doesn't need all member
43 // functions of class ResolverTest and class DnsResponderClient.
44 class TestBase : public ::testing::Test {
45   protected:
SetUp()46     void SetUp() override {
47         // Create cache for test
48         resolv_create_cache_for_net(TEST_NETID);
49     }
TearDown()50     void TearDown() override {
51         // Delete cache for test
52         resolv_delete_cache_for_net(TEST_NETID);
53     }
54 
ToString(const hostent * he)55     static std::string ToString(const hostent* he) {
56         if (he == nullptr) return "<null>";
57         char buffer[INET6_ADDRSTRLEN];
58         if (!inet_ntop(he->h_addrtype, he->h_addr_list[0], buffer, sizeof(buffer))) {
59             return "<invalid>";
60         }
61         return buffer;
62     }
63 
ToString(const addrinfo * ai)64     static std::string ToString(const addrinfo* ai) {
65         if (!ai) return "<null>";
66         for (const auto* aip = ai; aip != nullptr; aip = aip->ai_next) {
67             char host[NI_MAXHOST];
68             int rv = getnameinfo(aip->ai_addr, aip->ai_addrlen, host, sizeof(host), nullptr, 0,
69                                  NI_NUMERICHOST);
70             if (rv != 0) return gai_strerror(rv);
71             return host;
72         }
73         return "<invalid>";
74     }
75 
GetNumQueries(const test::DNSResponder & dns,const char * name) const76     size_t GetNumQueries(const test::DNSResponder& dns, const char* name) const {
77         auto queries = dns.queries();
78         size_t found = 0;
79         for (const auto& p : queries) {
80             if (p.first == name) {
81                 ++found;
82             }
83         }
84         return found;
85     }
86 
87     const char* mDefaultSearchDomains = "example.com";
88     const res_params mDefaultParams_Binder = {
89             .sample_validity = 300,
90             .success_threshold = 25,
91             .min_samples = 8,
92             .max_samples = 8,
93             .base_timeout_msec = 1000,
94             .retry_count = 2,
95     };
96     const android_net_context mNetcontext = {
97             .app_netid = TEST_NETID,
98             .app_mark = MARK_UNSET,
99             .dns_netid = TEST_NETID,
100             .dns_mark = MARK_UNSET,
101             .uid = NET_CONTEXT_INVALID_UID,
102     };
103 };
104 
105 class GetAddrInfoForNetContextTest : public TestBase {};
106 class GetHostByNameForNetContextTest : public TestBase {};
107 
TEST_F(GetAddrInfoForNetContextTest,InvalidParameters)108 TEST_F(GetAddrInfoForNetContextTest, InvalidParameters) {
109     // Both null "netcontext" and null "res" of android_getaddrinfofornetcontext() are not tested
110     // here because they are checked by assert() without returning any error number.
111 
112     // Invalid hostname and servname.
113     // Both hostname and servname are null pointers. Expect error number EAI_NONAME.
114     struct addrinfo* result = nullptr;
115     int rv = android_getaddrinfofornetcontext(nullptr /*hostname*/, nullptr /*servname*/,
116                                               nullptr /*hints*/, &mNetcontext, &result);
117     EXPECT_EQ(EAI_NONAME, rv);
118     if (result) {
119         freeaddrinfo(result);
120         result = nullptr;
121     }
122 
123     // Invalid hints.
124     // These place holders are used to test function call with unrequired parameters.
125     // The content is not important because function call returns error directly if
126     // there have any unrequired parameter.
127     char placeholder_cname[] = "invalid_cname";
128     sockaddr placeholder_addr = {};
129     addrinfo placeholder_next = {};
130     static const struct TestConfig {
131         int ai_flags;
132         socklen_t ai_addrlen;
133         char* ai_canonname;
134         struct sockaddr* ai_addr;
135         struct addrinfo* ai_next;
136         int expected_errorno;  // expected result
137 
138         std::string asParameters() const {
139             return StringPrintf("0x%x/%u/%s/%p/%p", ai_flags, ai_addrlen,
140                                 ai_canonname ? ai_canonname : "(null)", (void*) ai_addr,
141                                 (void*) ai_next);
142         }
143     } testConfigs[]{
144             {0, sizeof(struct in_addr) /*bad*/, nullptr, nullptr, nullptr, EAI_BADHINTS},
145             {0, 0, placeholder_cname /*bad*/, nullptr, nullptr, EAI_BADHINTS},
146             {0, 0, nullptr, &placeholder_addr /*bad*/, nullptr, EAI_BADHINTS},
147             {0, 0, nullptr, nullptr, &placeholder_next /*bad*/, EAI_BADHINTS},
148             {AI_ALL /*bad*/, 0, nullptr, nullptr, nullptr, EAI_BADFLAGS},
149             {AI_V4MAPPED_CFG /*bad*/, 0, nullptr, nullptr, nullptr, EAI_BADFLAGS},
150             {AI_V4MAPPED /*bad*/, 0, nullptr, nullptr, nullptr, EAI_BADFLAGS},
151             {AI_DEFAULT /*bad*/, 0, nullptr, nullptr, nullptr, EAI_BADFLAGS},
152     };
153 
154     for (const auto& config : testConfigs) {
155         SCOPED_TRACE(config.asParameters());
156 
157         // In current test configuration set, ai_family, ai_protocol and ai_socktype are not
158         // checked because other fields cause hints error check failed first.
159         const struct addrinfo hints = {
160                 .ai_flags = config.ai_flags,
161                 .ai_family = AF_UNSPEC,
162                 .ai_socktype = ANY,
163                 .ai_protocol = ANY,
164                 .ai_addrlen = config.ai_addrlen,
165                 .ai_canonname = config.ai_canonname,
166                 .ai_addr = config.ai_addr,
167                 .ai_next = config.ai_next,
168         };
169 
170         rv = android_getaddrinfofornetcontext("localhost", nullptr /*servname*/, &hints,
171                                               &mNetcontext, &result);
172         EXPECT_EQ(config.expected_errorno, rv);
173 
174         if (result) {
175             freeaddrinfo(result);
176             result = nullptr;
177         }
178     }
179 }
180 
TEST_F(GetAddrInfoForNetContextTest,InvalidParameters_Family)181 TEST_F(GetAddrInfoForNetContextTest, InvalidParameters_Family) {
182     for (int family = 0; family < AF_MAX; ++family) {
183         if (family == AF_UNSPEC || family == AF_INET || family == AF_INET6) {
184             continue;  // skip supported family
185         }
186         SCOPED_TRACE(StringPrintf("family: %d", family));
187 
188         struct addrinfo* result = nullptr;
189         const struct addrinfo hints = {
190                 .ai_family = family,  // unsupported family
191         };
192 
193         int rv = android_getaddrinfofornetcontext("localhost", nullptr /*servname*/, &hints,
194                                                   &mNetcontext, &result);
195         EXPECT_EQ(EAI_FAMILY, rv);
196 
197         if (result) freeaddrinfo(result);
198     }
199 }
200 
TEST_F(GetAddrInfoForNetContextTest,InvalidParameters_MeaningfulSocktypeAndProtocolCombination)201 TEST_F(GetAddrInfoForNetContextTest, InvalidParameters_MeaningfulSocktypeAndProtocolCombination) {
202     static const int families[] = {PF_INET, PF_INET6, PF_UNSPEC};
203     // Skip to test socket type SOCK_RAW in meaningful combination (explore_options[]) of
204     // system\netd\resolv\getaddrinfo.cpp. In explore_options[], the socket type SOCK_RAW always
205     // comes with protocol ANY which causes skipping meaningful socktype/protocol combination
206     // check. So it nerver returns error number EAI_BADHINTS which we want to test in this test
207     // case.
208     static const int socktypes[] = {SOCK_STREAM, SOCK_DGRAM};
209 
210     // If both socktype/protocol are specified, check non-meaningful combination returns
211     // expected error number EAI_BADHINTS. See meaningful combination in explore_options[] of
212     // system\netd\resolv\getaddrinfo.cpp.
213     for (const auto& family : families) {
214         for (const auto& socktype : socktypes) {
215             for (int protocol = 0; protocol < IPPROTO_MAX; ++protocol) {
216                 SCOPED_TRACE(StringPrintf("family: %d, socktype: %d, protocol: %d", family,
217                                           socktype, protocol));
218 
219                 // Both socktype/protocol need to be specified.
220                 if (!socktype || !protocol) continue;
221 
222                 // Skip meaningful combination in explore_options[] of
223                 // system\netd\resolv\getaddrinfo.cpp.
224                 if ((family == AF_INET6 && socktype == SOCK_DGRAM && protocol == IPPROTO_UDP) ||
225                     (family == AF_INET6 && socktype == SOCK_STREAM && protocol == IPPROTO_TCP) ||
226                     (family == AF_INET && socktype == SOCK_DGRAM && protocol == IPPROTO_UDP) ||
227                     (family == AF_INET && socktype == SOCK_STREAM && protocol == IPPROTO_TCP) ||
228                     (family == AF_UNSPEC && socktype == SOCK_DGRAM && protocol == IPPROTO_UDP) ||
229                     (family == AF_UNSPEC && socktype == SOCK_STREAM && protocol == IPPROTO_TCP)) {
230                     continue;
231                 }
232 
233                 struct addrinfo* result = nullptr;
234                 const struct addrinfo hints = {
235                         .ai_family = family,
236                         .ai_protocol = protocol,
237                         .ai_socktype = socktype,
238                 };
239 
240                 int rv = android_getaddrinfofornetcontext("localhost", nullptr /*servname*/, &hints,
241                                                           &mNetcontext, &result);
242                 EXPECT_EQ(EAI_BADHINTS, rv);
243 
244                 if (result) freeaddrinfo(result);
245             }
246         }
247     }
248 }
249 
TEST_F(GetAddrInfoForNetContextTest,InvalidParameters_PortNameAndNumber)250 TEST_F(GetAddrInfoForNetContextTest, InvalidParameters_PortNameAndNumber) {
251     constexpr char http_portno[] = "80";
252     constexpr char invalid_portno[] = "65536";  // out of valid port range from 0 to 65535
253     constexpr char http_portname[] = "http";
254     constexpr char invalid_portname[] = "invalid_portname";
255 
256     static const struct TestConfig {
257         int ai_flags;
258         int ai_family;
259         int ai_socktype;
260         const char* servname;
261         int expected_errorno;  // expected result
262 
263         std::string asParameters() const {
264             return StringPrintf("0x%x/%d/%d/%s", ai_flags, ai_family, ai_socktype,
265                                 servname ? servname : "(null)");
266         }
267     } testConfigs[]{
268             {0, AF_INET, SOCK_RAW /*bad*/, http_portno, EAI_SERVICE},
269             {0, AF_INET6, SOCK_RAW /*bad*/, http_portno, EAI_SERVICE},
270             {0, AF_UNSPEC, SOCK_RAW /*bad*/, http_portno, EAI_SERVICE},
271             {0, AF_INET, SOCK_RDM /*bad*/, http_portno, EAI_SOCKTYPE},
272             {0, AF_INET6, SOCK_RDM /*bad*/, http_portno, EAI_SOCKTYPE},
273             {0, AF_UNSPEC, SOCK_RDM /*bad*/, http_portno, EAI_SOCKTYPE},
274             {0, AF_INET, SOCK_SEQPACKET /*bad*/, http_portno, EAI_SOCKTYPE},
275             {0, AF_INET6, SOCK_SEQPACKET /*bad*/, http_portno, EAI_SOCKTYPE},
276             {0, AF_UNSPEC, SOCK_SEQPACKET /*bad*/, http_portno, EAI_SOCKTYPE},
277             {0, AF_INET, SOCK_DCCP /*bad*/, http_portno, EAI_SOCKTYPE},
278             {0, AF_INET6, SOCK_DCCP /*bad*/, http_portno, EAI_SOCKTYPE},
279             {0, AF_UNSPEC, SOCK_DCCP /*bad*/, http_portno, EAI_SOCKTYPE},
280             {0, AF_INET, SOCK_PACKET /*bad*/, http_portno, EAI_SOCKTYPE},
281             {0, AF_INET6, SOCK_PACKET /*bad*/, http_portno, EAI_SOCKTYPE},
282             {0, AF_UNSPEC, SOCK_PACKET /*bad*/, http_portno, EAI_SOCKTYPE},
283             {0, AF_INET, ANY, invalid_portno /*bad*/, EAI_SERVICE},
284             {0, AF_INET, SOCK_STREAM, invalid_portno /*bad*/, EAI_SERVICE},
285             {0, AF_INET, SOCK_DGRAM, invalid_portno /*bad*/, EAI_SERVICE},
286             {0, AF_INET6, ANY, invalid_portno /*bad*/, EAI_SERVICE},
287             {0, AF_INET6, SOCK_STREAM, invalid_portno /*bad*/, EAI_SERVICE},
288             {0, AF_INET6, SOCK_DGRAM, invalid_portno /*bad*/, EAI_SERVICE},
289             {0, AF_UNSPEC, ANY, invalid_portno /*bad*/, EAI_SERVICE},
290             {0, AF_UNSPEC, SOCK_STREAM, invalid_portno /*bad*/, EAI_SERVICE},
291             {0, AF_UNSPEC, SOCK_DGRAM, invalid_portno /*bad*/, EAI_SERVICE},
292             {AI_NUMERICSERV, AF_INET, ANY, http_portname /*bad*/, EAI_NONAME},
293             {AI_NUMERICSERV, AF_INET, SOCK_STREAM, http_portname /*bad*/, EAI_NONAME},
294             {AI_NUMERICSERV, AF_INET, SOCK_DGRAM, http_portname /*bad*/, EAI_NONAME},
295             {AI_NUMERICSERV, AF_INET6, ANY, http_portname /*bad*/, EAI_NONAME},
296             {AI_NUMERICSERV, AF_INET6, SOCK_STREAM, http_portname /*bad*/, EAI_NONAME},
297             {AI_NUMERICSERV, AF_INET6, SOCK_DGRAM, http_portname /*bad*/, EAI_NONAME},
298             {AI_NUMERICSERV, AF_UNSPEC, ANY, http_portname /*bad*/, EAI_NONAME},
299             {AI_NUMERICSERV, AF_UNSPEC, SOCK_STREAM, http_portname /*bad*/, EAI_NONAME},
300             {AI_NUMERICSERV, AF_UNSPEC, SOCK_DGRAM, http_portname /*bad*/, EAI_NONAME},
301             {0, AF_INET, ANY, invalid_portname /*bad*/, EAI_SERVICE},
302             {0, AF_INET, SOCK_STREAM, invalid_portname /*bad*/, EAI_SERVICE},
303             {0, AF_INET, SOCK_DGRAM, invalid_portname /*bad*/, EAI_SERVICE},
304             {0, AF_INET6, ANY, invalid_portname /*bad*/, EAI_SERVICE},
305             {0, AF_INET6, SOCK_STREAM, invalid_portname /*bad*/, EAI_SERVICE},
306             {0, AF_INET6, SOCK_DGRAM, invalid_portname /*bad*/, EAI_SERVICE},
307             {0, AF_UNSPEC, ANY, invalid_portname /*bad*/, EAI_SERVICE},
308             {0, AF_UNSPEC, SOCK_STREAM, invalid_portname /*bad*/, EAI_SERVICE},
309             {0, AF_UNSPEC, SOCK_DGRAM, invalid_portname /*bad*/, EAI_SERVICE},
310     };
311 
312     for (const auto& config : testConfigs) {
313         const std::string testParameters = config.asParameters();
314         SCOPED_TRACE(testParameters);
315 
316         const struct addrinfo hints = {
317                 .ai_flags = config.ai_flags,
318                 .ai_family = config.ai_family,
319                 .ai_socktype = config.ai_socktype,
320         };
321 
322         struct addrinfo* result = nullptr;
323         int rv = android_getaddrinfofornetcontext("localhost", config.servname, &hints,
324                                                   &mNetcontext, &result);
325         EXPECT_EQ(config.expected_errorno, rv);
326 
327         if (result) freeaddrinfo(result);
328     }
329 }
330 
TEST_F(GetAddrInfoForNetContextTest,AlphabeticalHostname_NoData)331 TEST_F(GetAddrInfoForNetContextTest, AlphabeticalHostname_NoData) {
332     constexpr char listen_addr[] = "127.0.0.3";
333     constexpr char listen_srv[] = "53";
334     constexpr char v4_host_name[] = "v4only.example.com.";
335     test::DNSResponder dns(listen_addr, listen_srv, 250, ns_rcode::ns_r_servfail);
336     dns.addMapping(v4_host_name, ns_type::ns_t_a, "1.2.3.3");
337     ASSERT_TRUE(dns.startServer());
338     const char* servers[] = {listen_addr};
339     ASSERT_EQ(0, resolv_set_nameservers_for_net(TEST_NETID, servers,
340                                                 sizeof(servers) / sizeof(servers[0]),
341                                                 mDefaultSearchDomains, &mDefaultParams_Binder));
342     dns.clearQueries();
343 
344     // Want AAAA answer but DNS server has A answer only.
345     struct addrinfo* result = nullptr;
346     const addrinfo hints = {.ai_family = AF_INET6};
347     int rv = android_getaddrinfofornetcontext("v4only", nullptr, &hints, &mNetcontext, &result);
348     EXPECT_LE(1U, GetNumQueries(dns, v4_host_name));
349     EXPECT_TRUE(result == nullptr);
350     EXPECT_EQ(EAI_NODATA, rv);
351 
352     if (result) freeaddrinfo(result);
353 }
354 
TEST_F(GetAddrInfoForNetContextTest,AlphabeticalHostname)355 TEST_F(GetAddrInfoForNetContextTest, AlphabeticalHostname) {
356     constexpr char listen_addr[] = "127.0.0.3";
357     constexpr char listen_srv[] = "53";
358     constexpr char host_name[] = "sawadee.example.com.";
359     constexpr char v4addr[] = "1.2.3.4";
360     constexpr char v6addr[] = "::1.2.3.4";
361 
362     test::DNSResponder dns(listen_addr, listen_srv, 250, ns_rcode::ns_r_servfail);
363     dns.addMapping(host_name, ns_type::ns_t_a, v4addr);
364     dns.addMapping(host_name, ns_type::ns_t_aaaa, v6addr);
365     ASSERT_TRUE(dns.startServer());
366     const char* servers[] = {listen_addr};
367     ASSERT_EQ(0, resolv_set_nameservers_for_net(TEST_NETID, servers,
368                                                 sizeof(servers) / sizeof(servers[0]),
369                                                 mDefaultSearchDomains, &mDefaultParams_Binder));
370 
371     static const struct TestConfig {
372         int ai_family;
373         const std::string expected_addr;
374     } testConfigs[]{
375             {AF_INET, v4addr},
376             {AF_INET6, v6addr},
377     };
378 
379     for (const auto& config : testConfigs) {
380         SCOPED_TRACE(StringPrintf("family: %d", config.ai_family));
381         dns.clearQueries();
382 
383         struct addrinfo* result = nullptr;
384         const struct addrinfo hints = {.ai_family = config.ai_family};
385         int rv =
386                 android_getaddrinfofornetcontext("sawadee", nullptr, &hints, &mNetcontext, &result);
387         EXPECT_EQ(0, rv);
388         EXPECT_TRUE(result != nullptr);
389         EXPECT_EQ(1U, GetNumQueries(dns, host_name));
390         EXPECT_EQ(config.expected_addr, ToString(result));
391 
392         if (result) freeaddrinfo(result);
393     }
394 }
395 
TEST_F(GetAddrInfoForNetContextTest,ServerResponseError)396 TEST_F(GetAddrInfoForNetContextTest, ServerResponseError) {
397     constexpr char listen_addr[] = "127.0.0.3";
398     constexpr char listen_srv[] = "53";
399     constexpr char host_name[] = "hello.example.com.";
400 
401     static const struct TestConfig {
402         ns_rcode rcode;
403         int expected_errorno;  // expected result
404 
405         // Only test failure RCODE [1..5] in RFC 1035 section 4.1.1 and skip successful RCODE 0
406         // which means no error.
407     } testConfigs[]{
408             // clang-format off
409             {ns_rcode::ns_r_formerr, EAI_FAIL},
410             {ns_rcode::ns_r_servfail, EAI_AGAIN},
411             {ns_rcode::ns_r_nxdomain, EAI_NODATA},
412             {ns_rcode::ns_r_notimpl, EAI_FAIL},
413             {ns_rcode::ns_r_refused, EAI_FAIL},
414             // clang-format on
415     };
416 
417     for (const auto& config : testConfigs) {
418         SCOPED_TRACE(StringPrintf("rcode: %d", config.rcode));
419 
420         test::DNSResponder dns(listen_addr, listen_srv, 250,
421                                config.rcode /*response specific rcode*/);
422         dns.addMapping(host_name, ns_type::ns_t_a, "1.2.3.4");
423         dns.setResponseProbability(0.0);  // always ignore requests and response preset rcode
424         ASSERT_TRUE(dns.startServer());
425         const char* servers[] = {listen_addr};
426         ASSERT_EQ(0, resolv_set_nameservers_for_net(TEST_NETID, servers,
427                                                     sizeof(servers) / sizeof(servers[0]),
428                                                     mDefaultSearchDomains, &mDefaultParams_Binder));
429 
430         struct addrinfo* result = nullptr;
431         const struct addrinfo hints = {.ai_family = AF_UNSPEC};
432         int rv =
433                 android_getaddrinfofornetcontext(host_name, nullptr, &hints, &mNetcontext, &result);
434         EXPECT_EQ(config.expected_errorno, rv);
435 
436         if (result) freeaddrinfo(result);
437     }
438 }
439 
440 // TODO: Add private DNS server timeout test.
TEST_F(GetAddrInfoForNetContextTest,ServerTimeout)441 TEST_F(GetAddrInfoForNetContextTest, ServerTimeout) {
442     constexpr char listen_addr[] = "127.0.0.3";
443     constexpr char listen_srv[] = "53";
444     constexpr char host_name[] = "hello.example.com.";
445     test::DNSResponder dns(listen_addr, listen_srv, 250, static_cast<ns_rcode>(-1) /*no response*/);
446     dns.addMapping(host_name, ns_type::ns_t_a, "1.2.3.4");
447     dns.setResponseProbability(0.0);  // always ignore requests and don't response
448     ASSERT_TRUE(dns.startServer());
449     const char* servers[] = {listen_addr};
450     ASSERT_EQ(0, resolv_set_nameservers_for_net(TEST_NETID, servers,
451                                                 sizeof(servers) / sizeof(servers[0]),
452                                                 mDefaultSearchDomains, &mDefaultParams_Binder));
453 
454     struct addrinfo* result = nullptr;
455     const struct addrinfo hints = {.ai_family = AF_UNSPEC};
456     int rv = android_getaddrinfofornetcontext("hello", nullptr, &hints, &mNetcontext, &result);
457     EXPECT_EQ(NETD_RESOLV_TIMEOUT, rv);
458 
459     if (result) freeaddrinfo(result);
460 }
461 
TEST_F(GetHostByNameForNetContextTest,AlphabeticalHostname)462 TEST_F(GetHostByNameForNetContextTest, AlphabeticalHostname) {
463     constexpr char listen_addr[] = "127.0.0.3";
464     constexpr char listen_srv[] = "53";
465     constexpr char host_name[] = "jiababuei.example.com.";
466     constexpr char v4addr[] = "1.2.3.4";
467     constexpr char v6addr[] = "::1.2.3.4";
468 
469     test::DNSResponder dns(listen_addr, listen_srv, 250, ns_rcode::ns_r_servfail);
470     dns.addMapping(host_name, ns_type::ns_t_a, v4addr);
471     dns.addMapping(host_name, ns_type::ns_t_aaaa, v6addr);
472     ASSERT_TRUE(dns.startServer());
473     const char* servers[] = {listen_addr};
474     ASSERT_EQ(0, resolv_set_nameservers_for_net(TEST_NETID, servers,
475                                                 sizeof(servers) / sizeof(servers[0]),
476                                                 mDefaultSearchDomains, &mDefaultParams_Binder));
477 
478     static const struct TestConfig {
479         int ai_family;
480         const std::string expected_addr;
481     } testConfigs[]{
482             {AF_INET, v4addr},
483             {AF_INET6, v6addr},
484     };
485 
486     for (const auto& config : testConfigs) {
487         SCOPED_TRACE(StringPrintf("family: %d", config.ai_family));
488         dns.clearQueries();
489 
490         struct hostent* hp = nullptr;
491         int rv = android_gethostbynamefornetcontext("jiababuei", config.ai_family, &mNetcontext,
492                                                     &hp);
493         EXPECT_EQ(0, rv);
494         EXPECT_TRUE(hp != nullptr);
495         EXPECT_EQ(1U, GetNumQueries(dns, host_name));
496         EXPECT_EQ(config.expected_addr, ToString(hp));
497     }
498 }
499 
TEST_F(GetHostByNameForNetContextTest,NoData)500 TEST_F(GetHostByNameForNetContextTest, NoData) {
501     constexpr char listen_addr[] = "127.0.0.3";
502     constexpr char listen_srv[] = "53";
503     constexpr char v4_host_name[] = "v4only.example.com.";
504     test::DNSResponder dns(listen_addr, listen_srv, 250, ns_rcode::ns_r_servfail);
505     dns.addMapping(v4_host_name, ns_type::ns_t_a, "1.2.3.3");
506     ASSERT_TRUE(dns.startServer());
507     const char* servers[] = {listen_addr};
508     ASSERT_EQ(0, resolv_set_nameservers_for_net(TEST_NETID, servers,
509                                                 sizeof(servers) / sizeof(servers[0]),
510                                                 mDefaultSearchDomains, &mDefaultParams_Binder));
511     dns.clearQueries();
512 
513     // Want AAAA answer but DNS server has A answer only.
514     struct hostent* hp = nullptr;
515     int rv = android_gethostbynamefornetcontext("v4only", AF_INET6, &mNetcontext, &hp);
516     EXPECT_LE(1U, GetNumQueries(dns, v4_host_name));
517     EXPECT_TRUE(hp == nullptr);
518     EXPECT_EQ(EAI_NODATA, rv);
519 }
520 
TEST_F(GetHostByNameForNetContextTest,ServerResponseError)521 TEST_F(GetHostByNameForNetContextTest, ServerResponseError) {
522     constexpr char listen_addr[] = "127.0.0.3";
523     constexpr char listen_srv[] = "53";
524     constexpr char host_name[] = "hello.example.com.";
525 
526     static const struct TestConfig {
527         ns_rcode rcode;
528         int expected_errorno;  // expected result
529 
530         // Only test failure RCODE [1..5] in RFC 1035 section 4.1.1 and skip successful RCODE 0
531         // which means no error. Note that the return error codes aren't mapped by rcode in the
532         // test case SERVFAIL, NOTIMP and REFUSED. See the comment of res_nsend()
533         // in system\netd\resolv\res_query.cpp for more detail.
534     } testConfigs[]{
535             // clang-format off
536             {ns_rcode::ns_r_formerr, EAI_FAIL},
537             {ns_rcode::ns_r_servfail, EAI_AGAIN},  // Not mapped by rcode.
538             {ns_rcode::ns_r_nxdomain, EAI_NODATA},
539             {ns_rcode::ns_r_notimpl, EAI_AGAIN},  // Not mapped by rcode.
540             {ns_rcode::ns_r_refused, EAI_AGAIN},  // Not mapped by rcode.
541             // clang-format on
542     };
543 
544     for (const auto& config : testConfigs) {
545         SCOPED_TRACE(StringPrintf("rcode: %d", config.rcode));
546 
547         test::DNSResponder dns(listen_addr, listen_srv, 250,
548                                config.rcode /*response specific rcode*/);
549         dns.addMapping(host_name, ns_type::ns_t_a, "1.2.3.4");
550         dns.setResponseProbability(0.0);  // always ignore requests and response preset rcode
551         ASSERT_TRUE(dns.startServer());
552         const char* servers[] = {listen_addr};
553         ASSERT_EQ(0, resolv_set_nameservers_for_net(TEST_NETID, servers,
554                                                     sizeof(servers) / sizeof(servers[0]),
555                                                     mDefaultSearchDomains, &mDefaultParams_Binder));
556 
557         struct hostent* hp = nullptr;
558         int rv = android_gethostbynamefornetcontext(host_name, AF_INET, &mNetcontext, &hp);
559         EXPECT_TRUE(hp == nullptr);
560         EXPECT_EQ(config.expected_errorno, rv);
561     }
562 }
563 
564 // TODO: Add private DNS server timeout test.
TEST_F(GetHostByNameForNetContextTest,ServerTimeout)565 TEST_F(GetHostByNameForNetContextTest, ServerTimeout) {
566     constexpr char listen_addr[] = "127.0.0.3";
567     constexpr char listen_srv[] = "53";
568     constexpr char host_name[] = "hello.example.com.";
569     test::DNSResponder dns(listen_addr, listen_srv, 250, static_cast<ns_rcode>(-1) /*no response*/);
570     dns.addMapping(host_name, ns_type::ns_t_a, "1.2.3.4");
571     dns.setResponseProbability(0.0);  // always ignore requests and don't response
572     ASSERT_TRUE(dns.startServer());
573     const char* servers[] = {listen_addr};
574     ASSERT_EQ(0, resolv_set_nameservers_for_net(TEST_NETID, servers,
575                                                 sizeof(servers) / sizeof(servers[0]),
576                                                 mDefaultSearchDomains, &mDefaultParams_Binder));
577 
578     struct hostent* hp = nullptr;
579     int rv = android_gethostbynamefornetcontext(host_name, AF_INET, &mNetcontext, &hp);
580     EXPECT_EQ(NETD_RESOLV_TIMEOUT, rv);
581 }
582 
583 // Note that local host file function, files_getaddrinfo(), of android_getaddrinfofornetcontext()
584 // is not tested because it only returns a boolean (success or failure) without any error number.
585 
586 // TODO: Add test NULL hostname, or numeric hostname for android_getaddrinfofornetcontext.
587 // TODO: Add test invalid parameters for android_gethostbynamefornetcontext.
588 // TODO: Add test for android_gethostbyaddrfornetcontext.
589 
590 }  // end of namespace net
591 }  // end of namespace android
592