• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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 #include "net/dns/dns_config_watcher_mac.h"
6 
7 #include <dlfcn.h>
8 
9 #include "base/lazy_instance.h"
10 #include "third_party/apple_apsl/dnsinfo.h"
11 
12 namespace {
13 
14 // dnsinfo symbols are available via libSystem.dylib, but can also be present in
15 // SystemConfiguration.framework. To avoid confusion, load them explicitly from
16 // libSystem.dylib.
17 class DnsInfoApi {
18  public:
19   typedef const char* (*dns_configuration_notify_key_t)();
20   typedef dns_config_t* (*dns_configuration_copy_t)();
21   typedef void (*dns_configuration_free_t)(dns_config_t*);
22 
DnsInfoApi()23   DnsInfoApi()
24       : dns_configuration_notify_key(NULL),
25         dns_configuration_copy(NULL),
26         dns_configuration_free(NULL) {
27     handle_ = dlopen("/usr/lib/libSystem.dylib",
28                      RTLD_LAZY | RTLD_NOLOAD);
29     if (!handle_)
30       return;
31     dns_configuration_notify_key =
32         reinterpret_cast<dns_configuration_notify_key_t>(
33             dlsym(handle_, "dns_configuration_notify_key"));
34     dns_configuration_copy =
35         reinterpret_cast<dns_configuration_copy_t>(
36             dlsym(handle_, "dns_configuration_copy"));
37     dns_configuration_free =
38         reinterpret_cast<dns_configuration_free_t>(
39             dlsym(handle_, "dns_configuration_free"));
40   }
41 
~DnsInfoApi()42   ~DnsInfoApi() {
43     if (handle_)
44       dlclose(handle_);
45   }
46 
47   dns_configuration_notify_key_t dns_configuration_notify_key;
48   dns_configuration_copy_t dns_configuration_copy;
49   dns_configuration_free_t dns_configuration_free;
50 
51  private:
52   void* handle_;
53 };
54 
GetDnsInfoApi()55 const DnsInfoApi& GetDnsInfoApi() {
56   static base::LazyInstance<DnsInfoApi>::Leaky api = LAZY_INSTANCE_INITIALIZER;
57   return api.Get();
58 }
59 
60 struct DnsConfigTDeleter {
operator ()__anon36202df70111::DnsConfigTDeleter61   inline void operator()(dns_config_t* ptr) const {
62     if (GetDnsInfoApi().dns_configuration_free)
63       GetDnsInfoApi().dns_configuration_free(ptr);
64   }
65 };
66 
67 }  // namespace
68 
69 namespace net {
70 namespace internal {
71 
Watch(const base::Callback<void (bool succeeded)> & callback)72 bool DnsConfigWatcher::Watch(
73     const base::Callback<void(bool succeeded)>& callback) {
74   if (!GetDnsInfoApi().dns_configuration_notify_key)
75     return false;
76   return watcher_.Watch(GetDnsInfoApi().dns_configuration_notify_key(),
77                         callback);
78 }
79 
80 // static
CheckDnsConfig()81 ConfigParsePosixResult DnsConfigWatcher::CheckDnsConfig() {
82   if (!GetDnsInfoApi().dns_configuration_copy)
83     return CONFIG_PARSE_POSIX_NO_DNSINFO;
84   scoped_ptr<dns_config_t, DnsConfigTDeleter> dns_config(
85       GetDnsInfoApi().dns_configuration_copy());
86   if (!dns_config)
87     return CONFIG_PARSE_POSIX_NO_DNSINFO;
88 
89   // TODO(szym): Parse dns_config_t for resolvers rather than res_state.
90   // DnsClient can't handle domain-specific unscoped resolvers.
91   unsigned num_resolvers = 0;
92   for (int i = 0; i < dns_config->n_resolver; ++i) {
93     dns_resolver_t* resolver = dns_config->resolver[i];
94     if (!resolver->n_nameserver)
95       continue;
96     if (resolver->options && !strcmp(resolver->options, "mdns"))
97       continue;
98     ++num_resolvers;
99   }
100   if (num_resolvers > 1)
101     return CONFIG_PARSE_POSIX_UNHANDLED_OPTIONS;
102   return CONFIG_PARSE_POSIX_OK;
103 }
104 
105 }  // namespace internal
106 }  // namespace net
107