Reland "Support getting transform state in IpSecService"
This reverts commit 69eb8325c0c403e28fb938112a3077d381207a8e.
Bug: 308011229
Change-Id: I4dd68bdedc0088860895a833f2b4cb8e1845429a
Test: IpSecServiceParameterizedTest (new tests)
diff --git a/service-t/src/com/android/server/IpSecService.java b/service-t/src/com/android/server/IpSecService.java
index a884840..ea91e64 100644
--- a/service-t/src/com/android/server/IpSecService.java
+++ b/service-t/src/com/android/server/IpSecService.java
@@ -42,6 +42,7 @@
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.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 @@
@VisibleForTesting static final int MAX_PORT_BIND_ATTEMPTS = 10;
private final INetd mNetd;
+ private final IpSecXfrmController mIpSecXfrmCtrl;
static {
try {
@@ -152,6 +155,11 @@
}
return netd;
}
+
+ /** Get a instance of IpSecXfrmController */
+ public IpSecXfrmController getIpSecXfrmController() {
+ return new IpSecXfrmController();
+ }
}
final UidFdTagger mUidFdTagger;
@@ -1111,6 +1119,7 @@
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 @@
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