Merge changes I3dd45b29,Ic177015f am: 67c7cd81a7
Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/2264261 Change-Id: Ie32a8ef9886cd832f4a22ccd6c30c93dfbf5967c Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -66,6 +66,12 @@ interface IIpSecService
|
||||
IpSecTransformResponse createTransform(
|
||||
in IpSecConfig c, in IBinder binder, in String callingPackage);
|
||||
|
||||
void migrateTransform(
|
||||
int transformId,
|
||||
in String newSourceAddress,
|
||||
in String newDestinationAddress,
|
||||
in String callingPackage);
|
||||
|
||||
void deleteTransform(int transformId);
|
||||
|
||||
void applyTransportModeTransform(
|
||||
|
||||
@@ -37,6 +37,7 @@ import android.util.AndroidException;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.modules.utils.build.SdkLevel;
|
||||
|
||||
import dalvik.system.CloseGuard;
|
||||
|
||||
@@ -64,6 +65,24 @@ import java.util.Objects;
|
||||
public class IpSecManager {
|
||||
private static final String TAG = "IpSecManager";
|
||||
|
||||
/**
|
||||
* Feature flag to declare the kernel support of updating IPsec SAs.
|
||||
*
|
||||
* <p>Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device
|
||||
* has the requisite kernel support for migrating IPsec tunnels to new source/destination
|
||||
* addresses.
|
||||
*
|
||||
* <p>This feature implies that the device supports XFRM Migration (CONFIG_XFRM_MIGRATE) and has
|
||||
* the kernel fixes to allow XFRM Migration correctly
|
||||
*
|
||||
* @see android.content.pm.PackageManager#FEATURE_IPSEC_TUNNEL_MIGRATION
|
||||
* @hide
|
||||
*/
|
||||
// Redefine this flag here so that IPsec code shipped in a mainline module can build on old
|
||||
// platforms before FEATURE_IPSEC_TUNNEL_MIGRATION API is released.
|
||||
public static final String FEATURE_IPSEC_TUNNEL_MIGRATION =
|
||||
"android.software.ipsec_tunnel_migration";
|
||||
|
||||
/**
|
||||
* Used when applying a transform to direct traffic through an {@link IpSecTransform}
|
||||
* towards the host.
|
||||
@@ -987,6 +1006,59 @@ public class IpSecManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate an active Tunnel Mode IPsec Transform to new source/destination addresses.
|
||||
*
|
||||
* <p>Begins the process of migrating a transform and cache the new addresses. To complete the
|
||||
* migration once started, callers MUST apply the same transform to the appropriate tunnel using
|
||||
* {@link IpSecManager#applyTunnelModeTransform}. Otherwise, the address update will not be
|
||||
* committed and the transform will still only process traffic between the current source and
|
||||
* destination address. One common use case is that the control plane will start the migration
|
||||
* process and then hand off the transform to the IPsec caller to perform the actual migration
|
||||
* when the tunnel is ready.
|
||||
*
|
||||
* <p>If this method is called multiple times before {@link
|
||||
* IpSecManager#applyTunnelModeTransform} is called, when the transform is applied, it will be
|
||||
* migrated to the addresses from the last call.
|
||||
*
|
||||
* <p>The provided source and destination addresses MUST share the same address family, but they
|
||||
* can have a different family from the current addresses.
|
||||
*
|
||||
* <p>Transform migration is only supported for tunnel mode transforms. Calling this method on
|
||||
* other types of transforms will throw an {@code UnsupportedOperationException}.
|
||||
*
|
||||
* @see IpSecTunnelInterface#setUnderlyingNetwork
|
||||
* @param transform a tunnel mode {@link IpSecTransform}
|
||||
* @param newSourceAddress the new source address
|
||||
* @param newDestinationAddress the new destination address
|
||||
* @hide
|
||||
*/
|
||||
@RequiresFeature(FEATURE_IPSEC_TUNNEL_MIGRATION)
|
||||
@RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
|
||||
public void startMigration(
|
||||
@NonNull IpSecTransform transform,
|
||||
@NonNull InetAddress newSourceAddress,
|
||||
@NonNull InetAddress newDestinationAddress) {
|
||||
if (!SdkLevel.isAtLeastU()) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Transform migration only supported for Android 14+");
|
||||
}
|
||||
|
||||
Objects.requireNonNull(transform, "transform was null");
|
||||
Objects.requireNonNull(newSourceAddress, "newSourceAddress was null");
|
||||
Objects.requireNonNull(newDestinationAddress, "newDestinationAddress was null");
|
||||
|
||||
try {
|
||||
mService.migrateTransform(
|
||||
transform.getResourceId(),
|
||||
newSourceAddress.getHostAddress(),
|
||||
newDestinationAddress.getHostAddress(),
|
||||
mContext.getOpPackageName());
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.server;
|
||||
|
||||
import static android.Manifest.permission.DUMP;
|
||||
import static android.net.IpSecManager.FEATURE_IPSEC_TUNNEL_MIGRATION;
|
||||
import static android.net.IpSecManager.INVALID_RESOURCE_ID;
|
||||
import static android.system.OsConstants.AF_INET;
|
||||
import static android.system.OsConstants.AF_INET6;
|
||||
@@ -36,6 +37,7 @@ import android.net.InetAddresses;
|
||||
import android.net.IpSecAlgorithm;
|
||||
import android.net.IpSecConfig;
|
||||
import android.net.IpSecManager;
|
||||
import android.net.IpSecMigrateInfoParcel;
|
||||
import android.net.IpSecSpiResponse;
|
||||
import android.net.IpSecTransform;
|
||||
import android.net.IpSecTransformResponse;
|
||||
@@ -590,14 +592,19 @@ public class IpSecService extends IIpSecService.Stub {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks an SA in the kernel, and manages cleanup paths. Once a TransformRecord is
|
||||
* created, the SpiRecord that originally tracked the SAs will reliquish the
|
||||
* responsibility of freeing the underlying SA to this class via the mOwnedByTransform flag.
|
||||
* Tracks an SA in the kernel, and manages cleanup paths. Once a TransformRecord is created, the
|
||||
* SpiRecord that originally tracked the SAs will reliquish the responsibility of freeing the
|
||||
* underlying SA to this class via the mOwnedByTransform flag.
|
||||
*
|
||||
* <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
|
||||
*/
|
||||
private final class TransformRecord extends OwnedResourceRecord {
|
||||
private final IpSecConfig mConfig;
|
||||
private final SpiRecord mSpi;
|
||||
private final EncapSocketRecord mSocket;
|
||||
private String mNewSourceAddress = null;
|
||||
private String mNewDestinationAddress = null;
|
||||
|
||||
TransformRecord(
|
||||
int resourceId, IpSecConfig config, SpiRecord spi, EncapSocketRecord socket) {
|
||||
@@ -621,6 +628,51 @@ public class IpSecService extends IIpSecService.Stub {
|
||||
return mSocket;
|
||||
}
|
||||
|
||||
@GuardedBy("IpSecService.this")
|
||||
public String getNewSourceAddress() {
|
||||
return mNewSourceAddress;
|
||||
}
|
||||
|
||||
@GuardedBy("IpSecService.this")
|
||||
public String getNewDestinationAddress() {
|
||||
return mNewDestinationAddress;
|
||||
}
|
||||
|
||||
private void verifyTunnelModeOrThrow() {
|
||||
if (mConfig.getMode() != IpSecTransform.MODE_TUNNEL) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Migration requested/called on non-tunnel-mode transform");
|
||||
}
|
||||
}
|
||||
|
||||
/** Start migrating this transform to new source and destination addresses */
|
||||
@GuardedBy("IpSecService.this")
|
||||
public void startMigration(String newSourceAddress, String newDestinationAddress) {
|
||||
verifyTunnelModeOrThrow();
|
||||
Objects.requireNonNull(newSourceAddress, "newSourceAddress was null");
|
||||
Objects.requireNonNull(newDestinationAddress, "newDestinationAddress was null");
|
||||
mNewSourceAddress = newSourceAddress;
|
||||
mNewDestinationAddress = newDestinationAddress;
|
||||
}
|
||||
|
||||
/** Finish migration and update addresses. */
|
||||
@GuardedBy("IpSecService.this")
|
||||
public void finishMigration() {
|
||||
verifyTunnelModeOrThrow();
|
||||
mConfig.setSourceAddress(mNewSourceAddress);
|
||||
mConfig.setDestinationAddress(mNewDestinationAddress);
|
||||
mNewSourceAddress = null;
|
||||
mNewDestinationAddress = null;
|
||||
}
|
||||
|
||||
/** Return if this transform is going to be migrated. */
|
||||
@GuardedBy("IpSecService.this")
|
||||
public boolean isMigrating() {
|
||||
verifyTunnelModeOrThrow();
|
||||
|
||||
return mNewSourceAddress != null;
|
||||
}
|
||||
|
||||
/** always guarded by IpSecService#this */
|
||||
@Override
|
||||
public void freeUnderlyingResources() {
|
||||
@@ -1630,6 +1682,14 @@ public class IpSecService extends IIpSecService.Stub {
|
||||
android.Manifest.permission.MANAGE_IPSEC_TUNNELS, "IpSecService");
|
||||
}
|
||||
|
||||
private void enforceMigrateFeature() {
|
||||
if (!mContext.getPackageManager().hasSystemFeature(FEATURE_IPSEC_TUNNEL_MIGRATION)) {
|
||||
throw new UnsupportedOperationException(
|
||||
"IPsec Tunnel migration requires"
|
||||
+ " PackageManager.FEATURE_IPSEC_TUNNEL_MIGRATION");
|
||||
}
|
||||
}
|
||||
|
||||
private void createOrUpdateTransform(
|
||||
IpSecConfig c, int resourceId, SpiRecord spiRecord, EncapSocketRecord socketRecord)
|
||||
throws RemoteException {
|
||||
@@ -1725,6 +1785,45 @@ public class IpSecService extends IIpSecService.Stub {
|
||||
return new IpSecTransformResponse(IpSecManager.Status.OK, resourceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate an active Tunnel Mode IPsec Transform to new source/destination addresses.
|
||||
*
|
||||
* <p>Begins the process of migrating a transform and cache the new addresses. To complete the
|
||||
* migration once started, callers MUST apply the same transform to the appropriate tunnel using
|
||||
* {@link #applyTunnelModeTransform}. Otherwise, the address update will not be committed and
|
||||
* the transform will still only process traffic between the current source and destination
|
||||
* address. One common use case is that the control plane will start the migration process and
|
||||
* then hand off the transform to the IPsec caller to perform the actual migration when the
|
||||
* tunnel is ready.
|
||||
*
|
||||
* <p>If this method is called multiple times before {@link #applyTunnelModeTransform} is
|
||||
* called, when the transform is applied, it will be migrated to the addresses from the last
|
||||
* call.
|
||||
*
|
||||
* <p>The provided source and destination addresses MUST share the same address family, but they
|
||||
* can have a different family from the current addresses.
|
||||
*
|
||||
* <p>Transform migration is only supported for tunnel mode transforms. Calling this method on
|
||||
* other types of transforms will throw an {@code UnsupportedOperationException}.
|
||||
*/
|
||||
@Override
|
||||
public synchronized void migrateTransform(
|
||||
int transformId,
|
||||
String newSourceAddress,
|
||||
String newDestinationAddress,
|
||||
String callingPackage) {
|
||||
Objects.requireNonNull(newSourceAddress, "newSourceAddress was null");
|
||||
Objects.requireNonNull(newDestinationAddress, "newDestinationAddress was null");
|
||||
|
||||
enforceTunnelFeatureAndPermissions(callingPackage);
|
||||
enforceMigrateFeature();
|
||||
|
||||
UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
|
||||
TransformRecord transformInfo =
|
||||
userRecord.mTransformRecords.getResourceOrThrow(transformId);
|
||||
transformInfo.startMigration(newSourceAddress, newDestinationAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a transport mode transform that was previously allocated by + registered with the
|
||||
* system server. If this is called on an inactive (or non-existent) transform, it will not
|
||||
@@ -1784,12 +1883,15 @@ public class IpSecService extends IIpSecService.Stub {
|
||||
|
||||
/**
|
||||
* Apply an active tunnel mode transform to a TunnelInterface, which will apply the IPsec
|
||||
* security association as a correspondent policy to the provided interface
|
||||
* security association as a correspondent policy to the provided interface.
|
||||
*
|
||||
* <p>If the transform is migrating, migrate the IPsec security association to new
|
||||
* source/destination addresses, and mark the migration as finished.
|
||||
*/
|
||||
@Override
|
||||
public synchronized void applyTunnelModeTransform(
|
||||
int tunnelResourceId, int direction,
|
||||
int transformResourceId, String callingPackage) throws RemoteException {
|
||||
int tunnelResourceId, int direction, int transformResourceId, String callingPackage)
|
||||
throws RemoteException {
|
||||
enforceTunnelFeatureAndPermissions(callingPackage);
|
||||
checkDirection(direction);
|
||||
|
||||
@@ -1868,6 +1970,32 @@ public class IpSecService extends IIpSecService.Stub {
|
||||
|
||||
// Update SA with tunnel mark (ikey or okey based on direction)
|
||||
createOrUpdateTransform(c, transformResourceId, spiRecord, socketRecord);
|
||||
|
||||
if (transformInfo.isMigrating()) {
|
||||
if (!mContext.getPackageManager()
|
||||
.hasSystemFeature(FEATURE_IPSEC_TUNNEL_MIGRATION)) {
|
||||
Log.wtf(
|
||||
TAG,
|
||||
"Attempted to migrate a transform without"
|
||||
+ " FEATURE_IPSEC_TUNNEL_MIGRATION");
|
||||
}
|
||||
|
||||
for (int selAddrFamily : ADDRESS_FAMILIES) {
|
||||
final IpSecMigrateInfoParcel migrateInfo =
|
||||
new IpSecMigrateInfoParcel(
|
||||
Binder.getCallingUid(),
|
||||
selAddrFamily,
|
||||
direction,
|
||||
c.getSourceAddress(),
|
||||
c.getDestinationAddress(),
|
||||
transformInfo.getNewSourceAddress(),
|
||||
transformInfo.getNewDestinationAddress(),
|
||||
c.getXfrmInterfaceId());
|
||||
|
||||
mNetd.ipSecMigrate(migrateInfo);
|
||||
}
|
||||
transformInfo.finishMigration();
|
||||
}
|
||||
} catch (ServiceSpecificException e) {
|
||||
if (e.errorCode == EINVAL) {
|
||||
throw new IllegalArgumentException(e.toString());
|
||||
|
||||
@@ -18,22 +18,92 @@ package android.net;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.test.mock.MockContext;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.server.IpSecService;
|
||||
import com.android.testutils.DevSdkIgnoreRule;
|
||||
import com.android.testutils.DevSdkIgnoreRunner;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.net.InetAddress;
|
||||
|
||||
/** Unit tests for {@link IpSecTransform}. */
|
||||
@SmallTest
|
||||
@RunWith(DevSdkIgnoreRunner.class)
|
||||
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
|
||||
public class IpSecTransformTest {
|
||||
@Rule public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
|
||||
|
||||
private static final int DROID_SPI = 0xD1201D;
|
||||
private static final int TEST_RESOURCE_ID = 0x1234;
|
||||
|
||||
private static final InetAddress SRC_ADDRESS = InetAddresses.parseNumericAddress("192.0.2.200");
|
||||
private static final InetAddress DST_ADDRESS = InetAddresses.parseNumericAddress("192.0.2.201");
|
||||
private static final InetAddress SRC_ADDRESS_V6 =
|
||||
InetAddresses.parseNumericAddress("2001:db8::200");
|
||||
private static final InetAddress DST_ADDRESS_V6 =
|
||||
InetAddresses.parseNumericAddress("2001:db8::201");
|
||||
|
||||
private MockContext mMockContext;
|
||||
private IpSecService mMockIpSecService;
|
||||
private IpSecManager mIpSecManager;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
mMockIpSecService = mock(IpSecService.class);
|
||||
mIpSecManager = new IpSecManager(mock(Context.class) /* unused */, mMockIpSecService);
|
||||
|
||||
// Set up mMockContext since IpSecTransform needs an IpSecManager instance and a non-null
|
||||
// package name to create transform
|
||||
mMockContext =
|
||||
new MockContext() {
|
||||
@Override
|
||||
public String getSystemServiceName(Class<?> serviceClass) {
|
||||
if (serviceClass.equals(IpSecManager.class)) {
|
||||
return Context.IPSEC_SERVICE;
|
||||
}
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSystemService(String name) {
|
||||
if (name.equals(Context.IPSEC_SERVICE)) {
|
||||
return mIpSecManager;
|
||||
}
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOpPackageName() {
|
||||
return "fooPackage";
|
||||
}
|
||||
};
|
||||
|
||||
final IpSecSpiResponse spiResp =
|
||||
new IpSecSpiResponse(IpSecManager.Status.OK, TEST_RESOURCE_ID, DROID_SPI);
|
||||
when(mMockIpSecService.allocateSecurityParameterIndex(any(), anyInt(), any()))
|
||||
.thenReturn(spiResp);
|
||||
|
||||
final IpSecTransformResponse transformResp =
|
||||
new IpSecTransformResponse(IpSecManager.Status.OK, TEST_RESOURCE_ID);
|
||||
when(mMockIpSecService.createTransform(any(), any(), any())).thenReturn(transformResp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateTransformCopiesConfig() {
|
||||
@@ -64,4 +134,32 @@ public class IpSecTransformTest {
|
||||
|
||||
assertEquals(config1, config2);
|
||||
}
|
||||
|
||||
private IpSecTransform buildTestTransform() throws Exception {
|
||||
final IpSecManager.SecurityParameterIndex spi =
|
||||
mIpSecManager.allocateSecurityParameterIndex(DST_ADDRESS);
|
||||
return new IpSecTransform.Builder(mMockContext).buildTunnelModeTransform(SRC_ADDRESS, spi);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
|
||||
public void testStartMigration() throws Exception {
|
||||
mIpSecManager.startMigration(buildTestTransform(), SRC_ADDRESS_V6, DST_ADDRESS_V6);
|
||||
verify(mMockIpSecService)
|
||||
.migrateTransform(
|
||||
anyInt(),
|
||||
eq(SRC_ADDRESS_V6.getHostAddress()),
|
||||
eq(DST_ADDRESS_V6.getHostAddress()),
|
||||
any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DevSdkIgnoreRule.IgnoreAfter(Build.VERSION_CODES.TIRAMISU)
|
||||
public void testStartMigrationOnSdkBeforeU() throws Exception {
|
||||
try {
|
||||
mIpSecManager.startMigration(buildTestTransform(), SRC_ADDRESS_V6, DST_ADDRESS_V6);
|
||||
fail("Expect to fail since migration is not supported before U");
|
||||
} catch (UnsupportedOperationException expected) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import static android.net.INetd.IF_STATE_UP;
|
||||
import static android.net.IpSecManager.DIRECTION_FWD;
|
||||
import static android.net.IpSecManager.DIRECTION_IN;
|
||||
import static android.net.IpSecManager.DIRECTION_OUT;
|
||||
import static android.net.IpSecManager.FEATURE_IPSEC_TUNNEL_MIGRATION;
|
||||
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
|
||||
import static android.system.OsConstants.AF_INET;
|
||||
import static android.system.OsConstants.AF_INET6;
|
||||
@@ -30,11 +31,16 @@ import static android.system.OsConstants.AF_INET6;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -49,6 +55,7 @@ import android.net.InterfaceConfigurationParcel;
|
||||
import android.net.IpSecAlgorithm;
|
||||
import android.net.IpSecConfig;
|
||||
import android.net.IpSecManager;
|
||||
import android.net.IpSecMigrateInfoParcel;
|
||||
import android.net.IpSecSpiResponse;
|
||||
import android.net.IpSecTransform;
|
||||
import android.net.IpSecTransformResponse;
|
||||
@@ -130,6 +137,9 @@ public class IpSecServiceParameterizedTest {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F
|
||||
};
|
||||
|
||||
private static final String NEW_SRC_ADDRESS = "2001:db8:2::1";
|
||||
private static final String NEW_DST_ADDRESS = "2001:db8:2::2";
|
||||
|
||||
AppOpsManager mMockAppOps = mock(AppOpsManager.class);
|
||||
ConnectivityManager mMockConnectivityMgr = mock(ConnectivityManager.class);
|
||||
|
||||
@@ -369,8 +379,8 @@ public class IpSecServiceParameterizedTest {
|
||||
.ipSecAddSecurityAssociation(
|
||||
eq(mUid),
|
||||
eq(config.getMode()),
|
||||
eq(config.getSourceAddress()),
|
||||
eq(config.getDestinationAddress()),
|
||||
eq(mSourceAddr),
|
||||
eq(mDestinationAddr),
|
||||
eq((config.getNetwork() != null) ? config.getNetwork().netId : 0),
|
||||
eq(TEST_SPI),
|
||||
eq(0),
|
||||
@@ -910,9 +920,60 @@ public class IpSecServiceParameterizedTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
|
||||
public void testApplyAndMigrateTunnelModeTransformOutbound() throws Exception {
|
||||
verifyApplyAndMigrateTunnelModeTransformCommon(false, DIRECTION_OUT);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
|
||||
public void testApplyAndMigrateTunnelModeTransformOutboundReleasedSpi() throws Exception {
|
||||
verifyApplyAndMigrateTunnelModeTransformCommon(true, DIRECTION_OUT);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
|
||||
public void testApplyAndMigrateTunnelModeTransformInbound() throws Exception {
|
||||
verifyApplyAndMigrateTunnelModeTransformCommon(false, DIRECTION_IN);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
|
||||
public void testApplyAndMigrateTunnelModeTransformInboundReleasedSpi() throws Exception {
|
||||
verifyApplyAndMigrateTunnelModeTransformCommon(true, DIRECTION_IN);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
|
||||
public void testApplyAndMigrateTunnelModeTransformForward() throws Exception {
|
||||
verifyApplyAndMigrateTunnelModeTransformCommon(false, DIRECTION_FWD);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
|
||||
public void testApplyAndMigrateTunnelModeTransformForwardReleasedSpi() throws Exception {
|
||||
verifyApplyAndMigrateTunnelModeTransformCommon(true, DIRECTION_FWD);
|
||||
}
|
||||
|
||||
public void verifyApplyTunnelModeTransformCommon(boolean closeSpiBeforeApply, int direction)
|
||||
throws Exception {
|
||||
IpSecConfig ipSecConfig = new IpSecConfig();
|
||||
verifyApplyTunnelModeTransformCommon(
|
||||
new IpSecConfig(), closeSpiBeforeApply, false /* isMigrating */, direction);
|
||||
}
|
||||
|
||||
public void verifyApplyAndMigrateTunnelModeTransformCommon(
|
||||
boolean closeSpiBeforeApply, int direction) throws Exception {
|
||||
verifyApplyTunnelModeTransformCommon(
|
||||
new IpSecConfig(), closeSpiBeforeApply, true /* isMigrating */, direction);
|
||||
}
|
||||
|
||||
public int verifyApplyTunnelModeTransformCommon(
|
||||
IpSecConfig ipSecConfig,
|
||||
boolean closeSpiBeforeApply,
|
||||
boolean isMigrating,
|
||||
int direction)
|
||||
throws Exception {
|
||||
ipSecConfig.setMode(IpSecTransform.MODE_TUNNEL);
|
||||
addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
|
||||
addAuthAndCryptToIpSecConfig(ipSecConfig);
|
||||
@@ -928,6 +989,12 @@ public class IpSecServiceParameterizedTest {
|
||||
|
||||
int transformResourceId = createTransformResp.resourceId;
|
||||
int tunnelResourceId = createTunnelResp.resourceId;
|
||||
|
||||
if (isMigrating) {
|
||||
mIpSecService.migrateTransform(
|
||||
transformResourceId, NEW_SRC_ADDRESS, NEW_DST_ADDRESS, BLESSED_PACKAGE);
|
||||
}
|
||||
|
||||
mIpSecService.applyTunnelModeTransform(
|
||||
tunnelResourceId, direction, transformResourceId, BLESSED_PACKAGE);
|
||||
|
||||
@@ -947,8 +1014,16 @@ public class IpSecServiceParameterizedTest {
|
||||
|
||||
ipSecConfig.setXfrmInterfaceId(tunnelResourceId);
|
||||
verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp);
|
||||
}
|
||||
|
||||
if (isMigrating) {
|
||||
verify(mMockNetd, times(ADDRESS_FAMILIES.length))
|
||||
.ipSecMigrate(any(IpSecMigrateInfoParcel.class));
|
||||
} else {
|
||||
verify(mMockNetd, never()).ipSecMigrate(any());
|
||||
}
|
||||
|
||||
return tunnelResourceId;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApplyTunnelModeTransformWithClosedSpi() throws Exception {
|
||||
@@ -1023,7 +1098,7 @@ public class IpSecServiceParameterizedTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFeatureFlagVerification() throws Exception {
|
||||
public void testFeatureFlagIpSecTunnelsVerification() throws Exception {
|
||||
when(mMockPkgMgr.hasSystemFeature(eq(PackageManager.FEATURE_IPSEC_TUNNELS)))
|
||||
.thenReturn(false);
|
||||
|
||||
@@ -1035,4 +1110,17 @@ public class IpSecServiceParameterizedTest {
|
||||
} catch (UnsupportedOperationException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
|
||||
public void testFeatureFlagIpSecTunnelMigrationVerification() throws Exception {
|
||||
when(mMockPkgMgr.hasSystemFeature(eq(FEATURE_IPSEC_TUNNEL_MIGRATION))).thenReturn(false);
|
||||
|
||||
try {
|
||||
mIpSecService.migrateTransform(
|
||||
1 /* transformId */, NEW_SRC_ADDRESS, NEW_DST_ADDRESS, BLESSED_PACKAGE);
|
||||
fail("Expected UnsupportedOperationException for disabled feature");
|
||||
} catch (UnsupportedOperationException expected) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user