Support IPsec transform migration
This commit adds methods to support migrating tunnel mode IpSecTransform to new source/destination addresses. Bug: 169171001 Test: atest FrameworksNetTests (new tests added) Change-Id: Ic177015fba5b62d3f73009633118109d3631086f
This commit is contained in:
@@ -66,6 +66,12 @@ interface IIpSecService
|
|||||||
IpSecTransformResponse createTransform(
|
IpSecTransformResponse createTransform(
|
||||||
in IpSecConfig c, in IBinder binder, in String callingPackage);
|
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 deleteTransform(int transformId);
|
||||||
|
|
||||||
void applyTransportModeTransform(
|
void applyTransportModeTransform(
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import android.util.AndroidException;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
import com.android.modules.utils.build.SdkLevel;
|
||||||
|
|
||||||
import dalvik.system.CloseGuard;
|
import dalvik.system.CloseGuard;
|
||||||
|
|
||||||
@@ -987,6 +988,60 @@ 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
|
||||||
|
*/
|
||||||
|
// TODO: b/169169973 Require FEATURE_IPSEC_MIGRATE
|
||||||
|
@RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
|
||||||
|
@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
|
* @hide
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import android.net.InetAddresses;
|
|||||||
import android.net.IpSecAlgorithm;
|
import android.net.IpSecAlgorithm;
|
||||||
import android.net.IpSecConfig;
|
import android.net.IpSecConfig;
|
||||||
import android.net.IpSecManager;
|
import android.net.IpSecManager;
|
||||||
|
import android.net.IpSecMigrateInfoParcel;
|
||||||
import android.net.IpSecSpiResponse;
|
import android.net.IpSecSpiResponse;
|
||||||
import android.net.IpSecTransform;
|
import android.net.IpSecTransform;
|
||||||
import android.net.IpSecTransformResponse;
|
import android.net.IpSecTransformResponse;
|
||||||
@@ -590,14 +591,19 @@ public class IpSecService extends IIpSecService.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tracks an SA in the kernel, and manages cleanup paths. Once a TransformRecord is
|
* Tracks an SA in the kernel, and manages cleanup paths. Once a TransformRecord is created, the
|
||||||
* created, the SpiRecord that originally tracked the SAs will reliquish the
|
* SpiRecord that originally tracked the SAs will reliquish the responsibility of freeing the
|
||||||
* responsibility of freeing the underlying SA to this class via the mOwnedByTransform flag.
|
* 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 class TransformRecord extends OwnedResourceRecord {
|
||||||
private final IpSecConfig mConfig;
|
private final IpSecConfig mConfig;
|
||||||
private final SpiRecord mSpi;
|
private final SpiRecord mSpi;
|
||||||
private final EncapSocketRecord mSocket;
|
private final EncapSocketRecord mSocket;
|
||||||
|
private String mNewSourceAddress = null;
|
||||||
|
private String mNewDestinationAddress = null;
|
||||||
|
|
||||||
TransformRecord(
|
TransformRecord(
|
||||||
int resourceId, IpSecConfig config, SpiRecord spi, EncapSocketRecord socket) {
|
int resourceId, IpSecConfig config, SpiRecord spi, EncapSocketRecord socket) {
|
||||||
@@ -621,6 +627,51 @@ public class IpSecService extends IIpSecService.Stub {
|
|||||||
return mSocket;
|
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 */
|
/** always guarded by IpSecService#this */
|
||||||
@Override
|
@Override
|
||||||
public void freeUnderlyingResources() {
|
public void freeUnderlyingResources() {
|
||||||
@@ -1725,6 +1776,44 @@ public class IpSecService extends IIpSecService.Stub {
|
|||||||
return new IpSecTransformResponse(IpSecManager.Status.OK, resourceId);
|
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);
|
||||||
|
|
||||||
|
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
|
* 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
|
* system server. If this is called on an inactive (or non-existent) transform, it will not
|
||||||
@@ -1784,12 +1873,15 @@ public class IpSecService extends IIpSecService.Stub {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply an active tunnel mode transform to a TunnelInterface, which will apply the IPsec
|
* 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
|
@Override
|
||||||
public synchronized void applyTunnelModeTransform(
|
public synchronized void applyTunnelModeTransform(
|
||||||
int tunnelResourceId, int direction,
|
int tunnelResourceId, int direction, int transformResourceId, String callingPackage)
|
||||||
int transformResourceId, String callingPackage) throws RemoteException {
|
throws RemoteException {
|
||||||
enforceTunnelFeatureAndPermissions(callingPackage);
|
enforceTunnelFeatureAndPermissions(callingPackage);
|
||||||
checkDirection(direction);
|
checkDirection(direction);
|
||||||
|
|
||||||
@@ -1868,6 +1960,24 @@ public class IpSecService extends IIpSecService.Stub {
|
|||||||
|
|
||||||
// Update SA with tunnel mark (ikey or okey based on direction)
|
// Update SA with tunnel mark (ikey or okey based on direction)
|
||||||
createOrUpdateTransform(c, transformResourceId, spiRecord, socketRecord);
|
createOrUpdateTransform(c, transformResourceId, spiRecord, socketRecord);
|
||||||
|
|
||||||
|
if (transformInfo.isMigrating()) {
|
||||||
|
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) {
|
} catch (ServiceSpecificException e) {
|
||||||
if (e.errorCode == EINVAL) {
|
if (e.errorCode == EINVAL) {
|
||||||
throw new IllegalArgumentException(e.toString());
|
throw new IllegalArgumentException(e.toString());
|
||||||
|
|||||||
@@ -18,22 +18,92 @@ package android.net;
|
|||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotEquals;
|
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.os.Build;
|
||||||
|
import android.test.mock.MockContext;
|
||||||
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
|
import com.android.server.IpSecService;
|
||||||
import com.android.testutils.DevSdkIgnoreRule;
|
import com.android.testutils.DevSdkIgnoreRule;
|
||||||
import com.android.testutils.DevSdkIgnoreRunner;
|
import com.android.testutils.DevSdkIgnoreRunner;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
|
||||||
/** Unit tests for {@link IpSecTransform}. */
|
/** Unit tests for {@link IpSecTransform}. */
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@RunWith(DevSdkIgnoreRunner.class)
|
@RunWith(DevSdkIgnoreRunner.class)
|
||||||
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
|
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
|
||||||
public class IpSecTransformTest {
|
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
|
@Test
|
||||||
public void testCreateTransformCopiesConfig() {
|
public void testCreateTransformCopiesConfig() {
|
||||||
@@ -64,4 +134,32 @@ public class IpSecTransformTest {
|
|||||||
|
|
||||||
assertEquals(config1, config2);
|
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) {
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,11 +30,16 @@ import static android.system.OsConstants.AF_INET6;
|
|||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.fail;
|
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.argThat;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Matchers.anyInt;
|
import static org.mockito.Matchers.anyInt;
|
||||||
import static org.mockito.Matchers.anyString;
|
import static org.mockito.Matchers.anyString;
|
||||||
import static org.mockito.Matchers.eq;
|
import static org.mockito.Matchers.eq;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
@@ -49,6 +54,7 @@ import android.net.InterfaceConfigurationParcel;
|
|||||||
import android.net.IpSecAlgorithm;
|
import android.net.IpSecAlgorithm;
|
||||||
import android.net.IpSecConfig;
|
import android.net.IpSecConfig;
|
||||||
import android.net.IpSecManager;
|
import android.net.IpSecManager;
|
||||||
|
import android.net.IpSecMigrateInfoParcel;
|
||||||
import android.net.IpSecSpiResponse;
|
import android.net.IpSecSpiResponse;
|
||||||
import android.net.IpSecTransform;
|
import android.net.IpSecTransform;
|
||||||
import android.net.IpSecTransformResponse;
|
import android.net.IpSecTransformResponse;
|
||||||
@@ -130,6 +136,9 @@ public class IpSecServiceParameterizedTest {
|
|||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F
|
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);
|
AppOpsManager mMockAppOps = mock(AppOpsManager.class);
|
||||||
ConnectivityManager mMockConnectivityMgr = mock(ConnectivityManager.class);
|
ConnectivityManager mMockConnectivityMgr = mock(ConnectivityManager.class);
|
||||||
|
|
||||||
@@ -369,8 +378,8 @@ public class IpSecServiceParameterizedTest {
|
|||||||
.ipSecAddSecurityAssociation(
|
.ipSecAddSecurityAssociation(
|
||||||
eq(mUid),
|
eq(mUid),
|
||||||
eq(config.getMode()),
|
eq(config.getMode()),
|
||||||
eq(config.getSourceAddress()),
|
eq(mSourceAddr),
|
||||||
eq(config.getDestinationAddress()),
|
eq(mDestinationAddr),
|
||||||
eq((config.getNetwork() != null) ? config.getNetwork().netId : 0),
|
eq((config.getNetwork() != null) ? config.getNetwork().netId : 0),
|
||||||
eq(TEST_SPI),
|
eq(TEST_SPI),
|
||||||
eq(0),
|
eq(0),
|
||||||
@@ -910,9 +919,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)
|
public void verifyApplyTunnelModeTransformCommon(boolean closeSpiBeforeApply, int direction)
|
||||||
throws Exception {
|
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);
|
ipSecConfig.setMode(IpSecTransform.MODE_TUNNEL);
|
||||||
addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
|
addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
|
||||||
addAuthAndCryptToIpSecConfig(ipSecConfig);
|
addAuthAndCryptToIpSecConfig(ipSecConfig);
|
||||||
@@ -928,6 +988,12 @@ public class IpSecServiceParameterizedTest {
|
|||||||
|
|
||||||
int transformResourceId = createTransformResp.resourceId;
|
int transformResourceId = createTransformResp.resourceId;
|
||||||
int tunnelResourceId = createTunnelResp.resourceId;
|
int tunnelResourceId = createTunnelResp.resourceId;
|
||||||
|
|
||||||
|
if (isMigrating) {
|
||||||
|
mIpSecService.migrateTransform(
|
||||||
|
transformResourceId, NEW_SRC_ADDRESS, NEW_DST_ADDRESS, BLESSED_PACKAGE);
|
||||||
|
}
|
||||||
|
|
||||||
mIpSecService.applyTunnelModeTransform(
|
mIpSecService.applyTunnelModeTransform(
|
||||||
tunnelResourceId, direction, transformResourceId, BLESSED_PACKAGE);
|
tunnelResourceId, direction, transformResourceId, BLESSED_PACKAGE);
|
||||||
|
|
||||||
@@ -947,8 +1013,16 @@ public class IpSecServiceParameterizedTest {
|
|||||||
|
|
||||||
ipSecConfig.setXfrmInterfaceId(tunnelResourceId);
|
ipSecConfig.setXfrmInterfaceId(tunnelResourceId);
|
||||||
verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp);
|
verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp);
|
||||||
}
|
|
||||||
|
|
||||||
|
if (isMigrating) {
|
||||||
|
verify(mMockNetd, times(ADDRESS_FAMILIES.length))
|
||||||
|
.ipSecMigrate(any(IpSecMigrateInfoParcel.class));
|
||||||
|
} else {
|
||||||
|
verify(mMockNetd, never()).ipSecMigrate(any());
|
||||||
|
}
|
||||||
|
|
||||||
|
return tunnelResourceId;
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testApplyTunnelModeTransformWithClosedSpi() throws Exception {
|
public void testApplyTunnelModeTransformWithClosedSpi() throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user