blob: e33392d359dd59bd25dbf23554a3053d2c5904df [file] [log] [blame]
Erik Kline1742fe12017-12-13 19:40:49 +09001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.connectivity;
18
Erik Kline19841792018-05-16 16:41:57 +090019import static android.net.ConnectivityManager.PRIVATE_DNS_DEFAULT_MODE_FALLBACK;
Erik Klinea24d4592018-01-11 21:07:29 +090020import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
Erik Kline1742fe12017-12-13 19:40:49 +090021import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
Erik Kline1742fe12017-12-13 19:40:49 +090022import static android.provider.Settings.Global.DNS_RESOLVER_MAX_SAMPLES;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090023import static android.provider.Settings.Global.DNS_RESOLVER_MIN_SAMPLES;
Erik Kline1742fe12017-12-13 19:40:49 +090024import static android.provider.Settings.Global.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS;
25import static android.provider.Settings.Global.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT;
Erik Kline19841792018-05-16 16:41:57 +090026import static android.provider.Settings.Global.PRIVATE_DNS_DEFAULT_MODE;
Erik Kline1742fe12017-12-13 19:40:49 +090027import static android.provider.Settings.Global.PRIVATE_DNS_MODE;
28import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER;
29
30import android.content.ContentResolver;
31import android.content.Context;
32import android.content.Intent;
Luke Huang65914772019-03-16 00:31:46 +080033import android.net.IDnsResolver;
Erik Klinea24d4592018-01-11 21:07:29 +090034import android.net.LinkProperties;
35import android.net.Network;
Erik Kline1742fe12017-12-13 19:40:49 +090036import android.net.NetworkUtils;
Wayne Ma28417f42019-04-17 08:03:59 -070037import android.net.ResolverParamsParcel;
Erik Klinea24d4592018-01-11 21:07:29 +090038import android.net.Uri;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090039import android.net.shared.PrivateDnsConfig;
Erik Kline1742fe12017-12-13 19:40:49 +090040import android.os.Binder;
Luke Huang65914772019-03-16 00:31:46 +080041import android.os.RemoteException;
42import android.os.ServiceSpecificException;
Erik Kline1742fe12017-12-13 19:40:49 +090043import android.os.UserHandle;
44import android.provider.Settings;
45import android.text.TextUtils;
dalyk1fcb7392018-03-05 12:42:22 -050046import android.util.Pair;
Erik Kline1742fe12017-12-13 19:40:49 +090047import android.util.Slog;
48
Erik Kline1742fe12017-12-13 19:40:49 +090049import java.net.InetAddress;
Erik Klinea24d4592018-01-11 21:07:29 +090050import java.util.Arrays;
Erik Kline1742fe12017-12-13 19:40:49 +090051import java.util.Collection;
Chalard Jeanf0f364f2018-04-11 18:58:52 +090052import java.util.Collections;
Erik Klinea24d4592018-01-11 21:07:29 +090053import java.util.HashMap;
dalyk1fcb7392018-03-05 12:42:22 -050054import java.util.HashSet;
55import java.util.Iterator;
Erik Klinea24d4592018-01-11 21:07:29 +090056import java.util.Map;
dalyk1fcb7392018-03-05 12:42:22 -050057import java.util.Set;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090058import java.util.stream.Collectors;
Erik Kline1742fe12017-12-13 19:40:49 +090059
60
61/**
62 * Encapsulate the management of DNS settings for networks.
63 *
64 * This class it NOT designed for concurrent access. Furthermore, all non-static
65 * methods MUST be called from ConnectivityService's thread.
66 *
Erik Kline79c6d052018-03-21 07:18:33 -070067 * [ Private DNS ]
68 * The code handling Private DNS is spread across several components, but this
69 * seems like the least bad place to collect all the observations.
70 *
71 * Private DNS handling and updating occurs in response to several different
72 * events. Each is described here with its corresponding intended handling.
73 *
74 * [A] Event: A new network comes up.
75 * Mechanics:
76 * [1] ConnectivityService gets notifications from NetworkAgents.
77 * [2] in updateNetworkInfo(), the first time the NetworkAgent goes into
78 * into CONNECTED state, the Private DNS configuration is retrieved,
79 * programmed, and strict mode hostname resolution (if applicable) is
80 * enqueued in NetworkAgent's NetworkMonitor, via a call to
81 * handlePerNetworkPrivateDnsConfig().
82 * [3] Re-resolution of strict mode hostnames that fail to return any
83 * IP addresses happens inside NetworkMonitor; it sends itself a
84 * delayed CMD_EVALUATE_PRIVATE_DNS message in a simple backoff
85 * schedule.
86 * [4] Successfully resolved hostnames are sent to ConnectivityService
87 * inside an EVENT_PRIVATE_DNS_CONFIG_RESOLVED message. The resolved
88 * IP addresses are programmed into netd via:
89 *
90 * updatePrivateDns() -> updateDnses()
91 *
92 * both of which make calls into DnsManager.
93 * [5] Upon a successful hostname resolution NetworkMonitor initiates a
94 * validation attempt in the form of a lookup for a one-time hostname
95 * that uses Private DNS.
96 *
97 * [B] Event: Private DNS settings are changed.
98 * Mechanics:
99 * [1] ConnectivityService gets notifications from its SettingsObserver.
100 * [2] handlePrivateDnsSettingsChanged() is called, which calls
101 * handlePerNetworkPrivateDnsConfig() and the process proceeds
102 * as if from A.3 above.
103 *
104 * [C] Event: An application calls ConnectivityManager#reportBadNetwork().
105 * Mechanics:
106 * [1] NetworkMonitor is notified and initiates a reevaluation, which
107 * always bypasses Private DNS.
108 * [2] Once completed, NetworkMonitor checks if strict mode is in operation
109 * and if so enqueues another evaluation of Private DNS, as if from
110 * step A.5 above.
111 *
Erik Kline1742fe12017-12-13 19:40:49 +0900112 * @hide
113 */
114public class DnsManager {
115 private static final String TAG = DnsManager.class.getSimpleName();
dalyk1fcb7392018-03-05 12:42:22 -0500116 private static final PrivateDnsConfig PRIVATE_DNS_OFF = new PrivateDnsConfig();
Erik Kline1742fe12017-12-13 19:40:49 +0900117
118 /* Defaults for resolver parameters. */
119 private static final int DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS = 1800;
120 private static final int DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT = 25;
121 private static final int DNS_RESOLVER_DEFAULT_MIN_SAMPLES = 8;
122 private static final int DNS_RESOLVER_DEFAULT_MAX_SAMPLES = 64;
123
Erik Klinea24d4592018-01-11 21:07:29 +0900124 public static PrivateDnsConfig getPrivateDnsConfig(ContentResolver cr) {
125 final String mode = getPrivateDnsMode(cr);
126
127 final boolean useTls = !TextUtils.isEmpty(mode) && !PRIVATE_DNS_MODE_OFF.equals(mode);
128
129 if (PRIVATE_DNS_MODE_PROVIDER_HOSTNAME.equals(mode)) {
130 final String specifier = getStringSetting(cr, PRIVATE_DNS_SPECIFIER);
131 return new PrivateDnsConfig(specifier, null);
132 }
133
134 return new PrivateDnsConfig(useTls);
135 }
136
Erik Klinea24d4592018-01-11 21:07:29 +0900137 public static Uri[] getPrivateDnsSettingsUris() {
Erik Klinec43d2f52018-03-21 07:18:33 -0700138 return new Uri[]{
Erik Kline19841792018-05-16 16:41:57 +0900139 Settings.Global.getUriFor(PRIVATE_DNS_DEFAULT_MODE),
Erik Klinec43d2f52018-03-21 07:18:33 -0700140 Settings.Global.getUriFor(PRIVATE_DNS_MODE),
141 Settings.Global.getUriFor(PRIVATE_DNS_SPECIFIER),
142 };
Erik Klinea24d4592018-01-11 21:07:29 +0900143 }
144
dalyk1fcb7392018-03-05 12:42:22 -0500145 public static class PrivateDnsValidationUpdate {
146 final public int netId;
147 final public InetAddress ipAddress;
148 final public String hostname;
149 final public boolean validated;
150
151 public PrivateDnsValidationUpdate(int netId, InetAddress ipAddress,
152 String hostname, boolean validated) {
153 this.netId = netId;
154 this.ipAddress = ipAddress;
155 this.hostname = hostname;
156 this.validated = validated;
157 }
158 }
159
160 private static class PrivateDnsValidationStatuses {
161 enum ValidationStatus {
162 IN_PROGRESS,
163 FAILED,
164 SUCCEEDED
165 }
166
167 // Validation statuses of <hostname, ipAddress> pairs for a single netId
Chalard Jeanf0f364f2018-04-11 18:58:52 +0900168 // Caution : not thread-safe. As mentioned in the top file comment, all
169 // methods of this class must only be called on ConnectivityService's thread.
dalyk1fcb7392018-03-05 12:42:22 -0500170 private Map<Pair<String, InetAddress>, ValidationStatus> mValidationMap;
171
172 private PrivateDnsValidationStatuses() {
173 mValidationMap = new HashMap<>();
174 }
175
176 private boolean hasValidatedServer() {
177 for (ValidationStatus status : mValidationMap.values()) {
178 if (status == ValidationStatus.SUCCEEDED) {
179 return true;
180 }
181 }
182 return false;
183 }
184
185 private void updateTrackedDnses(String[] ipAddresses, String hostname) {
186 Set<Pair<String, InetAddress>> latestDnses = new HashSet<>();
187 for (String ipAddress : ipAddresses) {
188 try {
189 latestDnses.add(new Pair(hostname,
190 InetAddress.parseNumericAddress(ipAddress)));
191 } catch (IllegalArgumentException e) {}
192 }
193 // Remove <hostname, ipAddress> pairs that should not be tracked.
194 for (Iterator<Map.Entry<Pair<String, InetAddress>, ValidationStatus>> it =
195 mValidationMap.entrySet().iterator(); it.hasNext(); ) {
196 Map.Entry<Pair<String, InetAddress>, ValidationStatus> entry = it.next();
197 if (!latestDnses.contains(entry.getKey())) {
198 it.remove();
199 }
200 }
201 // Add new <hostname, ipAddress> pairs that should be tracked.
202 for (Pair<String, InetAddress> p : latestDnses) {
203 if (!mValidationMap.containsKey(p)) {
204 mValidationMap.put(p, ValidationStatus.IN_PROGRESS);
205 }
206 }
207 }
208
209 private void updateStatus(PrivateDnsValidationUpdate update) {
210 Pair<String, InetAddress> p = new Pair(update.hostname,
211 update.ipAddress);
212 if (!mValidationMap.containsKey(p)) {
213 return;
214 }
215 if (update.validated) {
216 mValidationMap.put(p, ValidationStatus.SUCCEEDED);
217 } else {
218 mValidationMap.put(p, ValidationStatus.FAILED);
219 }
220 }
Chalard Jeanf0f364f2018-04-11 18:58:52 +0900221
222 private LinkProperties fillInValidatedPrivateDns(LinkProperties lp) {
223 lp.setValidatedPrivateDnsServers(Collections.EMPTY_LIST);
224 mValidationMap.forEach((key, value) -> {
225 if (value == ValidationStatus.SUCCEEDED) {
226 lp.addValidatedPrivateDnsServer(key.second);
227 }
228 });
229 return lp;
230 }
dalyk1fcb7392018-03-05 12:42:22 -0500231 }
232
Erik Kline1742fe12017-12-13 19:40:49 +0900233 private final Context mContext;
234 private final ContentResolver mContentResolver;
Luke Huang65914772019-03-16 00:31:46 +0800235 private final IDnsResolver mDnsResolver;
Erik Kline1742fe12017-12-13 19:40:49 +0900236 private final MockableSystemProperties mSystemProperties;
dalyk1fcb7392018-03-05 12:42:22 -0500237 // TODO: Replace these Maps with SparseArrays.
Erik Klinea24d4592018-01-11 21:07:29 +0900238 private final Map<Integer, PrivateDnsConfig> mPrivateDnsMap;
dalyk1fcb7392018-03-05 12:42:22 -0500239 private final Map<Integer, PrivateDnsValidationStatuses> mPrivateDnsValidationMap;
Erik Kline1742fe12017-12-13 19:40:49 +0900240
241 private int mNumDnsEntries;
242 private int mSampleValidity;
243 private int mSuccessThreshold;
244 private int mMinSamples;
245 private int mMaxSamples;
246 private String mPrivateDnsMode;
247 private String mPrivateDnsSpecifier;
248
Luke Huang65914772019-03-16 00:31:46 +0800249 public DnsManager(Context ctx, IDnsResolver dnsResolver, MockableSystemProperties sp) {
Erik Kline1742fe12017-12-13 19:40:49 +0900250 mContext = ctx;
251 mContentResolver = mContext.getContentResolver();
Luke Huang65914772019-03-16 00:31:46 +0800252 mDnsResolver = dnsResolver;
Erik Kline1742fe12017-12-13 19:40:49 +0900253 mSystemProperties = sp;
Erik Klinea24d4592018-01-11 21:07:29 +0900254 mPrivateDnsMap = new HashMap<>();
dalyk1fcb7392018-03-05 12:42:22 -0500255 mPrivateDnsValidationMap = new HashMap<>();
Erik Kline1742fe12017-12-13 19:40:49 +0900256
257 // TODO: Create and register ContentObservers to track every setting
258 // used herein, posting messages to respond to changes.
259 }
260
Erik Klinea24d4592018-01-11 21:07:29 +0900261 public PrivateDnsConfig getPrivateDnsConfig() {
262 return getPrivateDnsConfig(mContentResolver);
263 }
264
265 public void removeNetwork(Network network) {
Luke Huang65914772019-03-16 00:31:46 +0800266 try {
267 mDnsResolver.clearResolverConfiguration(network.netId);
268 } catch (RemoteException | ServiceSpecificException e) {
269 Slog.e(TAG, "Error clearing DNS configuration: " + e);
270 return;
271 }
Erik Klinea24d4592018-01-11 21:07:29 +0900272 mPrivateDnsMap.remove(network.netId);
dalyk1fcb7392018-03-05 12:42:22 -0500273 mPrivateDnsValidationMap.remove(network.netId);
Erik Klinea24d4592018-01-11 21:07:29 +0900274 }
275
276 public PrivateDnsConfig updatePrivateDns(Network network, PrivateDnsConfig cfg) {
277 Slog.w(TAG, "updatePrivateDns(" + network + ", " + cfg + ")");
278 return (cfg != null)
279 ? mPrivateDnsMap.put(network.netId, cfg)
Andreas Gampeba061332018-03-05 17:23:07 -0800280 : mPrivateDnsMap.remove(network.netId);
Erik Kline1742fe12017-12-13 19:40:49 +0900281 }
282
dalyk1fcb7392018-03-05 12:42:22 -0500283 public void updatePrivateDnsStatus(int netId, LinkProperties lp) {
284 // Use the PrivateDnsConfig data pushed to this class instance
285 // from ConnectivityService.
286 final PrivateDnsConfig privateDnsCfg = mPrivateDnsMap.getOrDefault(netId,
287 PRIVATE_DNS_OFF);
288
289 final boolean useTls = privateDnsCfg.useTls;
Chalard Jeanf0f364f2018-04-11 18:58:52 +0900290 final PrivateDnsValidationStatuses statuses =
291 useTls ? mPrivateDnsValidationMap.get(netId) : null;
292 final boolean validated = (null != statuses) && statuses.hasValidatedServer();
dalyk1fcb7392018-03-05 12:42:22 -0500293 final boolean strictMode = privateDnsCfg.inStrictMode();
Chalard Jeanf0f364f2018-04-11 18:58:52 +0900294 final String tlsHostname = strictMode ? privateDnsCfg.hostname : null;
295 final boolean usingPrivateDns = strictMode || validated;
dalyk1fcb7392018-03-05 12:42:22 -0500296
Chalard Jeanf0f364f2018-04-11 18:58:52 +0900297 lp.setUsePrivateDns(usingPrivateDns);
298 lp.setPrivateDnsServerName(tlsHostname);
299 if (usingPrivateDns && null != statuses) {
300 statuses.fillInValidatedPrivateDns(lp);
dalyk1fcb7392018-03-05 12:42:22 -0500301 } else {
Chalard Jeanf0f364f2018-04-11 18:58:52 +0900302 lp.setValidatedPrivateDnsServers(Collections.EMPTY_LIST);
dalyk1fcb7392018-03-05 12:42:22 -0500303 }
304 }
305
306 public void updatePrivateDnsValidation(PrivateDnsValidationUpdate update) {
307 final PrivateDnsValidationStatuses statuses =
308 mPrivateDnsValidationMap.get(update.netId);
309 if (statuses == null) return;
310 statuses.updateStatus(update);
311 }
312
Erik Kline1742fe12017-12-13 19:40:49 +0900313 public void setDnsConfigurationForNetwork(
Erik Klinea24d4592018-01-11 21:07:29 +0900314 int netId, LinkProperties lp, boolean isDefaultNetwork) {
Erik Kline117e7f32018-03-04 21:01:01 +0900315
316 updateParametersSettings();
Wayne Ma28417f42019-04-17 08:03:59 -0700317 final ResolverParamsParcel paramsParcel = new ResolverParamsParcel();
Erik Kline117e7f32018-03-04 21:01:01 +0900318
Erik Klinea24d4592018-01-11 21:07:29 +0900319 // We only use the PrivateDnsConfig data pushed to this class instance
320 // from ConnectivityService because it works in coordination with
321 // NetworkMonitor to decide which networks need validation and runs the
322 // blocking calls to resolve Private DNS strict mode hostnames.
323 //
Erik Klinec43d2f52018-03-21 07:18:33 -0700324 // At this time we do not attempt to enable Private DNS on non-Internet
Erik Klinea24d4592018-01-11 21:07:29 +0900325 // networks like IMS.
dalyk1fcb7392018-03-05 12:42:22 -0500326 final PrivateDnsConfig privateDnsCfg = mPrivateDnsMap.getOrDefault(netId,
327 PRIVATE_DNS_OFF);
Erik Kline1742fe12017-12-13 19:40:49 +0900328
dalyk1fcb7392018-03-05 12:42:22 -0500329 final boolean useTls = privateDnsCfg.useTls;
330 final boolean strictMode = privateDnsCfg.inStrictMode();
Wayne Ma28417f42019-04-17 08:03:59 -0700331 paramsParcel.netId = netId;
332 paramsParcel.sampleValiditySeconds = mSampleValidity;
333 paramsParcel.successThreshold = mSuccessThreshold;
334 paramsParcel.minSamples = mMinSamples;
335 paramsParcel.maxSamples = mMaxSamples;
336 paramsParcel.servers = NetworkUtils.makeStrings(lp.getDnsServers());
337 paramsParcel.domains = getDomainStrings(lp.getDomains());
338 paramsParcel.tlsName = strictMode ? privateDnsCfg.hostname : "";
339 paramsParcel.tlsServers =
Erik Kline117e7f32018-03-04 21:01:01 +0900340 strictMode ? NetworkUtils.makeStrings(
341 Arrays.stream(privateDnsCfg.ips)
342 .filter((ip) -> lp.isReachable(ip))
343 .collect(Collectors.toList()))
Wayne Ma28417f42019-04-17 08:03:59 -0700344 : useTls ? paramsParcel.servers // Opportunistic
Erik Kline117e7f32018-03-04 21:01:01 +0900345 : new String[0]; // Off
Wayne Ma28417f42019-04-17 08:03:59 -0700346 paramsParcel.tlsFingerprints = new String[0];
dalyk1fcb7392018-03-05 12:42:22 -0500347 // Prepare to track the validation status of the DNS servers in the
348 // resolver config when private DNS is in opportunistic or strict mode.
349 if (useTls) {
350 if (!mPrivateDnsValidationMap.containsKey(netId)) {
351 mPrivateDnsValidationMap.put(netId, new PrivateDnsValidationStatuses());
352 }
Wayne Ma28417f42019-04-17 08:03:59 -0700353 mPrivateDnsValidationMap.get(netId).updateTrackedDnses(paramsParcel.tlsServers,
354 paramsParcel.tlsName);
dalyk1fcb7392018-03-05 12:42:22 -0500355 } else {
356 mPrivateDnsValidationMap.remove(netId);
357 }
358
Wayne Ma28417f42019-04-17 08:03:59 -0700359 Slog.d(TAG, String.format("setDnsConfigurationForNetwork(%d, %s, %s, %d, %d, %d, %d, "
360 + "%d, %d, %s, %s)", paramsParcel.netId, Arrays.toString(paramsParcel.servers),
361 Arrays.toString(paramsParcel.domains), paramsParcel.sampleValiditySeconds,
362 paramsParcel.successThreshold, paramsParcel.minSamples,
363 paramsParcel.maxSamples, paramsParcel.baseTimeoutMsec,
364 paramsParcel.retryCount, paramsParcel.tlsName,
365 Arrays.toString(paramsParcel.tlsServers)));
366
Erik Kline1742fe12017-12-13 19:40:49 +0900367 try {
Wayne Ma28417f42019-04-17 08:03:59 -0700368 mDnsResolver.setResolverConfiguration(paramsParcel);
Luke Huang65914772019-03-16 00:31:46 +0800369 } catch (RemoteException | ServiceSpecificException e) {
Erik Kline1742fe12017-12-13 19:40:49 +0900370 Slog.e(TAG, "Error setting DNS configuration: " + e);
371 return;
372 }
373
374 // TODO: netd should listen on [::1]:53 and proxy queries to the current
375 // default network, and we should just set net.dns1 to ::1, not least
376 // because applications attempting to use net.dns resolvers will bypass
377 // the privacy protections of things like DNS-over-TLS.
Erik Klinea24d4592018-01-11 21:07:29 +0900378 if (isDefaultNetwork) setDefaultDnsSystemProperties(lp.getDnsServers());
Erik Kline1742fe12017-12-13 19:40:49 +0900379 flushVmDnsCache();
380 }
381
382 public void setDefaultDnsSystemProperties(Collection<InetAddress> dnses) {
383 int last = 0;
384 for (InetAddress dns : dnses) {
385 ++last;
386 setNetDnsProperty(last, dns.getHostAddress());
387 }
388 for (int i = last + 1; i <= mNumDnsEntries; ++i) {
389 setNetDnsProperty(i, "");
390 }
391 mNumDnsEntries = last;
392 }
393
394 private void flushVmDnsCache() {
395 /*
396 * Tell the VMs to toss their DNS caches
397 */
398 final Intent intent = new Intent(Intent.ACTION_CLEAR_DNS_CACHE);
399 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
400 /*
401 * Connectivity events can happen before boot has completed ...
402 */
403 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
404 final long ident = Binder.clearCallingIdentity();
405 try {
406 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
407 } finally {
408 Binder.restoreCallingIdentity(ident);
409 }
410 }
411
Erik Kline1742fe12017-12-13 19:40:49 +0900412 private void updateParametersSettings() {
413 mSampleValidity = getIntSetting(
414 DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS,
415 DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
416 if (mSampleValidity < 0 || mSampleValidity > 65535) {
417 Slog.w(TAG, "Invalid sampleValidity=" + mSampleValidity + ", using default=" +
418 DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
419 mSampleValidity = DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS;
420 }
421
422 mSuccessThreshold = getIntSetting(
423 DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT,
424 DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
425 if (mSuccessThreshold < 0 || mSuccessThreshold > 100) {
426 Slog.w(TAG, "Invalid successThreshold=" + mSuccessThreshold + ", using default=" +
427 DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
428 mSuccessThreshold = DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT;
429 }
430
431 mMinSamples = getIntSetting(DNS_RESOLVER_MIN_SAMPLES, DNS_RESOLVER_DEFAULT_MIN_SAMPLES);
432 mMaxSamples = getIntSetting(DNS_RESOLVER_MAX_SAMPLES, DNS_RESOLVER_DEFAULT_MAX_SAMPLES);
433 if (mMinSamples < 0 || mMinSamples > mMaxSamples || mMaxSamples > 64) {
434 Slog.w(TAG, "Invalid sample count (min, max)=(" + mMinSamples + ", " + mMaxSamples +
435 "), using default=(" + DNS_RESOLVER_DEFAULT_MIN_SAMPLES + ", " +
436 DNS_RESOLVER_DEFAULT_MAX_SAMPLES + ")");
437 mMinSamples = DNS_RESOLVER_DEFAULT_MIN_SAMPLES;
438 mMaxSamples = DNS_RESOLVER_DEFAULT_MAX_SAMPLES;
439 }
440 }
441
Erik Kline1742fe12017-12-13 19:40:49 +0900442 private int getIntSetting(String which, int dflt) {
443 return Settings.Global.getInt(mContentResolver, which, dflt);
444 }
445
446 private void setNetDnsProperty(int which, String value) {
447 final String key = "net.dns" + which;
448 // Log and forget errors setting unsupported properties.
449 try {
450 mSystemProperties.set(key, value);
451 } catch (Exception e) {
452 Slog.e(TAG, "Error setting unsupported net.dns property: ", e);
453 }
454 }
455
Erik Klinea24d4592018-01-11 21:07:29 +0900456 private static String getPrivateDnsMode(ContentResolver cr) {
Erik Kline19841792018-05-16 16:41:57 +0900457 String mode = getStringSetting(cr, PRIVATE_DNS_MODE);
458 if (TextUtils.isEmpty(mode)) mode = getStringSetting(cr, PRIVATE_DNS_DEFAULT_MODE);
459 if (TextUtils.isEmpty(mode)) mode = PRIVATE_DNS_DEFAULT_MODE_FALLBACK;
460 return mode;
Erik Klinea24d4592018-01-11 21:07:29 +0900461 }
462
463 private static String getStringSetting(ContentResolver cr, String which) {
464 return Settings.Global.getString(cr, which);
465 }
466
467 private static String[] getDomainStrings(String domains) {
468 return (TextUtils.isEmpty(domains)) ? new String[0] : domains.split(" ");
Erik Kline1742fe12017-12-13 19:40:49 +0900469 }
470}