Merge "Add tunnel-mode calls to netd in IpSecService" am: 475fe28c50
am: 02d6d81006 Change-Id: I8a3d16c8e58ad1c09d967943abe1c729fe37636a
This commit is contained in:
@@ -65,7 +65,6 @@ import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
import java.util.List;
|
||||
|
||||
import libcore.io.IoUtils;
|
||||
@@ -596,6 +595,10 @@ public class IpSecService extends IIpSecService.Stub {
|
||||
return mSpi;
|
||||
}
|
||||
|
||||
public EncapSocketRecord getSocketRecord() {
|
||||
return mSocket;
|
||||
}
|
||||
|
||||
/** always guarded by IpSecService#this */
|
||||
@Override
|
||||
public void freeUnderlyingResources() {
|
||||
@@ -806,9 +809,29 @@ public class IpSecService extends IIpSecService.Stub {
|
||||
/** always guarded by IpSecService#this */
|
||||
@Override
|
||||
public void freeUnderlyingResources() {
|
||||
// TODO: Add calls to netd
|
||||
// Calls to netd
|
||||
// Teardown VTI
|
||||
// Delete global policies
|
||||
try {
|
||||
mSrvConfig.getNetdInstance().removeVirtualTunnelInterface(mInterfaceName);
|
||||
|
||||
for (int direction : DIRECTIONS) {
|
||||
int mark = (direction == IpSecManager.DIRECTION_IN) ? mIkey : mOkey;
|
||||
mSrvConfig
|
||||
.getNetdInstance()
|
||||
.ipSecDeleteSecurityPolicy(
|
||||
0, direction, mLocalAddress, mRemoteAddress, mark, 0xffffffff);
|
||||
}
|
||||
} catch (ServiceSpecificException e) {
|
||||
// FIXME: get the error code and throw is at an IOException from Errno Exception
|
||||
} catch (RemoteException e) {
|
||||
Log.e(
|
||||
TAG,
|
||||
"Failed to delete VTI with interface name: "
|
||||
+ mInterfaceName
|
||||
+ " and id: "
|
||||
+ mResourceId);
|
||||
}
|
||||
|
||||
getResourceTracker().give();
|
||||
releaseNetId(mIkey);
|
||||
@@ -1229,10 +1252,29 @@ public class IpSecService extends IIpSecService.Stub {
|
||||
final int okey = reserveNetId();
|
||||
String intfName = String.format("%s%d", TUNNEL_INTERFACE_PREFIX, resourceId);
|
||||
|
||||
// TODO: Add calls to netd:
|
||||
try {
|
||||
// Calls to netd:
|
||||
// Create VTI
|
||||
// Add inbound/outbound global policies
|
||||
// (use reqid = 0)
|
||||
mSrvConfig
|
||||
.getNetdInstance()
|
||||
.addVirtualTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey);
|
||||
|
||||
for (int direction : DIRECTIONS) {
|
||||
int mark = (direction == IpSecManager.DIRECTION_OUT) ? okey : ikey;
|
||||
|
||||
mSrvConfig
|
||||
.getNetdInstance()
|
||||
.ipSecAddSecurityPolicy(
|
||||
0, // Use 0 for reqId
|
||||
direction,
|
||||
"",
|
||||
"",
|
||||
0,
|
||||
mark,
|
||||
0xffffffff);
|
||||
}
|
||||
|
||||
userRecord.mTunnelInterfaceRecords.put(
|
||||
resourceId,
|
||||
@@ -1247,6 +1289,20 @@ public class IpSecService extends IIpSecService.Stub {
|
||||
okey),
|
||||
binder));
|
||||
return new IpSecTunnelInterfaceResponse(IpSecManager.Status.OK, resourceId, intfName);
|
||||
} catch (RemoteException e) {
|
||||
// Release keys if we got an error.
|
||||
releaseNetId(ikey);
|
||||
releaseNetId(okey);
|
||||
throw e.rethrowFromSystemServer();
|
||||
} catch (ServiceSpecificException e) {
|
||||
// FIXME: get the error code and throw is at an IOException from Errno Exception
|
||||
}
|
||||
|
||||
// If we make it to here, then something has gone wrong and we couldn't create a VTI.
|
||||
// Release the keys that we reserved, and return an error status.
|
||||
releaseNetId(ikey);
|
||||
releaseNetId(okey);
|
||||
return new IpSecTunnelInterfaceResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1381,37 +1437,12 @@ public class IpSecService extends IIpSecService.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a transport mode transform, which represent two security associations (one in each
|
||||
* direction) in the kernel. The transform will be cached by the system server and must be freed
|
||||
* when no longer needed. It is possible to free one, deleting the SA from underneath sockets
|
||||
* that are using it, which will result in all of those sockets becoming unable to send or
|
||||
* receive data.
|
||||
*/
|
||||
@Override
|
||||
public synchronized IpSecTransformResponse createTransform(IpSecConfig c, IBinder binder)
|
||||
private void createOrUpdateTransform(
|
||||
IpSecConfig c, int resourceId, SpiRecord spiRecord, EncapSocketRecord socketRecord)
|
||||
throws RemoteException {
|
||||
checkIpSecConfig(c);
|
||||
checkNotNull(binder, "Null Binder passed to createTransform");
|
||||
final int resourceId = mNextResourceId++;
|
||||
|
||||
UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
|
||||
List<RefcountedResource> dependencies = new ArrayList<>();
|
||||
|
||||
if (!userRecord.mTransformQuotaTracker.isAvailable()) {
|
||||
return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
|
||||
}
|
||||
|
||||
int encapType, encapLocalPort = 0, encapRemotePort = 0;
|
||||
EncapSocketRecord socketRecord = null;
|
||||
encapType = c.getEncapType();
|
||||
int encapType = c.getEncapType(), encapLocalPort = 0, encapRemotePort = 0;
|
||||
if (encapType != IpSecTransform.ENCAP_NONE) {
|
||||
RefcountedResource<EncapSocketRecord> refcountedSocketRecord =
|
||||
userRecord.mEncapSocketRecords.getRefcountedResourceOrThrow(
|
||||
c.getEncapSocketResourceId());
|
||||
dependencies.add(refcountedSocketRecord);
|
||||
|
||||
socketRecord = refcountedSocketRecord.getResource();
|
||||
encapLocalPort = socketRecord.getPort();
|
||||
encapRemotePort = c.getEncapRemotePort();
|
||||
}
|
||||
@@ -1420,12 +1451,6 @@ public class IpSecService extends IIpSecService.Stub {
|
||||
IpSecAlgorithm crypt = c.getEncryption();
|
||||
IpSecAlgorithm authCrypt = c.getAuthenticatedEncryption();
|
||||
|
||||
RefcountedResource<SpiRecord> refcountedSpiRecord =
|
||||
userRecord.mSpiRecords.getRefcountedResourceOrThrow(c.getSpiResourceId());
|
||||
dependencies.add(refcountedSpiRecord);
|
||||
SpiRecord spiRecord = refcountedSpiRecord.getResource();
|
||||
|
||||
try {
|
||||
mSrvConfig
|
||||
.getNetdInstance()
|
||||
.ipSecAddSecurityAssociation(
|
||||
@@ -1449,11 +1474,50 @@ public class IpSecService extends IIpSecService.Stub {
|
||||
encapType,
|
||||
encapLocalPort,
|
||||
encapRemotePort);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a IPsec transform, which represents a single security association in the kernel. The
|
||||
* transform will be cached by the system server and must be freed when no longer needed. It is
|
||||
* possible to free one, deleting the SA from underneath sockets that are using it, which will
|
||||
* result in all of those sockets becoming unable to send or receive data.
|
||||
*/
|
||||
@Override
|
||||
public synchronized IpSecTransformResponse createTransform(IpSecConfig c, IBinder binder)
|
||||
throws RemoteException {
|
||||
checkIpSecConfig(c);
|
||||
checkNotNull(binder, "Null Binder passed to createTransform");
|
||||
final int resourceId = mNextResourceId++;
|
||||
|
||||
UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
|
||||
List<RefcountedResource> dependencies = new ArrayList<>();
|
||||
|
||||
if (!userRecord.mTransformQuotaTracker.isAvailable()) {
|
||||
return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
|
||||
}
|
||||
|
||||
EncapSocketRecord socketRecord = null;
|
||||
if (c.getEncapType() != IpSecTransform.ENCAP_NONE) {
|
||||
RefcountedResource<EncapSocketRecord> refcountedSocketRecord =
|
||||
userRecord.mEncapSocketRecords.getRefcountedResourceOrThrow(
|
||||
c.getEncapSocketResourceId());
|
||||
dependencies.add(refcountedSocketRecord);
|
||||
socketRecord = refcountedSocketRecord.getResource();
|
||||
}
|
||||
|
||||
RefcountedResource<SpiRecord> refcountedSpiRecord =
|
||||
userRecord.mSpiRecords.getRefcountedResourceOrThrow(c.getSpiResourceId());
|
||||
dependencies.add(refcountedSpiRecord);
|
||||
SpiRecord spiRecord = refcountedSpiRecord.getResource();
|
||||
|
||||
try {
|
||||
createOrUpdateTransform(c, resourceId, spiRecord, socketRecord);
|
||||
} catch (ServiceSpecificException e) {
|
||||
// FIXME: get the error code and throw is at an IOException from Errno Exception
|
||||
return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
|
||||
}
|
||||
// Both SAs were created successfully, time to construct a record and lock it away
|
||||
|
||||
// SA was created successfully, time to construct a record and lock it away
|
||||
userRecord.mTransformRecords.put(
|
||||
resourceId,
|
||||
new RefcountedResource<TransformRecord>(
|
||||
@@ -1561,14 +1625,48 @@ public class IpSecService extends IIpSecService.Stub {
|
||||
c.getMode() == IpSecTransform.MODE_TUNNEL,
|
||||
"Transform mode was not Tunnel mode; cannot be applied to a tunnel interface");
|
||||
|
||||
EncapSocketRecord socketRecord = null;
|
||||
if (c.getEncapType() != IpSecTransform.ENCAP_NONE) {
|
||||
socketRecord =
|
||||
userRecord.mEncapSocketRecords.getResourceOrThrow(c.getEncapSocketResourceId());
|
||||
}
|
||||
SpiRecord spiRecord = userRecord.mSpiRecords.getResourceOrThrow(c.getSpiResourceId());
|
||||
|
||||
int mark =
|
||||
(direction == IpSecManager.DIRECTION_IN)
|
||||
? tunnelInterfaceInfo.getIkey()
|
||||
: tunnelInterfaceInfo.getOkey();
|
||||
|
||||
// TODO: Add calls to netd:
|
||||
try {
|
||||
c.setMarkValue(mark);
|
||||
c.setMarkMask(0xffffffff);
|
||||
|
||||
if (direction == IpSecManager.DIRECTION_OUT) {
|
||||
// Set output mark via underlying network (output only)
|
||||
c.setNetwork(tunnelInterfaceInfo.getUnderlyingNetwork());
|
||||
|
||||
// If outbound, also add SPI to the policy.
|
||||
mSrvConfig
|
||||
.getNetdInstance()
|
||||
.ipSecUpdateSecurityPolicy(
|
||||
0, // Use 0 for reqId
|
||||
direction,
|
||||
"",
|
||||
"",
|
||||
transformInfo.getSpiRecord().getSpi(),
|
||||
mark,
|
||||
0xffffffff);
|
||||
}
|
||||
|
||||
// Update SA with tunnel mark (ikey or okey based on direction)
|
||||
// If outbound, add SPI to policy
|
||||
createOrUpdateTransform(c, transformResourceId, spiRecord, socketRecord);
|
||||
} catch (ServiceSpecificException e) {
|
||||
if (e.errorCode == EINVAL) {
|
||||
throw new IllegalArgumentException(e.toString());
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user