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

#include "ip6.hpp"

#include "backbone_router/bbr_leader.hpp"
#include "backbone_router/bbr_local.hpp"
#include "backbone_router/ndproxy_table.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/message.hpp"
#include "common/random.hpp"
#include "net/checksum.hpp"
#include "net/icmp6.hpp"
#include "net/ip6_address.hpp"
#include "net/ip6_filter.hpp"
#include "net/nat64_translator.hpp"
#include "net/netif.hpp"
#include "net/udp6.hpp"
#include "openthread/ip6.h"
#include "thread/mle.hpp"

using IcmpType = ot::Ip6::Icmp::Header::Type;

static const IcmpType sForwardICMPTypes[] = {
    IcmpType::kTypeDstUnreach,       IcmpType::kTypePacketToBig, IcmpType::kTypeTimeExceeded,
    IcmpType::kTypeParameterProblem, IcmpType::kTypeEchoRequest, IcmpType::kTypeEchoReply,
};

namespace ot {
namespace Ip6 {

RegisterLogModule("Ip6");

Ip6::Ip6(Instance &aInstance)
    : InstanceLocator(aInstance)
    , mIsReceiveIp6FilterEnabled(false)
    , mSendQueueTask(aInstance)
    , mIcmp(aInstance)
    , mUdp(aInstance)
    , mMpl(aInstance)
#if OPENTHREAD_CONFIG_TCP_ENABLE
    , mTcp(aInstance)
#endif
{
#if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE
    ResetBorderRoutingCounters();
#endif
}

Message *Ip6::NewMessage(void) { return NewMessage(0); }

Message *Ip6::NewMessage(uint16_t aReserved) { return NewMessage(aReserved, Message::Settings::GetDefault()); }

Message *Ip6::NewMessage(uint16_t aReserved, const Message::Settings &aSettings)
{
    return Get<MessagePool>().Allocate(
        Message::kTypeIp6, sizeof(Header) + sizeof(HopByHopHeader) + sizeof(MplOption) + aReserved, aSettings);
}

Message *Ip6::NewMessageFromData(const uint8_t *aData, uint16_t aDataLength, const Message::Settings &aSettings)
{
    Message          *message  = nullptr;
    Message::Settings settings = aSettings;
    const Header     *header;

    VerifyOrExit((aData != nullptr) && (aDataLength >= sizeof(Header)));

    // Determine priority from IPv6 header
    header = reinterpret_cast<const Header *>(aData);
    VerifyOrExit(header->IsValid());
    VerifyOrExit(sizeof(Header) + header->GetPayloadLength() == aDataLength);
    settings.mPriority = DscpToPriority(header->GetDscp());

    message = Get<MessagePool>().Allocate(Message::kTypeIp6, /* aReserveHeader */ 0, settings);

    VerifyOrExit(message != nullptr);

    if (message->AppendBytes(aData, aDataLength) != kErrorNone)
    {
        message->Free();
        message = nullptr;
    }

exit:
    return message;
}

Message::Priority Ip6::DscpToPriority(uint8_t aDscp)
{
    Message::Priority priority;
    uint8_t           cs = aDscp & kDscpCsMask;

    switch (cs)
    {
    case kDscpCs1:
    case kDscpCs2:
        priority = Message::kPriorityLow;
        break;

    case kDscpCs0:
    case kDscpCs3:
        priority = Message::kPriorityNormal;
        break;

    case kDscpCs4:
    case kDscpCs5:
    case kDscpCs6:
    case kDscpCs7:
        priority = Message::kPriorityHigh;
        break;

    default:
        priority = Message::kPriorityNormal;
        break;
    }

    return priority;
}

uint8_t Ip6::PriorityToDscp(Message::Priority aPriority)
{
    uint8_t dscp = kDscpCs0;

    switch (aPriority)
    {
    case Message::kPriorityLow:
        dscp = kDscpCs1;
        break;

    case Message::kPriorityNormal:
    case Message::kPriorityNet:
        dscp = kDscpCs0;
        break;

    case Message::kPriorityHigh:
        dscp = kDscpCs4;
        break;
    }

    return dscp;
}

Error Ip6::AddMplOption(Message &aMessage, Header &aHeader)
{
    Error          error = kErrorNone;
    HopByHopHeader hbhHeader;
    MplOption      mplOption;
    PadOption      padOption;

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

    // Check if MPL option may require padding
    if (padOption.InitToPadHeaderWithSize(sizeof(HopByHopHeader) + mplOption.GetSize()) == kErrorNone)
    {
        SuccessOrExit(error = aMessage.PrependBytes(&padOption, padOption.GetSize()));
    }

    SuccessOrExit(error = aMessage.PrependBytes(&mplOption, mplOption.GetSize()));
    SuccessOrExit(error = aMessage.Prepend(hbhHeader));
    aHeader.SetPayloadLength(aHeader.GetPayloadLength() + sizeof(hbhHeader) + sizeof(mplOption));
    aHeader.SetNextHeader(kProtoHopOpts);

exit:
    return error;
}

Error Ip6::AddTunneledMplOption(Message &aMessage, Header &aHeader)
{
    Error          error = kErrorNone;
    Header         tunnelHeader;
    const Address *source;

    // Use IP-in-IP encapsulation (RFC2473) and ALL_MPL_FORWARDERS address.
    tunnelHeader.InitVersionTrafficClassFlow();
    tunnelHeader.SetHopLimit(static_cast<uint8_t>(kDefaultHopLimit));
    tunnelHeader.SetPayloadLength(aHeader.GetPayloadLength() + sizeof(tunnelHeader));
    tunnelHeader.GetDestination().SetToRealmLocalAllMplForwarders();
    tunnelHeader.SetNextHeader(kProtoIp6);

    source = SelectSourceAddress(tunnelHeader.GetDestination());
    VerifyOrExit(source != nullptr, error = kErrorInvalidSourceAddress);

    tunnelHeader.SetSource(*source);

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

exit:
    return error;
}

Error Ip6::InsertMplOption(Message &aMessage, Header &aHeader)
{
    Error error = kErrorNone;

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

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

        if (aHeader.GetNextHeader() == kProtoHopOpts)
        {
            HopByHopHeader hbh;
            uint16_t       hbhSize;
            MplOption      mplOption;
            PadOption      padOption;

            // Read existing hop-by-hop option header
            SuccessOrExit(error = aMessage.Read(0, hbh));
            hbhSize = hbh.GetSize();

            VerifyOrExit(hbhSize <= aHeader.GetPayloadLength(), error = kErrorParse);

            // Increment hop-by-hop option header length by one which
            // increases its total size by 8 bytes.
            hbh.SetLength(hbh.GetLength() + 1);
            aMessage.Write(0, hbh);

            // Make space for MPL Option + padding (8 bytes) at the end
            // of hop-by-hop header
            SuccessOrExit(error = aMessage.InsertHeader(hbhSize, ExtensionHeader::kLengthUnitSize));

            // Insert MPL Option
            mMpl.InitOption(mplOption, aHeader.GetSource());
            aMessage.WriteBytes(hbhSize, &mplOption, mplOption.GetSize());

            // Insert Pad Option (if needed)
            if (padOption.InitToPadHeaderWithSize(mplOption.GetSize()) == kErrorNone)
            {
                aMessage.WriteBytes(hbhSize + mplOption.GetSize(), &padOption, padOption.GetSize());
            }

            // Update IPv6 Payload Length
            aHeader.SetPayloadLength(aHeader.GetPayloadLength() + ExtensionHeader::kLengthUnitSize);
        }
        else
        {
            SuccessOrExit(error = AddMplOption(aMessage, aHeader));
        }

        SuccessOrExit(error = aMessage.Prepend(aHeader));
    }
    else
    {
#if OPENTHREAD_FTD
        if (aHeader.GetDestination().IsMulticastLargerThanRealmLocal() &&
            Get<ChildTable>().HasSleepyChildWithAddress(aHeader.GetDestination()))
        {
            Message *messageCopy = nullptr;

            if ((messageCopy = aMessage.Clone()) != nullptr)
            {
                IgnoreError(HandleDatagram(*messageCopy));
                LogInfo("Message copy for indirect transmission to sleepy children");
            }
            else
            {
                LogWarn("No enough buffer for message copy for indirect transmission to sleepy children");
            }
        }
#endif

        SuccessOrExit(error = AddTunneledMplOption(aMessage, aHeader));
    }

exit:
    return error;
}

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

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

