15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file. 45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/dns/dns_config_watcher_mac.h" 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <dlfcn.h> 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/lazy_instance.h" 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/apple_apsl/dnsinfo.h" 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// dnsinfo symbols are available via libSystem.dylib, but can also be present in 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// SystemConfiguration.framework. To avoid confusion, load them explicitly from 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// libSystem.dylib. 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class DnsInfoApi { 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) typedef const char* (*dns_configuration_notify_key_t)(); 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) typedef dns_config_t* (*dns_configuration_copy_t)(); 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) typedef void (*dns_configuration_free_t)(dns_config_t*); 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DnsInfoApi() 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : dns_configuration_notify_key(NULL), 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dns_configuration_copy(NULL), 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dns_configuration_free(NULL) { 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) handle_ = dlopen("/usr/lib/libSystem.dylib", 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RTLD_LAZY | RTLD_NOLOAD); 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!handle_) 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dns_configuration_notify_key = 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) reinterpret_cast<dns_configuration_notify_key_t>( 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dlsym(handle_, "dns_configuration_notify_key")); 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dns_configuration_copy = 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) reinterpret_cast<dns_configuration_copy_t>( 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dlsym(handle_, "dns_configuration_copy")); 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dns_configuration_free = 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) reinterpret_cast<dns_configuration_free_t>( 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dlsym(handle_, "dns_configuration_free")); 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ~DnsInfoApi() { 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (handle_) 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dlclose(handle_); 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dns_configuration_notify_key_t dns_configuration_notify_key; 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dns_configuration_copy_t dns_configuration_copy; 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dns_configuration_free_t dns_configuration_free; 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void* handle_; 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const DnsInfoApi& GetDnsInfoApi() { 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static base::LazyInstance<DnsInfoApi>::Leaky api = LAZY_INSTANCE_INITIALIZER; 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return api.Get(); 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct DnsConfigTDeleter { 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) inline void operator()(dns_config_t* ptr) const { 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (GetDnsInfoApi().dns_configuration_free) 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetDnsInfoApi().dns_configuration_free(ptr); 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace net { 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace internal { 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool DnsConfigWatcher::Watch( 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Callback<void(bool succeeded)>& callback) { 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!GetDnsInfoApi().dns_configuration_notify_key) 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return watcher_.Watch(GetDnsInfoApi().dns_configuration_notify_key(), 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback); 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ConfigParsePosixResult DnsConfigWatcher::CheckDnsConfig() { 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!GetDnsInfoApi().dns_configuration_copy) 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return CONFIG_PARSE_POSIX_NO_DNSINFO; 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<dns_config_t, DnsConfigTDeleter> dns_config( 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetDnsInfoApi().dns_configuration_copy()); 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!dns_config) 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return CONFIG_PARSE_POSIX_NO_DNSINFO; 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(szym): Parse dns_config_t for resolvers rather than res_state. 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // DnsClient can't handle domain-specific unscoped resolvers. 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) unsigned num_resolvers = 0; 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (int i = 0; i < dns_config->n_resolver; ++i) { 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dns_resolver_t* resolver = dns_config->resolver[i]; 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!resolver->n_nameserver) 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) continue; 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (resolver->options && !strcmp(resolver->options, "mdns")) 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) continue; 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++num_resolvers; 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (num_resolvers > 1) 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return CONFIG_PARSE_POSIX_UNHANDLED_OPTIONS; 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return CONFIG_PARSE_POSIX_OK; 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace internal 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace net 107