/*
 *  Copyright (c) 2016, The OpenThread Authors.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. Neither the name of the copyright holder nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @file
 *   This file implements IPv6 addresses.
 */

#include "ip6_address.hpp"

#include <stdio.h>

#include "common/array.hpp"
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
#include "common/encoding.hpp"
#include "common/instance.hpp"
#include "common/numeric_limits.hpp"
#include "common/random.hpp"
#include "net/ip4_address.hpp"
#include "net/netif.hpp"

using ot::Encoding::BigEndian::HostSwap32;

namespace ot {
namespace Ip6 {

//---------------------------------------------------------------------------------------------------------------------
// NetworkPrefix methods

Error NetworkPrefix::GenerateRandomUla(void)
{
    m8[0] = 0xfd;

    return Random::Crypto::FillBuffer(&m8[1], kSize - 1);
}

//---------------------------------------------------------------------------------------------------------------------
// Prefix methods

void Prefix::Set(const uint8_t *aPrefix, uint8_t aLength)
{
    memcpy(mPrefix.mFields.m8, aPrefix, SizeForLength(aLength));
    mLength = aLength;
}

bool Prefix::IsEqual(const uint8_t *aPrefixBytes, uint8_t aPrefixLength) const
{
    return (mLength == aPrefixLength) && (MatchLength(GetBytes(), aPrefixBytes, GetBytesSize()) >= mLength);
}

bool Prefix::operator<(const Prefix &aOther) const
{
    bool    isSmaller;
    uint8_t matchedLength;

    VerifyOrExit(GetLength() == aOther.GetLength(), isSmaller = GetLength() < aOther.GetLength());

    matchedLength = MatchLength(GetBytes(), aOther.GetBytes(), GetBytesSize());

    VerifyOrExit(matchedLength < GetLength(), isSmaller = false);

    isSmaller = GetBytes()[matchedLength / CHAR_BIT] < aOther.GetBytes()[matchedLength / CHAR_BIT];

exit:
    return isSmaller;
}

uint8_t Prefix::MatchLength(const uint8_t *aPrefixA, const uint8_t *aPrefixB, uint8_t aMaxSize)
{
    uint8_t matchedLength = 0;

    OT_ASSERT(aMaxSize <= Address::kSize);

    for (uint8_t i = 0; i < aMaxSize; i++)
    {
        uint8_t diff = aPrefixA[i] ^ aPrefixB[i];

        if (diff == 0)
        {
            matchedLength += CHAR_BIT;
        }
        else
        {
            while ((diff & 0x80) == 0)
            {
                matchedLength++;
                diff <<= 1;
            }

            break;
        }
    }

    return matchedLength;
}

bool Prefix::IsValidNat64(void) const
{
    return (mLength == 32) || (mLength == 40) || (mLength == 48) || (mLength == 56) || (mLength == 64) ||
           (mLength == 96);
}

Prefix::InfoString Prefix::ToString(void) const
{
    InfoString string;

    ToString(string);

    return string;
}

void Prefix::ToString(char *aBuffer, uint16_t aSize) const
{
    StringWriter writer(aBuffer, aSize);

    ToString(writer);
}

void Prefix::ToString(StringWriter &aWriter) const
{
    uint8_t sizeInUint16 = (GetBytesSize() + sizeof(uint16_t) - 1) / sizeof(uint16_t);

    AsCoreType(&mPrefix).AppendHexWords(aWriter, sizeInUint16);

    if (GetBytesSize() < Address::kSize - 1)
    {
        aWriter.Append("::");
    }

    aWriter.Append("/%d", mLength);
}

//---------------------------------------------------------------------------------------------------------------------
// InterfaceIdentifier methods

bool InterfaceIdentifier::IsUnspecified(void) const
{
    return (mFields.m32[0] == 0) && (mFields.m32[1] == 0);
}

bool InterfaceIdentifier::IsReserved(void) const
{
    return IsSubnetRouterAnycast() || IsReservedSubnetAnycast() || IsAnycastLocator();
}

bool InterfaceIdentifier::IsSubnetRouterAnycast(void) const
{
    return (mFields.m32[0] == 0) && (mFields.m32[1] == 0);
}

bool InterfaceIdentifier::IsReservedSubnetAnycast(void) const
{
    // Format of IID in a Reserved Subnet Anycast Address (RFC 2526)
    //
    // |      57 bits     |   7 bits   |
    // +------------------+------------+
    // | 1111110111...111 | anycast ID |
    // +------------------+------------+

    return (mFields.m32[0] == HostSwap32(0xfdffffff) && mFields.m16[2] == HostSwap16(0xffff) && mFields.m8[6] == 0xff &&
            mFields.m8[7] >= 0x80);
}

void InterfaceIdentifier::GenerateRandom(void)
{
    SuccessOrAssert(Random::Crypto::FillBuffer(mFields.m8, kSize));
}

void InterfaceIdentifier::SetBytes(const uint8_t *aBuffer)
{
    memcpy(mFields.m8, aBuffer, kSize);
}

void InterfaceIdentifier::SetFromExtAddress(const Mac::ExtAddress &aExtAddress)
{
    Mac::ExtAddress addr;

    addr = aExtAddress;
    addr.ToggleLocal();
    addr.CopyTo(mFields.m8);
}

void InterfaceIdentifier::ConvertToExtAddress(Mac::ExtAddress &aExtAddress) const
{
    aExtAddress.Set(mFields.m8);
    aExtAddress.ToggleLocal();
}

void InterfaceIdentifier::ConvertToMacAddress(Mac::Address &aMacAddress) const
{
    aMacAddress.SetExtended(mFields.m8);
    aMacAddress.GetExtended().ToggleLocal();
}

void InterfaceIdentifier::SetToLocator(uint16_t aLocator)
{
    // Locator IID pattern `0000:00ff:fe00:xxxx`
    mFields.m32[0] = HostSwap32(0x000000ff);
    mFields.m16[2] = HostSwap16(0xfe00);
    mFields.m16[3] = HostSwap16(aLocator);
}

bool InterfaceIdentifier::IsLocator(void) const
{
    // Locator IID pattern 0000:00ff:fe00:xxxx
    return (mFields.m32[0] == HostSwap32(0x000000ff) && mFields.m16[2] == HostSwap16(0xfe00));
}

bool InterfaceIdentifier::IsRoutingLocator(void) const
{
    return (IsLocator() && (mFields.m8[6] < kAloc16Mask) && ((mFields.m8[6] & kRloc16ReservedBitMask) == 0));
}

bool InterfaceIdentifier::IsAnycastLocator(void) const
{
    // Anycast locator range 0xfc00- 0xfcff (`kAloc16Mask` is 0xfc)
    return (IsLocator() && (mFields.m8[6] == kAloc16Mask));
}

bool InterfaceIdentifier::IsAnycastServiceLocator(void) const
{
    uint16_t locator = GetLocator();

    return (IsLocator() && (locator >= Mle::kAloc16ServiceStart) && (locator <= Mle::kAloc16ServiceEnd));
}

InterfaceIdentifier::InfoString InterfaceIdentifier::ToString(void) const
{
    InfoString string;

    string.AppendHexBytes(mFields.m8, kSize);

    return string;
}

//---------------------------------------------------------------------------------------------------------------------
// Address methods

bool Address::IsUnspecified(void) const
{
    return (mFields.m32[0] == 0 && mFields.m32[1] == 0 && mFields.m32[2] == 0 && mFields.m32[3] == 0);
}

bool Address::IsLoopback(void) const
{
    return (mFields.m32[0] == 0 && mFields.m32[1] == 0 && mFields.m32[2] == 0 && mFields.m32[3] == HostSwap32(1));
}

bool Address::IsLinkLocal(void) const
{
    return (mFields.m16[0] & HostSwap16(0xffc0)) == HostSwap16(0xfe80);
}

void Address::SetToLinkLocalAddress(const Mac::ExtAddress &aExtAddress)
{
    mFields.m32[0] = HostSwap32(0xfe800000);
    mFields.m32[1] = 0;
    GetIid().SetFromExtAddress(aExtAddress);
}

void Address::SetToLinkLocalAddress(const InterfaceIdentifier &aIid)
{
    mFields.m32[0] = HostSwap32(0xfe800000);
    mFields.m32[1] = 0;
    SetIid(aIid);
}

bool Address::IsLinkLocalMulticast(void) const
{
    return IsMulticast() && (GetScope() == kLinkLocalScope);
}

bool Address::IsLinkLocalAllNodesMulticast(void) const
{
    return (*this == GetLinkLocalAllNodesMulticast());
}

void Address::SetToLinkLocalAllNodesMulticast(void)
{
    *this = GetLinkLocalAllNodesMulticast();
}

bool Address::IsLinkLocalAllRoutersMulticast(void) const
{
    return (*this == GetLinkLocalAllRoutersMulticast());
}

void Address::SetToLinkLocalAllRoutersMulticast(void)
{
    *this = GetLinkLocalAllRoutersMulticast();
}

bool Address::IsRealmLocalMulticast(void) const
{
    return IsMulticast() && (GetScope() == kRealmLocalScope);
}

bool Address::IsMulticastLargerThanRealmLocal(void) const
{
    return IsMulticast() && (GetScope() > kRealmLocalScope);
}

bool Address::IsRealmLocalAllNodesMulticast(void) const
{
    return (*this == GetRealmLocalAllNodesMulticast());
}

void Address::SetToRealmLocalAllNodesMulticast(void)
{
    *this = GetRealmLocalAllNodesMulticast();
}

bool Address::IsRealmLocalAllRoutersMulticast(void) const
{
    return (*this == GetRealmLocalAllRoutersMulticast());
}

void Address::SetToRealmLocalAllRoutersMulticast(void)
{
    *this = GetRealmLocalAllRoutersMulticast();
}

bool Address::IsRealmLocalAllMplForwarders(void) const
{
    return (*this == GetRealmLocalAllMplForwarders());
}

void Address::SetToRealmLocalAllMplForwarders(void)
{
    *this = GetRealmLocalAllMplForwarders();
}

bool Address::MatchesPrefix(const Prefix &aPrefix) const
{
    return Prefix::MatchLength(mFields.m8, aPrefix.GetBytes(), aPrefix.GetBytesSize()) >= aPrefix.GetLength();
}

bool Address::MatchesPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength) const
{
    return Prefix::MatchLength(mFields.m8, aPrefix, Prefix::SizeForLength(aPrefixLength)) >= aPrefixLength;
}

void Address::SetPrefix(const NetworkPrefix &aNetworkPrefix)
{
    mFields.mComponents.mNetworkPrefix = aNetworkPrefix;
}

void Address::SetPrefix(const Prefix &aPrefix)
{
    SetPrefix(0, aPrefix.GetBytes(), aPrefix.GetLength());
}

void Address::SetPrefix(uint8_t aOffset, const uint8_t *aPrefix, uint8_t aPrefixLength)
{
    uint8_t bytes     = aPrefixLength / CHAR_BIT;
    uint8_t extraBits = aPrefixLength % CHAR_BIT;

    OT_ASSERT(aPrefixLength <= (sizeof(Address) - aOffset) * CHAR_BIT);

    memcpy(mFields.m8 + aOffset, aPrefix, bytes);

    if (extraBits > 0)
    {
        uint8_t index = aOffset + bytes;
        uint8_t mask  = ((0x80 >> (extraBits - 1)) - 1);

        // `mask` has its higher (msb) `extraBits` bits as `0` and the remaining as `1`.
        // Example with `extraBits` = 3:
        // ((0x80 >> 2) - 1) = (0b0010_0000 - 1) = 0b0001_1111

        mFields.m8[index] &= mask;
        mFields.m8[index] |= (aPrefix[index] & ~mask);
    }
}

void Address::SetMulticastNetworkPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength)
{
    SetPrefix(kMulticastNetworkPrefixOffset, aPrefix, aPrefixLength);
    mFields.m8[kMulticastNetworkPrefixLengthOffset] = aPrefixLength;
}