    IgnoreError(aMessage.Read(offset, hbh));
    endOffset = offset + hbh.GetSize();
    VerifyOrExit(aMessage.GetLength() >= endOffset, error = kErrorParse);

    offset += sizeof(hbh);

    for (; offset < endOffset; offset += option.GetSize())
    {
        IgnoreError(option.ParseFrom(aMessage, offset, endOffset));

        if (option.IsPadding())
        {
            continue;
        }

        if (option.GetType() == MplOption::kType)
        {
            // If multiple MPL options exist, discard packet
            VerifyOrExit(mplOffset == 0, error = kErrorParse);

            mplOffset = offset;
            mplLength = option.GetLength();

            VerifyOrExit(mplLength <= sizeof(MplOption) - sizeof(Option), error = kErrorParse);

            if (mplOffset == sizeof(ip6Header) + sizeof(hbh) && hbh.GetLength() == 0)
            {
                // First and only IPv6 Option, remove IPv6 HBH Option header
                remove = true;
            }
            else if (mplOffset + ExtensionHeader::kLengthUnitSize == endOffset)
            {
                // Last IPv6 Option, remove the last 8 bytes
                remove = true;
            }
        }
        else
        {
            // Encountered another option, now just replace
            // MPL Option with Pad Option
            remove = false;
        }
    }

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

    if (remove)
    {
        // Last IPv6 Option, shrink HBH Option header by
        // 8 bytes (`kLengthUnitSize`)
        aMessage.RemoveHeader(endOffset - ExtensionHeader::kLengthUnitSize, ExtensionHeader::kLengthUnitSize);

        if (mplOffset == sizeof(ip6Header) + sizeof(hbh))
        {
            // Remove entire HBH header
            ip6Header.SetNextHeader(hbh.GetNextHeader());
        }
        else
        {
            // Update HBH header length, decrement by one
            // which decreases its total size by 8 bytes.

            hbh.SetLength(hbh.GetLength() - 1);
            aMessage.Write(sizeof(ip6Header), hbh);
        }

        ip6Header.SetPayloadLength(ip6Header.GetPayloadLength() - ExtensionHeader::kLengthUnitSize);
        aMessage.Write(0, ip6Header);
    }
    else if (mplOffset != 0)
    {
        // Replace MPL Option with Pad Option
        PadOption padOption;

        padOption.InitForPadSize(sizeof(Option) + mplLength);
        aMessage.WriteBytes(mplOffset, &padOption, padOption.GetSize());
    }

exit:
    return error;
}

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

Error Ip6::SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aIpProto)
{
    Error    error = kErrorNone;
    Header   header;
    uint8_t  dscp;
    uint16_t payloadLength = aMessage.GetLength();

    if ((aIpProto == kProtoUdp) &&
        Get<Tmf::Agent>().IsTmfMessage(aMessageInfo.GetSockAddr(), aMessageInfo.GetPeerAddr(),
                                       aMessageInfo.GetPeerPort()))
    {
        dscp = Tmf::Agent::PriorityToDscp(aMessage.GetPriority());
    }
    else
    {
        dscp = PriorityToDscp(aMessage.GetPriority());
    }

    header.InitVersionTrafficClassFlow();
    header.SetDscp(dscp);
    header.SetEcn(aMessageInfo.GetEcn());
    header.SetPayloadLength(payloadLength);
    header.SetNextHeader(aIpProto);

    if (aMessageInfo.GetHopLimit() != 0 || aMessageInfo.ShouldAllowZeroHopLimit())
    {
        header.SetHopLimit(aMessageInfo.GetHopLimit());
    }
    else
    {
        header.SetHopLimit(static_cast<uint8_t>(kDefaultHopLimit));
    }

    if (aMessageInfo.GetSockAddr().IsUnspecified() || aMessageInfo.GetSockAddr().IsMulticast())
    {
        const Address *source = SelectSourceAddress(aMessageInfo.GetPeerAddr());

        VerifyOrExit(source != nullptr, error = kErrorInvalidSourceAddress);
        header.SetSource(*source);
    }
    else
    {
        header.SetSource(aMessageInfo.GetSockAddr());
    }

    header.SetDestination(aMessageInfo.GetPeerAddr());

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

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

    Checksum::UpdateMessageChecksum(aMessage, header.GetSource(), header.GetDestination(), aIpProto);

    if (aMessageInfo.GetPeerAddr().IsMulticastLargerThanRealmLocal())
    {
#if OPENTHREAD_FTD
        if (Get<ChildTable>().HasSleepyChildWithAddress(header.GetDestination()))
        {
            Message *messageCopy = aMessage.Clone();

            if (messageCopy != nullptr)
            {
                LogInfo("Message copy for indirect transmission to sleepy children");
                EnqueueDatagram(*messageCopy);
            }
            else
            {
                LogWarn("No enough buffer for message copy for indirect transmission to sleepy children");
            }
        }
#endif

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

    aMessage.SetMulticastLoop(aMessageInfo.GetMulticastLoop());

    if (aMessage.GetLength() > kMaxDatagramLength)
    {
        error = FragmentDatagram(aMessage, aIpProto);
    }
    else
    {
        EnqueueDatagram(aMessage);
    }

exit:

    return error;
}

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

    while ((message = mSendQueue.GetHead()) != nullptr)
    {
        mSendQueue.Dequeue(*message);
        IgnoreError(HandleDatagram(*message));
    }
}

