/*
 *  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 network interfaces.
 */
#include <openthread/config.h>

#include "netif.hpp"

#include "openthread-instance.h"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/message.hpp"
#include "net/ip6.hpp"

namespace ot {
namespace Ip6 {

Netif::Netif(Ip6 &aIp6, int8_t aInterfaceId):
    Ip6Locator(aIp6),
    mCallbacks(NULL),
    mUnicastAddresses(NULL),
    mMulticastAddresses(NULL),
    mInterfaceId(aInterfaceId),
    mAllRoutersSubscribed(false),
    mMulticastPromiscuous(false),
    mStateChangedTask(aIp6.mTaskletScheduler, &Netif::HandleStateChangedTask, this),
    mNext(NULL),
    mStateChangedFlags(0)
{
#if OPENTHREAD_CONFIG_NEST_STAY_SUBSCRIBED_TO_ALL_ROUTERS_MULTICAST_ADDR
    mAllRoutersSubscribed = true;
#endif

    for (size_t i = 0; i < sizeof(mExtUnicastAddresses) / sizeof(mExtUnicastAddresses[0]); i++)
    {
        // To mark the address as unused/available, set the `mNext` to point back to itself.
        mExtUnicastAddresses[i].mNext = &mExtUnicastAddresses[i];
    }

    for (size_t i = 0; i < sizeof(mExtMulticastAddresses) / sizeof(mExtMulticastAddresses[0]); i++)
    {
        // To mark the address as unused/available, set the `mNext` to point back to itself.
        mExtMulticastAddresses[i].mNext = &mExtMulticastAddresses[i];
    }
}

otError Netif::RegisterCallback(NetifCallback &aCallback)
{
    otError error = OT_ERROR_NONE;

    for (NetifCallback *cur = mCallbacks; cur; cur = cur->mNext)
    {
        if (cur == &aCallback)
        {
            ExitNow(error = OT_ERROR_ALREADY);
        }
    }

    aCallback.mNext = mCallbacks;
    mCallbacks = &aCallback;

exit:
    return error;
}

otError Netif::RemoveCallback(NetifCallback &aCallback)
{
    otError error = OT_ERROR_ALREADY;
    NetifCallback *prev = NULL;

    for (NetifCallback *cur = mCallbacks; cur; cur = cur->mNext)
    {
        if (cur == &aCallback)
        {
            if (prev)
            {
                prev->mNext = cur->mNext;
            }
            else
            {
                mCallbacks = mCallbacks->mNext;
            }

            cur->mNext = NULL;
            error = OT_ERROR_NONE;
            break;
        }

        prev = cur;
    }

    return error;
}

bool Netif::IsMulticastSubscribed(const Address &aAddress) const
{
    bool rval = false;

    if (aAddress.IsLinkLocalAllNodesMulticast() || aAddress.IsRealmLocalAllNodesMulticast() ||
        aAddress.IsRealmLocalAllMplForwarders())
    {
        ExitNow(rval = true);
    }
    else if (aAddress.IsLinkLocalAllRoutersMulticast() || aAddress.IsRealmLocalAllRoutersMulticast())
    {
        ExitNow(rval = mAllRoutersSubscribed);
    }

    for (NetifMulticastAddress *cur = mMulticastAddresses; cur; cur = cur->GetNext())
    {
        if (memcmp(&cur->mAddress, &aAddress, sizeof(cur->mAddress)) == 0)
        {
            ExitNow(rval = true);
        }
    }

exit:
    return rval;
}

otError Netif::SubscribeMulticast(NetifMulticastAddress &aAddress)
{
    otError error = OT_ERROR_NONE;

    for (NetifMulticastAddress *cur = mMulticastAddresses; cur; cur = cur->GetNext())
    {
        if (cur == &aAddress)
        {
            ExitNow(error = OT_ERROR_ALREADY);
        }
    }

    aAddress.mNext = mMulticastAddresses;
    mMulticastAddresses = &aAddress;

exit:
    return error;
}

otError Netif::UnsubscribeMulticast(const NetifMulticastAddress &aAddress)
{
    otError error = OT_ERROR_NONE;

    if (mMulticastAddresses == &aAddress)
    {
        mMulticastAddresses = mMulticastAddresses->GetNext();
        ExitNow();
    }
    else if (mMulticastAddresses != NULL)
    {
        for (NetifMulticastAddress *cur = mMulticastAddresses; cur->GetNext(); cur = cur->GetNext())
        {
            if (cur->mNext == &aAddress)
            {
                cur->mNext = aAddress.mNext;
                ExitNow();
            }
        }
    }

    ExitNow(error = OT_ERROR_NOT_FOUND);

exit:
    return error;
}

otError Netif::SubscribeExternalMulticast(const Address &aAddress)
{
    otError error = OT_ERROR_NONE;
    NetifMulticastAddress *entry;
    size_t num = sizeof(mExtMulticastAddresses) / sizeof(mExtMulticastAddresses[0]);

    if (IsMulticastSubscribed(aAddress))
    {
        ExitNow(error = OT_ERROR_ALREADY);
    }

    // Find an available entry in the `mExtMulticastAddresses` array.
    for (entry = &mExtMulticastAddresses[0]; num > 0; num--, entry++)
    {
        // In an unused/available entry, `mNext` points back to the entry itself.
        if (entry->mNext == entry)
        {
            break;
        }
    }

    VerifyOrExit(num > 0, error = OT_ERROR_NO_BUFS);

    // Copy the address into the available entry and add it to linked-list.
    entry->mAddress = aAddress;
    entry->mNext = mMulticastAddresses;
    mMulticastAddresses = entry;

exit:
    return error;
}

otError Netif::UnsubscribeExternalMulticast(const Address &aAddress)
{
    otError error = OT_ERROR_NONE;
    NetifMulticastAddress *entry;
    NetifMulticastAddress *last = NULL;
    size_t num = sizeof(mExtMulticastAddresses) / sizeof(mExtMulticastAddresses[0]);

    for (entry = mMulticastAddresses; entry; entry = entry->GetNext())
    {
        if (memcmp(&entry->mAddress, &aAddress, sizeof(otIp6Address)) == 0)
        {
            VerifyOrExit((entry >= &mExtMulticastAddresses[0]) && (entry < &mExtMulticastAddresses[num]),
                         error = OT_ERROR_INVALID_ARGS);

            if (last)
            {
                last->mNext = entry->GetNext();
            }
            else
            {
                mMulticastAddresses = entry->GetNext();
            }

            break;
        }

        last = entry;
    }

    VerifyOrExit(entry != NULL, error = OT_ERROR_NOT_FOUND);

    // To mark the address entry as unused/available, set the `mNext` pointer back to the entry itself.
    entry->mNext = entry;

exit:
    return error;
}

void Netif::UnsubscribeAllExternalMulticastAddresses(void)
{
    size_t num = sizeof(mExtMulticastAddresses) / sizeof(mExtMulticastAddresses[0]);

    for (NetifMulticastAddress *entry = &mExtMulticastAddresses[0]; num > 0; num--, entry++)
    {
        // In unused entries, the `mNext` points back to the entry itself.
        if (entry->mNext != entry)
        {
            UnsubscribeExternalMulticast(*static_cast<Address *>(&entry->mAddress));
        }
    }
}

otError Netif::AddUnicastAddress(NetifUnicastAddress &aAddress)
{
    otError error = OT_ERROR_NONE;

    for (NetifUnicastAddress *cur = mUnicastAddresses; cur; cur = cur->GetNext())
    {
        if (cur == &aAddress)
        {
            ExitNow(error = OT_ERROR_ALREADY);
        }
    }

    aAddress.mNext = mUnicastAddresses;
    mUnicastAddresses = &aAddress;

    SetStateChangedFlags(aAddress.mRloc ? OT_CHANGED_THREAD_RLOC_ADDED : OT_CHANGED_IP6_ADDRESS_ADDED);

exit:
    return error;
}

otError Netif::RemoveUnicastAddress(const NetifUnicastAddress &aAddress)
{
    otError error = OT_ERROR_NONE;

    if (mUnicastAddresses == &aAddress)
    {
        mUnicastAddresses = mUnicastAddresses->GetNext();
        ExitNow();
    }
    else if (mUnicastAddresses != NULL)
    {
        for (NetifUnicastAddress *cur = mUnicastAddresses; cur->GetNext(); cur = cur->GetNext())
        {
            if (cur->mNext == &aAddress)
            {
                cur->mNext = aAddress.mNext;
                ExitNow();
            }
        }
    }

    ExitNow(error = OT_ERROR_NOT_FOUND);

exit:

    if (error != OT_ERROR_NOT_FOUND)
    {
        SetStateChangedFlags(aAddress.mRloc ? OT_CHANGED_THREAD_RLOC_REMOVED : OT_CHANGED_IP6_ADDRESS_REMOVED);
    }

    return error;
}

otError Netif::AddExternalUnicastAddress(const NetifUnicastAddress &aAddress)
{
    otError error = OT_ERROR_NONE;
    NetifUnicastAddress *entry;
    size_t num = sizeof(mExtUnicastAddresses) / sizeof(mExtUnicastAddresses[0]);

    for (entry = mUnicastAddresses; entry; entry = entry->GetNext())
    {
        if (memcmp(&entry->mAddress, &aAddress.mAddress, sizeof(otIp6Address)) == 0)
        {
            VerifyOrExit((entry >= &mExtUnicastAddresses[0]) && (entry < &mExtUnicastAddresses[num]),
                         error = OT_ERROR_INVALID_ARGS);

            entry->mPrefixLength = aAddress.mPrefixLength;
            entry->mPreferred = aAddress.mPreferred;
            entry->mValid = aAddress.mValid;
            ExitNow();
        }
    }

    // Find an available entry in the `mExtUnicastAddresses` array.
    for (entry = &mExtUnicastAddresses[0]; num > 0; num--, entry++)
    {
        // In an unused/available entry, `mNext` points back to the entry itself.
        if (entry->mNext == entry)
        {
            break;
        }
    }

    VerifyOrExit(num > 0, error = OT_ERROR_NO_BUFS);

    // Copy the new address into the available entry and insert it in linked-list.
    *entry = aAddress;
    entry->mNext = mUnicastAddresses;
    mUnicastAddresses = entry;

    SetStateChangedFlags(OT_CHANGED_IP6_ADDRESS_ADDED);

exit:
    return error;
}

otError Netif::RemoveExternalUnicastAddress(const Address &aAddress)
{
    otError error = OT_ERROR_NONE;
    NetifUnicastAddress *entry;
    NetifUnicastAddress *last = NULL;
    size_t num = sizeof(mExtUnicastAddresses) / sizeof(mExtUnicastAddresses[0]);

    for (entry = mUnicastAddresses; entry; entry = entry->GetNext())
    {
        if (memcmp(&entry->mAddress, &aAddress, sizeof(otIp6Address)) == 0)
        {
            VerifyOrExit((entry >= &mExtUnicastAddresses[0]) && (entry < &mExtUnicastAddresses[num]),
                         error = OT_ERROR_INVALID_ARGS);

            if (last)
            {
                last->mNext = entry->mNext;
            }
            else
            {
                mUnicastAddresses = entry->GetNext();
            }

            break;
        }

        last = entry;
    }

    VerifyOrExit(entry != NULL, error = OT_ERROR_NOT_FOUND);

    // To mark the address entry as unused/available, set the `mNext` pointer back to the entry itself.
    entry->mNext = entry;

    SetStateChangedFlags(OT_CHANGED_IP6_ADDRESS_REMOVED);

exit:
    return error;
}

void Netif::RemoveAllExternalUnicastAddresses(void)
{
    size_t num = sizeof(mExtUnicastAddresses) / sizeof(mExtUnicastAddresses[0]);

    for (NetifUnicastAddress *entry = &mExtUnicastAddresses[0]; num > 0; num--, entry++)
    {
        // In unused entries, the `mNext` points back to the entry itself.
        if (entry->mNext != entry)
        {
            RemoveExternalUnicastAddress(*static_cast<Address *>(&entry->mAddress));
        }
    }
}

bool Netif::IsUnicastAddress(const Address &aAddress) const
{
    bool rval = false;

    for (const NetifUnicastAddress *cur = mUnicastAddresses; cur; cur = cur->GetNext())
    {
        if (cur->GetAddress() == aAddress)
        {
            ExitNow(rval = true);
        }
    }

exit:
    return rval;
}

void Netif::SetStateChangedFlags(uint32_t aFlags)
{
    mStateChangedFlags |= aFlags;
    mStateChangedTask.Post();
}

void Netif::HandleStateChangedTask(Tasklet &aTasklet)
{
    GetOwner(aTasklet).HandleStateChangedTask();
}

void Netif::HandleStateChangedTask(void)
{
    uint32_t flags = mStateChangedFlags;

    mStateChangedFlags = 0;

    for (NetifCallback *callback = mCallbacks; callback; callback = callback->mNext)
    {
        callback->Callback(flags);
    }
}

Netif &Netif::GetOwner(const Context &aContext)
{
#if OPENTHREAD_ENABLE_MULTIPLE_INSTANCES
    Netif &netif = *static_cast<Netif *>(aContext.GetContext());
#else
    Netif &netif = otGetThreadNetif();
    OT_UNUSED_VARIABLE(aContext);
#endif
    return netif;
}

}  // namespace Ip6
}  // namespace ot
