Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(462)

Side by Side Diff: net/dns/dns_config_service_posix.cc

Issue 21368005: Detect domain-specific resolvers on OS X and disable DnsClient in such cases. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add unhandled_options to NetLog Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/dns/dns_config_service_posix.h" 5 #include "net/dns/dns_config_service_posix.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/basictypes.h" 9 #include "base/basictypes.h"
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/files/file_path.h" 11 #include "base/files/file_path.h"
12 #include "base/files/file_path_watcher.h" 12 #include "base/files/file_path_watcher.h"
13 #include "base/lazy_instance.h"
13 #include "base/memory/scoped_ptr.h" 14 #include "base/memory/scoped_ptr.h"
14 #include "base/metrics/histogram.h" 15 #include "base/metrics/histogram.h"
15 #include "base/time/time.h" 16 #include "base/time/time.h"
16 #include "net/base/ip_endpoint.h" 17 #include "net/base/ip_endpoint.h"
17 #include "net/base/net_util.h" 18 #include "net/base/net_util.h"
18 #include "net/dns/dns_hosts.h" 19 #include "net/dns/dns_hosts.h"
19 #include "net/dns/dns_protocol.h" 20 #include "net/dns/dns_protocol.h"
20 #include "net/dns/notify_watcher_mac.h" 21 #include "net/dns/notify_watcher_mac.h"
21 #include "net/dns/serial_worker.h" 22 #include "net/dns/serial_worker.h"
22 23
24 #if defined(OS_MACOSX)
25 #include <dlfcn.h>
26 #include "third_party/apple_dnsinfo/dnsinfo.h"
27 namespace {
28
29 // dnsinfo symbols are available via System.framework, but can
Mark Mentovai 2013/08/06 15:41:00 System.framework is just a symbolic link to libSys
szym 2013/08/06 17:50:25 Done.
30 // also be present in SystemConfiguration. To avoid confusion,
Mark Mentovai 2013/08/06 15:41:00 …and say SystemConfiguration.framework on this lin
szym 2013/08/06 17:50:25 Done.
31 // load them explicitly from System.
32 class DnsInfoApi {
33 public:
34 typedef const char* (*dns_configuration_notify_key_t)();
35 typedef dns_config_t* (*dns_configuration_copy_t)();
36 typedef void (*dns_configuration_free_t)(dns_config_t*);
37
38 DnsInfoApi() {
39 handle_ = dlopen("/usr/lib/libSystem.dylib",
40 RTLD_LAZY | RTLD_NOLOAD);
41 if (!handle_) return;
42 dns_configuration_notify_key =
43 reinterpret_cast<dns_configuration_notify_key_t>(
44 dlsym(handle_, "dns_configuration_notify_key"));
45 dns_configuration_copy =
46 reinterpret_cast<dns_configuration_copy_t>(
47 dlsym(handle_, "dns_configuration_copy"));
48 dns_configuration_free =
49 reinterpret_cast<dns_configuration_free_t>(
50 dlsym(handle_, "dns_configuration_free"));
51 }
52 ~DnsInfoApi() {
53 if (handle_) dlclose(handle_);
54 }
55 bool ready() const { return handle_; }
Mark Mentovai 2013/08/06 15:41:00 ready() isn’t a great interface. It checks that th
szym 2013/08/06 17:50:25 Done.
56
57 dns_configuration_notify_key_t dns_configuration_notify_key;
Mark Mentovai 2013/08/06 15:41:00 Someone outside of this class can accidentally say
szym 2013/08/06 15:48:58 That's exactly why dns_info_api() returns a _const
58 dns_configuration_copy_t dns_configuration_copy;
59 dns_configuration_free_t dns_configuration_free;
60
61 private:
62 void* handle_;
63 };
64
65 const DnsInfoApi& dns_info_api() {
66 base::LazyInstance<DnsInfoApi>::Leaky api = LAZY_INSTANCE_INITIALIZER;
67 return api.Get();
68 }
69
70 } // namespace
71 #endif
72
23 namespace net { 73 namespace net {
24 74
25 #if !defined(OS_ANDROID) 75 #if !defined(OS_ANDROID)
26 namespace internal { 76 namespace internal {
27 77
28 namespace { 78 namespace {
29 79
30 const base::FilePath::CharType* kFilePathHosts = 80 const base::FilePath::CharType* kFilePathHosts =
31 FILE_PATH_LITERAL("/etc/hosts"); 81 FILE_PATH_LITERAL("/etc/hosts");
32 82
33 #if defined(OS_MACOSX) 83 #if defined(OS_MACOSX)
34 // From 10.7.3 configd-395.10/dnsinfo/dnsinfo.h
35 static const char* kDnsNotifyKey =
36 "com.apple.system.SystemConfiguration.dns_configuration";
37
38 class ConfigWatcher { 84 class ConfigWatcher {
39 public: 85 public:
40 bool Watch(const base::Callback<void(bool succeeded)>& callback) { 86 bool Watch(const base::Callback<void(bool succeeded)>& callback) {
41 return watcher_.Watch(kDnsNotifyKey, callback); 87 if (!dns_info_api().ready()) return false;
88 return watcher_.Watch(dns_info_api().dns_configuration_notify_key(),
89 callback);
42 } 90 }
43 91
44 private: 92 private:
45 NotifyWatcherMac watcher_; 93 NotifyWatcherMac watcher_;
46 }; 94 };
47 #else 95 #else
48 96
49 #ifndef _PATH_RESCONF // Normally defined in <resolv.h> 97 #ifndef _PATH_RESCONF // Normally defined in <resolv.h>
50 #define _PATH_RESCONF "/etc/resolv.conf" 98 #define _PATH_RESCONF "/etc/resolv.conf"
51 #endif 99 #endif
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 } else { 141 } else {
94 result = CONFIG_PARSE_POSIX_RES_INIT_FAILED; 142 result = CONFIG_PARSE_POSIX_RES_INIT_FAILED;
95 } 143 }
96 // Prefer res_ndestroy where available. 144 // Prefer res_ndestroy where available.
97 #if defined(OS_MACOSX) || defined(OS_FREEBSD) 145 #if defined(OS_MACOSX) || defined(OS_FREEBSD)
98 res_ndestroy(&res); 146 res_ndestroy(&res);
99 #else 147 #else
100 res_nclose(&res); 148 res_nclose(&res);
101 #endif 149 #endif
102 #endif 150 #endif
151
152 #if defined(OS_MACOSX)
153 if (!dns_info_api().ready()) return CONFIG_PARSE_POSIX_NO_DNSINFO;
154 dns_config_t* dns_config = dns_info_api().dns_configuration_copy();
155 if (!dns_config)
156 return CONFIG_PARSE_POSIX_NO_DNSINFO;
157
158 // TODO(szym): Parse dns_config_t for resolvers rather than res_state.
159 // DnsClient can't handle domain-specific unscoped resolvers.
160 unsigned num_resolvers = 0;
161 for (int i = 0; i < dns_config->n_resolver; ++i) {
162 dns_resolver_t* resolver = dns_config->resolver[i];
163 if (!resolver->n_nameserver)
164 continue;
165 if (resolver->options && !strcmp(resolver->options, "mdns"))
166 continue;
167 ++num_resolvers;
168 }
169 dns_info_api().dns_configuration_free(dns_config);
Mark Mentovai 2013/08/06 15:41:00 Can you add a scoper to free this instead of calli
szym 2013/08/06 17:50:25 Done.
170 if (num_resolvers > 1) {
171 LOG(WARNING) << "dns_config has unhandled options!";
172 return CONFIG_PARSE_POSIX_UNHANDLED_OPTIONS;
173 }
174 #endif
103 // Override timeout value to match default setting on Windows. 175 // Override timeout value to match default setting on Windows.
104 config->timeout = base::TimeDelta::FromSeconds(kDnsTimeoutSeconds); 176 config->timeout = base::TimeDelta::FromSeconds(kDnsTimeoutSeconds);
105 return result; 177 return result;
106 } 178 }
107 179
108 } // namespace 180 } // namespace
109 181
110 class DnsConfigServicePosix::Watcher { 182 class DnsConfigServicePosix::Watcher {
111 public: 183 public:
112 explicit Watcher(DnsConfigServicePosix* service) 184 explicit Watcher(DnsConfigServicePosix* service)
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 236
165 // A SerialWorker that uses libresolv to initialize res_state and converts 237 // A SerialWorker that uses libresolv to initialize res_state and converts
166 // it to DnsConfig. 238 // it to DnsConfig.
167 class DnsConfigServicePosix::ConfigReader : public SerialWorker { 239 class DnsConfigServicePosix::ConfigReader : public SerialWorker {
168 public: 240 public:
169 explicit ConfigReader(DnsConfigServicePosix* service) 241 explicit ConfigReader(DnsConfigServicePosix* service)
170 : service_(service), success_(false) {} 242 : service_(service), success_(false) {}
171 243
172 virtual void DoWork() OVERRIDE { 244 virtual void DoWork() OVERRIDE {
173 base::TimeTicks start_time = base::TimeTicks::Now(); 245 base::TimeTicks start_time = base::TimeTicks::Now();
246 dns_config_.unhandled_options = false;
174 ConfigParsePosixResult result = ReadDnsConfig(&dns_config_); 247 ConfigParsePosixResult result = ReadDnsConfig(&dns_config_);
175 success_ = (result == CONFIG_PARSE_POSIX_OK); 248 switch (result) {
249 case CONFIG_PARSE_POSIX_MISSING_OPTIONS:
250 case CONFIG_PARSE_POSIX_UNHANDLED_OPTIONS:
251 dns_config_.unhandled_options = true;
252 // Fall through.
253 case CONFIG_PARSE_POSIX_OK:
254 success_ = true;
255 break;
256 default:
257 success_ = false;
258 break;
259 }
176 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ConfigParsePosix", 260 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ConfigParsePosix",
177 result, CONFIG_PARSE_POSIX_MAX); 261 result, CONFIG_PARSE_POSIX_MAX);
178 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.ConfigParseResult", success_); 262 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.ConfigParseResult", success_);
179 UMA_HISTOGRAM_TIMES("AsyncDNS.ConfigParseDuration", 263 UMA_HISTOGRAM_TIMES("AsyncDNS.ConfigParseDuration",
180 base::TimeTicks::Now() - start_time); 264 base::TimeTicks::Now() - start_time);
181 } 265 }
182 266
183 virtual void OnWorkFinished() OVERRIDE { 267 virtual void OnWorkFinished() OVERRIDE {
184 DCHECK(!IsCancelled()); 268 DCHECK(!IsCancelled());
185 if (success_) { 269 if (success_) {
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 virtual void ReadNow() OVERRIDE {} 479 virtual void ReadNow() OVERRIDE {}
396 virtual bool StartWatching() OVERRIDE { return false; } 480 virtual bool StartWatching() OVERRIDE { return false; }
397 }; 481 };
398 // static 482 // static
399 scoped_ptr<DnsConfigService> DnsConfigService::CreateSystemService() { 483 scoped_ptr<DnsConfigService> DnsConfigService::CreateSystemService() {
400 return scoped_ptr<DnsConfigService>(new StubDnsConfigService()); 484 return scoped_ptr<DnsConfigService>(new StubDnsConfigService());
401 } 485 }
402 #endif 486 #endif
403 487
404 } // namespace net 488 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698