Skip to content
Snippets Groups Projects
Commit 07e425cd authored by Yan Yan's avatar Yan Yan Committed by Gerrit Code Review
Browse files

Merge changes from topic "ipsec-tramsform-state" into main

* changes:
  Expose APIs to query the state of an IpSecTransform
  Reland "Support getting transform state in IpSecService"
parents 9efc4299 3976e49e
No related branches found
No related tags found
No related merge requests found
...@@ -127,6 +127,7 @@ package android.net { ...@@ -127,6 +127,7 @@ package android.net {
public final class IpSecTransform implements java.lang.AutoCloseable { public final class IpSecTransform implements java.lang.AutoCloseable {
method public void close(); method public void close();
method @FlaggedApi("com.android.net.flags.ipsec_transform_state") public void getIpSecTransformState(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.net.IpSecTransformState,java.lang.RuntimeException>);
} }
public static class IpSecTransform.Builder { public static class IpSecTransform.Builder {
...@@ -138,6 +139,29 @@ package android.net { ...@@ -138,6 +139,29 @@ package android.net {
method @NonNull public android.net.IpSecTransform.Builder setIpv4Encapsulation(@NonNull android.net.IpSecManager.UdpEncapsulationSocket, int); method @NonNull public android.net.IpSecTransform.Builder setIpv4Encapsulation(@NonNull android.net.IpSecManager.UdpEncapsulationSocket, int);
} }
@FlaggedApi("com.android.net.flags.ipsec_transform_state") public final class IpSecTransformState implements android.os.Parcelable {
method public int describeContents();
method public long getByteCount();
method public long getPacketCount();
method @NonNull public byte[] getReplayBitmap();
method public long getRxHighestSequenceNumber();
method public long getTimestamp();
method public long getTxHighestSequenceNumber();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.IpSecTransformState> CREATOR;
}
@FlaggedApi("com.android.net.flags.ipsec_transform_state") public static final class IpSecTransformState.Builder {
ctor public IpSecTransformState.Builder();
method @NonNull public android.net.IpSecTransformState build();
method @NonNull public android.net.IpSecTransformState.Builder setByteCount(long);
method @NonNull public android.net.IpSecTransformState.Builder setPacketCount(long);
method @NonNull public android.net.IpSecTransformState.Builder setReplayBitmap(@NonNull byte[]);
method @NonNull public android.net.IpSecTransformState.Builder setRxHighestSequenceNumber(long);
method @NonNull public android.net.IpSecTransformState.Builder setTimestamp(long);
method @NonNull public android.net.IpSecTransformState.Builder setTxHighestSequenceNumber(long);
}
public class TrafficStats { public class TrafficStats {
ctor public TrafficStats(); ctor public TrafficStats();
method public static void clearThreadStatsTag(); method public static void clearThreadStatsTag();
......
...@@ -22,6 +22,7 @@ import android.net.IpSecConfig; ...@@ -22,6 +22,7 @@ import android.net.IpSecConfig;
import android.net.IpSecUdpEncapResponse; import android.net.IpSecUdpEncapResponse;
import android.net.IpSecSpiResponse; import android.net.IpSecSpiResponse;
import android.net.IpSecTransformResponse; import android.net.IpSecTransformResponse;
import android.net.IpSecTransformState;
import android.net.IpSecTunnelInterfaceResponse; import android.net.IpSecTunnelInterfaceResponse;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
...@@ -74,6 +75,8 @@ interface IIpSecService ...@@ -74,6 +75,8 @@ interface IIpSecService
void deleteTransform(int transformId); void deleteTransform(int transformId);
IpSecTransformState getTransformState(int transformId);
void applyTransportModeTransform( void applyTransportModeTransform(
in ParcelFileDescriptor socket, int direction, int transformId); in ParcelFileDescriptor socket, int direction, int transformId);
......
...@@ -65,6 +65,13 @@ import java.util.Objects; ...@@ -65,6 +65,13 @@ import java.util.Objects;
public class IpSecManager { public class IpSecManager {
private static final String TAG = "IpSecManager"; private static final String TAG = "IpSecManager";
// TODO : remove this class when udc-mainline-prod is abandoned and android.net.flags.Flags is
// available here
/** @hide */
public static class Flags {
static final String IPSEC_TRANSFORM_STATE = "com.android.net.flags.ipsec_transform_state";
}
/** /**
* Feature flag to declare the kernel support of updating IPsec SAs. * Feature flag to declare the kernel support of updating IPsec SAs.
* *
...@@ -1084,6 +1091,12 @@ public class IpSecManager { ...@@ -1084,6 +1091,12 @@ public class IpSecManager {
} }
} }
/** @hide */
public IpSecTransformState getTransformState(int transformId)
throws IllegalStateException, RemoteException {
return mService.getTransformState(transformId);
}
/** /**
* Construct an instance of IpSecManager within an application context. * Construct an instance of IpSecManager within an application context.
* *
......
...@@ -15,8 +15,11 @@ ...@@ -15,8 +15,11 @@
*/ */
package android.net; package android.net;
import static android.net.IpSecManager.Flags.IPSEC_TRANSFORM_STATE;
import static android.net.IpSecManager.INVALID_RESOURCE_ID; import static android.net.IpSecManager.INVALID_RESOURCE_ID;
import android.annotation.CallbackExecutor;
import android.annotation.FlaggedApi;
import android.annotation.IntDef; import android.annotation.IntDef;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
...@@ -26,6 +29,8 @@ import android.annotation.SystemApi; ...@@ -26,6 +29,8 @@ import android.annotation.SystemApi;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.Binder; import android.os.Binder;
import android.os.OutcomeReceiver;
import android.os.RemoteException;
import android.os.ServiceSpecificException; import android.os.ServiceSpecificException;
import android.util.Log; import android.util.Log;
...@@ -38,6 +43,7 @@ import java.lang.annotation.Retention; ...@@ -38,6 +43,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.Executor;
/** /**
* This class represents a transform, which roughly corresponds to an IPsec Security Association. * This class represents a transform, which roughly corresponds to an IPsec Security Association.
...@@ -200,6 +206,43 @@ public final class IpSecTransform implements AutoCloseable { ...@@ -200,6 +206,43 @@ public final class IpSecTransform implements AutoCloseable {
return mResourceId; return mResourceId;
} }
/**
* Retrieve the current state of this IpSecTransform.
*
* @param executor The {@link Executor} on which to call the supplied callback.
* @param callback Callback that's called after the transform state is ready or when an error
* occurs.
* @see IpSecTransformState
*/
@FlaggedApi(IPSEC_TRANSFORM_STATE)
public void getIpSecTransformState(
@CallbackExecutor @NonNull Executor executor,
@NonNull OutcomeReceiver<IpSecTransformState, RuntimeException> callback) {
Objects.requireNonNull(executor);
Objects.requireNonNull(callback);
// TODO: Consider adding check to prevent DDoS attack.
try {
final IpSecTransformState ipSecTransformState =
getIpSecManager(mContext).getTransformState(mResourceId);
executor.execute(
() -> {
callback.onResult(ipSecTransformState);
});
} catch (IllegalStateException e) {
executor.execute(
() -> {
callback.onError(e);
});
} catch (RemoteException e) {
executor.execute(
() -> {
callback.onError(e.rethrowFromSystemServer());
});
}
}
/** /**
* A callback class to provide status information regarding a NAT-T keepalive session * A callback class to provide status information regarding a NAT-T keepalive session
* *
......
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.net;
/** @hide */
parcelable IpSecTransformState;
\ No newline at end of file
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.net;
import static android.net.IpSecManager.Flags.IPSEC_TRANSFORM_STATE;
import static com.android.internal.annotations.VisibleForTesting.Visibility;
import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.net.module.util.HexDump;
import java.util.Objects;
/**
* This class represents a snapshot of the state of an IpSecTransform
*
* <p>This class provides the current state of an IpSecTransform, enabling link metric analysis by
* the caller. Use cases include understanding transform usage, such as packet and byte counts, as
* well as observing out-of-order delivery by checking the bitmap. Additionally, callers can query
* IpSecTransformStates at two timestamps. By comparing the changes in packet counts and sequence
* numbers, callers can estimate IPsec data loss in the inbound direction.
*/
@FlaggedApi(IPSEC_TRANSFORM_STATE)
public final class IpSecTransformState implements Parcelable {
private final long mTimeStamp;
private final long mTxHighestSequenceNumber;
private final long mRxHighestSequenceNumber;
private final long mPacketCount;
private final long mByteCount;
private final byte[] mReplayBitmap;
private IpSecTransformState(
long timestamp,
long txHighestSequenceNumber,
long rxHighestSequenceNumber,
long packetCount,
long byteCount,
byte[] replayBitmap) {
mTimeStamp = timestamp;
mTxHighestSequenceNumber = txHighestSequenceNumber;
mRxHighestSequenceNumber = rxHighestSequenceNumber;
mPacketCount = packetCount;
mByteCount = byteCount;
Objects.requireNonNull(replayBitmap, "replayBitmap is null");
mReplayBitmap = replayBitmap.clone();
validate();
}
private void validate() {
Objects.requireNonNull(mReplayBitmap, "mReplayBitmap is null");
}
/**
* Deserializes a IpSecTransformState from a PersistableBundle.
*
* @hide
*/
@VisibleForTesting(visibility = Visibility.PRIVATE)
public IpSecTransformState(@NonNull Parcel in) {
Objects.requireNonNull(in, "The input PersistableBundle is null");
mTimeStamp = in.readLong();
mTxHighestSequenceNumber = in.readLong();
mRxHighestSequenceNumber = in.readLong();
mPacketCount = in.readLong();
mByteCount = in.readLong();
mReplayBitmap = HexDump.hexStringToByteArray(in.readString());
validate();
}
// Parcelable methods
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeLong(mTimeStamp);
out.writeLong(mTxHighestSequenceNumber);
out.writeLong(mRxHighestSequenceNumber);
out.writeLong(mPacketCount);
out.writeLong(mByteCount);
out.writeString(HexDump.toHexString(mReplayBitmap));
}
@NonNull
public static final Parcelable.Creator<IpSecTransformState> CREATOR =
new Parcelable.Creator<IpSecTransformState>() {
@NonNull
public IpSecTransformState createFromParcel(Parcel in) {
return new IpSecTransformState(in);
}
@NonNull
public IpSecTransformState[] newArray(int size) {
return new IpSecTransformState[size];
}
};
/**
* Retrieve the epoch timestamp (milliseconds) for when this state was created
*
* @see Builder#setTimestamp(long)
*/
public long getTimestamp() {
return mTimeStamp;
}
/**
* Retrieve the highest sequence number sent so far
*
* @see Builder#setTxHighestSequenceNumber(long)
*/
public long getTxHighestSequenceNumber() {
return mTxHighestSequenceNumber;
}
/**
* Retrieve the highest sequence number received so far
*
* @see Builder#setRxHighestSequenceNumber(long)
*/
public long getRxHighestSequenceNumber() {
return mRxHighestSequenceNumber;
}
/**
* Retrieve the number of packets received AND sent so far
*
* @see Builder#setPacketCount(long)
*/
public long getPacketCount() {
return mPacketCount;
}
/**
* Retrieve the number of bytes received AND sent so far
*
* @see Builder#setByteCount(long)
*/
public long getByteCount() {
return mByteCount;
}
/**
* Retrieve the replay bitmap
*
* <p>This bitmap represents a replay window, allowing the caller to observe out-of-order
* delivery. The last bit represents the highest sequence number received so far and bits for
* the received packets will be marked as true.
*
* <p>The size of a replay bitmap will never change over the lifetime of an IpSecTransform
*
* <p>The replay bitmap is solely useful for inbound IpSecTransforms. For outbound
* IpSecTransforms, all bits will be unchecked.
*
* @see Builder#setReplayBitmap(byte[])
*/
@NonNull
public byte[] getReplayBitmap() {
return mReplayBitmap.clone();
}
/** Builder class for testing purposes */
@FlaggedApi(IPSEC_TRANSFORM_STATE)
public static final class Builder {
private long mTimeStamp;
private long mTxHighestSequenceNumber;
private long mRxHighestSequenceNumber;
private long mPacketCount;
private long mByteCount;
private byte[] mReplayBitmap;
public Builder() {
mTimeStamp = System.currentTimeMillis();
}
/**
* Set the epoch timestamp (milliseconds) for when this state was created
*
* @see IpSecTransformState#getTimestamp()
*/
@NonNull
public Builder setTimestamp(long timeStamp) {
mTimeStamp = timeStamp;
return this;
}
/**
* Set the highest sequence number sent so far
*
* @see IpSecTransformState#getTxHighestSequenceNumber()
*/
@NonNull
public Builder setTxHighestSequenceNumber(long seqNum) {
mTxHighestSequenceNumber = seqNum;
return this;
}
/**
* Set the highest sequence number received so far
*
* @see IpSecTransformState#getRxHighestSequenceNumber()
*/
@NonNull
public Builder setRxHighestSequenceNumber(long seqNum) {
mRxHighestSequenceNumber = seqNum;
return this;
}
/**
* Set the number of packets received AND sent so far
*
* @see IpSecTransformState#getPacketCount()
*/
@NonNull
public Builder setPacketCount(long packetCount) {
mPacketCount = packetCount;
return this;
}
/**
* Set the number of bytes received AND sent so far
*
* @see IpSecTransformState#getByteCount()
*/
@NonNull
public Builder setByteCount(long byteCount) {
mByteCount = byteCount;
return this;
}
/**
* Set the replay bitmap
*
* @see IpSecTransformState#getReplayBitmap()
*/
@NonNull
public Builder setReplayBitmap(@NonNull byte[] bitMap) {
mReplayBitmap = bitMap.clone();
return this;
}
/**
* Build and validate the IpSecTransformState
*
* @return an immutable IpSecTransformState instance
*/
@NonNull
public IpSecTransformState build() {
return new IpSecTransformState(
mTimeStamp,
mTxHighestSequenceNumber,
mRxHighestSequenceNumber,
mPacketCount,
mByteCount,
mReplayBitmap);
}
}
}
...@@ -42,6 +42,7 @@ import android.net.IpSecMigrateInfoParcel; ...@@ -42,6 +42,7 @@ 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;
import android.net.IpSecTransformState;
import android.net.IpSecTunnelInterfaceResponse; import android.net.IpSecTunnelInterfaceResponse;
import android.net.IpSecUdpEncapResponse; import android.net.IpSecUdpEncapResponse;
import android.net.LinkAddress; import android.net.LinkAddress;
...@@ -70,6 +71,7 @@ import com.android.modules.utils.build.SdkLevel; ...@@ -70,6 +71,7 @@ import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.BinderUtils; import com.android.net.module.util.BinderUtils;
import com.android.net.module.util.NetdUtils; import com.android.net.module.util.NetdUtils;
import com.android.net.module.util.PermissionUtils; import com.android.net.module.util.PermissionUtils;
import com.android.net.module.util.netlink.xfrm.XfrmNetlinkNewSaMessage;
import libcore.io.IoUtils; import libcore.io.IoUtils;
...@@ -109,6 +111,7 @@ public class IpSecService extends IIpSecService.Stub { ...@@ -109,6 +111,7 @@ public class IpSecService extends IIpSecService.Stub {
@VisibleForTesting static final int MAX_PORT_BIND_ATTEMPTS = 10; @VisibleForTesting static final int MAX_PORT_BIND_ATTEMPTS = 10;
private final INetd mNetd; private final INetd mNetd;
private final IpSecXfrmController mIpSecXfrmCtrl;
static { static {
try { try {
...@@ -152,6 +155,11 @@ public class IpSecService extends IIpSecService.Stub { ...@@ -152,6 +155,11 @@ public class IpSecService extends IIpSecService.Stub {
} }
return netd; return netd;
} }
/** Get a instance of IpSecXfrmController */
public IpSecXfrmController getIpSecXfrmController() {
return new IpSecXfrmController();
}
} }
final UidFdTagger mUidFdTagger; final UidFdTagger mUidFdTagger;
...@@ -1111,6 +1119,7 @@ public class IpSecService extends IIpSecService.Stub { ...@@ -1111,6 +1119,7 @@ public class IpSecService extends IIpSecService.Stub {
mContext = context; mContext = context;
mDeps = Objects.requireNonNull(deps, "Missing dependencies."); mDeps = Objects.requireNonNull(deps, "Missing dependencies.");
mUidFdTagger = uidFdTagger; mUidFdTagger = uidFdTagger;
mIpSecXfrmCtrl = mDeps.getIpSecXfrmController();
try { try {
mNetd = mDeps.getNetdInstance(mContext); mNetd = mDeps.getNetdInstance(mContext);
} catch (RemoteException e) { } catch (RemoteException e) {
...@@ -1862,6 +1871,48 @@ public class IpSecService extends IIpSecService.Stub { ...@@ -1862,6 +1871,48 @@ public class IpSecService extends IIpSecService.Stub {
releaseResource(userRecord.mTransformRecords, resourceId); releaseResource(userRecord.mTransformRecords, resourceId);
} }
@Override
public synchronized IpSecTransformState getTransformState(int transformId)
throws IllegalStateException, RemoteException {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.ACCESS_NETWORK_STATE, "IpsecService#getTransformState");
UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
TransformRecord transformInfo =
userRecord.mTransformRecords.getResourceOrThrow(transformId);
final int spi = transformInfo.getSpiRecord().getSpi();
final InetAddress destAddress =
InetAddresses.parseNumericAddress(
transformInfo.getConfig().getDestinationAddress());
Log.d(TAG, "getTransformState for spi " + spi + " destAddress " + destAddress);
// Make netlink call
final XfrmNetlinkNewSaMessage xfrmNewSaMsg;
try {
xfrmNewSaMsg = mIpSecXfrmCtrl.ipSecGetSa(destAddress, Integer.toUnsignedLong(spi));
} catch (ErrnoException | IOException e) {
Log.e(TAG, "getTransformState: failed to get IpSecTransformState" + e.toString());
throw new IllegalStateException("Failed to get IpSecTransformState", e);
}
// Keep the netlink socket open to save time for the next call. It is cheap to have a
// persistent netlink socket in the system server
if (xfrmNewSaMsg == null) {
Log.e(TAG, "getTransformState: failed to get IpSecTransformState xfrmNewSaMsg is null");
throw new IllegalStateException("Failed to get IpSecTransformState");
}
return new IpSecTransformState.Builder()
.setTxHighestSequenceNumber(xfrmNewSaMsg.getTxSequenceNumber())
.setRxHighestSequenceNumber(xfrmNewSaMsg.getRxSequenceNumber())
.setPacketCount(xfrmNewSaMsg.getPacketCount())
.setByteCount(xfrmNewSaMsg.getByteCount())
.setReplayBitmap(xfrmNewSaMsg.getBitmap())
.build();
}
/** /**
* Apply an active transport mode transform to a socket, which will apply the IPsec security * Apply an active transport mode transform to a socket, which will apply the IPsec security
* association as a correspondent policy to the provided socket * association as a correspondent policy to the provided socket
......
...@@ -33,6 +33,7 @@ import static org.junit.Assert.assertNotNull; ...@@ -33,6 +33,7 @@ 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.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString; 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.ArgumentMatchers.eq;
...@@ -74,6 +75,7 @@ import android.util.ArraySet; ...@@ -74,6 +75,7 @@ import android.util.ArraySet;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
import com.android.net.module.util.netlink.xfrm.XfrmNetlinkNewSaMessage;
import com.android.server.IpSecService.TunnelInterfaceRecord; import com.android.server.IpSecService.TunnelInterfaceRecord;
import com.android.testutils.DevSdkIgnoreRule; import com.android.testutils.DevSdkIgnoreRule;
...@@ -85,6 +87,7 @@ import org.junit.runner.RunWith; ...@@ -85,6 +87,7 @@ import org.junit.runner.RunWith;
import org.junit.runners.Parameterized; import org.junit.runners.Parameterized;
import java.net.Inet4Address; import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.Socket; import java.net.Socket;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
...@@ -149,6 +152,7 @@ public class IpSecServiceParameterizedTest { ...@@ -149,6 +152,7 @@ public class IpSecServiceParameterizedTest {
private Set<String> mAllowedPermissions = new ArraySet<>(Arrays.asList( private Set<String> mAllowedPermissions = new ArraySet<>(Arrays.asList(
android.Manifest.permission.MANAGE_IPSEC_TUNNELS, android.Manifest.permission.MANAGE_IPSEC_TUNNELS,
android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_STACK,
android.Manifest.permission.ACCESS_NETWORK_STATE,
PERMISSION_MAINLINE_NETWORK_STACK)); PERMISSION_MAINLINE_NETWORK_STACK));
private void setAllowedPermissions(String... permissions) { private void setAllowedPermissions(String... permissions) {
...@@ -202,11 +206,13 @@ public class IpSecServiceParameterizedTest { ...@@ -202,11 +206,13 @@ public class IpSecServiceParameterizedTest {
private IpSecService.Dependencies makeDependencies() throws RemoteException { private IpSecService.Dependencies makeDependencies() throws RemoteException {
final IpSecService.Dependencies deps = mock(IpSecService.Dependencies.class); final IpSecService.Dependencies deps = mock(IpSecService.Dependencies.class);
when(deps.getNetdInstance(mTestContext)).thenReturn(mMockNetd); when(deps.getNetdInstance(mTestContext)).thenReturn(mMockNetd);
when(deps.getIpSecXfrmController()).thenReturn(mMockXfrmCtrl);
return deps; return deps;
} }
INetd mMockNetd; INetd mMockNetd;
PackageManager mMockPkgMgr; PackageManager mMockPkgMgr;
IpSecXfrmController mMockXfrmCtrl;
IpSecService.Dependencies mDeps; IpSecService.Dependencies mDeps;
IpSecService mIpSecService; IpSecService mIpSecService;
Network fakeNetwork = new Network(0xAB); Network fakeNetwork = new Network(0xAB);
...@@ -235,6 +241,7 @@ public class IpSecServiceParameterizedTest { ...@@ -235,6 +241,7 @@ public class IpSecServiceParameterizedTest {
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
mMockNetd = mock(INetd.class); mMockNetd = mock(INetd.class);
mMockXfrmCtrl = mock(IpSecXfrmController.class);
mMockPkgMgr = mock(PackageManager.class); mMockPkgMgr = mock(PackageManager.class);
mDeps = makeDependencies(); mDeps = makeDependencies();
mIpSecService = new IpSecService(mTestContext, mDeps); mIpSecService = new IpSecService(mTestContext, mDeps);
...@@ -505,6 +512,32 @@ public class IpSecServiceParameterizedTest { ...@@ -505,6 +512,32 @@ public class IpSecServiceParameterizedTest {
} }
} }
@Test
public void getTransformState() throws Exception {
XfrmNetlinkNewSaMessage mockXfrmNewSaMsg = mock(XfrmNetlinkNewSaMessage.class);
when(mockXfrmNewSaMsg.getBitmap()).thenReturn(new byte[512]);
when(mMockXfrmCtrl.ipSecGetSa(any(InetAddress.class), anyLong()))
.thenReturn(mockXfrmNewSaMsg);
// Create transform
IpSecConfig ipSecConfig = new IpSecConfig();
addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
addAuthAndCryptToIpSecConfig(ipSecConfig);
IpSecTransformResponse createTransformResp =
mIpSecService.createTransform(ipSecConfig, new Binder(), BLESSED_PACKAGE);
assertEquals(IpSecManager.Status.OK, createTransformResp.status);
// Get transform state
mIpSecService.getTransformState(createTransformResp.resourceId);
// Verifications
verify(mMockXfrmCtrl)
.ipSecGetSa(
eq(InetAddresses.parseNumericAddress(mDestinationAddr)),
eq(Integer.toUnsignedLong(TEST_SPI)));
}
@Test @Test
public void testReleaseOwnedSpi() throws Exception { public void testReleaseOwnedSpi() throws Exception {
IpSecConfig ipSecConfig = new IpSecConfig(); IpSecConfig ipSecConfig = new IpSecConfig();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment