/*
 * Copyright (C) 2010 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;

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;
import static android.system.OsConstants.RT_SCOPE_SITE;
import static android.system.OsConstants.RT_SCOPE_UNIVERSE;

import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Pair;

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

/**
 * Identifies an IP address on a network link.
 *
 * A {@code LinkAddress} consists of:
 * <ul>
 * <li>An IP address and prefix length (e.g., {@code 2001:db8::1/64} or {@code 192.0.2.1/24}).
 * The address must be unicast, as multicast addresses cannot be assigned to interfaces.
 * <li>Address flags: A bitmask of {@code OsConstants.IFA_F_*} values representing properties
 * of the address (e.g., {@code android.system.OsConstants.IFA_F_OPTIMISTIC}).
 * <li>Address scope: One of the {@code OsConstants.IFA_F_*} values; defines the scope in which
 * the address is unique (e.g.,
 * {@code android.system.OsConstants.RT_SCOPE_LINK} or
 * {@code android.system.OsConstants.RT_SCOPE_UNIVERSE}).
 * </ul>
 */
public class LinkAddress implements Parcelable {
    /**
     * IPv4 or IPv6 address.
     */
    @UnsupportedAppUsage
    private InetAddress address;

    /**
     * Prefix length.
     */
    @UnsupportedAppUsage
    private int prefixLength;

    /**
     * Address flags. A bitmask of IFA_F_* values.
     */
    private int flags;

    /**
     * Address scope. One of the RT_SCOPE_* constants.
     */
    private int scope;

    /**
     * Utility function to determines the scope of a unicast address. Per RFC 4291 section 2.5 and
     * RFC 6724 section 3.2.
     * @hide
     */
    private static int scopeForUnicastAddress(InetAddress addr) {
        if (addr.isAnyLocalAddress()) {
            return RT_SCOPE_HOST;
        }

        if (addr.isLoopbackAddress() || addr.isLinkLocalAddress()) {
            return RT_SCOPE_LINK;
        }

        // isSiteLocalAddress() returns true for private IPv4 addresses, but RFC 6724 section 3.2
        // says that they are assigned global scope.
        if (!(addr instanceof Inet4Address) && addr.isSiteLocalAddress()) {
            return RT_SCOPE_SITE;
        }

        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 (isIPv6()) {
            byte[] bytes = address.getAddress();
            return ((bytes[0] & (byte)0xfe) == (byte)0xfc);
        }
        return false;
    }

    /**
     * @return true if the address is IPv6.
     * @hide
     */
    @UnsupportedAppUsage
    public boolean isIPv6() {
        return address instanceof Inet6Address;
    }

    /**
     * @return true if the address is IPv4 or is a mapped IPv4 address.
     * @hide
     */
    public boolean isIPv4() {
        return address instanceof Inet4Address;
    }

    /**
     * Utility function for the constructors.
     */
    private void init(InetAddress address, int prefixLength, int flags, int scope) {
        if (address == null ||
                address.isMulticastAddress() ||
                prefixLength < 0 ||
                (address instanceof Inet4Address && prefixLength > 32) ||
                (prefixLength > 128)) {
            throw new IllegalArgumentException("Bad LinkAddress params " + address +
                    "/" + prefixLength);
        }
        this.address = address;
        this.prefixLength = prefixLength;
        this.flags = flags;
        this.scope = scope;
    }

    /**
     * Constructs a new {@code LinkAddress} from an {@code InetAddress} and prefix length, with
     * the specified flags and scope. Flags and scope are not checked for validity.
     * @param address The IP address.
     * @param prefixLength The prefix length.
     * @param flags A bitmask of {@code IFA_F_*} values representing properties of the address.
     * @param scope An integer defining the scope in which the address is unique (e.g.,
     *              {@link OsConstants#RT_SCOPE_LINK} or {@link OsConstants#RT_SCOPE_SITE}).
     * @hide
     */
    public LinkAddress(InetAddress address, int prefixLength, int flags, int scope) {
        init(address, prefixLength, flags, scope);
    }

    /**
     * Constructs a new {@code LinkAddress} from an {@code InetAddress} and a prefix length.
     * The flags are set to zero and the scope is determined from the address.
     * @param address The IP address.
     * @param prefixLength The prefix length.
     * @hide
     */
    @SystemApi
    public LinkAddress(InetAddress address, int prefixLength) {
        this(address, prefixLength, 0, 0);
        this.scope = scopeForUnicastAddress(address);
    }

    /**
     * Constructs a new {@code LinkAddress} from an {@code InterfaceAddress}.
     * The flags are set to zero and the scope is determined from the address.
     * @param interfaceAddress The interface address.
     * @hide
     */
    public LinkAddress(InterfaceAddress interfaceAddress) {
        this(interfaceAddress.getAddress(),
             interfaceAddress.getNetworkPrefixLength());
    }

