[mesh-forwarder] ensure mesh dst checks for dst unreach (#4879)

An out-dated EID-to-RLOC map cache may lead a device to send an IPv6
datagram to a device that does not have the IPv6 Destination Address
assigned to its interface. However, the existing implementation would
not send back an ICMPv6 Destination Unreachable message necessary to
invalidate the originator's EID-to-RLOC cache entry.

This implementation adds reachability checks on the mesh destination
receive path to ensure that reachability checks are performed in the
above situation.
This commit is contained in:
Jonathan Hui
2020-04-28 11:30:13 -07:00
parent 2567aec36f
commit 3c09c378d4
4 changed files with 45 additions and 7 deletions
+8 -2
View File
@@ -1102,9 +1102,12 @@ void MeshForwarder::HandleFragment(const uint8_t * aFrame,
message->SetNetworkTimeOffset(aLinkInfo.mNetworkTimeOffset);
#endif
// Security Check
VerifyOrExit(Get<Ip6::Filter>().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<Ip6::Filter>().Accept(*message), error = OT_ERROR_DROP);
#if OPENTHREAD_FTD
SendIcmpErrorIfDstUnreach(*message, aMacSource, aMacDest);
#endif
exit:
if (error == OT_ERROR_NONE)
+3
View File
@@ -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,
+29 -5
View File
@@ -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<ChildTable>().FindChild(aMacSource.GetShort(), Child::kInStateAnyExceptInvalid);
VerifyOrExit((child == NULL) || child->IsFullThreadDevice(), OT_NOOP);
aMessage.Read(0, sizeof(ip6header), &ip6header);
VerifyOrExit(!ip6header.GetDestination().IsMulticast() &&
Get<NetworkData::Leader>().IsOnMesh(ip6header.GetDestination()),
OT_NOOP);
error = Get<Mle::MleRouter>().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,
+5
View File
@@ -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