| Index: net/dns/dns_config_service_win.cc
|
| diff --git a/net/dns/dns_config_service_win.cc b/net/dns/dns_config_service_win.cc
|
| index 6d12155d8ccd2733af111250b648b1a57dcfc592..fe97b74f73e37507a6f92804ea21748670d4c7b9 100644
|
| --- a/net/dns/dns_config_service_win.cc
|
| +++ b/net/dns/dns_config_service_win.cc
|
| @@ -43,8 +43,19 @@ namespace {
|
| // Interval between retries to parse config. Used only until parsing succeeds.
|
| const int kRetryIntervalSeconds = 5;
|
|
|
| +// Registry key paths.
|
| +const wchar_t* const kTcpipPath =
|
| + L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters";
|
| +const wchar_t* const kTcpip6Path =
|
| + L"SYSTEM\\CurrentControlSet\\Services\\Tcpip6\\Parameters";
|
| +const wchar_t* const kDnscachePath =
|
| + L"SYSTEM\\CurrentControlSet\\Services\\Dnscache\\Parameters";
|
| +const wchar_t* const kPolicyPath =
|
| + L"SOFTWARE\\Policies\\Microsoft\\Windows NT\\DNSClient";
|
| const wchar_t* const kPrimaryDnsSuffixPath =
|
| L"SOFTWARE\\Policies\\Microsoft\\System\\DNSClient";
|
| +const wchar_t* const kNRPTPath =
|
| + L"SOFTWARE\\Policies\\Microsoft\\Windows NT\\DNSClient\\DnsPolicyConfig";
|
|
|
| enum HostsParseWinResult {
|
| HOSTS_PARSE_WIN_OK = 0,
|
| @@ -198,6 +209,10 @@ ConfigParseWinResult ReadSystemSettings(DnsSystemSettings* settings) {
|
| &settings->primary_dns_suffix)) {
|
| return CONFIG_PARSE_WIN_READ_PRIMARY_SUFFIX;
|
| }
|
| +
|
| + base::win::RegistryKeyIterator nrpt_rules(HKEY_LOCAL_MACHINE, kNRPTPath);
|
| + settings->have_name_resolution_policy = (nrpt_rules.SubkeyCount() > 0);
|
| +
|
| return CONFIG_PARSE_WIN_OK;
|
| }
|
|
|
| @@ -330,8 +345,7 @@ bool IsStatelessDiscoveryAddress(const IPAddressNumber& address) {
|
| address.begin()) && (address.back() < 4);
|
| }
|
|
|
| -} // namespace
|
| -
|
| +// Returns the path to the HOSTS file.
|
| base::FilePath GetHostsPath() {
|
| TCHAR buffer[MAX_PATH];
|
| UINT rc = GetSystemDirectory(buffer, MAX_PATH);
|
| @@ -340,6 +354,92 @@ base::FilePath GetHostsPath() {
|
| FILE_PATH_LITERAL("drivers\\etc\\hosts"));
|
| }
|
|
|
| +void ConfigureSuffixSearch(const DnsSystemSettings& settings,
|
| + DnsConfig* config) {
|
| + // SearchList takes precedence, so check it first.
|
| + if (settings.policy_search_list.set) {
|
| + std::vector<std::string> search;
|
| + if (ParseSearchList(settings.policy_search_list.value, &search)) {
|
| + config->search.swap(search);
|
| + return;
|
| + }
|
| + // Even if invalid, the policy disables the user-specified setting below.
|
| + } else if (settings.tcpip_search_list.set) {
|
| + std::vector<std::string> search;
|
| + if (ParseSearchList(settings.tcpip_search_list.value, &search)) {
|
| + config->search.swap(search);
|
| + return;
|
| + }
|
| + }
|
| +
|
| + // In absence of explicit search list, suffix search is:
|
| + // [primary suffix, connection-specific suffix, devolution of primary suffix].
|
| + // Primary suffix can be set by policy (primary_dns_suffix) or
|
| + // user setting (tcpip_domain).
|
| + //
|
| + // The policy (primary_dns_suffix) can be edited via Group Policy Editor
|
| + // (gpedit.msc) at Local Computer Policy => Computer Configuration
|
| + // => Administrative Template => Network => DNS Client => Primary DNS Suffix.
|
| + //
|
| + // The user setting (tcpip_domain) can be configurred at Computer Name in
|
| + // System Settings
|
| + std::string primary_suffix;
|
| + if ((settings.primary_dns_suffix.set &&
|
| + ParseDomainASCII(settings.primary_dns_suffix.value, &primary_suffix)) ||
|
| + (settings.tcpip_domain.set &&
|
| + ParseDomainASCII(settings.tcpip_domain.value, &primary_suffix))) {
|
| + // Primary suffix goes in front.
|
| + config->search.insert(config->search.begin(), primary_suffix);
|
| + } else {
|
| + return; // No primary suffix, hence no devolution.
|
| + }
|
| +
|
| + // Devolution is determined by precedence: policy > dnscache > tcpip.
|
| + // |enabled|: UseDomainNameDevolution and |level|: DomainNameDevolutionLevel
|
| + // are overridden independently.
|
| + DnsSystemSettings::DevolutionSetting devolution = settings.policy_devolution;
|
| +
|
| + if (!devolution.enabled.set)
|
| + devolution.enabled = settings.dnscache_devolution.enabled;
|
| + if (!devolution.enabled.set)
|
| + devolution.enabled = settings.tcpip_devolution.enabled;
|
| + if (devolution.enabled.set && (devolution.enabled.value == 0))
|
| + return; // Devolution disabled.
|
| +
|
| + // By default devolution is enabled.
|
| +
|
| + if (!devolution.level.set)
|
| + devolution.level = settings.dnscache_devolution.level;
|
| + if (!devolution.level.set)
|
| + devolution.level = settings.tcpip_devolution.level;
|
| +
|
| + // After the recent update, Windows will try to determine a safe default
|
| + // value by comparing the forest root domain (FRD) to the primary suffix.
|
| + // See http://support.microsoft.com/kb/957579 for details.
|
| + // For now, if the level is not set, we disable devolution, assuming that
|
| + // we will fallback to the system getaddrinfo anyway. This might cause
|
| + // performance loss for resolutions which depend on the system default
|
| + // devolution setting.
|
| + //
|
| + // If the level is explicitly set below 2, devolution is disabled.
|
| + if (!devolution.level.set || devolution.level.value < 2)
|
| + return; // Devolution disabled.
|
| +
|
| + // Devolve the primary suffix. This naive logic matches the observed
|
| + // behavior (see also ParseSearchList). If a suffix is not valid, it will be
|
| + // discarded when the fully-qualified name is converted to DNS format.
|
| +
|
| + unsigned num_dots = std::count(primary_suffix.begin(),
|
| + primary_suffix.end(), '.');
|
| +
|
| + for (size_t offset = 0; num_dots >= devolution.level.value; --num_dots) {
|
| + offset = primary_suffix.find('.', offset + 1);
|
| + config->search.push_back(primary_suffix.substr(offset + 1));
|
| + }
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| bool ParseSearchList(const base::string16& value,
|
| std::vector<std::string>* output) {
|
| DCHECK(output);
|
| @@ -429,87 +529,16 @@ ConfigParseWinResult ConvertSettingsToDnsConfig(
|
| (settings.append_to_multi_label_name.value != 0);
|
| }
|
|
|
| - // SearchList takes precedence, so check it first.
|
| - if (settings.policy_search_list.set) {
|
| - std::vector<std::string> search;
|
| - if (ParseSearchList(settings.policy_search_list.value, &search)) {
|
| - config->search.swap(search);
|
| - return CONFIG_PARSE_WIN_OK;
|
| - }
|
| - // Even if invalid, the policy disables the user-specified setting below.
|
| - } else if (settings.tcpip_search_list.set) {
|
| - std::vector<std::string> search;
|
| - if (ParseSearchList(settings.tcpip_search_list.value, &search)) {
|
| - config->search.swap(search);
|
| - return CONFIG_PARSE_WIN_OK;
|
| - }
|
| + ConfigParseWinResult result = CONFIG_PARSE_WIN_OK;
|
| + if (settings.have_name_resolution_policy) {
|
| + config->unhandled_options = true;
|
| + // TODO(szym): only set this to true if NRPT has DirectAccess rules.
|
| + config->use_local_ipv6 = true;
|
| + result = CONFIG_PARSE_WIN_UNHANDLED_OPTIONS;
|
| }
|
|
|
| - // In absence of explicit search list, suffix search is:
|
| - // [primary suffix, connection-specific suffix, devolution of primary suffix].
|
| - // Primary suffix can be set by policy (primary_dns_suffix) or
|
| - // user setting (tcpip_domain).
|
| - //
|
| - // The policy (primary_dns_suffix) can be edited via Group Policy Editor
|
| - // (gpedit.msc) at Local Computer Policy => Computer Configuration
|
| - // => Administrative Template => Network => DNS Client => Primary DNS Suffix.
|
| - //
|
| - // The user setting (tcpip_domain) can be configurred at Computer Name in
|
| - // System Settings
|
| - std::string primary_suffix;
|
| - if ((settings.primary_dns_suffix.set &&
|
| - ParseDomainASCII(settings.primary_dns_suffix.value, &primary_suffix)) ||
|
| - (settings.tcpip_domain.set &&
|
| - ParseDomainASCII(settings.tcpip_domain.value, &primary_suffix))) {
|
| - // Primary suffix goes in front.
|
| - config->search.insert(config->search.begin(), primary_suffix);
|
| - } else {
|
| - return CONFIG_PARSE_WIN_OK; // No primary suffix, hence no devolution.
|
| - }
|
| -
|
| - // Devolution is determined by precedence: policy > dnscache > tcpip.
|
| - // |enabled|: UseDomainNameDevolution and |level|: DomainNameDevolutionLevel
|
| - // are overridden independently.
|
| - DnsSystemSettings::DevolutionSetting devolution = settings.policy_devolution;
|
| -
|
| - if (!devolution.enabled.set)
|
| - devolution.enabled = settings.dnscache_devolution.enabled;
|
| - if (!devolution.enabled.set)
|
| - devolution.enabled = settings.tcpip_devolution.enabled;
|
| - if (devolution.enabled.set && (devolution.enabled.value == 0))
|
| - return CONFIG_PARSE_WIN_OK; // Devolution disabled.
|
| -
|
| - // By default devolution is enabled.
|
| -
|
| - if (!devolution.level.set)
|
| - devolution.level = settings.dnscache_devolution.level;
|
| - if (!devolution.level.set)
|
| - devolution.level = settings.tcpip_devolution.level;
|
| -
|
| - // After the recent update, Windows will try to determine a safe default
|
| - // value by comparing the forest root domain (FRD) to the primary suffix.
|
| - // See http://support.microsoft.com/kb/957579 for details.
|
| - // For now, if the level is not set, we disable devolution, assuming that
|
| - // we will fallback to the system getaddrinfo anyway. This might cause
|
| - // performance loss for resolutions which depend on the system default
|
| - // devolution setting.
|
| - //
|
| - // If the level is explicitly set below 2, devolution is disabled.
|
| - if (!devolution.level.set || devolution.level.value < 2)
|
| - return CONFIG_PARSE_WIN_OK; // Devolution disabled.
|
| -
|
| - // Devolve the primary suffix. This naive logic matches the observed
|
| - // behavior (see also ParseSearchList). If a suffix is not valid, it will be
|
| - // discarded when the fully-qualified name is converted to DNS format.
|
| -
|
| - unsigned num_dots = std::count(primary_suffix.begin(),
|
| - primary_suffix.end(), '.');
|
| -
|
| - for (size_t offset = 0; num_dots >= devolution.level.value; --num_dots) {
|
| - offset = primary_suffix.find('.', offset + 1);
|
| - config->search.push_back(primary_suffix.substr(offset + 1));
|
| - }
|
| - return CONFIG_PARSE_WIN_OK;
|
| + ConfigureSuffixSearch(settings, config);
|
| + return result;
|
| }
|
|
|
| // Watches registry and HOSTS file for changes. Must live on a thread which
|
| @@ -606,7 +635,8 @@ class DnsConfigServiceWin::ConfigReader : public SerialWorker {
|
| ConfigParseWinResult result = ReadSystemSettings(&settings);
|
| if (result == CONFIG_PARSE_WIN_OK)
|
| result = ConvertSettingsToDnsConfig(settings, &dns_config_);
|
| - success_ = (result == CONFIG_PARSE_WIN_OK);
|
| + success_ = (result == CONFIG_PARSE_WIN_OK ||
|
| + result == CONFIG_PARSE_WIN_UNHANDLED_OPTIONS);
|
| UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ConfigParseWin",
|
| result, CONFIG_PARSE_WIN_MAX);
|
| UMA_HISTOGRAM_BOOLEAN("AsyncDNS.ConfigParseResult", success_);
|
|
|