/*
 *  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 the Thread IPv6 global addresses configuration utilities.
 */

#include "slaac_address.hpp"

#if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE

#include "common/array.hpp"
#include "common/code_utils.hpp"
#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/random.hpp"
#include "common/settings.hpp"
#include "crypto/sha256.hpp"
#include "net/ip6_address.hpp"

namespace ot {
namespace Utils {

RegisterLogModule("Slaac");

Slaac::Slaac(Instance &aInstance)
    : InstanceLocator(aInstance)
    , mEnabled(true)
    , mFilter(nullptr)
{
    memset(mAddresses, 0, sizeof(mAddresses));
}

void Slaac::Enable(void)
{
    VerifyOrExit(!mEnabled);

    LogInfo("Enabling");
    mEnabled = true;
    Update(kModeAdd);

exit:
    return;
}

void Slaac::Disable(void)
{
    VerifyOrExit(mEnabled);

    LogInfo("Disabling");
    mEnabled = false;
    Update(kModeRemove);

exit:
    return;
}

void Slaac::SetFilter(otIp6SlaacPrefixFilter aFilter)
{
    VerifyOrExit(aFilter != mFilter);

    mFilter = aFilter;
    LogInfo("Filter %s", (mFilter != nullptr) ? "updated" : "disabled");

    VerifyOrExit(mEnabled);
    Update(kModeAdd | kModeRemove);

exit:
    return;
}

bool Slaac::ShouldFilter(const Ip6::Prefix &aPrefix) const
{
    return (mFilter != nullptr) && mFilter(&GetInstance(), &aPrefix);
}

void Slaac::HandleNotifierEvents(Events aEvents)
{
    UpdateMode mode = kModeNone;

    VerifyOrExit(mEnabled);

    if (aEvents.Contains(kEventThreadNetdataChanged))
    {
        mode |= kModeAdd | kModeRemove;
    }

    if (aEvents.Contains(kEventIp6AddressRemoved))
    {
        // When an IPv6 address is removed, we ensure to check if a SLAAC address
        // needs to be added (replacing the removed address).
        //
        // Note that if an address matching a newly added on-mesh prefix (with
        // SLAAC flag) is already present (e.g., user previously added an address
        // with same prefix), the SLAAC module will not add a SLAAC address with same
        // prefix. So on IPv6 address removal event, we check if SLAAC module need
        // to add any addresses.

        mode |= kModeAdd;
    }

    if (mode != kModeNone)
    {
        Update(mode);
    }

exit:
    return;
}

bool Slaac::DoesConfigMatchNetifAddr(const NetworkData::OnMeshPrefixConfig &aConfig,
                                     const Ip6::Netif::UnicastAddress &     aAddr)
{
    return (((aConfig.mOnMesh && (aAddr.mPrefixLength == aConfig.mPrefix.mLength)) ||
             (!aConfig.mOnMesh && (aAddr.mPrefixLength == 128))) &&
            (aAddr.GetAddress().MatchesPrefix(aConfig.GetPrefix())));
}

void Slaac::Update(UpdateMode aMode)
{
    NetworkData::Iterator           iterator;
    NetworkData::OnMeshPrefixConfig config;
    bool                            found;

    if (aMode & kModeRemove)
    {
        // If enabled, remove any SLAAC addresses with no matching on-mesh prefix,
        // otherwise (when disabled) remove all previously added SLAAC addresses.

        for (Ip6::Netif::UnicastAddress &slaacAddr : mAddresses)
        {
            if (!slaacAddr.mValid)
            {
                continue;
            }

            found = false;

            if (mEnabled)
            {
                iterator = NetworkData::kIteratorInit;

                while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, config) == kErrorNone)
                {
                    if (config.mDp)
                    {
                        // Skip domain prefix which is processed in MLE.
                        continue;
                    }

                    if (config.mSlaac && !ShouldFilter(config.GetPrefix()) &&
                        DoesConfigMatchNetifAddr(config, slaacAddr))
                    {
                        found = true;
                        break;
                    }
                }
            }

            if (!found)
            {
                LogInfo("Removing address %s", slaacAddr.GetAddress().ToString().AsCString());

                Get<ThreadNetif>().RemoveUnicastAddress(slaacAddr);
                slaacAddr.mValid = false;
            }
        }
    }

