Skip to content

Commit

Permalink
[netdata] fix the source address check in LeaderBase::RouteLookup() (
Browse files Browse the repository at this point in the history
…openthread#9335)

In `LeaderBase::RouteLookup()`, OT currently checks the source address
of the packet to ensure it matches any of the Prefix TLV in leader's
netdata. Actually it should also verify that the Prefix TLV has a
Border Router sub-TLV.

In the current implementation, OT may wrongly send/forward a packet to
BR when its source address matches with a Prefix TLV which only
contains an External Route sub-TLV. This lets BR accidentally forward
packets from Thread to infra network. For example, a packet from
Mesh-Local address to On-Link address will be wrongly forwarded to
infra network.

I recently noticed this problem because we're now using either
`fc00:/7` or `::/0` for external routes in netdata, which always
matches Mesh-Local source addresses and makes the issue more obvious.
  • Loading branch information
superwhd authored Aug 3, 2023
1 parent 037056b commit 499f668
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/core/thread/network_data_leader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,11 @@ Error LeaderBase::RouteLookup(const Ip6::Address &aSource, const Ip6::Address &a

while ((prefixTlv = FindNextMatchingPrefixTlv(aSource, prefixTlv)) != nullptr)
{
if (prefixTlv->FindSubTlv<BorderRouterTlv>() == nullptr)
{
continue;
}

if (ExternalRouteLookup(prefixTlv->GetDomainId(), aDestination, aRloc16) == kErrorNone)
{
ExitNow(error = kErrorNone);
Expand Down
8 changes: 8 additions & 0 deletions tests/scripts/thread-cert/border_router/test_firewall.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,10 @@ def host_ping_ether(dest, interface, ttl=10, add_interface=False, add_route=Fals
# 12. Host pings MA1 from router1's MLE-ID.
self.assertFalse(host_ping_ether(MA1, ttl=10, interface=router1.get_mleid(), add_interface=True))

# 13. Router1 pings Host from router1's MLE-ID.
self.assertFalse(
router1.ping(host.get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0], interface=router1.get_mleid()))

self.collect_ipaddrs()
self.collect_rlocs()
self.collect_rloc16s()
Expand Down Expand Up @@ -265,6 +269,10 @@ def verify(self, pv: pktverify.packet_verifier.PacketVerifier):
pkts.filter_wpan_src64(
vars['BR_1']).filter_AMPLFMA().filter_ping_request(identifier=_pkt.icmpv6.echo.identifier).must_not_next()

# 13. Router1 pings Host from router1's MLE-ID.
pkts.filter_eth_src(vars['BR_1_ETH']).filter_ipv6_src_dst(
vars['Router_1_MLEID'], vars['Host_BGUA']).filter_ping_request().must_not_next()


if __name__ == '__main__':
unittest.main()

0 comments on commit 499f668

Please sign in to comment.