blob: cf6a7f6e8d7053071fbee060614e4908b664f122 [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
chenbruce5d955622020-02-20 14:28:31 +080030import android.annotation.NonNull;
Erik Kline1742fe12017-12-13 19:40:49 +090031import android.content.ContentResolver;
32import android.content.Context;
33import android.content.Intent;
Luke Huang65914772019-03-16 00:31:46 +080034import android.net.IDnsResolver;
Erik Klinea24d4592018-01-11 21:07:29 +090035import android.net.LinkProperties;
36import android.net.Network;
Erik Kline1742fe12017-12-13 19:40:49 +090037import android.net.NetworkUtils;
chenbruce5d955622020-02-20 14:28:31 +080038import android.net.ResolverOptionsParcel;
waynema13516842019-03-12 18:13:49 +080039import android.net.ResolverParamsParcel;
Erik Klinea24d4592018-01-11 21:07:29 +090040import android.net.Uri;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090041import android.net.shared.PrivateDnsConfig;
Erik Kline1742fe12017-12-13 19:40:49 +090042import android.os.Binder;
Luke Huang65914772019-03-16 00:31:46 +080043import android.os.RemoteException;
44import android.os.ServiceSpecificException;
Erik Kline1742fe12017-12-13 19:40:49 +090045import android.os.UserHandle;
46import android.provider.Settings;
47import android.text.TextUtils;
dalyk1fcb7392018-03-05 12:42:22 -050048import android.util.Pair;
Erik Kline1742fe12017-12-13 19:40:49 +090049import android.util.Slog;
50
Erik Kline1742fe12017-12-13 19:40:49 +090051import java.net.InetAddress;
Erik Klinea24d4592018-01-11 21:07:29 +090052import java.util.Arrays;
Erik Kline1742fe12017-12-13 19:40:49 +090053import java.util.Collection;
Chalard Jeanf0f364f2018-04-11 18:58:52 +090054import java.util.Collections;
Erik Klinea24d4592018-01-11 21:07:29 +090055import java.util.HashMap;
dalyk1fcb7392018-03-05 12:42:22 -050056import java.util.HashSet;
57import java.util.Iterator;
Erik Klinea24d4592018-01-11 21:07:29 +090058import java.util.Map;
dalyk1fcb7392018-03-05 12:42:22 -050059import java.util.Set;
Mike Yu1a5e45e2020-06-22 06:56:39 +000060import java.util.concurrent.ConcurrentHashMap;
Remi NGUYEN VANe67b0c32018-12-27 16:43:56 +090061import java.util.stream.Collectors;
Erik Kline1742fe12017-12-13 19:40:49 +090062
63
64/**
65 * Encapsulate the management of DNS settings for networks.
66 *
67 * This class it NOT designed for concurrent access. Furthermore, all non-static
Mike Yu1a5e45e2020-06-22 06:56:39 +000068 * methods MUST be called from ConnectivityService's thread. However, an exceptional
69 * case is getPrivateDnsConfig(Network) which is exclusively for
70 * ConnectivityService#dumpNetworkDiagnostics() on a random binder thread.
Erik Kline1742fe12017-12-13 19:40:49 +090071 *
Erik Kline79c6d052018-03-21 07:18:33 -070072 * [ Private DNS ]
73 * The code handling Private DNS is spread across several components, but this
74 * seems like the least bad place to collect all the observations.
75 *
76 * Private DNS handling and updating occurs in response to several different
77 * events. Each is described here with its corresponding intended handling.
78 *
79 * [A] Event: A new network comes up.
80 * Mechanics:
81 * [1] ConnectivityService gets notifications from NetworkAgents.
82 * [2] in updateNetworkInfo(), the first time the NetworkAgent goes into
83 * into CONNECTED state, the Private DNS configuration is retrieved,
84 * programmed, and strict mode hostname resolution (if applicable) is
85 * enqueued in NetworkAgent's NetworkMonitor, via a call to
86 * handlePerNetworkPrivateDnsConfig().
87 * [3] Re-resolution of strict mode hostnames that fail to return any
88 * IP addresses happens inside NetworkMonitor; it sends itself a
89 * delayed CMD_EVALUATE_PRIVATE_DNS message in a simple backoff
90 * schedule.
91 * [4] Successfully resolved hostnames are sent to ConnectivityService
92 * inside an EVENT_PRIVATE_DNS_CONFIG_RESOLVED message. The resolved
93 * IP addresses are programmed into netd via:
94 *
95 * updatePrivateDns() -> updateDnses()
96 *
97 * both of which make calls into DnsManager.
98 * [5] Upon a successful hostname resolution NetworkMonitor initiates a
99 * validation attempt in the form of a lookup for a one-time hostname
100 * that uses Private DNS.
101 *
102 * [B] Event: Private DNS settings are changed.
103 * Mechanics:
104 * [1] ConnectivityService gets notifications from its SettingsObserver.
105 * [2] handlePrivateDnsSettingsChanged() is called, which calls
106 * handlePerNetworkPrivateDnsConfig() and the process proceeds
107 * as if from A.3 above.
108 *
109 * [C] Event: An application calls ConnectivityManager#reportBadNetwork().
110 * Mechanics:
111 * [1] NetworkMonitor is notified and initiates a reevaluation, which
112 * always bypasses Private DNS.
113 * [2] Once completed, NetworkMonitor checks if strict mode is in operation
114 * and if so enqueues another evaluation of Private DNS, as if from
115 * step A.5 above.
116 *
Erik Kline1742fe12017-12-13 19:40:49 +0900117 * @hide
118 */
119public class DnsManager {
120 private static final String TAG = DnsManager.class.getSimpleName();
dalyk1fcb7392018-03-05 12:42:22 -0500121 private static final PrivateDnsConfig PRIVATE_DNS_OFF = new PrivateDnsConfig();
Erik Kline1742fe12017-12-13 19:40:49 +0900122
123 /* Defaults for resolver parameters. */
124 private static final int DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS = 1800;
125 private static final int DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT = 25;
126 private static final int DNS_RESOLVER_DEFAULT_MIN_SAMPLES = 8;
127 private static final int DNS_RESOLVER_DEFAULT_MAX_SAMPLES = 64;
128
Erik Klinea24d4592018-01-11 21:07:29 +0900129 public static PrivateDnsConfig getPrivateDnsConfig(ContentResolver cr) {
130 final String mode = getPrivateDnsMode(cr);
131
132 final boolean useTls = !TextUtils.isEmpty(mode) && !PRIVATE_DNS_MODE_OFF.equals(mode);
133
134 if (PRIVATE_DNS_MODE_PROVIDER_HOSTNAME.equals(mode)) {
135 final String specifier = getStringSetting(cr, PRIVATE_DNS_SPECIFIER);
136 return new PrivateDnsConfig(specifier, null);
137 }
138
139 return new PrivateDnsConfig(useTls);
140 }
141
Erik Klinea24d4592018-01-11 21:07:29 +0900142 public static Uri[] getPrivateDnsSettingsUris() {
Erik Klinec43d2f52018-03-21 07:18:33 -0700143 return new Uri[]{
Erik Kline19841792018-05-16 16:41:57 +0900144 Settings.Global.getUriFor(PRIVATE_DNS_DEFAULT_MODE),
Erik Klinec43d2f52018-03-21 07:18:33 -0700145 Settings.Global.getUriFor(PRIVATE_DNS_MODE),
146 Settings.Global.getUriFor(PRIVATE_DNS_SPECIFIER),
147 };
Erik Klinea24d4592018-01-11 21:07:29 +0900148 }
149
dalyk1fcb7392018-03-05 12:42:22 -0500150 public static class PrivateDnsValidationUpdate {
151 final public int netId;
152 final public InetAddress ipAddress;
153 final public String hostname;
154 final public boolean validated;
155
156 public PrivateDnsValidationUpdate(int netId, InetAddress ipAddress,
157 String hostname, boolean validated) {
158 this.netId = netId;
159 this.ipAddress = ipAddress;
160 this.hostname = hostname;
161 this.validated = validated;
162 }
163 }
164
165 private static class PrivateDnsValidationStatuses {
166 enum ValidationStatus {
167 IN_PROGRESS,
168 FAILED,
169 SUCCEEDED
170 }
171
172 // Validation statuses of <hostname, ipAddress> pairs for a single netId
Chalard Jeanf0f364f2018-04-11 18:58:52 +0900173 // Caution : not thread-safe. As mentioned in the top file comment, all
174 // methods of this class must only be called on ConnectivityService's thread.
dalyk1fcb7392018-03-05 12:42:22 -0500175 private Map<Pair<String, InetAddress>, ValidationStatus> mValidationMap;
176
177 private PrivateDnsValidationStatuses() {
178 mValidationMap = new HashMap<>();
179 }
180
181 private boolean hasValidatedServer() {
182 for (ValidationStatus status : mValidationMap.values()) {
183 if (status == ValidationStatus.SUCCEEDED) {
184 return true;
185 }
186 }
187 return false;
188 }
189
190 private void updateTrackedDnses(String[] ipAddresses, String hostname) {
191 Set<Pair<String, InetAddress>> latestDnses = new HashSet<>();
192 for (String ipAddress : ipAddresses) {
193 try {
194 latestDnses.add(new Pair(hostname,
195 InetAddress.parseNumericAddress(ipAddress)));
196 } catch (IllegalArgumentException e) {}
197 }
198 // Remove <hostname, ipAddress> pairs that should not be tracked.
199 for (Iterator<Map.Entry<Pair<String, InetAddress>, ValidationStatus>> it =
200 mValidationMap.entrySet().iterator(); it.hasNext(); ) {
201 Map.Entry<Pair<String, InetAddress>, ValidationStatus> entry = it.next();
202 if (!latestDnses.contains(entry.getKey())) {
203 it.remove();
204 }
205 }
206 // Add new <hostname, ipAddress> pairs that should be tracked.
207 for (Pair<String, InetAddress> p : latestDnses) {
208 if (!mValidationMap.containsKey(p)) {
209 mValidationMap.put(p, ValidationStatus.IN_PROGRESS);
210 }
211 }
212 }
213
214 private void updateStatus(PrivateDnsValidationUpdate update) {
215 Pair<String, InetAddress> p = new Pair(update.hostname,
216 update.ipAddress);
217 if (!mValidationMap.containsKey(p)) {
218 return;
219 }
220 if (update.validated) {
221 mValidationMap.put(p, ValidationStatus.SUCCEEDED);
222 } else {
223 mValidationMap.put(p, ValidationStatus.FAILED);
224 }
225 }
Chalard Jeanf0f364f2018-04-11 18:58:52 +0900226
227 private LinkProperties fillInValidatedPrivateDns(LinkProperties lp) {
228 lp.setValidatedPrivateDnsServers(Collections.EMPTY_LIST);
229 mValidationMap.forEach((key, value) -> {
230 if (value == ValidationStatus.SUCCEEDED) {
231 lp.addValidatedPrivateDnsServer(key.second);
232 }
233 });
234 return lp;
235 }
dalyk1fcb7392018-03-05 12:42:22 -0500236 }
237
Erik Kline1742fe12017-12-13 19:40:49 +0900238 private final Context mContext;
239 private final ContentResolver mContentResolver;
Luke Huang65914772019-03-16 00:31:46 +0800240 private final IDnsResolver mDnsResolver;
Erik Kline1742fe12017-12-13 19:40:49 +0900241 private final MockableSystemProperties mSystemProperties;
Mike Yu1a5e45e2020-06-22 06:56:39 +0000242 private final ConcurrentHashMap<Integer, PrivateDnsConfig> mPrivateDnsMap;
243 // TODO: Replace the Map with SparseArrays.
dalyk1fcb7392018-03-05 12:42:22 -0500244 private final Map<Integer, PrivateDnsValidationStatuses> mPrivateDnsValidationMap;
chenbruce5d955622020-02-20 14:28:31 +0800245 private final Map<Integer, LinkProperties> mLinkPropertiesMap;
246 private final Map<Integer, int[]> mTransportsMap;
Erik Kline1742fe12017-12-13 19:40:49 +0900247
248 private int mNumDnsEntries;
249 private int mSampleValidity;
250 private int mSuccessThreshold;
251 private int mMinSamples;
252 private int mMaxSamples;
Erik Kline1742fe12017-12-13 19:40:49 +0900253
Luke Huang65914772019-03-16 00:31:46 +0800254 public DnsManager(Context ctx, IDnsResolver dnsResolver, MockableSystemProperties sp) {
Erik Kline1742fe12017-12-13 19:40:49 +0900255 mContext = ctx;
256 mContentResolver = mContext.getContentResolver();
Luke Huang65914772019-03-16 00:31:46 +0800257 mDnsResolver = dnsResolver;
Erik Kline1742fe12017-12-13 19:40:49 +0900258 mSystemProperties = sp;
Mike Yu1a5e45e2020-06-22 06:56:39 +0000259 mPrivateDnsMap = new ConcurrentHashMap<>();
dalyk1fcb7392018-03-05 12:42:22 -0500260 mPrivateDnsValidationMap = new HashMap<>();
chenbruce5d955622020-02-20 14:28:31 +0800261 mLinkPropertiesMap = new HashMap<>();
262 mTransportsMap = new HashMap<>();
Erik Kline1742fe12017-12-13 19:40:49 +0900263
264 // TODO: Create and register ContentObservers to track every setting
265 // used herein, posting messages to respond to changes.
266 }
267
Erik Klinea24d4592018-01-11 21:07:29 +0900268 public PrivateDnsConfig getPrivateDnsConfig() {
269 return getPrivateDnsConfig(mContentResolver);
270 }
271
272 public void removeNetwork(Network network) {
273 mPrivateDnsMap.remove(network.netId);
dalyk1fcb7392018-03-05 12:42:22 -0500274 mPrivateDnsValidationMap.remove(network.netId);
chenbruce5d955622020-02-20 14:28:31 +0800275 mTransportsMap.remove(network.netId);
276 mLinkPropertiesMap.remove(network.netId);
Erik Klinea24d4592018-01-11 21:07:29 +0900277 }
278
Mike Yu1a5e45e2020-06-22 06:56:39 +0000279 // This is exclusively called by ConnectivityService#dumpNetworkDiagnostics() which
280 // is not on the ConnectivityService handler thread.
281 public PrivateDnsConfig getPrivateDnsConfig(@NonNull Network network) {
282 return mPrivateDnsMap.getOrDefault(network.netId, PRIVATE_DNS_OFF);
283 }
284
Erik Klinea24d4592018-01-11 21:07:29 +0900285 public PrivateDnsConfig updatePrivateDns(Network network, PrivateDnsConfig cfg) {
286 Slog.w(TAG, "updatePrivateDns(" + network + ", " + cfg + ")");
287 return (cfg != null)
288 ? mPrivateDnsMap.put(network.netId, cfg)
Andreas Gampeba061332018-03-05 17:23:07 -0800289 : mPrivateDnsMap.remove(network.netId);
Erik Kline1742fe12017-12-13 19:40:49 +0900290 }
291
dalyk1fcb7392018-03-05 12:42:22 -0500292 public void updatePrivateDnsStatus(int netId, LinkProperties lp) {
293 // Use the PrivateDnsConfig data pushed to this class instance
294 // from ConnectivityService.
295 final PrivateDnsConfig privateDnsCfg = mPrivateDnsMap.getOrDefault(netId,
296 PRIVATE_DNS_OFF);
297
298 final boolean useTls = privateDnsCfg.useTls;
Chalard Jeanf0f364f2018-04-11 18:58:52 +0900299 final PrivateDnsValidationStatuses statuses =
300 useTls ? mPrivateDnsValidationMap.get(netId) : null;
301 final boolean validated = (null != statuses) && statuses.hasValidatedServer();
dalyk1fcb7392018-03-05 12:42:22 -0500302 final boolean strictMode = privateDnsCfg.inStrictMode();
Chalard Jeanf0f364f2018-04-11 18:58:52 +0900303 final String tlsHostname = strictMode ? privateDnsCfg.hostname : null;
304 final boolean usingPrivateDns = strictMode || validated;
dalyk1fcb7392018-03-05 12:42:22 -0500305
Chalard Jeanf0f364f2018-04-11 18:58:52 +0900306 lp.setUsePrivateDns(usingPrivateDns);
307 lp.setPrivateDnsServerName(tlsHostname);
308 if (usingPrivateDns && null != statuses) {
309 statuses.fillInValidatedPrivateDns(lp);
dalyk1fcb7392018-03-05 12:42:22 -0500310 } else {
Chalard Jeanf0f364f2018-04-11 18:58:52 +0900311 lp.setValidatedPrivateDnsServers(Collections.EMPTY_LIST);
dalyk1fcb7392018-03-05 12:42:22 -0500312 }
313 }
314
315 public void updatePrivateDnsValidation(PrivateDnsValidationUpdate update) {
316 final PrivateDnsValidationStatuses statuses =
317 mPrivateDnsValidationMap.get(update.netId);
318 if (statuses == null) return;
319 statuses.updateStatus(update);
320 }
321
chenbruce5d955622020-02-20 14:28:31 +0800322 /**
323 * When creating a new network or transport types are changed in a specific network,
324 * transport types are always saved to a hashMap before update dns config.
325 * When destroying network, the specific network will be removed from the hashMap.
326 * The hashMap is always accessed on the same thread.
327 */
328 public void updateTransportsForNetwork(int netId, @NonNull int[] transportTypes) {
329 mTransportsMap.put(netId, transportTypes);
330 sendDnsConfigurationForNetwork(netId);
331 }
Erik Kline117e7f32018-03-04 21:01:01 +0900332
chenbruce5d955622020-02-20 14:28:31 +0800333 /**
334 * When {@link LinkProperties} are changed in a specific network, they are
335 * always saved to a hashMap before update dns config.
336 * When destroying network, the specific network will be removed from the hashMap.
337 * The hashMap is always accessed on the same thread.
338 */
339 public void noteDnsServersForNetwork(int netId, @NonNull LinkProperties lp) {
340 mLinkPropertiesMap.put(netId, lp);
341 sendDnsConfigurationForNetwork(netId);
342 }
343
344 /**
345 * Send dns configuration parameters to resolver for a given network.
346 */
347 public void sendDnsConfigurationForNetwork(int netId) {
348 final LinkProperties lp = mLinkPropertiesMap.get(netId);
349 final int[] transportTypes = mTransportsMap.get(netId);
350 if (lp == null || transportTypes == null) return;
Erik Kline117e7f32018-03-04 21:01:01 +0900351 updateParametersSettings();
waynema13516842019-03-12 18:13:49 +0800352 final ResolverParamsParcel paramsParcel = new ResolverParamsParcel();
Erik Kline117e7f32018-03-04 21:01:01 +0900353
Erik Klinea24d4592018-01-11 21:07:29 +0900354 // We only use the PrivateDnsConfig data pushed to this class instance
355 // from ConnectivityService because it works in coordination with
356 // NetworkMonitor to decide which networks need validation and runs the
357 // blocking calls to resolve Private DNS strict mode hostnames.
358 //
Erik Klinec43d2f52018-03-21 07:18:33 -0700359 // At this time we do not attempt to enable Private DNS on non-Internet
Erik Klinea24d4592018-01-11 21:07:29 +0900360 // networks like IMS.
dalyk1fcb7392018-03-05 12:42:22 -0500361 final PrivateDnsConfig privateDnsCfg = mPrivateDnsMap.getOrDefault(netId,
362 PRIVATE_DNS_OFF);
dalyk1fcb7392018-03-05 12:42:22 -0500363 final boolean useTls = privateDnsCfg.useTls;
364 final boolean strictMode = privateDnsCfg.inStrictMode();
chenbruce5d955622020-02-20 14:28:31 +0800365
waynema13516842019-03-12 18:13:49 +0800366 paramsParcel.netId = netId;
367 paramsParcel.sampleValiditySeconds = mSampleValidity;
368 paramsParcel.successThreshold = mSuccessThreshold;
369 paramsParcel.minSamples = mMinSamples;
370 paramsParcel.maxSamples = mMaxSamples;
chenbruce5d955622020-02-20 14:28:31 +0800371 paramsParcel.servers =
372 NetworkUtils.makeStrings(lp.getDnsServers());
waynema13516842019-03-12 18:13:49 +0800373 paramsParcel.domains = getDomainStrings(lp.getDomains());
374 paramsParcel.tlsName = strictMode ? privateDnsCfg.hostname : "";
375 paramsParcel.tlsServers =
Erik Kline117e7f32018-03-04 21:01:01 +0900376 strictMode ? NetworkUtils.makeStrings(
377 Arrays.stream(privateDnsCfg.ips)
378 .filter((ip) -> lp.isReachable(ip))
379 .collect(Collectors.toList()))
waynema13516842019-03-12 18:13:49 +0800380 : useTls ? paramsParcel.servers // Opportunistic
Erik Kline117e7f32018-03-04 21:01:01 +0900381 : new String[0]; // Off
chenbruce5d955622020-02-20 14:28:31 +0800382 paramsParcel.resolverOptions = new ResolverOptionsParcel();
383 paramsParcel.transportTypes = transportTypes;
dalyk1fcb7392018-03-05 12:42:22 -0500384 // Prepare to track the validation status of the DNS servers in the
385 // resolver config when private DNS is in opportunistic or strict mode.
386 if (useTls) {
387 if (!mPrivateDnsValidationMap.containsKey(netId)) {
388 mPrivateDnsValidationMap.put(netId, new PrivateDnsValidationStatuses());
389 }
waynema13516842019-03-12 18:13:49 +0800390 mPrivateDnsValidationMap.get(netId).updateTrackedDnses(paramsParcel.tlsServers,
391 paramsParcel.tlsName);
dalyk1fcb7392018-03-05 12:42:22 -0500392 } else {
393 mPrivateDnsValidationMap.remove(netId);
394 }
395
chenbruce5d955622020-02-20 14:28:31 +0800396 Slog.d(TAG, String.format("sendDnsConfigurationForNetwork(%d, %s, %s, %d, %d, %d, %d, "
waynema13516842019-03-12 18:13:49 +0800397 + "%d, %d, %s, %s)", paramsParcel.netId, Arrays.toString(paramsParcel.servers),
398 Arrays.toString(paramsParcel.domains), paramsParcel.sampleValiditySeconds,
399 paramsParcel.successThreshold, paramsParcel.minSamples,
400 paramsParcel.maxSamples, paramsParcel.baseTimeoutMsec,
401 paramsParcel.retryCount, paramsParcel.tlsName,
402 Arrays.toString(paramsParcel.tlsServers)));
403
Erik Kline1742fe12017-12-13 19:40:49 +0900404 try {
waynema13516842019-03-12 18:13:49 +0800405 mDnsResolver.setResolverConfiguration(paramsParcel);
Luke Huang65914772019-03-16 00:31:46 +0800406 } catch (RemoteException | ServiceSpecificException e) {
Erik Kline1742fe12017-12-13 19:40:49 +0900407 Slog.e(TAG, "Error setting DNS configuration: " + e);
408 return;
409 }
Erik Kline1742fe12017-12-13 19:40:49 +0900410 }
411
412 public void setDefaultDnsSystemProperties(Collection<InetAddress> dnses) {
413 int last = 0;
414 for (InetAddress dns : dnses) {
415 ++last;
416 setNetDnsProperty(last, dns.getHostAddress());
417 }
418 for (int i = last + 1; i <= mNumDnsEntries; ++i) {
419 setNetDnsProperty(i, "");
420 }
421 mNumDnsEntries = last;
422 }
423
chenbruce5d955622020-02-20 14:28:31 +0800424 /**
425 * Flush DNS caches and events work before boot has completed.
426 */
427 public void flushVmDnsCache() {
Erik Kline1742fe12017-12-13 19:40:49 +0900428 /*
429 * Tell the VMs to toss their DNS caches
430 */
431 final Intent intent = new Intent(Intent.ACTION_CLEAR_DNS_CACHE);
432 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
433 /*
434 * Connectivity events can happen before boot has completed ...
435 */
436 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
437 final long ident = Binder.clearCallingIdentity();
438 try {
439 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
440 } finally {
441 Binder.restoreCallingIdentity(ident);
442 }
443 }
444
Erik Kline1742fe12017-12-13 19:40:49 +0900445 private void updateParametersSettings() {
446 mSampleValidity = getIntSetting(
447 DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS,
448 DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
449 if (mSampleValidity < 0 || mSampleValidity > 65535) {
450 Slog.w(TAG, "Invalid sampleValidity=" + mSampleValidity + ", using default=" +
451 DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
452 mSampleValidity = DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS;
453 }
454
455 mSuccessThreshold = getIntSetting(
456 DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT,
457 DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
458 if (mSuccessThreshold < 0 || mSuccessThreshold > 100) {
459 Slog.w(TAG, "Invalid successThreshold=" + mSuccessThreshold + ", using default=" +
460 DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
461 mSuccessThreshold = DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT;
462 }
463
464 mMinSamples = getIntSetting(DNS_RESOLVER_MIN_SAMPLES, DNS_RESOLVER_DEFAULT_MIN_SAMPLES);
465 mMaxSamples = getIntSetting(DNS_RESOLVER_MAX_SAMPLES, DNS_RESOLVER_DEFAULT_MAX_SAMPLES);
466 if (mMinSamples < 0 || mMinSamples > mMaxSamples || mMaxSamples > 64) {
467 Slog.w(TAG, "Invalid sample count (min, max)=(" + mMinSamples + ", " + mMaxSamples +
468 "), using default=(" + DNS_RESOLVER_DEFAULT_MIN_SAMPLES + ", " +
469 DNS_RESOLVER_DEFAULT_MAX_SAMPLES + ")");
470 mMinSamples = DNS_RESOLVER_DEFAULT_MIN_SAMPLES;
471 mMaxSamples = DNS_RESOLVER_DEFAULT_MAX_SAMPLES;
472 }
473 }
474
Erik Kline1742fe12017-12-13 19:40:49 +0900475 private int getIntSetting(String which, int dflt) {
476 return Settings.Global.getInt(mContentResolver, which, dflt);
477 }
478
479 private void setNetDnsProperty(int which, String value) {
480 final String key = "net.dns" + which;
481 // Log and forget errors setting unsupported properties.
482 try {
483 mSystemProperties.set(key, value);
484 } catch (Exception e) {
485 Slog.e(TAG, "Error setting unsupported net.dns property: ", e);
486 }
487 }
488
Erik Klinea24d4592018-01-11 21:07:29 +0900489 private static String getPrivateDnsMode(ContentResolver cr) {
Erik Kline19841792018-05-16 16:41:57 +0900490 String mode = getStringSetting(cr, PRIVATE_DNS_MODE);
491 if (TextUtils.isEmpty(mode)) mode = getStringSetting(cr, PRIVATE_DNS_DEFAULT_MODE);
492 if (TextUtils.isEmpty(mode)) mode = PRIVATE_DNS_DEFAULT_MODE_FALLBACK;
493 return mode;
Erik Klinea24d4592018-01-11 21:07:29 +0900494 }
495
496 private static String getStringSetting(ContentResolver cr, String which) {
497 return Settings.Global.getString(cr, which);
498 }
499
500 private static String[] getDomainStrings(String domains) {
501 return (TextUtils.isEmpty(domains)) ? new String[0] : domains.split(" ");
Erik Kline1742fe12017-12-13 19:40:49 +0900502 }
503}