| Index: net/dns/dns_config_watcher_mac.cc
|
| diff --git a/net/dns/dns_config_watcher_mac.cc b/net/dns/dns_config_watcher_mac.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..cee15ba790a447ca748fee097236438f5dce8a9c
|
| --- /dev/null
|
| +++ b/net/dns/dns_config_watcher_mac.cc
|
| @@ -0,0 +1,106 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "net/dns/dns_config_watcher_mac.h"
|
| +
|
| +#include <dlfcn.h>
|
| +
|
| +#include "base/lazy_instance.h"
|
| +#include "third_party/apple_apsl/dnsinfo.h"
|
| +
|
| +namespace {
|
| +
|
| +// dnsinfo symbols are available via libSystem.dylib, but can also be present in
|
| +// SystemConfiguration.framework. To avoid confusion, load them explicitly from
|
| +// libSystem.dylib.
|
| +class DnsInfoApi {
|
| + public:
|
| + typedef const char* (*dns_configuration_notify_key_t)();
|
| + typedef dns_config_t* (*dns_configuration_copy_t)();
|
| + typedef void (*dns_configuration_free_t)(dns_config_t*);
|
| +
|
| + DnsInfoApi()
|
| + : dns_configuration_notify_key(NULL),
|
| + dns_configuration_copy(NULL),
|
| + dns_configuration_free(NULL) {
|
| + handle_ = dlopen("/usr/lib/libSystem.dylib",
|
| + RTLD_LAZY | RTLD_NOLOAD);
|
| + if (!handle_)
|
| + return;
|
| + dns_configuration_notify_key =
|
| + reinterpret_cast<dns_configuration_notify_key_t>(
|
| + dlsym(handle_, "dns_configuration_notify_key"));
|
| + dns_configuration_copy =
|
| + reinterpret_cast<dns_configuration_copy_t>(
|
| + dlsym(handle_, "dns_configuration_copy"));
|
| + dns_configuration_free =
|
| + reinterpret_cast<dns_configuration_free_t>(
|
| + dlsym(handle_, "dns_configuration_free"));
|
| + }
|
| +
|
| + ~DnsInfoApi() {
|
| + if (handle_)
|
| + dlclose(handle_);
|
| + }
|
| +
|
| + dns_configuration_notify_key_t dns_configuration_notify_key;
|
| + dns_configuration_copy_t dns_configuration_copy;
|
| + dns_configuration_free_t dns_configuration_free;
|
| +
|
| + private:
|
| + void* handle_;
|
| +};
|
| +
|
| +const DnsInfoApi& GetDnsInfoApi() {
|
| + static base::LazyInstance<DnsInfoApi>::Leaky api = LAZY_INSTANCE_INITIALIZER;
|
| + return api.Get();
|
| +}
|
| +
|
| +struct DnsConfigTDeleter {
|
| + inline void operator()(dns_config_t* ptr) const {
|
| + if (GetDnsInfoApi().dns_configuration_free)
|
| + GetDnsInfoApi().dns_configuration_free(ptr);
|
| + }
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +namespace net {
|
| +namespace internal {
|
| +
|
| +bool DnsConfigWatcher::Watch(
|
| + const base::Callback<void(bool succeeded)>& callback) {
|
| + if (!GetDnsInfoApi().dns_configuration_notify_key)
|
| + return false;
|
| + return watcher_.Watch(GetDnsInfoApi().dns_configuration_notify_key(),
|
| + callback);
|
| +}
|
| +
|
| +// static
|
| +ConfigParsePosixResult DnsConfigWatcher::GetDnsConfigError() {
|
| + if (!GetDnsInfoApi().dns_configuration_copy)
|
| + return CONFIG_PARSE_POSIX_NO_DNSINFO;
|
| + scoped_ptr<dns_config_t, DnsConfigTDeleter> dns_config(
|
| + GetDnsInfoApi().dns_configuration_copy());
|
| + if (!dns_config)
|
| + return CONFIG_PARSE_POSIX_NO_DNSINFO;
|
| +
|
| + // TODO(szym): Parse dns_config_t for resolvers rather than res_state.
|
| + // DnsClient can't handle domain-specific unscoped resolvers.
|
| + unsigned num_resolvers = 0;
|
| + for (int i = 0; i < dns_config->n_resolver; ++i) {
|
| + dns_resolver_t* resolver = dns_config->resolver[i];
|
| + if (!resolver->n_nameserver)
|
| + continue;
|
| + if (resolver->options && !strcmp(resolver->options, "mdns"))
|
| + continue;
|
| + ++num_resolvers;
|
| + }
|
| + if (num_resolvers > 1)
|
| + return CONFIG_PARSE_POSIX_UNHANDLED_OPTIONS;
|
| + return CONFIG_PARSE_POSIX_OK;
|
| +}
|
| +
|
| +} // naespace internal
|
| +} // namespace net
|
|
|