Error Ip6::HandleOptions(Message &aMessage, Header &aHeader, bool aIsOutbound, bool &aReceive)
{
    Error          error = kErrorNone;
    HopByHopHeader hbhHeader;
    Option         option;
    uint16_t       offset = aMessage.GetOffset();
    uint16_t       endOffset;

    SuccessOrExit(error = aMessage.Read(offset, hbhHeader));

    endOffset = offset + hbhHeader.GetSize();
    VerifyOrExit(endOffset <= aMessage.GetLength(), error = kErrorParse);

    offset += sizeof(HopByHopHeader);

    for (; offset < endOffset; offset += option.GetSize())
    {
        SuccessOrExit(error = option.ParseFrom(aMessage, offset, endOffset));

        if (option.IsPadding())
        {
            continue;
        }

        if (option.GetType() == MplOption::kType)
        {
            SuccessOrExit(error = mMpl.ProcessOption(aMessage, offset, aHeader.GetSource(), aIsOutbound, aReceive));
            continue;
        }

        VerifyOrExit(option.GetAction() == Option::kActionSkip, error = kErrorDrop);
    }

    aMessage.SetOffset(offset);

exit:
    return error;
}

#if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE
Error Ip6::FragmentDatagram(Message &aMessage, uint8_t aIpProto)
{
    Error          error = kErrorNone;
    Header         header;
    FragmentHeader fragmentHeader;
    Message       *fragment        = nullptr;
    uint16_t       fragmentCnt     = 0;
    uint16_t       payloadFragment = 0;
    uint16_t       offset          = 0;

    uint16_t maxPayloadFragment =
        FragmentHeader::MakeDivisibleByEight(kMinimalMtu - aMessage.GetOffset() - sizeof(fragmentHeader));
    uint16_t payloadLeft = aMessage.GetLength() - aMessage.GetOffset();

    SuccessOrExit(error = aMessage.Read(0, header));
    header.SetNextHeader(kProtoFragment);

    fragmentHeader.Init();
    fragmentHeader.SetIdentification(Random::NonCrypto::GetUint32());
    fragmentHeader.SetNextHeader(aIpProto);
    fragmentHeader.SetMoreFlag();

    while (payloadLeft != 0)
    {
        if (payloadLeft < maxPayloadFragment)
        {
            fragmentHeader.ClearMoreFlag();

            payloadFragment = payloadLeft;
            payloadLeft     = 0;

            LogDebg("Last Fragment");
        }
        else
        {
            payloadLeft -= maxPayloadFragment;
            payloadFragment = maxPayloadFragment;
        }

        offset = fragmentCnt * FragmentHeader::BytesToFragmentOffset(maxPayloadFragment);
        fragmentHeader.SetOffset(offset);

        VerifyOrExit((fragment = NewMessage()) != nullptr, error = kErrorNoBufs);
        IgnoreError(fragment->SetPriority(aMessage.GetPriority()));
        SuccessOrExit(error = fragment->SetLength(aMessage.GetOffset() + sizeof(fragmentHeader) + payloadFragment));

        header.SetPayloadLength(payloadFragment + sizeof(fragmentHeader));
        fragment->Write(0, header);

        fragment->SetOffset(aMessage.GetOffset());
        fragment->Write(aMessage.GetOffset(), fragmentHeader);

        fragment->WriteBytesFromMessage(
            /* aWriteOffset */ aMessage.GetOffset() + sizeof(fragmentHeader), aMessage,
            /* aReadOffset */ aMessage.GetOffset() + FragmentHeader::FragmentOffsetToBytes(offset),
            /* aLength */ payloadFragment);

        EnqueueDatagram(*fragment);

        fragmentCnt++;
        fragment = nullptr;

        LogInfo("Fragment %d with %d bytes sent", fragmentCnt, payloadFragment);
    }

    aMessage.Free();

exit:

    if (error == kErrorNoBufs)
    {
        LogWarn("No buffer for Ip6 fragmentation");
    }

    FreeMessageOnError(fragment, error);
    return error;
}

