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

Commit 761198a0 authored by Remi NGUYEN VAN's avatar Remi NGUYEN VAN
Browse files

Add parceling for DhcpServingParams

Introduce a stable AIDL parcel class, DhcpServingParamsParcel, and
methods to convert to and from that class to DhcpServingParams.
This will be used to move DhcpServer to the NetworkStack app.

Test: atest FrameworksNetTests
Bug: b/112869080
Change-Id: I276b7affccb938059769c90a53f0f6beb26e6ede
parent 7ec9e684
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -825,6 +825,7 @@ aidl_interface {
    local_include_dir: "core/java",
    srcs: [
        "core/java/android/net/INetworkStackConnector.aidl",
        "core/java/android/net/dhcp/DhcpServingParamsParcel.aidl",
    ],
    api_dir: "aidl/networkstack",
}
+30 −0
Original line number Diff line number Diff line
/**
 *
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net.dhcp;

parcelable DhcpServingParamsParcel {
    int serverAddr;
    int serverAddrPrefixLength;
    int[] defaultRouters;
    int[] dnsServers;
    int[] excludedAddrs;
    long dhcpLeaseTimeSecs;
    int linkMtu;
    boolean metered;
}
+72 −36
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.net.dhcp;

import static android.net.NetworkUtils.getPrefixMaskAsInet4Address;
import static android.net.NetworkUtils.intToInet4AddressHTH;
import static android.net.dhcp.DhcpPacket.INFINITE_LEASE;
import static android.net.util.NetworkConstants.IPV4_MAX_MTU;
import static android.net.util.NetworkConstants.IPV4_MIN_MTU;
@@ -24,6 +25,7 @@ import static android.net.util.NetworkConstants.IPV4_MIN_MTU;
import static java.lang.Integer.toUnsignedLong;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.NetworkUtils;
@@ -103,6 +105,37 @@ public class DhcpServingParams {
        this.metered = metered;
    }

    /**
     * Create parameters from a stable AIDL-compatible parcel.
     */
    public static DhcpServingParams fromParcelableObject(@NonNull DhcpServingParamsParcel parcel)
            throws InvalidParameterException {
        final LinkAddress serverAddr = new LinkAddress(
                intToInet4AddressHTH(parcel.serverAddr),
                parcel.serverAddrPrefixLength);
        return new Builder()
                .setServerAddr(serverAddr)
                .setDefaultRouters(toInet4AddressSet(parcel.defaultRouters))
                .setDnsServers(toInet4AddressSet(parcel.dnsServers))
                .setExcludedAddrs(toInet4AddressSet(parcel.excludedAddrs))
                .setDhcpLeaseTimeSecs(parcel.dhcpLeaseTimeSecs)
                .setLinkMtu(parcel.linkMtu)
                .setMetered(parcel.metered)
                .build();
    }

    private static Set<Inet4Address> toInet4AddressSet(@Nullable int[] addrs) {
        if (addrs == null) {
            return new HashSet<>(0);
        }

        final HashSet<Inet4Address> res = new HashSet<>();
        for (int addr : addrs) {
            res.add(intToInet4AddressHTH(addr));
        }
        return res;
    }

    @NonNull
    public Inet4Address getServerInet4Addr() {
        return (Inet4Address) serverAddr.getAddress();
@@ -134,13 +167,13 @@ public class DhcpServingParams {
     * of the parameters.
     */
    public static class Builder {
        private LinkAddress serverAddr;
        private Set<Inet4Address> defaultRouters;
        private Set<Inet4Address> dnsServers;
        private Set<Inet4Address> excludedAddrs;
        private long dhcpLeaseTimeSecs;
        private int linkMtu = MTU_UNSET;
        private boolean metered;
        private LinkAddress mServerAddr;
        private Set<Inet4Address> mDefaultRouters;
        private Set<Inet4Address> mDnsServers;
        private Set<Inet4Address> mExcludedAddrs;
        private long mDhcpLeaseTimeSecs;
        private int mLinkMtu = MTU_UNSET;
        private boolean mMetered;

        /**
         * Set the server address and served prefix for the DHCP server.
@@ -148,7 +181,7 @@ public class DhcpServingParams {
         * <p>This parameter is required.
         */
        public Builder setServerAddr(@NonNull LinkAddress serverAddr) {
            this.serverAddr = serverAddr;
            this.mServerAddr = serverAddr;
            return this;
        }

@@ -159,7 +192,7 @@ public class DhcpServingParams {
         * always be set explicitly before building the {@link DhcpServingParams}.
         */
        public Builder setDefaultRouters(@NonNull Set<Inet4Address> defaultRouters) {
            this.defaultRouters = defaultRouters;
            this.mDefaultRouters = defaultRouters;
            return this;
        }

@@ -189,7 +222,7 @@ public class DhcpServingParams {
         * {@link DhcpServingParams}.
         */
        public Builder setDnsServers(@NonNull Set<Inet4Address> dnsServers) {
            this.dnsServers = dnsServers;
            this.mDnsServers = dnsServers;
            return this;
        }

@@ -219,7 +252,7 @@ public class DhcpServingParams {
         * and do not need to be set here.
         */
        public Builder setExcludedAddrs(@NonNull Set<Inet4Address> excludedAddrs) {
            this.excludedAddrs = excludedAddrs;
            this.mExcludedAddrs = excludedAddrs;
            return this;
        }

@@ -239,7 +272,7 @@ public class DhcpServingParams {
         * <p>This parameter is required.
         */
        public Builder setDhcpLeaseTimeSecs(long dhcpLeaseTimeSecs) {
            this.dhcpLeaseTimeSecs = dhcpLeaseTimeSecs;
            this.mDhcpLeaseTimeSecs = dhcpLeaseTimeSecs;
            return this;
        }

@@ -250,7 +283,7 @@ public class DhcpServingParams {
         * is optional and defaults to {@link #MTU_UNSET}.
         */
        public Builder setLinkMtu(int linkMtu) {
            this.linkMtu = linkMtu;
            this.mLinkMtu = linkMtu;
            return this;
        }

@@ -260,7 +293,7 @@ public class DhcpServingParams {
         * <p>If not set, the default value is false.
         */
        public Builder setMetered(boolean metered) {
            this.metered = metered;
            this.mMetered = metered;
            return this;
        }

@@ -274,54 +307,57 @@ public class DhcpServingParams {
         */
        @NonNull
        public DhcpServingParams build() throws InvalidParameterException {
            if (serverAddr == null) {
            if (mServerAddr == null) {
                throw new InvalidParameterException("Missing serverAddr");
            }
            if (defaultRouters == null) {
            if (mDefaultRouters == null) {
                throw new InvalidParameterException("Missing defaultRouters");
            }
            if (dnsServers == null) {
            if (mDnsServers == null) {
                // Empty set is OK, but enforce explicitly setting it
                throw new InvalidParameterException("Missing dnsServers");
            }
            if (dhcpLeaseTimeSecs <= 0 || dhcpLeaseTimeSecs > toUnsignedLong(INFINITE_LEASE)) {
                throw new InvalidParameterException("Invalid lease time: " + dhcpLeaseTimeSecs);
            if (mDhcpLeaseTimeSecs <= 0 || mDhcpLeaseTimeSecs > toUnsignedLong(INFINITE_LEASE)) {
                throw new InvalidParameterException("Invalid lease time: " + mDhcpLeaseTimeSecs);
            }
            if (linkMtu != MTU_UNSET && (linkMtu < IPV4_MIN_MTU || linkMtu > IPV4_MAX_MTU)) {
                throw new InvalidParameterException("Invalid link MTU: " + linkMtu);
            if (mLinkMtu != MTU_UNSET && (mLinkMtu < IPV4_MIN_MTU || mLinkMtu > IPV4_MAX_MTU)) {
                throw new InvalidParameterException("Invalid link MTU: " + mLinkMtu);
            }
            if (!serverAddr.isIPv4()) {
            if (!mServerAddr.isIPv4()) {
                throw new InvalidParameterException("serverAddr must be IPv4");
            }
            if (serverAddr.getPrefixLength() < MIN_PREFIX_LENGTH
                    || serverAddr.getPrefixLength() > MAX_PREFIX_LENGTH) {
            if (mServerAddr.getPrefixLength() < MIN_PREFIX_LENGTH
                    || mServerAddr.getPrefixLength() > MAX_PREFIX_LENGTH) {
                throw new InvalidParameterException("Prefix length is not in supported range");
            }

            final IpPrefix prefix = makeIpPrefix(serverAddr);
            for (Inet4Address addr : defaultRouters) {
            final IpPrefix prefix = makeIpPrefix(mServerAddr);
            for (Inet4Address addr : mDefaultRouters) {
                if (!prefix.contains(addr)) {
                    throw new InvalidParameterException(String.format(
                            "Default router %s is not in server prefix %s", addr, serverAddr));
                            "Default router %s is not in server prefix %s", addr, mServerAddr));
                }
            }

            final Set<Inet4Address> excl = new HashSet<>();
            if (excludedAddrs != null) {
                excl.addAll(excludedAddrs);
            if (mExcludedAddrs != null) {
                excl.addAll(mExcludedAddrs);
            }
            excl.add((Inet4Address) serverAddr.getAddress());
            excl.addAll(defaultRouters);
            excl.addAll(dnsServers);
            excl.add((Inet4Address) mServerAddr.getAddress());
            excl.addAll(mDefaultRouters);
            excl.addAll(mDnsServers);

            return new DhcpServingParams(serverAddr,
                    Collections.unmodifiableSet(new HashSet<>(defaultRouters)),
                    Collections.unmodifiableSet(new HashSet<>(dnsServers)),
            return new DhcpServingParams(mServerAddr,
                    Collections.unmodifiableSet(new HashSet<>(mDefaultRouters)),
                    Collections.unmodifiableSet(new HashSet<>(mDnsServers)),
                    Collections.unmodifiableSet(excl),
                    dhcpLeaseTimeSecs, linkMtu, metered);
                    mDhcpLeaseTimeSecs, mLinkMtu, mMetered);
        }
    }

    /**
     * Utility method to create an IpPrefix with the address and prefix length of a LinkAddress.
     */
    @NonNull
    static IpPrefix makeIpPrefix(@NonNull LinkAddress addr) {
        return new IpPrefix(addr.getAddress(), addr.getPrefixLength());
+172 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net.dhcp;

import static android.net.NetworkUtils.inet4AddressToIntHTH;

import android.annotation.NonNull;
import android.net.LinkAddress;

import com.google.android.collect.Sets;

import java.net.Inet4Address;
import java.util.Collection;
import java.util.Set;

/**
 * Subclass of {@link DhcpServingParamsParcel} with additional utility methods for building.
 *
 * <p>This utility class does not check for validity of the parameters: invalid parameters are
 * reported by the receiving module when unparceling the parcel.
 *
 * @see DhcpServingParams
 * @hide
 */
public class DhcpServingParamsParcelExt extends DhcpServingParamsParcel {
    public static final int MTU_UNSET = 0;

    /**
     * Set the server address and served prefix for the DHCP server.
     *
     * <p>This parameter is required.
     */
    public DhcpServingParamsParcelExt setServerAddr(@NonNull LinkAddress serverAddr) {
        this.serverAddr = inet4AddressToIntHTH((Inet4Address) serverAddr.getAddress());
        this.serverAddrPrefixLength = serverAddr.getPrefixLength();
        return this;
    }

    /**
     * Set the default routers to be advertised to DHCP clients.
     *
     * <p>Each router must be inside the served prefix. This may be an empty set, but it must
     * always be set explicitly.
     */
    public DhcpServingParamsParcelExt setDefaultRouters(@NonNull Set<Inet4Address> defaultRouters) {
        this.defaultRouters = toIntArray(defaultRouters);
        return this;
    }

    /**
     * Set the default routers to be advertised to DHCP clients.
     *
     * <p>Each router must be inside the served prefix. This may be an empty list of routers,
     * but it must always be set explicitly.
     */
    public DhcpServingParamsParcelExt setDefaultRouters(@NonNull Inet4Address... defaultRouters) {
        return setDefaultRouters(Sets.newArraySet(defaultRouters));
    }

    /**
     * Convenience method to build the parameters with no default router.
     *
     * <p>Equivalent to calling {@link #setDefaultRouters(Inet4Address...)} with no address.
     */
    public DhcpServingParamsParcelExt setNoDefaultRouter() {
        return setDefaultRouters();
    }

    /**
     * Set the DNS servers to be advertised to DHCP clients.
     *
     * <p>This may be an empty set, but it must always be set explicitly.
     */
    public DhcpServingParamsParcelExt setDnsServers(@NonNull Set<Inet4Address> dnsServers) {
        this.dnsServers = toIntArray(dnsServers);
        return this;
    }

    /**
     * Set the DNS servers to be advertised to DHCP clients.
     *
     * <p>This may be an empty list of servers, but it must always be set explicitly.
     */
    public DhcpServingParamsParcelExt setDnsServers(@NonNull Inet4Address... dnsServers) {
        return setDnsServers(Sets.newArraySet(dnsServers));
    }

    /**
     * Convenience method to build the parameters with no DNS server.
     *
     * <p>Equivalent to calling {@link #setDnsServers(Inet4Address...)} with no address.
     */
    public DhcpServingParamsParcelExt setNoDnsServer() {
        return setDnsServers();
    }

    /**
     * Set excluded addresses that the DHCP server is not allowed to assign to clients.
     *
     * <p>This parameter is optional. DNS servers and default routers are always excluded
     * and do not need to be set here.
     */
    public DhcpServingParamsParcelExt setExcludedAddrs(@NonNull Set<Inet4Address> excludedAddrs) {
        this.excludedAddrs = toIntArray(excludedAddrs);
        return this;
    }

    /**
     * Set excluded addresses that the DHCP server is not allowed to assign to clients.
     *
     * <p>This parameter is optional. DNS servers and default routers are always excluded
     * and do not need to be set here.
     */
    public DhcpServingParamsParcelExt setExcludedAddrs(@NonNull Inet4Address... excludedAddrs) {
        return setExcludedAddrs(Sets.newArraySet(excludedAddrs));
    }

    /**
     * Set the lease time for leases assigned by the DHCP server.
     *
     * <p>This parameter is required.
     */
    public DhcpServingParamsParcelExt setDhcpLeaseTimeSecs(long dhcpLeaseTimeSecs) {
        this.dhcpLeaseTimeSecs = dhcpLeaseTimeSecs;
        return this;
    }

    /**
     * Set the link MTU to be advertised to DHCP clients.
     *
     * <p>If set to {@link #MTU_UNSET}, no MTU will be advertised to clients. This parameter
     * is optional and defaults to {@link #MTU_UNSET}.
     */
    public DhcpServingParamsParcelExt setLinkMtu(int linkMtu) {
        this.linkMtu = linkMtu;
        return this;
    }

    /**
     * Set whether the DHCP server should send the ANDROID_METERED vendor-specific option.
     *
     * <p>If not set, the default value is false.
     */
    public DhcpServingParamsParcelExt setMetered(boolean metered) {
        this.metered = metered;
        return this;
    }

    private static int[] toIntArray(@NonNull Collection<Inet4Address> addrs) {
        int[] res = new int[addrs.size()];
        int i = 0;
        for (Inet4Address addr : addrs) {
            res[i] = inet4AddressToIntHTH(addr);
            i++;
        }
        return res;
    }
}
+113 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net.dhcp;

import static android.net.InetAddresses.parseNumericAddress;

import static com.google.android.collect.Sets.newHashSet;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import android.net.LinkAddress;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.net.Inet4Address;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@RunWith(AndroidJUnit4.class)
@SmallTest
public class DhcpServingParamsParcelExtTest {
    private static final Inet4Address TEST_ADDRESS = inet4Addr("192.168.0.123");
    private static final int TEST_ADDRESS_PARCELED = 0xc0a8007b;
    private static final int TEST_PREFIX_LENGTH = 17;
    private static final int TEST_LEASE_TIME_SECS = 120;
    private static final int TEST_MTU = 1000;
    private static final Set<Inet4Address> TEST_ADDRESS_SET =
            newHashSet(inet4Addr("192.168.1.123"), inet4Addr("192.168.1.124"));
    private static final Set<Integer> TEST_ADDRESS_SET_PARCELED =
            newHashSet(0xc0a8017b, 0xc0a8017c);

    private DhcpServingParamsParcelExt mParcel;

    @Before
    public void setUp() {
        mParcel = new DhcpServingParamsParcelExt();
    }

    @Test
    public void testSetServerAddr() {
        mParcel.setServerAddr(new LinkAddress(TEST_ADDRESS, TEST_PREFIX_LENGTH));

        assertEquals(TEST_ADDRESS_PARCELED, mParcel.serverAddr);
        assertEquals(TEST_PREFIX_LENGTH, mParcel.serverAddrPrefixLength);
    }

    @Test
    public void testSetDefaultRouters() {
        mParcel.setDefaultRouters(TEST_ADDRESS_SET);
        assertEquals(TEST_ADDRESS_SET_PARCELED, asSet(mParcel.defaultRouters));
    }

    @Test
    public void testSetDnsServers() {
        mParcel.setDnsServers(TEST_ADDRESS_SET);
        assertEquals(TEST_ADDRESS_SET_PARCELED, asSet(mParcel.dnsServers));
    }

    @Test
    public void testSetExcludedAddrs() {
        mParcel.setExcludedAddrs(TEST_ADDRESS_SET);
        assertEquals(TEST_ADDRESS_SET_PARCELED, asSet(mParcel.excludedAddrs));
    }

    @Test
    public void testSetDhcpLeaseTimeSecs() {
        mParcel.setDhcpLeaseTimeSecs(TEST_LEASE_TIME_SECS);
        assertEquals(TEST_LEASE_TIME_SECS, mParcel.dhcpLeaseTimeSecs);
    }

    @Test
    public void testSetLinkMtu() {
        mParcel.setLinkMtu(TEST_MTU);
        assertEquals(TEST_MTU, mParcel.linkMtu);
    }

    @Test
    public void testSetMetered() {
        mParcel.setMetered(true);
        assertTrue(mParcel.metered);
        mParcel.setMetered(false);
        assertFalse(mParcel.metered);
    }

    private static Inet4Address inet4Addr(String addr) {
        return (Inet4Address) parseNumericAddress(addr);
    }

    private static Set<Integer> asSet(int[] ints) {
        return IntStream.of(ints).boxed().collect(Collectors.toSet());
    }
}
Loading