Home | History | Annotate | Download | only in dns
      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
      3 // found in the LICENSE file.
      4 
      5 #ifndef NET_DNS_DNS_CONFIG_SERVICE_H_
      6 #define NET_DNS_DNS_CONFIG_SERVICE_H_
      7 
      8 #include <map>
      9 #include <string>
     10 #include <vector>
     11 
     12 #include "base/gtest_prod_util.h"
     13 #include "base/memory/scoped_ptr.h"
     14 #include "base/memory/scoped_vector.h"
     15 #include "base/threading/non_thread_safe.h"
     16 #include "base/time/time.h"
     17 #include "base/timer/timer.h"
     18 // Needed on shared build with MSVS2010 to avoid multiple definitions of
     19 // std::vector<IPEndPoint>.
     20 #include "net/base/address_list.h"
     21 #include "net/base/ip_endpoint.h"  // win requires size of IPEndPoint
     22 #include "net/base/net_export.h"
     23 #include "net/dns/dns_hosts.h"
     24 
     25 namespace base {
     26 class Value;
     27 }
     28 
     29 namespace net {
     30 
     31 // Always use 1 second timeout (followed by binary exponential backoff).
     32 // TODO(szym): Remove code which reads timeout from system.
     33 const unsigned kDnsTimeoutSeconds = 1;
     34 
     35 // Classifies nameserver address lists for histograms.
     36 class NET_EXPORT_PRIVATE NameServerClassifier {
     37  public:
     38   // This is used in a histogram (AsyncDNS.NameServersType); add new entries
     39   // right before MAX_VALUE.
     40   enum NameServersType {
     41     NAME_SERVERS_TYPE_NONE,
     42     NAME_SERVERS_TYPE_GOOGLE_PUBLIC_DNS,
     43     NAME_SERVERS_TYPE_PRIVATE,
     44     NAME_SERVERS_TYPE_PUBLIC,
     45     NAME_SERVERS_TYPE_MIXED,
     46     NAME_SERVERS_TYPE_MAX_VALUE
     47   };
     48 
     49   NameServerClassifier();
     50   ~NameServerClassifier();
     51 
     52   NameServersType GetNameServersType(
     53       const std::vector<net::IPEndPoint>& nameservers) const;
     54 
     55  private:
     56   struct NameServerTypeRule;
     57 
     58   void AddRule(const char* pattern_string, NameServersType type);
     59   NameServersType GetNameServerType(const IPAddressNumber& address) const;
     60   static NameServersType MergeNameServersTypes(NameServersType a,
     61                                                NameServersType b);
     62 
     63   ScopedVector<NameServerTypeRule> rules_;
     64 };
     65 
     66 // DnsConfig stores configuration of the system resolver.
     67 struct NET_EXPORT_PRIVATE DnsConfig {
     68   DnsConfig();
     69   virtual ~DnsConfig();
     70 
     71   bool Equals(const DnsConfig& d) const;
     72 
     73   bool EqualsIgnoreHosts(const DnsConfig& d) const;
     74 
     75   void CopyIgnoreHosts(const DnsConfig& src);
     76 
     77   // Returns a Value representation of |this|.  Caller takes ownership of the
     78   // returned Value.  For performance reasons, the Value only contains the
     79   // number of hosts rather than the full list.
     80   base::Value* ToValue() const;
     81 
     82   bool IsValid() const {
     83     return !nameservers.empty();
     84   }
     85 
     86   // List of name server addresses.
     87   std::vector<IPEndPoint> nameservers;
     88   // Suffix search list; used on first lookup when number of dots in given name
     89   // is less than |ndots|.
     90   std::vector<std::string> search;
     91 
     92   DnsHosts hosts;
     93 
     94   // True if there are options set in the system configuration that are not yet
     95   // supported by DnsClient.
     96   bool unhandled_options;
     97 
     98   // AppendToMultiLabelName: is suffix search performed for multi-label names?
     99   // True, except on Windows where it can be configured.
    100   bool append_to_multi_label_name;
    101 
    102   // Indicates that source port randomization is required. This uses additional
    103   // resources on some platforms.
    104   bool randomize_ports;
    105 
    106   // Resolver options; see man resolv.conf.
    107 
    108   // Minimum number of dots before global resolution precedes |search|.
    109   int ndots;
    110   // Time between retransmissions, see res_state.retrans.
    111   base::TimeDelta timeout;
    112   // Maximum number of attempts, see res_state.retry.
    113   int attempts;
    114   // Round robin entries in |nameservers| for subsequent requests.
    115   bool rotate;
    116   // Enable EDNS0 extensions.
    117   bool edns0;
    118 
    119   // Indicates system configuration uses local IPv6 connectivity, e.g.,
    120   // DirectAccess. This is exposed for HostResolver to skip IPv6 probes,
    121   // as it may cause them to return incorrect results.
    122   bool use_local_ipv6;
    123 };
    124 
    125 // Service for reading system DNS settings, on demand or when signalled by
    126 // internal watchers and NetworkChangeNotifier.
    127 class NET_EXPORT_PRIVATE DnsConfigService
    128     : NON_EXPORTED_BASE(public base::NonThreadSafe) {
    129  public:
    130   // Callback interface for the client, called on the same thread as
    131   // ReadConfig() and WatchConfig().
    132   typedef base::Callback<void(const DnsConfig& config)> CallbackType;
    133 
    134   // Creates the platform-specific DnsConfigService.
    135   static scoped_ptr<DnsConfigService> CreateSystemService();
    136 
    137   DnsConfigService();
    138   virtual ~DnsConfigService();
    139 
    140   // Attempts to read the configuration. Will run |callback| when succeeded.
    141   // Can be called at most once.
    142   void ReadConfig(const CallbackType& callback);
    143 
    144   // Registers systems watchers. Will attempt to read config after watch starts,
    145   // but only if watchers started successfully. Will run |callback| iff config
    146   // changes from last call or has to be withdrawn. Can be called at most once.
    147   // Might require MessageLoopForIO.
    148   void WatchConfig(const CallbackType& callback);
    149 
    150  protected:
    151   enum WatchStatus {
    152     DNS_CONFIG_WATCH_STARTED = 0,
    153     DNS_CONFIG_WATCH_FAILED_TO_START_CONFIG,
    154     DNS_CONFIG_WATCH_FAILED_TO_START_HOSTS,
    155     DNS_CONFIG_WATCH_FAILED_CONFIG,
    156     DNS_CONFIG_WATCH_FAILED_HOSTS,
    157     DNS_CONFIG_WATCH_MAX,
    158   };
    159 
    160  // Immediately attempts to read the current configuration.
    161   virtual void ReadNow() = 0;
    162   // Registers system watchers. Returns true iff succeeds.
    163   virtual bool StartWatching() = 0;
    164 
    165   // Called when the current config (except hosts) has changed.
    166   void InvalidateConfig();
    167   // Called when the current hosts have changed.
    168   void InvalidateHosts();
    169 
    170   // Called with new config. |config|.hosts is ignored.
    171   void OnConfigRead(const DnsConfig& config);
    172   // Called with new hosts. Rest of the config is assumed unchanged.
    173   void OnHostsRead(const DnsHosts& hosts);
    174 
    175   void set_watch_failed(bool value) { watch_failed_ = value; }
    176 
    177  private:
    178   // The timer counts from the last Invalidate* until complete config is read.
    179   void StartTimer();
    180   void OnTimeout();
    181   // Called when the config becomes complete. Stops the timer.
    182   void OnCompleteConfig();
    183 
    184   CallbackType callback_;
    185 
    186   DnsConfig dns_config_;
    187 
    188   // True if any of the necessary watchers failed. In that case, the service
    189   // will communicate changes via OnTimeout, but will only send empty DnsConfig.
    190   bool watch_failed_;
    191   // True after On*Read, before Invalidate*. Tells if the config is complete.
    192   bool have_config_;
    193   bool have_hosts_;
    194   // True if receiver needs to be updated when the config becomes complete.
    195   bool need_update_;
    196   // True if the last config sent was empty (instead of |dns_config_|).
    197   // Set when |timer_| expires.
    198   bool last_sent_empty_;
    199 
    200   // Initialized and updated on Invalidate* call.
    201   base::TimeTicks last_invalidate_config_time_;
    202   base::TimeTicks last_invalidate_hosts_time_;
    203   // Initialized and updated when |timer_| expires.
    204   base::TimeTicks last_sent_empty_time_;
    205 
    206   // Started in Invalidate*, cleared in On*Read.
    207   base::OneShotTimer<DnsConfigService> timer_;
    208 
    209   NameServerClassifier classifier_;
    210 
    211   DISALLOW_COPY_AND_ASSIGN(DnsConfigService);
    212 };
    213 
    214 }  // namespace net
    215 
    216 #endif  // NET_DNS_DNS_CONFIG_SERVICE_H_
    217