void Address::SetToLocator(const NetworkPrefix &aNetworkPrefix, uint16_t aLocator)
{
    SetPrefix(aNetworkPrefix);
    GetIid().SetToLocator(aLocator);
}

uint8_t Address::GetScope(void) const
{
    uint8_t rval;

    if (IsMulticast())
    {
        rval = mFields.m8[1] & 0xf;
    }
    else if (IsLinkLocal())
    {
        rval = kLinkLocalScope;
    }
    else if (IsLoopback())
    {
        rval = kNodeLocalScope;
    }
    else
    {
        rval = kGlobalScope;
    }

    return rval;
}

uint8_t Address::PrefixMatch(const Address &aOther) const
{
    return Prefix::MatchLength(mFields.m8, aOther.mFields.m8, sizeof(Address));
}

bool Address::MatchesFilter(TypeFilter aFilter) const
{
    bool matches = true;

    switch (aFilter)
    {
    case kTypeAny:
        break;

    case kTypeUnicast:
        matches = !IsUnspecified() && !IsMulticast();
        break;

    case kTypeMulticast:
        matches = IsMulticast();
        break;

    case kTypeMulticastLargerThanRealmLocal:
        matches = IsMulticastLargerThanRealmLocal();
        break;
    }

    return matches;
}

void Address::SynthesizeFromIp4Address(const Prefix &aPrefix, const Ip4::Address &aIp4Address)
{
    // The prefix length must be 32, 40, 48, 56, 64, 96. IPv4 bytes are added
    // after the prefix, skipping over the bits 64 to 71 (byte at `kSkipIndex`)
    // which must be set to zero. The suffix is set to zero (per RFC 6502).
    //
    //    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
    //    |PL| 0-------------32--40--48--56--64--72--80--88--96--104---------|
    //    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
    //    |32|     prefix    |v4(32)         | u | suffix                    |
    //    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
    //    |40|     prefix        |v4(24)     | u |(8)| suffix                |
    //    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
    //    |48|     prefix            |v4(16) | u | (16)  | suffix            |
    //    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
    //    |56|     prefix                |(8)| u |  v4(24)   | suffix        |
    //    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
    //    |64|     prefix                    | u |   v4(32)      | suffix    |
    //    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
    //    |96|     prefix                                    |    v4(32)     |
    //    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

    constexpr uint8_t kSkipIndex = 8;

    uint8_t ip6Index;

    OT_ASSERT(aPrefix.IsValidNat64());

    Clear();
    SetPrefix(aPrefix);

    ip6Index = aPrefix.GetLength() / CHAR_BIT;

    for (uint8_t i = 0; i < Ip4::Address::kSize; i++)
    {
        if (ip6Index == kSkipIndex)
        {
            ip6Index++;
        }

        mFields.m8[ip6Index++] = aIp4Address.GetBytes()[i];
    }
}

