Merge "Set transport types to resolver" am: d275ec139a

Change-Id: I26b6e523bbc6ccd6e57a1b30782b74c6c33a7fbb
This commit is contained in:
Lorenzo Colitti
2020-04-13 07:22:21 +00:00
committed by Automerger Merge Worker
4 changed files with 186 additions and 22 deletions

View File

@@ -3330,6 +3330,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
getNetworkPermission(networkAgent.networkCapabilities));
}
mDnsResolver.createNetworkCache(networkAgent.network.netId);
mDnsManager.updateTransportsForNetwork(networkAgent.network.netId,
networkAgent.networkCapabilities.getTransportTypes());
return true;
} catch (RemoteException | ServiceSpecificException e) {
loge("Error creating network " + networkAgent.network.netId + ": "
@@ -6079,7 +6081,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
log("Setting DNS servers for network " + netId + " to " + dnses);
}
try {
mDnsManager.setDnsConfigurationForNetwork(netId, newLp, isDefaultNetwork);
mDnsManager.noteDnsServersForNetwork(netId, newLp);
// TODO: netd should listen on [::1]:53 and proxy queries to the current
// default network, and we should just set net.dns1 to ::1, not least
// because applications attempting to use net.dns resolvers will bypass
// the privacy protections of things like DNS-over-TLS.
if (isDefaultNetwork) mDnsManager.setDefaultDnsSystemProperties(newLp.getDnsServers());
mDnsManager.flushVmDnsCache();
} catch (Exception e) {
loge("Exception in setDnsConfigurationForNetwork: " + e);
}
@@ -6277,6 +6285,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
// bubble those changes through.
updateAllVpnsCapabilities();
}
if (!newNc.equalsTransportTypes(prevNc)) {
mDnsManager.updateTransportsForNetwork(nai.network.netId, newNc.getTransportTypes());
}
}
/**

View File

@@ -27,6 +27,7 @@ import static android.provider.Settings.Global.PRIVATE_DNS_DEFAULT_MODE;
import static android.provider.Settings.Global.PRIVATE_DNS_MODE;
import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER;
import android.annotation.NonNull;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -34,6 +35,7 @@ import android.net.IDnsResolver;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkUtils;
import android.net.ResolverOptionsParcel;
import android.net.ResolverParamsParcel;
import android.net.Uri;
import android.net.shared.PrivateDnsConfig;
@@ -237,6 +239,8 @@ public class DnsManager {
// TODO: Replace these Maps with SparseArrays.
private final Map<Integer, PrivateDnsConfig> mPrivateDnsMap;
private final Map<Integer, PrivateDnsValidationStatuses> mPrivateDnsValidationMap;
private final Map<Integer, LinkProperties> mLinkPropertiesMap;
private final Map<Integer, int[]> mTransportsMap;
private int mNumDnsEntries;
private int mSampleValidity;
@@ -253,6 +257,8 @@ public class DnsManager {
mSystemProperties = sp;
mPrivateDnsMap = new HashMap<>();
mPrivateDnsValidationMap = new HashMap<>();
mLinkPropertiesMap = new HashMap<>();
mTransportsMap = new HashMap<>();
// TODO: Create and register ContentObservers to track every setting
// used herein, posting messages to respond to changes.
@@ -265,6 +271,8 @@ public class DnsManager {
public void removeNetwork(Network network) {
mPrivateDnsMap.remove(network.netId);
mPrivateDnsValidationMap.remove(network.netId);
mTransportsMap.remove(network.netId);
mLinkPropertiesMap.remove(network.netId);
}
public PrivateDnsConfig updatePrivateDns(Network network, PrivateDnsConfig cfg) {
@@ -304,9 +312,35 @@ public class DnsManager {
statuses.updateStatus(update);
}
public void setDnsConfigurationForNetwork(
int netId, LinkProperties lp, boolean isDefaultNetwork) {
/**
* When creating a new network or transport types are changed in a specific network,
* transport types are always saved to a hashMap before update dns config.
* When destroying network, the specific network will be removed from the hashMap.
* The hashMap is always accessed on the same thread.
*/
public void updateTransportsForNetwork(int netId, @NonNull int[] transportTypes) {
mTransportsMap.put(netId, transportTypes);
sendDnsConfigurationForNetwork(netId);
}
/**
* When {@link LinkProperties} are changed in a specific network, they are
* always saved to a hashMap before update dns config.
* When destroying network, the specific network will be removed from the hashMap.
* The hashMap is always accessed on the same thread.
*/
public void noteDnsServersForNetwork(int netId, @NonNull LinkProperties lp) {
mLinkPropertiesMap.put(netId, lp);
sendDnsConfigurationForNetwork(netId);
}
/**
* Send dns configuration parameters to resolver for a given network.
*/
public void sendDnsConfigurationForNetwork(int netId) {
final LinkProperties lp = mLinkPropertiesMap.get(netId);
final int[] transportTypes = mTransportsMap.get(netId);
if (lp == null || transportTypes == null) return;
updateParametersSettings();
final ResolverParamsParcel paramsParcel = new ResolverParamsParcel();
@@ -319,15 +353,16 @@ public class DnsManager {
// networks like IMS.
final PrivateDnsConfig privateDnsCfg = mPrivateDnsMap.getOrDefault(netId,
PRIVATE_DNS_OFF);
final boolean useTls = privateDnsCfg.useTls;
final boolean strictMode = privateDnsCfg.inStrictMode();
paramsParcel.netId = netId;
paramsParcel.sampleValiditySeconds = mSampleValidity;
paramsParcel.successThreshold = mSuccessThreshold;
paramsParcel.minSamples = mMinSamples;
paramsParcel.maxSamples = mMaxSamples;
paramsParcel.servers = NetworkUtils.makeStrings(lp.getDnsServers());
paramsParcel.servers =
NetworkUtils.makeStrings(lp.getDnsServers());
paramsParcel.domains = getDomainStrings(lp.getDomains());
paramsParcel.tlsName = strictMode ? privateDnsCfg.hostname : "";
paramsParcel.tlsServers =
@@ -337,6 +372,8 @@ public class DnsManager {
.collect(Collectors.toList()))
: useTls ? paramsParcel.servers // Opportunistic
: new String[0]; // Off
paramsParcel.resolverOptions = new ResolverOptionsParcel();
paramsParcel.transportTypes = transportTypes;
// Prepare to track the validation status of the DNS servers in the
// resolver config when private DNS is in opportunistic or strict mode.
if (useTls) {
@@ -349,7 +386,7 @@ public class DnsManager {
mPrivateDnsValidationMap.remove(netId);
}
Slog.d(TAG, String.format("setDnsConfigurationForNetwork(%d, %s, %s, %d, %d, %d, %d, "
Slog.d(TAG, String.format("sendDnsConfigurationForNetwork(%d, %s, %s, %d, %d, %d, %d, "
+ "%d, %d, %s, %s)", paramsParcel.netId, Arrays.toString(paramsParcel.servers),
Arrays.toString(paramsParcel.domains), paramsParcel.sampleValiditySeconds,
paramsParcel.successThreshold, paramsParcel.minSamples,
@@ -363,13 +400,6 @@ public class DnsManager {
Slog.e(TAG, "Error setting DNS configuration: " + e);
return;
}
// TODO: netd should listen on [::1]:53 and proxy queries to the current
// default network, and we should just set net.dns1 to ::1, not least
// because applications attempting to use net.dns resolvers will bypass
// the privacy protections of things like DNS-over-TLS.
if (isDefaultNetwork) setDefaultDnsSystemProperties(lp.getDnsServers());
flushVmDnsCache();
}
public void setDefaultDnsSystemProperties(Collection<InetAddress> dnses) {
@@ -384,7 +414,10 @@ public class DnsManager {
mNumDnsEntries = last;
}
private void flushVmDnsCache() {
/**
* Flush DNS caches and events work before boot has completed.
*/
public void flushVmDnsCache() {
/*
* Tell the VMs to toss their DNS caches
*/

View File

@@ -4907,6 +4907,29 @@ public class ConnectivityServiceTest {
reset(mMockDnsResolver);
}
@Test
public void testDnsConfigurationTransTypesPushed() throws Exception {
// Clear any interactions that occur as a result of CS starting up.
reset(mMockDnsResolver);
final NetworkRequest request = new NetworkRequest.Builder()
.clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
.build();
final TestNetworkCallback callback = new TestNetworkCallback();
mCm.registerNetworkCallback(request, callback);
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
verify(mMockDnsResolver, times(1)).createNetworkCache(
eq(mWiFiNetworkAgent.getNetwork().netId));
verify(mMockDnsResolver, times(2)).setResolverConfiguration(
mResolverParamsParcelCaptor.capture());
final ResolverParamsParcel resolverParams = mResolverParamsParcelCaptor.getValue();
assertContainsExactly(resolverParams.transportTypes, TRANSPORT_WIFI);
reset(mMockDnsResolver);
}
@Test
public void testPrivateDnsNotification() throws Exception {
NetworkRequest request = new NetworkRequest.Builder()

View File

@@ -18,22 +18,34 @@ package com.android.server.connectivity;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.provider.Settings.Global.PRIVATE_DNS_DEFAULT_MODE;
import static android.provider.Settings.Global.PRIVATE_DNS_MODE;
import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER;
import static com.android.testutils.MiscAssertsKt.assertContainsExactly;
import static com.android.testutils.MiscAssertsKt.assertContainsStringsExactly;
import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.content.Context;
import android.net.IDnsResolver;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.ResolverOptionsParcel;
import android.net.ResolverParamsParcel;
import android.net.RouteInfo;
import android.net.shared.PrivateDnsConfig;
import android.provider.Settings;
@@ -47,6 +59,7 @@ import com.android.internal.util.test.FakeSettingsProvider;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -66,8 +79,11 @@ public class DnsManagerTest {
static final int TEST_NETID = 100;
static final int TEST_NETID_ALTERNATE = 101;
static final int TEST_NETID_UNTRACKED = 102;
final boolean IS_DEFAULT = true;
final boolean NOT_DEFAULT = false;
static final int TEST_DEFAULT_SAMPLE_VALIDITY_SECONDS = 1800;
static final int TEST_DEFAULT_SUCCESS_THRESHOLD_PERCENT = 25;
static final int TEST_DEFAULT_MIN_SAMPLES = 8;
static final int TEST_DEFAULT_MAX_SAMPLES = 64;
static final int[] TEST_TRANSPORT_TYPES = {TRANSPORT_WIFI, TRANSPORT_VPN};
DnsManager mDnsManager;
MockContentResolver mContentResolver;
@@ -76,6 +92,35 @@ public class DnsManagerTest {
@Mock IDnsResolver mMockDnsResolver;
@Mock MockableSystemProperties mSystemProperties;
private void assertResolverOptionsEquals(
@NonNull ResolverOptionsParcel actual,
@NonNull ResolverOptionsParcel expected) {
assertEquals(actual.hosts, expected.hosts);
assertEquals(actual.tcMode, expected.tcMode);
assertFieldCountEquals(2, ResolverOptionsParcel.class);
}
private void assertResolverParamsEquals(@NonNull ResolverParamsParcel actual,
@NonNull ResolverParamsParcel expected) {
assertEquals(actual.netId, expected.netId);
assertEquals(actual.sampleValiditySeconds, expected.sampleValiditySeconds);
assertEquals(actual.successThreshold, expected.successThreshold);
assertEquals(actual.minSamples, expected.minSamples);
assertEquals(actual.maxSamples, expected.maxSamples);
assertEquals(actual.baseTimeoutMsec, expected.baseTimeoutMsec);
assertEquals(actual.retryCount, expected.retryCount);
assertContainsStringsExactly(actual.servers, expected.servers);
assertContainsStringsExactly(actual.domains, expected.domains);
assertEquals(actual.tlsName, expected.tlsName);
assertContainsStringsExactly(actual.tlsServers, expected.tlsServers);
assertContainsStringsExactly(actual.tlsFingerprints, expected.tlsFingerprints);
assertEquals(actual.caCertificate, expected.caCertificate);
assertEquals(actual.tlsConnectTimeoutMs, expected.tlsConnectTimeoutMs);
assertResolverOptionsEquals(actual.resolverOptions, expected.resolverOptions);
assertContainsExactly(actual.transportTypes, expected.transportTypes);
assertFieldCountEquals(16, ResolverParamsParcel.class);
}
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
@@ -103,8 +148,13 @@ public class DnsManagerTest {
lp.addDnsServer(InetAddress.getByName("4.4.4.4"));
// Send a validation event that is tracked on the alternate netId
mDnsManager.setDnsConfigurationForNetwork(TEST_NETID, lp, IS_DEFAULT);
mDnsManager.setDnsConfigurationForNetwork(TEST_NETID_ALTERNATE, lp, NOT_DEFAULT);
mDnsManager.updateTransportsForNetwork(TEST_NETID, TEST_TRANSPORT_TYPES);
mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp);
mDnsManager.setDefaultDnsSystemProperties(lp.getDnsServers());
mDnsManager.flushVmDnsCache();
mDnsManager.updateTransportsForNetwork(TEST_NETID_ALTERNATE, TEST_TRANSPORT_TYPES);
mDnsManager.noteDnsServersForNetwork(TEST_NETID_ALTERNATE, lp);
mDnsManager.flushVmDnsCache();
mDnsManager.updatePrivateDnsValidation(
new DnsManager.PrivateDnsValidationUpdate(TEST_NETID_ALTERNATE,
InetAddress.parseNumericAddress("4.4.4.4"), "", true));
@@ -135,7 +185,10 @@ public class DnsManagerTest {
InetAddress.parseNumericAddress("6.6.6.6"),
InetAddress.parseNumericAddress("2001:db8:66:66::1")
}));
mDnsManager.setDnsConfigurationForNetwork(TEST_NETID, lp, IS_DEFAULT);
mDnsManager.updateTransportsForNetwork(TEST_NETID, TEST_TRANSPORT_TYPES);
mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp);
mDnsManager.setDefaultDnsSystemProperties(lp.getDnsServers());
mDnsManager.flushVmDnsCache();
fixedLp = new LinkProperties(lp);
mDnsManager.updatePrivateDnsStatus(TEST_NETID, fixedLp);
assertTrue(fixedLp.isPrivateDnsActive());
@@ -168,7 +221,10 @@ public class DnsManagerTest {
// be tracked.
LinkProperties lp = new LinkProperties();
lp.addDnsServer(InetAddress.getByName("3.3.3.3"));
mDnsManager.setDnsConfigurationForNetwork(TEST_NETID, lp, IS_DEFAULT);
mDnsManager.updateTransportsForNetwork(TEST_NETID, TEST_TRANSPORT_TYPES);
mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp);
mDnsManager.setDefaultDnsSystemProperties(lp.getDnsServers());
mDnsManager.flushVmDnsCache();
mDnsManager.updatePrivateDnsValidation(
new DnsManager.PrivateDnsValidationUpdate(TEST_NETID,
InetAddress.parseNumericAddress("3.3.3.3"), "", true));
@@ -179,7 +235,10 @@ public class DnsManagerTest {
// Validation event has untracked netId
mDnsManager.updatePrivateDns(new Network(TEST_NETID),
mDnsManager.getPrivateDnsConfig());
mDnsManager.setDnsConfigurationForNetwork(TEST_NETID, lp, IS_DEFAULT);
mDnsManager.updateTransportsForNetwork(TEST_NETID, TEST_TRANSPORT_TYPES);
mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp);
mDnsManager.setDefaultDnsSystemProperties(lp.getDnsServers());
mDnsManager.flushVmDnsCache();
mDnsManager.updatePrivateDnsValidation(
new DnsManager.PrivateDnsValidationUpdate(TEST_NETID_UNTRACKED,
InetAddress.parseNumericAddress("3.3.3.3"), "", true));
@@ -225,7 +284,10 @@ public class DnsManagerTest {
Settings.Global.putString(mContentResolver, PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_OFF);
mDnsManager.updatePrivateDns(new Network(TEST_NETID),
mDnsManager.getPrivateDnsConfig());
mDnsManager.setDnsConfigurationForNetwork(TEST_NETID, lp, IS_DEFAULT);
mDnsManager.updateTransportsForNetwork(TEST_NETID, TEST_TRANSPORT_TYPES);
mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp);
mDnsManager.setDefaultDnsSystemProperties(lp.getDnsServers());
mDnsManager.flushVmDnsCache();
mDnsManager.updatePrivateDnsValidation(
new DnsManager.PrivateDnsValidationUpdate(TEST_NETID,
InetAddress.parseNumericAddress("3.3.3.3"), "", true));
@@ -258,4 +320,38 @@ public class DnsManagerTest {
assertEquals("strictmode.com", cfgStrict.hostname);
assertEquals(new InetAddress[0], cfgStrict.ips);
}
@Test
public void testSendDnsConfiguration() throws Exception {
reset(mMockDnsResolver);
mDnsManager.updatePrivateDns(new Network(TEST_NETID),
mDnsManager.getPrivateDnsConfig());
final LinkProperties lp = new LinkProperties();
lp.setInterfaceName(TEST_IFACENAME);
lp.addDnsServer(InetAddress.getByName("3.3.3.3"));
lp.addDnsServer(InetAddress.getByName("4.4.4.4"));
mDnsManager.updateTransportsForNetwork(TEST_NETID, TEST_TRANSPORT_TYPES);
mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp);
mDnsManager.setDefaultDnsSystemProperties(lp.getDnsServers());
mDnsManager.flushVmDnsCache();
final ArgumentCaptor<ResolverParamsParcel> resolverParamsParcelCaptor =
ArgumentCaptor.forClass(ResolverParamsParcel.class);
verify(mMockDnsResolver, times(1)).setResolverConfiguration(
resolverParamsParcelCaptor.capture());
final ResolverParamsParcel actualParams = resolverParamsParcelCaptor.getValue();
final ResolverParamsParcel expectedParams = new ResolverParamsParcel();
expectedParams.netId = TEST_NETID;
expectedParams.sampleValiditySeconds = TEST_DEFAULT_SAMPLE_VALIDITY_SECONDS;
expectedParams.successThreshold = TEST_DEFAULT_SUCCESS_THRESHOLD_PERCENT;
expectedParams.minSamples = TEST_DEFAULT_MIN_SAMPLES;
expectedParams.maxSamples = TEST_DEFAULT_MAX_SAMPLES;
expectedParams.servers = new String[]{"3.3.3.3", "4.4.4.4"};
expectedParams.domains = new String[]{};
expectedParams.tlsName = "";
expectedParams.tlsServers = new String[]{"3.3.3.3", "4.4.4.4"};
expectedParams.transportTypes = TEST_TRANSPORT_TYPES;
expectedParams.resolverOptions = new ResolverOptionsParcel();
assertResolverParamsEquals(actualParams, expectedParams);
}
}