/*
 *  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 networking.
 */

#define WPP_NAME "ip6.tmh"

#include "ip6.hpp"

#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/instance.hpp"
#include "common/logging.hpp"
#include "common/message.hpp"
#include "common/owner-locator.hpp"
#include "net/icmp6.hpp"
#include "net/ip6_address.hpp"
#include "net/ip6_routes.hpp"
#include "net/netif.hpp"
#include "net/udp6.hpp"
#include "thread/mle.hpp"

namespace ot {
namespace Ip6 {

Ip6::Ip6(Instance &aInstance)
    : InstanceLocator(aInstance)
    , mForwardingEnabled(false)
    , mIsReceiveIp6FilterEnabled(false)
    , mReceiveIp6DatagramCallback(NULL)
    , mReceiveIp6DatagramCallbackContext(NULL)
    , mNetifListHead(NULL)
    , mSendQueue()
    , mSendQueueTask(aInstance, HandleSendQueue, this)
    , mRoutes(aInstance)
    , mIcmp(aInstance)
    , mUdp(aInstance)
    , mMpl(aInstance)
{
}

Message *Ip6::NewMessage(uint16_t aReserved, uint8_t aPriority)
{
    return GetInstance().GetMessagePool().New(
        Message::kTypeIp6, sizeof(Header) + sizeof(HopByHopHeader) + sizeof(OptionMpl) + aReserved, aPriority);
}

uint16_t Ip6::UpdateChecksum(uint16_t aChecksum, const Address &aAddress)
{
    return Message::UpdateChecksum(aChecksum, aAddress.mFields.m8, sizeof(aAddress));
}

uint16_t Ip6::ComputePseudoheaderChecksum(const Address &aSource,
                                          const Address &aDestination,
                                          uint16_t       aLength,
                                          IpProto        aProto)
{
    uint16_t checksum;

    checksum = Message::UpdateChecksum(0, aLength);
    checksum = Message::UpdateChecksum(checksum, static_cast<uint16_t>(aProto));
    checksum = UpdateChecksum(checksum, aSource);
    checksum = UpdateChecksum(checksum, aDestination);

    return checksum;
}

void Ip6::SetReceiveDatagramCallback(otIp6ReceiveCallback aCallback, void *aCallbackContext)
{
    mReceiveIp6DatagramCallback        = aCallback;
    mReceiveIp6DatagramCallbackContext = aCallbackContext;
}

otError Ip6::AddMplOption(Message &aMessage, Header &aHeader)
{
    otError        error = OT_ERROR_NONE;
    HopByHopHeader hbhHeader;
    OptionMpl      mplOption;
    OptionPadN     padOption;

    hbhHeader.SetNextHeader(aHeader.GetNextHeader());
    hbhHeader.SetLength(0);
    mMpl.InitOption(mplOption, aHeader.GetSource());

    // Mpl option may require two bytes padding.
    if ((mplOption.GetTotalLength() + sizeof(hbhHeader)) % 8)
    {
        padOption.Init(2);
        SuccessOrExit(error = aMessage.Prepend(&padOption, padOption.GetTotalLength()));
    }

    SuccessOrExit(error = aMessage.Prepend(&mplOption, mplOption.GetTotalLength()));
    SuccessOrExit(error = aMessage.Prepend(&hbhHeader, sizeof(hbhHeader)));
    aHeader.SetPayloadLength(aHeader.GetPayloadLength() + sizeof(hbhHeader) + sizeof(mplOption));
    aHeader.SetNextHeader(kProtoHopOpts);
exit:
    return error;
}

otError Ip6::AddTunneledMplOption(Message &aMessage, Header &aHeader, MessageInfo &aMessageInfo)
{
    otError                    error = OT_ERROR_NONE;
    Header                     tunnelHeader;
    const NetifUnicastAddress *source;
    MessageInfo                messageInfo(aMessageInfo);

    // Use IP-in-IP encapsulation (RFC2473) and ALL_MPL_FORWARDERS address.
    memset(&messageInfo.GetPeerAddr(), 0, sizeof(Address));
    messageInfo.GetPeerAddr().mFields.m16[0] = HostSwap16(0xff03);
    messageInfo.GetPeerAddr().mFields.m16[7] = HostSwap16(0x00fc);

    tunnelHeader.Init();
    tunnelHeader.SetHopLimit(static_cast<uint8_t>(kDefaultHopLimit));
    tunnelHeader.SetPayloadLength(aHeader.GetPayloadLength() + sizeof(tunnelHeader));
    tunnelHeader.SetDestination(messageInfo.GetPeerAddr());
    tunnelHeader.SetNextHeader(kProtoIp6);

    VerifyOrExit((source = SelectSourceAddress(messageInfo)) != NULL, error = OT_ERROR_INVALID_SOURCE_ADDRESS);

    tunnelHeader.SetSource(source->GetAddress());

    SuccessOrExit(error = AddMplOption(aMessage, tunnelHeader));
    SuccessOrExit(error = aMessage.Prepend(&tunnelHeader, sizeof(tunnelHeader)));

exit:
    return error;
}

otError Ip6::InsertMplOption(Message &aMessage, Header &aIp6Header, MessageInfo &aMessageInfo)
{
    otError error = OT_ERROR_NONE;

    VerifyOrExit(aIp6Header.GetDestination().IsMulticast() &&
                 aIp6Header.GetDestination().GetScope() >= Address::kRealmLocalScope);

    if (aIp6Header.GetDestination().IsRealmLocalMulticast())
    {
        aMessage.RemoveHeader(sizeof(aIp6Header));

        if (aIp6Header.GetNextHeader() == kProtoHopOpts)
        {
            HopByHopHeader hbh;
            uint16_t       hbhLength = 0;
            OptionMpl      mplOption;

            // read existing hop-by-hop option header
            aMessage.Read(0, sizeof(hbh), &hbh);
            hbhLength = (hbh.GetLength() + 1) * 8;

            VerifyOrExit(hbhLength <= aIp6Header.GetPayloadLength(), error = OT_ERROR_PARSE);

            // increase existing hop-by-hop option header length by 8 bytes
            hbh.SetLength(hbh.GetLength() + 1);
            aMessage.Write(0, sizeof(hbh), &hbh);

            // make space for MPL Option + padding by shifting hop-by-hop option header
            SuccessOrExit(error = aMessage.Prepend(NULL, 8));
            aMessage.CopyTo(8, 0, hbhLength, aMessage);

            // insert MPL Option
            mMpl.InitOption(mplOption, aIp6Header.GetSource());
            aMessage.Write(hbhLength, mplOption.GetTotalLength(), &mplOption);

            // insert Pad Option (if needed)
            if (mplOption.GetTotalLength() % 8)
            {
                OptionPadN padOption;
                padOption.Init(8 - (mplOption.GetTotalLength() % 8));
                aMessage.Write(hbhLength + mplOption.GetTotalLength(), padOption.GetTotalLength(), &padOption);
            }

            // increase IPv6 Payload Length
            aIp6Header.SetPayloadLength(aIp6Header.GetPayloadLength() + 8);
        }
        else
        {
            SuccessOrExit(error = AddMplOption(aMessage, aIp6Header));
        }

        SuccessOrExit(error = aMessage.Prepend(&aIp6Header, sizeof(aIp6Header)));
    }
    else
    {
        if (aIp6Header.GetDestination().IsMulticastLargerThanRealmLocal() &&
            GetInstance().GetThreadNetif().GetMle().HasSleepyChildrenSubscribed(aIp6Header.GetDestination()))
        {
            Message *messageCopy = NULL;

            if ((messageCopy = aMessage.Clone()) != NULL)
            {
                HandleDatagram(*messageCopy, NULL, aMessageInfo.GetInterfaceId(), NULL, true);
                otLogInfoIp6(GetInstance(), "Message copy for indirect transmission to sleepy children");
            }
            else
            {
                otLogWarnIp6(GetInstance(),
                             "No enough buffer for message copy for indirect transmission to sleepy children");
            }
        }

        SuccessOrExit(error = AddTunneledMplOption(aMessage, aIp6Header, aMessageInfo));
    }

exit:
    return error;
}

otError Ip6::RemoveMplOption(Message &aMessage)
{
    otError        error = OT_ERROR_NONE;
    Header         ip6Header;
    HopByHopHeader hbh;
    uint16_t       offset;
    uint16_t       endOffset;
    uint16_t       mplOffset = 0;
    uint8_t        mplLength = 0;
    bool           remove    = false;

    offset = 0;
    aMessage.Read(offset, sizeof(ip6Header), &ip6Header);
    offset += sizeof(ip6Header);
    VerifyOrExit(ip6Header.GetNextHeader() == kProtoHopOpts);

    aMessage.Read(offset, sizeof(hbh), &hbh);
    endOffset = offset + (hbh.GetLength() + 1) * 8;
    VerifyOrExit(aMessage.GetLength() >= endOffset, error = OT_ERROR_PARSE);

    offset += sizeof(hbh);

    while (offset < endOffset)
    {
        OptionHeader option;

        aMessage.Read(offset, sizeof(option), &option);

        switch (option.GetType())
        {
        case OptionMpl::kType:
            mplOffset = offset;
            mplLength = option.GetLength();

            if (mplOffset == sizeof(ip6Header) + sizeof(hbh) && hbh.GetLength() == 0)
            {
                // first and only IPv6 Option, remove IPv6 HBH Option header
                remove = true;
            }
            else if (mplOffset + 8 == endOffset)
            {
                // last IPv6 Option, remove last 8 bytes
                remove = true;
            }

            offset += sizeof(option) + option.GetLength();
            break;

        case OptionPad1::kType:
            offset += sizeof(OptionPad1);
            break;

        case OptionPadN::kType:
            offset += sizeof(option) + option.GetLength();
            break;

        default:
            // encountered another option, now just replace MPL Option with PadN
            remove = false;
            offset += sizeof(option) + option.GetLength();
            break;
        }
    }

    // verify that IPv6 Options header is properly formed
    VerifyOrExit(offset == endOffset, error = OT_ERROR_PARSE);

    if (remove)
    {
        // last IPv6 Option, shrink HBH Option header
        uint8_t buf[8];

        offset = endOffset - sizeof(buf);

        while (offset >= sizeof(buf))
        {
            aMessage.Read(offset - sizeof(buf), sizeof(buf), buf);
            aMessage.Write(offset, sizeof(buf), buf);
            offset -= sizeof(buf);
        }

        aMessage.RemoveHeader(sizeof(buf));

        if (mplOffset == sizeof(ip6Header) + sizeof(hbh))
        {
            // remove entire HBH header
            ip6Header.SetNextHeader(hbh.GetNextHeader());
        }
        else
        {
            // update HBH header length
            hbh.SetLength(hbh.GetLength() - 1);
            aMessage.Write(sizeof(ip6Header), sizeof(hbh), &hbh);
        }

        ip6Header.SetPayloadLength(ip6Header.GetPayloadLength() - sizeof(buf));
        aMessage.Write(0, sizeof(ip6Header), &ip6Header);
    }
    else if (mplOffset != 0)
    {
        // replace MPL Option with PadN Option
        OptionPadN padOption;

        padOption.Init(sizeof(OptionHeader) + mplLength);
        aMessage.Write(mplOffset, padOption.GetTotalLength(), &padOption);
    }

exit:
    return error;
}

void Ip6::EnqueueDatagram(Message &aMessage)
{
    mSendQueue.Enqueue(aMessage);
    mSendQueueTask.Post();
}

otError Ip6::SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, IpProto aIpProto)
{
    otError                    error = OT_ERROR_NONE;
    Header                     header;
    uint16_t                   payloadLength = aMessage.GetLength();
    uint16_t                   checksum;
    const NetifUnicastAddress *source;

    header.Init();
    header.SetPayloadLength(payloadLength);
    header.SetNextHeader(aIpProto);
    header.SetHopLimit(aMessageInfo.mHopLimit ? aMessageInfo.mHopLimit : static_cast<uint8_t>(kDefaultHopLimit));

    if (aMessageInfo.GetSockAddr().IsUnspecified() || aMessageInfo.GetSockAddr().IsMulticast())
    {
        VerifyOrExit((source = SelectSourceAddress(aMessageInfo)) != NULL, error = OT_ERROR_INVALID_SOURCE_ADDRESS);
        header.SetSource(source->GetAddress());
    }
    else
    {
        header.SetSource(aMessageInfo.GetSockAddr());
    }

    header.SetDestination(aMessageInfo.GetPeerAddr());

    if (header.GetDestination().IsLinkLocal() || header.GetDestination().IsLinkLocalMulticast())
    {
        VerifyOrExit(aMessageInfo.GetInterfaceId() != 0, error = OT_ERROR_DROP);
    }

    if (aMessageInfo.GetPeerAddr().IsRealmLocalMulticast())
    {
        SuccessOrExit(error = AddMplOption(aMessage, header));
    }

    SuccessOrExit(error = aMessage.Prepend(&header, sizeof(header)));

    // compute checksum
    checksum = ComputePseudoheaderChecksum(header.GetSource(), header.GetDestination(), payloadLength, aIpProto);

    switch (aIpProto)
    {
    case kProtoUdp:
        SuccessOrExit(error = mUdp.UpdateChecksum(aMessage, checksum));
        break;

    case kProtoIcmp6:
        SuccessOrExit(error = mIcmp.UpdateChecksum(aMessage, checksum));
        break;

    default:
        break;
    }

    if (aMessageInfo.GetPeerAddr().IsMulticastLargerThanRealmLocal())
    {
        if (GetInstance().GetThreadNetif().GetMle().HasSleepyChildrenSubscribed(header.GetDestination()))
        {
            Message *messageCopy = NULL;

            if ((messageCopy = aMessage.Clone()) != NULL)
            {
                otLogInfoIp6(GetInstance(), "Message copy for indirect transmission to sleepy children");
                messageCopy->SetInterfaceId(aMessageInfo.GetInterfaceId());
                EnqueueDatagram(*messageCopy);
            }
            else
            {
                otLogWarnIp6(GetInstance(),
                             "No enough buffer for message copy for indirect transmission to sleepy children");
            }
        }

        SuccessOrExit(error = AddTunneledMplOption(aMessage, header, aMessageInfo));
    }

exit:

    if (error == OT_ERROR_NONE)
    {
        aMessage.SetInterfaceId(aMessageInfo.GetInterfaceId());
        EnqueueDatagram(aMessage);
    }

    return error;
}

void Ip6::HandleSendQueue(Tasklet &aTasklet)
{
    aTasklet.GetOwner<Ip6>().HandleSendQueue();
}

void Ip6::HandleSendQueue(void)
{
    Message *message;

    while ((message = mSendQueue.GetHead()) != NULL)
    {
        mSendQueue.Dequeue(*message);
        HandleDatagram(*message, NULL, message->GetInterfaceId(), NULL, false);
    }
}

otError Ip6::HandleOptions(Message &aMessage, Header &aHeader, bool &aForward)
{
    otError        error = OT_ERROR_NONE;
    HopByHopHeader hbhHeader;
    OptionHeader   optionHeader;
    uint16_t       endOffset;

    VerifyOrExit(aMessage.Read(aMessage.GetOffset(), sizeof(hbhHeader), &hbhHeader) == sizeof(hbhHeader),
                 error = OT_ERROR_DROP);
    endOffset = aMessage.GetOffset() + (hbhHeader.GetLength() + 1) * 8;

    VerifyOrExit(endOffset <= aMessage.GetLength(), error = OT_ERROR_DROP);

    aMessage.MoveOffset(sizeof(optionHeader));

    while (aMessage.GetOffset() < endOffset)
    {
        VerifyOrExit(aMessage.Read(aMessage.GetOffset(), sizeof(optionHeader), &optionHeader) == sizeof(optionHeader),
                     error = OT_ERROR_DROP);

        if (optionHeader.GetType() == OptionPad1::kType)
        {
            aMessage.MoveOffset(sizeof(OptionPad1));
            continue;
        }

        VerifyOrExit(aMessage.GetOffset() + sizeof(optionHeader) + optionHeader.GetLength() <= endOffset,
                     error = OT_ERROR_DROP);

        switch (optionHeader.GetType())
        {
        case OptionMpl::kType:
            SuccessOrExit(error = mMpl.ProcessOption(aMessage, aHeader.GetSource(), aForward));
            break;

        default:
            switch (optionHeader.GetAction())
            {
            case OptionHeader::kActionSkip:
                break;

            case OptionHeader::kActionDiscard:
                ExitNow(error = OT_ERROR_DROP);

            case OptionHeader::kActionForceIcmp:
                // TODO: send icmp error
                ExitNow(error = OT_ERROR_DROP);

            case OptionHeader::kActionIcmp:
                // TODO: send icmp error
                ExitNow(error = OT_ERROR_DROP);
            }

            break;
        }

        aMessage.MoveOffset(sizeof(optionHeader) + optionHeader.GetLength());
    }

exit:
    return error;
}

otError Ip6::HandleFragment(Message &aMessage)
{
    otError        error = OT_ERROR_NONE;
    FragmentHeader fragmentHeader;

    VerifyOrExit(aMessage.Read(aMessage.GetOffset(), sizeof(fragmentHeader), &fragmentHeader) == sizeof(fragmentHeader),
                 error = OT_ERROR_DROP);

    VerifyOrExit(fragmentHeader.GetOffset() == 0 && fragmentHeader.IsMoreFlagSet() == false, error = OT_ERROR_DROP);

    aMessage.MoveOffset(sizeof(fragmentHeader));

exit:
    return error;
}

otError Ip6::HandleExtensionHeaders(Message &aMessage,
                                    Header & aHeader,
                                    uint8_t &aNextHeader,
                                    bool     aForward,
                                    bool     aReceive)
{
    otError         error = OT_ERROR_NONE;
    ExtensionHeader extHeader;

    while (aReceive == true || aNextHeader == kProtoHopOpts)
    {
        VerifyOrExit(aMessage.Read(aMessage.GetOffset(), sizeof(extHeader), &extHeader) == sizeof(extHeader),
                     error = OT_ERROR_DROP);

        switch (aNextHeader)
        {
        case kProtoHopOpts:
            SuccessOrExit(error = HandleOptions(aMessage, aHeader, aForward));
            break;

        case kProtoFragment:
            SuccessOrExit(error = HandleFragment(aMessage));
            break;

        case kProtoDstOpts:
            SuccessOrExit(error = HandleOptions(aMessage, aHeader, aForward));
            break;

        case kProtoIp6:
            ExitNow();

        case kProtoRouting:
        case kProtoNone:
            ExitNow(error = OT_ERROR_DROP);

        default:
            ExitNow();
        }

        aNextHeader = static_cast<uint8_t>(extHeader.GetNextHeader());
    }

exit:
    return error;
}

otError Ip6::HandlePayload(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aIpProto)
{
    otError error = OT_ERROR_NONE;

    switch (aIpProto)
    {
    case kProtoUdp:
        ExitNow(error = mUdp.HandleMessage(aMessage, aMessageInfo));

    case kProtoIcmp6:
        ExitNow(error = mIcmp.HandleMessage(aMessage, aMessageInfo));
    }

exit:
    return error;
}

otError Ip6::ProcessReceiveCallback(const Message &    aMessage,
                                    const MessageInfo &aMessageInfo,
                                    uint8_t            aIpProto,
                                    bool               aFromNcpHost)
{
    otError  error       = OT_ERROR_NONE;
    Message *messageCopy = NULL;

    VerifyOrExit(aFromNcpHost == false, error = OT_ERROR_DROP);
    VerifyOrExit(mReceiveIp6DatagramCallback != NULL, error = OT_ERROR_NO_ROUTE);

    if (mIsReceiveIp6FilterEnabled)
    {
        // do not pass messages sent to an RLOC/ALOC
        VerifyOrExit(!aMessageInfo.GetSockAddr().IsRoutingLocator() &&
                         !aMessageInfo.GetSockAddr().IsAnycastRoutingLocator(),
                     error = OT_ERROR_NO_ROUTE);

        switch (aIpProto)
        {
        case kProtoIcmp6:
            if (mIcmp.ShouldHandleEchoRequest(aMessageInfo))
            {
                IcmpHeader icmp;
                aMessage.Read(aMessage.GetOffset(), sizeof(icmp), &icmp);

                // do not pass ICMP Echo Request messages
                VerifyOrExit(icmp.GetType() != IcmpHeader::kTypeEchoRequest, error = OT_ERROR_NO_ROUTE);
            }

            break;

        case kProtoUdp:
        {
            UdpHeader udp;
            aMessage.Read(aMessage.GetOffset(), sizeof(udp), &udp);

            switch (udp.GetDestinationPort())
            {
            case Mle::kUdpPort:

                // do not pass MLE messages
                if (aMessageInfo.GetSockAddr().IsLinkLocal() || aMessageInfo.GetSockAddr().IsLinkLocalMulticast())
                {
                    ExitNow(error = OT_ERROR_NO_ROUTE);
                }

                break;

            case kCoapUdpPort:

                // do not pass TMF messages
                if (GetInstance().GetThreadNetif().IsTmfMessage(aMessageInfo))
                {
                    ExitNow(error = OT_ERROR_NO_ROUTE);
                }

                break;

            default:
                break;
            }

            break;
        }

        default:
            break;
        }
    }

    // make a copy of the datagram to pass to host
    VerifyOrExit((messageCopy = aMessage.Clone()) != NULL, error = OT_ERROR_NO_BUFS);
    RemoveMplOption(*messageCopy);
    mReceiveIp6DatagramCallback(messageCopy, mReceiveIp6DatagramCallbackContext);

exit:

    switch (error)
    {
    case OT_ERROR_NO_BUFS:
        otLogWarnIp6(GetInstance(), "Failed to pass up message (len: %d) to host - out of message buffer.",
                     aMessage.GetLength());
        break;

    case OT_ERROR_DROP:
        otLogNoteIp6(GetInstance(), "Dropping message (len: %d) from local host since next hop is the host.",
                     aMessage.GetLength());
        break;

    default:
        break;
    }

    return error;
}

otError Ip6::SendRaw(Message &aMessage, int8_t aInterfaceId)
{
    otError     error = OT_ERROR_NONE;
    Header      header;
    MessageInfo messageInfo;
    bool        freed = false;

    SuccessOrExit(error = header.Init(aMessage));

    messageInfo.SetPeerAddr(header.GetSource());
    messageInfo.SetSockAddr(header.GetDestination());
    messageInfo.SetInterfaceId(aInterfaceId);
    messageInfo.SetHopLimit(header.GetHopLimit());
    messageInfo.SetLinkInfo(NULL);

    if (header.GetDestination().IsMulticast())
    {
        SuccessOrExit(error = InsertMplOption(aMessage, header, messageInfo));
    }

    error = HandleDatagram(aMessage, NULL, aInterfaceId, NULL, true);
    freed = true;

exit:

    if (!freed)
    {
        aMessage.Free();
    }

    return error;
}

otError Ip6::HandleDatagram(Message &   aMessage,
                            Netif *     aNetif,
                            int8_t      aInterfaceId,
                            const void *aLinkMessageInfo,
                            bool        aFromNcpHost)
{
    otError     error = OT_ERROR_NONE;
    MessageInfo messageInfo;
    Header      header;
    bool        receive              = false;
    bool        forward              = false;
    bool        tunnel               = false;
    bool        multicastPromiscuous = false;
    uint8_t     nextHeader;
    uint8_t     hopLimit;
    int8_t      forwardInterfaceId;

    SuccessOrExit(error = header.Init(aMessage));

    messageInfo.SetPeerAddr(header.GetSource());
    messageInfo.SetSockAddr(header.GetDestination());
    messageInfo.SetInterfaceId(aInterfaceId);
    messageInfo.SetHopLimit(header.GetHopLimit());
    messageInfo.SetLinkInfo(aLinkMessageInfo);

    // determine destination of packet
    if (header.GetDestination().IsMulticast())
    {
        if (aNetif != NULL)
        {
            if (aNetif->IsMulticastSubscribed(header.GetDestination()))
            {
                receive = true;
            }
            else if (aNetif->IsMulticastPromiscuousEnabled())
            {
                multicastPromiscuous = true;
            }

            if (header.GetDestination().IsMulticastLargerThanRealmLocal() &&
                GetInstance().GetThreadNetif().GetMle().HasSleepyChildrenSubscribed(header.GetDestination()))
            {
                forward = true;
            }
        }
        else
        {
            forward = true;
        }
    }
    else
    {
        if (IsUnicastAddress(header.GetDestination()))
        {
            receive = true;
        }
        else if (!header.GetDestination().IsLinkLocal())
        {
            forward = true;
        }
        else if (aNetif == NULL)
        {
            forward = true;
        }
    }

    aMessage.SetInterfaceId(aInterfaceId);
    aMessage.SetOffset(sizeof(header));

    // process IPv6 Extension Headers
    nextHeader = static_cast<uint8_t>(header.GetNextHeader());
    SuccessOrExit(error = HandleExtensionHeaders(aMessage, header, nextHeader, forward, receive));

    // process IPv6 Payload
    if (receive)
    {
        if (nextHeader == kProtoIp6)
        {
            // Remove encapsulating header.
            aMessage.RemoveHeader(aMessage.GetOffset());

            HandleDatagram(aMessage, aNetif, aInterfaceId, aLinkMessageInfo, aFromNcpHost);
            ExitNow(tunnel = true);
        }

        ProcessReceiveCallback(aMessage, messageInfo, nextHeader, aFromNcpHost);

        SuccessOrExit(error = HandlePayload(aMessage, messageInfo, nextHeader));
    }
    else if (multicastPromiscuous)
    {
        ProcessReceiveCallback(aMessage, messageInfo, nextHeader, aFromNcpHost);
    }

    if (forward)
    {
        forwardInterfaceId = FindForwardInterfaceId(messageInfo);

        if (forwardInterfaceId == 0)
        {
            // try passing to host
            SuccessOrExit(error = ProcessReceiveCallback(aMessage, messageInfo, nextHeader, aFromNcpHost));

            // the caller transfers custody in the success case, so free the aMessage here
            aMessage.Free();

            ExitNow();
        }

        if (aNetif != NULL)
        {
            VerifyOrExit(mForwardingEnabled, forward = false);
            header.SetHopLimit(header.GetHopLimit() - 1);
        }

        if (header.GetHopLimit() == 0)
        {
            // send time exceeded
            ExitNow(error = OT_ERROR_DROP);
        }
        else
        {
            hopLimit = header.GetHopLimit();
            aMessage.Write(Header::GetHopLimitOffset(), Header::GetHopLimitSize(), &hopLimit);

            // submit aMessage to interface
            VerifyOrExit((aNetif = GetNetifById(forwardInterfaceId)) != NULL, error = OT_ERROR_NO_ROUTE);
            SuccessOrExit(error = aNetif->SendMessage(aMessage));
        }
    }

exit:

    if (!tunnel && (error != OT_ERROR_NONE || !forward))
    {
        aMessage.Free();
    }

    return error;
}

int8_t Ip6::FindForwardInterfaceId(const MessageInfo &aMessageInfo)
{
    int8_t interfaceId;

    if (aMessageInfo.GetSockAddr().IsMulticast())
    {
        // multicast
        interfaceId = aMessageInfo.mInterfaceId;
    }
    else if (aMessageInfo.GetSockAddr().IsLinkLocal())
    {
        // on-link link-local address
        interfaceId = aMessageInfo.mInterfaceId;
    }
    else if ((interfaceId = GetOnLinkNetif(aMessageInfo.GetSockAddr())) > 0)
    {
        // on-link global address
        ;
    }
    else if ((interfaceId = mRoutes.Lookup(aMessageInfo.GetPeerAddr(), aMessageInfo.GetSockAddr())) > 0)
    {
        // route
        ;
    }
    else
    {
        interfaceId = 0;
    }

    return interfaceId;
}

otError Ip6::AddNetif(Netif &aNetif)
{
    otError error = OT_ERROR_NONE;
    Netif * netif;

    if (mNetifListHead == NULL)
    {
        mNetifListHead = &aNetif;
    }
    else
    {
        netif = mNetifListHead;

        do
        {
            if (netif == &aNetif || netif->mInterfaceId == aNetif.mInterfaceId)
            {
                ExitNow(error = OT_ERROR_ALREADY);
            }
        } while (netif->mNext);

        netif->mNext = &aNetif;
    }

    aNetif.mNext = NULL;

exit:
    return error;
}

otError Ip6::RemoveNetif(Netif &aNetif)
{
    otError error = OT_ERROR_NOT_FOUND;

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

    if (mNetifListHead == &aNetif)
    {
        mNetifListHead = aNetif.mNext;
    }
    else
    {
        for (Netif *netif = mNetifListHead; netif->mNext; netif = netif->mNext)
        {
            if (netif->mNext != &aNetif)
            {
                continue;
            }

            netif->mNext = aNetif.mNext;
            error        = OT_ERROR_NONE;
            break;
        }
    }

    aNetif.mNext = NULL;

exit:
    return error;
}

Netif *Ip6::GetNetifById(int8_t aInterfaceId)
{
    Netif *netif;

    for (netif = mNetifListHead; netif; netif = netif->mNext)
    {
        if (netif->GetInterfaceId() == aInterfaceId)
        {
            ExitNow();
        }
    }

exit:
    return netif;
}

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

