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

Commit f705ea69 authored by Remi NGUYEN VAN's avatar Remi NGUYEN VAN
Browse files

Fix parceling of LinkProperties Inet6Addr

IPv6 addresses parceled for DNS servers, private DNS servers, PCSCF
servers were parceled without the scope. This causes issues with
link-local DNS servers.

Test: atest FrameworksNetTests
Bug: 145181158
Change-Id: I0ed24e51d4d0656f4a1f932b5e9f646b35b4b971
parent ea1b85a5
Loading
Loading
Loading
Loading
+37 −16
Original line number Diff line number Diff line
@@ -74,6 +74,8 @@ public final class LinkProperties implements Parcelable {
    private static final int MIN_MTU_V6 = 1280;
    private static final int MAX_MTU    = 10000;

    private static final int INET6_ADDR_LENGTH = 16;

    // Stores the properties of links that are "stacked" above this link.
    // Indexed by interface name to allow modification and to prevent duplicates being added.
    private Hashtable<String, LinkProperties> mStackedLinks = new Hashtable<>();
@@ -1626,20 +1628,11 @@ public final class LinkProperties implements Parcelable {
            dest.writeParcelable(linkAddress, flags);
        }

        dest.writeInt(mDnses.size());
        for (InetAddress d : mDnses) {
            dest.writeByteArray(d.getAddress());
        }
        dest.writeInt(mValidatedPrivateDnses.size());
        for (InetAddress d : mValidatedPrivateDnses) {
            dest.writeByteArray(d.getAddress());
        }
        writeAddresses(dest, mDnses);
        writeAddresses(dest, mValidatedPrivateDnses);
        dest.writeBoolean(mUsePrivateDns);
        dest.writeString(mPrivateDnsServerName);
        dest.writeInt(mPcscfs.size());
        for (InetAddress d : mPcscfs) {
            dest.writeByteArray(d.getAddress());
        }
        writeAddresses(dest, mPcscfs);
        dest.writeString(mDomains);
        dest.writeInt(mMtu);
        dest.writeString(mTcpBufferSizes);
@@ -1662,6 +1655,35 @@ public final class LinkProperties implements Parcelable {
        dest.writeBoolean(mWakeOnLanSupported);
    }

    private static void writeAddresses(@NonNull Parcel dest, @NonNull List<InetAddress> list) {
        dest.writeInt(list.size());
        for (InetAddress d : list) {
            writeAddress(dest, d);
        }
    }

    private static void writeAddress(@NonNull Parcel dest, @NonNull InetAddress addr) {
        dest.writeByteArray(addr.getAddress());
        if (addr instanceof Inet6Address) {
            final Inet6Address v6Addr = (Inet6Address) addr;
            final boolean hasScopeId = v6Addr.getScopeId() != 0;
            dest.writeBoolean(hasScopeId);
            if (hasScopeId) dest.writeInt(v6Addr.getScopeId());
        }
    }

    @NonNull
    private static InetAddress readAddress(@NonNull Parcel p) throws UnknownHostException {
        final byte[] addr = p.createByteArray();
        if (addr.length == INET6_ADDR_LENGTH) {
            final boolean hasScopeId = p.readBoolean();
            final int scopeId = hasScopeId ? p.readInt() : 0;
            return Inet6Address.getByAddress(null /* host */, addr, scopeId);
        }

        return InetAddress.getByAddress(addr);
    }

    /**
     * Implement the Parcelable interface.
     */
@@ -1681,14 +1703,13 @@ public final class LinkProperties implements Parcelable {
                addressCount = in.readInt();
                for (int i = 0; i < addressCount; i++) {
                    try {
                        netProp.addDnsServer(InetAddress.getByAddress(in.createByteArray()));
                        netProp.addDnsServer(readAddress(in));
                    } catch (UnknownHostException e) { }
                }
                addressCount = in.readInt();
                for (int i = 0; i < addressCount; i++) {
                    try {
                        netProp.addValidatedPrivateDnsServer(
                                InetAddress.getByAddress(in.createByteArray()));
                        netProp.addValidatedPrivateDnsServer(readAddress(in));
                    } catch (UnknownHostException e) { }
                }
                netProp.setUsePrivateDns(in.readBoolean());
@@ -1696,7 +1717,7 @@ public final class LinkProperties implements Parcelable {
                addressCount = in.readInt();
                for (int i = 0; i < addressCount; i++) {
                    try {
                        netProp.addPcscfServer(InetAddress.getByAddress(in.createByteArray()));
                        netProp.addPcscfServer(readAddress(in));
                    } catch (UnknownHostException e) { }
                }
                netProp.setDomains(in.readString());
+70 −43
Original line number Diff line number Diff line
@@ -16,7 +16,9 @@

package android.net;

import static com.android.testutils.ParcelUtilsKt.assertParcelSane;
import static com.android.testutils.ParcelUtilsKt.assertParcelingIsLossless;
import static com.android.testutils.ParcelUtilsKt.parcelingRoundTrip;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -47,25 +49,22 @@ import java.util.Set;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class LinkPropertiesTest {
    private static final InetAddress ADDRV4 = InetAddresses.parseNumericAddress("75.208.6.1");
    private static final InetAddress ADDRV6 = InetAddresses.parseNumericAddress(
            "2001:0db8:85a3:0000:0000:8a2e:0370:7334");
    private static final InetAddress DNS1 = InetAddresses.parseNumericAddress("75.208.7.1");
    private static final InetAddress DNS2 = InetAddresses.parseNumericAddress("69.78.7.1");
    private static final InetAddress DNS6 = InetAddresses.parseNumericAddress(
            "2001:4860:4860::8888");
    private static final InetAddress PRIVDNS1 = InetAddresses.parseNumericAddress("1.1.1.1");
    private static final InetAddress PRIVDNS2 = InetAddresses.parseNumericAddress("1.0.0.1");
    private static final InetAddress PRIVDNS6 = InetAddresses.parseNumericAddress(
            "2606:4700:4700::1111");
    private static final InetAddress PCSCFV4 = InetAddresses.parseNumericAddress("10.77.25.37");
    private static final InetAddress PCSCFV6 = InetAddresses.parseNumericAddress(
            "2001:0db8:85a3:0000:0000:8a2e:0370:1");
    private static final InetAddress GATEWAY1 = InetAddresses.parseNumericAddress("75.208.8.1");
    private static final InetAddress GATEWAY2 = InetAddresses.parseNumericAddress("69.78.8.1");
    private static final InetAddress GATEWAY61 = InetAddresses.parseNumericAddress(
            "fe80::6:0000:613");
    private static final InetAddress GATEWAY62 = InetAddresses.parseNumericAddress("fe80::6:2222");
    private static final InetAddress ADDRV4 = address("75.208.6.1");
    private static final InetAddress ADDRV6 = address("2001:0db8:85a3:0000:0000:8a2e:0370:7334");
    private static final InetAddress DNS1 = address("75.208.7.1");
    private static final InetAddress DNS2 = address("69.78.7.1");
    private static final InetAddress DNS6 = address("2001:4860:4860::8888");
    private static final InetAddress PRIVDNS1 = address("1.1.1.1");
    private static final InetAddress PRIVDNS2 = address("1.0.0.1");
    private static final InetAddress PRIVDNS6 = address("2606:4700:4700::1111");
    private static final InetAddress PCSCFV4 = address("10.77.25.37");
    private static final InetAddress PCSCFV6 = address("2001:0db8:85a3:0000:0000:8a2e:0370:1");
    private static final InetAddress GATEWAY1 = address("75.208.8.1");
    private static final InetAddress GATEWAY2 = address("69.78.8.1");
    private static final InetAddress GATEWAY61 = address("fe80::6:0000:613");
    private static final InetAddress GATEWAY62 = address("fe80::6:22%lo");
    private static final InetAddress TESTIPV4ADDR = address("192.168.47.42");
    private static final InetAddress TESTIPV6ADDR = address("fe80::7:33%43");
    private static final String NAME = "qmi0";
    private static final String DOMAINS = "google.com";
    private static final String PRIV_DNS_SERVER_NAME = "private.dns.com";
@@ -75,8 +74,7 @@ public class LinkPropertiesTest {
    private static final LinkAddress LINKADDRV6 = new LinkAddress(ADDRV6, 128);
    private static final LinkAddress LINKADDRV6LINKLOCAL = new LinkAddress("fe80::1/64");

    // TODO: replace all calls to NetworkUtils.numericToInetAddress with calls to this method.
    private InetAddress Address(String addrString) {
    private static InetAddress address(String addrString) {
        return InetAddresses.parseNumericAddress(addrString);
    }

@@ -228,7 +226,7 @@ public class LinkPropertiesTest {
        target.clear();
        target.setInterfaceName(NAME);
        // change link addresses
        target.addLinkAddress(new LinkAddress(Address("75.208.6.2"), 32));
        target.addLinkAddress(new LinkAddress(address("75.208.6.2"), 32));
        target.addLinkAddress(LINKADDRV6);
        target.addDnsServer(DNS1);
        target.addDnsServer(DNS2);
@@ -243,7 +241,7 @@ public class LinkPropertiesTest {
        target.addLinkAddress(LINKADDRV4);
        target.addLinkAddress(LINKADDRV6);
        // change dnses
        target.addDnsServer(Address("75.208.7.2"));
        target.addDnsServer(address("75.208.7.2"));
        target.addDnsServer(DNS2);
        target.addPcscfServer(PCSCFV6);
        target.addRoute(new RouteInfo(GATEWAY1));
@@ -255,10 +253,10 @@ public class LinkPropertiesTest {
        target.setInterfaceName(NAME);
        target.addLinkAddress(LINKADDRV4);
        target.addLinkAddress(LINKADDRV6);
        target.addDnsServer(Address("75.208.7.2"));
        target.addDnsServer(address("75.208.7.2"));
        target.addDnsServer(DNS2);
        // change pcscf
        target.addPcscfServer(Address("2001::1"));
        target.addPcscfServer(address("2001::1"));
        target.addRoute(new RouteInfo(GATEWAY1));
        target.addRoute(new RouteInfo(GATEWAY2));
        target.setMtu(MTU);
@@ -271,9 +269,9 @@ public class LinkPropertiesTest {
        target.addDnsServer(DNS1);
        target.addDnsServer(DNS2);
        // change gateway
        target.addRoute(new RouteInfo(Address("75.208.8.2")));
        target.addRoute(new RouteInfo(GATEWAY2));
        target.addRoute(new RouteInfo(address("75.208.8.2")));
        target.setMtu(MTU);
        target.addRoute(new RouteInfo(GATEWAY2));
        assertFalse(source.equals(target));

        target.clear();
@@ -349,7 +347,7 @@ public class LinkPropertiesTest {

    @Test
    public void testRouteInterfaces() {
        LinkAddress prefix = new LinkAddress(Address("2001:db8::"), 32);
        LinkAddress prefix = new LinkAddress(address("2001:db8::"), 32);
        InetAddress address = ADDRV6;

        // Add a route with no interface to a LinkProperties with no interface. No errors.
@@ -739,8 +737,7 @@ public class LinkPropertiesTest {

        // Add an on-link route, making the on-link DNS server reachable,
        // but there is still no IPv4 address.
        assertTrue(v4lp.addRoute(new RouteInfo(
                new IpPrefix(NetworkUtils.numericToInetAddress("75.208.0.0"), 16))));
        assertTrue(v4lp.addRoute(new RouteInfo(new IpPrefix(address("75.208.0.0"), 16))));
        assertFalse(v4lp.isReachable(DNS1));
        assertFalse(v4lp.isReachable(DNS2));

@@ -756,9 +753,9 @@ public class LinkPropertiesTest {
        assertTrue(v4lp.isReachable(DNS2));

        final LinkProperties v6lp = new LinkProperties();
        final InetAddress kLinkLocalDns = Address("fe80::6:1");
        final InetAddress kLinkLocalDnsWithScope = Address("fe80::6:2%43");
        final InetAddress kOnLinkDns = Address("2001:db8:85a3::53");
        final InetAddress kLinkLocalDns = address("fe80::6:1");
        final InetAddress kLinkLocalDnsWithScope = address("fe80::6:2%43");
        final InetAddress kOnLinkDns = address("2001:db8:85a3::53");
        assertFalse(v6lp.isReachable(kLinkLocalDns));
        assertFalse(v6lp.isReachable(kLinkLocalDnsWithScope));
        assertFalse(v6lp.isReachable(kOnLinkDns));
@@ -767,7 +764,7 @@ public class LinkPropertiesTest {
        // Add a link-local route, making the link-local DNS servers reachable. Because
        // we assume the presence of an IPv6 link-local address, link-local DNS servers
        // are considered reachable, but only those with a non-zero scope identifier.
        assertTrue(v6lp.addRoute(new RouteInfo(new IpPrefix(Address("fe80::"), 64))));
        assertTrue(v6lp.addRoute(new RouteInfo(new IpPrefix(address("fe80::"), 64))));
        assertFalse(v6lp.isReachable(kLinkLocalDns));
        assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
        assertFalse(v6lp.isReachable(kOnLinkDns));
@@ -783,7 +780,7 @@ public class LinkPropertiesTest {
        // Add a global route on link, but no global address yet. DNS servers reachable
        // via a route that doesn't require a gateway: give them the benefit of the
        // doubt and hope the link-local source address suffices for communication.
        assertTrue(v6lp.addRoute(new RouteInfo(new IpPrefix(Address("2001:db8:85a3::"), 64))));
        assertTrue(v6lp.addRoute(new RouteInfo(new IpPrefix(address("2001:db8:85a3::"), 64))));
        assertFalse(v6lp.isReachable(kLinkLocalDns));
        assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
        assertTrue(v6lp.isReachable(kOnLinkDns));
@@ -812,7 +809,7 @@ public class LinkPropertiesTest {
        stacked.setInterfaceName("v4-test0");
        v6lp.addStackedLink(stacked);

        InetAddress stackedAddress = Address("192.0.0.4");
        InetAddress stackedAddress = address("192.0.0.4");
        LinkAddress stackedLinkAddress = new LinkAddress(stackedAddress, 32);
        assertFalse(v6lp.isReachable(stackedAddress));
        stacked.addLinkAddress(stackedLinkAddress);
@@ -845,7 +842,7 @@ public class LinkPropertiesTest {
        LinkProperties rmnet1 = new LinkProperties();
        rmnet1.setInterfaceName("rmnet1");
        rmnet1.addLinkAddress(new LinkAddress("10.0.0.3/8"));
        RouteInfo defaultRoute1 = new RouteInfo((IpPrefix) null, Address("10.0.0.1"),
        RouteInfo defaultRoute1 = new RouteInfo((IpPrefix) null, address("10.0.0.1"),
                rmnet1.getInterfaceName());
        RouteInfo directRoute1 = new RouteInfo(new IpPrefix("10.0.0.0/8"), null,
                rmnet1.getInterfaceName());
@@ -864,7 +861,7 @@ public class LinkPropertiesTest {
        rmnet2.setInterfaceName("rmnet2");
        rmnet2.addLinkAddress(new LinkAddress("fe80::cafe/64"));
        rmnet2.addLinkAddress(new LinkAddress("2001:db8::2/64"));
        RouteInfo defaultRoute2 = new RouteInfo((IpPrefix) null, Address("2001:db8::1"),
        RouteInfo defaultRoute2 = new RouteInfo((IpPrefix) null, address("2001:db8::1"),
                rmnet2.getInterfaceName());
        RouteInfo directRoute2 = new RouteInfo(new IpPrefix("2001:db8::/64"), null,
                rmnet2.getInterfaceName());
@@ -930,24 +927,54 @@ public class LinkPropertiesTest {
    public void testLinkPropertiesParcelable() throws Exception {
        LinkProperties source = new LinkProperties();
        source.setInterfaceName(NAME);
        // set 2 link addresses

        source.addLinkAddress(LINKADDRV4);
        source.addLinkAddress(LINKADDRV6);
        // set 2 dnses

        source.addDnsServer(DNS1);
        source.addDnsServer(DNS2);
        // set 2 gateways
        source.addDnsServer(GATEWAY62);

        source.addPcscfServer(TESTIPV4ADDR);
        source.addPcscfServer(TESTIPV6ADDR);

        source.setUsePrivateDns(true);
        source.setPrivateDnsServerName(PRIV_DNS_SERVER_NAME);

        source.setDomains(DOMAINS);

        source.addRoute(new RouteInfo(GATEWAY1));
        source.addRoute(new RouteInfo(GATEWAY2));
        // set 2 validated private dnses

        source.addValidatedPrivateDnsServer(DNS6);
        source.addValidatedPrivateDnsServer(GATEWAY61);
        source.addValidatedPrivateDnsServer(TESTIPV6ADDR);

        source.setHttpProxy(ProxyInfo.buildDirectProxy("test", 8888));

        source.setMtu(MTU);

        source.setTcpBufferSizes(TCP_BUFFER_SIZES);

        source.setNat64Prefix(new IpPrefix("2001:db8:1:2:64:64::/96"));

        assertParcelingIsLossless(source);
        source.setWakeOnLanSupported(true);

        final LinkProperties stacked = new LinkProperties();
        stacked.setInterfaceName("test-stacked");
        source.addStackedLink(stacked);

        assertParcelSane(source, 15 /* fieldCount */);
    }

    @Test
    public void testLinkLocalDnsServerParceling() throws Exception {
        final String strAddress = "fe80::1%lo";
        final LinkProperties lp = new LinkProperties();
        lp.addDnsServer(address(strAddress));
        final LinkProperties unparceled = parcelingRoundTrip(lp);
        // Inet6Address#equals does not test for the scope id
        assertEquals(strAddress, unparceled.getDnsServers().get(0).getHostAddress());
    }

    @Test