Error Ip6::HandleFragment(Message &aMessage, MessageInfo &aMessageInfo)
{
    Error          error = kErrorNone;
    Header         header, headerBuffer;
    FragmentHeader fragmentHeader;
    Message       *message         = nullptr;
    uint16_t       offset          = 0;
    uint16_t       payloadFragment = 0;
    bool           isFragmented    = true;

    SuccessOrExit(error = aMessage.Read(0, header));
    SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), fragmentHeader));

    if (fragmentHeader.GetOffset() == 0 && !fragmentHeader.IsMoreFlagSet())
    {
        isFragmented = false;
        aMessage.MoveOffset(sizeof(fragmentHeader));
        ExitNow();
    }

    for (Message &msg : mReassemblyList)
    {
        SuccessOrExit(error = msg.Read(0, headerBuffer));

        if (msg.GetDatagramTag() == fragmentHeader.GetIdentification() &&
            headerBuffer.GetSource() == header.GetSource() && headerBuffer.GetDestination() == header.GetDestination())
        {
            message = &msg;
            break;
        }
    }

    offset          = FragmentHeader::FragmentOffsetToBytes(fragmentHeader.GetOffset());
    payloadFragment = aMessage.GetLength() - aMessage.GetOffset() - sizeof(fragmentHeader);

    LogInfo("Fragment with id %d received > %d bytes, offset %d", fragmentHeader.GetIdentification(), payloadFragment,
            offset);

    if (offset + payloadFragment + aMessage.GetOffset() > kMaxAssembledDatagramLength)
    {
        LogWarn("Packet too large for fragment buffer");
        ExitNow(error = kErrorNoBufs);
    }

    if (message == nullptr)
    {
        LogDebg("start reassembly");
        VerifyOrExit((message = NewMessage()) != nullptr, error = kErrorNoBufs);
        mReassemblyList.Enqueue(*message);

        message->SetTimestampToNow();
        message->SetOffset(0);
        message->SetDatagramTag(fragmentHeader.GetIdentification());

        // copying the non-fragmentable header to the fragmentation buffer
        SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, 0, aMessage.GetOffset()));

        Get<TimeTicker>().RegisterReceiver(TimeTicker::kIp6FragmentReassembler);
    }

    // increase message buffer if necessary
    if (message->GetLength() < offset + payloadFragment + aMessage.GetOffset())
    {
        SuccessOrExit(error = message->SetLength(offset + payloadFragment + aMessage.GetOffset()));
    }

    // copy the fragment payload into the message buffer
    message->WriteBytesFromMessage(
        /* aWriteOffset */ aMessage.GetOffset() + offset, aMessage,
        /* aReadOffset */ aMessage.GetOffset() + sizeof(fragmentHeader), /* aLength */ payloadFragment);

    // check if it is the last frame
    if (!fragmentHeader.IsMoreFlagSet())
    {
        // use the offset value for the whole ip message length
        message->SetOffset(aMessage.GetOffset() + offset + payloadFragment);

        // creates the header for the reassembled ipv6 package
        SuccessOrExit(error = aMessage.Read(0, header));
        header.SetPayloadLength(message->GetLength() - sizeof(header));
        header.SetNextHeader(fragmentHeader.GetNextHeader());
        message->Write(0, header);

        LogDebg("Reassembly complete.");

        mReassemblyList.Dequeue(*message);

        IgnoreError(HandleDatagram(*message, aMessageInfo.mLinkInfo, /* aIsReassembled */ true));
    }

exit:
    if (error != kErrorDrop && error != kErrorNone && isFragmented)
    {
        if (message != nullptr)
        {
            mReassemblyList.DequeueAndFree(*message);
        }

        LogWarn("Reassembly failed: %s", ErrorToString(error));
    }

    if (isFragmented)
    {
        // drop all fragments, the payload is stored in the fragment buffer
        error = kErrorDrop;
    }

    return error;
}

void Ip6::CleanupFragmentationBuffer(void) { mReassemblyList.DequeueAndFreeAll(); }

void Ip6::HandleTimeTick(void)
{
    UpdateReassemblyList();

    if (mReassemblyList.GetHead() == nullptr)
    {
        Get<TimeTicker>().UnregisterReceiver(TimeTicker::kIp6FragmentReassembler);
    }
}

void Ip6::UpdateReassemblyList(void)
{
    TimeMilli now = TimerMilli::GetNow();

    for (Message &message : mReassemblyList)
    {
        if (now - message.GetTimestamp() >= TimeMilli::SecToMsec(kIp6ReassemblyTimeout))
        {
            LogNote("Reassembly timeout.");
            SendIcmpError(message, Icmp::Header::kTypeTimeExceeded, Icmp::Header::kCodeFragmReasTimeEx);

            mReassemblyList.DequeueAndFree(message);
        }
    }
}

void Ip6::SendIcmpError(Message &aMessage, Icmp::Header::Type aIcmpType, Icmp::Header::Code aIcmpCode)
{
    Error       error = kErrorNone;
    Header      header;
    MessageInfo messageInfo;

    SuccessOrExit(error = aMessage.Read(0, header));

    messageInfo.SetPeerAddr(header.GetSource());
    messageInfo.SetSockAddr(header.GetDestination());
    messageInfo.SetHopLimit(header.GetHopLimit());
    messageInfo.SetLinkInfo(nullptr);

    error = mIcmp.SendError(aIcmpType, aIcmpCode, messageInfo, aMessage);

exit:

    if (error != kErrorNone)
    {
        LogWarn("Failed to send ICMP error: %s", ErrorToString(error));
    }
}

#else
Error Ip6::FragmentDatagram(Message &aMessage, uint8_t aIpProto)
{
    OT_UNUSED_VARIABLE(aIpProto);

    EnqueueDatagram(aMessage);

    return kErrorNone;
}

Error Ip6::HandleFragment(Message &aMessage, MessageInfo &aMessageInfo)
{
    OT_UNUSED_VARIABLE(aMessageInfo);

    Error          error = kErrorNone;
    FragmentHeader fragmentHeader;

    SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), fragmentHeader));

    VerifyOrExit(fragmentHeader.GetOffset() == 0 && !fragmentHeader.IsMoreFlagSet(), error = kErrorDrop);

    aMessage.MoveOffset(sizeof(fragmentHeader));

exit:
    return error;
}
#endif // OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE

Error Ip6::HandleExtensionHeaders(Message     &aMessage,
                                  MessageInfo &aMessageInfo,
                                  Header      &aHeader,
                                  uint8_t     &aNextHeader,
                                  bool        &aReceive)
{
    Error           error      = kErrorNone;
    bool            isOutbound = !aMessage.IsOriginThreadNetif();
    ExtensionHeader extHeader;

    while (aReceive || aNextHeader == kProtoHopOpts)
    {
        SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), extHeader));

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

        case kProtoFragment:
            IgnoreError(PassToHost(aMessage, aMessageInfo, aNextHeader,
                                   /* aApplyFilter */ false, aReceive, Message::kCopyToUse));
            SuccessOrExit(error = HandleFragment(aMessage, aMessageInfo));
            break;

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

        case kProtoIp6:
            ExitNow();

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

        default:
            ExitNow();
        }

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

exit:
    return error;
}

