Snap for 11878282 from c6f55b854420d47feac461d4ace44dd398d061c1 to sdk-release
Change-Id: I31fec266987aaf381f0c62fd8fd4b4912a707979
diff --git a/src/android/net/apf/ProcfsParsingUtils.java b/src/android/net/apf/ProcfsParsingUtils.java
index 17116bb..4bac0f8 100644
--- a/src/android/net/apf/ProcfsParsingUtils.java
+++ b/src/android/net/apf/ProcfsParsingUtils.java
@@ -15,6 +15,8 @@
*/
package android.net.apf;
+import android.annotation.NonNull;
+import android.net.MacAddress;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -36,6 +38,8 @@
private static final String IPV6_CONF_PATH = "/proc/sys/net/ipv6/conf/";
private static final String IPV6_ANYCAST_PATH = "/proc/net/anycast6";
+ private static final String ETHER_MCAST_PATH = "/proc/net/dev_mcast";
+ private static final String IPV6_MCAST_PATH = "/proc/net/igmp6";
private ProcfsParsingUtils() {
}
@@ -81,7 +85,7 @@
}
/**
- * Parses an anycast6 address associated with a specific interface from a list of strings.
+ * Parses anycast6 addresses associated with a specific interface from a list of strings.
*
* This function searches the input list for a line containing the specified interface name.
* If found, it extracts the IPv6 address from that line and
@@ -90,32 +94,85 @@
* @param lines A list of strings where each line is expected to contain
* interface and address information.
* @param ifname The name of the network interface to search for.
- * @return The parsed `Inet6Address` representing the anycast address
- * associated with the specified interface,
- * or `null` if no matching line is found or if an error occurs during parsing.
+ * @return A list of The `Inet6Address` representing the anycast address
+ * associated with the specified interface,
+ * If an error occurs during parsing, an empty list is returned.
*/
@VisibleForTesting
- public static Inet6Address parseAnycast6Address(final List<String> lines, final String ifname) {
+ public static List<Inet6Address> parseAnycast6Addresses(
+ @NonNull List<String> lines, @NonNull String ifname) {
+ final List<Inet6Address> addresses = new ArrayList<>();
try {
for (String line : lines) {
- if (!line.contains(ifname)) {
+ final String[] fields = line.split("\\s+");
+ if (!fields[1].equals(ifname)) {
continue;
}
- // If there's multiple anycast addresses, only the first one will be returned.
- // It only has one anycast address per interface for clat.
- final String[] fields = line.split(" ");
final byte[] addr = HexDump.hexStringToByteArray(fields[2]);
- return (Inet6Address) InetAddress.getByAddress(addr);
+ addresses.add((Inet6Address) InetAddress.getByAddress(addr));
}
} catch (UnknownHostException e) {
Log.wtf("failed to convert to Inet6Address.", e);
- return null;
+ addresses.clear();
}
- return null;
+ return addresses;
}
/**
+ * Parses Ethernet multicast MAC addresses with a specific interface from a list of strings.
+ *
+ * @param lines A list of strings, each containing interface and MAC address information.
+ * @param ifname The name of the network interface for which to extract multicast addresses.
+ * @return A list of MacAddress objects representing the parsed multicast addresses.
+ */
+ @VisibleForTesting
+ public static List<MacAddress> parseEtherMulticastAddresses(
+ @NonNull List<String> lines, @NonNull String ifname) {
+ final List<MacAddress> addresses = new ArrayList<>();
+ for (String line: lines) {
+ final String[] fields = line.split("\\s+");
+ if (!fields[1].equals(ifname)) {
+ continue;
+ }
+
+ final byte[] addr = HexDump.hexStringToByteArray(fields[4]);
+ addresses.add(MacAddress.fromBytes(addr));
+ }
+
+ return addresses;
+ }
+
+ /**
+ * Parses IPv6 multicast addresses associated with a specific interface from a list of strings.
+ *
+ * @param lines A list of strings, each containing interface and IPv6 address information.
+ * @param ifname The name of the network interface for which to extract multicast addresses.
+ * @return A list of Inet6Address objects representing the parsed IPv6 multicast addresses.
+ * If an error occurs during parsing, an empty list is returned.
+ */
+ @VisibleForTesting
+ public static List<Inet6Address> parseIPv6MulticastAddresses(
+ @NonNull List<String> lines, @NonNull String ifname) {
+ final List<Inet6Address> addresses = new ArrayList<>();
+ try {
+ for (String line: lines) {
+ final String[] fields = line.split("\\s+");
+ if (!fields[1].equals(ifname)) {
+ continue;
+ }
+
+ final byte[] addr = HexDump.hexStringToByteArray(fields[2]);
+ addresses.add((Inet6Address) InetAddress.getByAddress(addr));
+ }
+ } catch (UnknownHostException e) {
+ Log.wtf(TAG, "failed to convert to Inet6Address.", e);
+ addresses.clear();
+ }
+
+ return addresses;
+ }
+ /**
* Returns the traffic class for the specified interface.
* The function loads the existing traffic class from the file
* `/proc/sys/net/ipv6/conf/{ifname}/ndisc_tclass`. If the file does not exist, the
@@ -133,13 +190,42 @@
/**
* The function loads the existing IPv6 anycast address from the file `/proc/net/anycast6`.
* If the file does not exist or the interface is not found, the function
- * returns null.
+ * returns an empty list.
*
* @param ifname The name of the interface.
- * @return The IPv6 anycast address for the interface.
+ * @return A list of the IPv6 anycast addresses for the interface.
*/
- public static Inet6Address getAnycast6Address(final String ifname) {
+ public static List<Inet6Address> getAnycast6Addresses(@NonNull String ifname) {
final List<String> lines = readFile(IPV6_ANYCAST_PATH);
- return parseAnycast6Address(lines, ifname);
+ return parseAnycast6Addresses(lines, ifname);
+ }
+
+ /**
+ * The function loads the existing Ethernet multicast addresses from
+ * the file `/proc/net/dev_mcast`.
+ * If the file does not exist or the interface is not found, the function returns empty list.
+ *
+ * @param ifname The name of the interface.
+ * @return A list of MacAddress objects representing the multicast addresses
+ * found for the interface.
+ * If the file cannot be read or there are no addresses, an empty list is returned.
+ */
+ public static List<MacAddress> getEtherMulticastAddresses(@NonNull String ifname) {
+ final List<String> lines = readFile(ETHER_MCAST_PATH);
+ return parseEtherMulticastAddresses(lines, ifname);
+ }
+
+ /**
+ * The function loads the existing IPv6 multicast addresses from the file `/proc/net/igmp6`.
+ * If the file does not exist or the interface is not found, the function returns empty list.
+ *
+ * @param ifname The name of the network interface to query.
+ * @return A list of Inet6Address objects representing the IPv6 multicast addresses
+ * found for the interface.
+ * If the file cannot be read or there are no addresses, an empty list is returned.
+ */
+ public static List<Inet6Address> getIpv6MulticastAddresses(@NonNull String ifname) {
+ final List<String> lines = readFile(IPV6_MCAST_PATH);
+ return parseIPv6MulticastAddresses(lines, ifname);
}
}
diff --git a/tests/unit/src/com/android/networkstack/util/ProcfsParsingUtilsTest.kt b/tests/unit/src/com/android/networkstack/util/ProcfsParsingUtilsTest.kt
index 9936a3f..7f8cacb 100644
--- a/tests/unit/src/com/android/networkstack/util/ProcfsParsingUtilsTest.kt
+++ b/tests/unit/src/com/android/networkstack/util/ProcfsParsingUtilsTest.kt
@@ -15,6 +15,7 @@
*/
package com.android.networkstack.util
+import android.net.MacAddress
import android.net.apf.ProcfsParsingUtils
import androidx.test.filters.SmallTest
import com.android.internal.util.HexDump
@@ -40,17 +41,98 @@
fun testParseAnycast6Address() {
val inputString = listOf(
"41 eth0 2a0034e2abc1334591a733387s2e322e 2",
+ "42 wlan0 2a0012e2abcddee459123738456e134a 4",
"47 wlan0 2a0079e10abc15391ba735397a2e311f 1",
"48 wlan1 2a004591a733387s2e334e2abc13322e 3"
)
- val expectedResult = InetAddress.getByAddress(
- HexDump.hexStringToByteArray("2a0079e10abc15391ba735397a2e311f")
- ) as Inet6Address
+ val expectedResult = listOf(
+ InetAddress.getByAddress(
+ HexDump.hexStringToByteArray("2a0012e2abcddee459123738456e134a")
+ ) as Inet6Address,
+ InetAddress.getByAddress(
+ HexDump.hexStringToByteArray("2a0079e10abc15391ba735397a2e311f")
+ ) as Inet6Address
+ )
assertEquals(
expectedResult,
- ProcfsParsingUtils.parseAnycast6Address(inputString, "wlan0")
+ ProcfsParsingUtils.parseAnycast6Addresses(inputString, "wlan0")
+ )
+ }
+
+ @Test
+ fun testParseEtherMulticastAddress() {
+ val inputString = listOf(
+ "2 dummy0 1 0 333300000001",
+ "2 dummy0 1 0 01005e000001",
+ "3 ifb0 1 0 333300000001",
+ "4 ifb1 1 0 333300000001",
+ "7 gretap0 1 0 333300000001",
+ "8 erspan0 1 0 333300000001",
+ "47 wlan0 1 0 01005e000001",
+ "47 wlan0 1 0 333300000001",
+ "47 wlan0 1 0 3333ff8a3667",
+ "47 wlan0 1 0 3333ff59c632",
+ "47 wlan0 1 0 3333ff574870",
+ "48 wlan1 1 0 333300000001"
+ )
+
+ val expectedResult = listOf(
+ MacAddress.fromBytes(HexDump.hexStringToByteArray("01005e000001")),
+ MacAddress.fromBytes(HexDump.hexStringToByteArray("333300000001")),
+ MacAddress.fromBytes(HexDump.hexStringToByteArray("3333ff8a3667")),
+ MacAddress.fromBytes(HexDump.hexStringToByteArray("3333ff59c632")),
+ MacAddress.fromBytes(HexDump.hexStringToByteArray("3333ff574870"))
+ )
+
+ assertEquals(
+ expectedResult,
+ ProcfsParsingUtils.parseEtherMulticastAddresses(inputString, "wlan0")
+ )
+ }
+
+ @Test
+ fun testParseIpv6MulticastAddress() {
+ val inputString = listOf(
+ "44 umts_dummy ff020000000000000000000000000001 1 0000000C 0",
+ "44 umts_dummy ff010000000000000000000000000001 1 00000008 0",
+ "46 aware_nmi0 ff020000000000000000000000000001 1 00000008 0",
+ "46 aware_nmi0 ff010000000000000000000000000001 1 00000008 0",
+ "47 wlan0 ff0200000000000000000001ff574870 1 00000004 0",
+ "47 wlan0 ff0200000000000000000001ff59c632 1 00000004 0",
+ "47 wlan0 ff0200000000000000000001ff8a3667 2 00000004 0",
+ "47 wlan0 ff020000000000000000000000000001 1 0000000C 0",
+ "47 wlan0 ff010000000000000000000000000001 1 00000008 0",
+ "48 wlan1 ff020000000000000000000000000001 1 0000000C 0",
+ "48 wlan1 ff010000000000000000000000000001 1 00000008 0",
+ "49 radiotap0 ff020000000000000000000000000001 1 0000000C 0",
+ "49 radiotap0 ff010000000000000000000000000001 1 00000008 0",
+ "50 v4-wlan0 ff020000000000000000000000000001 1 0000000C 0",
+ "50 v4-wlan0 ff010000000000000000000000000001 1 00000008 0"
+ )
+
+ val expectedResult = listOf(
+ InetAddress.getByAddress(
+ HexDump.hexStringToByteArray("ff0200000000000000000001ff574870")
+ ) as Inet6Address,
+ InetAddress.getByAddress(
+ HexDump.hexStringToByteArray("ff0200000000000000000001ff59c632")
+ ) as Inet6Address,
+ InetAddress.getByAddress(
+ HexDump.hexStringToByteArray("ff0200000000000000000001ff8a3667")
+ ) as Inet6Address,
+ InetAddress.getByAddress(
+ HexDump.hexStringToByteArray("ff020000000000000000000000000001")
+ ) as Inet6Address,
+ InetAddress.getByAddress(
+ HexDump.hexStringToByteArray("ff010000000000000000000000000001")
+ ) as Inet6Address
+ )
+
+ assertEquals(
+ expectedResult,
+ ProcfsParsingUtils.parseIPv6MulticastAddresses(inputString, "wlan0")
)
}
}