/*
 *  Copyright (c) 2020, 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.
 */

#include "posix/platform/multicast_routing.hpp"

#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE

#include <assert.h>
#include <net/if.h>
#include <netinet/icmp6.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#if __linux__
#include <linux/mroute6.h>
#else
#error "Multicast Routing feature is not ported to non-Linux platforms yet."
#endif

#include <openthread/backbone_router_ftd.h>
#include <openthread/logging.h>

#include "core/common/arg_macros.hpp"
#include "core/common/debug.hpp"

namespace ot {
namespace Posix {

#define LogResult(aError, ...)                                                                                      \
    do                                                                                                              \
    {                                                                                                               \
        otError _err = (aError);                                                                                    \
                                                                                                                    \
        if (_err == OT_ERROR_NONE)                                                                                  \
        {                                                                                                           \
            otLogInfoPlat(OT_FIRST_ARG(__VA_ARGS__) ": %s" OT_REST_ARGS(__VA_ARGS__), otThreadErrorToString(_err)); \
        }                                                                                                           \
        else                                                                                                        \
        {                                                                                                           \
            otLogWarnPlat(OT_FIRST_ARG(__VA_ARGS__) ": %s" OT_REST_ARGS(__VA_ARGS__), otThreadErrorToString(_err)); \
        }                                                                                                           \
    } while (false)

void MulticastRoutingManager::SetUp(void)
{
    OT_ASSERT(gInstance != nullptr);

    otBackboneRouterSetMulticastListenerCallback(gInstance,
                                                 &MulticastRoutingManager::HandleBackboneMulticastListenerEvent, this);
    Mainloop::Manager::Get().Add(*this);
}

void MulticastRoutingManager::TearDown(void)
{
    OT_ASSERT(gInstance != nullptr);

    otBackboneRouterSetMulticastListenerCallback(gInstance, nullptr, nullptr);
    Mainloop::Manager::Get().Remove(*this);
}

void MulticastRoutingManager::HandleBackboneMulticastListenerEvent(void *                                 aContext,
                                                                   otBackboneRouterMulticastListenerEvent aEvent,
                                                                   const otIp6Address *                   aAddress)
{
    static_cast<MulticastRoutingManager *>(aContext)->HandleBackboneMulticastListenerEvent(
        aEvent, static_cast<const Ip6::Address &>(*aAddress));
}

void MulticastRoutingManager::HandleBackboneMulticastListenerEvent(otBackboneRouterMulticastListenerEvent aEvent,
                                                                   const Ip6::Address &                   aAddress)
{
    switch (aEvent)
    {
    case OT_BACKBONE_ROUTER_MULTICAST_LISTENER_ADDED:
        Add(aAddress);
        break;
    case OT_BACKBONE_ROUTER_MULTICAST_LISTENER_REMOVED:
        Remove(aAddress);
        break;
    }
}

void MulticastRoutingManager::Enable(void)
{
    VerifyOrExit(!IsEnabled());

    InitMulticastRouterSock();

    LogResult(OT_ERROR_NONE, "MulticastRoutingManager: %s", __FUNCTION__);
exit:
    return;
}

void MulticastRoutingManager::Disable(void)
{
    FinalizeMulticastRouterSock();

    LogResult(OT_ERROR_NONE, "MulticastRoutingManager: %s", __FUNCTION__);
}

void MulticastRoutingManager::Add(const Ip6::Address &aAddress)
{
    VerifyOrExit(IsEnabled());

    UnblockInboundMulticastForwardingCache(aAddress);
    UpdateMldReport(aAddress, true);

    LogResult(OT_ERROR_NONE, "MulticastRoutingManager: %s: %s", __FUNCTION__, aAddress.ToString().AsCString());

exit:
    return;
}

void MulticastRoutingManager::Remove(const Ip6::Address &aAddress)
{
    otError error = OT_ERROR_NONE;

    VerifyOrExit(IsEnabled());

    RemoveInboundMulticastForwardingCache(aAddress);
    UpdateMldReport(aAddress, false);

    LogResult(error, "MulticastRoutingManager: %s: %s", __FUNCTION__, aAddress.ToString().AsCString());

exit:
    return;
}

void MulticastRoutingManager::UpdateMldReport(const Ip6::Address &aAddress, bool isAdd)
{
    struct ipv6_mreq ipv6mr;
    otError          error = OT_ERROR_NONE;

    ipv6mr.ipv6mr_interface = if_nametoindex(gBackboneNetifName);
    memcpy(&ipv6mr.ipv6mr_multiaddr, aAddress.GetBytes(), sizeof(ipv6mr.ipv6mr_multiaddr));
    error = (setsockopt(mMulticastRouterSock, IPPROTO_IPV6, (isAdd ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP),
                        (void *)&ipv6mr, sizeof(ipv6mr))
                 ? OT_ERROR_FAILED
                 : OT_ERROR_NONE);

    LogResult(error, "MulticastRoutingManager: %s: address %s %s", __FUNCTION__, aAddress.ToString().AsCString(),
              (isAdd ? "Added" : "Removed"));
}

bool MulticastRoutingManager::HasMulticastListener(const Ip6::Address &aAddress) const
{
    bool                                      found = false;
    otBackboneRouterMulticastListenerIterator iter  = OT_BACKBONE_ROUTER_MULTICAST_LISTENER_ITERATOR_INIT;
    otBackboneRouterMulticastListenerInfo     listenerInfo;

    while (otBackboneRouterMulticastListenerGetNext(gInstance, &iter, &listenerInfo) == OT_ERROR_NONE)
    {
        VerifyOrExit(static_cast<const Ip6::Address &>(listenerInfo.mAddress) != aAddress, found = true);
    }

exit:
    return found;
}

void MulticastRoutingManager::Update(otSysMainloopContext &aContext)
{
    VerifyOrExit(IsEnabled());

    FD_SET(mMulticastRouterSock, &aContext.mReadFdSet);
    aContext.mMaxFd = OT_MAX(aContext.mMaxFd, mMulticastRouterSock);

exit:
    return;
}

void MulticastRoutingManager::Process(const otSysMainloopContext &aContext)
{
    VerifyOrExit(IsEnabled());

    ExpireMulticastForwardingCache();

    if (FD_ISSET(mMulticastRouterSock, &aContext.mReadFdSet))
    {
        ProcessMulticastRouterMessages();
    }

exit:
    return;
}

void MulticastRoutingManager::InitMulticastRouterSock(void)
{
    int                 one = 1;
    struct icmp6_filter filter;
    struct mif6ctl      mif6ctl;

    // Create a Multicast Routing socket
    mMulticastRouterSock = SocketWithCloseExec(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6, kSocketBlock);
    VerifyOrDie(mMulticastRouterSock != -1, OT_EXIT_ERROR_ERRNO);

    // Enable Multicast Forwarding in Kernel
    VerifyOrDie(0 == setsockopt(mMulticastRouterSock, IPPROTO_IPV6, MRT6_INIT, &one, sizeof(one)), OT_EXIT_ERROR_ERRNO);

    // Filter all ICMPv6 messages
    ICMP6_FILTER_SETBLOCKALL(&filter);
    VerifyOrDie(0 == setsockopt(mMulticastRouterSock, IPPROTO_ICMPV6, ICMP6_FILTER, (void *)&filter, sizeof(filter)),
                OT_EXIT_ERROR_ERRNO);

    memset(&mif6ctl, 0, sizeof(mif6ctl));
    mif6ctl.mif6c_flags     = 0;
    mif6ctl.vifc_threshold  = 1;
    mif6ctl.vifc_rate_limit = 0;

    // Add Thread network interface to MIF
    mif6ctl.mif6c_mifi = kMifIndexThread;
    mif6ctl.mif6c_pifi = if_nametoindex(gNetifName);
    VerifyOrDie(mif6ctl.mif6c_pifi > 0, OT_EXIT_ERROR_ERRNO);
    VerifyOrDie(0 == setsockopt(mMulticastRouterSock, IPPROTO_IPV6, MRT6_ADD_MIF, &mif6ctl, sizeof(mif6ctl)),
                OT_EXIT_ERROR_ERRNO);

    // Add Backbone network interface to MIF
    mif6ctl.mif6c_mifi = kMifIndexBackbone;
    mif6ctl.mif6c_pifi = if_nametoindex(gBackboneNetifName);
    VerifyOrDie(mif6ctl.mif6c_pifi > 0, OT_EXIT_ERROR_ERRNO);
    VerifyOrDie(0 == setsockopt(mMulticastRouterSock, IPPROTO_IPV6, MRT6_ADD_MIF, &mif6ctl, sizeof(mif6ctl)),
                OT_EXIT_ERROR_ERRNO);
}

void MulticastRoutingManager::FinalizeMulticastRouterSock(void)
{
    VerifyOrExit(IsEnabled());

    close(mMulticastRouterSock);
    mMulticastRouterSock = -1;

exit:
    return;
}

void MulticastRoutingManager::ProcessMulticastRouterMessages(void)
{
    otError         error = OT_ERROR_NONE;
    char            buf[sizeof(struct mrt6msg)];
    int             nr;
    struct mrt6msg *mrt6msg;
    Ip6::Address    src, dst;

    nr = read(mMulticastRouterSock, buf, sizeof(buf));

    VerifyOrExit(nr >= static_cast<int>(sizeof(struct mrt6msg)), error = OT_ERROR_FAILED);

    mrt6msg = reinterpret_cast<struct mrt6msg *>(buf);

    VerifyOrExit(mrt6msg->im6_mbz == 0);
    VerifyOrExit(mrt6msg->im6_msgtype == MRT6MSG_NOCACHE);

    src.SetBytes(mrt6msg->im6_src.s6_addr);
    dst.SetBytes(mrt6msg->im6_dst.s6_addr);

    error = AddMulticastForwardingCache(src, dst, static_cast<MifIndex>(mrt6msg->im6_mif));

exit:
    LogResult(error, "MulticastRoutingManager: %s", __FUNCTION__);
}

otError MulticastRoutingManager::AddMulticastForwardingCache(const Ip6::Address &aSrcAddr,
                                                             const Ip6::Address &aGroupAddr,
                                                             MifIndex            aIif)
{
    otError        error = OT_ERROR_NONE;
    struct mf6cctl mf6cctl;
    MifIndex       forwardMif = kMifIndexNone;

    VerifyOrExit(aIif == kMifIndexThread || aIif == kMifIndexBackbone, error = OT_ERROR_INVALID_ARGS);

    ExpireMulticastForwardingCache();

    if (aIif == kMifIndexBackbone)
    {
        // Forward multicast traffic from Backbone to Thread if the group address is subscribed by any Thread device via
        // MLR.
        if (HasMulticastListener(aGroupAddr))
        {
            forwardMif = kMifIndexThread;
        }
    }
    else
    {
        // Forward multicast traffic from Thread to Backbone if multicast scope > kRealmLocalScope
        // TODO: (MLR) allow scope configuration of outbound multicast routing
        if (aGroupAddr.GetScope() > Ip6::Address::kRealmLocalScope)
        {
            forwardMif = kMifIndexBackbone;
        }
    }

    memset(&mf6cctl, 0, sizeof(mf6cctl));

    memcpy(mf6cctl.mf6cc_origin.sin6_addr.s6_addr, aSrcAddr.GetBytes(), sizeof(mf6cctl.mf6cc_origin.sin6_addr.s6_addr));
    memcpy(mf6cctl.mf6cc_mcastgrp.sin6_addr.s6_addr, aGroupAddr.GetBytes(),
           sizeof(mf6cctl.mf6cc_mcastgrp.sin6_addr.s6_addr));
    mf6cctl.mf6cc_parent = aIif;

    if (forwardMif != kMifIndexNone)
    {
        IF_SET(forwardMif, &mf6cctl.mf6cc_ifset);
    }

    // Note that kernel reports repetitive `MRT6MSG_NOCACHE` upcalls with a rate limit (e.g. once per 10s for Linux).
    // Because of it, we need to add a "blocking" MFC even if there is no forwarding for this group address.
    // When a  Multicast Listener is later added, the "blocking" MFC will be altered to be a "forwarding" MFC so that
    // corresponding multicast traffic can be forwarded instantly.
    VerifyOrExit(0 == setsockopt(mMulticastRouterSock, IPPROTO_IPV6, MRT6_ADD_MFC, &mf6cctl, sizeof(mf6cctl)),
                 error = OT_ERROR_FAILED);

    SaveMulticastForwardingCache(aSrcAddr, aGroupAddr, aIif, forwardMif);
exit:
    LogResult(error, "MulticastRoutingManager: %s: add dynamic route: %s %s => %s %s", __FUNCTION__,
              MifIndexToString(aIif), aSrcAddr.ToString().AsCString(), aGroupAddr.ToString().AsCString(),
              MifIndexToString(forwardMif));

    return error;
}

void MulticastRoutingManager::UnblockInboundMulticastForwardingCache(const Ip6::Address &aGroupAddr)
{
    struct mf6cctl mf6cctl;

    memset(&mf6cctl, 0, sizeof(mf6cctl));
    memcpy(mf6cctl.mf6cc_mcastgrp.sin6_addr.s6_addr, aGroupAddr.GetBytes(),
           sizeof(mf6cctl.mf6cc_mcastgrp.sin6_addr.s6_addr));
    mf6cctl.mf6cc_parent = kMifIndexBackbone;
    IF_SET(kMifIndexThread, &mf6cctl.mf6cc_ifset);

    for (MulticastForwardingCache &mfc : mMulticastForwardingCacheTable)
    {
        otError error;

        if (!mfc.IsValid() || mfc.mIif != kMifIndexBackbone || mfc.mOif == kMifIndexThread ||
            mfc.mGroupAddr != aGroupAddr)
        {
            continue;
        }

        // Unblock this inbound route
        memcpy(mf6cctl.mf6cc_origin.sin6_addr.s6_addr, mfc.mSrcAddr.GetBytes(),
               sizeof(mf6cctl.mf6cc_origin.sin6_addr.s6_addr));

        error = (0 == setsockopt(mMulticastRouterSock, IPPROTO_IPV6, MRT6_ADD_MFC, &mf6cctl, sizeof(mf6cctl)))
                    ? OT_ERROR_NONE
                    : OT_ERROR_FAILED;

        mfc.Set(kMifIndexBackbone, kMifIndexThread);

        LogResult(error, "MulticastRoutingManager: %s: %s %s => %s %s", __FUNCTION__, MifIndexToString(mfc.mIif),
                  mfc.mSrcAddr.ToString().AsCString(), mfc.mGroupAddr.ToString().AsCString(),
                  MifIndexToString(kMifIndexThread));
    }
}

void MulticastRoutingManager::RemoveInboundMulticastForwardingCache(const Ip6::Address &aGroupAddr)
{
    for (MulticastForwardingCache &mfc : mMulticastForwardingCacheTable)
    {
        if (mfc.IsValid() && mfc.mIif == kMifIndexBackbone && mfc.mGroupAddr == aGroupAddr)
        {
            RemoveMulticastForwardingCache(mfc);
        }
    }
}

void MulticastRoutingManager::ExpireMulticastForwardingCache(void)
{
    struct sioc_sg_req6 sioc_sg_req6;
    uint64_t            now = otPlatTimeGet();
    struct mf6cctl      mf6cctl;

    VerifyOrExit(now >= mLastExpireTime + kMulticastForwardingCacheExpiringInterval * US_PER_S);

    mLastExpireTime = now;

    memset(&mf6cctl, 0, sizeof(mf6cctl));
    memset(&sioc_sg_req6, 0, sizeof(sioc_sg_req6));

    for (MulticastForwardingCache &mfc : mMulticastForwardingCacheTable)
    {
        if (mfc.IsValid() && mfc.mLastUseTime + kMulticastForwardingCacheExpireTimeout * US_PER_S < now)
        {
            if (!UpdateMulticastRouteInfo(mfc))
            {
                // The multicast route is expired
                RemoveMulticastForwardingCache(mfc);
            }
        }
    }

    DumpMulticastForwardingCache();

exit:
    return;
}

bool MulticastRoutingManager::UpdateMulticastRouteInfo(MulticastForwardingCache &aMfc) const
{
    bool                updated = false;
    struct sioc_sg_req6 sioc_sg_req6;

    memset(&sioc_sg_req6, 0, sizeof(sioc_sg_req6));

    memcpy(sioc_sg_req6.src.sin6_addr.s6_addr, aMfc.mSrcAddr.GetBytes(), sizeof(sioc_sg_req6.src.sin6_addr.s6_addr));
    memcpy(sioc_sg_req6.grp.sin6_addr.s6_addr, aMfc.mGroupAddr.GetBytes(), sizeof(sioc_sg_req6.grp.sin6_addr.s6_addr));

    if (ioctl(mMulticastRouterSock, SIOCGETSGCNT_IN6, &sioc_sg_req6) != -1)
    {
        unsigned long validPktCnt;

        otLogDebgPlat("MulticastRoutingManager: %s: SIOCGETSGCNT_IN6 %s => %s: bytecnt=%lu, pktcnt=%lu, wrong_if=%lu",
                      __FUNCTION__, aMfc.mSrcAddr.ToString().AsCString(), aMfc.mGroupAddr.ToString().AsCString(),
                      sioc_sg_req6.bytecnt, sioc_sg_req6.pktcnt, sioc_sg_req6.wrong_if);

        validPktCnt = sioc_sg_req6.pktcnt - sioc_sg_req6.wrong_if;
        if (validPktCnt != aMfc.mValidPktCnt)
        {
            aMfc.SetValidPktCnt(validPktCnt);

            updated = true;
        }
    }
    else
    {
        otLogWarnPlat("MulticastRoutingManager: %s: SIOCGETSGCNT_IN6 %s => %s failed: %s", __FUNCTION__,
                      aMfc.mSrcAddr.ToString().AsCString(), aMfc.mGroupAddr.ToString().AsCString(), strerror(errno));
    }

    return updated;
}

const char *MulticastRoutingManager::MifIndexToString(MifIndex aMif)
{
    const char *string = "Unknown";

    switch (aMif)
    {
    case kMifIndexNone:
        string = "None";
        break;
    case kMifIndexThread:
        string = "Thread";
        break;
    case kMifIndexBackbone:
        string = "Backbone";
        break;
    }

    return string;
}

void MulticastRoutingManager::DumpMulticastForwardingCache(void) const
{
#if OPENTHREAD_CONFIG_LOG_PLATFORM && (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_DEBG)
    otLogDebgPlat("MulticastRoutingManager: ==================== MFC ENTRIES ====================");

    for (const MulticastForwardingCache &mfc : mMulticastForwardingCacheTable)
    {
        if (mfc.IsValid())
        {
            otLogDebgPlat("MulticastRoutingManager: %s %s => %s %s", MifIndexToString(mfc.mIif),
                          mfc.mSrcAddr.ToString().AsCString(), mfc.mGroupAddr.ToString().AsCString(),
                          MifIndexToString(mfc.mOif));
        }
    }

    otLogDebgPlat("MulticastRoutingManager: =====================================================");
#endif
}

void MulticastRoutingManager::HandleStateChange(otInstance *aInstance, otChangedFlags aFlags)
{
    if (aFlags & OT_CHANGED_THREAD_BACKBONE_ROUTER_STATE)
    {
        otBackboneRouterState state = otBackboneRouterGetState(aInstance);

        switch (state)
        {
        case OT_BACKBONE_ROUTER_STATE_DISABLED:
        case OT_BACKBONE_ROUTER_STATE_SECONDARY:
            Disable();
            break;
        case OT_BACKBONE_ROUTER_STATE_PRIMARY:
            Enable();
            break;
        }
    }
}

void MulticastRoutingManager::MulticastForwardingCache::Set(MulticastRoutingManager::MifIndex aIif,
                                                            MulticastRoutingManager::MifIndex aOif)
{
    mIif         = aIif;
    mOif         = aOif;
    mValidPktCnt = 0;
    mLastUseTime = otPlatTimeGet();
}

void MulticastRoutingManager::MulticastForwardingCache::Set(const Ip6::Address &aSrcAddr,
                                                            const Ip6::Address &aGroupAddr,
                                                            MifIndex            aIif,
                                                            MifIndex            aOif)
{
    mSrcAddr   = aSrcAddr;
    mGroupAddr = aGroupAddr;
    Set(aIif, aOif);
}

void MulticastRoutingManager::MulticastForwardingCache::SetValidPktCnt(unsigned long aValidPktCnt)
{
    mValidPktCnt = aValidPktCnt;
    mLastUseTime = otPlatTimeGet();
}

void MulticastRoutingManager::SaveMulticastForwardingCache(const Ip6::Address &              aSrcAddr,
                                                           const Ip6::Address &              aGroupAddr,
                                                           MulticastRoutingManager::MifIndex aIif,
                                                           MulticastRoutingManager::MifIndex aOif)
{
    MulticastForwardingCache *invalid = nullptr;
    MulticastForwardingCache *oldest  = nullptr;

    for (MulticastForwardingCache &mfc : mMulticastForwardingCacheTable)
    {
        if (mfc.IsValid())
        {
            if (mfc.mSrcAddr == aSrcAddr && mfc.mGroupAddr == aGroupAddr)
            {
                mfc.Set(aIif, aOif);
                ExitNow();
            }

            if (oldest == nullptr || mfc.mLastUseTime < oldest->mLastUseTime)
            {
                oldest = &mfc;
            }
        }
        else if (invalid == nullptr)
        {
            invalid = &mfc;
        }
    }

    if (invalid != nullptr)
    {
        invalid->Set(aSrcAddr, aGroupAddr, aIif, aOif);
    }
    else
    {
        RemoveMulticastForwardingCache(*oldest);
        oldest->Set(aSrcAddr, aGroupAddr, aIif, aOif);
    }

exit:
    return;
}

void MulticastRoutingManager::RemoveMulticastForwardingCache(
    MulticastRoutingManager::MulticastForwardingCache &aMfc) const
{
    otError        error;
    struct mf6cctl mf6cctl;

    memset(&mf6cctl, 0, sizeof(mf6cctl));

    memcpy(mf6cctl.mf6cc_origin.sin6_addr.s6_addr, aMfc.mSrcAddr.GetBytes(),
           sizeof(mf6cctl.mf6cc_origin.sin6_addr.s6_addr));
    memcpy(mf6cctl.mf6cc_mcastgrp.sin6_addr.s6_addr, aMfc.mGroupAddr.GetBytes(),
           sizeof(mf6cctl.mf6cc_mcastgrp.sin6_addr.s6_addr));

    mf6cctl.mf6cc_parent = aMfc.mIif;

    error = (0 == setsockopt(mMulticastRouterSock, IPPROTO_IPV6, MRT6_DEL_MFC, &mf6cctl, sizeof(mf6cctl)))
                ? OT_ERROR_NONE
                : OT_ERROR_FAILED;

    LogResult(error, "MulticastRoutingManager: %s: %s %s => %s %s", __FUNCTION__, MifIndexToString(aMfc.mIif),
              aMfc.mSrcAddr.ToString().AsCString(), aMfc.mGroupAddr.ToString().AsCString(),
              MifIndexToString(aMfc.mOif));

    aMfc.Erase();
}

} // namespace Posix
} // namespace ot

#endif // OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
