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