Error Ip6::HandlePayload(Header            &aIp6Header,
                         Message           &aMessage,
                         MessageInfo       &aMessageInfo,
                         uint8_t            aIpProto,
                         Message::Ownership aMessageOwnership)
{
#if !OPENTHREAD_CONFIG_TCP_ENABLE
    OT_UNUSED_VARIABLE(aIp6Header);
#endif

    Error    error   = kErrorNone;
    Message *message = (aMessageOwnership == Message::kTakeCustody) ? &aMessage : nullptr;

    switch (aIpProto)
    {
    case kProtoUdp:
    case kProtoIcmp6:
        break;
#if OPENTHREAD_CONFIG_TCP_ENABLE
    case kProtoTcp:
        break;
#endif
    default:
        ExitNow();
    }

    if (aMessageOwnership == Message::kCopyToUse)
    {
        message = aMessage.Clone();
    }

    VerifyOrExit(message != nullptr, error = kErrorNoBufs);

    switch (aIpProto)
    {
#if OPENTHREAD_CONFIG_TCP_ENABLE
    case kProtoTcp:
        error = mTcp.HandleMessage(aIp6Header, *message, aMessageInfo);
        if (error == kErrorDrop)
        {
            LogNote("Error TCP Checksum");
        }
        break;
#endif
    case kProtoUdp:
        error = mUdp.HandleMessage(*message, aMessageInfo);
        if (error == kErrorDrop)
        {
            LogNote("Error UDP Checksum");
        }
        break;

    case kProtoIcmp6:
        error = mIcmp.HandleMessage(*message, aMessageInfo);
        break;

    default:
        break;
    }

exit:
    if (error != kErrorNone)
    {
        LogNote("Failed to handle payload: %s", ErrorToString(error));
    }

    FreeMessage(message);

    return error;
}

Error Ip6::PassToHost(Message           &aMessage,
                      const MessageInfo &aMessageInfo,
                      uint8_t            aIpProto,
                      bool               aApplyFilter,
                      bool               aReceive,
                      Message::Ownership aMessageOwnership)
{
    // This method passes the message to host by invoking the
    // registered IPv6 receive callback. When NAT64 is enabled, it
    // may also perform translation and invoke IPv4 receive
    // callback.

    Error    error   = kErrorNone;
    Message *message = nullptr;

    // `message` points to the `Message` instance we own in this
    // method. If we can take ownership of `aMessage`, we use it as
    // `message`. Otherwise, we may create a clone of it and use as
    // `message`. `message` variable will be set to `nullptr` if the
    // message ownership is transferred to an invoked callback. At
    // the end of this method we free `message` if it is not `nullptr`
    // indicating it was not passed to a callback.

    if (aMessageOwnership == Message::kTakeCustody)
    {
        message = &aMessage;
    }

    VerifyOrExit(aMessage.IsLoopbackToHostAllowed(), error = kErrorNoRoute);

    VerifyOrExit(mReceiveIp6DatagramCallback.IsSet(), error = kErrorNoRoute);

    // Do not pass IPv6 packets that exceed kMinimalMtu.
    VerifyOrExit(aMessage.GetLength() <= kMinimalMtu, error = kErrorDrop);

    // If the sender used mesh-local address as source, do not pass to
    // host unless this message is intended for this device itself.
    if (Get<Mle::Mle>().IsMeshLocalAddress(aMessageInfo.GetPeerAddr()))
    {
        VerifyOrExit(aReceive, error = kErrorDrop);
    }

    if (mIsReceiveIp6FilterEnabled && aApplyFilter)
    {
#if !OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
        // Do not pass messages sent to an RLOC/ALOC, except
        // Service Locator

        bool isLocator = Get<Mle::Mle>().IsMeshLocalAddress(aMessageInfo.GetSockAddr()) &&
                         aMessageInfo.GetSockAddr().GetIid().IsLocator();

        VerifyOrExit(!isLocator || aMessageInfo.GetSockAddr().GetIid().IsAnycastServiceLocator(),
                     error = kErrorNoRoute);
#endif

        switch (aIpProto)
        {
        case kProtoIcmp6:
            if (mIcmp.ShouldHandleEchoRequest(aMessageInfo))
            {
                Icmp::Header icmp;

                IgnoreError(aMessage.Read(aMessage.GetOffset(), icmp));
                VerifyOrExit(icmp.GetType() != Icmp::Header::kTypeEchoRequest, error = kErrorDrop);
            }

            break;

        case kProtoUdp:
        {
            Udp::Header udp;

            IgnoreError(aMessage.Read(aMessage.GetOffset(), udp));
            VerifyOrExit(Get<Udp>().ShouldUsePlatformUdp(udp.GetDestinationPort()) &&
                             !Get<Udp>().IsPortInUse(udp.GetDestinationPort()),
                         error = kErrorNoRoute);
            break;
        }

#if OPENTHREAD_CONFIG_TCP_ENABLE
        // Do not pass TCP message to avoid dual processing from both
        // OpenThread and POSIX TCP stacks.
        case kProtoTcp:
            error = kErrorNoRoute;
            ExitNow();
#endif

        default:
            break;
        }
    }

    switch (aMessageOwnership)
    {
    case Message::kTakeCustody:
        break;

    case Message::kCopyToUse:
        message = aMessage.Clone();

        if (message == nullptr)
        {
            LogWarn("No buff to clone msg (len: %d) to pass to host", aMessage.GetLength());
            ExitNow(error = kErrorNoBufs);
        }

        break;
    }

    IgnoreError(RemoveMplOption(*message));

#if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
    switch (Get<Nat64::Translator>().TranslateFromIp6(aMessage))
    {
    case Nat64::Translator::kNotTranslated:
        break;

    case Nat64::Translator::kDrop:
        ExitNow(error = kErrorDrop);

    case Nat64::Translator::kForward:
        VerifyOrExit(mReceiveIp4DatagramCallback.IsSet(), error = kErrorNoRoute);
        // Pass message to callback transferring its ownership.
        mReceiveIp4DatagramCallback.Invoke(message);
        message = nullptr;
        ExitNow();
    }
#endif

    // Pass message to callback transferring its ownership.
    mReceiveIp6DatagramCallback.Invoke(message);
    message = nullptr;

#if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE
    {
        Header header;

        IgnoreError(header.ParseFrom(aMessage));
        UpdateBorderRoutingCounters(header, aMessage.GetLength(), /* aIsInbound */ false);
    }
#endif

exit:
    FreeMessage(message);
    return error;
}

