/*
 * 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 com.android.net.module.util.Inet4AddressUtils.getPrefixMaskAsInet4Address;
import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH;
import static com.android.net.module.util.NetworkStackConstants.INFINITE_LEASE;
import static com.android.net.module.util.NetworkStackConstants.IPV4_MAX_MTU;
import static com.android.net.module.util.NetworkStackConstants.IPV4_MIN_MTU;

import static java.lang.Integer.toUnsignedLong;

import android.net.IpPrefix;
import android.net.LinkAddress;
import android.util.ArraySet;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.net.module.util.Inet4AddressUtils;

import java.net.Inet4Address;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
 * Parameters used by the DhcpServer to serve requests.
 *
 * <p>Instances are immutable. Use {@link DhcpServingParams.Builder} to instantiate.
 * @hide
 */
public class DhcpServingParams {
    public static final int MTU_UNSET = 0;
    public static final int MIN_PREFIX_LENGTH = 16;
    public static final int MAX_PREFIX_LENGTH = 30;

    /** Server inet address and prefix to serve */
    @NonNull
    public final LinkAddress serverAddr;

    /**
     * Default routers to be advertised to DHCP clients. May be empty.
     * This set is provided by {@link DhcpServingParams.Builder} and is immutable.
     */
    @NonNull
    public final Set<Inet4Address> defaultRouters;

    /**
     * DNS servers to be advertised to DHCP clients. May be empty.
     * This set is provided by {@link DhcpServingParams.Builder} and is immutable.
     */
    @NonNull
    public final Set<Inet4Address> dnsServers;

    /**
     * Excluded addresses that the DHCP server is not allowed to assign to clients.
     * This set is provided by {@link DhcpServingParams.Builder} and is immutable.
     */
    @NonNull
    public final Set<Inet4Address> excludedAddrs;

    // DHCP uses uint32. Use long for clearer code, and check range when building.
    public final long dhcpLeaseTimeSecs;
    public final int linkMtu;

    /**
     * Indicates whether the DHCP server should send the ANDROID_METERED vendor-specific option.
     */
    public final boolean metered;

    /**
     * Client inet address. This will be the only address offered by DhcpServer if set.
     */
    @Nullable
    public final Inet4Address singleClientAddr;

    /**
     * Indicates whether the DHCP server should request a new prefix from IpServer when receiving
     * DHCPDECLINE message in certain particular link (e.g. there is only one downstream USB
     * tethering client). If it's false, process DHCPDECLINE message as RFC2131#4.3.3 suggests.
     */
    public final boolean changePrefixOnDecline;

    /**
     * Checked exception thrown when some parameters used to build {@link DhcpServingParams} are
     * missing or invalid.
     */
    public static class InvalidParameterException extends Exception {
        public InvalidParameterException(String message) {
            super(message);
        }
    }

    private DhcpServingParams(@NonNull LinkAddress serverAddr,
            @NonNull Set<Inet4Address> defaultRouters,
            @NonNull Set<Inet4Address> dnsServers, @NonNull Set<Inet4Address> excludedAddrs,
            long dhcpLeaseTimeSecs, int linkMtu, boolean metered, Inet4Address singleClientAddr,
            boolean changePrefixOnDecline) {
        this.serverAddr = serverAddr;
        this.defaultRouters = defaultRouters;
        this.dnsServers = dnsServers;
        this.excludedAddrs = excludedAddrs;
        this.dhcpLeaseTimeSecs = dhcpLeaseTimeSecs;
        this.linkMtu = linkMtu;
        this.metered = metered;
        this.singleClientAddr = singleClientAddr;
        this.changePrefixOnDecline = changePrefixOnDecline;
    }

