blob: 35fcbab3500040aa45c7526d1af6708c6136ac09 [file] [log] [blame]
[email protected]fea484e2012-02-07 23:21:571// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]d84316a2011-08-18 04:41:212// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]d84316a2011-08-18 04:41:215#include <resolv.h>
6
fdoray81f6ee032016-09-15 14:10:367#include <memory>
8
pauljensen101ed372015-04-17 00:11:429#include "base/cancelable_callback.h"
10#include "base/files/file_util.h"
fdoray81f6ee032016-09-15 14:10:3611#include "base/memory/ptr_util.h"
12#include "base/run_loop.h"
[email protected]0e6f6192011-12-28 23:18:2113#include "base/sys_byteorder.h"
pauljensen101ed372015-04-17 00:11:4214#include "base/test/test_timeouts.h"
15#include "base/threading/platform_thread.h"
martijna23c8962016-03-04 18:18:5116#include "net/base/ip_address.h"
[email protected]d84316a2011-08-18 04:41:2117#include "net/dns/dns_config_service_posix.h"
pauljensen101ed372015-04-17 00:11:4218#include "net/dns/dns_protocol.h"
[email protected]6998a662011-09-03 00:17:2919
[email protected]d84316a2011-08-18 04:41:2120#include "testing/gtest/include/gtest/gtest.h"
21
pauljensen101ed372015-04-17 00:11:4222#if defined(OS_ANDROID)
23#include "base/android/path_utils.h"
24#endif // defined(OS_ANDROID)
[email protected]f6679032014-01-21 20:31:1425
bcwhitee2452b1f2015-11-30 19:09:3326// Required for inet_pton()
27#if defined(OS_WIN)
28#include <winsock2.h>
29#else
30#include <arpa/inet.h>
31#endif
32
[email protected]d84316a2011-08-18 04:41:2133namespace net {
pauljensen101ed372015-04-17 00:11:4234
35#if !defined(OS_ANDROID)
36
[email protected]d84316a2011-08-18 04:41:2137namespace {
38
[email protected]7549cc22012-05-12 09:39:5539// MAXNS is normally 3, but let's test 4 if possible.
thestig9d3bb0c2015-01-24 00:49:5140const char* const kNameserversIPv4[] = {
[email protected]7549cc22012-05-12 09:39:5541 "8.8.8.8",
42 "192.168.1.1",
43 "63.1.2.4",
44 "1.0.0.1",
45};
[email protected]d84316a2011-08-18 04:41:2146
[email protected]629ddf852012-07-20 16:17:2947#if defined(OS_LINUX)
thestig9d3bb0c2015-01-24 00:49:5148const char* const kNameserversIPv6[] = {
[email protected]7549cc22012-05-12 09:39:5549 NULL,
50 "2001:DB8:0::42",
51 NULL,
52 "::FFFF:129.144.52.38",
53};
[email protected]629ddf852012-07-20 16:17:2954#endif
[email protected]d84316a2011-08-18 04:41:2155
maclellant912064d2015-11-20 23:21:4656void DummyConfigCallback(const DnsConfig& config) {
57 // Do nothing
58}
59
[email protected]7549cc22012-05-12 09:39:5560// Fills in |res| with sane configuration.
61void InitializeResState(res_state res) {
[email protected]d84316a2011-08-18 04:41:2162 memset(res, 0, sizeof(*res));
[email protected]539df6c2012-06-19 21:21:2963 res->options = RES_INIT | RES_RECURSE | RES_DEFNAMES | RES_DNSRCH |
64 RES_ROTATE;
[email protected]d84316a2011-08-18 04:41:2165 res->ndots = 2;
[email protected]7549cc22012-05-12 09:39:5566 res->retrans = 4;
[email protected]d84316a2011-08-18 04:41:2167 res->retry = 7;
68
69 const char kDnsrch[] = "chromium.org" "\0" "example.com";
70 memcpy(res->defdname, kDnsrch, sizeof(kDnsrch));
71 res->dnsrch[0] = res->defdname;
72 res->dnsrch[1] = res->defdname + sizeof("chromium.org");
73
[email protected]7549cc22012-05-12 09:39:5574 for (unsigned i = 0; i < arraysize(kNameserversIPv4) && i < MAXNS; ++i) {
[email protected]d84316a2011-08-18 04:41:2175 struct sockaddr_in sa;
76 sa.sin_family = AF_INET;
[email protected]7549cc22012-05-12 09:39:5577 sa.sin_port = base::HostToNet16(NS_DEFAULTPORT + i);
78 inet_pton(AF_INET, kNameserversIPv4[i], &sa.sin_addr);
[email protected]d84316a2011-08-18 04:41:2179 res->nsaddr_list[i] = sa;
[email protected]7549cc22012-05-12 09:39:5580 ++res->nscount;
[email protected]d84316a2011-08-18 04:41:2181 }
[email protected]d84316a2011-08-18 04:41:2182
[email protected]5c5b7382011-08-18 18:02:3383#if defined(OS_LINUX)
[email protected]7549cc22012-05-12 09:39:5584 // Install IPv6 addresses, replacing the corresponding IPv4 addresses.
85 unsigned nscount6 = 0;
86 for (unsigned i = 0; i < arraysize(kNameserversIPv6) && i < MAXNS; ++i) {
87 if (!kNameserversIPv6[i])
88 continue;
[email protected]d84316a2011-08-18 04:41:2189 // Must use malloc to mimick res_ninit.
90 struct sockaddr_in6 *sa6;
91 sa6 = (struct sockaddr_in6 *)malloc(sizeof(*sa6));
92 sa6->sin6_family = AF_INET6;
[email protected]9eb7b11b2012-03-28 20:19:3193 sa6->sin6_port = base::HostToNet16(NS_DEFAULTPORT - i);
[email protected]7549cc22012-05-12 09:39:5594 inet_pton(AF_INET6, kNameserversIPv6[i], &sa6->sin6_addr);
[email protected]d84316a2011-08-18 04:41:2195 res->_u._ext.nsaddrs[i] = sa6;
[email protected]7549cc22012-05-12 09:39:5596 memset(&res->nsaddr_list[i], 0, sizeof res->nsaddr_list[i]);
97 ++nscount6;
[email protected]d84316a2011-08-18 04:41:2198 }
[email protected]7549cc22012-05-12 09:39:5599 res->_u._ext.nscount6 = nscount6;
[email protected]d84316a2011-08-18 04:41:21100#endif
101}
102
103void CloseResState(res_state res) {
[email protected]5c5b7382011-08-18 18:02:33104#if defined(OS_LINUX)
[email protected]7549cc22012-05-12 09:39:55105 for (int i = 0; i < res->nscount; ++i) {
106 if (res->_u._ext.nsaddrs[i] != NULL)
107 free(res->_u._ext.nsaddrs[i]);
108 }
109#endif
110}
111
112void InitializeExpectedConfig(DnsConfig* config) {
113 config->ndots = 2;
114 config->timeout = base::TimeDelta::FromSeconds(4);
115 config->attempts = 7;
116 config->rotate = true;
117 config->edns0 = false;
118 config->append_to_multi_label_name = true;
119 config->search.clear();
120 config->search.push_back("chromium.org");
121 config->search.push_back("example.com");
122
123 config->nameservers.clear();
124 for (unsigned i = 0; i < arraysize(kNameserversIPv4) && i < MAXNS; ++i) {
martijna23c8962016-03-04 18:18:51125 IPAddress ip;
126 EXPECT_TRUE(ip.AssignFromIPLiteral(kNameserversIPv4[i]));
[email protected]7549cc22012-05-12 09:39:55127 config->nameservers.push_back(IPEndPoint(ip, NS_DEFAULTPORT + i));
128 }
129
130#if defined(OS_LINUX)
131 for (unsigned i = 0; i < arraysize(kNameserversIPv6) && i < MAXNS; ++i) {
132 if (!kNameserversIPv6[i])
133 continue;
martijna23c8962016-03-04 18:18:51134 IPAddress ip;
135 EXPECT_TRUE(ip.AssignFromIPLiteral(kNameserversIPv6[i]));
[email protected]7549cc22012-05-12 09:39:55136 config->nameservers[i] = IPEndPoint(ip, NS_DEFAULTPORT - i);
[email protected]d84316a2011-08-18 04:41:21137 }
138#endif
139}
140
[email protected]b3601bc22012-02-21 21:23:20141TEST(DnsConfigServicePosixTest, ConvertResStateToDnsConfig) {
[email protected]7549cc22012-05-12 09:39:55142 struct __res_state res;
143 DnsConfig config;
144 EXPECT_FALSE(config.IsValid());
145 InitializeResState(&res);
[email protected]539df6c2012-06-19 21:21:29146 ASSERT_EQ(internal::CONFIG_PARSE_POSIX_OK,
147 internal::ConvertResStateToDnsConfig(res, &config));
[email protected]7549cc22012-05-12 09:39:55148 CloseResState(&res);
149 EXPECT_TRUE(config.IsValid());
150
151 DnsConfig expected_config;
152 EXPECT_FALSE(expected_config.EqualsIgnoreHosts(config));
153 InitializeExpectedConfig(&expected_config);
154 EXPECT_TRUE(expected_config.EqualsIgnoreHosts(config));
[email protected]d84316a2011-08-18 04:41:21155}
156
[email protected]45d2f8472012-06-14 17:48:39157TEST(DnsConfigServicePosixTest, RejectEmptyNameserver) {
158 struct __res_state res = {};
[email protected]539df6c2012-06-19 21:21:29159 res.options = RES_INIT | RES_RECURSE | RES_DEFNAMES | RES_DNSRCH;
[email protected]45d2f8472012-06-14 17:48:39160 const char kDnsrch[] = "chromium.org";
161 memcpy(res.defdname, kDnsrch, sizeof(kDnsrch));
162 res.dnsrch[0] = res.defdname;
163
164 struct sockaddr_in sa = {};
165 sa.sin_family = AF_INET;
166 sa.sin_port = base::HostToNet16(NS_DEFAULTPORT);
167 sa.sin_addr.s_addr = INADDR_ANY;
168 res.nsaddr_list[0] = sa;
169 sa.sin_addr.s_addr = 0xCAFE1337;
170 res.nsaddr_list[1] = sa;
171 res.nscount = 2;
172
173 DnsConfig config;
[email protected]539df6c2012-06-19 21:21:29174 EXPECT_EQ(internal::CONFIG_PARSE_POSIX_NULL_ADDRESS,
175 internal::ConvertResStateToDnsConfig(res, &config));
[email protected]45d2f8472012-06-14 17:48:39176
177 sa.sin_addr.s_addr = 0xDEADBEEF;
178 res.nsaddr_list[0] = sa;
[email protected]539df6c2012-06-19 21:21:29179 EXPECT_EQ(internal::CONFIG_PARSE_POSIX_OK,
180 internal::ConvertResStateToDnsConfig(res, &config));
[email protected]45d2f8472012-06-14 17:48:39181}
182
maclellant912064d2015-11-20 23:21:46183TEST(DnsConfigServicePosixTest, DestroyWhileJobsWorking) {
184 // Regression test to verify crash does not occur if DnsConfigServicePosix
185 // instance is destroyed while SerialWorker jobs have posted to worker pool.
danakj22f90e72016-04-16 01:55:40186 std::unique_ptr<internal::DnsConfigServicePosix> service(
maclellant912064d2015-11-20 23:21:46187 new internal::DnsConfigServicePosix());
188 service->ReadConfig(base::Bind(&DummyConfigCallback));
189 service.reset();
190 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1000));
191}
192
[email protected]b4481b222012-03-16 17:13:11193} // namespace
[email protected]f6679032014-01-21 20:31:14194
pauljensen101ed372015-04-17 00:11:42195#else // OS_ANDROID
196
197namespace internal {
198
199const char kTempHosts1[] = "127.0.0.1 localhost";
juliatuttlea2e7ea62016-05-05 13:56:36200// kTempHosts2 is only used by SeenChangeSinceHostsChange, which doesn't run
201// on Android.
202#if !defined(OS_ANDROID)
pauljensen101ed372015-04-17 00:11:42203const char kTempHosts2[] = "127.0.0.2 localhost";
juliatuttlea2e7ea62016-05-05 13:56:36204#endif // !defined(OS_ANDROID)
pauljensen101ed372015-04-17 00:11:42205
206class DnsConfigServicePosixTest : public testing::Test {
207 public:
208 DnsConfigServicePosixTest() : seen_config_(false) {}
209 ~DnsConfigServicePosixTest() override {}
210
211 void OnConfigChanged(const DnsConfig& config) {
212 EXPECT_TRUE(config.IsValid());
213 seen_config_ = true;
fdoray81f6ee032016-09-15 14:10:36214 run_loop_->QuitWhenIdle();
pauljensen101ed372015-04-17 00:11:42215 }
216
217 void WriteMockHostsFile(const char* hosts_string) {
218 ASSERT_EQ(base::WriteFile(temp_file_, hosts_string, strlen(hosts_string)),
219 static_cast<int>(strlen(hosts_string)));
220 }
221
222 void MockDNSConfig(const char* dns_server) {
martijna23c8962016-03-04 18:18:51223 IPAddress dns_address;
224 ASSERT_TRUE(dns_address.AssignFromIPLiteral(dns_server));
pauljensen101ed372015-04-17 00:11:42225 test_config_.nameservers.clear();
226 test_config_.nameservers.push_back(
martijna23c8962016-03-04 18:18:51227 IPEndPoint(dns_address, dns_protocol::kDefaultPort));
pauljensen101ed372015-04-17 00:11:42228 service_->SetDnsConfigForTesting(&test_config_);
229 }
230
maclellant912064d2015-11-20 23:21:46231 void MockHostsFilePath(const char* file_path) {
232 service_->SetHostsFilePathForTesting(file_path);
233 }
234
pauljensen101ed372015-04-17 00:11:42235 void SetUp() override {
236 // TODO(pauljensen): Get rid of GetExternalStorageDirectory() when
237 // crbug.com/475568 is fixed. For now creating a temp file in the
238 // default temp directory (/data/data/...) will cause FilePathWatcher
239 // to fail, so create the temp file in /sdcard.
240 base::FilePath parent_dir;
241 ASSERT_TRUE(base::android::GetExternalStorageDirectory(&parent_dir));
242 ASSERT_TRUE(base::CreateTemporaryFileInDir(parent_dir, &temp_file_));
243 WriteMockHostsFile(kTempHosts1);
244 // Set the time on the hosts file back so it appears older than the
245 // 1s safety offset in DnsConfigServicePosix::SeenChangeSince().
246 // TODO(pauljensen): Switch from Sleep() to TouchFile() when
247 // crbug.com/475568 is fixed. For now TouchFile() will fail in /sdcard.
248 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1100));
249 // // Copy real hosts file's last modified time to mock hosts file.
250 // base::File hosts(base::FilePath(DnsConfigServicePosix::kFilePathHosts),
251 // base::File::FLAG_OPEN | base::File::FLAG_READ);
252 // base::File::Info hosts_info;
253 // ASSERT_TRUE(hosts.GetInfo(&hosts_info));
254 // ASSERT_TRUE(base::TouchFile(temp_file_, hosts_info.last_modified,
255 // hosts_info.last_accessed));
256 }
257
258 void TearDown() override { ASSERT_TRUE(base::DeleteFile(temp_file_, false)); }
259
260 void StartWatching() {
261 creation_time_ = base::Time::Now();
262 service_.reset(new DnsConfigServicePosix());
maclellant912064d2015-11-20 23:21:46263 MockHostsFilePath(temp_file_.value().c_str());
pauljensen101ed372015-04-17 00:11:42264 MockDNSConfig("8.8.8.8");
265 seen_config_ = false;
266 service_->WatchConfig(base::Bind(
267 &DnsConfigServicePosixTest::OnConfigChanged, base::Unretained(this)));
268 ExpectChange();
269 }
270
271 void ExpectChange() {
272 EXPECT_FALSE(seen_config_);
fdoray81f6ee032016-09-15 14:10:36273 run_loop_ = base::MakeUnique<base::RunLoop>();
274 run_loop_->Run();
pauljensen101ed372015-04-17 00:11:42275 EXPECT_TRUE(seen_config_);
276 seen_config_ = false;
277 }
278
279 bool seen_config_;
280 base::Time creation_time_;
281 base::FilePath temp_file_;
danakj22f90e72016-04-16 01:55:40282 std::unique_ptr<DnsConfigServicePosix> service_;
pauljensen101ed372015-04-17 00:11:42283 DnsConfig test_config_;
fdoray81f6ee032016-09-15 14:10:36284 std::unique_ptr<base::RunLoop> run_loop_;
pauljensen101ed372015-04-17 00:11:42285};
286
juliatuttlea2e7ea62016-05-05 13:56:36287TEST_F(DnsConfigServicePosixTest, SeenChangeSinceNetworkChange) {
pauljensen101ed372015-04-17 00:11:42288 // Verify SeenChangeSince() returns false if no changes
289 StartWatching();
290 EXPECT_FALSE(service_->SeenChangeSince(creation_time_));
291 // Verify SeenChangeSince() returns true if network change
292 MockDNSConfig("8.8.4.4");
293 service_->OnNetworkChanged(NetworkChangeNotifier::CONNECTION_WIFI);
294 EXPECT_TRUE(service_->SeenChangeSince(creation_time_));
295 ExpectChange();
pauljensen101ed372015-04-17 00:11:42296}
297
298} // namespace internal
299
300#endif // OS_ANDROID
301
302} // namespace net