Error Ip6::SendRaw(Message &aMessage)
{
    Error  error = kErrorNone;
    Header header;
    bool   freed = false;

    SuccessOrExit(error = header.ParseFrom(aMessage));
    VerifyOrExit(!header.GetSource().IsMulticast(), error = kErrorInvalidSourceAddress);

#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
    // The filtering rules don't apply to packets from DUA.
    if (!Get<BackboneRouter::Leader>().IsDomainUnicast(header.GetSource()))
#endif
    {
        // When the packet is forwarded from host to Thread, if its source is on-mesh or its destination is
        // mesh-local, we'll drop the packet unless the packet originates from this device.
        if (Get<NetworkData::Leader>().IsOnMesh(header.GetSource()) ||
            Get<Mle::Mle>().IsMeshLocalAddress(header.GetDestination()))
        {
            VerifyOrExit(Get<ThreadNetif>().HasUnicastAddress(header.GetSource()), error = kErrorDrop);
        }
    }

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

    error = HandleDatagram(aMessage);
    freed = true;

#if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE
    UpdateBorderRoutingCounters(header, aMessage.GetLength(), /* aIsInbound */ true);
#endif

exit:

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

    return error;
}

Error Ip6::HandleDatagram(Message &aMessage, const void *aLinkMessageInfo, bool aIsReassembled)
{
    Error       error;
    MessageInfo messageInfo;
    Header      header;
    bool        receive;
    bool        forwardThread;
    bool        forwardHost;
    bool        shouldFreeMessage;
    uint8_t     nextHeader;

start:
    receive           = false;
    forwardThread     = false;
    forwardHost       = false;
    shouldFreeMessage = true;

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

    messageInfo.Clear();
    messageInfo.SetPeerAddr(header.GetSource());
    messageInfo.SetSockAddr(header.GetDestination());
    messageInfo.SetHopLimit(header.GetHopLimit());
    messageInfo.SetEcn(header.GetEcn());
    messageInfo.SetLinkInfo(aLinkMessageInfo);

    // Determine `forwardThread`, `forwardHost` and `receive`
    // based on the destination address.

    if (header.GetDestination().IsMulticast())
    {
        // Destination is multicast

        forwardThread = !aMessage.IsOriginThreadNetif();

#if OPENTHREAD_FTD
        if (aMessage.IsOriginThreadNetif() && header.GetDestination().IsMulticastLargerThanRealmLocal() &&
            Get<ChildTable>().HasSleepyChildWithAddress(header.GetDestination()))
        {
            forwardThread = true;
        }
#endif

        forwardHost = header.GetDestination().IsMulticastLargerThanRealmLocal();

        if ((aMessage.IsOriginThreadNetif() || aMessage.GetMulticastLoop()) &&
            Get<ThreadNetif>().IsMulticastSubscribed(header.GetDestination()))
        {
            receive = true;
        }
        else if (Get<ThreadNetif>().IsMulticastPromiscuousEnabled())
        {
            forwardHost = true;
        }
    }
    else
    {
        // Destination is unicast

        if (Get<ThreadNetif>().HasUnicastAddress(header.GetDestination()))
        {
            receive = true;
        }
        else if (!aMessage.IsOriginThreadNetif() || !header.GetDestination().IsLinkLocal())
        {
            if (header.GetDestination().IsLinkLocal())
            {
                forwardThread = true;
            }
            else if (IsOnLink(header.GetDestination()))
            {
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE
                forwardThread = (!aMessage.IsLoopbackToHostAllowed() ||
                                 !Get<BackboneRouter::Manager>().ShouldForwardDuaToBackbone(header.GetDestination()));
#else
                forwardThread = true;
#endif
            }
            else if (RouteLookup(header.GetSource(), header.GetDestination()) == kErrorNone)
            {
                forwardThread = true;
            }

            forwardHost = !forwardThread;
        }
    }

    aMessage.SetOffset(sizeof(header));

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

    if (receive && (nextHeader == kProtoIp6))
    {
        // Remove encapsulating header and start over.
        aMessage.RemoveHeader(aMessage.GetOffset());
        Get<MeshForwarder>().LogMessage(MeshForwarder::kMessageReceive, aMessage);
        goto start;
    }

    if ((forwardHost || receive) && !aIsReassembled)
    {
        error = PassToHost(aMessage, messageInfo, nextHeader,
                           /* aApplyFilter */ !forwardHost, receive,
                           (receive || forwardThread) ? Message::kCopyToUse : Message::kTakeCustody);

        // Need to free the message if we did not pass its
        // ownership in the call to `PassToHost()`
        shouldFreeMessage = (receive || forwardThread);
    }

    if (receive)
    {
        error = HandlePayload(header, aMessage, messageInfo, nextHeader,
                              forwardThread ? Message::kCopyToUse : Message::kTakeCustody);

        // Need to free the message if we did not pass its
        // ownership in the call to `HandlePayload()`
        shouldFreeMessage = forwardThread;
    }

    if (forwardThread)
    {
        uint8_t hopLimit;

        if (aMessage.IsOriginThreadNetif())
        {
            VerifyOrExit(Get<Mle::Mle>().IsRouterOrLeader());
            header.SetHopLimit(header.GetHopLimit() - 1);
        }

        VerifyOrExit(header.GetHopLimit() > 0, error = kErrorDrop);

        hopLimit = header.GetHopLimit();
        aMessage.Write(Header::kHopLimitFieldOffset, hopLimit);

        if (nextHeader == kProtoIcmp6)
        {
            uint8_t icmpType;
            bool    isAllowedType = false;

            SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), icmpType));
            for (IcmpType type : sForwardICMPTypes)
            {
                if (icmpType == type)
                {
                    isAllowedType = true;
                    break;
                }
            }
            VerifyOrExit(isAllowedType, error = kErrorDrop);
        }

        if (aMessage.IsOriginHostUntrusted() && (nextHeader == kProtoUdp))
        {
            uint16_t destPort;

            SuccessOrExit(error = aMessage.Read(aMessage.GetOffset() + Udp::Header::kDestPortFieldOffset, destPort));
            destPort = HostSwap16(destPort);

            if (destPort == Tmf::kUdpPort)
            {
                LogNote("Dropping TMF message from untrusted origin");
                ExitNow(error = kErrorDrop);
            }
        }

