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

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

Issue 10543168: [net/dns] Instrument DnsConfigService to measure performance and failures. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Provide stub service for Android. Created 8 years, 6 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_win.h" 5 #include "net/dns/dns_config_service_win.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/callback.h" 11 #include "base/callback.h"
12 #include "base/compiler_specific.h" 12 #include "base/compiler_specific.h"
13 #include "base/file_path.h" 13 #include "base/file_path.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/memory/scoped_ptr.h" 15 #include "base/memory/scoped_ptr.h"
16 #include "base/metrics/histogram.h"
16 #include "base/string_split.h" 17 #include "base/string_split.h"
17 #include "base/string_util.h" 18 #include "base/string_util.h"
18 #include "base/synchronization/lock.h" 19 #include "base/synchronization/lock.h"
19 #include "base/threading/non_thread_safe.h" 20 #include "base/threading/non_thread_safe.h"
20 #include "base/threading/thread_restrictions.h" 21 #include "base/threading/thread_restrictions.h"
22 #include "base/time.h"
21 #include "base/utf_string_conversions.h" 23 #include "base/utf_string_conversions.h"
22 #include "base/win/registry.h" 24 #include "base/win/registry.h"
23 #include "base/win/windows_version.h" 25 #include "base/win/windows_version.h"
24 #include "googleurl/src/url_canon.h" 26 #include "googleurl/src/url_canon.h"
25 #include "net/base/net_util.h" 27 #include "net/base/net_util.h"
26 #include "net/base/network_change_notifier.h" 28 #include "net/base/network_change_notifier.h"
27 #include "net/dns/dns_hosts.h" 29 #include "net/dns/dns_hosts.h"
28 #include "net/dns/dns_protocol.h" 30 #include "net/dns/dns_protocol.h"
29 #include "net/dns/serial_worker.h" 31 #include "net/dns/serial_worker.h"
30 32
31 #pragma comment(lib, "iphlpapi.lib") 33 #pragma comment(lib, "iphlpapi.lib")
32 34
33 namespace net { 35 namespace net {
34 36
35 namespace internal { 37 namespace internal {
36 38
37 namespace { 39 namespace {
38 40
39 const wchar_t* const kPrimaryDnsSuffixPath = 41 const wchar_t* const kPrimaryDnsSuffixPath =
40 L"SOFTWARE\\Policies\\Microsoft\\System\\DNSClient"; 42 L"SOFTWARE\\Policies\\Microsoft\\System\\DNSClient";
41 43
44 enum ConfigParseWinResult {
45 CONFIG_PARSE_WIN_OK = 0,
46 CONFIG_PARSE_WIN_READ_IPHELPER,
47 CONFIG_PARSE_WIN_READ_POLICY_SEARCHLIST,
48 CONFIG_PARSE_WIN_READ_TCPIP_SEARCHLIST,
49 CONFIG_PARSE_WIN_READ_DOMAIN,
50 CONFIG_PARSE_WIN_READ_POLICY_DEVOLUTION,
51 CONFIG_PARSE_WIN_READ_DNSCACHE_DEVOLUTION,
52 CONFIG_PARSE_WIN_READ_TCPIP_DEVOLUTION,
53 CONFIG_PARSE_WIN_READ_APPEND_MULTILABEL,
54 CONFIG_PARSE_WIN_READ_PRIMARY_SUFFIX,
55 CONFIG_PARSE_WIN_BAD_ADDRESS,
56 CONFIG_PARSE_WIN_NO_NAMESERVERS,
mmenke 2012/06/18 17:19:50 You should name these consistently - Currently som
szym 2012/06/18 20:53:08 The naming scheme is meant to describe the problem
57 CONFIG_PARSE_WIN_MAX // Bounding values for enumeration.
58 };
59
60 static void RecordConfigParseResult(ConfigParseWinResult result) {
61 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ConfigParseWin",
62 result, CONFIG_PARSE_WIN_MAX);
63 }
64
65 enum HostsParseWinResult {
66 HOSTS_PARSE_WIN_OK = 0,
67 HOSTS_PARSE_WIN_READ_HOSTS,
68 HOSTS_PARSE_WIN_READ_COMPUTER_NAME,
69 HOSTS_PARSE_WIN_READ_IPHELPER,
70 HOSTS_PARSE_WIN_BAD_ADDRESS,
mmenke 2012/06/18 17:19:50 See above comment.
71 HOSTS_PARSE_WIN_MAX // Bounding values for enumeration.
72 };
73
74 static void RecordHostsParseResult(HostsParseWinResult result) {
75 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.HostsParseWin",
76 result, HOSTS_PARSE_WIN_MAX);
77 }
78
42 // Convenience for reading values using RegKey. 79 // Convenience for reading values using RegKey.
43 class RegistryReader : public base::NonThreadSafe { 80 class RegistryReader : public base::NonThreadSafe {
44 public: 81 public:
45 explicit RegistryReader(const wchar_t* key) { 82 explicit RegistryReader(const wchar_t* key) {
46 // Ignoring the result. |key_.Valid()| will catch failures. 83 // Ignoring the result. |key_.Valid()| will catch failures.
47 key_.Open(HKEY_LOCAL_MACHINE, key, KEY_QUERY_VALUE); 84 key_.Open(HKEY_LOCAL_MACHINE, key, KEY_QUERY_VALUE);
48 } 85 }
49 86
50 bool ReadString(const wchar_t* name, 87 bool ReadString(const wchar_t* name,
51 DnsSystemSettings::RegString* out) const { 88 DnsSystemSettings::RegString* out) const {
(...skipping 26 matching lines...) Expand all
78 } 115 }
79 return (result == ERROR_FILE_NOT_FOUND); 116 return (result == ERROR_FILE_NOT_FOUND);
80 } 117 }
81 118
82 private: 119 private:
83 base::win::RegKey key_; 120 base::win::RegKey key_;
84 121
85 DISALLOW_COPY_AND_ASSIGN(RegistryReader); 122 DISALLOW_COPY_AND_ASSIGN(RegistryReader);
86 }; 123 };
87 124
88 // Returns NULL if failed. 125 // Wrapper for GetAdaptersAddresses. Returns NULL if failed.
89 scoped_ptr_malloc<IP_ADAPTER_ADDRESSES> ReadIpHelper(ULONG flags) { 126 scoped_ptr_malloc<IP_ADAPTER_ADDRESSES> ReadIpHelper(ULONG flags) {
90 base::ThreadRestrictions::AssertIOAllowed(); 127 base::ThreadRestrictions::AssertIOAllowed();
91 128
92 scoped_ptr_malloc<IP_ADAPTER_ADDRESSES> out; 129 scoped_ptr_malloc<IP_ADAPTER_ADDRESSES> out;
93 ULONG len = 15000; // As recommended by MSDN for GetAdaptersAddresses. 130 ULONG len = 15000; // As recommended by MSDN for GetAdaptersAddresses.
94 UINT rv = ERROR_BUFFER_OVERFLOW; 131 UINT rv = ERROR_BUFFER_OVERFLOW;
95 // Try up to three times. 132 // Try up to three times.
96 for (unsigned tries = 0; (tries < 3) && (rv == ERROR_BUFFER_OVERFLOW); 133 for (unsigned tries = 0; (tries < 3) && (rv == ERROR_BUFFER_OVERFLOW);
97 tries++) { 134 tries++) {
98 out.reset(reinterpret_cast<PIP_ADAPTER_ADDRESSES>(malloc(len))); 135 out.reset(reinterpret_cast<PIP_ADAPTER_ADDRESSES>(malloc(len)));
(...skipping 26 matching lines...) Expand all
125 162
126 // |punycode_output| should now be ASCII; convert it to a std::string. 163 // |punycode_output| should now be ASCII; convert it to a std::string.
127 // (We could use UTF16ToASCII() instead, but that requires an extra string 164 // (We could use UTF16ToASCII() instead, but that requires an extra string
128 // copy. Since ASCII is a subset of UTF8 the following is equivalent). 165 // copy. Since ASCII is a subset of UTF8 the following is equivalent).
129 bool success = UTF16ToUTF8(punycode.data(), punycode.length(), domain); 166 bool success = UTF16ToUTF8(punycode.data(), punycode.length(), domain);
130 DCHECK(success); 167 DCHECK(success);
131 DCHECK(IsStringASCII(*domain)); 168 DCHECK(IsStringASCII(*domain));
132 return success && !domain->empty(); 169 return success && !domain->empty();
133 } 170 }
134 171
172 bool ReadDevolutionSetting(const RegistryReader& reader,
173 DnsSystemSettings::DevolutionSetting* setting) {
174 return reader.ReadDword(L"UseDomainNameDevolution", &setting->enabled) &&
175 reader.ReadDword(L"DomainNameDevolutionLevel", &setting->level);
176 }
177
178 // Reads DnsSystemSettings from IpHelper and registry.
179 bool ReadSystemSettings(DnsSystemSettings* settings) {
mmenke 2012/06/18 17:19:50 Same suggestion as for the posix version - return
180 settings->addresses = ReadIpHelper(GAA_FLAG_SKIP_ANYCAST |
181 GAA_FLAG_SKIP_UNICAST |
182 GAA_FLAG_SKIP_MULTICAST |
183 GAA_FLAG_SKIP_FRIENDLY_NAME);
184 if (!settings->addresses.get()) {
185 RecordConfigParseResult(CONFIG_PARSE_WIN_READ_IPHELPER);
186 return false;
187 }
188
189 RegistryReader tcpip_reader(kTcpipPath);
190 RegistryReader tcpip6_reader(kTcpip6Path);
191 RegistryReader dnscache_reader(kDnscachePath);
192 RegistryReader policy_reader(kPolicyPath);
193 RegistryReader primary_dns_suffix_reader(kPrimaryDnsSuffixPath);
194
195 if (!policy_reader.ReadString(L"SearchList",
196 &settings->policy_search_list)) {
197 RecordConfigParseResult(CONFIG_PARSE_WIN_READ_POLICY_SEARCHLIST);
198 return false;
199 }
200
201 if (!tcpip_reader.ReadString(L"SearchList", &settings->tcpip_search_list)) {
202 RecordConfigParseResult(CONFIG_PARSE_WIN_READ_TCPIP_SEARCHLIST);
203 return false;
204 }
205
206 if (!tcpip_reader.ReadString(L"Domain", &settings->tcpip_domain)) {
207 RecordConfigParseResult(CONFIG_PARSE_WIN_READ_DOMAIN);
208 return false;
209 }
210
211 if (!ReadDevolutionSetting(policy_reader, &settings->policy_devolution)) {
212 RecordConfigParseResult(CONFIG_PARSE_WIN_READ_POLICY_DEVOLUTION);
213 return false;
214 }
215
216 if (!ReadDevolutionSetting(dnscache_reader,
217 &settings->dnscache_devolution)) {
218 RecordConfigParseResult(CONFIG_PARSE_WIN_READ_DNSCACHE_DEVOLUTION);
219 return false;
220 }
221
222 if (!ReadDevolutionSetting(tcpip_reader, &settings->tcpip_devolution)) {
223 RecordConfigParseResult(CONFIG_PARSE_WIN_READ_TCPIP_DEVOLUTION);
224 return false;
225 }
226
227 if (!policy_reader.ReadDword(L"AppendToMultiLabelName",
228 &settings->append_to_multi_label_name)) {
229 RecordConfigParseResult(CONFIG_PARSE_WIN_READ_APPEND_MULTILABEL);
230 return false;
231 }
232
233 if (!primary_dns_suffix_reader.ReadString(L"PrimaryDnsSuffix",
234 &settings->primary_dns_suffix)) {
235 RecordConfigParseResult(CONFIG_PARSE_WIN_READ_PRIMARY_SUFFIX);
236 return false;
237 }
238 return true;
239 }
240
241 // Default address of "localhost" and local computer name can be overridden
242 // by the HOSTS file, but if it's not there, then we need to fill it in.
243 bool AddLocalhostEntries(DnsHosts* phosts) {
cbentzel 2012/06/16 18:03:41 Nit: We don't tend to use hungarian-style notation
mmenke 2012/06/18 17:19:50 Why not just make the function take in DnsHosts& h
mmenke 2012/06/18 17:19:50 Again, suggest having this return a HostsParseWinR
cbentzel 2012/06/18 18:37:17 Style-guide doesn't allow non-const references. h
mmenke 2012/06/18 18:46:26 Ahh, right, good point. Doing a quick search thro
244 DnsHosts& hosts = *phosts;
245 const unsigned char kIPv4Localhost[] = { 127, 0, 0, 1 };
246 const unsigned char kIPv6Localhost[] = { 0, 0, 0, 0, 0, 0, 0, 0,
247 0, 0, 0, 0, 0, 0, 0, 1 };
248 IPAddressNumber loopback_ipv4(kIPv4Localhost,
249 kIPv4Localhost + arraysize(kIPv4Localhost));
250 IPAddressNumber loopback_ipv6(kIPv6Localhost,
251 kIPv6Localhost + arraysize(kIPv6Localhost));
252
253 // This does not override any pre-existing entries from the HOSTS file.
254 hosts.insert(std::make_pair(DnsHostsKey("localhost", ADDRESS_FAMILY_IPV4),
255 loopback_ipv4));
256 hosts.insert(std::make_pair(DnsHostsKey("localhost", ADDRESS_FAMILY_IPV6),
257 loopback_ipv6));
258
259 WCHAR buffer[MAX_PATH];
260 DWORD size = MAX_PATH;
261 std::string localname;
262 if (!GetComputerNameExW(ComputerNameDnsHostname, buffer, &size) ||
263 !ParseDomainASCII(buffer, &localname)) {
264 LOG(ERROR) << "Failed to read local computer name";
cbentzel 2012/06/16 18:03:41 Do you need the LOG(ERROR) now that we have the hi
265 RecordHostsParseResult(HOSTS_PARSE_WIN_READ_COMPUTER_NAME);
266 return false;
267 }
268 StringToLowerASCII(&localname);
269
270 bool have_ipv4 =
271 hosts.count(DnsHostsKey(localname, ADDRESS_FAMILY_IPV4)) > 0;
272 bool have_ipv6 =
273 hosts.count(DnsHostsKey(localname, ADDRESS_FAMILY_IPV6)) > 0;
274
275 if (have_ipv4 && have_ipv6)
276 return true;
277
278 scoped_ptr_malloc<IP_ADAPTER_ADDRESSES> addresses =
279 ReadIpHelper(GAA_FLAG_SKIP_ANYCAST |
280 GAA_FLAG_SKIP_DNS_SERVER |
281 GAA_FLAG_SKIP_MULTICAST |
282 GAA_FLAG_SKIP_FRIENDLY_NAME);
283 if (!addresses.get()) {
284 RecordHostsParseResult(HOSTS_PARSE_WIN_READ_IPHELPER);
285 return false;
286 }
287
288 // The order of adapters is the network binding order, so stick to the
289 // first good adapter for each family.
290 for (const IP_ADAPTER_ADDRESSES* adapter = addresses.get();
291 adapter != NULL && (!have_ipv4 || !have_ipv6);
292 adapter = adapter->Next) {
293 if (adapter->OperStatus != IfOperStatusUp)
294 continue;
295 if (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK)
296 continue;
297
298 for (const IP_ADAPTER_UNICAST_ADDRESS* address =
299 adapter->FirstUnicastAddress;
300 address != NULL;
301 address = address->Next) {
302 IPEndPoint ipe;
303 if (!ipe.FromSockAddr(address->Address.lpSockaddr,
304 address->Address.iSockaddrLength)) {
305 RecordHostsParseResult(HOSTS_PARSE_WIN_BAD_ADDRESS);
306 return false;
307 }
308 if (!have_ipv4 && (ipe.GetFamily() == AF_INET)) {
309 have_ipv4 = true;
310 hosts[DnsHostsKey(localname, ADDRESS_FAMILY_IPV4)] = ipe.address();
311 } else if (!have_ipv6 && (ipe.GetFamily() == AF_INET6)) {
312 have_ipv6 = true;
313 hosts[DnsHostsKey(localname, ADDRESS_FAMILY_IPV6)] = ipe.address();
314 }
315 }
316 }
317 RecordHostsParseResult(HOSTS_PARSE_WIN_OK);
318 return true;
319 }
320
135 } // namespace 321 } // namespace
136 322
137 FilePath GetHostsPath() { 323 FilePath GetHostsPath() {
138 TCHAR buffer[MAX_PATH]; 324 TCHAR buffer[MAX_PATH];
139 UINT rc = GetSystemDirectory(buffer, MAX_PATH); 325 UINT rc = GetSystemDirectory(buffer, MAX_PATH);
140 DCHECK(0 < rc && rc < MAX_PATH); 326 DCHECK(0 < rc && rc < MAX_PATH);
141 return FilePath(buffer).Append(FILE_PATH_LITERAL("drivers\\etc\\hosts")); 327 return FilePath(buffer).Append(FILE_PATH_LITERAL("drivers\\etc\\hosts"));
142 } 328 }
143 329
144 bool ParseSearchList(const string16& value, std::vector<std::string>* output) { 330 bool ParseSearchList(const string16& value, std::vector<std::string>* output) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 address != NULL; 373 address != NULL;
188 address = address->Next) { 374 address = address->Next) {
189 IPEndPoint ipe; 375 IPEndPoint ipe;
190 if (ipe.FromSockAddr(address->Address.lpSockaddr, 376 if (ipe.FromSockAddr(address->Address.lpSockaddr,
191 address->Address.iSockaddrLength)) { 377 address->Address.iSockaddrLength)) {
192 // Override unset port. 378 // Override unset port.
193 if (!ipe.port()) 379 if (!ipe.port())
194 ipe = IPEndPoint(ipe.address(), dns_protocol::kDefaultPort); 380 ipe = IPEndPoint(ipe.address(), dns_protocol::kDefaultPort);
195 config->nameservers.push_back(ipe); 381 config->nameservers.push_back(ipe);
196 } else { 382 } else {
383 RecordConfigParseResult(CONFIG_PARSE_WIN_BAD_ADDRESS);
197 return false; 384 return false;
198 } 385 }
199 } 386 }
200 387
201 // IP_ADAPTER_ADDRESSES in Vista+ has a search list at |FirstDnsSuffix|, 388 // IP_ADAPTER_ADDRESSES in Vista+ has a search list at |FirstDnsSuffix|,
202 // but it came up empty in all trials. 389 // but it came up empty in all trials.
203 // |DnsSuffix| stores the effective connection-specific suffix, which is 390 // |DnsSuffix| stores the effective connection-specific suffix, which is
204 // obtained via DHCP (regkey: Tcpip\Parameters\Interfaces\{XXX}\DhcpDomain) 391 // obtained via DHCP (regkey: Tcpip\Parameters\Interfaces\{XXX}\DhcpDomain)
205 // or specified by the user (regkey: Tcpip\Parameters\Domain). 392 // or specified by the user (regkey: Tcpip\Parameters\Domain).
206 std::string dns_suffix; 393 std::string dns_suffix;
207 if (ParseDomainASCII(adapter->DnsSuffix, &dns_suffix)) 394 if (ParseDomainASCII(adapter->DnsSuffix, &dns_suffix))
208 config->search.push_back(dns_suffix); 395 config->search.push_back(dns_suffix);
209 } 396 }
210 397
211 if (config->nameservers.empty()) 398 if (config->nameservers.empty()) {
399 RecordConfigParseResult(CONFIG_PARSE_WIN_NO_NAMESERVERS);
212 return false; // No point continuing. 400 return false; // No point continuing.
401 }
213 402
214 // Windows always tries a multi-label name "as is" before using suffixes. 403 // Windows always tries a multi-label name "as is" before using suffixes.
215 config->ndots = 1; 404 config->ndots = 1;
216 405
217 if (!settings.append_to_multi_label_name.set) { 406 if (!settings.append_to_multi_label_name.set) {
218 // The default setting is true for XP, false for Vista+. 407 // The default setting is true for XP, false for Vista+.
219 if (base::win::GetVersion() >= base::win::VERSION_VISTA) { 408 if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
220 config->append_to_multi_label_name = false; 409 config->append_to_multi_label_name = false;
221 } else { 410 } else {
222 config->append_to_multi_label_name = true; 411 config->append_to_multi_label_name = true;
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 // behavior (see also ParseSearchList). If a suffix is not valid, it will be 488 // behavior (see also ParseSearchList). If a suffix is not valid, it will be
300 // discarded when the fully-qualified name is converted to DNS format. 489 // discarded when the fully-qualified name is converted to DNS format.
301 490
302 unsigned num_dots = std::count(primary_suffix.begin(), 491 unsigned num_dots = std::count(primary_suffix.begin(),
303 primary_suffix.end(), '.'); 492 primary_suffix.end(), '.');
304 493
305 for (size_t offset = 0; num_dots >= devolution.level.value; --num_dots) { 494 for (size_t offset = 0; num_dots >= devolution.level.value; --num_dots) {
306 offset = primary_suffix.find('.', offset + 1); 495 offset = primary_suffix.find('.', offset + 1);
307 config->search.push_back(primary_suffix.substr(offset + 1)); 496 config->search.push_back(primary_suffix.substr(offset + 1));
308 } 497 }
309 498 RecordConfigParseResult(CONFIG_PARSE_WIN_OK);
310 return true; 499 return true;
311 } 500 }
312 501
313 // Watches registry for changes and reads config from registry and IP helper. 502 // Reads config from registry and IP helper. All work performed on WorkerPool.
314 // Reading and opening of reg keys is always performed on WorkerPool. Setting
315 // up watches requires IO loop.
316 class DnsConfigServiceWin::ConfigReader : public SerialWorker { 503 class DnsConfigServiceWin::ConfigReader : public SerialWorker {
317 public: 504 public:
318 explicit ConfigReader(DnsConfigServiceWin* service) 505 explicit ConfigReader(DnsConfigServiceWin* service)
319 : service_(service), 506 : service_(service),
320 success_(false) {} 507 success_(false) {}
321 508
322 private: 509 private:
323 bool ReadDevolutionSetting(const RegistryReader& reader, 510 virtual ~ConfigReader() {}
324 DnsSystemSettings::DevolutionSetting& setting) {
325 return reader.ReadDword(L"UseDomainNameDevolution", &setting.enabled) &&
326 reader.ReadDword(L"DomainNameDevolutionLevel", &setting.level);
327 }
328 511
329 virtual void DoWork() OVERRIDE { 512 virtual void DoWork() OVERRIDE {
330 // Should be called on WorkerPool. 513 // Should be called on WorkerPool.
331 success_ = false; 514 base::TimeTicks start_time = base::TimeTicks::Now();
332
333 DnsSystemSettings settings = {}; 515 DnsSystemSettings settings = {};
334 settings.addresses = ReadIpHelper(GAA_FLAG_SKIP_ANYCAST | 516 success_ = ReadSystemSettings(&settings);
335 GAA_FLAG_SKIP_UNICAST | 517 if (success_)
336 GAA_FLAG_SKIP_MULTICAST | 518 success_ = ConvertSettingsToDnsConfig(settings, &dns_config_);
337 GAA_FLAG_SKIP_FRIENDLY_NAME); 519 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.ConfigParseWinResult", success_);
338 if (!settings.addresses.get()) 520 UMA_HISTOGRAM_TIMES("AsyncDNS.ConfigParseDuration",
339 return; // no point reading the rest 521 base::TimeTicks::Now() - start_time);
340
341 RegistryReader tcpip_reader(kTcpipPath);
342 RegistryReader tcpip6_reader(kTcpip6Path);
343 RegistryReader dnscache_reader(kDnscachePath);
344 RegistryReader policy_reader(kPolicyPath);
345 RegistryReader primary_dns_suffix_reader(kPrimaryDnsSuffixPath);
346
347 if (!policy_reader.ReadString(L"SearchList",
348 &settings.policy_search_list))
349 return;
350
351 if (!tcpip_reader.ReadString(L"SearchList", &settings.tcpip_search_list))
352 return;
353
354 if (!tcpip_reader.ReadString(L"Domain", &settings.tcpip_domain))
355 return;
356
357 if (!ReadDevolutionSetting(policy_reader, settings.policy_devolution))
358 return;
359
360 if (!ReadDevolutionSetting(dnscache_reader,
361 settings.dnscache_devolution))
362 return;
363
364 if (!ReadDevolutionSetting(tcpip_reader, settings.tcpip_devolution))
365 return;
366
367 if (!policy_reader.ReadDword(L"AppendToMultiLabelName",
368 &settings.append_to_multi_label_name))
369 return;
370
371 if (!primary_dns_suffix_reader.ReadString(L"PrimaryDnsSuffix",
372 &settings.primary_dns_suffix))
373 return;
374
375 success_ = ConvertSettingsToDnsConfig(settings, &dns_config_);
376 } 522 }
377 523
378 virtual void OnWorkFinished() OVERRIDE { 524 virtual void OnWorkFinished() OVERRIDE {
379 DCHECK(loop()->BelongsToCurrentThread()); 525 DCHECK(loop()->BelongsToCurrentThread());
380 DCHECK(!IsCancelled()); 526 DCHECK(!IsCancelled());
381 if (success_) { 527 if (success_) {
382 service_->OnConfigRead(dns_config_); 528 service_->OnConfigRead(dns_config_);
383 } else { 529 } else {
384 LOG(WARNING) << "Failed to read DnsConfig."; 530 LOG(WARNING) << "Failed to read DnsConfig.";
385 } 531 }
386 } 532 }
387 533
388 DnsConfigServiceWin* service_; 534 DnsConfigServiceWin* service_;
389 // Written in DoRead(), read in OnReadFinished(). No locking required. 535 // Written in DoRead(), read in OnReadFinished(). No locking required.
390 DnsConfig dns_config_; 536 DnsConfig dns_config_;
391 bool success_; 537 bool success_;
392 }; 538 };
393 539
394 // An extension for DnsHostsReader which also watches the HOSTS file, 540 // An extension for DnsHostsReader which also watches the HOSTS file,
395 // reads local name from GetComputerNameEx, local IP from GetAdaptersAddresses, 541 // reads local name from GetComputerNameEx, local IP from GetAdaptersAddresses,
396 // and observes changes to local IP address. 542 // and observes changes to local IP address.
397 class DnsConfigServiceWin::HostsReader : public SerialWorker { 543 class DnsConfigServiceWin::HostsReader : public SerialWorker {
398 public: 544 public:
399 explicit HostsReader(DnsConfigServiceWin* service) 545 explicit HostsReader(DnsConfigServiceWin* service)
400 : path_(GetHostsPath()), service_(service) { 546 : path_(GetHostsPath()), service_(service) {
401 } 547 }
402 548
403 private: 549 private:
550 virtual ~HostsReader() {}
551
404 virtual void DoWork() OVERRIDE { 552 virtual void DoWork() OVERRIDE {
553 base::TimeTicks start_time = base::TimeTicks::Now();
405 success_ = ParseHostsFile(path_, &hosts_); 554 success_ = ParseHostsFile(path_, &hosts_);
406 555 if (success_) {
407 if (!success_) 556 success_ = AddLocalhostEntries(&hosts_);
408 return; 557 } else {
409 558 RecordHostsParseResult(HOSTS_PARSE_WIN_READ_HOSTS);
410 success_ = false;
411
412 // Default address of "localhost" and local computer name can be overridden
413 // by the HOSTS file, but if it's not there, then we need to fill it in.
414
415 const unsigned char kIPv4Localhost[] = { 127, 0, 0, 1 };
416 const unsigned char kIPv6Localhost[] = { 0, 0, 0, 0, 0, 0, 0, 0,
417 0, 0, 0, 0, 0, 0, 0, 1 };
418 IPAddressNumber loopback_ipv4(kIPv4Localhost,
419 kIPv4Localhost + arraysize(kIPv4Localhost));
420 IPAddressNumber loopback_ipv6(kIPv6Localhost,
421 kIPv6Localhost + arraysize(kIPv6Localhost));
422
423 // This does not override any pre-existing entries from the HOSTS file.
424 hosts_.insert(std::make_pair(DnsHostsKey("localhost", ADDRESS_FAMILY_IPV4),
425 loopback_ipv4));
426 hosts_.insert(std::make_pair(DnsHostsKey("localhost", ADDRESS_FAMILY_IPV6),
427 loopback_ipv6));
428
429 WCHAR buffer[MAX_PATH];
430 DWORD size = MAX_PATH;
431 std::string localname;
432 if (!GetComputerNameExW(ComputerNameDnsHostname, buffer, &size) ||
433 !ParseDomainASCII(buffer, &localname)) {
434 LOG(ERROR) << "Failed to read local computer name";
435 return;
436 } 559 }
437 StringToLowerASCII(&localname); 560 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.HostParseResult", success_);
438 561 UMA_HISTOGRAM_TIMES("AsyncDNS.HostsParseDuration",
439 bool have_ipv4 = 562 base::TimeTicks::Now() - start_time);
440 hosts_.count(DnsHostsKey(localname, ADDRESS_FAMILY_IPV4)) > 0;
441 bool have_ipv6 =
442 hosts_.count(DnsHostsKey(localname, ADDRESS_FAMILY_IPV6)) > 0;
443
444 if (have_ipv4 && have_ipv6) {
445 success_ = true;
446 return;
447 }
448
449 scoped_ptr_malloc<IP_ADAPTER_ADDRESSES> addresses =
450 ReadIpHelper(GAA_FLAG_SKIP_ANYCAST |
451 GAA_FLAG_SKIP_DNS_SERVER |
452 GAA_FLAG_SKIP_MULTICAST |
453 GAA_FLAG_SKIP_FRIENDLY_NAME);
454 if (!addresses.get())
455 return;
456
457 // The order of adapters is the network binding order, so stick to the
458 // first good adapter for each family.
459 for (const IP_ADAPTER_ADDRESSES* adapter = addresses.get();
460 adapter != NULL && (!have_ipv4 || !have_ipv6);
461 adapter = adapter->Next) {
462 if (adapter->OperStatus != IfOperStatusUp)
463 continue;
464 if (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK)
465 continue;
466
467 for (const IP_ADAPTER_UNICAST_ADDRESS* address =
468 adapter->FirstUnicastAddress;
469 address != NULL;
470 address = address->Next) {
471 IPEndPoint ipe;
472 if (!ipe.FromSockAddr(address->Address.lpSockaddr,
473 address->Address.iSockaddrLength)) {
474 return;
475 }
476 if (!have_ipv4 && (ipe.GetFamily() == AF_INET)) {
477 have_ipv4 = true;
478 hosts_[DnsHostsKey(localname, ADDRESS_FAMILY_IPV4)] = ipe.address();
479 } else if (!have_ipv6 && (ipe.GetFamily() == AF_INET6)) {
480 have_ipv6 = true;
481 hosts_[DnsHostsKey(localname, ADDRESS_FAMILY_IPV6)] = ipe.address();
482 }
483 }
484 }
485 success_ = true;
486 } 563 }
487 564
488 virtual void OnWorkFinished() OVERRIDE { 565 virtual void OnWorkFinished() OVERRIDE {
489 DCHECK(loop()->BelongsToCurrentThread()); 566 DCHECK(loop()->BelongsToCurrentThread());
490 if (success_) { 567 if (success_) {
491 service_->OnHostsRead(hosts_); 568 service_->OnHostsRead(hosts_);
492 } else { 569 } else {
493 LOG(WARNING) << "Failed to read DnsHosts."; 570 LOG(WARNING) << "Failed to read DnsHosts.";
494 } 571 }
495 } 572 }
496 573
497 const FilePath path_; 574 const FilePath path_;
498 DnsConfigServiceWin* service_; 575 DnsConfigServiceWin* service_;
499 // Written in DoWork, read in OnWorkFinished, no locking necessary. 576 // Written in DoWork, read in OnWorkFinished, no locking necessary.
500 DnsHosts hosts_; 577 DnsHosts hosts_;
501 bool success_; 578 bool success_;
502 579
503 DISALLOW_COPY_AND_ASSIGN(HostsReader); 580 DISALLOW_COPY_AND_ASSIGN(HostsReader);
504 }; 581 };
505 582
506 DnsConfigServiceWin::DnsConfigServiceWin() 583 DnsConfigServiceWin::DnsConfigServiceWin()
507 : config_reader_(new ConfigReader(this)), 584 : config_reader_(new ConfigReader(this)),
508 hosts_reader_(new HostsReader(this)) {} 585 hosts_reader_(new HostsReader(this)) {}
509 586
510 DnsConfigServiceWin::~DnsConfigServiceWin() { 587 DnsConfigServiceWin::~DnsConfigServiceWin() {
511 DCHECK(CalledOnValidThread());
512 config_reader_->Cancel(); 588 config_reader_->Cancel();
513 hosts_reader_->Cancel(); 589 hosts_reader_->Cancel();
514 NetworkChangeNotifier::RemoveIPAddressObserver(this); 590 NetworkChangeNotifier::RemoveIPAddressObserver(this);
515 } 591 }
516 592
517 void DnsConfigServiceWin::Watch(const CallbackType& callback) { 593 void DnsConfigServiceWin::Watch(const CallbackType& callback) {
518 DnsConfigService::Watch(callback); 594 DnsConfigService::Watch(callback);
519 // Also need to observe changes to local non-loopback IP for DnsHosts. 595 // Also need to observe changes to local non-loopback IP for DnsHosts.
520 NetworkChangeNotifier::AddIPAddressObserver(this); 596 NetworkChangeNotifier::AddIPAddressObserver(this);
521 } 597 }
(...skipping 27 matching lines...) Expand all
549 625
550 } // namespace internal 626 } // namespace internal
551 627
552 // static 628 // static
553 scoped_ptr<DnsConfigService> DnsConfigService::CreateSystemService() { 629 scoped_ptr<DnsConfigService> DnsConfigService::CreateSystemService() {
554 return scoped_ptr<DnsConfigService>(new internal::DnsConfigServiceWin()); 630 return scoped_ptr<DnsConfigService>(new internal::DnsConfigServiceWin());
555 } 631 }
556 632
557 } // namespace net 633 } // namespace net
558 634
OLDNEW
« net/dns/dns_config_service_posix_unittest.cc ('K') | « net/dns/dns_config_service_unittest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698