Loading services/core/java/com/android/server/connectivity/Vpn.java +9 −18 Original line number Diff line number Diff line Loading @@ -953,30 +953,21 @@ public class Vpn { return false; } LinkProperties lp = makeLinkProperties(); final boolean hadInternetCapability = mNetworkCapabilities.hasCapability( NetworkCapabilities.NET_CAPABILITY_INTERNET); final boolean willHaveInternetCapability = providesRoutesToMostDestinations(lp); if (hadInternetCapability != willHaveInternetCapability) { // A seamless handover would have led to a change to INTERNET capability, which // is supposed to be immutable for a given network. In this case bail out and do not // perform handover. Log.i(TAG, "Handover not possible due to changes to INTERNET capability"); return false; } agent.sendLinkProperties(lp); agent.sendLinkProperties(makeLinkProperties()); return true; } private void agentConnect() { LinkProperties lp = makeLinkProperties(); if (providesRoutesToMostDestinations(lp)) { // VPN either provide a default route (IPv4 or IPv6 or both), or they are a split tunnel // that falls back to the default network, which by definition provides INTERNET (unless // there is no default network, in which case none of this matters in any sense). // Also, it guarantees that when a VPN applies to an app, the VPN will always be reported // as the network by getDefaultNetwork and registerDefaultNetworkCallback. This in turn // protects the invariant that apps calling CM#bindProcessToNetwork(getDefaultNetwork()) // the same as if they use the default network. mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); } else { mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); } mNetworkInfo.setDetailedState(DetailedState.CONNECTING, null, null); Loading tests/net/java/com/android/server/connectivity/VpnTest.java +0 −90 Original line number Diff line number Diff line Loading @@ -727,94 +727,4 @@ public class VpnTest { "::/1", "8000::/2", "c000::/3", "e000::/4", "f000::/5", "f800::/6", "fe00::/8", "2605:ef80:e:af1d::/64"); } @Test public void testProvidesRoutesToMostDestinations() { final LinkProperties lp = new LinkProperties(); // Default route provides routes to all IPv4 destinations. lp.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0"))); assertTrue(Vpn.providesRoutesToMostDestinations(lp)); // Empty LP provides routes to no destination lp.clear(); assertFalse(Vpn.providesRoutesToMostDestinations(lp)); // All IPv4 routes except for local networks. This is the case most relevant // to this function. It provides routes to almost the entire space. // (clone the stream so that we can reuse it later) publicIpV4Routes().forEach(s -> lp.addRoute(new RouteInfo(new IpPrefix(s)))); assertTrue(Vpn.providesRoutesToMostDestinations(lp)); // Removing a 16-bit prefix, which is 65536 addresses. This is still enough to // provide routes to "most" destinations. lp.removeRoute(new RouteInfo(new IpPrefix("192.169.0.0/16"))); assertTrue(Vpn.providesRoutesToMostDestinations(lp)); // Remove the /2 route, which represent a quarter of the available routing space. // This LP does not provides routes to "most" destinations any more. lp.removeRoute(new RouteInfo(new IpPrefix("64.0.0.0/2"))); assertFalse(Vpn.providesRoutesToMostDestinations(lp)); lp.clear(); publicIpV6Routes().forEach(s -> lp.addRoute(new RouteInfo(new IpPrefix(s)))); assertTrue(Vpn.providesRoutesToMostDestinations(lp)); lp.removeRoute(new RouteInfo(new IpPrefix("::/1"))); assertFalse(Vpn.providesRoutesToMostDestinations(lp)); // V6 does not provide sufficient coverage but v4 does publicIpV4Routes().forEach(s -> lp.addRoute(new RouteInfo(new IpPrefix(s)))); assertTrue(Vpn.providesRoutesToMostDestinations(lp)); // V4 still does lp.removeRoute(new RouteInfo(new IpPrefix("192.169.0.0/16"))); assertTrue(Vpn.providesRoutesToMostDestinations(lp)); // V4 does not any more lp.removeRoute(new RouteInfo(new IpPrefix("64.0.0.0/2"))); assertFalse(Vpn.providesRoutesToMostDestinations(lp)); // V4 does not, but V6 has sufficient coverage again lp.addRoute(new RouteInfo(new IpPrefix("::/1"))); assertTrue(Vpn.providesRoutesToMostDestinations(lp)); lp.clear(); // V4-unreachable route should not be treated as sufficient coverage lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE)); assertFalse(Vpn.providesRoutesToMostDestinations(lp)); lp.clear(); // V6-unreachable route should not be treated as sufficient coverage lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE)); assertFalse(Vpn.providesRoutesToMostDestinations(lp)); } @Test public void testDoesNotLockUpWithTooManyRoutes() { final LinkProperties lp = new LinkProperties(); final byte[] ad = new byte[4]; // Actually evaluating this many routes under 1500ms is impossible on // current hardware and for some time, as the algorithm is O(n²). // Make sure the system has a safeguard against this and does not // lock up. final int MAX_ROUTES = 4000; final long MAX_ALLOWED_TIME_MS = 1500; for (int i = 0; i < MAX_ROUTES; ++i) { ad[0] = (byte)((i >> 24) & 0xFF); ad[1] = (byte)((i >> 16) & 0xFF); ad[2] = (byte)((i >> 8) & 0xFF); ad[3] = (byte)(i & 0xFF); try { lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.getByAddress(ad), 32))); } catch (UnknownHostException e) { // UnknownHostException is only thrown for an address of illegal length, // which can't happen in the case above. } } final long start = SystemClock.currentThreadTimeMillis(); assertTrue(Vpn.providesRoutesToMostDestinations(lp)); final long end = SystemClock.currentThreadTimeMillis(); assertTrue(end - start < MAX_ALLOWED_TIME_MS); } } Loading
services/core/java/com/android/server/connectivity/Vpn.java +9 −18 Original line number Diff line number Diff line Loading @@ -953,30 +953,21 @@ public class Vpn { return false; } LinkProperties lp = makeLinkProperties(); final boolean hadInternetCapability = mNetworkCapabilities.hasCapability( NetworkCapabilities.NET_CAPABILITY_INTERNET); final boolean willHaveInternetCapability = providesRoutesToMostDestinations(lp); if (hadInternetCapability != willHaveInternetCapability) { // A seamless handover would have led to a change to INTERNET capability, which // is supposed to be immutable for a given network. In this case bail out and do not // perform handover. Log.i(TAG, "Handover not possible due to changes to INTERNET capability"); return false; } agent.sendLinkProperties(lp); agent.sendLinkProperties(makeLinkProperties()); return true; } private void agentConnect() { LinkProperties lp = makeLinkProperties(); if (providesRoutesToMostDestinations(lp)) { // VPN either provide a default route (IPv4 or IPv6 or both), or they are a split tunnel // that falls back to the default network, which by definition provides INTERNET (unless // there is no default network, in which case none of this matters in any sense). // Also, it guarantees that when a VPN applies to an app, the VPN will always be reported // as the network by getDefaultNetwork and registerDefaultNetworkCallback. This in turn // protects the invariant that apps calling CM#bindProcessToNetwork(getDefaultNetwork()) // the same as if they use the default network. mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); } else { mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); } mNetworkInfo.setDetailedState(DetailedState.CONNECTING, null, null); Loading
tests/net/java/com/android/server/connectivity/VpnTest.java +0 −90 Original line number Diff line number Diff line Loading @@ -727,94 +727,4 @@ public class VpnTest { "::/1", "8000::/2", "c000::/3", "e000::/4", "f000::/5", "f800::/6", "fe00::/8", "2605:ef80:e:af1d::/64"); } @Test public void testProvidesRoutesToMostDestinations() { final LinkProperties lp = new LinkProperties(); // Default route provides routes to all IPv4 destinations. lp.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0"))); assertTrue(Vpn.providesRoutesToMostDestinations(lp)); // Empty LP provides routes to no destination lp.clear(); assertFalse(Vpn.providesRoutesToMostDestinations(lp)); // All IPv4 routes except for local networks. This is the case most relevant // to this function. It provides routes to almost the entire space. // (clone the stream so that we can reuse it later) publicIpV4Routes().forEach(s -> lp.addRoute(new RouteInfo(new IpPrefix(s)))); assertTrue(Vpn.providesRoutesToMostDestinations(lp)); // Removing a 16-bit prefix, which is 65536 addresses. This is still enough to // provide routes to "most" destinations. lp.removeRoute(new RouteInfo(new IpPrefix("192.169.0.0/16"))); assertTrue(Vpn.providesRoutesToMostDestinations(lp)); // Remove the /2 route, which represent a quarter of the available routing space. // This LP does not provides routes to "most" destinations any more. lp.removeRoute(new RouteInfo(new IpPrefix("64.0.0.0/2"))); assertFalse(Vpn.providesRoutesToMostDestinations(lp)); lp.clear(); publicIpV6Routes().forEach(s -> lp.addRoute(new RouteInfo(new IpPrefix(s)))); assertTrue(Vpn.providesRoutesToMostDestinations(lp)); lp.removeRoute(new RouteInfo(new IpPrefix("::/1"))); assertFalse(Vpn.providesRoutesToMostDestinations(lp)); // V6 does not provide sufficient coverage but v4 does publicIpV4Routes().forEach(s -> lp.addRoute(new RouteInfo(new IpPrefix(s)))); assertTrue(Vpn.providesRoutesToMostDestinations(lp)); // V4 still does lp.removeRoute(new RouteInfo(new IpPrefix("192.169.0.0/16"))); assertTrue(Vpn.providesRoutesToMostDestinations(lp)); // V4 does not any more lp.removeRoute(new RouteInfo(new IpPrefix("64.0.0.0/2"))); assertFalse(Vpn.providesRoutesToMostDestinations(lp)); // V4 does not, but V6 has sufficient coverage again lp.addRoute(new RouteInfo(new IpPrefix("::/1"))); assertTrue(Vpn.providesRoutesToMostDestinations(lp)); lp.clear(); // V4-unreachable route should not be treated as sufficient coverage lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE)); assertFalse(Vpn.providesRoutesToMostDestinations(lp)); lp.clear(); // V6-unreachable route should not be treated as sufficient coverage lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE)); assertFalse(Vpn.providesRoutesToMostDestinations(lp)); } @Test public void testDoesNotLockUpWithTooManyRoutes() { final LinkProperties lp = new LinkProperties(); final byte[] ad = new byte[4]; // Actually evaluating this many routes under 1500ms is impossible on // current hardware and for some time, as the algorithm is O(n²). // Make sure the system has a safeguard against this and does not // lock up. final int MAX_ROUTES = 4000; final long MAX_ALLOWED_TIME_MS = 1500; for (int i = 0; i < MAX_ROUTES; ++i) { ad[0] = (byte)((i >> 24) & 0xFF); ad[1] = (byte)((i >> 16) & 0xFF); ad[2] = (byte)((i >> 8) & 0xFF); ad[3] = (byte)(i & 0xFF); try { lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.getByAddress(ad), 32))); } catch (UnknownHostException e) { // UnknownHostException is only thrown for an address of illegal length, // which can't happen in the case above. } } final long start = SystemClock.currentThreadTimeMillis(); assertTrue(Vpn.providesRoutesToMostDestinations(lp)); final long end = SystemClock.currentThreadTimeMillis(); assertTrue(end - start < MAX_ALLOWED_TIME_MS); } }