#if !OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
        if (aMessage.IsOriginHostTrusted() && !aMessage.IsLoopbackToHostAllowed() && (nextHeader == kProtoUdp))
        {
            uint16_t destPort;

            SuccessOrExit(error = aMessage.Read(aMessage.GetOffset() + Udp::Header::kDestPortFieldOffset, destPort));
            destPort = HostSwap16(destPort);

            if (nextHeader == kProtoUdp)
            {
                VerifyOrExit(Get<Udp>().ShouldUsePlatformUdp(destPort), error = kErrorDrop);
            }
        }
#endif

#if OPENTHREAD_CONFIG_MULTI_RADIO
        // Since the message will be forwarded, we clear the radio
        // type on the message to allow the radio type for tx to be
        // selected later (based on the radios supported by the next
        // hop).
        aMessage.ClearRadioType();
#endif

        // `SendMessage()` takes custody of message in the success case
        SuccessOrExit(error = Get<MeshForwarder>().SendMessage(aMessage));
        shouldFreeMessage = false;
    }

exit:

    if (shouldFreeMessage)
    {
        aMessage.Free();
    }

    return error;
}

Error Ip6::SelectSourceAddress(MessageInfo &aMessageInfo) const
{
    Error          error = kErrorNone;
    const Address *source;

    source = SelectSourceAddress(aMessageInfo.GetPeerAddr());
    VerifyOrExit(source != nullptr, error = kErrorNotFound);
    aMessageInfo.SetSockAddr(*source);

exit:
    return error;
}

const Address *Ip6::SelectSourceAddress(const Address &aDestination) const
{
    uint8_t                      destScope    = aDestination.GetScope();
    bool                         destIsRloc   = Get<Mle::Mle>().IsRoutingLocator(aDestination);
    const Netif::UnicastAddress *bestAddr     = nullptr;
    uint8_t                      bestMatchLen = 0;

    for (const Netif::UnicastAddress &addr : Get<ThreadNetif>().GetUnicastAddresses())
    {
        uint8_t matchLen;
        uint8_t overrideScope;

        if (Get<Mle::Mle>().IsAnycastLocator(addr.GetAddress()))
        {
            // Don't use anycast address as source address.
            continue;
        }

        matchLen = aDestination.PrefixMatch(addr.GetAddress());

        if (matchLen >= addr.mPrefixLength)
        {
            matchLen      = addr.mPrefixLength;
            overrideScope = addr.GetScope();
        }
        else
        {
            overrideScope = destScope;
        }

        if (bestAddr == nullptr)
        {
            // Rule 0: Prefer any address
            bestAddr     = &addr;
            bestMatchLen = matchLen;
        }
        else if (addr.GetAddress() == aDestination)
        {
            // Rule 1: Prefer same address
            bestAddr = &addr;
            ExitNow();
        }
        else if (addr.GetScope() < bestAddr->GetScope())
        {
            // Rule 2: Prefer appropriate scope
            if (addr.GetScope() >= overrideScope)
            {
                bestAddr     = &addr;
                bestMatchLen = matchLen;
            }
            else
            {
                continue;
            }
        }
        else if (addr.GetScope() > bestAddr->GetScope())
        {
            if (bestAddr->GetScope() < overrideScope)
            {
                bestAddr     = &addr;
                bestMatchLen = matchLen;
            }
            else
            {
                continue;
            }
        }
        else if (addr.mPreferred && !bestAddr->mPreferred)
        {
            // Rule 3: Avoid deprecated addresses
            bestAddr     = &addr;
            bestMatchLen = matchLen;
        }
        else if (matchLen > bestMatchLen)
        {
            // Rule 6: Prefer matching label
            // Rule 7: Prefer public address
            // Rule 8: Use longest prefix matching
            bestAddr     = &addr;
            bestMatchLen = matchLen;
        }
        else if ((matchLen == bestMatchLen) && (destIsRloc == Get<Mle::Mle>().IsRoutingLocator(addr.GetAddress())))
        {
            // Additional rule: Prefer RLOC source for RLOC destination, EID source for anything else
            bestAddr     = &addr;
            bestMatchLen = matchLen;
        }
        else
        {
            continue;
        }

        // infer destination scope based on prefix match
        if (bestMatchLen >= bestAddr->mPrefixLength)
        {
            destScope = bestAddr->GetScope();
        }
    }

exit:
    return (bestAddr != nullptr) ? &bestAddr->GetAddress() : nullptr;
}

bool Ip6::IsOnLink(const Address &aAddress) const
{
    bool isOnLink = false;

    if (Get<NetworkData::Leader>().IsOnMesh(aAddress))
    {
        ExitNow(isOnLink = true);
    }

    for (const Netif::UnicastAddress &unicastAddr : Get<ThreadNetif>().GetUnicastAddresses())
    {
        if (unicastAddr.GetAddress().PrefixMatch(aAddress) >= unicastAddr.mPrefixLength)
        {
            ExitNow(isOnLink = true);
        }
    }

exit:
    return isOnLink;
}

Error Ip6::RouteLookup(const Address &aSource, const Address &aDestination) const
{
    Error    error;
    uint16_t rloc;

    error = Get<NetworkData::Leader>().RouteLookup(aSource, aDestination, rloc);

    if (error == kErrorNone)
    {
        if (rloc == Get<Mle::MleRouter>().GetRloc16())
        {
            error = kErrorNoRoute;
        }
    }
    else
    {
        LogNote("Failed to find valid route for: %s", aDestination.ToString().AsCString());
    }

    return error;
}

#if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE
void Ip6::UpdateBorderRoutingCounters(const Header &aHeader, uint16_t aMessageLength, bool aIsInbound)
{
    otPacketsAndBytes *counter = nullptr;

    VerifyOrExit(!aHeader.GetSource().IsLinkLocal());
    VerifyOrExit(!aHeader.GetDestination().IsLinkLocal());
    VerifyOrExit(aHeader.GetSource().GetPrefix() != Get<Mle::Mle>().GetMeshLocalPrefix());
    VerifyOrExit(aHeader.GetDestination().GetPrefix() != Get<Mle::Mle>().GetMeshLocalPrefix());

    if (aIsInbound)
    {
        VerifyOrExit(!Get<Netif>().HasUnicastAddress(aHeader.GetSource()));

        if (aHeader.GetDestination().IsMulticast())
        {
            VerifyOrExit(aHeader.GetDestination().IsMulticastLargerThanRealmLocal());
            counter = &mBorderRoutingCounters.mInboundMulticast;
        }
        else
        {
            counter = &mBorderRoutingCounters.mInboundUnicast;
        }
    }
    else
    {
        VerifyOrExit(!Get<Netif>().HasUnicastAddress(aHeader.GetDestination()));

        if (aHeader.GetDestination().IsMulticast())
        {
            VerifyOrExit(aHeader.GetDestination().IsMulticastLargerThanRealmLocal());
            counter = &mBorderRoutingCounters.mOutboundMulticast;
        }
        else
        {
            counter = &mBorderRoutingCounters.mOutboundUnicast;
        }
    }

exit:

    if (counter)
    {
        counter->mPackets += 1;
        counter->mBytes += aMessageLength;
    }
}
#endif

