From 0f0dbb822278a677836c63f7fa38612fee787513 Mon Sep 17 00:00:00 2001 From: Erik Kline Date: Wed, 17 Jun 2015 13:19:54 +0900 Subject: [PATCH] Carefully select which DNS servers to send to netd Select only DNS servers that: - are reachable, according to routes in the LinkProperties, AND - have a "suitable" source address in the LinkProperites, meaning: - IPv4 DNS server: - only if LinkProperties has any IPv4 address - IPv6 link-local DNS server: - only if the server has a scopeId set - assume for now that LinkProperties has a suitable link-local address - IPv6 non-link-local DNS server: - only if LinkProperties has a global, preferred IPv6 address Bug: 19470192 Bug: 20733156 Change-Id: Ibd95f3f7b33a4fb6c36d1cea4adb63c99068f657 --- .../android/server/ConnectivityService.java | 46 ++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 82399da92f..98f0b454e0 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -136,11 +136,13 @@ import java.io.FileReader; import java.io.IOException; import java.io.PrintWriter; import java.net.Inet4Address; +import java.net.Inet6Address; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -3920,10 +3922,52 @@ public class ConnectivityService extends IConnectivityManager.Stub } return !routeDiff.added.isEmpty() || !routeDiff.removed.isEmpty(); } + + // TODO: investigate moving this into LinkProperties, if only to make more accurate + // the isProvisioned() checks. + private static Collection getLikelyReachableDnsServers(LinkProperties lp) { + final ArrayList dnsServers = new ArrayList(); + final List allRoutes = lp.getAllRoutes(); + for (InetAddress nameserver : lp.getDnsServers()) { + // If the LinkProperties doesn't include a route to the nameserver, ignore it. + final RouteInfo bestRoute = RouteInfo.selectBestRoute(allRoutes, nameserver); + if (bestRoute == null) { + continue; + } + + // TODO: better source address evaluation for destination addresses. + if (nameserver instanceof Inet4Address) { + if (!lp.hasIPv4Address()) { + continue; + } + } else if (nameserver instanceof Inet6Address) { + if (nameserver.isLinkLocalAddress()) { + if (((Inet6Address)nameserver).getScopeId() == 0) { + // For now, just make sure link-local DNS servers have + // scopedIds set, since DNS lookups will fail otherwise. + // TODO: verify the scopeId matches that of lp's interface. + continue; + } + } else { + if (bestRoute.isIPv6Default() && !lp.hasGlobalIPv6Address()) { + // TODO: reconsider all corner cases (disconnected ULA networks, ...). + continue; + } + } + } + + dnsServers.add(nameserver); + } + return Collections.unmodifiableList(dnsServers); + } + private void updateDnses(LinkProperties newLp, LinkProperties oldLp, int netId, boolean flush, boolean useDefaultDns) { + // TODO: consider comparing the getLikelyReachableDnsServers() lists, in case the + // route to a DNS server has been removed (only really applicable in special cases + // where there is no default route). if (oldLp == null || (newLp.isIdenticalDnses(oldLp) == false)) { - Collection dnses = newLp.getDnsServers(); + Collection dnses = getLikelyReachableDnsServers(newLp); if (dnses.size() == 0 && mDefaultDns != null && useDefaultDns) { dnses = new ArrayList(); dnses.add(mDefaultDns);