Translate v4 keepalive packet on clat started network to v6

This commit translates the address of keepalive packet to v6
in order to make NATT keepalive work on v6 only network.

Sending a v4 NATT keepalive on a v6 only network is bogus if
hardware does not translate the packet automatically. Network
may drop the packet or reject the attempt by hardware. This
results in ERROR_INVALID_IP_ADDRESS and stop the keepalive
request.

Bug: 196453719
Test: atest FrameworksNetTests
Test: Manually connect to v6 only network and check if the
      keepalive packets are sent
Change-Id: I798c5d48661d8151b19902435732f465b5aa725b
This commit is contained in:
chiachangwang
2023-06-27 02:54:12 +00:00
parent 558aa41874
commit c5c5c84f4c
4 changed files with 141 additions and 22 deletions

View File

@@ -6850,17 +6850,19 @@ public class ConnectivityServiceTest {
@Test
public void testPacketKeepalives() throws Exception {
InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
final LinkAddress v4Addr = new LinkAddress("192.0.2.129/24");
final InetAddress myIPv4 = v4Addr.getAddress();
InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
doReturn(getClatInterfaceConfigParcel(v4Addr)).when(mMockNetd)
.interfaceGetCfg(CLAT_MOBILE_IFNAME);
final int validKaInterval = 15;
final int invalidKaInterval = 9;
LinkProperties lp = new LinkProperties();
lp.setInterfaceName("wlan12");
lp.setInterfaceName(MOBILE_IFNAME);
lp.addLinkAddress(new LinkAddress(myIPv6, 64));
lp.addLinkAddress(new LinkAddress(myIPv4, 25));
lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));

View File

@@ -52,6 +52,7 @@ import android.content.Context;
import android.content.res.Resources;
import android.net.INetd;
import android.net.ISocketKeepaliveCallback;
import android.net.InetAddresses;
import android.net.KeepalivePacketData;
import android.net.LinkAddress;
import android.net.LinkProperties;
@@ -116,7 +117,8 @@ public class AutomaticOnOffKeepaliveTrackerTest {
private static final int MOCK_RESOURCE_ID = 5;
private static final int TEST_KEEPALIVE_INTERVAL_SEC = 10;
private static final int TEST_KEEPALIVE_INVALID_INTERVAL_SEC = 9;
private static final byte[] V4_SRC_ADDR = new byte[] { (byte) 192, 0, 0, (byte) 129 };
private static final String TEST_V4_IFACE = "v4-testIface";
private AutomaticOnOffKeepaliveTracker mAOOKeepaliveTracker;
private HandlerThread mHandlerThread;
@@ -327,6 +329,8 @@ public class AutomaticOnOffKeepaliveTrackerTest {
NetworkInfo.DetailedState.CONNECTED, "test reason", "test extra info");
doReturn(new Network(TEST_NETID)).when(mNai).network();
mNai.linkProperties = new LinkProperties();
doReturn(null).when(mNai).translateV4toClatV6(any());
doReturn(null).when(mNai).getClatv6SrcAddress();
doReturn(PERMISSION_GRANTED).when(mCtx).checkPermission(any() /* permission */,
anyInt() /* pid */, anyInt() /* uid */);
@@ -429,8 +433,7 @@ public class AutomaticOnOffKeepaliveTrackerTest {
}
private TestKeepaliveInfo doStartNattKeepalive(int intervalSeconds) throws Exception {
final InetAddress srcAddress = InetAddress.getByAddress(
new byte[] { (byte) 192, 0, 0, (byte) 129 });
final InetAddress srcAddress = InetAddress.getByAddress(V4_SRC_ADDR);
final int srcPort = 12345;
final InetAddress dstAddress = InetAddress.getByAddress(new byte[] {8, 8, 8, 8});
final int dstPort = 12345;
@@ -609,6 +612,42 @@ public class AutomaticOnOffKeepaliveTrackerTest {
verifyNoMoreInteractions(ignoreStubs(testInfo.socketKeepaliveCallback));
}
@Test
public void testStartNattKeepalive_addressTranslationOnClat() throws Exception {
final InetAddress v6AddrSrc = InetAddresses.parseNumericAddress("2001:db8::1");
final InetAddress v6AddrDst = InetAddresses.parseNumericAddress("2001:db8::2");
doReturn(v6AddrDst).when(mNai).translateV4toClatV6(any());
doReturn(v6AddrSrc).when(mNai).getClatv6SrcAddress();
doReturn(InetAddress.getByAddress(V4_SRC_ADDR)).when(mNai).getClatv4SrcAddress();
// Setup nai to add clat address
final LinkProperties stacked = new LinkProperties();
stacked.setInterfaceName(TEST_V4_IFACE);
mNai.linkProperties.addStackedLink(stacked);
final TestKeepaliveInfo testInfo = doStartNattKeepalive();
final ArgumentCaptor<NattKeepalivePacketData> kpdCaptor =
ArgumentCaptor.forClass(NattKeepalivePacketData.class);
verify(mNai).onStartNattSocketKeepalive(
eq(TEST_SLOT), eq(TEST_KEEPALIVE_INTERVAL_SEC), kpdCaptor.capture());
final NattKeepalivePacketData kpd = kpdCaptor.getValue();
// Verify the addresses are updated to v6 when clat is started.
assertEquals(v6AddrSrc, kpd.getSrcAddress());
assertEquals(v6AddrDst, kpd.getDstAddress());
triggerEventKeepalive(TEST_SLOT, SocketKeepalive.SUCCESS);
verify(testInfo.socketKeepaliveCallback).onStarted();
// Remove clat address should stop the keepalive.
doReturn(null).when(mNai).getClatv6SrcAddress();
visibleOnHandlerThread(
mTestHandler, () -> mAOOKeepaliveTracker.handleCheckKeepalivesStillValid(mNai));
checkAndProcessKeepaliveStop();
assertNull(getAutoKiForBinder(testInfo.binder));
verify(testInfo.socketKeepaliveCallback).onError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
verifyNoMoreInteractions(ignoreStubs(testInfo.socketKeepaliveCallback));
}
@Test
public void testHandleEventSocketKeepalive_startingFailureHardwareError() throws Exception {
final TestKeepaliveInfo testInfo = doStartNattKeepalive();