15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NET_DNS_DNS_CONFIG_SERVICE_WIN_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NET_DNS_DNS_CONFIG_SERVICE_WIN_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The sole purpose of dns_config_service_win.h is for unittests so we just
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// include these headers here.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <winsock2.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <iphlpapi.h>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
185e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string16.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_export.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/dns/dns_config_service.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The general effort of DnsConfigServiceWin is to configure |nameservers| and
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |search| in DnsConfig. The settings are stored in the Windows registry, but
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to simplify the task we use the IP Helper API wherever possible. That API
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// yields the complete and ordered |nameservers|, but to determine |search| we
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// need to use the registry. On Windows 7, WMI does return the correct |search|
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// but on earlier versions it is insufficient.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Experimental evaluation of Windows behavior suggests that domain parsing is
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// naive. Domain suffixes in |search| are not validated until they are appended
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to the resolved name. We attempt to replicate this behavior.
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace internal {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Parses |value| as search list (comma-delimited list of domain names) from
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a registry key and stores it in |out|. Returns true on success. Empty
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// entries (e.g., "chromium.org,,org") terminate the list. Non-ascii hostnames
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// are converted to punycode.
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool NET_EXPORT_PRIVATE ParseSearchList(const base::string16& value,
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        std::vector<std::string>* out);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All relevant settings read from registry and IP Helper. This isolates our
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// logic from system calls and is exposed for unit tests. Keep it an aggregate
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// struct for easy initialization.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct NET_EXPORT_PRIVATE DnsSystemSettings {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The |set| flag distinguishes between empty and unset values.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct RegString {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool set;
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::string16 value;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct RegDword {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool set;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DWORD value;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct DevolutionSetting {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // UseDomainNameDevolution
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RegDword enabled;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // DomainNameDevolutionLevel
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RegDword level;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Filled in by GetAdapterAddresses. Note that the alternative
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GetNetworkParams does not include IPv6 addresses.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr_malloc<IP_ADAPTER_ADDRESSES> addresses;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SOFTWARE\Policies\Microsoft\Windows NT\DNSClient\SearchList
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RegString policy_search_list;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SYSTEM\CurrentControlSet\Tcpip\Parameters\SearchList
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RegString tcpip_search_list;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SYSTEM\CurrentControlSet\Tcpip\Parameters\Domain
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RegString tcpip_domain;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SOFTWARE\Policies\Microsoft\System\DNSClient\PrimaryDnsSuffix
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RegString primary_dns_suffix;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SOFTWARE\Policies\Microsoft\Windows NT\DNSClient
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DevolutionSetting policy_devolution;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SYSTEM\CurrentControlSet\Dnscache\Parameters
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DevolutionSetting dnscache_devolution;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SYSTEM\CurrentControlSet\Tcpip\Parameters
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DevolutionSetting tcpip_devolution;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SOFTWARE\Policies\Microsoft\Windows NT\DNSClient\AppendToMultiLabelName
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RegDword append_to_multi_label_name;
88d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
89d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // True when the Name Resolution Policy Table (NRPT) has at least one rule:
90d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // SOFTWARE\Policies\Microsoft\Windows NT\DNSClient\DnsPolicyConfig\Rule*
91d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  bool have_name_resolution_policy;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum ConfigParseWinResult {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CONFIG_PARSE_WIN_OK = 0,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CONFIG_PARSE_WIN_READ_IPHELPER,
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CONFIG_PARSE_WIN_READ_POLICY_SEARCHLIST,
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CONFIG_PARSE_WIN_READ_TCPIP_SEARCHLIST,
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CONFIG_PARSE_WIN_READ_DOMAIN,
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CONFIG_PARSE_WIN_READ_POLICY_DEVOLUTION,
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CONFIG_PARSE_WIN_READ_DNSCACHE_DEVOLUTION,
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CONFIG_PARSE_WIN_READ_TCPIP_DEVOLUTION,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CONFIG_PARSE_WIN_READ_APPEND_MULTILABEL,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CONFIG_PARSE_WIN_READ_PRIMARY_SUFFIX,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CONFIG_PARSE_WIN_BAD_ADDRESS,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CONFIG_PARSE_WIN_NO_NAMESERVERS,
107d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  CONFIG_PARSE_WIN_UNHANDLED_OPTIONS,
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CONFIG_PARSE_WIN_MAX  // Bounding values for enumeration.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Fills in |dns_config| from |settings|. Exposed for tests.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ConfigParseWinResult NET_EXPORT_PRIVATE ConvertSettingsToDnsConfig(
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const DnsSystemSettings& settings,
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DnsConfig* dns_config);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use DnsConfigService::CreateSystemService to use it outside of tests.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NET_EXPORT_PRIVATE DnsConfigServiceWin : public DnsConfigService {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DnsConfigServiceWin();
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~DnsConfigServiceWin();
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class Watcher;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class ConfigReader;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class HostsReader;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // DnsConfigService:
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void ReadNow() OVERRIDE;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool StartWatching() OVERRIDE;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnConfigChanged(bool succeeded);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnHostsChanged(bool succeeded);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Watcher> watcher_;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<ConfigReader> config_reader_;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<HostsReader> hosts_reader_;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DnsConfigServiceWin);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace internal
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // NET_DNS_DNS_CONFIG_SERVICE_WIN_H_
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
147