From aa0e9602bb4e845bd84984e130b9a432d8afa40b Mon Sep 17 00:00:00 2001 From: Yuyang Huang Date: Fri, 17 Mar 2023 12:43:09 +0900 Subject: [PATCH] NsdService should set the Inet6Address scope ids Link local Inet6Address cannot be used without scope id being set properly. NsdService should set the Inet6Address scopes everywhere NsdServiceInfo.setHost or NsdServiceInfo.setHostAddresses is used. Test: atest CtsNetTestCases:android.net.cts.NsdManagerTest Bug: 273391977 Change-Id: I45da6aebeba4e2e398e0b58ce3b88470fb60863b --- .../src/com/android/server/NsdService.java | 64 ++++++++++--------- .../net/src/android/net/cts/NsdManagerTest.kt | 19 ++++++ 2 files changed, 52 insertions(+), 31 deletions(-) diff --git a/service-t/src/com/android/server/NsdService.java b/service-t/src/com/android/server/NsdService.java index cbe6691d8c..c00f1aefcb 100644 --- a/service-t/src/com/android/server/NsdService.java +++ b/service-t/src/com/android/server/NsdService.java @@ -72,6 +72,7 @@ import com.android.server.connectivity.mdns.MdnsSocketProvider; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.net.Inet6Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; @@ -1155,22 +1156,7 @@ public class NsdService extends INsdManager.Stub { Log.e(TAG, "Invalid attribute", e); } } - final List addresses = new ArrayList<>(); - for (String ipv4Address : serviceInfo.getIpv4Addresses()) { - try { - addresses.add(InetAddresses.parseNumericAddress(ipv4Address)); - } catch (IllegalArgumentException e) { - Log.wtf(TAG, "Invalid ipv4 address", e); - } - } - for (String ipv6Address : serviceInfo.getIpv6Addresses()) { - try { - addresses.add(InetAddresses.parseNumericAddress(ipv6Address)); - } catch (IllegalArgumentException e) { - Log.wtf(TAG, "Invalid ipv6 address", e); - } - } - + final List addresses = getInetAddresses(serviceInfo); if (addresses.size() != 0) { info.setHostAddresses(addresses); clientInfo.onResolveServiceSucceeded(clientId, info); @@ -1202,21 +1188,7 @@ public class NsdService extends INsdManager.Stub { } } - final List addresses = new ArrayList<>(); - for (String ipv4Address : serviceInfo.getIpv4Addresses()) { - try { - addresses.add(InetAddresses.parseNumericAddress(ipv4Address)); - } catch (IllegalArgumentException e) { - Log.wtf(TAG, "Invalid ipv4 address", e); - } - } - for (String ipv6Address : serviceInfo.getIpv6Addresses()) { - try { - addresses.add(InetAddresses.parseNumericAddress(ipv6Address)); - } catch (IllegalArgumentException e) { - Log.wtf(TAG, "Invalid ipv6 address", e); - } - } + final List addresses = getInetAddresses(serviceInfo); info.setHostAddresses(addresses); clientInfo.onServiceUpdated(clientId, info); break; @@ -1232,6 +1204,36 @@ public class NsdService extends INsdManager.Stub { } } + @NonNull + private static List getInetAddresses(@NonNull MdnsServiceInfo serviceInfo) { + final List v4Addrs = serviceInfo.getIpv4Addresses(); + final List v6Addrs = serviceInfo.getIpv6Addresses(); + final List addresses = new ArrayList<>(v4Addrs.size() + v6Addrs.size()); + for (String ipv4Address : v4Addrs) { + try { + addresses.add(InetAddresses.parseNumericAddress(ipv4Address)); + } catch (IllegalArgumentException e) { + Log.wtf(TAG, "Invalid ipv4 address", e); + } + } + for (String ipv6Address : v6Addrs) { + try { + final InetAddress addr = InetAddresses.parseNumericAddress(ipv6Address); + if (addr.isLinkLocalAddress()) { + final Inet6Address v6Addr = Inet6Address.getByAddress( + null /* host */, addr.getAddress(), + serviceInfo.getInterfaceIndex()); + addresses.add(v6Addr); + } else { + addresses.add(addr); + } + } catch (IllegalArgumentException | UnknownHostException e) { + Log.wtf(TAG, "Invalid ipv6 address", e); + } + } + return addresses; + } + private static void setServiceNetworkForCallback(NsdServiceInfo info, int netId, int ifaceIdx) { switch (netId) { case NETID_UNSET: diff --git a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt index db4f937f04..da0341a073 100644 --- a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt +++ b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt @@ -96,6 +96,8 @@ import com.android.testutils.tryTest import com.android.testutils.waitForIdle import java.io.File import java.io.IOException +import java.net.Inet6Address +import java.net.InetAddress import java.net.NetworkInterface import java.net.ServerSocket import java.nio.charset.StandardCharsets @@ -132,6 +134,7 @@ private val nsdShim = NsdShimImpl.newInstance() @AppModeFull(reason = "Socket cannot bind in instant app mode") @RunWith(AndroidJUnit4::class) +@ConnectivityModuleTest class NsdManagerTest { // Rule used to filter CtsNetTestCasesMaxTargetSdkXX @get:Rule @@ -696,6 +699,20 @@ class NsdManagerTest { } } + private fun checkAddressScopeId(iface: TestNetworkInterface, address: List) { + val targetSdkVersion = context.packageManager + .getTargetSdkVersion(context.applicationInfo.packageName) + if (targetSdkVersion <= Build.VERSION_CODES.TIRAMISU) { + return + } + val ifaceIdx = NetworkInterface.getByName(iface.interfaceName).index + address.forEach { + if (it is Inet6Address && it.isLinkLocalAddress) { + assertEquals(ifaceIdx, it.scopeId) + } + } + } + @Test fun testNsdManager_ResolveOnNetwork() { // This test requires shims supporting T+ APIs (NsdServiceInfo.network) @@ -731,6 +748,7 @@ class NsdManagerTest { assertEquals(registeredInfo.serviceName, it.serviceName) assertEquals(si.port, it.port) assertEquals(testNetwork1.network, nsdShim.getNetwork(it)) + checkAddressScopeId(testNetwork1.iface, it.hostAddresses) } // TODO: check that MDNS packets are sent only on testNetwork1. } cleanupStep { @@ -970,6 +988,7 @@ class NsdManagerTest { for (hostAddress in hostAddresses) { assertTrue(addresses.contains(hostAddress)) } + checkAddressScopeId(testNetwork1.iface, serviceInfoCb.serviceInfo.hostAddresses) } cleanupStep { nsdManager.unregisterService(registrationRecord) registrationRecord.expectCallback()