Merge "Make PrivateAddressCoordinator ignore vpn network"

This commit is contained in:
Treehugger Robot
2020-10-05 04:10:48 +00:00
committed by Gerrit Code Review
3 changed files with 84 additions and 68 deletions

View File

@@ -15,6 +15,7 @@
*/ */
package com.android.networkstack.tethering; package com.android.networkstack.tethering;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.TetheringManager.TETHERING_WIFI_P2P; import static android.net.TetheringManager.TETHERING_WIFI_P2P;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
@@ -23,7 +24,6 @@ import android.content.Context;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.IpPrefix; import android.net.IpPrefix;
import android.net.LinkAddress; import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network; import android.net.Network;
import android.net.ip.IpServer; import android.net.ip.IpServer;
import android.net.util.PrefixUtils; import android.net.util.PrefixUtils;
@@ -90,16 +90,24 @@ public class PrivateAddressCoordinator {
/** /**
* Record a new upstream IpPrefix which may conflict with tethering downstreams. * Record a new upstream IpPrefix which may conflict with tethering downstreams.
* The downstreams will be notified if a conflict is found. * The downstreams will be notified if a conflict is found. When updateUpstreamPrefix is called,
* UpstreamNetworkState must have an already populated LinkProperties.
*/ */
public void updateUpstreamPrefix(final Network network, final LinkProperties lp) { public void updateUpstreamPrefix(final UpstreamNetworkState ns) {
final ArrayList<IpPrefix> ipv4Prefixes = getIpv4Prefixes(lp.getAllLinkAddresses()); // Do not support VPN as upstream
if (ipv4Prefixes.isEmpty()) { if (ns.networkCapabilities != null && ns.networkCapabilities.hasTransport(TRANSPORT_VPN)) {
removeUpstreamPrefix(network); removeUpstreamPrefix(ns.network);
return; return;
} }
mUpstreamPrefixMap.put(network, ipv4Prefixes); final ArrayList<IpPrefix> ipv4Prefixes = getIpv4Prefixes(
ns.linkProperties.getAllLinkAddresses());
if (ipv4Prefixes.isEmpty()) {
removeUpstreamPrefix(ns.network);
return;
}
mUpstreamPrefixMap.put(ns.network, ipv4Prefixes);
handleMaybePrefixConflict(ipv4Prefixes); handleMaybePrefixConflict(ipv4Prefixes);
} }

View File

@@ -1678,14 +1678,6 @@ public class Tethering {
} }
} }
private void addUpstreamPrefixes(final UpstreamNetworkState ns) {
mPrivateAddressCoordinator.updateUpstreamPrefix(ns.network, ns.linkProperties);
}
private void removeUpstreamPrefixes(final UpstreamNetworkState ns) {
mPrivateAddressCoordinator.removeUpstreamPrefix(ns.network);
}
@VisibleForTesting @VisibleForTesting
void handleUpstreamNetworkMonitorCallback(int arg1, Object o) { void handleUpstreamNetworkMonitorCallback(int arg1, Object o) {
if (arg1 == UpstreamNetworkMonitor.NOTIFY_LOCAL_PREFIXES) { if (arg1 == UpstreamNetworkMonitor.NOTIFY_LOCAL_PREFIXES) {
@@ -1696,10 +1688,10 @@ public class Tethering {
final UpstreamNetworkState ns = (UpstreamNetworkState) o; final UpstreamNetworkState ns = (UpstreamNetworkState) o;
switch (arg1) { switch (arg1) {
case UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES: case UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES:
addUpstreamPrefixes(ns); mPrivateAddressCoordinator.updateUpstreamPrefix(ns);
break; break;
case UpstreamNetworkMonitor.EVENT_ON_LOST: case UpstreamNetworkMonitor.EVENT_ON_LOST:
removeUpstreamPrefixes(ns); mPrivateAddressCoordinator.removeUpstreamPrefix(ns.network);
break; break;
} }

View File

@@ -15,6 +15,10 @@
*/ */
package com.android.networkstack.tethering; package com.android.networkstack.tethering;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.TetheringManager.TETHERING_ETHERNET; import static android.net.TetheringManager.TETHERING_ETHERNET;
import static android.net.TetheringManager.TETHERING_USB; import static android.net.TetheringManager.TETHERING_USB;
import static android.net.TetheringManager.TETHERING_WIFI; import static android.net.TetheringManager.TETHERING_WIFI;
@@ -30,13 +34,12 @@ import static org.mockito.Mockito.when;
import android.content.Context; import android.content.Context;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.InetAddresses;
import android.net.IpPrefix; import android.net.IpPrefix;
import android.net.LinkAddress; import android.net.LinkAddress;
import android.net.LinkProperties; import android.net.LinkProperties;
import android.net.Network; import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.ip.IpServer; import android.net.ip.IpServer;
import android.net.util.NetworkConstants;
import android.net.util.PrefixUtils; import android.net.util.PrefixUtils;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
@@ -48,13 +51,10 @@ import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import java.util.List;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
@SmallTest @SmallTest
public final class PrivateAddressCoordinatorTest { public final class PrivateAddressCoordinatorTest {
private static final String TEST_MOBILE_IFNAME = "test_rmnet_data0"; private static final String TEST_IFNAME = "test0";
private static final String TEST_WIFI_IFNAME = "test_wlan0";
@Mock private IpServer mHotspotIpServer; @Mock private IpServer mHotspotIpServer;
@Mock private IpServer mUsbIpServer; @Mock private IpServer mUsbIpServer;
@@ -69,7 +69,8 @@ public final class PrivateAddressCoordinatorTest {
private final LinkAddress mLegacyWifiP2pAddress = new LinkAddress("192.168.49.1/24"); private final LinkAddress mLegacyWifiP2pAddress = new LinkAddress("192.168.49.1/24");
private final Network mWifiNetwork = new Network(1); private final Network mWifiNetwork = new Network(1);
private final Network mMobileNetwork = new Network(2); private final Network mMobileNetwork = new Network(2);
private final Network[] mAllNetworks = {mMobileNetwork, mWifiNetwork}; private final Network mVpnNetwork = new Network(3);
private final Network[] mAllNetworks = {mMobileNetwork, mWifiNetwork, mVpnNetwork};
private void setUpIpServers() throws Exception { private void setUpIpServers() throws Exception {
when(mUsbIpServer.interfaceType()).thenReturn(TETHERING_USB); when(mUsbIpServer.interfaceType()).thenReturn(TETHERING_USB);
@@ -184,33 +185,25 @@ public final class PrivateAddressCoordinatorTest {
assertEquals("Fail to reselect available prefix: ", predefinedPrefix, allowUseFreePrefix); assertEquals("Fail to reselect available prefix: ", predefinedPrefix, allowUseFreePrefix);
} }
private LinkProperties buildUpstreamLinkProperties(boolean withIPv4, boolean withIPv6, private UpstreamNetworkState buildUpstreamNetworkState(final Network network,
boolean isMobile) { final LinkAddress v4Addr, final LinkAddress v6Addr, final NetworkCapabilities cap) {
final String testIface;
final String testIpv4Address;
if (isMobile) {
testIface = TEST_MOBILE_IFNAME;
testIpv4Address = "10.0.0.1";
} else {
testIface = TEST_WIFI_IFNAME;
testIpv4Address = "192.168.43.5";
}
final LinkProperties prop = new LinkProperties(); final LinkProperties prop = new LinkProperties();
prop.setInterfaceName(testIface); prop.setInterfaceName(TEST_IFNAME);
if (v4Addr != null) prop.addLinkAddress(v4Addr);
if (withIPv4) { if (v6Addr != null) prop.addLinkAddress(v6Addr);
prop.addLinkAddress(
new LinkAddress(InetAddresses.parseNumericAddress(testIpv4Address), return new UpstreamNetworkState(prop, cap, network);
NetworkConstants.IPV4_ADDR_BITS)); }
private NetworkCapabilities makeNetworkCapabilities(final int transportType) {
final NetworkCapabilities cap = new NetworkCapabilities();
cap.addTransportType(transportType);
if (transportType == TRANSPORT_VPN) {
cap.removeCapability(NET_CAPABILITY_NOT_VPN);
} }
if (withIPv6) { return cap;
prop.addLinkAddress(
new LinkAddress(InetAddresses.parseNumericAddress("2001:db8::"),
NetworkConstants.RFC7421_PREFIX_LENGTH));
}
return prop;
} }
@Test @Test
@@ -220,53 +213,76 @@ public final class PrivateAddressCoordinatorTest {
final IpPrefix predefinedPrefix = new IpPrefix("192.168.43.0/24"); final IpPrefix predefinedPrefix = new IpPrefix("192.168.43.0/24");
// Force always get subAddress "43.5" for conflict testing. // Force always get subAddress "43.5" for conflict testing.
when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(fakeHotspotSubAddr); when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(fakeHotspotSubAddr);
// 1. Enable hotspot with prefix 192.168.43.0/24 // - Enable hotspot with prefix 192.168.43.0/24
final LinkAddress hotspotAddr = mPrivateAddressCoordinator.requestDownstreamAddress( final LinkAddress hotspotAddr = mPrivateAddressCoordinator.requestDownstreamAddress(
mHotspotIpServer); mHotspotIpServer);
final IpPrefix hotspotPrefix = PrefixUtils.asIpPrefix(hotspotAddr); final IpPrefix hotspotPrefix = PrefixUtils.asIpPrefix(hotspotAddr);
assertEquals("Wrong wifi prefix: ", predefinedPrefix, hotspotPrefix); assertEquals("Wrong wifi prefix: ", predefinedPrefix, hotspotPrefix);
when(mHotspotIpServer.getAddress()).thenReturn(hotspotAddr); when(mHotspotIpServer.getAddress()).thenReturn(hotspotAddr);
// 2. Update v6 only mobile network, hotspot prefix should not be removed. // - test mobile network with null NetworkCapabilities. Ideally this should not happen,
List<String> testConflicts; // just make sure no crash in this case.
final LinkProperties v6OnlyMobileProp = buildUpstreamLinkProperties(false, true, true); final UpstreamNetworkState noCapUpstream = buildUpstreamNetworkState(mMobileNetwork,
mPrivateAddressCoordinator.updateUpstreamPrefix(mMobileNetwork, v6OnlyMobileProp); new LinkAddress("10.0.0.8/24"), null, null);
mPrivateAddressCoordinator.updateUpstreamPrefix(noCapUpstream);
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
// - test mobile upstream with no address.
final UpstreamNetworkState noAddress = buildUpstreamNetworkState(mMobileNetwork,
null, null, makeNetworkCapabilities(TRANSPORT_CELLULAR));
mPrivateAddressCoordinator.updateUpstreamPrefix(noCapUpstream);
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
// - Update v6 only mobile network, hotspot prefix should not be removed.
final UpstreamNetworkState v6OnlyMobile = buildUpstreamNetworkState(mMobileNetwork,
null, new LinkAddress("2001:db8::/64"),
makeNetworkCapabilities(TRANSPORT_CELLULAR));
mPrivateAddressCoordinator.updateUpstreamPrefix(v6OnlyMobile);
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT); verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
mPrivateAddressCoordinator.removeUpstreamPrefix(mMobileNetwork); mPrivateAddressCoordinator.removeUpstreamPrefix(mMobileNetwork);
// 3. Update v4 only mobile network, hotspot prefix should not be removed. // - Update v4 only mobile network, hotspot prefix should not be removed.
final LinkProperties v4OnlyMobileProp = buildUpstreamLinkProperties(true, false, true); final UpstreamNetworkState v4OnlyMobile = buildUpstreamNetworkState(mMobileNetwork,
mPrivateAddressCoordinator.updateUpstreamPrefix(mMobileNetwork, v4OnlyMobileProp); new LinkAddress("10.0.0.8/24"), null,
makeNetworkCapabilities(TRANSPORT_CELLULAR));
mPrivateAddressCoordinator.updateUpstreamPrefix(v4OnlyMobile);
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT); verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
// 4. Update v4v6 mobile network, hotspot prefix should not be removed. // - Update v4v6 mobile network, hotspot prefix should not be removed.
final LinkProperties v4v6MobileProp = buildUpstreamLinkProperties(true, true, true); final UpstreamNetworkState v4v6Mobile = buildUpstreamNetworkState(mMobileNetwork,
mPrivateAddressCoordinator.updateUpstreamPrefix(mMobileNetwork, v4v6MobileProp); new LinkAddress("10.0.0.8/24"), new LinkAddress("2001:db8::/64"),
makeNetworkCapabilities(TRANSPORT_CELLULAR));
mPrivateAddressCoordinator.updateUpstreamPrefix(v4v6Mobile);
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT); verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
// 5. Update v6 only wifi network, hotspot prefix should not be removed. // - Update v6 only wifi network, hotspot prefix should not be removed.
final LinkProperties v6OnlyWifiProp = buildUpstreamLinkProperties(false, true, false); final UpstreamNetworkState v6OnlyWifi = buildUpstreamNetworkState(mWifiNetwork,
mPrivateAddressCoordinator.updateUpstreamPrefix(mWifiNetwork, v6OnlyWifiProp); null, new LinkAddress("2001:db8::/64"), makeNetworkCapabilities(TRANSPORT_WIFI));
mPrivateAddressCoordinator.updateUpstreamPrefix(v6OnlyWifi);
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT); verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
mPrivateAddressCoordinator.removeUpstreamPrefix(mWifiNetwork); mPrivateAddressCoordinator.removeUpstreamPrefix(mWifiNetwork);
// 6. Update v4 only wifi network, it conflict with hotspot prefix. // - Update vpn network, it conflict with hotspot prefix but VPN networks are ignored.
final LinkProperties v4OnlyWifiProp = buildUpstreamLinkProperties(true, false, false); final UpstreamNetworkState v4OnlyVpn = buildUpstreamNetworkState(mVpnNetwork,
mPrivateAddressCoordinator.updateUpstreamPrefix(mWifiNetwork, v4OnlyWifiProp); new LinkAddress("192.168.43.5/24"), null, makeNetworkCapabilities(TRANSPORT_VPN));
mPrivateAddressCoordinator.updateUpstreamPrefix(v4OnlyVpn);
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
// - Update v4 only wifi network, it conflict with hotspot prefix.
final UpstreamNetworkState v4OnlyWifi = buildUpstreamNetworkState(mWifiNetwork,
new LinkAddress("192.168.43.5/24"), null, makeNetworkCapabilities(TRANSPORT_WIFI));
mPrivateAddressCoordinator.updateUpstreamPrefix(v4OnlyWifi);
verify(mHotspotIpServer).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT); verify(mHotspotIpServer).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
reset(mHotspotIpServer); reset(mHotspotIpServer);
// 7. Restart hotspot again and its prefix is different previous. // - Restart hotspot again and its prefix is different previous.
mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer); mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
final LinkAddress hotspotAddr2 = mPrivateAddressCoordinator.requestDownstreamAddress( final LinkAddress hotspotAddr2 = mPrivateAddressCoordinator.requestDownstreamAddress(
mHotspotIpServer); mHotspotIpServer);
final IpPrefix hotspotPrefix2 = PrefixUtils.asIpPrefix(hotspotAddr2); final IpPrefix hotspotPrefix2 = PrefixUtils.asIpPrefix(hotspotAddr2);
assertNotEquals(hotspotPrefix, hotspotPrefix2); assertNotEquals(hotspotPrefix, hotspotPrefix2);
when(mHotspotIpServer.getAddress()).thenReturn(hotspotAddr2); when(mHotspotIpServer.getAddress()).thenReturn(hotspotAddr2);
mPrivateAddressCoordinator.updateUpstreamPrefix(mWifiNetwork, v4OnlyWifiProp); mPrivateAddressCoordinator.updateUpstreamPrefix(v4OnlyWifi);
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT); verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
// 7. Usb tethering can be enabled and its prefix is different with conflict one. // - Usb tethering can be enabled and its prefix is different with conflict one.
final LinkAddress usbAddr = mPrivateAddressCoordinator.requestDownstreamAddress( final LinkAddress usbAddr = mPrivateAddressCoordinator.requestDownstreamAddress(
mUsbIpServer); mUsbIpServer);
final IpPrefix usbPrefix = PrefixUtils.asIpPrefix(usbAddr); final IpPrefix usbPrefix = PrefixUtils.asIpPrefix(usbAddr);
assertNotEquals(predefinedPrefix, usbPrefix); assertNotEquals(predefinedPrefix, usbPrefix);
assertNotEquals(hotspotPrefix2, usbPrefix); assertNotEquals(hotspotPrefix2, usbPrefix);
when(mUsbIpServer.getAddress()).thenReturn(usbAddr); when(mUsbIpServer.getAddress()).thenReturn(usbAddr);
// 8. Disable wifi upstream, then wifi's prefix can be selected again. // - Disable wifi upstream, then wifi's prefix can be selected again.
mPrivateAddressCoordinator.removeUpstreamPrefix(mWifiNetwork); mPrivateAddressCoordinator.removeUpstreamPrefix(mWifiNetwork);
final LinkAddress ethAddr = mPrivateAddressCoordinator.requestDownstreamAddress( final LinkAddress ethAddr = mPrivateAddressCoordinator.requestDownstreamAddress(
mEthernetIpServer); mEthernetIpServer);