1 // Copyright 2021 The Chromium Authors
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_service_android.h"
6
7 #include <sys/system_properties.h>
8
9 #include <memory>
10 #include <optional>
11 #include <string>
12 #include <utility>
13
14 #include "base/android/build_info.h"
15 #include "base/files/file_path.h"
16 #include "base/functional/bind.h"
17 #include "base/logging.h"
18 #include "base/memory/raw_ptr.h"
19 #include "base/sequence_checker.h"
20 #include "base/time/time.h"
21 #include "net/android/network_library.h"
22 #include "net/base/address_tracker_linux.h"
23 #include "net/base/ip_address.h"
24 #include "net/base/ip_endpoint.h"
25 #include "net/base/network_interfaces.h"
26 #include "net/dns/dns_config.h"
27 #include "net/dns/dns_config_service.h"
28 #include "net/dns/public/dns_protocol.h"
29 #include "net/dns/serial_worker.h"
30
31 namespace net {
32 namespace internal {
33
34 namespace {
35
36 constexpr base::FilePath::CharType kFilePathHosts[] =
37 FILE_PATH_LITERAL("/system/etc/hosts");
38
IsVpnPresent()39 bool IsVpnPresent() {
40 NetworkInterfaceList networks;
41 if (!GetNetworkList(&networks, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES))
42 return false;
43
44 for (NetworkInterface network : networks) {
45 if (AddressTrackerLinux::IsTunnelInterfaceName(network.name.c_str()))
46 return true;
47 }
48 return false;
49 }
50
51 } // namespace
52
53 // static
54 constexpr base::TimeDelta DnsConfigServiceAndroid::kConfigChangeDelay;
55
56 class DnsConfigServiceAndroid::ConfigReader : public SerialWorker {
57 public:
ConfigReader(DnsConfigServiceAndroid & service,android::DnsServerGetter dns_server_getter)58 explicit ConfigReader(DnsConfigServiceAndroid& service,
59 android::DnsServerGetter dns_server_getter)
60 : dns_server_getter_(std::move(dns_server_getter)), service_(&service) {}
61
62 ~ConfigReader() override = default;
63
64 ConfigReader(const ConfigReader&) = delete;
65 ConfigReader& operator=(const ConfigReader&) = delete;
66
CreateWorkItem()67 std::unique_ptr<SerialWorker::WorkItem> CreateWorkItem() override {
68 return std::make_unique<WorkItem>(dns_server_getter_);
69 }
70
OnWorkFinished(std::unique_ptr<SerialWorker::WorkItem> serial_worker_work_item)71 bool OnWorkFinished(std::unique_ptr<SerialWorker::WorkItem>
72 serial_worker_work_item) override {
73 DCHECK(serial_worker_work_item);
74 DCHECK(!IsCancelled());
75
76 WorkItem* work_item = static_cast<WorkItem*>(serial_worker_work_item.get());
77 if (work_item->dns_config_.has_value()) {
78 service_->OnConfigRead(std::move(work_item->dns_config_).value());
79 return true;
80 } else {
81 LOG(WARNING) << "Failed to read DnsConfig.";
82 return false;
83 }
84 }
85
86 private:
87 class WorkItem : public SerialWorker::WorkItem {
88 public:
WorkItem(android::DnsServerGetter dns_server_getter)89 explicit WorkItem(android::DnsServerGetter dns_server_getter)
90 : dns_server_getter_(std::move(dns_server_getter)) {}
91
DoWork()92 void DoWork() override {
93 dns_config_.emplace();
94 dns_config_->unhandled_options = false;
95
96 if (base::android::BuildInfo::GetInstance()->sdk_int() >=
97 base::android::SDK_VERSION_MARSHMALLOW) {
98 if (!dns_server_getter_.Run(
99 &dns_config_->nameservers, &dns_config_->dns_over_tls_active,
100 &dns_config_->dns_over_tls_hostname, &dns_config_->search)) {
101 dns_config_.reset();
102 }
103 return;
104 }
105
106 if (IsVpnPresent()) {
107 dns_config_->unhandled_options = true;
108 }
109
110 // NOTE(pauljensen): __system_property_get and the net.dns1/2 properties
111 // are not supported APIs, but they're only read on pre-Marshmallow
112 // Android which was released years ago and isn't changing.
113 char property_value[PROP_VALUE_MAX];
114 __system_property_get("net.dns1", property_value);
115 std::string dns1_string = property_value;
116 __system_property_get("net.dns2", property_value);
117 std::string dns2_string = property_value;
118 if (dns1_string.empty() && dns2_string.empty()) {
119 dns_config_.reset();
120 return;
121 }
122
123 IPAddress dns1_address;
124 IPAddress dns2_address;
125 bool parsed1 = dns1_address.AssignFromIPLiteral(dns1_string);
126 bool parsed2 = dns2_address.AssignFromIPLiteral(dns2_string);
127 if (!parsed1 && !parsed2) {
128 dns_config_.reset();
129 return;
130 }
131
132 if (parsed1) {
133 IPEndPoint dns1(dns1_address, dns_protocol::kDefaultPort);
134 dns_config_->nameservers.push_back(dns1);
135 }
136 if (parsed2) {
137 IPEndPoint dns2(dns2_address, dns_protocol::kDefaultPort);
138 dns_config_->nameservers.push_back(dns2);
139 }
140 }
141
142 private:
143 friend class ConfigReader;
144 android::DnsServerGetter dns_server_getter_;
145 std::optional<DnsConfig> dns_config_;
146 };
147
148 android::DnsServerGetter dns_server_getter_;
149
150 // Raw pointer to owning DnsConfigService.
151 const raw_ptr<DnsConfigServiceAndroid> service_;
152 };
153
DnsConfigServiceAndroid()154 DnsConfigServiceAndroid::DnsConfigServiceAndroid()
155 : DnsConfigService(kFilePathHosts, kConfigChangeDelay) {
156 // Allow constructing on one thread and living on another.
157 DETACH_FROM_SEQUENCE(sequence_checker_);
158 dns_server_getter_ = base::BindRepeating(&android::GetCurrentDnsServers);
159 }
160
~DnsConfigServiceAndroid()161 DnsConfigServiceAndroid::~DnsConfigServiceAndroid() {
162 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
163 if (is_watching_network_change_) {
164 NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
165 }
166 if (config_reader_)
167 config_reader_->Cancel();
168 }
169
ReadConfigNow()170 void DnsConfigServiceAndroid::ReadConfigNow() {
171 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
172 if (!config_reader_) {
173 DCHECK(dns_server_getter_);
174 config_reader_ =
175 std::make_unique<ConfigReader>(*this, std::move(dns_server_getter_));
176 }
177 config_reader_->WorkNow();
178 }
179
StartWatching()180 bool DnsConfigServiceAndroid::StartWatching() {
181 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
182 CHECK(!is_watching_network_change_);
183 is_watching_network_change_ = true;
184
185 // On Android, assume DNS config may have changed on every network change.
186 NetworkChangeNotifier::AddNetworkChangeObserver(this);
187
188 // Hosts file should never change on Android (and watching it is
189 // problematic; see http://crbug.com/600442), so don't watch it.
190
191 return true;
192 }
193
OnNetworkChanged(NetworkChangeNotifier::ConnectionType type)194 void DnsConfigServiceAndroid::OnNetworkChanged(
195 NetworkChangeNotifier::ConnectionType type) {
196 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
197 if (type != NetworkChangeNotifier::CONNECTION_NONE) {
198 OnConfigChanged(/*succeeded=*/true);
199 }
200 }
201 } // namespace internal
202
203 // static
CreateSystemService()204 std::unique_ptr<DnsConfigService> DnsConfigService::CreateSystemService() {
205 return std::make_unique<internal::DnsConfigServiceAndroid>();
206 }
207
208 } // namespace net
209