diff --git a/src/core/radio/trel_interface.cpp b/src/core/radio/trel_interface.cpp index 7fa190767..2f69c7d0a 100644 --- a/src/core/radio/trel_interface.cpp +++ b/src/core/radio/trel_interface.cpp @@ -324,15 +324,9 @@ Interface::Peer *Interface::GetNewPeerEntry(void) } #if OPENTHREAD_FTD + if (Get().FindRxOnlyNeighborRouter(entry.GetExtAddress()) != nullptr) { - Mac::Address macAddress; - - macAddress.SetExtended(entry.GetExtAddress()); - - if (Get().FindRxOnlyNeighborRouter(macAddress) != nullptr) - { - continue; - } + continue; } #endif diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index d4bdbc10f..0eaedd9d8 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -2464,6 +2464,9 @@ void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageIn Mac::ExtAddress extAddr; uint8_t command; Neighbor *neighbor; +#if OPENTHREAD_FTD + bool isNeighborRxOnly = false; +#endif LogDebg("Receive MLE message"); @@ -2517,6 +2520,18 @@ void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageIn neighbor = (command == kCommandChildIdResponse) ? mNeighborTable.FindParent(extAddr) : mNeighborTable.FindNeighbor(extAddr); +#if OPENTHREAD_FTD + if (neighbor == nullptr) + { + // As an FED, we may have rx-only neighbors. We find and set + // `neighbor` to perform security processing (frame counter + // and key sequence checks) for messages from such neighbors. + + neighbor = mNeighborTable.FindRxOnlyNeighborRouter(extAddr); + isNeighborRxOnly = true; + } +#endif + if (neighbor != nullptr && neighbor->IsStateValid()) { if (keySequence == neighbor->GetKeySequence()) @@ -2564,6 +2579,30 @@ void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageIn } #endif +#if OPENTHREAD_FTD + if (isNeighborRxOnly) + { + // Clear the `neighbor` if it is a rx-only one before calling + // `Handle{Msg}()`, except for a subset of MLE messages such + // as MLE Advertisement. This ensures that, as an FED, we are + // selective about which messages to process from rx-only + // neighbors. + + switch (command) + { + case kCommandAdvertisement: + case kCommandLinkRequest: + case kCommandLinkAccept: + case kCommandLinkAcceptAndRequest: + break; + + default: + neighbor = nullptr; + break; + } + } +#endif + rxInfo.mKeySequence = keySequence; rxInfo.mFrameCounter = frameCounter; rxInfo.mNeighbor = neighbor; diff --git a/src/core/thread/neighbor_table.cpp b/src/core/thread/neighbor_table.cpp index d5f679b1f..39bd0663d 100644 --- a/src/core/thread/neighbor_table.cpp +++ b/src/core/thread/neighbor_table.cpp @@ -167,6 +167,15 @@ exit: return neighbor; } +Neighbor *NeighborTable::FindRxOnlyNeighborRouter(const Mac::ExtAddress &aExtAddress) +{ + Mac::Address macAddress; + + macAddress.SetExtended(aExtAddress); + + return FindRxOnlyNeighborRouter(macAddress); +} + Neighbor *NeighborTable::FindRxOnlyNeighborRouter(const Mac::Address &aMacAddress) { Neighbor *neighbor = nullptr; diff --git a/src/core/thread/neighbor_table.hpp b/src/core/thread/neighbor_table.hpp index 321983d45..67338c9fd 100644 --- a/src/core/thread/neighbor_table.hpp +++ b/src/core/thread/neighbor_table.hpp @@ -177,6 +177,17 @@ public: Neighbor *FindNeighbor(const Ip6::Address &aIp6Address, Neighbor::StateFilter aFilter = Neighbor::kInStateValidOrRestoring); + /** + * Searches in the neighbor table to find a `Neighbor` for which a one-way link is maintained (as in the + * case of an FTD child with neighbor routers). + * + * @param[in] aExtAddress An Extended address. + * + * @returns A pointer to the Neighbor corresponding to @p aExtAddress, `nullptr` otherwise. + * + */ + Neighbor *FindRxOnlyNeighborRouter(const Mac::ExtAddress &aExtAddress); + /** * Searches in the neighbor table to find a `Neighbor` for which a one-way link is maintained (as in the * case of an FTD child with neighbor routers).