blob: 0139472cbd1b9e7d28bbcf4b556443a60ac11019 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
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::CheckDnsConfig() {
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;
}
} // namespace internal
} // namespace net
|