Error Address::FromString(const char *aString)
{
    constexpr uint8_t kInvalidIndex = 0xff;
    constexpr char    kColonChar    = ':';
    constexpr char    kDotChar      = '.';
    constexpr char    kNullChar     = '\0';

    Error   error      = kErrorParse;
    uint8_t index      = 0;
    uint8_t endIndex   = kSize / sizeof(uint16_t);
    uint8_t colonIndex = kInvalidIndex;
    bool    hasIp4     = false;

    // Check if the string starts with "::".

    if (*aString == kColonChar)
    {
        aString++;
        VerifyOrExit(*aString == kColonChar);
        aString++;
        colonIndex = index;
    }

    while (*aString != kNullChar)
    {
        const char *start = aString;
        uint32_t    value = 0;

        // Parse hex number

        while (true)
        {
            char    c = *aString;
            uint8_t digit;

            if (('A' <= c) && (c <= 'F'))
            {
                digit = static_cast<uint8_t>(c - 'A' + 10);
            }
            else if (('a' <= c) && (c <= 'f'))
            {
                digit = static_cast<uint8_t>(c - 'a' + 10);
            }
            else if (('0' <= c) && (c <= '9'))
            {
                digit = static_cast<uint8_t>(c - '0');
            }
            else
            {
                break;
            }

            aString++;
            value = (value << 4) + digit;

            VerifyOrExit(value <= NumericLimits<uint16_t>::kMax);
        }

        VerifyOrExit(aString != start);

        if (*aString == kDotChar)
        {
            // IPv6 address contains an embedded IPv4 address.
            aString = start;
            hasIp4  = true;
            endIndex -= Ip4::Address::kSize / sizeof(uint16_t);
            VerifyOrExit(index <= endIndex);
            break;
        }

        VerifyOrExit((*aString == kColonChar) || (*aString == kNullChar));

        VerifyOrExit(index < endIndex);
        mFields.m16[index++] = HostSwap16(static_cast<uint16_t>(value));

        if (*aString == kColonChar)
        {
            aString++;

            if (*aString == kColonChar)
            {
                VerifyOrExit(colonIndex == kInvalidIndex);
                colonIndex = index;
                aString++;
            }
        }
    }

    if (index < endIndex)
    {
        uint8_t wordsToCopy;

        VerifyOrExit(colonIndex != kInvalidIndex);

        wordsToCopy = index - colonIndex;

        memmove(&mFields.m16[endIndex - wordsToCopy], &mFields.m16[colonIndex], wordsToCopy * sizeof(uint16_t));
        memset(&mFields.m16[colonIndex], 0, (endIndex - index) * sizeof(uint16_t));
    }

    if (hasIp4)
    {
        Ip4::Address ip4Addr;

        SuccessOrExit(error = ip4Addr.FromString(aString));
        memcpy(GetArrayEnd(mFields.m8) - Ip4::Address::kSize, ip4Addr.GetBytes(), Ip4::Address::kSize);
    }

    error = kErrorNone;

exit:
    return error;
}

