Split tenative and non-tentative IPv6 addresses in ApfFilter
Bug: 337807604
Test: atest NetworkStackTests:android.net.apf.ApfNewTest
Change-Id: Iaab55f19c0c6eb768ceb2696875a877763ac0ca5
diff --git a/src/android/net/apf/ApfFilter.java b/src/android/net/apf/ApfFilter.java
index 8f221af..f8a925e 100644
--- a/src/android/net/apf/ApfFilter.java
+++ b/src/android/net/apf/ApfFilter.java
@@ -77,6 +77,7 @@
import static android.system.OsConstants.ETH_P_ARP;
import static android.system.OsConstants.ETH_P_IP;
import static android.system.OsConstants.ETH_P_IPV6;
+import static android.system.OsConstants.IFA_F_TENTATIVE;
import static android.system.OsConstants.IPPROTO_ICMPV6;
import static android.system.OsConstants.IPPROTO_TCP;
import static android.system.OsConstants.IPPROTO_UDP;
@@ -116,6 +117,7 @@
import android.text.format.DateUtils;
import android.util.ArraySet;
import android.util.Log;
+import android.util.Pair;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
@@ -336,10 +338,14 @@
@GuardedBy("this")
private int mIPv4PrefixLength;
- // Our IPv6 addresses
+ // Our IPv6 non-tentative addresses
@GuardedBy("this")
private Set<Inet6Address> mIPv6Addresses = new ArraySet<>();
+ // Our tentative IPv6 addresses
+ @GuardedBy("this")
+ private Set<Inet6Address> mIPv6TentativeAddresses = new ArraySet<>();
+
// Whether CLAT is enabled.
@GuardedBy("this")
private boolean mHasClat;
@@ -2509,19 +2515,28 @@
return ipv4Address;
}
- /** Retrieve the IPv6 LinkAddress list, otherwise return empty list. */
- private static Set<Inet6Address> retrieveIPv6LinkAddress(LinkProperties lp) {
- final Set<Inet6Address> ipv6Addresses = new ArraySet<>();
-
+ /** Retrieve the pair of IPv6 Inet6Address set, otherwise return pair with two empty set.
+ * The first element is a set containing tentative IPv6 addresses,
+ * the second element is a set containing non-tentative IPv6 addresses
+ * */
+ private static Pair<Set<Inet6Address>, Set<Inet6Address>>
+ retrieveIPv6LinkAddress(LinkProperties lp) {
+ final Set<Inet6Address> tentativeAddrs = new ArraySet<>();
+ final Set<Inet6Address> nonTentativeAddrs = new ArraySet<>();
for (LinkAddress address : lp.getLinkAddresses()) {
if (!(address.getAddress() instanceof Inet6Address)) {
continue;
}
- ipv6Addresses.add((Inet6Address) address.getAddress());
+ if ((address.getFlags() & IFA_F_TENTATIVE) == IFA_F_TENTATIVE) {
+ tentativeAddrs.add((Inet6Address) address.getAddress());
+ } else {
+ nonTentativeAddrs.add((Inet6Address) address.getAddress());
+ }
}
- return ipv6Addresses;
+
+ return new Pair<>(tentativeAddrs, nonTentativeAddrs);
}
public synchronized void setLinkProperties(LinkProperties lp) {
@@ -2529,17 +2544,20 @@
final LinkAddress ipv4Address = retrieveIPv4LinkAddress(lp);
final byte[] addr = (ipv4Address != null) ? ipv4Address.getAddress().getAddress() : null;
final int prefix = (ipv4Address != null) ? ipv4Address.getPrefixLength() : 0;
- final Set<Inet6Address> ipv6Addresses = retrieveIPv6LinkAddress(lp);
+ final Pair<Set<Inet6Address>, Set<Inet6Address>>
+ ipv6Addresses = retrieveIPv6LinkAddress(lp);
if ((prefix == mIPv4PrefixLength)
&& Arrays.equals(addr, mIPv4Address)
- && ipv6Addresses.equals(mIPv6Addresses)
+ && ipv6Addresses.first.equals(mIPv6TentativeAddresses)
+ && ipv6Addresses.second.equals(mIPv6Addresses)
) {
return;
}
mIPv4Address = addr;
mIPv4PrefixLength = prefix;
- mIPv6Addresses = ipv6Addresses;
+ mIPv6TentativeAddresses = ipv6Addresses.first;
+ mIPv6Addresses = ipv6Addresses.second;
installNewProgramLocked();
}
diff --git a/tests/unit/src/android/net/apf/ApfNewTest.kt b/tests/unit/src/android/net/apf/ApfNewTest.kt
index d7a2900..d271b2e 100644
--- a/tests/unit/src/android/net/apf/ApfNewTest.kt
+++ b/tests/unit/src/android/net/apf/ApfNewTest.kt
@@ -57,6 +57,7 @@
import android.net.ip.IpClient.IpClientCallbacksWrapper
import android.os.Build
import android.system.OsConstants.ARPHRD_ETHER
+import android.system.OsConstants.IFA_F_TENTATIVE
import androidx.test.filters.SmallTest
import com.android.net.module.util.HexDump
import com.android.net.module.util.InterfaceParams
@@ -139,6 +140,14 @@
intArrayOf(0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x01, 0, 0, 0x1b, 0x44, 0x55, 0x66, 0x77)
.map{ it.toByte() }.toByteArray()
)
+ private val hostIpv6TentativeAddresses = listOf(
+ // 2001::200:1a:1234:5678
+ intArrayOf(0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x02, 0, 0, 0x1a, 0x12, 0x34, 0x56, 0x78)
+ .map{ it.toByte() }.toByteArray(),
+ // 2001::100:1b:1234:5678
+ intArrayOf(0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x01, 0, 0, 0x1b, 0x12, 0x34, 0x56, 0x78)
+ .map{ it.toByte() }.toByteArray()
+ )
private val hostAnycast6Addresses = listOf(
// 2001::100:1b:aabb:ccdd
intArrayOf(0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x01, 0, 0, 0x1b, 0xaa, 0xbb, 0xcc, 0xdd)
@@ -2207,6 +2216,18 @@
// add the same IPv6 addresses, expect to have no apf program update
apfFilter.setLinkProperties(lp)
verify(ipClientCallback, times(4)).installPacketFilter(any())
+
+ // add more tentative IPv6 addresses, expect to have apf program update
+ for (addr in hostIpv6TentativeAddresses) {
+ lp.addLinkAddress(LinkAddress(InetAddress.getByAddress(addr), 64, IFA_F_TENTATIVE, 0))
+ }
+
+ apfFilter.setLinkProperties(lp)
+ verify(ipClientCallback, times(5)).installPacketFilter(any())
+
+ // add the same IPv6 addresses, expect to have no apf program update
+ apfFilter.setLinkProperties(lp)
+ verify(ipClientCallback, times(5)).installPacketFilter(any())
apfFilter.shutdown()
}