    for (Netif *netif = mNetifListHead; netif; netif = netif->mNext)
    {
        rval = netif->IsUnicastAddress(aAddress);

        if (rval)
        {
            ExitNow();
        }
    }

exit:
    return rval;
}

const NetifUnicastAddress *Ip6::SelectSourceAddress(MessageInfo &aMessageInfo)
{
    Address *                  destination = &aMessageInfo.GetPeerAddr();
    int                        interfaceId = aMessageInfo.mInterfaceId;
    const NetifUnicastAddress *rvalAddr    = NULL;
    const Address *            candidateAddr;
    int8_t                     candidateId;
    int8_t                     rvalIface         = 0;
    uint8_t                    rvalPrefixMatched = 0;
    uint8_t                    destinationScope  = destination->GetScope();

    for (Netif *netif = GetNetifList(); netif; netif = netif->mNext)
    {
        candidateId = netif->GetInterfaceId();

        if (destination->IsLinkLocal() || destination->IsMulticast())
        {
            if (interfaceId != candidateId)
            {
                continue;
            }
        }

        for (const NetifUnicastAddress *addr = netif->mUnicastAddresses; addr; addr = addr->GetNext())
        {
            uint8_t overrideScope;
            uint8_t candidatePrefixMatched;

            candidateAddr          = &addr->GetAddress();
            candidatePrefixMatched = destination->PrefixMatch(*candidateAddr);
            overrideScope = (candidatePrefixMatched >= addr->mPrefixLength) ? addr->GetScope() : destinationScope;

            if (candidateAddr->IsAnycastRoutingLocator())
            {
                // Don't use anycast address as source address.
                continue;
            }

            if (rvalAddr == NULL)
            {
                // Rule 0: Prefer any address
                rvalAddr          = addr;
                rvalIface         = candidateId;
                rvalPrefixMatched = candidatePrefixMatched;
            }
            else if (*candidateAddr == *destination)
            {
                // Rule 1: Prefer same address
                rvalAddr  = addr;
                rvalIface = candidateId;
                ExitNow();
            }
            else if (addr->GetScope() < rvalAddr->GetScope())
            {
                // Rule 2: Prefer appropriate scope
                if (addr->GetScope() >= overrideScope)
                {
                    rvalAddr          = addr;
                    rvalIface         = candidateId;
                    rvalPrefixMatched = candidatePrefixMatched;
                }
            }
            else if (addr->GetScope() > rvalAddr->GetScope())
            {
                if (rvalAddr->GetScope() < overrideScope)
                {
                    rvalAddr          = addr;
                    rvalIface         = candidateId;
                    rvalPrefixMatched = candidatePrefixMatched;
                }
            }
            else if (rvalAddr->GetScope() == Address::kRealmLocalScope)
            {
                // Additional rule: Prefer appropriate realm local address
                if (overrideScope > Address::kRealmLocalScope)
                {
                    if (rvalAddr->GetAddress().IsRoutingLocator())
                    {
                        // Prefer EID if destination is not realm local.
                        rvalAddr          = addr;
                        rvalIface         = candidateId;
                        rvalPrefixMatched = candidatePrefixMatched;
                    }
                }
                else
                {
                    if (candidateAddr->IsRoutingLocator())
                    {
                        // Prefer RLOC if destination is realm local.
                        rvalAddr          = addr;
                        rvalIface         = candidateId;
                        rvalPrefixMatched = candidatePrefixMatched;
                    }
                }
            }
            else if (addr->mPreferred && !rvalAddr->mPreferred)
            {
                // Rule 3: Avoid deprecated addresses
                rvalAddr          = addr;
                rvalIface         = candidateId;
                rvalPrefixMatched = candidatePrefixMatched;
            }
            else if (aMessageInfo.mInterfaceId != 0 && aMessageInfo.mInterfaceId == candidateId &&
                     rvalIface != candidateId)
            {
                // Rule 4: Prefer home address
                // Rule 5: Prefer outgoing interface
                rvalAddr          = addr;
                rvalIface         = candidateId;
                rvalPrefixMatched = candidatePrefixMatched;
            }
            else if (candidatePrefixMatched > rvalPrefixMatched)
            {
                // Rule 6: Prefer matching label
                // Rule 7: Prefer public address
                // Rule 8: Use longest prefix matching
                rvalAddr          = addr;
                rvalIface         = candidateId;
                rvalPrefixMatched = candidatePrefixMatched;
            }
        }
    }

exit:
    aMessageInfo.mInterfaceId = rvalIface;
    return rvalAddr;
}

