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

Commit e6848fac authored by Robert Greenwalt's avatar Robert Greenwalt Committed by Android (Google) Code Review
Browse files

Merge "Fix the adding of host routes." into honeycomb-LTE

parents 652dbb7d f43396ca
Loading
Loading
Loading
Loading
+46 −0
Original line number Diff line number Diff line
@@ -225,4 +225,50 @@ public class NetworkUtils {
        }
        return addRoute(interfaceName, dstStr, prefixLength, gwStr) == 0;
    }

    /**
     * Get InetAddress masked with prefixLength.  Will never return null.
     * @param IP address which will be masked with specified prefixLength
     * @param prefixLength the prefixLength used to mask the IP
     */
    public static InetAddress getNetworkPart(InetAddress address, int prefixLength) {
        if (address == null) {
            throw new RuntimeException("getNetworkPart doesn't accept null address");
        }

        byte[] array = address.getAddress();

        if (prefixLength < 0 || prefixLength > array.length * 8) {
            throw new RuntimeException("getNetworkPart - bad prefixLength");
        }

        int offset = prefixLength / 8;
        int reminder = prefixLength % 8;
        byte mask = (byte)(0xFF << (8 - reminder));

        if (offset < array.length) array[offset] = (byte)(array[offset] & mask);

        offset++;

        for (; offset < array.length; offset++) {
            array[offset] = 0;
        }

        InetAddress netPart = null;
        try {
            netPart = InetAddress.getByAddress(array);
        } catch (UnknownHostException e) {
            throw new RuntimeException("getNetworkPart error - " + e.toString());
        }
        return netPart;
    }

    /**
     * Check if IP address type is consistent between two InetAddress.
     * @return true if both are the same type.  False otherwise.
     */
    public static boolean addressTypeMatches(InetAddress left, InetAddress right) {
        return (((left instanceof Inet4Address) && (right instanceof Inet4Address)) ||
                ((left instanceof Inet6Address) && (right instanceof Inet6Address)));
    }
}
+50 −17
Original line number Diff line number Diff line
@@ -23,6 +23,9 @@ import java.net.UnknownHostException;
import java.net.InetAddress;
import java.net.Inet4Address;
import java.net.Inet6Address;

import java.util.Collection;

/**
 * A simple container for route information.
 *
@@ -44,39 +47,30 @@ public class RouteInfo implements Parcelable {
    public RouteInfo(LinkAddress destination, InetAddress gateway) {
        if (destination == null) {
            try {
                if ((gateway != null) && (gateway instanceof Inet4Address)) {
                    destination = new LinkAddress(InetAddress.getByName("0.0.0.0"), 32);
                if ((gateway != null) || (gateway instanceof Inet4Address)) {
                    destination = new LinkAddress(Inet4Address.ANY, 0);
                } else {
                    destination = new LinkAddress(InetAddress.getByName("::0"), 128);
                    destination = new LinkAddress(Inet6Address.ANY, 0);
                }
            } catch (Exception e) {}
        }
        mDestination = destination;
        mDestination = new LinkAddress(NetworkUtils.getNetworkPart(destination.getAddress(),
                destination.getNetworkPrefixLength()), destination.getNetworkPrefixLength());
        mGateway = gateway;
        mIsDefault = isDefault();
    }

    public RouteInfo(InetAddress gateway) {
        LinkAddress destination = null;
        try {
            if ((gateway != null) && (gateway instanceof Inet4Address)) {
                destination = new LinkAddress(InetAddress.getByName("0.0.0.0"), 32);
            } else {
                destination = new LinkAddress(InetAddress.getByName("::0"), 128);
            }
        } catch (Exception e) {}
        mDestination = destination;
        mGateway = gateway;
        mIsDefault = isDefault();
        this(null, gateway);
    }

    private boolean isDefault() {
        boolean val = false;
        if (mGateway != null) {
            if (mGateway instanceof Inet4Address) {
                val = (mDestination == null || mDestination.getNetworkPrefixLength() == 32);
                val = (mDestination == null || mDestination.getNetworkPrefixLength() == 0);
            } else {
                val = (mDestination == null || mDestination.getNetworkPrefixLength() == 128);
                val = (mDestination == null || mDestination.getNetworkPrefixLength() == 0);
            }
        }
        return val;
@@ -159,4 +153,43 @@ public class RouteInfo implements Parcelable {
            return new RouteInfo[size];
        }
    };

    private boolean matches(InetAddress destination) {
        if (destination == null) return false;

        // if the destination is present and the route is default.
        // return true
        if (isDefault()) return true;

        // match the route destination and destination with prefix length
        InetAddress dstNet = NetworkUtils.getNetworkPart(destination,
                mDestination.getNetworkPrefixLength());

        return mDestination.getAddress().equals(dstNet);
    }

    /**
     * Find the route from a Collection of routes that best matches a given address.
     * May return null if no routes are applicable.
     * @param routes a Collection of RouteInfos to chose from
     * @param dest the InetAddress your trying to get to
     * @return the RouteInfo from the Collection that best fits the given address
     */
    public static RouteInfo selectBestRoute(Collection<RouteInfo> routes, InetAddress dest) {
        if ((routes == null) || (dest == null)) return null;

        RouteInfo bestRoute = null;
        // pick a longest prefix match under same address type
        for (RouteInfo route : routes) {
            if (NetworkUtils.addressTypeMatches(route.mDestination.getAddress(), dest)) {
                if ((bestRoute != null) &&
                        (bestRoute.mDestination.getNetworkPrefixLength() >=
                        route.mDestination.getNetworkPrefixLength())) {
                    continue;
                }
                if (route.matches(dest)) bestRoute = route;
            }
        }
        return bestRoute;
    }
}
+36 −11
Original line number Diff line number Diff line
@@ -81,6 +81,10 @@ public class ConnectivityService extends IConnectivityManager.Stub {
    private static final String NETWORK_RESTORE_DELAY_PROP_NAME =
            "android.telephony.apn-restore";

    // used in recursive route setting to add gateways for the host for which
    // a host route was requested.
    private static final int MAX_HOSTROUTE_CYCLE_COUNT = 10;

    private Tethering mTethering;
    private boolean mTetheringConfigValid = false;

@@ -921,7 +925,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
        }
        try {
            InetAddress addr = InetAddress.getByAddress(hostAddress);
            return addHostRoute(tracker, addr);
            return addHostRoute(tracker, addr, 0);
        } catch (UnknownHostException e) {}
        return false;
    }
