blob: f4ba012d4849a9339796127aba6b78dae95d9fcb [file] [log] [blame]
nuccachen0efcc802018-11-28 18:19:39 +08001/*
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
Ken Chen5471dca2019-04-15 15:25:35 +080017#define LOG_TAG "resolv"
nuccachen0efcc802018-11-28 18:19:39 +080018
19#include <gtest/gtest.h>
20
21#include <android-base/stringprintf.h>
Hungming Chen947aab02018-12-27 18:33:19 +080022#include <arpa/inet.h>
nuccachen0efcc802018-11-28 18:19:39 +080023#include <netdb.h>
24
25#include "dns_responder.h"
26#include "netd_resolv/resolv.h"
27
28// TODO: make this dynamic and stop depending on implementation details.
29constexpr unsigned int TEST_NETID = 30;
30
31// Specifying 0 in ai_socktype or ai_protocol of struct addrinfo indicates that any type or
32// protocol can be returned by getaddrinfo().
33constexpr unsigned int ANY = 0;
34
35using android::base::StringPrintf;
36
37namespace android {
38namespace net {
39
40// Minimize class ResolverTest to be class TestBase because class TestBase doesn't need all member
41// functions of class ResolverTest and class DnsResponderClient.
42class TestBase : public ::testing::Test {
43 protected:
Luke Huang9b80e6c2019-04-09 17:54:09 +080044 void SetUp() override {
45 // Create cache for test
46 resolv_create_cache_for_net(TEST_NETID);
47 }
48 void TearDown() override {
49 // Delete cache for test
nuccachen0efcc802018-11-28 18:19:39 +080050 resolv_delete_cache_for_net(TEST_NETID);
nuccachen0efcc802018-11-28 18:19:39 +080051 }
52
Hungming Chen947aab02018-12-27 18:33:19 +080053 static std::string ToString(const hostent* he) {
54 if (he == nullptr) return "<null>";
55 char buffer[INET6_ADDRSTRLEN];
56 if (!inet_ntop(he->h_addrtype, he->h_addr_list[0], buffer, sizeof(buffer))) {
57 return "<invalid>";
58 }
59 return buffer;
60 }
61
nuccachen0efcc802018-11-28 18:19:39 +080062 static std::string ToString(const addrinfo* ai) {
63 if (!ai) return "<null>";
64 for (const auto* aip = ai; aip != nullptr; aip = aip->ai_next) {
65 char host[NI_MAXHOST];
66 int rv = getnameinfo(aip->ai_addr, aip->ai_addrlen, host, sizeof(host), nullptr, 0,
67 NI_NUMERICHOST);
68 if (rv != 0) return gai_strerror(rv);
69 return host;
70 }
71 return "<invalid>";
72 }
73
74 size_t GetNumQueries(const test::DNSResponder& dns, const char* name) const {
75 auto queries = dns.queries();
76 size_t found = 0;
77 for (const auto& p : queries) {
78 if (p.first == name) {
79 ++found;
80 }
81 }
82 return found;
83 }
84
85 const char* mDefaultSearchDomains = "example.com";
Bernie Innocenti758005f2019-02-19 18:08:36 +090086 const res_params mDefaultParams_Binder = {
nuccachen0efcc802018-11-28 18:19:39 +080087 .sample_validity = 300,
88 .success_threshold = 25,
89 .min_samples = 8,
90 .max_samples = 8,
waynemaa74195e2019-01-18 14:02:31 +080091 .base_timeout_msec = 1000,
92 .retry_count = 2,
nuccachen0efcc802018-11-28 18:19:39 +080093 };
Hungming Chen947aab02018-12-27 18:33:19 +080094 const android_net_context mNetcontext = {
95 .app_netid = TEST_NETID,
nuccachen0efcc802018-11-28 18:19:39 +080096 .app_mark = MARK_UNSET,
Hungming Chen947aab02018-12-27 18:33:19 +080097 .dns_netid = TEST_NETID,
nuccachen0efcc802018-11-28 18:19:39 +080098 .dns_mark = MARK_UNSET,
99 .uid = NET_CONTEXT_INVALID_UID,
100 };
Hungming Chen947aab02018-12-27 18:33:19 +0800101};
nuccachen0efcc802018-11-28 18:19:39 +0800102
Hungming Chen947aab02018-12-27 18:33:19 +0800103class GetAddrInfoForNetContextTest : public TestBase {};
104class GetHostByNameForNetContextTest : public TestBase {};
105
106TEST_F(GetAddrInfoForNetContextTest, InvalidParameters) {
nuccachen0efcc802018-11-28 18:19:39 +0800107 // Both null "netcontext" and null "res" of android_getaddrinfofornetcontext() are not tested
108 // here because they are checked by assert() without returning any error number.
109
110 // Invalid hostname and servname.
111 // Both hostname and servname are null pointers. Expect error number EAI_NONAME.
Hungming Chen947aab02018-12-27 18:33:19 +0800112 struct addrinfo* result = nullptr;
nuccachen0efcc802018-11-28 18:19:39 +0800113 int rv = android_getaddrinfofornetcontext(nullptr /*hostname*/, nullptr /*servname*/,
Hungming Chen947aab02018-12-27 18:33:19 +0800114 nullptr /*hints*/, &mNetcontext, &result);
nuccachen0efcc802018-11-28 18:19:39 +0800115 EXPECT_EQ(EAI_NONAME, rv);
116 if (result) {
117 freeaddrinfo(result);
118 result = nullptr;
119 }
120
121 // Invalid hints.
122 // These place holders are used to test function call with unrequired parameters.
123 // The content is not important because function call returns error directly if
124 // there have any unrequired parameter.
125 char placeholder_cname[] = "invalid_cname";
126 sockaddr placeholder_addr = {};
127 addrinfo placeholder_next = {};
128 static const struct TestConfig {
129 int ai_flags;
130 socklen_t ai_addrlen;
131 char* ai_canonname;
132 struct sockaddr* ai_addr;
133 struct addrinfo* ai_next;
Bernie Innocenti7916c6a2019-04-25 15:16:51 +0900134
135 int expected_eai_error;
nuccachen0efcc802018-11-28 18:19:39 +0800136
137 std::string asParameters() const {
138 return StringPrintf("0x%x/%u/%s/%p/%p", ai_flags, ai_addrlen,
139 ai_canonname ? ai_canonname : "(null)", (void*) ai_addr,
140 (void*) ai_next);
141 }
142 } testConfigs[]{
143 {0, sizeof(struct in_addr) /*bad*/, nullptr, nullptr, nullptr, EAI_BADHINTS},
144 {0, 0, placeholder_cname /*bad*/, nullptr, nullptr, EAI_BADHINTS},
145 {0, 0, nullptr, &placeholder_addr /*bad*/, nullptr, EAI_BADHINTS},
146 {0, 0, nullptr, nullptr, &placeholder_next /*bad*/, EAI_BADHINTS},
147 {AI_ALL /*bad*/, 0, nullptr, nullptr, nullptr, EAI_BADFLAGS},
148 {AI_V4MAPPED_CFG /*bad*/, 0, nullptr, nullptr, nullptr, EAI_BADFLAGS},
149 {AI_V4MAPPED /*bad*/, 0, nullptr, nullptr, nullptr, EAI_BADFLAGS},
150 {AI_DEFAULT /*bad*/, 0, nullptr, nullptr, nullptr, EAI_BADFLAGS},
151 };
152
153 for (const auto& config : testConfigs) {
154 SCOPED_TRACE(config.asParameters());
155
156 // In current test configuration set, ai_family, ai_protocol and ai_socktype are not
157 // checked because other fields cause hints error check failed first.
158 const struct addrinfo hints = {
159 .ai_flags = config.ai_flags,
160 .ai_family = AF_UNSPEC,
161 .ai_socktype = ANY,
162 .ai_protocol = ANY,
163 .ai_addrlen = config.ai_addrlen,
164 .ai_canonname = config.ai_canonname,
165 .ai_addr = config.ai_addr,
166 .ai_next = config.ai_next,
167 };
168
169 rv = android_getaddrinfofornetcontext("localhost", nullptr /*servname*/, &hints,
Hungming Chen947aab02018-12-27 18:33:19 +0800170 &mNetcontext, &result);
Bernie Innocenti7916c6a2019-04-25 15:16:51 +0900171 EXPECT_EQ(config.expected_eai_error, rv);
nuccachen0efcc802018-11-28 18:19:39 +0800172
173 if (result) {
174 freeaddrinfo(result);
175 result = nullptr;
176 }
177 }
178}
179
180TEST_F(GetAddrInfoForNetContextTest, InvalidParameters_Family) {
nuccachen0efcc802018-11-28 18:19:39 +0800181 for (int family = 0; family < AF_MAX; ++family) {
182 if (family == AF_UNSPEC || family == AF_INET || family == AF_INET6) {
183 continue; // skip supported family
184 }
185 SCOPED_TRACE(StringPrintf("family: %d", family));
186
187 struct addrinfo* result = nullptr;
188 const struct addrinfo hints = {
189 .ai_family = family, // unsupported family
190 };
191
192 int rv = android_getaddrinfofornetcontext("localhost", nullptr /*servname*/, &hints,
Hungming Chen947aab02018-12-27 18:33:19 +0800193 &mNetcontext, &result);
nuccachen0efcc802018-11-28 18:19:39 +0800194 EXPECT_EQ(EAI_FAMILY, rv);
195
196 if (result) freeaddrinfo(result);
197 }
198}
199
200TEST_F(GetAddrInfoForNetContextTest, InvalidParameters_MeaningfulSocktypeAndProtocolCombination) {
nuccachen0efcc802018-11-28 18:19:39 +0800201 static const int families[] = {PF_INET, PF_INET6, PF_UNSPEC};
202 // Skip to test socket type SOCK_RAW in meaningful combination (explore_options[]) of
203 // system\netd\resolv\getaddrinfo.cpp. In explore_options[], the socket type SOCK_RAW always
204 // comes with protocol ANY which causes skipping meaningful socktype/protocol combination
205 // check. So it nerver returns error number EAI_BADHINTS which we want to test in this test
206 // case.
207 static const int socktypes[] = {SOCK_STREAM, SOCK_DGRAM};
208
209 // If both socktype/protocol are specified, check non-meaningful combination returns
210 // expected error number EAI_BADHINTS. See meaningful combination in explore_options[] of
211 // system\netd\resolv\getaddrinfo.cpp.
212 for (const auto& family : families) {
213 for (const auto& socktype : socktypes) {
214 for (int protocol = 0; protocol < IPPROTO_MAX; ++protocol) {
215 SCOPED_TRACE(StringPrintf("family: %d, socktype: %d, protocol: %d", family,
216 socktype, protocol));
217
218 // Both socktype/protocol need to be specified.
219 if (!socktype || !protocol) continue;
220
221 // Skip meaningful combination in explore_options[] of
222 // system\netd\resolv\getaddrinfo.cpp.
223 if ((family == AF_INET6 && socktype == SOCK_DGRAM && protocol == IPPROTO_UDP) ||
224 (family == AF_INET6 && socktype == SOCK_STREAM && protocol == IPPROTO_TCP) ||
225 (family == AF_INET && socktype == SOCK_DGRAM && protocol == IPPROTO_UDP) ||
226 (family == AF_INET && socktype == SOCK_STREAM && protocol == IPPROTO_TCP) ||
227 (family == AF_UNSPEC && socktype == SOCK_DGRAM && protocol == IPPROTO_UDP) ||
228 (family == AF_UNSPEC && socktype == SOCK_STREAM && protocol == IPPROTO_TCP)) {
229 continue;
230 }
231
232 struct addrinfo* result = nullptr;
233 const struct addrinfo hints = {
234 .ai_family = family,
235 .ai_protocol = protocol,
236 .ai_socktype = socktype,
237 };
238
239 int rv = android_getaddrinfofornetcontext("localhost", nullptr /*servname*/, &hints,
Hungming Chen947aab02018-12-27 18:33:19 +0800240 &mNetcontext, &result);
nuccachen0efcc802018-11-28 18:19:39 +0800241 EXPECT_EQ(EAI_BADHINTS, rv);
242
243 if (result) freeaddrinfo(result);
244 }
245 }
246 }
247}
248
249TEST_F(GetAddrInfoForNetContextTest, InvalidParameters_PortNameAndNumber) {
nuccachen0efcc802018-11-28 18:19:39 +0800250 constexpr char http_portno[] = "80";
251 constexpr char invalid_portno[] = "65536"; // out of valid port range from 0 to 65535
252 constexpr char http_portname[] = "http";
253 constexpr char invalid_portname[] = "invalid_portname";
254
255 static const struct TestConfig {
256 int ai_flags;
257 int ai_family;
258 int ai_socktype;
259 const char* servname;
Bernie Innocenti7916c6a2019-04-25 15:16:51 +0900260
261 int expected_eai_error;
nuccachen0efcc802018-11-28 18:19:39 +0800262
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;
Hungming Chen947aab02018-12-27 18:33:19 +0800323 int rv = android_getaddrinfofornetcontext("localhost", config.servname, &hints,
324 &mNetcontext, &result);
Bernie Innocenti7916c6a2019-04-25 15:16:51 +0900325 EXPECT_EQ(config.expected_eai_error, rv);
nuccachen0efcc802018-11-28 18:19:39 +0800326
327 if (result) freeaddrinfo(result);
328 }
329}
330
nuccachen0efcc802018-11-28 18:19:39 +0800331TEST_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.";
nuccachen0efcc802018-11-28 18:19:39 +0800335 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
nuccachen0efcc802018-11-28 18:19:39 +0800344 // Want AAAA answer but DNS server has A answer only.
Hungming Chen947aab02018-12-27 18:33:19 +0800345 struct addrinfo* result = nullptr;
nuccachen0efcc802018-11-28 18:19:39 +0800346 const addrinfo hints = {.ai_family = AF_INET6};
Hungming Chen947aab02018-12-27 18:33:19 +0800347 int rv = android_getaddrinfofornetcontext("v4only", nullptr, &hints, &mNetcontext, &result);
nuccachen0efcc802018-11-28 18:19:39 +0800348 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}
nuccachen0efcc802018-11-28 18:19:39 +0800354
355TEST_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
nuccachen0efcc802018-11-28 18:19:39 +0800371 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};
Hungming Chen947aab02018-12-27 18:33:19 +0800385 int rv =
386 android_getaddrinfofornetcontext("sawadee", nullptr, &hints, &mNetcontext, &result);
nuccachen0efcc802018-11-28 18:19:39 +0800387 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
396TEST_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
Hungming Chen947aab02018-12-27 18:33:19 +0800401 static const struct TestConfig {
402 ns_rcode rcode;
Bernie Innocenti7916c6a2019-04-25 15:16:51 +0900403 int expected_eai_error;
Hungming Chen947aab02018-12-27 18:33:19 +0800404
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
Bernie Innocenti7916c6a2019-04-25 15:16:51 +0900409 {ns_rcode::ns_r_formerr, EAI_FAIL},
Hungming Chen947aab02018-12-27 18:33:19 +0800410 {ns_rcode::ns_r_servfail, EAI_AGAIN},
411 {ns_rcode::ns_r_nxdomain, EAI_NODATA},
Bernie Innocenti7916c6a2019-04-25 15:16:51 +0900412 {ns_rcode::ns_r_notimpl, EAI_FAIL},
413 {ns_rcode::ns_r_refused, EAI_FAIL},
Hungming Chen947aab02018-12-27 18:33:19 +0800414 // clang-format on
nuccachen0efcc802018-11-28 18:19:39 +0800415 };
416
Hungming Chen947aab02018-12-27 18:33:19 +0800417 for (const auto& config : testConfigs) {
418 SCOPED_TRACE(StringPrintf("rcode: %d", config.rcode));
nuccachen0efcc802018-11-28 18:19:39 +0800419
Hungming Chen947aab02018-12-27 18:33:19 +0800420 test::DNSResponder dns(listen_addr, listen_srv, 250,
421 config.rcode /*response specific rcode*/);
nuccachen0efcc802018-11-28 18:19:39 +0800422 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};
Hungming Chen947aab02018-12-27 18:33:19 +0800432 int rv =
433 android_getaddrinfofornetcontext(host_name, nullptr, &hints, &mNetcontext, &result);
Bernie Innocenti7916c6a2019-04-25 15:16:51 +0900434 EXPECT_EQ(config.expected_eai_error, rv);
nuccachen0efcc802018-11-28 18:19:39 +0800435
436 if (result) freeaddrinfo(result);
437 }
438}
439
440// TODO: Add private DNS server timeout test.
441TEST_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;
nuccachen0efcc802018-11-28 18:19:39 +0800455 const struct addrinfo hints = {.ai_family = AF_UNSPEC};
Hungming Chen947aab02018-12-27 18:33:19 +0800456 int rv = android_getaddrinfofornetcontext("hello", nullptr, &hints, &mNetcontext, &result);
nuccachen0efcc802018-11-28 18:19:39 +0800457 EXPECT_EQ(NETD_RESOLV_TIMEOUT, rv);
458
459 if (result) freeaddrinfo(result);
460}
461
Hungming Chen947aab02018-12-27 18:33:19 +0800462TEST_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";
nuccachen0efcc802018-11-28 18:19:39 +0800468
Hungming Chen947aab02018-12-27 18:33:19 +0800469 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
500TEST_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
521TEST_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;
Bernie Innocenti7916c6a2019-04-25 15:16:51 +0900528 int expected_eai_error; // expected result
Hungming Chen947aab02018-12-27 18:33:19 +0800529
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);
Bernie Innocenti7916c6a2019-04-25 15:16:51 +0900560 EXPECT_EQ(config.expected_eai_error, rv);
Hungming Chen947aab02018-12-27 18:33:19 +0800561 }
562}
563
564// TODO: Add private DNS server timeout test.
565TEST_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.
nuccachen0efcc802018-11-28 18:19:39 +0800589
590} // end of namespace net
591} // end of namespace android