int8_t Ip6::GetOnLinkNetif(const Address &aAddress)
{
    int8_t rval = -1;

    for (Netif *netif = mNetifListHead; netif; netif = netif->mNext)
    {
        for (const NetifUnicastAddress *cur = netif->mUnicastAddresses; cur; cur = cur->GetNext())
        {
            if (cur->GetAddress().PrefixMatch(aAddress) >= cur->mPrefixLength)
            {
                ExitNow(rval = netif->GetInterfaceId());
            }
        }
    }

exit:
    return rval;
}

const char *Ip6::IpProtoToString(IpProto aIpProto)
{
    const char *retval;

    switch (aIpProto)
    {
    case kProtoHopOpts:
        retval = "HopOpts";
        break;

    case kProtoTcp:
        retval = "TCP";
        break;

    case kProtoUdp:
        retval = "UDP";
        break;

    case kProtoIp6:
        retval = "IP6";
        break;

    case kProtoRouting:
        retval = "Routing";
        break;

    case kProtoFragment:
        retval = "Frag";
        break;

    case kProtoIcmp6:
        retval = "ICMP6";
        break;

    case kProtoNone:
        retval = "None";
        break;

    case kProtoDstOpts:
        retval = "DstOpts";
        break;

    default:
        retval = "Unknown";
        break;
    }

    return retval;
}

} // namespace Ip6
} // namespace ot