Address::InfoString Address::ToString(void) const
{
    InfoString string;

    ToString(string);

    return string;
}

void Address::ToString(char *aBuffer, uint16_t aSize) const
{
    StringWriter writer(aBuffer, aSize);
    ToString(writer);
}

void Address::ToString(StringWriter &aWriter) const
{
    AppendHexWords(aWriter, static_cast<uint8_t>(GetArrayLength(mFields.m16)));
}

void Address::AppendHexWords(StringWriter &aWriter, uint8_t aLength) const
{
    // Appends the first `aLength` elements in `mFields.m16[]` array
    // as hex words.

    for (uint8_t index = 0; index < aLength; index++)
    {
        if (index > 0)
        {
            aWriter.Append(":");
        }

        aWriter.Append("%x", HostSwap16(mFields.m16[index]));
    }
}

const Address &Address::GetLinkLocalAllNodesMulticast(void)
{
    return AsCoreType(&Netif::kLinkLocalAllNodesMulticastAddress.mAddress);
}

const Address &Address::GetLinkLocalAllRoutersMulticast(void)
{
    return AsCoreType(&Netif::kLinkLocalAllRoutersMulticastAddress.mAddress);
}

const Address &Address::GetRealmLocalAllNodesMulticast(void)
{
    return AsCoreType(&Netif::kRealmLocalAllNodesMulticastAddress.mAddress);
}

const Address &Address::GetRealmLocalAllRoutersMulticast(void)
{
    return AsCoreType(&Netif::kRealmLocalAllRoutersMulticastAddress.mAddress);
}

const Address &Address::GetRealmLocalAllMplForwarders(void)
{
    return AsCoreType(&Netif::kRealmLocalAllMplForwardersMulticastAddress.mAddress);
}

} // namespace Ip6
} // namespace ot
