[ip6] drop forwarded packets with foreign link-local source address (#13317)

This commit updates `Ip6::SendRaw()` to drop packets forwarded from the
host stack or an adjacent infrastructure link into OpenThread if their
IPv6 source address is a link-local address that does not belong to the
Thread interface (`ThreadNetif`).

Updates to Nexus tests and test platform:
- Update `verify_1_3_DBR_TC_1.py` Step 7 by removing the destination
  address filter (`filter_ipv6_dst(ED_1_OMR)`). This strengthens the
  verification check to ensure that no packet with an infrastructure
  link-local source address (`ETH_1_LL_ADDR`) is ever forwarded onto
  the Thread mesh regardless of destination address.
- Add `InfraIf::FindAddress(const Ip6::Prefix &)` to look up addresses
  matching an IPv6 prefix on simulated infrastructure interfaces.
- Update `test_1_2_MATN_TC_21.cpp` Step 16 so the backbone host uses its
  address matching the Border Router's favored on-link prefix rather
  than its link-local address when sending multicast pings to `MA1`.
This commit is contained in:
Abtin Keshavarzian
2026-07-10 18:49:15 -07:00
committed by GitHub
parent 6dab219eef
commit d9ca7f05fc
5 changed files with 29 additions and 6 deletions
+9
View File
@@ -1102,6 +1102,15 @@ Error Ip6::SendRaw(OwnedPtr<Message> aMessagePtr)
ExitNow(error = kErrorDrop);
}
// When the message is forwarded from host to Thread, drop it if
// its source is a link-local address that does not belong to the
// Thread interface.
if (header.GetSource().IsLinkLocalUnicast() && !Get<ThreadNetif>().HasUnicastAddress(header.GetSource()))
{
LogInfo("Dropping packet with foreign link-local source address");
ExitNow(error = kErrorDrop);
}
// 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()) ||
+8 -3
View File
@@ -97,14 +97,19 @@ void InfraIf::RemoveAllAddresses(void)
const Ip6::Address *InfraIf::FindAddress(const char *aPrefix) const
{
Ip6::Prefix prefix;
const Ip6::Address *matchedAddress = nullptr;
Ip6::Prefix prefix;
SuccessOrQuit(prefix.FromString(aPrefix));
return FindAddress(prefix);
}
const Ip6::Address *InfraIf::FindAddress(const Ip6::Prefix &aPrefix) const
{
const Ip6::Address *matchedAddress = nullptr;
for (const Ip6::Address &address : mAddresses)
{
if (address.MatchesPrefix(prefix))
if (address.MatchesPrefix(aPrefix))
{
matchedAddress = &address;
break;
+1
View File
@@ -53,6 +53,7 @@ public:
void RemoveAllAddresses(void);
const Ip6::Address *FindAddress(const char *aPrefix) const;
const Ip6::Address *FindAddress(const Ip6::Prefix &aPrefix) const;
const Ip6::Address &FindMatchingAddress(const char *aPrefix) const;
const Ip6::Address &GetLinkLocalAddress(void) const { return mAddresses[0]; }
+11 -2
View File
@@ -149,6 +149,7 @@ void TestMatnTc21(void)
Ip6::Address mae1;
Ip6::Address mae2;
Ip6::Address mae3;
Ip6::Prefix onLinkPrefix;
br1.SetName("BR_1");
br2.SetName("BR_2");
@@ -206,6 +207,8 @@ void TestMatnTc21(void)
VerifyOrQuit(br1.Get<BackboneRouter::Local>().IsPrimary());
VerifyOrQuit(!br2.Get<BackboneRouter::Local>().IsPrimary());
SuccessOrQuit(br1.Get<BorderRouter::RoutingManager>().GetFavoredOnLinkPrefix(onLinkPrefix));
nexus.AddTestVar("MA1", kMA1);
nexus.AddTestVar("MA3", kMA3);
nexus.AddTestVar("MA5", kMA5);
@@ -410,8 +413,14 @@ void TestMatnTc21(void)
* - N/A
*/
Log("Step 16: Host sends a ICMPv6 Echo Request to MA1 on the backbone link.");
host.mInfraIf.SendEchoRequest(host.mInfraIf.GetLinkLocalAddress(), ma1, kEchoIdentifier, kEchoPayloadSize);
nexus.AdvanceTime(0);
{
const Ip6::Address *srcAddr;
srcAddr = host.mInfraIf.FindAddress(onLinkPrefix);
VerifyOrQuit(srcAddr != nullptr);
host.mInfraIf.SendEchoRequest(*srcAddr, ma1, kEchoIdentifier, kEchoPayloadSize);
nexus.AdvanceTime(0);
}
/**
* Step 17
-1
View File
@@ -301,7 +301,6 @@ def verify(pv):
pkts.filter_wpan_src64(BR_1).\
filter_ipv6_src(Ipv6Addr(pv.vars['ETH_1_LL_ADDR'])).\
filter_ipv6_dst(ED_1_OMR).\
filter_ping_request().\
must_not_next()