Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit befe778c authored by Erik Kline's avatar Erik Kline
Browse files

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
parent 8be95fdd
Loading
Loading
Loading
Loading
+25 −1
Original line number Original line Diff line number Diff line
@@ -21,12 +21,14 @@ import android.os.Parcelable;
import android.util.Pair;
import android.util.Pair;


import java.net.Inet4Address;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.InterfaceAddress;
import java.net.UnknownHostException;
import java.net.UnknownHostException;


import static android.system.OsConstants.IFA_F_DADFAILED;
import static android.system.OsConstants.IFA_F_DADFAILED;
import static android.system.OsConstants.IFA_F_DEPRECATED;
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.IFA_F_TENTATIVE;
import static android.system.OsConstants.RT_SCOPE_HOST;
import static android.system.OsConstants.RT_SCOPE_HOST;
import static android.system.OsConstants.RT_SCOPE_LINK;
import static android.system.OsConstants.RT_SCOPE_LINK;
@@ -92,6 +94,20 @@ public class LinkAddress implements Parcelable {
        return RT_SCOPE_UNIVERSE;
        return RT_SCOPE_UNIVERSE;
    }
    }


    /**
     * 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.
     * Utility function for the constructors.
     */
     */
@@ -268,8 +284,16 @@ public class LinkAddress implements Parcelable {
     * @hide
     * @hide
     */
     */
    public boolean isGlobalPreferred() {
    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 &&
        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));
    }
    }


    /**
    /**
+72 −0
Original line number Original line Diff line number Diff line
@@ -33,8 +33,11 @@ import android.test.AndroidTestCase;
import static android.test.MoreAsserts.assertNotEqual;
import static android.test.MoreAsserts.assertNotEqual;
import android.test.suitebuilder.annotation.SmallTest;
import android.test.suitebuilder.annotation.SmallTest;


import static android.system.OsConstants.IFA_F_DADFAILED;
import static android.system.OsConstants.IFA_F_DEPRECATED;
import static android.system.OsConstants.IFA_F_DEPRECATED;
import static android.system.OsConstants.IFA_F_OPTIMISTIC;
import static android.system.OsConstants.IFA_F_PERMANENT;
import static android.system.OsConstants.IFA_F_PERMANENT;
import static android.system.OsConstants.IFA_F_TEMPORARY;
import static android.system.OsConstants.IFA_F_TENTATIVE;
import static android.system.OsConstants.IFA_F_TENTATIVE;
import static android.system.OsConstants.RT_SCOPE_HOST;
import static android.system.OsConstants.RT_SCOPE_HOST;
import static android.system.OsConstants.RT_SCOPE_LINK;
import static android.system.OsConstants.RT_SCOPE_LINK;
@@ -340,4 +343,73 @@ public class LinkAddressTest extends AndroidTestCase {
        l = new LinkAddress(V4 + "/28", IFA_F_PERMANENT, RT_SCOPE_LINK);
        l = new LinkAddress(V4 + "/28", IFA_F_PERMANENT, RT_SCOPE_LINK);
        assertParcelingIsLossless(l);
        assertParcelingIsLossless(l);
    }
    }

    private void assertGlobalPreferred(LinkAddress l, String msg) {
        assertTrue(msg, l.isGlobalPreferred());
    }

    private void assertNotGlobalPreferred(LinkAddress l, String msg) {
        assertFalse(msg, l.isGlobalPreferred());
    }

    public void testIsGlobalPreferred() {
        LinkAddress l;

        l = new LinkAddress(V4_ADDRESS, 32, 0, RT_SCOPE_UNIVERSE);
        assertGlobalPreferred(l, "v4,global,noflags");

        l = new LinkAddress("10.10.1.7/23", 0, RT_SCOPE_UNIVERSE);
        assertGlobalPreferred(l, "v4-rfc1918,global,noflags");

        l = new LinkAddress("10.10.1.7/23", 0, RT_SCOPE_SITE);
        assertNotGlobalPreferred(l, "v4-rfc1918,site-local,noflags");

        l = new LinkAddress("127.0.0.7/8", 0, RT_SCOPE_HOST);
        assertNotGlobalPreferred(l, "v4-localhost,node-local,noflags");

        l = new LinkAddress(V6_ADDRESS, 64, 0, RT_SCOPE_UNIVERSE);
        assertGlobalPreferred(l, "v6,global,noflags");

        l = new LinkAddress(V6_ADDRESS, 64, IFA_F_PERMANENT, RT_SCOPE_UNIVERSE);
        assertGlobalPreferred(l, "v6,global,permanent");

        // IPv6 ULAs are not acceptable "global preferred" addresses.
        l = new LinkAddress("fc12::1/64", 0, RT_SCOPE_UNIVERSE);
        assertNotGlobalPreferred(l, "v6,ula1,noflags");

        l = new LinkAddress("fd34::1/64", 0, RT_SCOPE_UNIVERSE);
        assertNotGlobalPreferred(l, "v6,ula2,noflags");

        l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_UNIVERSE);
        assertGlobalPreferred(l, "v6,global,tempaddr");

        l = new LinkAddress(V6_ADDRESS, 64, (IFA_F_TEMPORARY|IFA_F_DADFAILED),
                            RT_SCOPE_UNIVERSE);
        assertNotGlobalPreferred(l, "v6,global,tempaddr+dadfailed");

        l = new LinkAddress(V6_ADDRESS, 64, (IFA_F_TEMPORARY|IFA_F_DEPRECATED),
                            RT_SCOPE_UNIVERSE);
        assertNotGlobalPreferred(l, "v6,global,tempaddr+deprecated");

        l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_SITE);
        assertNotGlobalPreferred(l, "v6,site-local,tempaddr");

        l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_LINK);
        assertNotGlobalPreferred(l, "v6,link-local,tempaddr");

        l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_HOST);
        assertNotGlobalPreferred(l, "v6,node-local,tempaddr");

        l = new LinkAddress("::1/128", IFA_F_PERMANENT, RT_SCOPE_HOST);
        assertNotGlobalPreferred(l, "v6-localhost,node-local,permanent");

        l = new LinkAddress(V6_ADDRESS, 64, (IFA_F_TEMPORARY|IFA_F_TENTATIVE),
                            RT_SCOPE_UNIVERSE);
        assertNotGlobalPreferred(l, "v6,global,tempaddr+tentative");

        l = new LinkAddress(V6_ADDRESS, 64,
                            (IFA_F_TEMPORARY|IFA_F_TENTATIVE|IFA_F_OPTIMISTIC),
                            RT_SCOPE_UNIVERSE);
        assertGlobalPreferred(l, "v6,global,tempaddr+optimistic");
    }
}
}