Support getting transform state in IpSecService

Bug: 308011229
Test: IpSecServiceParameterizedTest (new tests)
Change-Id: I3f1c2ef60ee9b6ac17909e0ee083ee6f8483588e
This commit is contained in:
Yan Yan
2023-11-15 21:41:51 +00:00
parent d7a9a654f7
commit ab5006c17d
7 changed files with 466 additions and 0 deletions

View File

@@ -42,6 +42,7 @@ import android.net.IpSecMigrateInfoParcel;
import android.net.IpSecSpiResponse;
import android.net.IpSecTransform;
import android.net.IpSecTransformResponse;
import android.net.IpSecTransformState;
import android.net.IpSecTunnelInterfaceResponse;
import android.net.IpSecUdpEncapResponse;
import android.net.LinkAddress;
@@ -70,6 +71,7 @@ import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.BinderUtils;
import com.android.net.module.util.NetdUtils;
import com.android.net.module.util.PermissionUtils;
import com.android.net.module.util.netlink.xfrm.XfrmNetlinkNewSaMessage;
import libcore.io.IoUtils;
@@ -109,6 +111,7 @@ public class IpSecService extends IIpSecService.Stub {
@VisibleForTesting static final int MAX_PORT_BIND_ATTEMPTS = 10;
private final INetd mNetd;
private final IpSecXfrmController mIpSecXfrmCtrl;
static {
try {
@@ -152,6 +155,11 @@ public class IpSecService extends IIpSecService.Stub {
}
return netd;
}
/** Get a instance of IpSecXfrmController */
public IpSecXfrmController getIpSecXfrmController() {
return new IpSecXfrmController();
}
}
final UidFdTagger mUidFdTagger;
@@ -1111,6 +1119,7 @@ public class IpSecService extends IIpSecService.Stub {
mContext = context;
mDeps = Objects.requireNonNull(deps, "Missing dependencies.");
mUidFdTagger = uidFdTagger;
mIpSecXfrmCtrl = mDeps.getIpSecXfrmController();
try {
mNetd = mDeps.getNetdInstance(mContext);
} catch (RemoteException e) {
@@ -1862,6 +1871,48 @@ public class IpSecService extends IIpSecService.Stub {
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
* association as a correspondent policy to the provided socket