Merge changes Ifc8ad902,I6d1b8d0e am: 8d659bb1ec am: 488687d11f am: e669fe43cd

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1453730

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I6f3235dd38e4c4912f986cbb27867ff14fe38e81
This commit is contained in:
Yan Yan
2021-02-12 22:46:32 +00:00
committed by Automerger Merge Worker
3 changed files with 89 additions and 4 deletions

View File

@@ -58,6 +58,9 @@ interface IIpSecService
in LinkAddress localAddr, in LinkAddress localAddr,
in String callingPackage); in String callingPackage);
void setNetworkForTunnelInterface(
int tunnelResourceId, in Network underlyingNetwork, in String callingPackage);
void deleteTunnelInterface(int resourceId, in String callingPackage); void deleteTunnelInterface(int resourceId, in String callingPackage);
IpSecTransformResponse createTransform( IpSecTransformResponse createTransform(

View File

@@ -782,6 +782,42 @@ public final class IpSecManager {
} }
} }
/**
* Update the underlying network for this IpSecTunnelInterface.
*
* <p>This new underlying network will be used for all transforms applied AFTER this call is
* complete. Before new {@link IpSecTransform}(s) with matching addresses are applied to
* this tunnel interface, traffic will still use the old SA, and be routed on the old
* underlying network.
*
* <p>To migrate IPsec tunnel mode traffic, a caller should:
*
* <ol>
* <li>Update the IpSecTunnelInterfaces underlying network.
* <li>Apply {@link IpSecTransform}(s) with matching addresses to this
* IpSecTunnelInterface.
* </ol>
*
* @param underlyingNetwork the new {@link Network} that will carry traffic for this tunnel.
* This network MUST never be the network exposing this IpSecTunnelInterface, otherwise
* this method will throw an {@link IllegalArgumentException}.
*/
// TODO: b/169171001 Update the documentation when transform migration is supported.
// The purpose of making updating network and applying transforms separate is to leave open
// the possibility to support lossless migration procedures. To do that, Android platform
// will need to support multiple inbound tunnel mode transforms, just like it can support
// multiple transport mode transforms.
@RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
@RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
public void setUnderlyingNetwork(@NonNull Network underlyingNetwork) throws IOException {
try {
mService.setNetworkForTunnelInterface(
mResourceId, underlyingNetwork, mOpPackageName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
private IpSecTunnelInterface(@NonNull Context ctx, @NonNull IIpSecService service, private IpSecTunnelInterface(@NonNull Context ctx, @NonNull IIpSecService service,
@NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress, @NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress,
@NonNull Network underlyingNetwork) @NonNull Network underlyingNetwork)

View File

@@ -29,6 +29,7 @@ import android.annotation.NonNull;
import android.app.AppOpsManager; import android.app.AppOpsManager;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.IIpSecService; import android.net.IIpSecService;
import android.net.INetd; import android.net.INetd;
import android.net.InetAddresses; import android.net.InetAddresses;
@@ -41,6 +42,7 @@ import android.net.IpSecTransformResponse;
import android.net.IpSecTunnelInterfaceResponse; import android.net.IpSecTunnelInterfaceResponse;
import android.net.IpSecUdpEncapResponse; import android.net.IpSecUdpEncapResponse;
import android.net.LinkAddress; import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network; import android.net.Network;
import android.net.TrafficStats; import android.net.TrafficStats;
import android.net.util.NetdService; import android.net.util.NetdService;
@@ -797,9 +799,15 @@ public class IpSecService extends IIpSecService.Stub {
} }
} }
private final class TunnelInterfaceRecord extends OwnedResourceRecord { /**
* Tracks an tunnel interface, and manages cleanup paths.
*
* <p>This class is not thread-safe, and expects that that users of this class will ensure
* synchronization and thread safety by holding the IpSecService.this instance lock
*/
@VisibleForTesting
final class TunnelInterfaceRecord extends OwnedResourceRecord {
private final String mInterfaceName; private final String mInterfaceName;
private final Network mUnderlyingNetwork;
// outer addresses // outer addresses
private final String mLocalAddress; private final String mLocalAddress;
@@ -810,6 +818,8 @@ public class IpSecService extends IIpSecService.Stub {
private final int mIfId; private final int mIfId;
private Network mUnderlyingNetwork;
TunnelInterfaceRecord( TunnelInterfaceRecord(
int resourceId, int resourceId,
String interfaceName, String interfaceName,
@@ -870,14 +880,22 @@ public class IpSecService extends IIpSecService.Stub {
releaseNetId(mOkey); releaseNetId(mOkey);
} }
public String getInterfaceName() { @GuardedBy("IpSecService.this")
return mInterfaceName; public void setUnderlyingNetwork(Network underlyingNetwork) {
// When #applyTunnelModeTransform is called, this new underlying network will be used to
// update the output mark of the input transform.
mUnderlyingNetwork = underlyingNetwork;
} }
@GuardedBy("IpSecService.this")
public Network getUnderlyingNetwork() { public Network getUnderlyingNetwork() {
return mUnderlyingNetwork; return mUnderlyingNetwork;
} }
public String getInterfaceName() {
return mInterfaceName;
}
/** Returns the local, outer address for the tunnelInterface */ /** Returns the local, outer address for the tunnelInterface */
public String getLocalAddress() { public String getLocalAddress() {
return mLocalAddress; return mLocalAddress;
@@ -1429,6 +1447,34 @@ public class IpSecService extends IIpSecService.Stub {
} }
} }
/** Set TunnelInterface to use a specific underlying network. */
@Override
public synchronized void setNetworkForTunnelInterface(
int tunnelResourceId, Network underlyingNetwork, String callingPackage) {
enforceTunnelFeatureAndPermissions(callingPackage);
Objects.requireNonNull(underlyingNetwork, "No underlying network was specified");
final UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
// Get tunnelInterface record; if no such interface is found, will throw
// IllegalArgumentException. userRecord.mTunnelInterfaceRecords is never null
final TunnelInterfaceRecord tunnelInterfaceInfo =
userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelResourceId);
final ConnectivityManager connectivityManager =
mContext.getSystemService(ConnectivityManager.class);
final LinkProperties lp = connectivityManager.getLinkProperties(underlyingNetwork);
if (tunnelInterfaceInfo.getInterfaceName().equals(lp.getInterfaceName())) {
throw new IllegalArgumentException(
"Underlying network cannot be the network being exposed by this tunnel");
}
// It is meaningless to check if the network exists or is valid because the network might
// disconnect at any time after it passes the check.
tunnelInterfaceInfo.setUnderlyingNetwork(underlyingNetwork);
}
/** /**
* Delete a TunnelInterface that has been been allocated by and registered with the system * Delete a TunnelInterface that has been been allocated by and registered with the system
* server * server