import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
}
// Validation statuses of <hostname, ipAddress> pairs for a single netId
+ // Caution : not thread-safe. As mentioned in the top file comment, all
+ // methods of this class must only be called on ConnectivityService's thread.
private Map<Pair<String, InetAddress>, ValidationStatus> mValidationMap;
private PrivateDnsValidationStatuses() {
mValidationMap.put(p, ValidationStatus.FAILED);
}
}
+
+ private LinkProperties fillInValidatedPrivateDns(LinkProperties lp) {
+ lp.setValidatedPrivateDnsServers(Collections.EMPTY_LIST);
+ mValidationMap.forEach((key, value) -> {
+ if (value == ValidationStatus.SUCCEEDED) {
+ lp.addValidatedPrivateDnsServer(key.second);
+ }
+ });
+ return lp;
+ }
}
private final Context mContext;
PRIVATE_DNS_OFF);
final boolean useTls = privateDnsCfg.useTls;
+ final PrivateDnsValidationStatuses statuses =
+ useTls ? mPrivateDnsValidationMap.get(netId) : null;
+ final boolean validated = (null != statuses) && statuses.hasValidatedServer();
final boolean strictMode = privateDnsCfg.inStrictMode();
- final String tlsHostname = strictMode ? privateDnsCfg.hostname : "";
+ final String tlsHostname = strictMode ? privateDnsCfg.hostname : null;
+ final boolean usingPrivateDns = strictMode || validated;
- if (strictMode) {
- lp.setUsePrivateDns(true);
- lp.setPrivateDnsServerName(tlsHostname);
- } else if (useTls) {
- // We are in opportunistic mode. Private DNS should be used if there
- // is a known DNS-over-TLS validated server.
- boolean validated = mPrivateDnsValidationMap.containsKey(netId) &&
- mPrivateDnsValidationMap.get(netId).hasValidatedServer();
- lp.setUsePrivateDns(validated);
- lp.setPrivateDnsServerName(null);
+ lp.setUsePrivateDns(usingPrivateDns);
+ lp.setPrivateDnsServerName(tlsHostname);
+ if (usingPrivateDns && null != statuses) {
+ statuses.fillInValidatedPrivateDns(lp);
} else {
- // Private DNS is disabled.
- lp.setUsePrivateDns(false);
- lp.setPrivateDnsServerName(null);
+ lp.setValidatedPrivateDnsServers(Collections.EMPTY_LIST);
}
}
import android.content.ContentResolver;
import android.content.Context;
+import android.net.IpPrefix;
+import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
+import android.net.RouteInfo;
import android.os.INetworkManagementService;
import android.provider.Settings;
import android.support.test.filters.SmallTest;
import com.android.server.connectivity.MockableSystemProperties;
import java.net.InetAddress;
+import java.util.Arrays;
import org.junit.runner.RunWith;
import org.junit.Before;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class DnsManagerTest {
+ static final String TEST_IFACENAME = "test_wlan0";
static final int TEST_NETID = 100;
static final int TEST_NETID_ALTERNATE = 101;
static final int TEST_NETID_UNTRACKED = 102;
mDnsManager.updatePrivateDns(new Network(TEST_NETID_ALTERNATE),
mDnsManager.getPrivateDnsConfig());
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.updatePrivateDnsStatus(TEST_NETID_ALTERNATE, fixedLp);
assertTrue(fixedLp.isPrivateDnsActive());
assertNull(fixedLp.getPrivateDnsServerName());
+ assertEquals(Arrays.asList(InetAddress.getByName("4.4.4.4")),
+ fixedLp.getValidatedPrivateDnsServers());
+
+ // Set up addresses for strict mode and switch to it.
+ lp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
+ lp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
+ TEST_IFACENAME));
+ lp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
+ lp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
+ TEST_IFACENAME));
- // Switch to strict mode
Settings.Global.putString(mContentResolver,
- Settings.Global.PRIVATE_DNS_MODE,
- PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
+ Settings.Global.PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
Settings.Global.putString(mContentResolver,
Settings.Global.PRIVATE_DNS_SPECIFIER, "strictmode.com");
mDnsManager.updatePrivateDns(new Network(TEST_NETID),
- mDnsManager.getPrivateDnsConfig());
+ new DnsManager.PrivateDnsConfig("strictmode.com", new InetAddress[] {
+ InetAddress.parseNumericAddress("6.6.6.6"),
+ InetAddress.parseNumericAddress("2001:db8:66:66::1")
+ }));
mDnsManager.setDnsConfigurationForNetwork(TEST_NETID, lp, IS_DEFAULT);
fixedLp = new LinkProperties(lp);
mDnsManager.updatePrivateDnsStatus(TEST_NETID, fixedLp);
assertTrue(fixedLp.isPrivateDnsActive());
assertEquals("strictmode.com", fixedLp.getPrivateDnsServerName());
+ // No validation events yet.
+ assertEquals(Arrays.asList(new InetAddress[0]), fixedLp.getValidatedPrivateDnsServers());
+ // Validate one.
+ mDnsManager.updatePrivateDnsValidation(
+ new DnsManager.PrivateDnsValidationUpdate(TEST_NETID,
+ InetAddress.parseNumericAddress("6.6.6.6"), "strictmode.com", true));
fixedLp = new LinkProperties(lp);
+ mDnsManager.updatePrivateDnsStatus(TEST_NETID, fixedLp);
+ assertEquals(Arrays.asList(InetAddress.parseNumericAddress("6.6.6.6")),
+ fixedLp.getValidatedPrivateDnsServers());
+ // Validate the 2nd one.
+ mDnsManager.updatePrivateDnsValidation(
+ new DnsManager.PrivateDnsValidationUpdate(TEST_NETID,
+ InetAddress.parseNumericAddress("2001:db8:66:66::1"), "strictmode.com", true));
+ fixedLp = new LinkProperties(lp);
+ mDnsManager.updatePrivateDnsStatus(TEST_NETID, fixedLp);
+ assertEquals(Arrays.asList(
+ InetAddress.parseNumericAddress("2001:db8:66:66::1"),
+ InetAddress.parseNumericAddress("6.6.6.6")),
+ fixedLp.getValidatedPrivateDnsServers());
}
@Test