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

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

Issue 9721002: [net/dns] Removes locking from DnsConfigServiceWin and adds local computer name. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Move lowercasing to ServeFromHosts, add test. Reorganize OnHostsRead. Created 8 years, 9 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
« no previous file with comments | « net/dns/dns_config_service_win.h ('k') | net/dns/dns_hosts.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/string_split.h" 16 #include "base/string_split.h"
17 #include "base/string_util.h" 17 #include "base/string_util.h"
18 #include "base/synchronization/lock.h" 18 #include "base/synchronization/lock.h"
19 #include "base/threading/non_thread_safe.h"
19 #include "base/threading/thread_restrictions.h" 20 #include "base/threading/thread_restrictions.h"
20 #include "base/utf_string_conversions.h" 21 #include "base/utf_string_conversions.h"
21 #include "base/win/object_watcher.h" 22 #include "base/win/object_watcher.h"
22 #include "base/win/registry.h" 23 #include "base/win/registry.h"
23 #include "base/win/windows_version.h" 24 #include "base/win/windows_version.h"
24 #include "googleurl/src/url_canon.h" 25 #include "googleurl/src/url_canon.h"
25 #include "net/base/net_util.h" 26 #include "net/base/net_util.h"
27 #include "net/base/network_change_notifier.h"
26 #include "net/dns/dns_protocol.h" 28 #include "net/dns/dns_protocol.h"
27 #include "net/dns/file_path_watcher_wrapper.h" 29 #include "net/dns/file_path_watcher_wrapper.h"
28 #include "net/dns/serial_worker.h" 30 #include "net/dns/serial_worker.h"
29 31
30 #pragma comment(lib, "iphlpapi.lib") 32 #pragma comment(lib, "iphlpapi.lib")
31 33
32 namespace net { 34 namespace net {
33 35
34 namespace internal { 36 namespace internal {
35 37
36 namespace { 38 namespace {
37 39
38 // Watches a single registry key for changes. Thread-safe. 40 // Registry key paths.
39 class RegistryWatcher : public base::win::ObjectWatcher::Delegate { 41 const wchar_t* const kTcpipPath =
42 L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters";
43 const wchar_t* const kTcpip6Path =
44 L"SYSTEM\\CurrentControlSet\\Services\\Tcpip6\\Parameters";
45 const wchar_t* const kDnscachePath =
46 L"SYSTEM\\CurrentControlSet\\Services\\Dnscache\\Parameters";
47 const wchar_t* const kPolicyPath =
48 L"SOFTWARE\\Policies\\Microsoft\\Windows NT\\DNSClient";
49
50 // Convenience for reading values using RegKey.
51 class RegistryReader : public base::NonThreadSafe {
40 public: 52 public:
41 typedef base::Callback<void(bool succeeded)> CallbackType; 53 explicit RegistryReader(const wchar_t* key) {
42 RegistryWatcher() {} 54 // Ignoring the result. |key_.Valid()| will catch failures.
43 55 key_.Open(HKEY_LOCAL_MACHINE, key, KEY_QUERY_VALUE);
44 bool Watch(const wchar_t* key, const CallbackType& callback) {
45 base::AutoLock lock(lock_);
46 DCHECK(!callback.is_null());
47 CancelLocked();
48 if (key_.Open(HKEY_LOCAL_MACHINE, key,
49 KEY_NOTIFY | KEY_QUERY_VALUE) != ERROR_SUCCESS)
50 return false;
51 if (key_.StartWatching() != ERROR_SUCCESS)
52 return false;
53 if (!watcher_.StartWatching(key_.watch_event(), this))
54 return false;
55 callback_ = callback;
56 return true;
57 }
58
59 void Cancel() {
60 base::AutoLock lock(lock_);
61 CancelLocked();
62 }
63
64 virtual void OnObjectSignaled(HANDLE object) OVERRIDE {
65 base::AutoLock lock(lock_);
66 bool succeeded = (key_.StartWatching() == ERROR_SUCCESS) &&
67 watcher_.StartWatching(key_.watch_event(), this);
68 if (!callback_.is_null())
69 callback_.Run(succeeded);
70 } 56 }
71 57
72 bool ReadString(const wchar_t* name, 58 bool ReadString(const wchar_t* name,
73 DnsSystemSettings::RegString* out) const { 59 DnsSystemSettings::RegString* out) const {
74 base::AutoLock lock(lock_); 60 DCHECK(CalledOnValidThread());
75 out->set = false; 61 out->set = false;
76 if (!key_.Valid()) { 62 if (!key_.Valid()) {
77 // Assume that if the |key_| is invalid then the key is missing. 63 // Assume that if the |key_| is invalid then the key is missing.
78 return true; 64 return true;
79 } 65 }
80 LONG result = key_.ReadValue(name, &out->value); 66 LONG result = key_.ReadValue(name, &out->value);
81 if (result == ERROR_SUCCESS) { 67 if (result == ERROR_SUCCESS) {
82 out->set = true; 68 out->set = true;
83 return true; 69 return true;
84 } 70 }
85 return (result == ERROR_FILE_NOT_FOUND); 71 return (result == ERROR_FILE_NOT_FOUND);
86 } 72 }
87 73
88 bool ReadDword(const wchar_t* name, 74 bool ReadDword(const wchar_t* name,
89 DnsSystemSettings::RegDword* out) const { 75 DnsSystemSettings::RegDword* out) const {
90 base::AutoLock lock(lock_); 76 DCHECK(CalledOnValidThread());
91 out->set = false; 77 out->set = false;
92 if (!key_.Valid()) { 78 if (!key_.Valid()) {
93 // Assume that if the |key_| is invalid then the key is missing. 79 // Assume that if the |key_| is invalid then the key is missing.
94 return true; 80 return true;
95 } 81 }
96 LONG result = key_.ReadValueDW(name, &out->value); 82 LONG result = key_.ReadValueDW(name, &out->value);
97 if (result == ERROR_SUCCESS) { 83 if (result == ERROR_SUCCESS) {
98 out->set = true; 84 out->set = true;
99 return true; 85 return true;
100 } 86 }
101 return (result == ERROR_FILE_NOT_FOUND); 87 return (result == ERROR_FILE_NOT_FOUND);
102 } 88 }
103 89
104 private: 90 private:
105 void CancelLocked() { 91 base::win::RegKey key_;
106 lock_.AssertAcquired(); 92
93 DISALLOW_COPY_AND_ASSIGN(RegistryReader);
94 };
95
96
97 // Watches a single registry key for changes.
98 class RegistryWatcher : public base::win::ObjectWatcher::Delegate,
99 public base::NonThreadSafe {
100 public:
101 typedef base::Callback<void(bool succeeded)> CallbackType;
102 RegistryWatcher() {}
103
104 bool Watch(const wchar_t* key, const CallbackType& callback) {
105 DCHECK(CalledOnValidThread());
106 DCHECK(!callback.is_null());
107 Cancel();
108 if (key_.Open(HKEY_LOCAL_MACHINE, key, KEY_NOTIFY) != ERROR_SUCCESS)
109 return false;
110 if (key_.StartWatching() != ERROR_SUCCESS)
111 return false;
112 if (!watcher_.StartWatching(key_.watch_event(), this))
113 return false;
114 callback_ = callback;
115 return true;
116 }
117
118 bool IsWatching() const {
119 DCHECK(CalledOnValidThread());
120 return !callback_.is_null();
121 }
122
123 void Cancel() {
124 DCHECK(CalledOnValidThread());
107 callback_.Reset(); 125 callback_.Reset();
108 if (key_.Valid()) { 126 if (key_.Valid()) {
109 watcher_.StopWatching(); 127 watcher_.StopWatching();
110 key_.StopWatching(); 128 key_.StopWatching();
129 key_.Close();
111 } 130 }
112 } 131 }
113 132
114 mutable base::Lock lock_; 133 virtual void OnObjectSignaled(HANDLE object) OVERRIDE {
134 DCHECK(CalledOnValidThread());
135 bool succeeded = (key_.StartWatching() == ERROR_SUCCESS) &&
136 watcher_.StartWatching(key_.watch_event(), this);
137 CallbackType callback = callback_;
138 if (!succeeded)
139 Cancel();
140 if (!callback.is_null())
141 callback.Run(succeeded);
142 }
143
144 private:
115 CallbackType callback_; 145 CallbackType callback_;
116 base::win::RegKey key_; 146 base::win::RegKey key_;
117 base::win::ObjectWatcher watcher_; 147 base::win::ObjectWatcher watcher_;
118 148
119 DISALLOW_COPY_AND_ASSIGN(RegistryWatcher); 149 DISALLOW_COPY_AND_ASSIGN(RegistryWatcher);
120 }; 150 };
121 151
152 // Returns NULL if failed.
153 scoped_ptr_malloc<IP_ADAPTER_ADDRESSES> ReadIpHelper(ULONG flags) {
154 base::ThreadRestrictions::AssertIOAllowed();
155
156 scoped_ptr_malloc<IP_ADAPTER_ADDRESSES> out;
157 ULONG len = 15000; // As recommended by MSDN for GetAdaptersAddresses.
158 UINT rv = ERROR_BUFFER_OVERFLOW;
159 // Try up to three times.
160 for (unsigned tries = 0; (tries < 3) && (rv == ERROR_BUFFER_OVERFLOW);
161 tries++) {
162 out.reset(reinterpret_cast<PIP_ADAPTER_ADDRESSES>(malloc(len)));
163 rv = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, out.get(), &len);
164 }
165 if (rv != NO_ERROR)
166 out.reset();
167 return out.Pass();
168 }
169
122 // Converts a string16 domain name to ASCII, possibly using punycode. 170 // Converts a string16 domain name to ASCII, possibly using punycode.
123 // Returns true if the conversion succeeds and output is not empty. In case of 171 // Returns true if the conversion succeeds and output is not empty. In case of
124 // failure, |domain| might become dirty. 172 // failure, |domain| might become dirty.
125 bool ParseDomainASCII(const string16& widestr, std::string* domain) { 173 bool ParseDomainASCII(const string16& widestr, std::string* domain) {
126 DCHECK(domain); 174 DCHECK(domain);
127 if (widestr.empty()) 175 if (widestr.empty())
128 return false; 176 return false;
129 177
130 // Check if already ASCII. 178 // Check if already ASCII.
131 if (IsStringASCII(widestr)) { 179 if (IsStringASCII(widestr)) {
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 : service_(service), 364 : service_(service),
317 success_(false) {} 365 success_(false) {}
318 366
319 bool Watch() { 367 bool Watch() {
320 DCHECK(loop()->BelongsToCurrentThread()); 368 DCHECK(loop()->BelongsToCurrentThread());
321 369
322 RegistryWatcher::CallbackType callback = 370 RegistryWatcher::CallbackType callback =
323 base::Bind(&ConfigReader::OnChange, base::Unretained(this)); 371 base::Bind(&ConfigReader::OnChange, base::Unretained(this));
324 372
325 // The Tcpip key must be present. 373 // The Tcpip key must be present.
326 if (!tcpip_watcher_.Watch( 374 if (!tcpip_watcher_.Watch(kTcpipPath, callback))
327 L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
328 callback))
329 return false; 375 return false;
330 376
331 // Watch for IPv6 nameservers. 377 // Watch for IPv6 nameservers.
332 tcpip6_watcher_.Watch( 378 tcpip6_watcher_.Watch(kTcpip6Path, callback);
333 L"SYSTEM\\CurrentControlSet\\Services\\Tcpip6\\Parameters",
334 callback);
335 379
336 // DNS suffix search list and devolution can be configured via group 380 // DNS suffix search list and devolution can be configured via group
337 // policy which sets this registry key. If the key is missing, the policy 381 // policy which sets this registry key. If the key is missing, the policy
338 // does not apply, and the DNS client uses Tcpip and Dnscache settings. 382 // does not apply, and the DNS client uses Tcpip and Dnscache settings.
339 // If a policy is installed, DnsConfigService will need to be restarted. 383 // If a policy is installed, DnsConfigService will need to be restarted.
340 // BUG=99509 384 // BUG=99509
341 385
342 dnscache_watcher_.Watch( 386 dnscache_watcher_.Watch(kDnscachePath, callback);
343 L"SYSTEM\\CurrentControlSet\\Services\\Dnscache\\Parameters", 387 policy_watcher_.Watch(kPolicyPath, callback);
344 callback);
345
346 policy_watcher_.Watch(
347 L"SOFTWARE\\Policies\\Microsoft\\Windows NT\\DNSClient",
348 callback);
349 388
350 WorkNow(); 389 WorkNow();
351 return true; 390 return true;
352 } 391 }
353 392
354 void Cancel() { 393 void Cancel() {
355 DCHECK(loop()->BelongsToCurrentThread()); 394 DCHECK(loop()->BelongsToCurrentThread());
356 SerialWorker::Cancel(); 395 SerialWorker::Cancel();
357 policy_watcher_.Cancel(); 396 policy_watcher_.Cancel();
358 dnscache_watcher_.Cancel(); 397 dnscache_watcher_.Cancel();
(...skipping 11 matching lines...) Expand all
370 if (!IsCancelled()) 409 if (!IsCancelled())
371 service_->InvalidateConfig(); 410 service_->InvalidateConfig();
372 // We don't trust a config that we cannot watch in the future. 411 // We don't trust a config that we cannot watch in the future.
373 // TODO(szym): re-start watcher if that makes sense. http://crbug.com/116139 412 // TODO(szym): re-start watcher if that makes sense. http://crbug.com/116139
374 if (succeeded) 413 if (succeeded)
375 WorkNow(); 414 WorkNow();
376 else 415 else
377 LOG(ERROR) << "Failed to watch DNS config"; 416 LOG(ERROR) << "Failed to watch DNS config";
378 } 417 }
379 418
380 bool ReadIpHelper(DnsSystemSettings* settings) { 419 bool ReadDevolutionSetting(const RegistryReader& reader,
381 base::ThreadRestrictions::AssertIOAllowed();
382
383 ULONG flags = GAA_FLAG_SKIP_ANYCAST |
384 GAA_FLAG_SKIP_UNICAST |
385 GAA_FLAG_SKIP_MULTICAST |
386 GAA_FLAG_SKIP_FRIENDLY_NAME;
387 ULONG len = 15000; // As recommended by MSDN for GetAdaptersAddresses.
388 UINT rv = ERROR_BUFFER_OVERFLOW;
389 // Try up to three times.
390 for (unsigned tries = 0;
391 (tries < 3) && (rv == ERROR_BUFFER_OVERFLOW);
392 tries++) {
393 settings->addresses.reset(
394 reinterpret_cast<PIP_ADAPTER_ADDRESSES>(malloc(len)));
395 rv = GetAdaptersAddresses(AF_UNSPEC, flags, NULL,
396 settings->addresses.get(), &len);
397 }
398 return (rv == NO_ERROR);
399 }
400
401 bool ReadDevolutionSetting(const RegistryWatcher& watcher,
402 DnsSystemSettings::DevolutionSetting& setting) { 420 DnsSystemSettings::DevolutionSetting& setting) {
403 return watcher.ReadDword(L"UseDomainNameDevolution", &setting.enabled) && 421 return reader.ReadDword(L"UseDomainNameDevolution", &setting.enabled) &&
404 watcher.ReadDword(L"DomainNameDevolutionLevel", &setting.level); 422 reader.ReadDword(L"DomainNameDevolutionLevel", &setting.level);
405 } 423 }
406 424
407 virtual void DoWork() OVERRIDE { 425 virtual void DoWork() OVERRIDE {
408 // Should be called on WorkerPool. 426 // Should be called on WorkerPool.
409 success_ = false; 427 success_ = false;
410 428
411 DnsSystemSettings settings; 429 DnsSystemSettings settings;
412 memset(&settings, 0, sizeof(settings)); 430 memset(&settings, 0, sizeof(settings));
413 if (!ReadIpHelper(&settings)) 431 settings.addresses = ReadIpHelper(GAA_FLAG_SKIP_ANYCAST |
432 GAA_FLAG_SKIP_UNICAST |
433 GAA_FLAG_SKIP_MULTICAST |
434 GAA_FLAG_SKIP_FRIENDLY_NAME);
435 if (!settings.addresses.get())
414 return; // no point reading the rest 436 return; // no point reading the rest
415 437
416 if (!policy_watcher_.ReadString(L"SearchList", 438 RegistryReader tcpip_reader(kTcpipPath);
417 &settings.policy_search_list)) 439 RegistryReader tcpip6_reader(kTcpip6Path);
440 RegistryReader dnscache_reader(kDnscachePath);
441 RegistryReader policy_reader(kPolicyPath);
442
443 if (!policy_reader.ReadString(L"SearchList",
444 &settings.policy_search_list))
418 return; 445 return;
419 446
420 if (!tcpip_watcher_.ReadString(L"SearchList", &settings.tcpip_search_list)) 447 if (!tcpip_reader.ReadString(L"SearchList", &settings.tcpip_search_list))
421 return; 448 return;
422 449
423 if (!tcpip_watcher_.ReadString(L"Domain", &settings.tcpip_domain)) 450 if (!tcpip_reader.ReadString(L"Domain", &settings.tcpip_domain))
424 return; 451 return;
425 452
426 if (!ReadDevolutionSetting(policy_watcher_, settings.policy_devolution)) 453 if (!ReadDevolutionSetting(policy_reader, settings.policy_devolution))
427 return; 454 return;
428 455
429 if (!ReadDevolutionSetting(dnscache_watcher_, 456 if (!ReadDevolutionSetting(dnscache_reader,
430 settings.dnscache_devolution)) 457 settings.dnscache_devolution))
431 return; 458 return;
432 459
433 if (!ReadDevolutionSetting(tcpip_watcher_, settings.tcpip_devolution)) 460 if (!ReadDevolutionSetting(tcpip_reader, settings.tcpip_devolution))
434 return; 461 return;
435 462
436 if (!policy_watcher_.ReadDword(L"AppendToMultiLabelName", 463 if (!policy_reader.ReadDword(L"AppendToMultiLabelName",
437 &settings.append_to_multi_label_name)) 464 &settings.append_to_multi_label_name))
438 return; 465 return;
439 466
440 success_ = ConvertSettingsToDnsConfig(settings, &dns_config_); 467 success_ = ConvertSettingsToDnsConfig(settings, &dns_config_);
441 } 468 }
442 469
443 virtual void OnWorkFinished() OVERRIDE { 470 virtual void OnWorkFinished() OVERRIDE {
444 DCHECK(loop()->BelongsToCurrentThread()); 471 DCHECK(loop()->BelongsToCurrentThread());
445 DCHECK(!IsCancelled()); 472 DCHECK(!IsCancelled());
446 if (success_) { 473 if (success_) {
447 service_->OnConfigRead(dns_config_); 474 service_->OnConfigRead(dns_config_);
448 } else { 475 } else {
449 LOG(WARNING) << "Failed to read config."; 476 LOG(WARNING) << "Failed to read config.";
450 } 477 }
451 } 478 }
452 479
453 DnsConfigServiceWin* service_; 480 DnsConfigServiceWin* service_;
454 // Written in DoRead(), read in OnReadFinished(). No locking required. 481 // Written in DoRead(), read in OnReadFinished(). No locking required.
455 DnsConfig dns_config_; 482 DnsConfig dns_config_;
456 bool success_; 483 bool success_;
457 484
458 RegistryWatcher tcpip_watcher_; 485 RegistryWatcher tcpip_watcher_;
459 RegistryWatcher tcpip6_watcher_; 486 RegistryWatcher tcpip6_watcher_;
460 RegistryWatcher dnscache_watcher_; 487 RegistryWatcher dnscache_watcher_;
461 RegistryWatcher policy_watcher_; 488 RegistryWatcher policy_watcher_;
462 }; 489 };
463 490
491 FilePath GetHostsPath() {
492 TCHAR buffer[MAX_PATH];
493 UINT rc = GetSystemDirectory(buffer, MAX_PATH);
494 DCHECK(0 < rc && rc < MAX_PATH);
495 return FilePath(buffer).Append(FILE_PATH_LITERAL("drivers\\etc\\hosts"));
496 }
497
498 // An extension for DnsHostsReader which also watches the HOSTS file,
499 // reads local name from GetComputerNameEx, local IP from GetAdaptersAddresses,
500 // and observes changes to local IP address.
501 class DnsConfigServiceWin::HostsReader
502 : public DnsHostsReader,
503 public NetworkChangeNotifier::IPAddressObserver {
504 public:
505 explicit HostsReader(DnsConfigServiceWin* service)
506 : DnsHostsReader(GetHostsPath()), service_(service) {
507 }
508
509 bool Watch() {
510 DCHECK(loop()->BelongsToCurrentThread());
511 DCHECK(!IsCancelled());
512
513 // In case the reader is restarted, remove it from the observer list.
514 NetworkChangeNotifier::RemoveIPAddressObserver(this);
515
516 if (!hosts_watcher_.Watch(path(),
517 base::Bind(&HostsReader::OnHostsChanged,
518 base::Unretained(this)))) {
519 return false;
520 }
521 NetworkChangeNotifier::AddIPAddressObserver(this);
522 WorkNow();
523 return true;
524 }
525
526 // Cancels the underlying SerialWorker. Cannot be undone.
527 void Cancel() {
528 DnsHostsReader::Cancel();
529 hosts_watcher_.Cancel();
530 NetworkChangeNotifier::RemoveIPAddressObserver(this);
531 }
532
533 private:
534 virtual void OnIPAddressChanged() OVERRIDE {
535 DCHECK(loop()->BelongsToCurrentThread());
536 service_->InvalidateHosts();
537 if (!hosts_watcher_.IsWatching())
538 return;
539 WorkNow();
540 }
541
542 void OnHostsChanged(bool succeeded) {
543 DCHECK(loop()->BelongsToCurrentThread());
544 service_->InvalidateHosts();
545 if (succeeded)
546 WorkNow();
547 else
548 LOG(ERROR) << "Failed to watch DNS hosts";
549 }
550
551 virtual void DoWork() OVERRIDE {
552 DnsHostsReader::DoWork();
553
554 if (!success_)
555 return;
556
557 success_ = false;
558
559 // Default address of "localhost" and local computer name can be overridden
560 // by the HOSTS file, but if it's not there, then we need to fill it in.
561
562 const unsigned char kIPv4Localhost[] = { 127, 0, 0, 1 };
563 const unsigned char kIPv6Localhost[] = { 0, 0, 0, 0, 0, 0, 0, 0,
564 0, 0, 0, 0, 0, 0, 0, 1 };
565 IPAddressNumber loopback_ipv4(kIPv4Localhost,
566 kIPv4Localhost + arraysize(kIPv4Localhost));
567 IPAddressNumber loopback_ipv6(kIPv6Localhost,
568 kIPv6Localhost + arraysize(kIPv6Localhost));
569
570 // This does not override any pre-existing entries from the HOSTS file.
571 dns_hosts_.insert(
572 std::make_pair(DnsHostsKey("localhost", ADDRESS_FAMILY_IPV4),
573 loopback_ipv4));
574 dns_hosts_.insert(
575 std::make_pair(DnsHostsKey("localhost", ADDRESS_FAMILY_IPV6),
576 loopback_ipv6));
577
578 WCHAR buffer[MAX_PATH];
579 DWORD size = MAX_PATH;
580 std::string localname;
581 if (!GetComputerNameExW(ComputerNameDnsHostname, buffer, &size) ||
582 !ParseDomainASCII(buffer, &localname)) {
583 LOG(ERROR) << "Failed to read local computer name";
584 return;
585 }
586 StringToLowerASCII(&localname);
587
588 bool have_ipv4 =
589 dns_hosts_.count(DnsHostsKey(localname, ADDRESS_FAMILY_IPV4)) > 0;
590 bool have_ipv6 =
591 dns_hosts_.count(DnsHostsKey(localname, ADDRESS_FAMILY_IPV6)) > 0;
592
593 if (have_ipv4 && have_ipv6) {
594 success_ = true;
595 return;
596 }
597
598 scoped_ptr_malloc<IP_ADAPTER_ADDRESSES> addresses =
599 ReadIpHelper(GAA_FLAG_SKIP_ANYCAST |
600 GAA_FLAG_SKIP_DNS_SERVER |
601 GAA_FLAG_SKIP_MULTICAST |
602 GAA_FLAG_SKIP_FRIENDLY_NAME);
603 if (!addresses.get())
604 return;
605
606 // The order of adapters is the network binding order, so stick to the
607 // first good adapter for each family.
608 for (const IP_ADAPTER_ADDRESSES* adapter = addresses.get();
609 adapter != NULL && (!have_ipv4 || !have_ipv6);
610 adapter = adapter->Next) {
611 if (adapter->OperStatus != IfOperStatusUp)
612 continue;
613 if (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK)
614 continue;
615
616 for (const IP_ADAPTER_UNICAST_ADDRESS* address =
617 adapter->FirstUnicastAddress;
618 address != NULL;
619 address = address->Next) {
620 IPEndPoint ipe;
621 if (!ipe.FromSockAddr(address->Address.lpSockaddr,
622 address->Address.iSockaddrLength)) {
623 return;
624 }
625 if (!have_ipv4 && (ipe.GetFamily() == AF_INET)) {
626 have_ipv4 = true;
627 dns_hosts_[DnsHostsKey(localname, ADDRESS_FAMILY_IPV4)] =
628 ipe.address();
629 } else if (!have_ipv6 && (ipe.GetFamily() == AF_INET6)) {
630 have_ipv6 = true;
631 dns_hosts_[DnsHostsKey(localname, ADDRESS_FAMILY_IPV6)] =
632 ipe.address();
633 }
634 }
635 }
636
637 success_ = true;
638 }
639
640 virtual void OnWorkFinished() OVERRIDE {
641 DCHECK(loop()->BelongsToCurrentThread());
642 if (!success_ || !hosts_watcher_.IsWatching())
643 return;
644 service_->OnHostsRead(dns_hosts_);
645 }
646
647 DnsConfigServiceWin* service_;
648 FilePathWatcherWrapper hosts_watcher_;
649
650 DISALLOW_COPY_AND_ASSIGN(HostsReader);
651 };
652
653
464 DnsConfigServiceWin::DnsConfigServiceWin() 654 DnsConfigServiceWin::DnsConfigServiceWin()
465 : config_reader_(new ConfigReader(this)), 655 : config_reader_(new ConfigReader(this)),
466 hosts_watcher_(new FilePathWatcherWrapper()) {} 656 hosts_reader_(new HostsReader(this)) {}
467 657
468 DnsConfigServiceWin::~DnsConfigServiceWin() { 658 DnsConfigServiceWin::~DnsConfigServiceWin() {
469 DCHECK(CalledOnValidThread()); 659 DCHECK(CalledOnValidThread());
470 config_reader_->Cancel(); 660 config_reader_->Cancel();
471 if (hosts_reader_) 661 hosts_reader_->Cancel();
472 hosts_reader_->Cancel();
473 } 662 }
474 663
475 void DnsConfigServiceWin::Watch(const CallbackType& callback) { 664 void DnsConfigServiceWin::Watch(const CallbackType& callback) {
476 DCHECK(CalledOnValidThread()); 665 DCHECK(CalledOnValidThread());
477 DCHECK(!callback.is_null()); 666 DCHECK(!callback.is_null());
478 set_callback(callback); 667 set_callback(callback);
479 668
480 // This is done only once per lifetime so open the keys and file watcher 669 // This is done only once per lifetime so open the keys and file watcher
481 // handles on this thread. 670 // handles on this thread.
482 // TODO(szym): Should/can this be avoided? http://crbug.com/114223 671 // TODO(szym): Should/can this be avoided? http://crbug.com/114223
483 base::ThreadRestrictions::ScopedAllowIO allow_io; 672 base::ThreadRestrictions::ScopedAllowIO allow_io;
484 673
485 if (!config_reader_->Watch()) { 674 if (!config_reader_->Watch()) {
486 LOG(ERROR) << "Failed to start watching DNS config"; 675 LOG(ERROR) << "Failed to start watching DNS config";
487 InvalidateConfig(); 676 InvalidateConfig();
488 } 677 }
489 678
490 TCHAR buffer[MAX_PATH]; 679 if (!hosts_reader_->Watch()) {
491 UINT rc = GetSystemDirectory(buffer, MAX_PATH); 680 LOG(ERROR) << "Failed to start watching HOSTS";
492 DCHECK(0 < rc && rc < MAX_PATH); 681 InvalidateHosts();
493 FilePath hosts_path = FilePath(buffer).
494 Append(FILE_PATH_LITERAL("drivers\\etc\\hosts"));
495 hosts_reader_ = new DnsHostsReader(
496 hosts_path,
497 base::Bind(&DnsConfigServiceWin::OnHostsRead, base::Unretained(this)));
498 if (hosts_watcher_->Watch(hosts_path,
499 base::Bind(&DnsConfigServiceWin::OnHostsChanged,
500 base::Unretained(this)))) {
501 OnHostsChanged(true);
502 } else {
503 OnHostsChanged(false);
504 } 682 }
505 } 683 }
506 684
507 void DnsConfigServiceWin::OnHostsChanged(bool succeeded) {
508 InvalidateHosts();
509 if (succeeded)
510 hosts_reader_->WorkNow();
511 else
512 LOG(ERROR) << "Failed to watch DNS hosts";
513 }
514
515 } // namespace internal 685 } // namespace internal
516 686
517 // static 687 // static
518 scoped_ptr<DnsConfigService> DnsConfigService::CreateSystemService() { 688 scoped_ptr<DnsConfigService> DnsConfigService::CreateSystemService() {
519 return scoped_ptr<DnsConfigService>(new internal::DnsConfigServiceWin()); 689 return scoped_ptr<DnsConfigService>(new internal::DnsConfigServiceWin());
520 } 690 }
521 691
522 } // namespace net 692 } // namespace net
523 693
OLDNEW
« no previous file with comments | « net/dns/dns_config_service_win.h ('k') | net/dns/dns_hosts.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698