    /**
     * Constructs a new {@code LinkAddress} from a string such as "192.0.2.5/24" or
     * "2001:db8::1/64". The flags are set to zero and the scope is determined from the address.
     * @param string The string to parse.
     * @hide
     */
    @SystemApi
    public LinkAddress(String address) {
        this(address, 0, 0);
        this.scope = scopeForUnicastAddress(this.address);
    }

    /**
     * Constructs a new {@code LinkAddress} from a string such as "192.0.2.5/24" or
     * "2001:db8::1/64", with the specified flags and scope.
     * @param string The string to parse.
     * @param flags The address flags.
     * @param scope The address scope.
     * @hide
     */
    public LinkAddress(String address, int flags, int scope) {
        // This may throw an IllegalArgumentException; catching it is the caller's responsibility.
        // TODO: consider rejecting mapped IPv4 addresses such as "::ffff:192.0.2.5/24".
        Pair<InetAddress, Integer> ipAndMask = NetworkUtils.parseIpAndMask(address);
        init(ipAndMask.first, ipAndMask.second, flags, scope);
    }

    /**
     * Returns a string representation of this address, such as "192.0.2.1/24" or "2001:db8::1/64".
     * The string representation does not contain the flags and scope, just the address and prefix
     * length.
     */
    @Override
    public String toString() {
        return address.getHostAddress() + "/" + prefixLength;
    }

    /**
     * Compares this {@code LinkAddress} instance against {@code obj}. Two addresses are equal if
     * their address, prefix length, flags and scope are equal. Thus, for example, two addresses
     * that have the same address and prefix length are not equal if one of them is deprecated and
     * the other is not.
     *
     * @param obj the object to be tested for equality.
     * @return {@code true} if both objects are equal, {@code false} otherwise.
     */
    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof LinkAddress)) {
            return false;
        }
        LinkAddress linkAddress = (LinkAddress) obj;
        return this.address.equals(linkAddress.address) &&
            this.prefixLength == linkAddress.prefixLength &&
            this.flags == linkAddress.flags &&
            this.scope == linkAddress.scope;
    }

    /**
     * Returns a hashcode for this address.
     */
    @Override
    public int hashCode() {
        return address.hashCode() + 11 * prefixLength + 19 * flags + 43 * scope;
    }

    /**
     * Determines whether this {@code LinkAddress} and the provided {@code LinkAddress}
     * represent the same address. Two {@code LinkAddresses} represent the same address
     * if they have the same IP address and prefix length, even if their properties are
     * different.
     *
     * @param other the {@code LinkAddress} to compare to.
     * @return {@code true} if both objects have the same address and prefix length, {@code false}
     * otherwise.
     * @hide
     */
    @UnsupportedAppUsage
    public boolean isSameAddressAs(LinkAddress other) {
        return address.equals(other.address) && prefixLength == other.prefixLength;
    }

    /**
     * Returns the {@link InetAddress} of this {@code LinkAddress}.
     */
    public InetAddress getAddress() {
        return address;
    }

    /**
     * Returns the prefix length of this {@code LinkAddress}.
     */
    public int getPrefixLength() {
        return prefixLength;
    }

    /**
     * Returns the prefix length of this {@code LinkAddress}.
     * TODO: Delete all callers and remove in favour of getPrefixLength().
     * @hide
     */
    @UnsupportedAppUsage
    public int getNetworkPrefixLength() {
        return getPrefixLength();
    }

    /**
     * Returns the flags of this {@code LinkAddress}.
     */
    public int getFlags() {
        return flags;
    }

    /**
     * Returns the scope of this {@code LinkAddress}.
     */
    public int getScope() {
        return scope;
    }

    /**
     * Returns true if this {@code LinkAddress} is global scope and preferred.
     * @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 &&
                !isIPv6ULA() &&
                (flags & (IFA_F_DADFAILED | IFA_F_DEPRECATED)) == 0L &&
                ((flags & IFA_F_TENTATIVE) == 0L || (flags & IFA_F_OPTIMISTIC) != 0L));
    }

    /**
     * Implement the Parcelable interface.
     */
    public int describeContents() {
        return 0;
    }

    /**
     * Implement the Parcelable interface.
     */
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeByteArray(address.getAddress());
        dest.writeInt(prefixLength);
        dest.writeInt(this.flags);
        dest.writeInt(scope);
    }

    /**
     * Implement the Parcelable interface.
     */
    public static final Creator<LinkAddress> CREATOR =
        new Creator<LinkAddress>() {
            public LinkAddress createFromParcel(Parcel in) {
                InetAddress address = null;
                try {
                    address = InetAddress.getByAddress(in.createByteArray());
                } catch (UnknownHostException e) {
                    // Nothing we can do here. When we call the constructor, we'll throw an
                    // IllegalArgumentException, because a LinkAddress can't have a null
                    // InetAddress.
                }
                int prefixLength = in.readInt();
                int flags = in.readInt();
                int scope = in.readInt();
                return new LinkAddress(address, prefixLength, flags, scope);
            }

            public LinkAddress[] newArray(int size) {
                return new LinkAddress[size];
            }
        };
}
