Treat optimistic addresses as global preferred.
If the kernel sends notification of an optimistic address then
treat is a useable address (isGlobalPreferred()).
Note that addresses flagged as IFA_F_OPTIMISTIC are
simultaneously flagged as IFA_F_TENTATIVE (when the tentative
state has cleared either DAD has succeeded or failed, and both
flags are cleared regardless).
Additionally: do not consider RFC 4193 ULA addresses sufficient
for "global preffered". They are, by definition, of global scope
but not sufficient for global reachability.
Bug: 17769720
Change-Id: I759623b28fd52758f2d4d76d167f3cafd9319d6a
diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java
index c387055..384ab1c 100644
--- a/core/java/android/net/LinkAddress.java
+++ b/core/java/android/net/LinkAddress.java
@@ -21,12 +21,14 @@
import android.util.Pair;
import java.net.Inet4Address;
+import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.UnknownHostException;
import static android.system.OsConstants.IFA_F_DADFAILED;
import static android.system.OsConstants.IFA_F_DEPRECATED;
+import static android.system.OsConstants.IFA_F_OPTIMISTIC;
import static android.system.OsConstants.IFA_F_TENTATIVE;
import static android.system.OsConstants.RT_SCOPE_HOST;
import static android.system.OsConstants.RT_SCOPE_LINK;
@@ -93,6 +95,20 @@
}
/**
+ * Utility function to check if |address| is a Unique Local IPv6 Unicast Address
+ * (a.k.a. "ULA"; RFC 4193).
+ *
+ * Per RFC 4193 section 8, fc00::/7 identifies these addresses.
+ */
+ private boolean isIPv6ULA() {
+ if (address != null && address instanceof Inet6Address) {
+ byte[] bytes = address.getAddress();
+ return ((bytes[0] & (byte)0xfc) == (byte)0xfc);
+ }
+ return false;
+ }
+
+ /**
* Utility function for the constructors.
*/
private void init(InetAddress address, int prefixLength, int flags, int scope) {
@@ -268,8 +284,16 @@
* @hide
*/
public boolean isGlobalPreferred() {
+ /**
+ * Note that addresses flagged as IFA_F_OPTIMISTIC are
+ * simultaneously flagged as IFA_F_TENTATIVE (when the tentative
+ * state has cleared either DAD has succeeded or failed, and both
+ * flags are cleared regardless).
+ */
return (scope == RT_SCOPE_UNIVERSE &&
- (flags & (IFA_F_DADFAILED | IFA_F_DEPRECATED | IFA_F_TENTATIVE)) == 0L);
+ !isIPv6ULA() &&
+ (flags & (IFA_F_DADFAILED | IFA_F_DEPRECATED)) == 0L &&
+ ((flags & IFA_F_TENTATIVE) == 0L || (flags & IFA_F_OPTIMISTIC) != 0L));
}
/**