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

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: update net.gyp 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_apsl/dnsinfo.h"
27 namespace {
28
29 // dnsinfo symbols are available via libSystem.dylib, but can also be present in
30 // SystemConfiguration.framework. To avoid confusion, load them explicitly from
31 // libSystem.dylib.
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
56 dns_configuration_notify_key_t dns_configuration_notify_key;
57 dns_configuration_copy_t dns_configuration_copy;
58 dns_configuration_free_t dns_configuration_free;
59
60 private:
61 void* handle_;
62 };
63
64 const DnsInfoApi& dns_info_api() {
65 base::LazyInstance<DnsInfoApi>::Leaky api = LAZY_INSTANCE_INITIALIZER;
66 return api.Get();
67 }
68
69 struct DnsConfigTDeleter {
70 inline void operator()(dns_config_t* ptr) const {
71 DCHECK(dns_info_api().dns_configuration_free);
Mark Mentovai 2013/08/06 18:05:28 I think you’d want to be defensive and wrap the ne
szym 2013/08/06 22:14:19 Done.
72 dns_info_api().dns_configuration_free(ptr);
73 }
74 };
75
76 } // namespace
77 #endif
78
23 namespace net { 79 namespace net {
24 80
25 #if !defined(OS_ANDROID) 81 #if !defined(OS_ANDROID)
26 namespace internal { 82 namespace internal {
27 83
28 namespace { 84 namespace {
29 85
30 const base::FilePath::CharType* kFilePathHosts = 86 const base::FilePath::CharType* kFilePathHosts =
31 FILE_PATH_LITERAL("/etc/hosts"); 87 FILE_PATH_LITERAL("/etc/hosts");
32 88
33 #if defined(OS_MACOSX) 89 #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 { 90 class ConfigWatcher {
39 public: 91 public:
40 bool Watch(const base::Callback<void(bool succeeded)>& callback) { 92 bool Watch(const base::Callback<void(bool succeeded)>& callback) {
41 return watcher_.Watch(kDnsNotifyKey, callback); 93 if (!dns_info_api().dns_configuration_notify_key) return false;
94 return watcher_.Watch(dns_info_api().dns_configuration_notify_key(),
95 callback);
42 } 96 }
43 97
44 private: 98 private:
45 NotifyWatcherMac watcher_; 99 NotifyWatcherMac watcher_;
46 }; 100 };
47 #else 101 #else
48 102
49 #ifndef _PATH_RESCONF // Normally defined in <resolv.h> 103 #ifndef _PATH_RESCONF // Normally defined in <resolv.h>
50 #define _PATH_RESCONF "/etc/resolv.conf" 104 #define _PATH_RESCONF "/etc/resolv.conf"
51 #endif 105 #endif
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 } else { 147 } else {
94 result = CONFIG_PARSE_POSIX_RES_INIT_FAILED; 148 result = CONFIG_PARSE_POSIX_RES_INIT_FAILED;
95 } 149 }
96 // Prefer res_ndestroy where available. 150 // Prefer res_ndestroy where available.
97 #if defined(OS_MACOSX) || defined(OS_FREEBSD) 151 #if defined(OS_MACOSX) || defined(OS_FREEBSD)
98 res_ndestroy(&res); 152 res_ndestroy(&res);
99 #else 153 #else
100 res_nclose(&res); 154 res_nclose(&res);
101 #endif 155 #endif
102 #endif 156 #endif
157
158 #if defined(OS_MACOSX)
159 if (!dns_info_api().dns_configuration_copy)
160 return CONFIG_PARSE_POSIX_NO_DNSINFO;
161 scoped_ptr<dns_config_t, DnsConfigTDeleter> dns_config(
162 dns_info_api().dns_configuration_copy());
163 if (!dns_config)
164 return CONFIG_PARSE_POSIX_NO_DNSINFO;
165
166 // TODO(szym): Parse dns_config_t for resolvers rather than res_state.
167 // DnsClient can't handle domain-specific unscoped resolvers.
168 unsigned num_resolvers = 0;
169 for (int i = 0; i < dns_config->n_resolver; ++i) {
170 dns_resolver_t* resolver = dns_config->resolver[i];
171 if (!resolver->n_nameserver)
172 continue;
173 if (resolver->options && !strcmp(resolver->options, "mdns"))
Mark Mentovai 2013/08/06 18:05:28 Do we know anything about the “options” format? Is
szym 2013/08/06 22:14:19 http://opensource.apple.com/source/mDNSResponder/m
174 continue;
175 ++num_resolvers;
176 }
177 if (num_resolvers > 1) {
178 LOG(WARNING) << "dns_config has unhandled options!";
179 return CONFIG_PARSE_POSIX_UNHANDLED_OPTIONS;
180 }
181 #endif
103 // Override timeout value to match default setting on Windows. 182 // Override timeout value to match default setting on Windows.
104 config->timeout = base::TimeDelta::FromSeconds(kDnsTimeoutSeconds); 183 config->timeout = base::TimeDelta::FromSeconds(kDnsTimeoutSeconds);
105 return result; 184 return result;
106 } 185 }
107 186
108 } // namespace 187 } // namespace
109 188
110 class DnsConfigServicePosix::Watcher { 189 class DnsConfigServicePosix::Watcher {
111 public: 190 public:
112 explicit Watcher(DnsConfigServicePosix* service) 191 explicit Watcher(DnsConfigServicePosix* service)
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 243
165 // A SerialWorker that uses libresolv to initialize res_state and converts 244 // A SerialWorker that uses libresolv to initialize res_state and converts
166 // it to DnsConfig. 245 // it to DnsConfig.
167 class DnsConfigServicePosix::ConfigReader : public SerialWorker { 246 class DnsConfigServicePosix::ConfigReader : public SerialWorker {
168 public: 247 public:
169 explicit ConfigReader(DnsConfigServicePosix* service) 248 explicit ConfigReader(DnsConfigServicePosix* service)
170 : service_(service), success_(false) {} 249 : service_(service), success_(false) {}
171 250
172 virtual void DoWork() OVERRIDE { 251 virtual void DoWork() OVERRIDE {
173 base::TimeTicks start_time = base::TimeTicks::Now(); 252 base::TimeTicks start_time = base::TimeTicks::Now();
253 dns_config_.unhandled_options = false;
174 ConfigParsePosixResult result = ReadDnsConfig(&dns_config_); 254 ConfigParsePosixResult result = ReadDnsConfig(&dns_config_);
175 success_ = (result == CONFIG_PARSE_POSIX_OK); 255 switch (result) {
256 case CONFIG_PARSE_POSIX_MISSING_OPTIONS:
257 case CONFIG_PARSE_POSIX_UNHANDLED_OPTIONS:
258 dns_config_.unhandled_options = true;
Mark Mentovai 2013/08/06 18:05:28 It seems like ReadDnsConfig should be responsible
szym 2013/08/06 22:14:19 Done, although I'm not sure it's easier to follow
259 // Fall through.
260 case CONFIG_PARSE_POSIX_OK:
261 success_ = true;
262 break;
263 default:
264 success_ = false;
265 break;
266 }
176 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ConfigParsePosix", 267 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ConfigParsePosix",
177 result, CONFIG_PARSE_POSIX_MAX); 268 result, CONFIG_PARSE_POSIX_MAX);
178 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.ConfigParseResult", success_); 269 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.ConfigParseResult", success_);
179 UMA_HISTOGRAM_TIMES("AsyncDNS.ConfigParseDuration", 270 UMA_HISTOGRAM_TIMES("AsyncDNS.ConfigParseDuration",
180 base::TimeTicks::Now() - start_time); 271 base::TimeTicks::Now() - start_time);
181 } 272 }
182 273
183 virtual void OnWorkFinished() OVERRIDE { 274 virtual void OnWorkFinished() OVERRIDE {
184 DCHECK(!IsCancelled()); 275 DCHECK(!IsCancelled());
185 if (success_) { 276 if (success_) {
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 virtual void ReadNow() OVERRIDE {} 486 virtual void ReadNow() OVERRIDE {}
396 virtual bool StartWatching() OVERRIDE { return false; } 487 virtual bool StartWatching() OVERRIDE { return false; }
397 }; 488 };
398 // static 489 // static
399 scoped_ptr<DnsConfigService> DnsConfigService::CreateSystemService() { 490 scoped_ptr<DnsConfigService> DnsConfigService::CreateSystemService() {
400 return scoped_ptr<DnsConfigService>(new StubDnsConfigService()); 491 return scoped_ptr<DnsConfigService>(new StubDnsConfigService());
401 } 492 }
402 #endif 493 #endif
403 494
404 } // namespace net 495 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698