Merge "Added implementation for VTI add/remove address"
This commit is contained in:
@@ -50,13 +50,18 @@ public class IpSecManagerTest {
|
|||||||
|
|
||||||
private static final int TEST_UDP_ENCAP_PORT = 34567;
|
private static final int TEST_UDP_ENCAP_PORT = 34567;
|
||||||
private static final int DROID_SPI = 0xD1201D;
|
private static final int DROID_SPI = 0xD1201D;
|
||||||
|
private static final int DUMMY_RESOURCE_ID = 0x1234;
|
||||||
|
|
||||||
private static final InetAddress GOOGLE_DNS_4;
|
private static final InetAddress GOOGLE_DNS_4;
|
||||||
|
private static final String VTI_INTF_NAME = "ipsec_test";
|
||||||
|
private static final InetAddress VTI_LOCAL_ADDRESS;
|
||||||
|
private static final LinkAddress VTI_INNER_ADDRESS = new LinkAddress("10.0.1.1/24");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
// Google Public DNS Addresses;
|
// Google Public DNS Addresses;
|
||||||
GOOGLE_DNS_4 = InetAddress.getByName("8.8.8.8");
|
GOOGLE_DNS_4 = InetAddress.getByName("8.8.8.8");
|
||||||
|
VTI_LOCAL_ADDRESS = InetAddress.getByName("8.8.4.4");
|
||||||
} catch (UnknownHostException e) {
|
} catch (UnknownHostException e) {
|
||||||
throw new RuntimeException("Could not resolve DNS Addresses", e);
|
throw new RuntimeException("Could not resolve DNS Addresses", e);
|
||||||
}
|
}
|
||||||
@@ -77,9 +82,8 @@ public class IpSecManagerTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testAllocSpi() throws Exception {
|
public void testAllocSpi() throws Exception {
|
||||||
int resourceId = 1;
|
|
||||||
IpSecSpiResponse spiResp =
|
IpSecSpiResponse spiResp =
|
||||||
new IpSecSpiResponse(IpSecManager.Status.OK, resourceId, DROID_SPI);
|
new IpSecSpiResponse(IpSecManager.Status.OK, DUMMY_RESOURCE_ID, DROID_SPI);
|
||||||
when(mMockIpSecService.allocateSecurityParameterIndex(
|
when(mMockIpSecService.allocateSecurityParameterIndex(
|
||||||
eq(GOOGLE_DNS_4.getHostAddress()),
|
eq(GOOGLE_DNS_4.getHostAddress()),
|
||||||
eq(DROID_SPI),
|
eq(DROID_SPI),
|
||||||
@@ -92,14 +96,13 @@ public class IpSecManagerTest {
|
|||||||
|
|
||||||
droidSpi.close();
|
droidSpi.close();
|
||||||
|
|
||||||
verify(mMockIpSecService).releaseSecurityParameterIndex(resourceId);
|
verify(mMockIpSecService).releaseSecurityParameterIndex(DUMMY_RESOURCE_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAllocRandomSpi() throws Exception {
|
public void testAllocRandomSpi() throws Exception {
|
||||||
int resourceId = 1;
|
|
||||||
IpSecSpiResponse spiResp =
|
IpSecSpiResponse spiResp =
|
||||||
new IpSecSpiResponse(IpSecManager.Status.OK, resourceId, DROID_SPI);
|
new IpSecSpiResponse(IpSecManager.Status.OK, DUMMY_RESOURCE_ID, DROID_SPI);
|
||||||
when(mMockIpSecService.allocateSecurityParameterIndex(
|
when(mMockIpSecService.allocateSecurityParameterIndex(
|
||||||
eq(GOOGLE_DNS_4.getHostAddress()),
|
eq(GOOGLE_DNS_4.getHostAddress()),
|
||||||
eq(IpSecManager.INVALID_SECURITY_PARAMETER_INDEX),
|
eq(IpSecManager.INVALID_SECURITY_PARAMETER_INDEX),
|
||||||
@@ -113,7 +116,7 @@ public class IpSecManagerTest {
|
|||||||
|
|
||||||
randomSpi.close();
|
randomSpi.close();
|
||||||
|
|
||||||
verify(mMockIpSecService).releaseSecurityParameterIndex(resourceId);
|
verify(mMockIpSecService).releaseSecurityParameterIndex(DUMMY_RESOURCE_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -165,11 +168,10 @@ public class IpSecManagerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOpenEncapsulationSocket() throws Exception {
|
public void testOpenEncapsulationSocket() throws Exception {
|
||||||
int resourceId = 1;
|
|
||||||
IpSecUdpEncapResponse udpEncapResp =
|
IpSecUdpEncapResponse udpEncapResp =
|
||||||
new IpSecUdpEncapResponse(
|
new IpSecUdpEncapResponse(
|
||||||
IpSecManager.Status.OK,
|
IpSecManager.Status.OK,
|
||||||
resourceId,
|
DUMMY_RESOURCE_ID,
|
||||||
TEST_UDP_ENCAP_PORT,
|
TEST_UDP_ENCAP_PORT,
|
||||||
Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
|
Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
|
||||||
when(mMockIpSecService.openUdpEncapsulationSocket(eq(TEST_UDP_ENCAP_PORT), anyObject()))
|
when(mMockIpSecService.openUdpEncapsulationSocket(eq(TEST_UDP_ENCAP_PORT), anyObject()))
|
||||||
@@ -182,16 +184,15 @@ public class IpSecManagerTest {
|
|||||||
|
|
||||||
encapSocket.close();
|
encapSocket.close();
|
||||||
|
|
||||||
verify(mMockIpSecService).closeUdpEncapsulationSocket(resourceId);
|
verify(mMockIpSecService).closeUdpEncapsulationSocket(DUMMY_RESOURCE_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOpenEncapsulationSocketOnRandomPort() throws Exception {
|
public void testOpenEncapsulationSocketOnRandomPort() throws Exception {
|
||||||
int resourceId = 1;
|
|
||||||
IpSecUdpEncapResponse udpEncapResp =
|
IpSecUdpEncapResponse udpEncapResp =
|
||||||
new IpSecUdpEncapResponse(
|
new IpSecUdpEncapResponse(
|
||||||
IpSecManager.Status.OK,
|
IpSecManager.Status.OK,
|
||||||
resourceId,
|
DUMMY_RESOURCE_ID,
|
||||||
TEST_UDP_ENCAP_PORT,
|
TEST_UDP_ENCAP_PORT,
|
||||||
Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
|
Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
|
||||||
|
|
||||||
@@ -206,7 +207,7 @@ public class IpSecManagerTest {
|
|||||||
|
|
||||||
encapSocket.close();
|
encapSocket.close();
|
||||||
|
|
||||||
verify(mMockIpSecService).closeUdpEncapsulationSocket(resourceId);
|
verify(mMockIpSecService).closeUdpEncapsulationSocket(DUMMY_RESOURCE_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -219,4 +220,45 @@ public class IpSecManagerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add test when applicable transform builder interface is available
|
// TODO: add test when applicable transform builder interface is available
|
||||||
}
|
|
||||||
|
private IpSecManager.IpSecTunnelInterface createAndValidateVti(int resourceId, String intfName)
|
||||||
|
throws Exception {
|
||||||
|
IpSecTunnelInterfaceResponse dummyResponse =
|
||||||
|
new IpSecTunnelInterfaceResponse(IpSecManager.Status.OK, resourceId, intfName);
|
||||||
|
when(mMockIpSecService.createTunnelInterface(
|
||||||
|
eq(VTI_LOCAL_ADDRESS.getHostAddress()), eq(GOOGLE_DNS_4.getHostAddress()),
|
||||||
|
anyObject(), anyObject()))
|
||||||
|
.thenReturn(dummyResponse);
|
||||||
|
|
||||||
|
IpSecManager.IpSecTunnelInterface tunnelIntf = mIpSecManager.createIpSecTunnelInterface(
|
||||||
|
VTI_LOCAL_ADDRESS, GOOGLE_DNS_4, mock(Network.class));
|
||||||
|
|
||||||
|
assertNotNull(tunnelIntf);
|
||||||
|
return tunnelIntf;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateVti() throws Exception {
|
||||||
|
IpSecManager.IpSecTunnelInterface tunnelIntf =
|
||||||
|
createAndValidateVti(DUMMY_RESOURCE_ID, VTI_INTF_NAME);
|
||||||
|
|
||||||
|
assertEquals(VTI_INTF_NAME, tunnelIntf.getInterfaceName());
|
||||||
|
|
||||||
|
tunnelIntf.close();
|
||||||
|
verify(mMockIpSecService).deleteTunnelInterface(eq(DUMMY_RESOURCE_ID));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddRemoveAddressesFromVti() throws Exception {
|
||||||
|
IpSecManager.IpSecTunnelInterface tunnelIntf =
|
||||||
|
createAndValidateVti(DUMMY_RESOURCE_ID, VTI_INTF_NAME);
|
||||||
|
|
||||||
|
tunnelIntf.addAddress(VTI_INNER_ADDRESS);
|
||||||
|
verify(mMockIpSecService)
|
||||||
|
.addAddressToTunnelInterface(eq(DUMMY_RESOURCE_ID), eq(VTI_INNER_ADDRESS));
|
||||||
|
|
||||||
|
tunnelIntf.removeAddress(VTI_INNER_ADDRESS);
|
||||||
|
verify(mMockIpSecService)
|
||||||
|
.addAddressToTunnelInterface(eq(DUMMY_RESOURCE_ID), eq(VTI_INNER_ADDRESS));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
package com.android.server;
|
package com.android.server;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
import static org.mockito.Matchers.anyInt;
|
import static org.mockito.Matchers.anyInt;
|
||||||
import static org.mockito.Matchers.anyString;
|
import static org.mockito.Matchers.anyString;
|
||||||
@@ -32,6 +33,9 @@ import android.net.IpSecConfig;
|
|||||||
import android.net.IpSecManager;
|
import android.net.IpSecManager;
|
||||||
import android.net.IpSecSpiResponse;
|
import android.net.IpSecSpiResponse;
|
||||||
import android.net.IpSecTransformResponse;
|
import android.net.IpSecTransformResponse;
|
||||||
|
import android.net.IpSecTunnelInterfaceResponse;
|
||||||
|
import android.net.LinkAddress;
|
||||||
|
import android.net.Network;
|
||||||
import android.net.NetworkUtils;
|
import android.net.NetworkUtils;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
@@ -56,10 +60,15 @@ public class IpSecServiceParameterizedTest {
|
|||||||
|
|
||||||
private final String mDestinationAddr;
|
private final String mDestinationAddr;
|
||||||
private final String mSourceAddr;
|
private final String mSourceAddr;
|
||||||
|
private final LinkAddress mLocalInnerAddress;
|
||||||
|
|
||||||
@Parameterized.Parameters
|
@Parameterized.Parameters
|
||||||
public static Collection ipSecConfigs() {
|
public static Collection ipSecConfigs() {
|
||||||
return Arrays.asList(new Object[][] {{"1.2.3.4", "8.8.4.4"}, {"2601::2", "2601::10"}});
|
return Arrays.asList(
|
||||||
|
new Object[][] {
|
||||||
|
{"1.2.3.4", "8.8.4.4", "10.0.1.1/24"},
|
||||||
|
{"2601::2", "2601::10", "2001:db8::1/64"}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final byte[] AEAD_KEY = {
|
private static final byte[] AEAD_KEY = {
|
||||||
@@ -86,6 +95,7 @@ public class IpSecServiceParameterizedTest {
|
|||||||
INetd mMockNetd;
|
INetd mMockNetd;
|
||||||
IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig;
|
IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig;
|
||||||
IpSecService mIpSecService;
|
IpSecService mIpSecService;
|
||||||
|
Network fakeNetwork = new Network(0xAB);
|
||||||
|
|
||||||
private static final IpSecAlgorithm AUTH_ALGO =
|
private static final IpSecAlgorithm AUTH_ALGO =
|
||||||
new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 4);
|
new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 4);
|
||||||
@@ -94,9 +104,11 @@ public class IpSecServiceParameterizedTest {
|
|||||||
private static final IpSecAlgorithm AEAD_ALGO =
|
private static final IpSecAlgorithm AEAD_ALGO =
|
||||||
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
|
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
|
||||||
|
|
||||||
public IpSecServiceParameterizedTest(String sourceAddr, String destAddr) {
|
public IpSecServiceParameterizedTest(
|
||||||
|
String sourceAddr, String destAddr, String localInnerAddr) {
|
||||||
mSourceAddr = sourceAddr;
|
mSourceAddr = sourceAddr;
|
||||||
mDestinationAddr = destAddr;
|
mDestinationAddr = destAddr;
|
||||||
|
mLocalInnerAddress = new LinkAddress(localInnerAddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@@ -406,4 +418,103 @@ public class IpSecServiceParameterizedTest {
|
|||||||
|
|
||||||
verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd.getFileDescriptor());
|
verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd.getFileDescriptor());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IpSecTunnelInterfaceResponse createAndValidateTunnel(
|
||||||
|
String localAddr, String remoteAddr) {
|
||||||
|
IpSecTunnelInterfaceResponse createTunnelResp =
|
||||||
|
mIpSecService.createTunnelInterface(
|
||||||
|
mSourceAddr, mDestinationAddr, fakeNetwork, new Binder());
|
||||||
|
|
||||||
|
assertNotNull(createTunnelResp);
|
||||||
|
assertEquals(IpSecManager.Status.OK, createTunnelResp.status);
|
||||||
|
return createTunnelResp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateTunnelInterface() throws Exception {
|
||||||
|
IpSecTunnelInterfaceResponse createTunnelResp =
|
||||||
|
createAndValidateTunnel(mSourceAddr, mDestinationAddr);
|
||||||
|
|
||||||
|
// Check that we have stored the tracking object, and retrieve it
|
||||||
|
IpSecService.UserRecord userRecord =
|
||||||
|
mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
|
||||||
|
IpSecService.RefcountedResource refcountedRecord =
|
||||||
|
userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
|
||||||
|
createTunnelResp.resourceId);
|
||||||
|
|
||||||
|
assertEquals(1, userRecord.mTunnelQuotaTracker.mCurrent);
|
||||||
|
verify(mMockNetd)
|
||||||
|
.addVirtualTunnelInterface(
|
||||||
|
eq(createTunnelResp.interfaceName),
|
||||||
|
eq(mSourceAddr),
|
||||||
|
eq(mDestinationAddr),
|
||||||
|
anyInt(),
|
||||||
|
anyInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeleteTunnelInterface() throws Exception {
|
||||||
|
IpSecTunnelInterfaceResponse createTunnelResp =
|
||||||
|
createAndValidateTunnel(mSourceAddr, mDestinationAddr);
|
||||||
|
|
||||||
|
IpSecService.UserRecord userRecord =
|
||||||
|
mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
|
||||||
|
|
||||||
|
mIpSecService.deleteTunnelInterface(createTunnelResp.resourceId);
|
||||||
|
|
||||||
|
// Verify quota and RefcountedResource objects cleaned up
|
||||||
|
assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent);
|
||||||
|
verify(mMockNetd).removeVirtualTunnelInterface(eq(createTunnelResp.interfaceName));
|
||||||
|
try {
|
||||||
|
userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
|
||||||
|
createTunnelResp.resourceId);
|
||||||
|
fail("Expected IllegalArgumentException on attempt to access deleted resource");
|
||||||
|
} catch (IllegalArgumentException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTunnelInterfaceBinderDeath() throws Exception {
|
||||||
|
IpSecTunnelInterfaceResponse createTunnelResp =
|
||||||
|
createAndValidateTunnel(mSourceAddr, mDestinationAddr);
|
||||||
|
|
||||||
|
IpSecService.UserRecord userRecord =
|
||||||
|
mIpSecService.mUserResourceTracker.getUserRecord(Os.getuid());
|
||||||
|
IpSecService.RefcountedResource refcountedRecord =
|
||||||
|
userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
|
||||||
|
createTunnelResp.resourceId);
|
||||||
|
|
||||||
|
refcountedRecord.binderDied();
|
||||||
|
|
||||||
|
// Verify quota and RefcountedResource objects cleaned up
|
||||||
|
assertEquals(0, userRecord.mTunnelQuotaTracker.mCurrent);
|
||||||
|
verify(mMockNetd).removeVirtualTunnelInterface(eq(createTunnelResp.interfaceName));
|
||||||
|
try {
|
||||||
|
userRecord.mTunnelInterfaceRecords.getRefcountedResourceOrThrow(
|
||||||
|
createTunnelResp.resourceId);
|
||||||
|
fail("Expected IllegalArgumentException on attempt to access deleted resource");
|
||||||
|
} catch (IllegalArgumentException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddRemoveAddressFromTunnelInterface() throws Exception {
|
||||||
|
IpSecTunnelInterfaceResponse createTunnelResp =
|
||||||
|
createAndValidateTunnel(mSourceAddr, mDestinationAddr);
|
||||||
|
|
||||||
|
mIpSecService.addAddressToTunnelInterface(createTunnelResp.resourceId, mLocalInnerAddress);
|
||||||
|
verify(mMockNetd)
|
||||||
|
.interfaceAddAddress(
|
||||||
|
eq(createTunnelResp.interfaceName),
|
||||||
|
eq(mLocalInnerAddress.getAddress().getHostAddress()),
|
||||||
|
eq(mLocalInnerAddress.getPrefixLength()));
|
||||||
|
|
||||||
|
mIpSecService.removeAddressFromTunnelInterface(
|
||||||
|
createTunnelResp.resourceId, mLocalInnerAddress);
|
||||||
|
verify(mMockNetd)
|
||||||
|
.interfaceDelAddress(
|
||||||
|
eq(createTunnelResp.interfaceName),
|
||||||
|
eq(mLocalInnerAddress.getAddress().getHostAddress()),
|
||||||
|
eq(mLocalInnerAddress.getPrefixLength()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user