blob: 2820b07f2a861e316ea52530d2e3dc17341dba80 [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>
Hungming Chen70161e52019-05-22 16:33:31 +080024#include <netdutils/InternetAddresses.h>
nuccachen0efcc802018-11-28 18:19:39 +080025
26#include "dns_responder.h"
Bernie Innocentie71a28a2019-05-29 00:42:35 +090027#include "getaddrinfo.h"
28#include "gethnamaddr.h"
29#include "resolv_cache.h"
lifr94981782019-05-17 21:15:19 +080030#include "stats.pb.h"
Hungming Chen32647472019-07-05 14:04:51 +080031#include "tests/resolv_test_utils.h"
nuccachen0efcc802018-11-28 18:19:39 +080032
Hungming Chen70161e52019-05-22 16:33:31 +080033#define NAME(variable) #variable
34
nuccachen0efcc802018-11-28 18:19:39 +080035namespace android {
36namespace net {
37
Hungming Chen70161e52019-05-22 16:33:31 +080038using android::base::StringPrintf;
lifr94981782019-05-17 21:15:19 +080039using android::net::NetworkDnsEventReported;
Hungming Chen70161e52019-05-22 16:33:31 +080040using android::netdutils::ScopedAddrinfo;
41
nuccachen0efcc802018-11-28 18:19:39 +080042// Minimize class ResolverTest to be class TestBase because class TestBase doesn't need all member
43// functions of class ResolverTest and class DnsResponderClient.
44class TestBase : public ::testing::Test {
45 protected:
Luke Huang9b80e6c2019-04-09 17:54:09 +080046 void SetUp() override {
47 // Create cache for test
48 resolv_create_cache_for_net(TEST_NETID);
49 }
50 void TearDown() override {
51 // Delete cache for test
nuccachen0efcc802018-11-28 18:19:39 +080052 resolv_delete_cache_for_net(TEST_NETID);
nuccachen0efcc802018-11-28 18:19:39 +080053 }
54
Mike Yuc7649d12019-05-22 15:28:07 +080055 int setResolvers() {
56 const std::vector<std::string> servers = {test::kDefaultListenAddr};
57 const std::vector<std::string> domains = {"example.com"};
58 const res_params params = {
59 .sample_validity = 300,
60 .success_threshold = 25,
61 .min_samples = 8,
62 .max_samples = 8,
63 .base_timeout_msec = 1000,
64 .retry_count = 2,
65 };
66 return resolv_set_nameservers(TEST_NETID, servers, domains, params);
67 }
68
Hungming Chen947aab02018-12-27 18:33:19 +080069 const android_net_context mNetcontext = {
70 .app_netid = TEST_NETID,
nuccachen0efcc802018-11-28 18:19:39 +080071 .app_mark = MARK_UNSET,
Hungming Chen947aab02018-12-27 18:33:19 +080072 .dns_netid = TEST_NETID,
nuccachen0efcc802018-11-28 18:19:39 +080073 .dns_mark = MARK_UNSET,
74 .uid = NET_CONTEXT_INVALID_UID,
75 };
Hungming Chen947aab02018-12-27 18:33:19 +080076};
nuccachen0efcc802018-11-28 18:19:39 +080077
Luke Huang69e67182019-06-17 17:06:41 +080078class ResolvGetAddrInfoTest : public TestBase {};
Hungming Chen947aab02018-12-27 18:33:19 +080079class GetHostByNameForNetContextTest : public TestBase {};
80
Luke Huang69e67182019-06-17 17:06:41 +080081TEST_F(ResolvGetAddrInfoTest, InvalidParameters) {
82 // Both null "netcontext" and null "res" of resolv_getaddrinfo() are not tested
nuccachen0efcc802018-11-28 18:19:39 +080083 // here because they are checked by assert() without returning any error number.
84
85 // Invalid hostname and servname.
86 // Both hostname and servname are null pointers. Expect error number EAI_NONAME.
Luke Huangd8ac4752019-06-18 17:05:47 +080087 {
88 addrinfo* result = nullptr;
89 NetworkDnsEventReported event;
90 int rv = resolv_getaddrinfo(nullptr /*hostname*/, nullptr /*servname*/, nullptr /*hints*/,
91 &mNetcontext, &result, &event);
92 ScopedAddrinfo result_cleanup(result);
93 EXPECT_EQ(EAI_NONAME, rv);
nuccachen0efcc802018-11-28 18:19:39 +080094 }
95
96 // Invalid hints.
97 // These place holders are used to test function call with unrequired parameters.
98 // The content is not important because function call returns error directly if
99 // there have any unrequired parameter.
100 char placeholder_cname[] = "invalid_cname";
101 sockaddr placeholder_addr = {};
102 addrinfo placeholder_next = {};
103 static const struct TestConfig {
104 int ai_flags;
105 socklen_t ai_addrlen;
106 char* ai_canonname;
Luke Huangd8ac4752019-06-18 17:05:47 +0800107 sockaddr* ai_addr;
108 addrinfo* ai_next;
Bernie Innocenti7916c6a2019-04-25 15:16:51 +0900109
110 int expected_eai_error;
nuccachen0efcc802018-11-28 18:19:39 +0800111
112 std::string asParameters() const {
113 return StringPrintf("0x%x/%u/%s/%p/%p", ai_flags, ai_addrlen,
Luke Huangd8ac4752019-06-18 17:05:47 +0800114 ai_canonname ? ai_canonname : "(null)", (void*)ai_addr,
115 (void*)ai_next);
nuccachen0efcc802018-11-28 18:19:39 +0800116 }
117 } testConfigs[]{
Luke Huangd8ac4752019-06-18 17:05:47 +0800118 {0, sizeof(in_addr) /*bad*/, nullptr, nullptr, nullptr, EAI_BADHINTS},
nuccachen0efcc802018-11-28 18:19:39 +0800119 {0, 0, placeholder_cname /*bad*/, nullptr, nullptr, EAI_BADHINTS},
120 {0, 0, nullptr, &placeholder_addr /*bad*/, nullptr, EAI_BADHINTS},
121 {0, 0, nullptr, nullptr, &placeholder_next /*bad*/, EAI_BADHINTS},
122 {AI_ALL /*bad*/, 0, nullptr, nullptr, nullptr, EAI_BADFLAGS},
123 {AI_V4MAPPED_CFG /*bad*/, 0, nullptr, nullptr, nullptr, EAI_BADFLAGS},
124 {AI_V4MAPPED /*bad*/, 0, nullptr, nullptr, nullptr, EAI_BADFLAGS},
125 {AI_DEFAULT /*bad*/, 0, nullptr, nullptr, nullptr, EAI_BADFLAGS},
126 };
127
128 for (const auto& config : testConfigs) {
129 SCOPED_TRACE(config.asParameters());
130
Luke Huangd8ac4752019-06-18 17:05:47 +0800131 addrinfo* result = nullptr;
nuccachen0efcc802018-11-28 18:19:39 +0800132 // In current test configuration set, ai_family, ai_protocol and ai_socktype are not
133 // checked because other fields cause hints error check failed first.
Luke Huangd8ac4752019-06-18 17:05:47 +0800134 const addrinfo hints = {
nuccachen0efcc802018-11-28 18:19:39 +0800135 .ai_flags = config.ai_flags,
136 .ai_family = AF_UNSPEC,
137 .ai_socktype = ANY,
138 .ai_protocol = ANY,
139 .ai_addrlen = config.ai_addrlen,
140 .ai_canonname = config.ai_canonname,
141 .ai_addr = config.ai_addr,
142 .ai_next = config.ai_next,
143 };
lifr94981782019-05-17 21:15:19 +0800144 NetworkDnsEventReported event;
Luke Huangd8ac4752019-06-18 17:05:47 +0800145 int rv = resolv_getaddrinfo("localhost", nullptr /*servname*/, &hints, &mNetcontext,
146 &result, &event);
147 ScopedAddrinfo result_cleanup(result);
Bernie Innocenti7916c6a2019-04-25 15:16:51 +0900148 EXPECT_EQ(config.expected_eai_error, rv);
nuccachen0efcc802018-11-28 18:19:39 +0800149 }
150}
151
Luke Huang69e67182019-06-17 17:06:41 +0800152TEST_F(ResolvGetAddrInfoTest, InvalidParameters_Family) {
nuccachen0efcc802018-11-28 18:19:39 +0800153 for (int family = 0; family < AF_MAX; ++family) {
154 if (family == AF_UNSPEC || family == AF_INET || family == AF_INET6) {
155 continue; // skip supported family
156 }
157 SCOPED_TRACE(StringPrintf("family: %d", family));
158
Luke Huangd8ac4752019-06-18 17:05:47 +0800159 addrinfo* result = nullptr;
160 const addrinfo hints = {
nuccachen0efcc802018-11-28 18:19:39 +0800161 .ai_family = family, // unsupported family
162 };
lifr94981782019-05-17 21:15:19 +0800163 NetworkDnsEventReported event;
Luke Huang69e67182019-06-17 17:06:41 +0800164 int rv = resolv_getaddrinfo("localhost", nullptr /*servname*/, &hints, &mNetcontext,
lifr94981782019-05-17 21:15:19 +0800165 &result, &event);
Luke Huangd8ac4752019-06-18 17:05:47 +0800166 ScopedAddrinfo result_cleanup(result);
nuccachen0efcc802018-11-28 18:19:39 +0800167 EXPECT_EQ(EAI_FAMILY, rv);
Luke Huangd8ac4752019-06-18 17:05:47 +0800168 }
169}
nuccachen0efcc802018-11-28 18:19:39 +0800170
Luke Huangd8ac4752019-06-18 17:05:47 +0800171TEST_F(ResolvGetAddrInfoTest, InvalidParameters_SocketType) {
172 for (const auto& family : {AF_INET, AF_INET6, AF_UNSPEC}) {
173 for (int protocol = 0; protocol < IPPROTO_MAX; ++protocol) {
174 // Socket types which are not in explore_options.
175 for (const auto& socktype : {SOCK_RDM, SOCK_SEQPACKET, SOCK_DCCP, SOCK_PACKET}) {
176 const addrinfo hints = {
177 .ai_family = family,
178 .ai_protocol = protocol,
179 .ai_socktype = socktype,
180 };
181 for (const char* service : {static_cast<const char*>(nullptr), // service is null
182 "80",
183 "", // empty service name
184 "ftp",
185 "65536", // out of valid port range from 0 to 65535
186 "invalid"}) {
187 SCOPED_TRACE(StringPrintf("family: %d, socktype: %d, protocol: %d, service: %s",
188 family, socktype, protocol,
189 service ? service : "service is nullptr"));
190 addrinfo* result = nullptr;
191 NetworkDnsEventReported event;
192 int rv = resolv_getaddrinfo("localhost", service, &hints, &mNetcontext, &result,
193 &event);
194 ScopedAddrinfo result_cleanup(result);
195 EXPECT_EQ(EAI_SOCKTYPE, rv);
196 }
197 }
198 }
nuccachen0efcc802018-11-28 18:19:39 +0800199 }
200}
201
Luke Huang69e67182019-06-17 17:06:41 +0800202TEST_F(ResolvGetAddrInfoTest, InvalidParameters_MeaningfulSocktypeAndProtocolCombination) {
nuccachen0efcc802018-11-28 18:19:39 +0800203 static const int families[] = {PF_INET, PF_INET6, PF_UNSPEC};
204 // Skip to test socket type SOCK_RAW in meaningful combination (explore_options[]) of
205 // system\netd\resolv\getaddrinfo.cpp. In explore_options[], the socket type SOCK_RAW always
206 // comes with protocol ANY which causes skipping meaningful socktype/protocol combination
207 // check. So it nerver returns error number EAI_BADHINTS which we want to test in this test
208 // case.
209 static const int socktypes[] = {SOCK_STREAM, SOCK_DGRAM};
210
211 // If both socktype/protocol are specified, check non-meaningful combination returns
212 // expected error number EAI_BADHINTS. See meaningful combination in explore_options[] of
213 // system\netd\resolv\getaddrinfo.cpp.
214 for (const auto& family : families) {
215 for (const auto& socktype : socktypes) {
216 for (int protocol = 0; protocol < IPPROTO_MAX; ++protocol) {
217 SCOPED_TRACE(StringPrintf("family: %d, socktype: %d, protocol: %d", family,
218 socktype, protocol));
219
220 // Both socktype/protocol need to be specified.
221 if (!socktype || !protocol) continue;
222
223 // Skip meaningful combination in explore_options[] of
224 // system\netd\resolv\getaddrinfo.cpp.
225 if ((family == AF_INET6 && socktype == SOCK_DGRAM && protocol == IPPROTO_UDP) ||
226 (family == AF_INET6 && socktype == SOCK_STREAM && protocol == IPPROTO_TCP) ||
227 (family == AF_INET && socktype == SOCK_DGRAM && protocol == IPPROTO_UDP) ||
228 (family == AF_INET && socktype == SOCK_STREAM && protocol == IPPROTO_TCP) ||
229 (family == AF_UNSPEC && socktype == SOCK_DGRAM && protocol == IPPROTO_UDP) ||
230 (family == AF_UNSPEC && socktype == SOCK_STREAM && protocol == IPPROTO_TCP)) {
231 continue;
232 }
233
Luke Huangd8ac4752019-06-18 17:05:47 +0800234 addrinfo* result = nullptr;
235 const addrinfo hints = {
nuccachen0efcc802018-11-28 18:19:39 +0800236 .ai_family = family,
237 .ai_protocol = protocol,
238 .ai_socktype = socktype,
239 };
lifr94981782019-05-17 21:15:19 +0800240 NetworkDnsEventReported event;
Luke Huang69e67182019-06-17 17:06:41 +0800241 int rv = resolv_getaddrinfo("localhost", nullptr /*servname*/, &hints, &mNetcontext,
lifr94981782019-05-17 21:15:19 +0800242 &result, &event);
Luke Huangd8ac4752019-06-18 17:05:47 +0800243 ScopedAddrinfo result_cleanup(result);
nuccachen0efcc802018-11-28 18:19:39 +0800244 EXPECT_EQ(EAI_BADHINTS, rv);
nuccachen0efcc802018-11-28 18:19:39 +0800245 }
246 }
247 }
248}
249
Luke Huangd8ac4752019-06-18 17:05:47 +0800250// The test configs are used for verifying the error path of get_port().
251// Note that the EAI_SOCKTYPE verification are moved to an independent
252// test case because validateHints() verify invalid socket type early now.
253// See also InvalidParameters_SocketType.
Luke Huang69e67182019-06-17 17:06:41 +0800254TEST_F(ResolvGetAddrInfoTest, InvalidParameters_PortNameAndNumber) {
nuccachen0efcc802018-11-28 18:19:39 +0800255 constexpr char http_portno[] = "80";
256 constexpr char invalid_portno[] = "65536"; // out of valid port range from 0 to 65535
257 constexpr char http_portname[] = "http";
258 constexpr char invalid_portname[] = "invalid_portname";
259
260 static const struct TestConfig {
261 int ai_flags;
262 int ai_family;
263 int ai_socktype;
264 const char* servname;
Bernie Innocenti7916c6a2019-04-25 15:16:51 +0900265
266 int expected_eai_error;
nuccachen0efcc802018-11-28 18:19:39 +0800267
268 std::string asParameters() const {
269 return StringPrintf("0x%x/%d/%d/%s", ai_flags, ai_family, ai_socktype,
270 servname ? servname : "(null)");
271 }
272 } testConfigs[]{
273 {0, AF_INET, SOCK_RAW /*bad*/, http_portno, EAI_SERVICE},
274 {0, AF_INET6, SOCK_RAW /*bad*/, http_portno, EAI_SERVICE},
275 {0, AF_UNSPEC, SOCK_RAW /*bad*/, http_portno, EAI_SERVICE},
nuccachen0efcc802018-11-28 18:19:39 +0800276 {0, AF_INET, ANY, invalid_portno /*bad*/, EAI_SERVICE},
277 {0, AF_INET, SOCK_STREAM, invalid_portno /*bad*/, EAI_SERVICE},
278 {0, AF_INET, SOCK_DGRAM, invalid_portno /*bad*/, EAI_SERVICE},
279 {0, AF_INET6, ANY, invalid_portno /*bad*/, EAI_SERVICE},
280 {0, AF_INET6, SOCK_STREAM, invalid_portno /*bad*/, EAI_SERVICE},
281 {0, AF_INET6, SOCK_DGRAM, invalid_portno /*bad*/, EAI_SERVICE},
282 {0, AF_UNSPEC, ANY, invalid_portno /*bad*/, EAI_SERVICE},
283 {0, AF_UNSPEC, SOCK_STREAM, invalid_portno /*bad*/, EAI_SERVICE},
284 {0, AF_UNSPEC, SOCK_DGRAM, invalid_portno /*bad*/, EAI_SERVICE},
285 {AI_NUMERICSERV, AF_INET, ANY, http_portname /*bad*/, EAI_NONAME},
286 {AI_NUMERICSERV, AF_INET, SOCK_STREAM, http_portname /*bad*/, EAI_NONAME},
287 {AI_NUMERICSERV, AF_INET, SOCK_DGRAM, http_portname /*bad*/, EAI_NONAME},
288 {AI_NUMERICSERV, AF_INET6, ANY, http_portname /*bad*/, EAI_NONAME},
289 {AI_NUMERICSERV, AF_INET6, SOCK_STREAM, http_portname /*bad*/, EAI_NONAME},
290 {AI_NUMERICSERV, AF_INET6, SOCK_DGRAM, http_portname /*bad*/, EAI_NONAME},
291 {AI_NUMERICSERV, AF_UNSPEC, ANY, http_portname /*bad*/, EAI_NONAME},
292 {AI_NUMERICSERV, AF_UNSPEC, SOCK_STREAM, http_portname /*bad*/, EAI_NONAME},
293 {AI_NUMERICSERV, AF_UNSPEC, SOCK_DGRAM, http_portname /*bad*/, EAI_NONAME},
294 {0, AF_INET, ANY, invalid_portname /*bad*/, EAI_SERVICE},
295 {0, AF_INET, SOCK_STREAM, invalid_portname /*bad*/, EAI_SERVICE},
296 {0, AF_INET, SOCK_DGRAM, invalid_portname /*bad*/, EAI_SERVICE},
297 {0, AF_INET6, ANY, invalid_portname /*bad*/, EAI_SERVICE},
298 {0, AF_INET6, SOCK_STREAM, invalid_portname /*bad*/, EAI_SERVICE},
299 {0, AF_INET6, SOCK_DGRAM, invalid_portname /*bad*/, EAI_SERVICE},
300 {0, AF_UNSPEC, ANY, invalid_portname /*bad*/, EAI_SERVICE},
301 {0, AF_UNSPEC, SOCK_STREAM, invalid_portname /*bad*/, EAI_SERVICE},
302 {0, AF_UNSPEC, SOCK_DGRAM, invalid_portname /*bad*/, EAI_SERVICE},
303 };
304
305 for (const auto& config : testConfigs) {
306 const std::string testParameters = config.asParameters();
307 SCOPED_TRACE(testParameters);
308
Luke Huangd8ac4752019-06-18 17:05:47 +0800309 const addrinfo hints = {
nuccachen0efcc802018-11-28 18:19:39 +0800310 .ai_flags = config.ai_flags,
311 .ai_family = config.ai_family,
312 .ai_socktype = config.ai_socktype,
313 };
314
Luke Huangd8ac4752019-06-18 17:05:47 +0800315 addrinfo* result = nullptr;
lifr94981782019-05-17 21:15:19 +0800316 NetworkDnsEventReported event;
317 int rv = resolv_getaddrinfo("localhost", config.servname, &hints, &mNetcontext, &result,
318 &event);
Luke Huangd8ac4752019-06-18 17:05:47 +0800319 ScopedAddrinfo result_cleanup(result);
Bernie Innocenti7916c6a2019-04-25 15:16:51 +0900320 EXPECT_EQ(config.expected_eai_error, rv);
nuccachen0efcc802018-11-28 18:19:39 +0800321 }
322}
323
Luke Huang69e67182019-06-17 17:06:41 +0800324TEST_F(ResolvGetAddrInfoTest, AlphabeticalHostname_NoData) {
nuccachen0efcc802018-11-28 18:19:39 +0800325 constexpr char v4_host_name[] = "v4only.example.com.";
Mike Yuc7649d12019-05-22 15:28:07 +0800326 test::DNSResponder dns;
nuccachen0efcc802018-11-28 18:19:39 +0800327 dns.addMapping(v4_host_name, ns_type::ns_t_a, "1.2.3.3");
328 ASSERT_TRUE(dns.startServer());
Mike Yuc7649d12019-05-22 15:28:07 +0800329 ASSERT_EQ(0, setResolvers());
nuccachen0efcc802018-11-28 18:19:39 +0800330
nuccachen0efcc802018-11-28 18:19:39 +0800331 // Want AAAA answer but DNS server has A answer only.
Luke Huangd8ac4752019-06-18 17:05:47 +0800332 addrinfo* result = nullptr;
nuccachen0efcc802018-11-28 18:19:39 +0800333 const addrinfo hints = {.ai_family = AF_INET6};
lifr94981782019-05-17 21:15:19 +0800334 NetworkDnsEventReported event;
335 int rv = resolv_getaddrinfo("v4only", nullptr, &hints, &mNetcontext, &result, &event);
Luke Huangd8ac4752019-06-18 17:05:47 +0800336 ScopedAddrinfo result_cleanup(result);
nuccachen0efcc802018-11-28 18:19:39 +0800337 EXPECT_LE(1U, GetNumQueries(dns, v4_host_name));
Hungming Chen70161e52019-05-22 16:33:31 +0800338 EXPECT_EQ(nullptr, result);
nuccachen0efcc802018-11-28 18:19:39 +0800339 EXPECT_EQ(EAI_NODATA, rv);
nuccachen0efcc802018-11-28 18:19:39 +0800340}
nuccachen0efcc802018-11-28 18:19:39 +0800341
Luke Huang69e67182019-06-17 17:06:41 +0800342TEST_F(ResolvGetAddrInfoTest, AlphabeticalHostname) {
nuccachen0efcc802018-11-28 18:19:39 +0800343 constexpr char host_name[] = "sawadee.example.com.";
344 constexpr char v4addr[] = "1.2.3.4";
345 constexpr char v6addr[] = "::1.2.3.4";
346
Mike Yuc7649d12019-05-22 15:28:07 +0800347 test::DNSResponder dns;
nuccachen0efcc802018-11-28 18:19:39 +0800348 dns.addMapping(host_name, ns_type::ns_t_a, v4addr);
349 dns.addMapping(host_name, ns_type::ns_t_aaaa, v6addr);
350 ASSERT_TRUE(dns.startServer());
Mike Yuc7649d12019-05-22 15:28:07 +0800351 ASSERT_EQ(0, setResolvers());
nuccachen0efcc802018-11-28 18:19:39 +0800352
nuccachen0efcc802018-11-28 18:19:39 +0800353 static const struct TestConfig {
354 int ai_family;
355 const std::string expected_addr;
356 } testConfigs[]{
357 {AF_INET, v4addr},
358 {AF_INET6, v6addr},
359 };
360
361 for (const auto& config : testConfigs) {
362 SCOPED_TRACE(StringPrintf("family: %d", config.ai_family));
363 dns.clearQueries();
364
Luke Huangd8ac4752019-06-18 17:05:47 +0800365 addrinfo* result = nullptr;
366 const addrinfo hints = {.ai_family = config.ai_family};
lifr94981782019-05-17 21:15:19 +0800367 NetworkDnsEventReported event;
368 int rv = resolv_getaddrinfo("sawadee", nullptr, &hints, &mNetcontext, &result, &event);
Luke Huangd8ac4752019-06-18 17:05:47 +0800369 ScopedAddrinfo result_cleanup(result);
nuccachen0efcc802018-11-28 18:19:39 +0800370 EXPECT_EQ(0, rv);
371 EXPECT_TRUE(result != nullptr);
372 EXPECT_EQ(1U, GetNumQueries(dns, host_name));
373 EXPECT_EQ(config.expected_addr, ToString(result));
nuccachen0efcc802018-11-28 18:19:39 +0800374 }
375}
376
Luke Huang69e67182019-06-17 17:06:41 +0800377TEST_F(ResolvGetAddrInfoTest, IllegalHostname) {
Mike Yuc7649d12019-05-22 15:28:07 +0800378 test::DNSResponder dns;
Hungming Chen70161e52019-05-22 16:33:31 +0800379 ASSERT_TRUE(dns.startServer());
Mike Yuc7649d12019-05-22 15:28:07 +0800380 ASSERT_EQ(0, setResolvers());
Hungming Chen70161e52019-05-22 16:33:31 +0800381
382 // Illegal hostname is verified by res_hnok() in system/netd/resolv/res_comp.cpp.
383 static constexpr char const* illegalHostnames[] = {
384 kBadCharAfterPeriodHost,
385 kBadCharBeforePeriodHost,
386 kBadCharAtTheEndHost,
387 kBadCharInTheMiddleOfLabelHost,
388 };
389
390 for (const auto& hostname : illegalHostnames) {
391 // Expect to get no address because hostname format is illegal.
392 //
393 // Ex:
394 // ANSWER SECTION:
395 // a.ex^ample.com. IN A 1.2.3.3
396 // a.ex^ample.com. IN AAAA 2001:db8::42
397 //
398 // In this example, querying "a.ex^ample.com" should get no address because
399 // "a.ex^ample.com" has an illegal char '^' in the middle of label.
400 dns.addMapping(hostname, ns_type::ns_t_a, "1.2.3.3");
401 dns.addMapping(hostname, ns_type::ns_t_aaaa, "2001:db8::42");
402
403 for (const auto& family : {AF_INET, AF_INET6, AF_UNSPEC}) {
404 SCOPED_TRACE(StringPrintf("family: %d, config.name: %s", family, hostname));
405
406 addrinfo* res = nullptr;
407 const addrinfo hints = {.ai_family = family};
lifr94981782019-05-17 21:15:19 +0800408 NetworkDnsEventReported event;
409 int rv = resolv_getaddrinfo(hostname, nullptr, &hints, &mNetcontext, &res, &event);
Hungming Chen70161e52019-05-22 16:33:31 +0800410 ScopedAddrinfo result(res);
411 EXPECT_EQ(nullptr, result);
412 EXPECT_EQ(EAI_FAIL, rv);
413 }
414 }
415}
416
Luke Huang69e67182019-06-17 17:06:41 +0800417TEST_F(ResolvGetAddrInfoTest, ServerResponseError) {
nuccachen0efcc802018-11-28 18:19:39 +0800418 constexpr char host_name[] = "hello.example.com.";
419
Hungming Chen947aab02018-12-27 18:33:19 +0800420 static const struct TestConfig {
421 ns_rcode rcode;
Bernie Innocenti7916c6a2019-04-25 15:16:51 +0900422 int expected_eai_error;
Hungming Chen947aab02018-12-27 18:33:19 +0800423
424 // Only test failure RCODE [1..5] in RFC 1035 section 4.1.1 and skip successful RCODE 0
425 // which means no error.
426 } testConfigs[]{
427 // clang-format off
Bernie Innocenti7916c6a2019-04-25 15:16:51 +0900428 {ns_rcode::ns_r_formerr, EAI_FAIL},
Hungming Chen947aab02018-12-27 18:33:19 +0800429 {ns_rcode::ns_r_servfail, EAI_AGAIN},
430 {ns_rcode::ns_r_nxdomain, EAI_NODATA},
Bernie Innocenti7916c6a2019-04-25 15:16:51 +0900431 {ns_rcode::ns_r_notimpl, EAI_FAIL},
432 {ns_rcode::ns_r_refused, EAI_FAIL},
Hungming Chen947aab02018-12-27 18:33:19 +0800433 // clang-format on
nuccachen0efcc802018-11-28 18:19:39 +0800434 };
435
Hungming Chen947aab02018-12-27 18:33:19 +0800436 for (const auto& config : testConfigs) {
437 SCOPED_TRACE(StringPrintf("rcode: %d", config.rcode));
nuccachen0efcc802018-11-28 18:19:39 +0800438
Mike Yuc7649d12019-05-22 15:28:07 +0800439 test::DNSResponder dns(config.rcode);
nuccachen0efcc802018-11-28 18:19:39 +0800440 dns.addMapping(host_name, ns_type::ns_t_a, "1.2.3.4");
441 dns.setResponseProbability(0.0); // always ignore requests and response preset rcode
442 ASSERT_TRUE(dns.startServer());
Mike Yuc7649d12019-05-22 15:28:07 +0800443 ASSERT_EQ(0, setResolvers());
nuccachen0efcc802018-11-28 18:19:39 +0800444
Luke Huangd8ac4752019-06-18 17:05:47 +0800445 addrinfo* result = nullptr;
446 const addrinfo hints = {.ai_family = AF_UNSPEC};
lifr94981782019-05-17 21:15:19 +0800447 NetworkDnsEventReported event;
448 int rv = resolv_getaddrinfo(host_name, nullptr, &hints, &mNetcontext, &result, &event);
Bernie Innocenti7916c6a2019-04-25 15:16:51 +0900449 EXPECT_EQ(config.expected_eai_error, rv);
nuccachen0efcc802018-11-28 18:19:39 +0800450 }
451}
452
453// TODO: Add private DNS server timeout test.
Luke Huang69e67182019-06-17 17:06:41 +0800454TEST_F(ResolvGetAddrInfoTest, ServerTimeout) {
nuccachen0efcc802018-11-28 18:19:39 +0800455 constexpr char host_name[] = "hello.example.com.";
Mike Yuc7649d12019-05-22 15:28:07 +0800456 test::DNSResponder dns(static_cast<ns_rcode>(-1) /*no response*/);
nuccachen0efcc802018-11-28 18:19:39 +0800457 dns.addMapping(host_name, ns_type::ns_t_a, "1.2.3.4");
458 dns.setResponseProbability(0.0); // always ignore requests and don't response
459 ASSERT_TRUE(dns.startServer());
Mike Yuc7649d12019-05-22 15:28:07 +0800460 ASSERT_EQ(0, setResolvers());
nuccachen0efcc802018-11-28 18:19:39 +0800461
Luke Huangd8ac4752019-06-18 17:05:47 +0800462 addrinfo* result = nullptr;
463 const addrinfo hints = {.ai_family = AF_UNSPEC};
lifr94981782019-05-17 21:15:19 +0800464 NetworkDnsEventReported event;
465 int rv = resolv_getaddrinfo("hello", nullptr, &hints, &mNetcontext, &result, &event);
nuccachen0efcc802018-11-28 18:19:39 +0800466 EXPECT_EQ(NETD_RESOLV_TIMEOUT, rv);
nuccachen0efcc802018-11-28 18:19:39 +0800467}
468
Luke Huang69e67182019-06-17 17:06:41 +0800469TEST_F(ResolvGetAddrInfoTest, CnamesNoIpAddress) {
Hungming Chen70161e52019-05-22 16:33:31 +0800470 constexpr char ACNAME[] = "acname"; // expect a cname in answer
471 constexpr char CNAMES[] = "cnames"; // expect cname chain in answer
472
Mike Yuc7649d12019-05-22 15:28:07 +0800473 test::DNSResponder dns;
Hungming Chen70161e52019-05-22 16:33:31 +0800474 dns.addMapping("cnames.example.com.", ns_type::ns_t_cname, "acname.example.com.");
475 dns.addMapping("acname.example.com.", ns_type::ns_t_cname, "hello.example.com.");
476 ASSERT_TRUE(dns.startServer());
Mike Yuc7649d12019-05-22 15:28:07 +0800477 ASSERT_EQ(0, setResolvers());
Hungming Chen70161e52019-05-22 16:33:31 +0800478
479 static const struct TestConfig {
480 const char* name;
481 int family;
482 } testConfigs[]{
483 // clang-format off
484 {ACNAME, AF_INET},
485 {ACNAME, AF_INET6},
486 {ACNAME, AF_UNSPEC},
487 {CNAMES, AF_INET},
488 {CNAMES, AF_INET6},
489 {CNAMES, AF_UNSPEC},
490 // clang-format on
491 };
492
493 for (const auto& config : testConfigs) {
494 SCOPED_TRACE(
495 StringPrintf("config.family: %d, config.name: %s", config.family, config.name));
496
497 addrinfo* res = nullptr;
498 const addrinfo hints = {.ai_family = config.family};
lifr94981782019-05-17 21:15:19 +0800499 NetworkDnsEventReported event;
500 int rv = resolv_getaddrinfo(config.name, nullptr, &hints, &mNetcontext, &res, &event);
Hungming Chen70161e52019-05-22 16:33:31 +0800501 ScopedAddrinfo result(res);
502 EXPECT_EQ(nullptr, result);
503 EXPECT_EQ(EAI_FAIL, rv);
504 }
505}
506
Luke Huang69e67182019-06-17 17:06:41 +0800507TEST_F(ResolvGetAddrInfoTest, CnamesBrokenChainByIllegalCname) {
Mike Yuc7649d12019-05-22 15:28:07 +0800508 test::DNSResponder dns;
Hungming Chen70161e52019-05-22 16:33:31 +0800509 ASSERT_TRUE(dns.startServer());
Mike Yuc7649d12019-05-22 15:28:07 +0800510 ASSERT_EQ(0, setResolvers());
Hungming Chen70161e52019-05-22 16:33:31 +0800511
512 static const struct TestConfig {
513 const char* name;
514 const char* cname;
515 std::string asHostName() const { return StringPrintf("%s.example.com.", name); }
516
517 // Illegal cname is verified by res_hnok() in system/netd/resolv/res_comp.cpp.
518 } testConfigs[]{
519 // clang-format off
520 {NAME(kBadCharAfterPeriodHost), kBadCharAfterPeriodHost},
521 {NAME(kBadCharBeforePeriodHost), kBadCharBeforePeriodHost},
522 {NAME(kBadCharAtTheEndHost), kBadCharAtTheEndHost},
523 {NAME(kBadCharInTheMiddleOfLabelHost), kBadCharInTheMiddleOfLabelHost},
524 // clang-format on
525 };
526
527 for (const auto& config : testConfigs) {
528 const std::string testHostName = config.asHostName();
529
530 // Expect to get no address because the cname chain is broken by an illegal cname format.
531 //
532 // Ex:
533 // ANSWER SECTION:
534 // hello.example.com. IN CNAME a.ex^ample.com.
535 // a.ex^ample.com. IN A 1.2.3.3
536 // a.ex^ample.com. IN AAAA 2001:db8::42
537 //
538 // In this example, querying hello.example.com should get no address because
539 // "a.ex^ample.com" has an illegal char '^' in the middle of label.
540 dns.addMapping(testHostName.c_str(), ns_type::ns_t_cname, config.cname);
541 dns.addMapping(config.cname, ns_type::ns_t_a, "1.2.3.3");
542 dns.addMapping(config.cname, ns_type::ns_t_aaaa, "2001:db8::42");
543
544 for (const auto& family : {AF_INET, AF_INET6, AF_UNSPEC}) {
545 SCOPED_TRACE(
546 StringPrintf("family: %d, testHostName: %s", family, testHostName.c_str()));
547
548 addrinfo* res = nullptr;
549 const addrinfo hints = {.ai_family = family};
lifr94981782019-05-17 21:15:19 +0800550 NetworkDnsEventReported event;
551 int rv = resolv_getaddrinfo(config.name, nullptr, &hints, &mNetcontext, &res, &event);
Hungming Chen70161e52019-05-22 16:33:31 +0800552 ScopedAddrinfo result(res);
553 EXPECT_EQ(nullptr, result);
554 EXPECT_EQ(EAI_FAIL, rv);
555 }
556 }
557}
558
Luke Huang69e67182019-06-17 17:06:41 +0800559TEST_F(ResolvGetAddrInfoTest, CnamesInfiniteLoop) {
Mike Yuc7649d12019-05-22 15:28:07 +0800560 test::DNSResponder dns;
Hungming Chen70161e52019-05-22 16:33:31 +0800561 dns.addMapping("hello.example.com.", ns_type::ns_t_cname, "a.example.com.");
562 dns.addMapping("a.example.com.", ns_type::ns_t_cname, "hello.example.com.");
563 ASSERT_TRUE(dns.startServer());
Mike Yuc7649d12019-05-22 15:28:07 +0800564 ASSERT_EQ(0, setResolvers());
Hungming Chen70161e52019-05-22 16:33:31 +0800565
566 for (const auto& family : {AF_INET, AF_INET6, AF_UNSPEC}) {
567 SCOPED_TRACE(StringPrintf("family: %d", family));
568
569 addrinfo* res = nullptr;
570 const addrinfo hints = {.ai_family = family};
lifr94981782019-05-17 21:15:19 +0800571 NetworkDnsEventReported event;
572 int rv = resolv_getaddrinfo("hello", nullptr, &hints, &mNetcontext, &res, &event);
Hungming Chen70161e52019-05-22 16:33:31 +0800573 ScopedAddrinfo result(res);
574 EXPECT_EQ(nullptr, result);
575 EXPECT_EQ(EAI_FAIL, rv);
576 }
577}
578
Hungming Chen947aab02018-12-27 18:33:19 +0800579TEST_F(GetHostByNameForNetContextTest, AlphabeticalHostname) {
Hungming Chen947aab02018-12-27 18:33:19 +0800580 constexpr char host_name[] = "jiababuei.example.com.";
581 constexpr char v4addr[] = "1.2.3.4";
582 constexpr char v6addr[] = "::1.2.3.4";
nuccachen0efcc802018-11-28 18:19:39 +0800583
Mike Yuc7649d12019-05-22 15:28:07 +0800584 test::DNSResponder dns;
Hungming Chen947aab02018-12-27 18:33:19 +0800585 dns.addMapping(host_name, ns_type::ns_t_a, v4addr);
586 dns.addMapping(host_name, ns_type::ns_t_aaaa, v6addr);
587 ASSERT_TRUE(dns.startServer());
Mike Yuc7649d12019-05-22 15:28:07 +0800588 ASSERT_EQ(0, setResolvers());
Hungming Chen947aab02018-12-27 18:33:19 +0800589
590 static const struct TestConfig {
591 int ai_family;
592 const std::string expected_addr;
593 } testConfigs[]{
594 {AF_INET, v4addr},
595 {AF_INET6, v6addr},
596 };
597
598 for (const auto& config : testConfigs) {
599 SCOPED_TRACE(StringPrintf("family: %d", config.ai_family));
600 dns.clearQueries();
601
Luke Huangd8ac4752019-06-18 17:05:47 +0800602 hostent* hp = nullptr;
lifr94981782019-05-17 21:15:19 +0800603 NetworkDnsEventReported event;
Hungming Chen947aab02018-12-27 18:33:19 +0800604 int rv = android_gethostbynamefornetcontext("jiababuei", config.ai_family, &mNetcontext,
lifr94981782019-05-17 21:15:19 +0800605 &hp, &event);
Hungming Chen947aab02018-12-27 18:33:19 +0800606 EXPECT_EQ(0, rv);
607 EXPECT_TRUE(hp != nullptr);
608 EXPECT_EQ(1U, GetNumQueries(dns, host_name));
609 EXPECT_EQ(config.expected_addr, ToString(hp));
610 }
611}
612
Hungming Chenb0cd3dc2019-05-24 16:18:07 +0800613TEST_F(GetHostByNameForNetContextTest, IllegalHostname) {
Mike Yuc7649d12019-05-22 15:28:07 +0800614 test::DNSResponder dns;
Hungming Chenb0cd3dc2019-05-24 16:18:07 +0800615 ASSERT_TRUE(dns.startServer());
Mike Yuc7649d12019-05-22 15:28:07 +0800616 ASSERT_EQ(0, setResolvers());
Hungming Chenb0cd3dc2019-05-24 16:18:07 +0800617
618 // Illegal hostname is verified by res_hnok() in system/netd/resolv/res_comp.cpp.
619 static constexpr char const* illegalHostnames[] = {
620 kBadCharAfterPeriodHost,
621 kBadCharBeforePeriodHost,
622 kBadCharAtTheEndHost,
623 kBadCharInTheMiddleOfLabelHost,
624 };
625
626 for (const auto& hostname : illegalHostnames) {
627 // Expect to get no address because hostname format is illegal.
628 //
629 // Ex:
630 // ANSWER SECTION:
631 // a.ex^ample.com. IN A 1.2.3.3
632 // a.ex^ample.com. IN AAAA 2001:db8::42
633 //
634 // In this example, querying "a.ex^ample.com" should get no address because
635 // "a.ex^ample.com" has an illegal char '^' in the middle of label.
636 dns.addMapping(hostname, ns_type::ns_t_a, "1.2.3.3");
637 dns.addMapping(hostname, ns_type::ns_t_aaaa, "2001:db8::42");
638
639 for (const auto& family : {AF_INET, AF_INET6}) {
640 SCOPED_TRACE(StringPrintf("family: %d, config.name: %s", family, hostname));
641
642 struct hostent* hp = nullptr;
lifr94981782019-05-17 21:15:19 +0800643 NetworkDnsEventReported event;
644 int rv =
645 android_gethostbynamefornetcontext(hostname, family, &mNetcontext, &hp, &event);
Hungming Chenb0cd3dc2019-05-24 16:18:07 +0800646 EXPECT_EQ(nullptr, hp);
647 EXPECT_EQ(EAI_FAIL, rv);
648 }
649 }
650}
651
Hungming Chen947aab02018-12-27 18:33:19 +0800652TEST_F(GetHostByNameForNetContextTest, NoData) {
Hungming Chen947aab02018-12-27 18:33:19 +0800653 constexpr char v4_host_name[] = "v4only.example.com.";
Mike Yuc7649d12019-05-22 15:28:07 +0800654
655 test::DNSResponder dns;
Hungming Chen947aab02018-12-27 18:33:19 +0800656 dns.addMapping(v4_host_name, ns_type::ns_t_a, "1.2.3.3");
657 ASSERT_TRUE(dns.startServer());
Mike Yuc7649d12019-05-22 15:28:07 +0800658 ASSERT_EQ(0, setResolvers());
Hungming Chen947aab02018-12-27 18:33:19 +0800659 dns.clearQueries();
660
661 // Want AAAA answer but DNS server has A answer only.
Luke Huangd8ac4752019-06-18 17:05:47 +0800662 hostent* hp = nullptr;
lifr94981782019-05-17 21:15:19 +0800663 NetworkDnsEventReported event;
664 int rv = android_gethostbynamefornetcontext("v4only", AF_INET6, &mNetcontext, &hp, &event);
Hungming Chen947aab02018-12-27 18:33:19 +0800665 EXPECT_LE(1U, GetNumQueries(dns, v4_host_name));
Hungming Chen70161e52019-05-22 16:33:31 +0800666 EXPECT_EQ(nullptr, hp);
Hungming Chen947aab02018-12-27 18:33:19 +0800667 EXPECT_EQ(EAI_NODATA, rv);
668}
669
670TEST_F(GetHostByNameForNetContextTest, ServerResponseError) {
Hungming Chen947aab02018-12-27 18:33:19 +0800671 constexpr char host_name[] = "hello.example.com.";
672
673 static const struct TestConfig {
674 ns_rcode rcode;
Bernie Innocenti7916c6a2019-04-25 15:16:51 +0900675 int expected_eai_error; // expected result
Hungming Chen947aab02018-12-27 18:33:19 +0800676
677 // Only test failure RCODE [1..5] in RFC 1035 section 4.1.1 and skip successful RCODE 0
678 // which means no error. Note that the return error codes aren't mapped by rcode in the
679 // test case SERVFAIL, NOTIMP and REFUSED. See the comment of res_nsend()
680 // in system\netd\resolv\res_query.cpp for more detail.
681 } testConfigs[]{
682 // clang-format off
683 {ns_rcode::ns_r_formerr, EAI_FAIL},
684 {ns_rcode::ns_r_servfail, EAI_AGAIN}, // Not mapped by rcode.
685 {ns_rcode::ns_r_nxdomain, EAI_NODATA},
686 {ns_rcode::ns_r_notimpl, EAI_AGAIN}, // Not mapped by rcode.
687 {ns_rcode::ns_r_refused, EAI_AGAIN}, // Not mapped by rcode.
688 // clang-format on
689 };
690
691 for (const auto& config : testConfigs) {
692 SCOPED_TRACE(StringPrintf("rcode: %d", config.rcode));
693
Mike Yuc7649d12019-05-22 15:28:07 +0800694 test::DNSResponder dns(config.rcode);
Hungming Chen947aab02018-12-27 18:33:19 +0800695 dns.addMapping(host_name, ns_type::ns_t_a, "1.2.3.4");
696 dns.setResponseProbability(0.0); // always ignore requests and response preset rcode
697 ASSERT_TRUE(dns.startServer());
Mike Yuc7649d12019-05-22 15:28:07 +0800698 ASSERT_EQ(0, setResolvers());
Hungming Chen947aab02018-12-27 18:33:19 +0800699
Luke Huangd8ac4752019-06-18 17:05:47 +0800700 hostent* hp = nullptr;
lifr94981782019-05-17 21:15:19 +0800701 NetworkDnsEventReported event;
702 int rv = android_gethostbynamefornetcontext(host_name, AF_INET, &mNetcontext, &hp, &event);
Hungming Chen70161e52019-05-22 16:33:31 +0800703 EXPECT_EQ(nullptr, hp);
Bernie Innocenti7916c6a2019-04-25 15:16:51 +0900704 EXPECT_EQ(config.expected_eai_error, rv);
Hungming Chen947aab02018-12-27 18:33:19 +0800705 }
706}
707
708// TODO: Add private DNS server timeout test.
709TEST_F(GetHostByNameForNetContextTest, ServerTimeout) {
Hungming Chen947aab02018-12-27 18:33:19 +0800710 constexpr char host_name[] = "hello.example.com.";
Mike Yuc7649d12019-05-22 15:28:07 +0800711 test::DNSResponder dns(static_cast<ns_rcode>(-1) /*no response*/);
Hungming Chen947aab02018-12-27 18:33:19 +0800712 dns.addMapping(host_name, ns_type::ns_t_a, "1.2.3.4");
713 dns.setResponseProbability(0.0); // always ignore requests and don't response
714 ASSERT_TRUE(dns.startServer());
Mike Yuc7649d12019-05-22 15:28:07 +0800715 ASSERT_EQ(0, setResolvers());
Hungming Chen947aab02018-12-27 18:33:19 +0800716
Luke Huangd8ac4752019-06-18 17:05:47 +0800717 hostent* hp = nullptr;
lifr94981782019-05-17 21:15:19 +0800718 NetworkDnsEventReported event;
719 int rv = android_gethostbynamefornetcontext(host_name, AF_INET, &mNetcontext, &hp, &event);
Hungming Chen947aab02018-12-27 18:33:19 +0800720 EXPECT_EQ(NETD_RESOLV_TIMEOUT, rv);
721}
722
Hungming Chenb0cd3dc2019-05-24 16:18:07 +0800723TEST_F(GetHostByNameForNetContextTest, CnamesNoIpAddress) {
724 constexpr char ACNAME[] = "acname"; // expect a cname in answer
725 constexpr char CNAMES[] = "cnames"; // expect cname chain in answer
726
Mike Yuc7649d12019-05-22 15:28:07 +0800727 test::DNSResponder dns;
Hungming Chenb0cd3dc2019-05-24 16:18:07 +0800728 dns.addMapping("cnames.example.com.", ns_type::ns_t_cname, "acname.example.com.");
729 dns.addMapping("acname.example.com.", ns_type::ns_t_cname, "hello.example.com.");
730 ASSERT_TRUE(dns.startServer());
Mike Yuc7649d12019-05-22 15:28:07 +0800731 ASSERT_EQ(0, setResolvers());
Hungming Chenb0cd3dc2019-05-24 16:18:07 +0800732
733 static const struct TestConfig {
734 const char* name;
735 int family;
736 } testConfigs[]{
737 {ACNAME, AF_INET},
738 {ACNAME, AF_INET6},
739 {CNAMES, AF_INET},
740 {CNAMES, AF_INET6},
741 };
742
743 for (const auto& config : testConfigs) {
744 SCOPED_TRACE(
745 StringPrintf("config.family: %d, config.name: %s", config.family, config.name));
746
747 struct hostent* hp = nullptr;
lifr94981782019-05-17 21:15:19 +0800748 NetworkDnsEventReported event;
749 int rv = android_gethostbynamefornetcontext(config.name, config.family, &mNetcontext, &hp,
750 &event);
Hungming Chenb0cd3dc2019-05-24 16:18:07 +0800751 EXPECT_EQ(nullptr, hp);
752 EXPECT_EQ(EAI_FAIL, rv);
753 }
754}
755
756TEST_F(GetHostByNameForNetContextTest, CnamesBrokenChainByIllegalCname) {
Mike Yuc7649d12019-05-22 15:28:07 +0800757 test::DNSResponder dns;
Hungming Chenb0cd3dc2019-05-24 16:18:07 +0800758 ASSERT_TRUE(dns.startServer());
Mike Yuc7649d12019-05-22 15:28:07 +0800759 ASSERT_EQ(0, setResolvers());
Hungming Chenb0cd3dc2019-05-24 16:18:07 +0800760
761 static const struct TestConfig {
762 const char* name;
763 const char* cname;
764 std::string asHostName() const { return StringPrintf("%s.example.com.", name); }
765
766 // Illegal cname is verified by res_hnok() in system/netd/resolv/res_comp.cpp
767 } testConfigs[]{
768 // clang-format off
769 {NAME(kBadCharAfterPeriodHost), kBadCharAfterPeriodHost},
770 {NAME(kBadCharBeforePeriodHost), kBadCharBeforePeriodHost},
771 {NAME(kBadCharAtTheEndHost), kBadCharAtTheEndHost},
772 {NAME(kBadCharInTheMiddleOfLabelHost), kBadCharInTheMiddleOfLabelHost},
773 // clang-format on
774 };
775
776 for (const auto& config : testConfigs) {
777 const std::string testHostName = config.asHostName();
778
779 // Expect to get no address because the cname chain is broken by an illegal cname format.
780 //
781 // Ex:
782 // ANSWER SECTION:
783 // hello.example.com. IN CNAME a.ex^ample.com.
784 // a.ex^ample.com. IN A 1.2.3.3
785 // a.ex^ample.com. IN AAAA 2001:db8::42
786 //
787 // In this example, querying hello.example.com should get no address because
788 // "a.ex^ample.com" has an illegal char '^' in the middle of label.
789 dns.addMapping(testHostName.c_str(), ns_type::ns_t_cname, config.cname);
790 dns.addMapping(config.cname, ns_type::ns_t_a, "1.2.3.3");
791 dns.addMapping(config.cname, ns_type::ns_t_aaaa, "2001:db8::42");
792
793 for (const auto& family : {AF_INET, AF_INET6}) {
794 SCOPED_TRACE(
795 StringPrintf("family: %d, testHostName: %s", family, testHostName.c_str()));
796
797 struct hostent* hp = nullptr;
lifr94981782019-05-17 21:15:19 +0800798 NetworkDnsEventReported event;
799 int rv = android_gethostbynamefornetcontext(config.name, family, &mNetcontext, &hp,
800 &event);
Hungming Chenb0cd3dc2019-05-24 16:18:07 +0800801 EXPECT_EQ(nullptr, hp);
802 EXPECT_EQ(EAI_FAIL, rv);
803 }
804 }
805}
806
807TEST_F(GetHostByNameForNetContextTest, CnamesInfiniteLoop) {
Mike Yuc7649d12019-05-22 15:28:07 +0800808 test::DNSResponder dns;
Hungming Chenb0cd3dc2019-05-24 16:18:07 +0800809 dns.addMapping("hello.example.com.", ns_type::ns_t_cname, "a.example.com.");
810 dns.addMapping("a.example.com.", ns_type::ns_t_cname, "hello.example.com.");
811 ASSERT_TRUE(dns.startServer());
Mike Yuc7649d12019-05-22 15:28:07 +0800812 ASSERT_EQ(0, setResolvers());
Hungming Chenb0cd3dc2019-05-24 16:18:07 +0800813
814 for (const auto& family : {AF_INET, AF_INET6}) {
815 SCOPED_TRACE(StringPrintf("family: %d", family));
816
817 struct hostent* hp = nullptr;
lifr94981782019-05-17 21:15:19 +0800818 NetworkDnsEventReported event;
819 int rv = android_gethostbynamefornetcontext("hello", family, &mNetcontext, &hp, &event);
Hungming Chenb0cd3dc2019-05-24 16:18:07 +0800820 EXPECT_EQ(nullptr, hp);
821 EXPECT_EQ(EAI_FAIL, rv);
822 }
823}
824
Luke Huang69e67182019-06-17 17:06:41 +0800825// Note that local host file function, files_getaddrinfo(), of resolv_getaddrinfo()
Hungming Chen947aab02018-12-27 18:33:19 +0800826// is not tested because it only returns a boolean (success or failure) without any error number.
827
Luke Huang2dac4382019-06-24 13:28:44 +0800828// TODO: Simplify the DNS server configuration, DNSResponder and resolv_set_nameservers, as
Hungming Chen70161e52019-05-22 16:33:31 +0800829// ResolverTest does.
Luke Huang69e67182019-06-17 17:06:41 +0800830// TODO: Add test for resolv_getaddrinfo().
Hungming Chen70161e52019-05-22 16:33:31 +0800831// - DNS response message parsing.
832// - Unexpected type of resource record (RR).
833// - Invalid length CNAME, or QNAME.
834// - Unexpected amount of questions.
835// - CNAME RDATA with the domain name which has null label(s).
836// TODO: Add test for android_gethostbynamefornetcontext().
837// - Invalid parameters.
Hungming Chenb0cd3dc2019-05-24 16:18:07 +0800838// - DNS response message parsing.
839// - Unexpected type of resource record (RR).
840// - Invalid length CNAME, or QNAME.
841// - Unexpected amount of questions.
842// - CNAME RDATA with the domain name which has null label(s).
Hungming Chen70161e52019-05-22 16:33:31 +0800843// TODO: Add test for android_gethostbyaddrfornetcontext().
nuccachen0efcc802018-11-28 18:19:39 +0800844
845} // end of namespace net
846} // end of namespace android