Loading core/java/android/net/IIpSecService.aidl +3 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.net; import android.net.LinkAddress; import android.net.Network; import android.net.IpSecConfig; import android.net.IpSecUdpEncapResponse; Loading Loading @@ -48,11 +49,11 @@ interface IIpSecService void addAddressToTunnelInterface( int tunnelResourceId, String localAddr); in LinkAddress localAddr); void removeAddressFromTunnelInterface( int tunnelResourceId, String localAddr); in LinkAddress localAddr); void deleteTunnelInterface(int resourceId); Loading core/java/android/net/IpSecManager.java +12 −4 Original line number Diff line number Diff line Loading @@ -656,10 +656,14 @@ public final class IpSecManager { * tunneled traffic. * * @param address the local address for traffic inside the tunnel * @throws IOException if the address could not be added * @hide */ public void addAddress(LinkAddress address) throws IOException { public void addAddress(LinkAddress address) { try { mService.addAddressToTunnelInterface(mResourceId, address); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Loading @@ -668,10 +672,14 @@ public final class IpSecManager { * <p>Remove an address which was previously added to the IpSecTunnelInterface * * @param address to be removed * @throws IOException if the address could not be removed * @hide */ public void removeAddress(LinkAddress address) throws IOException { public void removeAddress(LinkAddress address) { try { mService.removeAddressFromTunnelInterface(mResourceId, address); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } private IpSecTunnelInterface(@NonNull IIpSecService service, Loading services/core/java/com/android/server/IpSecService.java +42 −18 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import android.net.IpSecTransform; import android.net.IpSecTransformResponse; import android.net.IpSecTunnelInterfaceResponse; import android.net.IpSecUdpEncapResponse; import android.net.LinkAddress; import android.net.Network; import android.net.NetworkUtils; import android.net.TrafficStats; Loading Loading @@ -618,10 +619,8 @@ public class IpSecService extends IIpSecService.Stub { spi, mConfig.getMarkValue(), mConfig.getMarkMask()); } 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 SA with ID: " + mResourceId); } catch (RemoteException | ServiceSpecificException e) { Log.e(TAG, "Failed to delete SA with ID: " + mResourceId, e); } getResourceTracker().give(); Loading Loading @@ -681,10 +680,8 @@ public class IpSecService extends IIpSecService.Stub { .getNetdInstance() .ipSecDeleteSecurityAssociation( mResourceId, mSourceAddress, mDestinationAddress, mSpi, 0, 0); } 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 SPI reservation with ID: " + mResourceId); } catch (ServiceSpecificException | RemoteException e) { Log.e(TAG, "Failed to delete SPI reservation with ID: " + mResourceId, e); } mSpi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX; Loading Loading @@ -829,15 +826,13 @@ public class IpSecService extends IIpSecService.Stub { 0, direction, wildcardAddr, wildcardAddr, mark, 0xffffffff); } } } catch (ServiceSpecificException e) { // FIXME: get the error code and throw is at an IOException from Errno Exception } catch (RemoteException e) { } catch (ServiceSpecificException | RemoteException e) { Log.e( TAG, "Failed to delete VTI with interface name: " + mInterfaceName + " and id: " + mResourceId); + mResourceId, e); } getResourceTracker().give(); Loading Loading @@ -1319,7 +1314,9 @@ public class IpSecService extends IIpSecService.Stub { * from multiple local IP addresses over the same tunnel. */ @Override public synchronized void addAddressToTunnelInterface(int tunnelResourceId, String localAddr) { public synchronized void addAddressToTunnelInterface( int tunnelResourceId, LinkAddress localAddr) { enforceNetworkStackPermission(); UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); // Get tunnelInterface record; if no such interface is found, will throw Loading @@ -1327,8 +1324,21 @@ public class IpSecService extends IIpSecService.Stub { TunnelInterfaceRecord tunnelInterfaceInfo = userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelResourceId); // TODO: Add calls to netd: // Add address to TunnelInterface try { // We can assume general validity of the IP address, since we get them as a // LinkAddress, which does some validation. mSrvConfig .getNetdInstance() .interfaceAddAddress( tunnelInterfaceInfo.mInterfaceName, localAddr.getAddress().getHostAddress(), localAddr.getPrefixLength()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { // If we get here, one of the arguments provided was invalid. Wrap the SSE, and throw. throw new IllegalArgumentException(e); } } /** Loading @@ -1337,7 +1347,8 @@ public class IpSecService extends IIpSecService.Stub { */ @Override public synchronized void removeAddressFromTunnelInterface( int tunnelResourceId, String localAddr) { int tunnelResourceId, LinkAddress localAddr) { enforceNetworkStackPermission(); UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); // Get tunnelInterface record; if no such interface is found, will throw Loading @@ -1345,8 +1356,21 @@ public class IpSecService extends IIpSecService.Stub { TunnelInterfaceRecord tunnelInterfaceInfo = userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelResourceId); // TODO: Add calls to netd: // Remove address from TunnelInterface try { // We can assume general validity of the IP address, since we get them as a // LinkAddress, which does some validation. mSrvConfig .getNetdInstance() .interfaceDelAddress( tunnelInterfaceInfo.mInterfaceName, localAddr.getAddress().getHostAddress(), localAddr.getPrefixLength()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { // If we get here, one of the arguments provided was invalid. Wrap the SSE, and throw. throw new IllegalArgumentException(e); } } /** Loading tests/net/java/android/net/IpSecManagerTest.java +55 −13 Original line number Diff line number Diff line Loading @@ -50,13 +50,18 @@ public class IpSecManagerTest { private static final int TEST_UDP_ENCAP_PORT = 34567; 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 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 { try { // Google Public DNS Addresses; GOOGLE_DNS_4 = InetAddress.getByName("8.8.8.8"); VTI_LOCAL_ADDRESS = InetAddress.getByName("8.8.4.4"); } catch (UnknownHostException e) { throw new RuntimeException("Could not resolve DNS Addresses", e); } Loading @@ -77,9 +82,8 @@ public class IpSecManagerTest { */ @Test public void testAllocSpi() throws Exception { int resourceId = 1; IpSecSpiResponse spiResp = new IpSecSpiResponse(IpSecManager.Status.OK, resourceId, DROID_SPI); new IpSecSpiResponse(IpSecManager.Status.OK, DUMMY_RESOURCE_ID, DROID_SPI); when(mMockIpSecService.allocateSecurityParameterIndex( eq(GOOGLE_DNS_4.getHostAddress()), eq(DROID_SPI), Loading @@ -92,14 +96,13 @@ public class IpSecManagerTest { droidSpi.close(); verify(mMockIpSecService).releaseSecurityParameterIndex(resourceId); verify(mMockIpSecService).releaseSecurityParameterIndex(DUMMY_RESOURCE_ID); } @Test public void testAllocRandomSpi() throws Exception { int resourceId = 1; IpSecSpiResponse spiResp = new IpSecSpiResponse(IpSecManager.Status.OK, resourceId, DROID_SPI); new IpSecSpiResponse(IpSecManager.Status.OK, DUMMY_RESOURCE_ID, DROID_SPI); when(mMockIpSecService.allocateSecurityParameterIndex( eq(GOOGLE_DNS_4.getHostAddress()), eq(IpSecManager.INVALID_SECURITY_PARAMETER_INDEX), Loading @@ -113,7 +116,7 @@ public class IpSecManagerTest { randomSpi.close(); verify(mMockIpSecService).releaseSecurityParameterIndex(resourceId); verify(mMockIpSecService).releaseSecurityParameterIndex(DUMMY_RESOURCE_ID); } /* Loading Loading @@ -165,11 +168,10 @@ public class IpSecManagerTest { @Test public void testOpenEncapsulationSocket() throws Exception { int resourceId = 1; IpSecUdpEncapResponse udpEncapResp = new IpSecUdpEncapResponse( IpSecManager.Status.OK, resourceId, DUMMY_RESOURCE_ID, TEST_UDP_ENCAP_PORT, Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)); when(mMockIpSecService.openUdpEncapsulationSocket(eq(TEST_UDP_ENCAP_PORT), anyObject())) Loading @@ -182,16 +184,15 @@ public class IpSecManagerTest { encapSocket.close(); verify(mMockIpSecService).closeUdpEncapsulationSocket(resourceId); verify(mMockIpSecService).closeUdpEncapsulationSocket(DUMMY_RESOURCE_ID); } @Test public void testOpenEncapsulationSocketOnRandomPort() throws Exception { int resourceId = 1; IpSecUdpEncapResponse udpEncapResp = new IpSecUdpEncapResponse( IpSecManager.Status.OK, resourceId, DUMMY_RESOURCE_ID, TEST_UDP_ENCAP_PORT, Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)); Loading @@ -206,7 +207,7 @@ public class IpSecManagerTest { encapSocket.close(); verify(mMockIpSecService).closeUdpEncapsulationSocket(resourceId); verify(mMockIpSecService).closeUdpEncapsulationSocket(DUMMY_RESOURCE_ID); } @Test Loading @@ -219,4 +220,45 @@ public class IpSecManagerTest { } // 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)); } } No newline at end of file tests/net/java/com/android/server/IpSecServiceParameterizedTest.java +113 −2 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; Loading @@ -32,6 +33,9 @@ import android.net.IpSecConfig; import android.net.IpSecManager; import android.net.IpSecSpiResponse; import android.net.IpSecTransformResponse; import android.net.IpSecTunnelInterfaceResponse; import android.net.LinkAddress; import android.net.Network; import android.net.NetworkUtils; import android.os.Binder; import android.os.ParcelFileDescriptor; Loading @@ -56,10 +60,15 @@ public class IpSecServiceParameterizedTest { private final String mDestinationAddr; private final String mSourceAddr; private final LinkAddress mLocalInnerAddress; @Parameterized.Parameters 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 = { Loading @@ -86,6 +95,7 @@ public class IpSecServiceParameterizedTest { INetd mMockNetd; IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig; IpSecService mIpSecService; Network fakeNetwork = new Network(0xAB); private static final IpSecAlgorithm AUTH_ALGO = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 4); Loading @@ -94,9 +104,11 @@ public class IpSecServiceParameterizedTest { private static final IpSecAlgorithm AEAD_ALGO = 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; mDestinationAddr = destAddr; mLocalInnerAddress = new LinkAddress(localInnerAddr); } @Before Loading Loading @@ -406,4 +418,103 @@ public class IpSecServiceParameterizedTest { 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())); } } Loading
core/java/android/net/IIpSecService.aidl +3 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.net; import android.net.LinkAddress; import android.net.Network; import android.net.IpSecConfig; import android.net.IpSecUdpEncapResponse; Loading Loading @@ -48,11 +49,11 @@ interface IIpSecService void addAddressToTunnelInterface( int tunnelResourceId, String localAddr); in LinkAddress localAddr); void removeAddressFromTunnelInterface( int tunnelResourceId, String localAddr); in LinkAddress localAddr); void deleteTunnelInterface(int resourceId); Loading
core/java/android/net/IpSecManager.java +12 −4 Original line number Diff line number Diff line Loading @@ -656,10 +656,14 @@ public final class IpSecManager { * tunneled traffic. * * @param address the local address for traffic inside the tunnel * @throws IOException if the address could not be added * @hide */ public void addAddress(LinkAddress address) throws IOException { public void addAddress(LinkAddress address) { try { mService.addAddressToTunnelInterface(mResourceId, address); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** Loading @@ -668,10 +672,14 @@ public final class IpSecManager { * <p>Remove an address which was previously added to the IpSecTunnelInterface * * @param address to be removed * @throws IOException if the address could not be removed * @hide */ public void removeAddress(LinkAddress address) throws IOException { public void removeAddress(LinkAddress address) { try { mService.removeAddressFromTunnelInterface(mResourceId, address); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } private IpSecTunnelInterface(@NonNull IIpSecService service, Loading
services/core/java/com/android/server/IpSecService.java +42 −18 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import android.net.IpSecTransform; import android.net.IpSecTransformResponse; import android.net.IpSecTunnelInterfaceResponse; import android.net.IpSecUdpEncapResponse; import android.net.LinkAddress; import android.net.Network; import android.net.NetworkUtils; import android.net.TrafficStats; Loading Loading @@ -618,10 +619,8 @@ public class IpSecService extends IIpSecService.Stub { spi, mConfig.getMarkValue(), mConfig.getMarkMask()); } 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 SA with ID: " + mResourceId); } catch (RemoteException | ServiceSpecificException e) { Log.e(TAG, "Failed to delete SA with ID: " + mResourceId, e); } getResourceTracker().give(); Loading Loading @@ -681,10 +680,8 @@ public class IpSecService extends IIpSecService.Stub { .getNetdInstance() .ipSecDeleteSecurityAssociation( mResourceId, mSourceAddress, mDestinationAddress, mSpi, 0, 0); } 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 SPI reservation with ID: " + mResourceId); } catch (ServiceSpecificException | RemoteException e) { Log.e(TAG, "Failed to delete SPI reservation with ID: " + mResourceId, e); } mSpi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX; Loading Loading @@ -829,15 +826,13 @@ public class IpSecService extends IIpSecService.Stub { 0, direction, wildcardAddr, wildcardAddr, mark, 0xffffffff); } } } catch (ServiceSpecificException e) { // FIXME: get the error code and throw is at an IOException from Errno Exception } catch (RemoteException e) { } catch (ServiceSpecificException | RemoteException e) { Log.e( TAG, "Failed to delete VTI with interface name: " + mInterfaceName + " and id: " + mResourceId); + mResourceId, e); } getResourceTracker().give(); Loading Loading @@ -1319,7 +1314,9 @@ public class IpSecService extends IIpSecService.Stub { * from multiple local IP addresses over the same tunnel. */ @Override public synchronized void addAddressToTunnelInterface(int tunnelResourceId, String localAddr) { public synchronized void addAddressToTunnelInterface( int tunnelResourceId, LinkAddress localAddr) { enforceNetworkStackPermission(); UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); // Get tunnelInterface record; if no such interface is found, will throw Loading @@ -1327,8 +1324,21 @@ public class IpSecService extends IIpSecService.Stub { TunnelInterfaceRecord tunnelInterfaceInfo = userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelResourceId); // TODO: Add calls to netd: // Add address to TunnelInterface try { // We can assume general validity of the IP address, since we get them as a // LinkAddress, which does some validation. mSrvConfig .getNetdInstance() .interfaceAddAddress( tunnelInterfaceInfo.mInterfaceName, localAddr.getAddress().getHostAddress(), localAddr.getPrefixLength()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { // If we get here, one of the arguments provided was invalid. Wrap the SSE, and throw. throw new IllegalArgumentException(e); } } /** Loading @@ -1337,7 +1347,8 @@ public class IpSecService extends IIpSecService.Stub { */ @Override public synchronized void removeAddressFromTunnelInterface( int tunnelResourceId, String localAddr) { int tunnelResourceId, LinkAddress localAddr) { enforceNetworkStackPermission(); UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); // Get tunnelInterface record; if no such interface is found, will throw Loading @@ -1345,8 +1356,21 @@ public class IpSecService extends IIpSecService.Stub { TunnelInterfaceRecord tunnelInterfaceInfo = userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelResourceId); // TODO: Add calls to netd: // Remove address from TunnelInterface try { // We can assume general validity of the IP address, since we get them as a // LinkAddress, which does some validation. mSrvConfig .getNetdInstance() .interfaceDelAddress( tunnelInterfaceInfo.mInterfaceName, localAddr.getAddress().getHostAddress(), localAddr.getPrefixLength()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { // If we get here, one of the arguments provided was invalid. Wrap the SSE, and throw. throw new IllegalArgumentException(e); } } /** Loading
tests/net/java/android/net/IpSecManagerTest.java +55 −13 Original line number Diff line number Diff line Loading @@ -50,13 +50,18 @@ public class IpSecManagerTest { private static final int TEST_UDP_ENCAP_PORT = 34567; 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 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 { try { // Google Public DNS Addresses; GOOGLE_DNS_4 = InetAddress.getByName("8.8.8.8"); VTI_LOCAL_ADDRESS = InetAddress.getByName("8.8.4.4"); } catch (UnknownHostException e) { throw new RuntimeException("Could not resolve DNS Addresses", e); } Loading @@ -77,9 +82,8 @@ public class IpSecManagerTest { */ @Test public void testAllocSpi() throws Exception { int resourceId = 1; IpSecSpiResponse spiResp = new IpSecSpiResponse(IpSecManager.Status.OK, resourceId, DROID_SPI); new IpSecSpiResponse(IpSecManager.Status.OK, DUMMY_RESOURCE_ID, DROID_SPI); when(mMockIpSecService.allocateSecurityParameterIndex( eq(GOOGLE_DNS_4.getHostAddress()), eq(DROID_SPI), Loading @@ -92,14 +96,13 @@ public class IpSecManagerTest { droidSpi.close(); verify(mMockIpSecService).releaseSecurityParameterIndex(resourceId); verify(mMockIpSecService).releaseSecurityParameterIndex(DUMMY_RESOURCE_ID); } @Test public void testAllocRandomSpi() throws Exception { int resourceId = 1; IpSecSpiResponse spiResp = new IpSecSpiResponse(IpSecManager.Status.OK, resourceId, DROID_SPI); new IpSecSpiResponse(IpSecManager.Status.OK, DUMMY_RESOURCE_ID, DROID_SPI); when(mMockIpSecService.allocateSecurityParameterIndex( eq(GOOGLE_DNS_4.getHostAddress()), eq(IpSecManager.INVALID_SECURITY_PARAMETER_INDEX), Loading @@ -113,7 +116,7 @@ public class IpSecManagerTest { randomSpi.close(); verify(mMockIpSecService).releaseSecurityParameterIndex(resourceId); verify(mMockIpSecService).releaseSecurityParameterIndex(DUMMY_RESOURCE_ID); } /* Loading Loading @@ -165,11 +168,10 @@ public class IpSecManagerTest { @Test public void testOpenEncapsulationSocket() throws Exception { int resourceId = 1; IpSecUdpEncapResponse udpEncapResp = new IpSecUdpEncapResponse( IpSecManager.Status.OK, resourceId, DUMMY_RESOURCE_ID, TEST_UDP_ENCAP_PORT, Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)); when(mMockIpSecService.openUdpEncapsulationSocket(eq(TEST_UDP_ENCAP_PORT), anyObject())) Loading @@ -182,16 +184,15 @@ public class IpSecManagerTest { encapSocket.close(); verify(mMockIpSecService).closeUdpEncapsulationSocket(resourceId); verify(mMockIpSecService).closeUdpEncapsulationSocket(DUMMY_RESOURCE_ID); } @Test public void testOpenEncapsulationSocketOnRandomPort() throws Exception { int resourceId = 1; IpSecUdpEncapResponse udpEncapResp = new IpSecUdpEncapResponse( IpSecManager.Status.OK, resourceId, DUMMY_RESOURCE_ID, TEST_UDP_ENCAP_PORT, Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)); Loading @@ -206,7 +207,7 @@ public class IpSecManagerTest { encapSocket.close(); verify(mMockIpSecService).closeUdpEncapsulationSocket(resourceId); verify(mMockIpSecService).closeUdpEncapsulationSocket(DUMMY_RESOURCE_ID); } @Test Loading @@ -219,4 +220,45 @@ public class IpSecManagerTest { } // 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)); } } No newline at end of file
tests/net/java/com/android/server/IpSecServiceParameterizedTest.java +113 −2 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; Loading @@ -32,6 +33,9 @@ import android.net.IpSecConfig; import android.net.IpSecManager; import android.net.IpSecSpiResponse; import android.net.IpSecTransformResponse; import android.net.IpSecTunnelInterfaceResponse; import android.net.LinkAddress; import android.net.Network; import android.net.NetworkUtils; import android.os.Binder; import android.os.ParcelFileDescriptor; Loading @@ -56,10 +60,15 @@ public class IpSecServiceParameterizedTest { private final String mDestinationAddr; private final String mSourceAddr; private final LinkAddress mLocalInnerAddress; @Parameterized.Parameters 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 = { Loading @@ -86,6 +95,7 @@ public class IpSecServiceParameterizedTest { INetd mMockNetd; IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig; IpSecService mIpSecService; Network fakeNetwork = new Network(0xAB); private static final IpSecAlgorithm AUTH_ALGO = new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 4); Loading @@ -94,9 +104,11 @@ public class IpSecServiceParameterizedTest { private static final IpSecAlgorithm AEAD_ALGO = 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; mDestinationAddr = destAddr; mLocalInnerAddress = new LinkAddress(localInnerAddr); } @Before Loading Loading @@ -406,4 +418,103 @@ public class IpSecServiceParameterizedTest { 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())); } }