From 67ece8d236c56388e1a4826fa97eda83c9195719 Mon Sep 17 00:00:00 2001 From: chiachangwang Date: Fri, 16 Jun 2023 01:27:55 +0000 Subject: [PATCH 1/3] Add methods to provide clat source address Add method to provide clat v6 address for the follow up commit to translate keepalive packets. Bug: 196453719 Test: atest FrameworksNetTests Change-Id: I2ee4ae52434afb29842a912c724194eeeea230d3 --- .../server/connectivity/Nat464Xlat.java | 19 +++++++++++++++++++ .../server/connectivity/NetworkAgentInfo.java | 9 +++++++++ 2 files changed, 28 insertions(+) diff --git a/service/src/com/android/server/connectivity/Nat464Xlat.java b/service/src/com/android/server/connectivity/Nat464Xlat.java index 90cdddabca..a2df7abcf9 100644 --- a/service/src/com/android/server/connectivity/Nat464Xlat.java +++ b/service/src/com/android/server/connectivity/Nat464Xlat.java @@ -540,6 +540,25 @@ public class Nat464Xlat { mNetwork.handler().post(() -> handleInterfaceRemoved(iface)); } + /** + * Get the generated v6 address of clat. + */ + @Nullable + public Inet6Address getClatv6SrcAddress() { + // Variables in Nat464Xlat should only be accessed from handler thread. + ensureRunningOnHandlerThread(); + if (!isStarted()) return null; + + return mIPv6Address; + } + + private void ensureRunningOnHandlerThread() { + if (mNetwork.handler().getLooper().getThread() != Thread.currentThread()) { + throw new IllegalStateException( + "Not running on handler thread: " + Thread.currentThread().getName()); + } + } + /** * Dump the NAT64 xlat information. * diff --git a/service/src/com/android/server/connectivity/NetworkAgentInfo.java b/service/src/com/android/server/connectivity/NetworkAgentInfo.java index 85282cbc9b..56ee117d07 100644 --- a/service/src/com/android/server/connectivity/NetworkAgentInfo.java +++ b/service/src/com/android/server/connectivity/NetworkAgentInfo.java @@ -68,6 +68,7 @@ import com.android.modules.utils.build.SdkLevel; import com.android.server.ConnectivityService; import java.io.PrintWriter; +import java.net.Inet6Address; import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; @@ -1032,6 +1033,14 @@ public class NetworkAgentInfo implements NetworkRanker.Scoreable { return network; } + /** + * Get the generated v6 address of clat. + */ + @Nullable + public Inet6Address getClatv6SrcAddress() { + return clatd.getClatv6SrcAddress(); + } + /** * Get the NetworkMonitorManager in this NetworkAgentInfo. * From d07be2decbd0643a33411761ac8623af76d47142 Mon Sep 17 00:00:00 2001 From: chiachangwang Date: Tue, 20 Jun 2023 02:40:56 +0000 Subject: [PATCH 2/3] Add helper method to translate v4 address pair to clat v6 Add helper method to translate address for the follow up commit to translate keepalive packets. Bug: 196453719 Test: atest FrameworksNetTests Change-Id: I02378125e18d6b527dfbefce5066447856f8cfef --- .../server/connectivity/Nat464Xlat.java | 30 +++++++++++++++++++ .../server/connectivity/NetworkAgentInfo.java | 9 ++++++ 2 files changed, 39 insertions(+) diff --git a/service/src/com/android/server/connectivity/Nat464Xlat.java b/service/src/com/android/server/connectivity/Nat464Xlat.java index a2df7abcf9..4f1f871311 100644 --- a/service/src/com/android/server/connectivity/Nat464Xlat.java +++ b/service/src/com/android/server/connectivity/Nat464Xlat.java @@ -44,7 +44,9 @@ import com.android.net.module.util.NetworkStackConstants; import com.android.server.ConnectivityService; import java.io.IOException; +import java.net.Inet4Address; import java.net.Inet6Address; +import java.net.UnknownHostException; import java.util.Objects; /** @@ -540,6 +542,34 @@ public class Nat464Xlat { mNetwork.handler().post(() -> handleInterfaceRemoved(iface)); } + /** + * Translate the input v4 address to v6 clat address. + */ + @Nullable + public Inet6Address translateV4toV6(@NonNull Inet4Address addr) { + // Variables in Nat464Xlat should only be accessed from handler thread. + ensureRunningOnHandlerThread(); + if (!isStarted()) return null; + + return convertv4ToClatv6(mNat64PrefixInUse, addr); + } + + @Nullable + private static Inet6Address convertv4ToClatv6( + @NonNull IpPrefix prefix, @NonNull Inet4Address addr) { + final byte[] v6Addr = new byte[16]; + // Generate a v6 address from Nat64 prefix. Prefix should be 12 bytes long. + System.arraycopy(prefix.getAddress().getAddress(), 0, v6Addr, 0, 12); + System.arraycopy(addr.getAddress(), 0, v6Addr, 12, 4); + + try { + return (Inet6Address) Inet6Address.getByAddress(v6Addr); + } catch (UnknownHostException e) { + Log.e(TAG, "getByAddress should never throw for a numeric address"); + return null; + } + } + /** * Get the generated v6 address of clat. */ diff --git a/service/src/com/android/server/connectivity/NetworkAgentInfo.java b/service/src/com/android/server/connectivity/NetworkAgentInfo.java index 56ee117d07..08c14556d2 100644 --- a/service/src/com/android/server/connectivity/NetworkAgentInfo.java +++ b/service/src/com/android/server/connectivity/NetworkAgentInfo.java @@ -68,6 +68,7 @@ import com.android.modules.utils.build.SdkLevel; import com.android.server.ConnectivityService; import java.io.PrintWriter; +import java.net.Inet4Address; import java.net.Inet6Address; import java.time.Instant; import java.util.ArrayList; @@ -1041,6 +1042,14 @@ public class NetworkAgentInfo implements NetworkRanker.Scoreable { return clatd.getClatv6SrcAddress(); } + /** + * Translate the input v4 address to v6 clat address. + */ + @Nullable + public Inet6Address translateV4toClatV6(@NonNull Inet4Address addr) { + return clatd.translateV4toV6(addr); + } + /** * Get the NetworkMonitorManager in this NetworkAgentInfo. * From b3eccf7b8ab9bdf61bf9a93192defd968baad780 Mon Sep 17 00:00:00 2001 From: chiachangwang Date: Tue, 20 Jun 2023 02:41:52 +0000 Subject: [PATCH 3/3] Reset the generated v6 clat address when stop The v6 address is generated from the prefix when clat is started. The address should be reset when clat is stop. Test: atest FrameworksNetTests Change-Id: I943d4efba85dda556dd1ec852322caaf9470e87b --- .../src/com/android/server/connectivity/Nat464Xlat.java | 5 +++-- .../com/android/server/connectivity/Nat464XlatTest.java | 8 +++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/service/src/com/android/server/connectivity/Nat464Xlat.java b/service/src/com/android/server/connectivity/Nat464Xlat.java index 4f1f871311..b315235253 100644 --- a/service/src/com/android/server/connectivity/Nat464Xlat.java +++ b/service/src/com/android/server/connectivity/Nat464Xlat.java @@ -101,7 +101,8 @@ public class Nat464Xlat { private IpPrefix mNat64PrefixFromRa; private String mBaseIface; private String mIface; - private Inet6Address mIPv6Address; + @VisibleForTesting + Inet6Address mIPv6Address; private State mState = State.IDLE; private final ClatCoordinator mClatCoordinator; // non-null iff T+ @@ -241,6 +242,7 @@ public class Nat464Xlat { mNat64PrefixInUse = null; mIface = null; mBaseIface = null; + mIPv6Address = null; if (!mPrefixDiscoveryRunning) { setPrefix64(null); @@ -577,7 +579,6 @@ public class Nat464Xlat { public Inet6Address getClatv6SrcAddress() { // Variables in Nat464Xlat should only be accessed from handler thread. ensureRunningOnHandlerThread(); - if (!isStarted()) return null; return mIPv6Address; } diff --git a/tests/unit/java/com/android/server/connectivity/Nat464XlatTest.java b/tests/unit/java/com/android/server/connectivity/Nat464XlatTest.java index 06e0d6df3c..58c0114761 100644 --- a/tests/unit/java/com/android/server/connectivity/Nat464XlatTest.java +++ b/tests/unit/java/com/android/server/connectivity/Nat464XlatTest.java @@ -20,10 +20,12 @@ import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.never; @@ -72,6 +74,7 @@ public class Nat464XlatTest { static final String STACKED_IFACE = "v4-test0"; static final LinkAddress V6ADDR = new LinkAddress("2001:db8:1::f00/64"); static final LinkAddress ADDR = new LinkAddress("192.0.2.5/29"); + static final String CLAT_V6 = "64:ff9b::1"; static final String NAT64_PREFIX = "64:ff9b::/96"; static final String OTHER_NAT64_PREFIX = "2001:db8:0:64::/96"; static final int NETID = 42; @@ -132,6 +135,8 @@ public class Nat464XlatTest { when(mNetd.interfaceGetCfg(eq(STACKED_IFACE))).thenReturn(mConfig); mConfig.ipv4Addr = ADDR.getAddress().getHostAddress(); mConfig.prefixLength = ADDR.getPrefixLength(); + doReturn(CLAT_V6).when(mClatCoordinator).clatStart( + BASE_IFACE, NETID, new IpPrefix(NAT64_PREFIX)); } private void assertRequiresClat(boolean expected, NetworkAgentInfo nai) { @@ -286,7 +291,8 @@ public class Nat464XlatTest { assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); verify(mDnsResolver).stopPrefix64Discovery(eq(NETID)); assertIdle(nat); - + // Verify the generated v6 is reset when clat is stopped. + assertNull(nat.mIPv6Address); // Stacked interface removed notification arrives and is ignored. nat.interfaceRemoved(STACKED_IFACE); mLooper.dispatchNext();