// LCOV_EXCL_START

const char *Ip6::IpProtoToString(uint8_t aIpProto)
{
    static constexpr Stringify::Entry kIpProtoTable[] = {
        {kProtoHopOpts, "HopOpts"}, {kProtoTcp, "TCP"},         {kProtoUdp, "UDP"},
        {kProtoIp6, "IP6"},         {kProtoRouting, "Routing"}, {kProtoFragment, "Frag"},
        {kProtoIcmp6, "ICMP6"},     {kProtoNone, "None"},       {kProtoDstOpts, "DstOpts"},
    };

    static_assert(Stringify::IsSorted(kIpProtoTable), "kIpProtoTable is not sorted");

    return Stringify::Lookup(aIpProto, kIpProtoTable, "Unknown");
}

const char *Ip6::EcnToString(Ecn aEcn)
{
    static const char *const kEcnStrings[] = {
        "no", // (0) kEcnNotCapable
        "e1", // (1) kEcnCapable1  (ECT1)
        "e0", // (2) kEcnCapable0  (ECT0)
        "ce", // (3) kEcnMarked    (Congestion Encountered)
    };

    static_assert(0 == kEcnNotCapable, "kEcnNotCapable value is incorrect");
    static_assert(1 == kEcnCapable1, "kEcnCapable1 value is incorrect");
    static_assert(2 == kEcnCapable0, "kEcnCapable0 value is incorrect");
    static_assert(3 == kEcnMarked, "kEcnMarked value is incorrect");

    return kEcnStrings[aEcn];
}

// LCOV_EXCL_STOP

//---------------------------------------------------------------------------------------------------------------------
// Headers

Error Headers::ParseFrom(const Message &aMessage)
{
    Error error = kErrorParse;

    Clear();

    SuccessOrExit(mIp6Header.ParseFrom(aMessage));

    switch (mIp6Header.GetNextHeader())
    {
    case kProtoUdp:
        SuccessOrExit(aMessage.Read(sizeof(Header), mHeader.mUdp));
        break;
    case kProtoTcp:
        SuccessOrExit(aMessage.Read(sizeof(Header), mHeader.mTcp));
        break;
    case kProtoIcmp6:
        SuccessOrExit(aMessage.Read(sizeof(Header), mHeader.mIcmp));
        break;
    default:
        break;
    }

    error = kErrorNone;

exit:
    return error;
}

Error Headers::DecompressFrom(const Message &aMessage, uint16_t aOffset, const Mac::Addresses &aMacAddrs)
{
    static constexpr uint16_t kReadLength = sizeof(Lowpan::FragmentHeader::NextFrag) + sizeof(Headers);

    uint8_t   frameBuffer[kReadLength];
    uint16_t  frameLength;
    FrameData frameData;

    frameLength = aMessage.ReadBytes(aOffset, frameBuffer, sizeof(frameBuffer));
    frameData.Init(frameBuffer, frameLength);

    return DecompressFrom(frameData, aMacAddrs, aMessage.GetInstance());
}

Error Headers::DecompressFrom(const FrameData &aFrameData, const Mac::Addresses &aMacAddrs, Instance &aInstance)
{
    Error                  error     = kErrorNone;
    FrameData              frameData = aFrameData;
    Lowpan::FragmentHeader fragmentHeader;
    bool                   nextHeaderCompressed;

    if (fragmentHeader.ParseFrom(frameData) == kErrorNone)
    {
        // Only the first fragment header is followed by a LOWPAN_IPHC header
        VerifyOrExit(fragmentHeader.GetDatagramOffset() == 0, error = kErrorNotFound);
    }

    VerifyOrExit(Lowpan::Lowpan::IsLowpanHc(frameData), error = kErrorNotFound);

    SuccessOrExit(error = aInstance.Get<Lowpan::Lowpan>().DecompressBaseHeader(mIp6Header, nextHeaderCompressed,
                                                                               aMacAddrs, frameData));

    switch (mIp6Header.GetNextHeader())
    {
    case kProtoUdp:
        if (nextHeaderCompressed)
        {
            SuccessOrExit(error = aInstance.Get<Lowpan::Lowpan>().DecompressUdpHeader(mHeader.mUdp, frameData));
        }
        else
        {
            SuccessOrExit(error = frameData.Read(mHeader.mUdp));
        }
        break;

    case kProtoTcp:
        SuccessOrExit(error = frameData.Read(mHeader.mTcp));
        break;

    case kProtoIcmp6:
        SuccessOrExit(error = frameData.Read(mHeader.mIcmp));
        break;

    default:
        break;
    }

exit:
    return error;
}

uint16_t Headers::GetSourcePort(void) const
{
    uint16_t port = 0;

    switch (GetIpProto())
    {
    case kProtoUdp:
        port = mHeader.mUdp.GetSourcePort();
        break;

    case kProtoTcp:
        port = mHeader.mTcp.GetSourcePort();
        break;

    default:
        break;
    }

    return port;
}

uint16_t Headers::GetDestinationPort(void) const
{
    uint16_t port = 0;

    switch (GetIpProto())
    {
    case kProtoUdp:
        port = mHeader.mUdp.GetDestinationPort();
        break;

    case kProtoTcp:
        port = mHeader.mTcp.GetDestinationPort();
        break;

    default:
        break;
    }

    return port;
}

uint16_t Headers::GetChecksum(void) const
{
    uint16_t checksum = 0;

    switch (GetIpProto())
    {
    case kProtoUdp:
        checksum = mHeader.mUdp.GetChecksum();
        break;

    case kProtoTcp:
        checksum = mHeader.mTcp.GetChecksum();
        break;

    case kProtoIcmp6:
        checksum = mHeader.mIcmp.GetChecksum();
        break;

    default:
        break;
    }

    return checksum;
}

} // namespace Ip6
} // namespace ot
