Loading core/java/android/net/NetworkUtils.java +46 −0 Original line number Diff line number Diff line Loading @@ -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))); } } core/java/android/net/RouteInfo.java +50 −17 Original line number Diff line number Diff line Loading @@ -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. * Loading @@ -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; Loading Loading @@ -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; } } services/java/com/android/server/ConnectivityService.java +36 −11 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; } Loading @@ -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; } /** Loading Loading @@ -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); } Loading Loading @@ -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(); Loading Loading
core/java/android/net/NetworkUtils.java +46 −0 Original line number Diff line number Diff line Loading @@ -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))); } }
core/java/android/net/RouteInfo.java +50 −17 Original line number Diff line number Diff line Loading @@ -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. * Loading @@ -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; Loading Loading @@ -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; } }
services/java/com/android/server/ConnectivityService.java +36 −11 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; } Loading @@ -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; } /** Loading Loading @@ -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); } Loading Loading @@ -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(); Loading