    /**
     * Create parameters from a stable AIDL-compatible parcel.
     * @throws InvalidParameterException The parameters parcelable is null or invalid.
     */
    public static DhcpServingParams fromParcelableObject(@Nullable DhcpServingParamsParcel parcel)
            throws InvalidParameterException {
        if (parcel == null) {
            throw new InvalidParameterException("Null serving parameters");
        }
        final LinkAddress serverAddr = new LinkAddress(
                intToInet4AddressHTH(parcel.serverAddr),
                parcel.serverAddrPrefixLength);
        Inet4Address clientAddr = null;
        if (parcel.singleClientAddr != 0) {
            clientAddr = intToInet4AddressHTH(parcel.singleClientAddr);
        }

        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)
                .setSingleClientAddr(clientAddr)
                .setChangePrefixOnDecline(parcel.changePrefixOnDecline)
                .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();
    }

    /**
     * Get the served prefix mask as an IPv4 address.
     *
     * <p>For example, if the served prefix is 192.168.42.0/24, this will return 255.255.255.0.
     */
    @NonNull
    public Inet4Address getPrefixMaskAsAddress() {
        return getPrefixMaskAsInet4Address(serverAddr.getPrefixLength());
    }

    /**
     * Get the server broadcast address.
     *
     * <p>For example, if the server {@link LinkAddress} is 192.168.42.1/24, this will return
     * 192.168.42.255.
     */
    @NonNull
    public Inet4Address getBroadcastAddress() {
        return Inet4AddressUtils.getBroadcastAddress(
                getServerInet4Addr(), serverAddr.getPrefixLength());
    }

    /**
     * Utility class to create new instances of {@link DhcpServingParams} while checking validity
     * of the parameters.
     */
    public static class Builder {
        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;
        private Inet4Address mClientAddr;
        private boolean mChangePrefixOnDecline;

        /**
         * Set the server address and served prefix for the DHCP server.
         *
         * <p>This parameter is required.
         */
        public Builder setServerAddr(@NonNull LinkAddress serverAddr) {
            this.mServerAddr = serverAddr;
            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 before building the {@link DhcpServingParams}.
         */
        public Builder setDefaultRouters(@NonNull Set<Inet4Address> defaultRouters) {
            this.mDefaultRouters = 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 before building the {@link DhcpServingParams}.
         */
        public Builder setDefaultRouters(@NonNull Inet4Address... defaultRouters) {
            return setDefaultRouters(makeArraySet(defaultRouters));
        }

        /**
         * Convenience method to build the parameters with no default router.
         *
         * <p>Equivalent to calling {@link #setDefaultRouters(Inet4Address...)} with no address.
         */
        public Builder withNoDefaultRouter() {
            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 before building the
         * {@link DhcpServingParams}.
         */
        public Builder setDnsServers(@NonNull Set<Inet4Address> dnsServers) {
            this.mDnsServers = 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 before
         * building the {@link DhcpServingParams}.
         */
        public Builder setDnsServers(@NonNull Inet4Address... dnsServers) {
            return setDnsServers(makeArraySet(dnsServers));
        }

        /**
         * Convenience method to build the parameters with no DNS server.
         *
         * <p>Equivalent to calling {@link #setDnsServers(Inet4Address...)} with no address.
         */
        public Builder withNoDnsServer() {
            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 Builder setExcludedAddrs(@NonNull Set<Inet4Address> excludedAddrs) {
            this.mExcludedAddrs = 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 Builder setExcludedAddrs(@NonNull Inet4Address... excludedAddrs) {
            return setExcludedAddrs(makeArraySet(excludedAddrs));
        }

        /**
         * Set the lease time for leases assigned by the DHCP server.
         *
         * <p>This parameter is required.
         */
        public Builder setDhcpLeaseTimeSecs(long dhcpLeaseTimeSecs) {
            this.mDhcpLeaseTimeSecs = 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 Builder setLinkMtu(int linkMtu) {
            this.mLinkMtu = 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 Builder setMetered(boolean metered) {
            this.mMetered = metered;
            return this;
        }

        /**
         * Set the client address.
         *
         * <p>If not set, the default value is null.
         */
        public Builder setSingleClientAddr(@Nullable Inet4Address clientAddr) {
            this.mClientAddr = clientAddr;
            return this;
        }

        /**
         * Set whether the DHCP server should request a new prefix from IpServer when receiving
         * DHCPDECLINE message in certain particular link.
         *
         * <p>If not set, the default value is false.
         */
        public Builder setChangePrefixOnDecline(boolean changePrefixOnDecline) {
            this.mChangePrefixOnDecline = changePrefixOnDecline;
            return this;
        }

        /**
         * Create a new {@link DhcpServingParams} instance based on parameters set in the builder.
         *
         * <p>This method has no side-effects. If it does not throw, a valid
         * {@link DhcpServingParams} is returned.
         * @return The constructed parameters.
         * @throws InvalidParameterException At least one parameter is missing or invalid.
         */
        @NonNull
        public DhcpServingParams build() throws InvalidParameterException {
            if (mServerAddr == null) {
                throw new InvalidParameterException("Missing serverAddr");
            }
            if (mDefaultRouters == null) {
                throw new InvalidParameterException("Missing defaultRouters");
            }
            if (mDnsServers == null) {
                // Empty set is OK, but enforce explicitly setting it
                throw new InvalidParameterException("Missing dnsServers");
            }
            if (mDhcpLeaseTimeSecs <= 0 || mDhcpLeaseTimeSecs > toUnsignedLong(INFINITE_LEASE)) {
                throw new InvalidParameterException("Invalid lease time: " + mDhcpLeaseTimeSecs);
            }
            if (mLinkMtu != MTU_UNSET && (mLinkMtu < IPV4_MIN_MTU || mLinkMtu > IPV4_MAX_MTU)) {
                throw new InvalidParameterException("Invalid link MTU: " + mLinkMtu);
            }
            if (!mServerAddr.isIpv4()) {
                throw new InvalidParameterException("serverAddr must be IPv4");
            }
            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(mServerAddr);
            for (Inet4Address addr : mDefaultRouters) {
                if (!prefix.contains(addr)) {
                    throw new InvalidParameterException(String.format(
                            "Default router %s is not in server prefix %s", addr, mServerAddr));
                }
            }

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

            return new DhcpServingParams(mServerAddr,
                    Collections.unmodifiableSet(new HashSet<>(mDefaultRouters)),
                    Collections.unmodifiableSet(new HashSet<>(mDnsServers)),
                    Collections.unmodifiableSet(excl),
                    mDhcpLeaseTimeSecs, mLinkMtu, mMetered, mClientAddr, mChangePrefixOnDecline);
        }
    }

    /**
     * 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());
    }

    private static <T> ArraySet<T> makeArraySet(T[] elements) {
        final ArraySet<T> set = new ArraySet<>(elements.length);
        set.addAll(Arrays.asList(elements));
        return set;
    }
}
