Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 47650187 authored by Erik Kline's avatar Erik Kline Committed by Android Git Automerger
Browse files

am f2a08d05: am 49aeed9f: am 5f950417: Merge "Fix use of reachable DNS server logic" into mnc-dev

* commit 'f2a08d05':
  Fix use of reachable DNS server logic
parents 60b5cabb f2a08d05
Loading
Loading
Loading
Loading
+38 −1
Original line number Original line Diff line number Diff line
@@ -517,7 +517,7 @@ public final class LinkProperties implements Parcelable {
     * Note that Http Proxies are only a hint - the system recommends their use, but it does
     * Note that Http Proxies are only a hint - the system recommends their use, but it does
     * not enforce it and applications may ignore them.
     * not enforce it and applications may ignore them.
     *
     *
     * @param proxy A {@link ProxyInfo} defining the Http Proxy to use on this link.
     * @param proxy A {@link ProxyInfo} defining the HTTP Proxy to use on this link.
     * @hide
     * @hide
     */
     */
    public void setHttpProxy(ProxyInfo proxy) {
    public void setHttpProxy(ProxyInfo proxy) {
@@ -773,6 +773,43 @@ public final class LinkProperties implements Parcelable {
        return (isIPv4Provisioned() || isIPv6Provisioned());
        return (isIPv4Provisioned() || isIPv6Provisioned());
    }
    }


    /**
     * Evaluate whether the {@link InetAddress} is considered reachable.
     *
     * @return {@code true} if the given {@link InetAddress} is considered reachable,
     *         {@code false} otherwise.
     * @hide
     */
    public boolean isReachable(InetAddress ip) {
        final List<RouteInfo> allRoutes = getAllRoutes();
        // If we don't have a route to this IP address, it's not reachable.
        final RouteInfo bestRoute = RouteInfo.selectBestRoute(allRoutes, ip);
        if (bestRoute == null) {
            return false;
        }

        // TODO: better source address evaluation for destination addresses.

        if (ip instanceof Inet4Address) {
            // For IPv4, it suffices for now to simply have any address.
            return hasIPv4Address();
        } else if (ip instanceof Inet6Address) {
            if (ip.isLinkLocalAddress()) {
                // For now, just make sure link-local destinations have
                // scopedIds set, since transmits will generally fail otherwise.
                // TODO: verify it matches the ifindex of one of the interfaces.
                return (((Inet6Address)ip).getScopeId() != 0);
            }  else {
                // For non-link-local destinations check that either the best route
                // is directly connected or that some global preferred address exists.
                // TODO: reconsider all cases (disconnected ULA networks, ...).
                return (!bestRoute.hasGateway() || hasGlobalIPv6Address());
            }
        }

        return false;
    }

    /**
    /**
     * Compares this {@code LinkProperties} interface name against the target
     * Compares this {@code LinkProperties} interface name against the target
     *
     *
+79 −0
Original line number Original line Diff line number Diff line
@@ -16,6 +16,8 @@


package android.net;
package android.net;


import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.LinkProperties;
import android.net.LinkProperties.ProvisioningChange;
import android.net.LinkProperties.ProvisioningChange;
import android.net.RouteInfo;
import android.net.RouteInfo;
@@ -26,6 +28,7 @@ import junit.framework.TestCase;
import java.net.InetAddress;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.ArrayList;



public class LinkPropertiesTest extends TestCase {
public class LinkPropertiesTest extends TestCase {
    private static InetAddress ADDRV4 = NetworkUtils.numericToInetAddress("75.208.6.1");
    private static InetAddress ADDRV4 = NetworkUtils.numericToInetAddress("75.208.6.1");
    private static InetAddress ADDRV6 = NetworkUtils.numericToInetAddress(
    private static InetAddress ADDRV6 = NetworkUtils.numericToInetAddress(
@@ -567,4 +570,80 @@ public class LinkPropertiesTest extends TestCase {
        assertEquals(ProvisioningChange.STILL_PROVISIONED,
        assertEquals(ProvisioningChange.STILL_PROVISIONED,
                LinkProperties.compareProvisioning(v6lp, v6lp2));
                LinkProperties.compareProvisioning(v6lp, v6lp2));
    }
    }

    @SmallTest
    public void testIsReachable() {
        final LinkProperties v4lp = new LinkProperties();
        assertFalse(v4lp.isReachable(DNS1));
        assertFalse(v4lp.isReachable(DNS2));

        // Add an on-link route, making the on-link DNS server reachable,
        // but there is still no IPv4 address.
        assertTrue(v4lp.addRoute(new RouteInfo(
                new IpPrefix(NetworkUtils.numericToInetAddress("75.208.0.0"), 16))));
        assertFalse(v4lp.isReachable(DNS1));
        assertFalse(v4lp.isReachable(DNS2));

        // Adding an IPv4 address (right now, any IPv4 address) means we use
        // the routes to compute likely reachability.
        assertTrue(v4lp.addLinkAddress(new LinkAddress(ADDRV4, 16)));
        assertTrue(v4lp.isReachable(DNS1));
        assertFalse(v4lp.isReachable(DNS2));

        // Adding a default route makes the off-link DNS server reachable.
        assertTrue(v4lp.addRoute(new RouteInfo(GATEWAY1)));
        assertTrue(v4lp.isReachable(DNS1));
        assertTrue(v4lp.isReachable(DNS2));

        final LinkProperties v6lp = new LinkProperties();
        final InetAddress kLinkLocalDns = NetworkUtils.numericToInetAddress("fe80::6:1");
        final InetAddress kLinkLocalDnsWithScope = NetworkUtils.numericToInetAddress("fe80::6:2%43");
        final InetAddress kOnLinkDns = NetworkUtils.numericToInetAddress("2001:db8:85a3::53");
        assertFalse(v6lp.isReachable(kLinkLocalDns));
        assertFalse(v6lp.isReachable(kLinkLocalDnsWithScope));
        assertFalse(v6lp.isReachable(kOnLinkDns));
        assertFalse(v6lp.isReachable(DNS6));

        // Add a link-local route, making the link-local DNS servers reachable. Because
        // we assume the presence of an IPv6 link-local address, link-local DNS servers
        // are considered reachable, but only those with a non-zero scope identifier.
        assertTrue(v6lp.addRoute(new RouteInfo(
                new IpPrefix(NetworkUtils.numericToInetAddress("fe80::"), 64))));
        assertFalse(v6lp.isReachable(kLinkLocalDns));
        assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
        assertFalse(v6lp.isReachable(kOnLinkDns));
        assertFalse(v6lp.isReachable(DNS6));

        // Add a link-local address--nothing changes.
        assertTrue(v6lp.addLinkAddress(LINKADDRV6LINKLOCAL));
        assertFalse(v6lp.isReachable(kLinkLocalDns));
        assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
        assertFalse(v6lp.isReachable(kOnLinkDns));
        assertFalse(v6lp.isReachable(DNS6));

        // Add a global route on link, but no global address yet. DNS servers reachable
        // via a route that doesn't require a gateway: give them the benefit of the
        // doubt and hope the link-local source address suffices for communication.
        assertTrue(v6lp.addRoute(new RouteInfo(
                new IpPrefix(NetworkUtils.numericToInetAddress("2001:db8:85a3::"), 64))));
        assertFalse(v6lp.isReachable(kLinkLocalDns));
        assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
        assertTrue(v6lp.isReachable(kOnLinkDns));
        assertFalse(v6lp.isReachable(DNS6));

        // Add a global address; the on-link global address DNS server is (still)
        // presumed reachable.
        assertTrue(v6lp.addLinkAddress(new LinkAddress(ADDRV6, 64)));
        assertFalse(v6lp.isReachable(kLinkLocalDns));
        assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
        assertTrue(v6lp.isReachable(kOnLinkDns));
        assertFalse(v6lp.isReachable(DNS6));

        // Adding a default route makes the off-link DNS server reachable.
        assertTrue(v6lp.addRoute(new RouteInfo(GATEWAY62)));
        assertFalse(v6lp.isReachable(kLinkLocalDns));
        assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
        assertTrue(v6lp.isReachable(kOnLinkDns));
        assertTrue(v6lp.isReachable(DNS6));
    }
}
}
+1 −44
Original line number Original line Diff line number Diff line
@@ -140,14 +140,12 @@ import java.io.FileReader;
import java.io.IOException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.PrintWriter;
import java.net.Inet4Address;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.net.UnknownHostException;
import java.util.ArrayDeque;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Iterator;
@@ -4014,51 +4012,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
        return !routeDiff.added.isEmpty() || !routeDiff.removed.isEmpty();
        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<InetAddress> getLikelyReachableDnsServers(LinkProperties lp) {
        final ArrayList<InetAddress> dnsServers = new ArrayList<InetAddress>();
        final List<RouteInfo> 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,
    private void updateDnses(LinkProperties newLp, LinkProperties oldLp, int netId,
                             boolean flush, boolean useDefaultDns) {
                             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)) {
        if (oldLp == null || (newLp.isIdenticalDnses(oldLp) == false)) {
            Collection<InetAddress> dnses = getLikelyReachableDnsServers(newLp);
            Collection<InetAddress> dnses = newLp.getDnsServers();
            if (dnses.size() == 0 && mDefaultDns != null && useDefaultDns) {
            if (dnses.size() == 0 && mDefaultDns != null && useDefaultDns) {
                dnses = new ArrayList();
                dnses = new ArrayList();
                dnses.add(mDefaultDns);
                dnses.add(mDefaultDns);