    if ((aMode & kModeAdd) && mEnabled)
    {
        // Generate and add SLAAC addresses for any newly added on-mesh prefixes.

        iterator = NetworkData::kIteratorInit;

        while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, config) == kErrorNone)
        {
            Ip6::Prefix &prefix = config.GetPrefix();

            if (config.mDp || !config.mSlaac || ShouldFilter(prefix))
            {
                continue;
            }

            found = false;

            for (const Ip6::Netif::UnicastAddress &netifAddr : Get<ThreadNetif>().GetUnicastAddresses())
            {
                if (DoesConfigMatchNetifAddr(config, netifAddr))
                {
                    found = true;
                    break;
                }
            }

            if (!found)
            {
                bool added = false;

                for (Ip6::Netif::UnicastAddress &slaacAddr : mAddresses)
                {
                    if (slaacAddr.mValid)
                    {
                        continue;
                    }

                    slaacAddr.InitAsSlaacOrigin(config.mOnMesh ? prefix.mLength : 128, config.mPreferred);
                    slaacAddr.GetAddress().SetPrefix(prefix);

                    IgnoreError(GenerateIid(slaacAddr));

                    LogInfo("Adding address %s", slaacAddr.GetAddress().ToString().AsCString());

                    Get<ThreadNetif>().AddUnicastAddress(slaacAddr);

                    added = true;
                    break;
                }

                if (!added)
                {
                    LogWarn("Failed to add - max %d addresses supported and already in use",
                            GetArrayLength(mAddresses));
                }
            }
        }
    }
}

Error Slaac::GenerateIid(Ip6::Netif::UnicastAddress &aAddress,
                         uint8_t *                   aNetworkId,
                         uint8_t                     aNetworkIdLength,
                         uint8_t *                   aDadCounter) const
{
    /*
     *  This method generates a semantically opaque IID per RFC 7217.
     *
     * RID = F(Prefix, Net_Iface, Network_ID, DAD_Counter, secret_key)
     *
     *  - RID is random (but stable) Identifier.
     *  - For pseudo-random function `F()` SHA-256 is used in this method.
     *  - `Net_Iface` is set to constant string "wpan".
     *  - `Network_ID` is not used if `aNetworkId` is `nullptr` (optional per RF-7217).
     *  - The `secret_key` is randomly generated on first use (using true
     *    random number generator) and saved in non-volatile settings for
     *    future use.
     *
     */

    Error                error      = kErrorFailed;
    const uint8_t        netIface[] = {'w', 'p', 'a', 'n'};
    uint8_t              dadCounter = aDadCounter ? *aDadCounter : 0;
    IidSecretKey         secretKey;
    Crypto::Sha256       sha256;
    Crypto::Sha256::Hash hash;

    static_assert(sizeof(hash) >= Ip6::InterfaceIdentifier::kSize,
                  "SHA-256 hash size is too small to use as IPv6 address IID");

    GetIidSecretKey(secretKey);

    for (uint16_t count = 0; count < kMaxIidCreationAttempts; count++, dadCounter++)
    {
        sha256.Start();
        sha256.Update(aAddress.mAddress.mFields.m8, BitVectorBytes(aAddress.mPrefixLength));

        if (aNetworkId)
        {
            sha256.Update(aNetworkId, aNetworkIdLength);
        }

        sha256.Update(netIface);
        sha256.Update(dadCounter);
        sha256.Update(secretKey);
        sha256.Finish(hash);

        aAddress.GetAddress().GetIid().SetBytes(hash.GetBytes());

        // If the IID is reserved, try again with a new dadCounter
        if (aAddress.GetAddress().GetIid().IsReserved())
        {
            continue;
        }

        if (aDadCounter)
        {
            *aDadCounter = dadCounter;
        }

        // Exit and return the address if the IID is not reserved,
        ExitNow(error = kErrorNone);
    }

    LogWarn("Failed to generate a non-reserved IID after %d attempts", kMaxIidCreationAttempts);

exit:
    return error;
}

void Slaac::GetIidSecretKey(IidSecretKey &aKey) const
{
    Error error;

    error = Get<Settings>().Read<Settings::SlaacIidSecretKey>(aKey);
    VerifyOrExit(error != kErrorNone);

    // If there is no previously saved secret key, generate
    // a random one and save it.

    error = Random::Crypto::FillBuffer(aKey.m8, sizeof(IidSecretKey));

    if (error != kErrorNone)
    {
        IgnoreError(Random::Crypto::FillBuffer(aKey.m8, sizeof(IidSecretKey)));
    }

    IgnoreError(Get<Settings>().Save<Settings::SlaacIidSecretKey>(aKey));

    LogInfo("Generated and saved secret key");

exit:
    return;
}

} // namespace Utils
} // namespace ot

#endif // OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
