diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index 124b4685c..c30f677fc 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -1102,9 +1102,12 @@ void MeshForwarder::HandleFragment(const uint8_t * aFrame, message->SetNetworkTimeOffset(aLinkInfo.mNetworkTimeOffset); #endif - // Security Check VerifyOrExit(Get().Accept(*message), error = OT_ERROR_DROP); +#if OPENTHREAD_FTD + SendIcmpErrorIfDstUnreach(*message, aMacSource, aMacDest); +#endif + // Allow re-assembly of only one message at a time on a SED by clearing // any remaining fragments in reassembly list upon receiving of a new // (secure) first fragment. @@ -1301,9 +1304,12 @@ void MeshForwarder::HandleLowpanHC(const uint8_t * aFrame, message->SetNetworkTimeOffset(aLinkInfo.mNetworkTimeOffset); #endif - // Security Check VerifyOrExit(Get().Accept(*message), error = OT_ERROR_DROP); +#if OPENTHREAD_FTD + SendIcmpErrorIfDstUnreach(*message, aMacSource, aMacDest); +#endif + exit: if (error == OT_ERROR_NONE) diff --git a/src/core/thread/mesh_forwarder.hpp b/src/core/thread/mesh_forwarder.hpp index efffdcac3..259ee06df 100644 --- a/src/core/thread/mesh_forwarder.hpp +++ b/src/core/thread/mesh_forwarder.hpp @@ -336,6 +336,9 @@ private: kMessageEvict, ///< Indicates that the message was evicted. }; + void SendIcmpErrorIfDstUnreach(const Message & aMessage, + const Mac::Address &aMacSource, + const Mac::Address &aMacDest); otError CheckReachability(const uint8_t * aFrame, uint16_t aFrameLength, const Mac::Address &aMeshSource, diff --git a/src/core/thread/mesh_forwarder_ftd.cpp b/src/core/thread/mesh_forwarder_ftd.cpp index f77992c58..e2df50514 100644 --- a/src/core/thread/mesh_forwarder_ftd.cpp +++ b/src/core/thread/mesh_forwarder_ftd.cpp @@ -500,11 +500,6 @@ otError MeshForwarder::UpdateIp6RouteFtd(Ip6::Header &ip6Header, Message &aMessa } exit: - if (error == OT_ERROR_NO_ROUTE) - { - SendDestinationUnreachable(mMeshSource, aMessage); - } - return error; } @@ -521,6 +516,35 @@ otError MeshForwarder::GetIp6Header(const uint8_t * aFrame, nextHeaderCompressed); } +void MeshForwarder::SendIcmpErrorIfDstUnreach(const Message & aMessage, + const Mac::Address &aMacSource, + const Mac::Address &aMacDest) +{ + otError error; + Ip6::Header ip6header; + Child * child; + + VerifyOrExit(aMacSource.IsShort() && aMacDest.IsShort(), OT_NOOP); + + child = Get().FindChild(aMacSource.GetShort(), Child::kInStateAnyExceptInvalid); + VerifyOrExit((child == NULL) || child->IsFullThreadDevice(), OT_NOOP); + + aMessage.Read(0, sizeof(ip6header), &ip6header); + VerifyOrExit(!ip6header.GetDestination().IsMulticast() && + Get().IsOnMesh(ip6header.GetDestination()), + OT_NOOP); + + error = Get().CheckReachability(aMacDest.GetShort(), ip6header); + + if (error == OT_ERROR_NO_ROUTE) + { + SendDestinationUnreachable(aMacSource.GetShort(), aMessage); + } + +exit: + return; +} + otError MeshForwarder::CheckReachability(const uint8_t * aFrame, uint16_t aFrameLength, const Mac::Address &aMeshSource, diff --git a/src/core/thread/mle_router.hpp b/src/core/thread/mle_router.hpp index 4578032b6..0f52ad1a9 100644 --- a/src/core/thread/mle_router.hpp +++ b/src/core/thread/mle_router.hpp @@ -897,6 +897,11 @@ public: static bool IsRouterIdValid(uint8_t aRouterId) { return aRouterId <= kMaxRouterId; } otError SendChildUpdateRequest(void) { return Mle::SendChildUpdateRequest(); } + + otError CheckReachability(uint16_t aMeshDest, Ip6::Header &aIp6Header) + { + return Mle::CheckReachability(aMeshDest, aIp6Header); + } }; #endif // OPENTHREAD_MTD