@@ -934,24 +938,45 @@ public class ConnectivityService extends IConnectivityManager.Stub {
     * TODO - deprecate
     * @return {@code true} on success, {@code false} on failure
     */
    private boolean addHostRoute(NetworkStateTracker nt, InetAddress hostAddress) {
    private boolean addHostRoute(NetworkStateTracker nt, InetAddress hostAddress, int cycleCount) {
        if (nt.getNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI) {
            return false;
        }

        LinkProperties p = nt.getLinkProperties();
        if (p == null) return false;
        String interfaceName = p.getInterfaceName();
        LinkProperties lp = nt.getLinkProperties();
        if ((lp == null) || (hostAddress == null)) return false;

        String interfaceName = lp.getInterfaceName();
        if (DBG) {
            log("Requested host route to " + hostAddress + "(" + interfaceName + ")");
            log("Requested host route to " + hostAddress + "(" + interfaceName + "), cycleCount=" +
                    cycleCount);
        }
        if (interfaceName != null) {
            return NetworkUtils.addHostRoute(interfaceName, hostAddress, null);
        } else {
        if (interfaceName == null) {
            if (DBG) loge("addHostRoute failed due to null interface name");
            return false;
        }

        RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), hostAddress);
        InetAddress gateway = null;
        if (bestRoute != null) {
            gateway = bestRoute.getGateway();
            // if the best route is ourself, don't relf-reference, just add the host route
            if (hostAddress.equals(gateway)) gateway = null;
        }
        if (gateway != null) {
            if (cycleCount > MAX_HOSTROUTE_CYCLE_COUNT) {
                loge("Error adding hostroute - too much recursion");
                return false;
            }
            if (!addHostRoute(nt, gateway, cycleCount+1)) return false;
        }
        return NetworkUtils.addHostRoute(interfaceName, hostAddress, gateway);
    }

    // TODO support the removal of single host routes.  Keep a ref count of them so we
    // aren't over-zealous
    private boolean removeHostRoute(NetworkStateTracker nt, InetAddress hostAddress) {
        return false;
    }

    /**
@@ -1389,7 +1414,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
            Collection<InetAddress> dnsList = p.getDnses();
            for (InetAddress dns : dnsList) {
                if (DBG) log("  adding " + dns);
                NetworkUtils.addHostRoute(interfaceName, dns, null);
                addHostRoute(nt, dns, 0);
            }
            nt.privateDnsRouteSet(true);
        }
@@ -1423,7 +1448,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
            //TODO - handle non-default routes
            if (route.isDefaultRoute()) {
                InetAddress gateway = route.getGateway();
                if (NetworkUtils.addHostRoute(interfaceName, gateway, null) &&
                if (addHostRoute(nt, gateway, 0) &&
                        NetworkUtils.addDefaultRoute(interfaceName, gateway)) {
                    if (DBG) {
                        NetworkInfo networkInfo = nt.getNetworkInfo();