diff --git a/src/core/net/ip6.cpp b/src/core/net/ip6.cpp index f74ec64b0..4395881c0 100644 --- a/src/core/net/ip6.cpp +++ b/src/core/net/ip6.cpp @@ -978,9 +978,13 @@ otError Ip6::ProcessReceiveCallback(Message & aMessage, if (mIsReceiveIp6FilterEnabled) { // do not pass messages sent to an RLOC/ALOC, except Service Locator - VerifyOrExit(!aMessageInfo.GetSockAddr().GetIid().IsLocator() || - aMessageInfo.GetSockAddr().GetIid().IsAnycastServiceLocator(), +#if !OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE + bool isLocator = Get().IsMeshLocalAddress(aMessageInfo.GetSockAddr()) && + aMessageInfo.GetSockAddr().GetIid().IsLocator(); + + VerifyOrExit(!isLocator || aMessageInfo.GetSockAddr().GetIid().IsAnycastServiceLocator(), error = OT_ERROR_NO_ROUTE); +#endif switch (aIpProto) { diff --git a/src/posix/platform/netif.cpp b/src/posix/platform/netif.cpp index 179dbc506..0bae6928a 100644 --- a/src/posix/platform/netif.cpp +++ b/src/posix/platform/netif.cpp @@ -1479,6 +1479,7 @@ void platformNetifInit(otInstance *aInstance, const char *aInterfaceName) mldListenerInit(); #endif + otIp6SetReceiveFilterEnabled(aInstance, true); otIcmp6SetEchoMode(aInstance, OT_ICMP6_ECHO_HANDLER_DISABLED); otIp6SetReceiveCallback(aInstance, processReceive, aInstance); otIp6SetAddressCallback(aInstance, processAddressChange, aInstance); diff --git a/tests/scripts/thread-cert/backbone/test_mle_must_not_send_icmpv6_destination_unreachable.py b/tests/scripts/thread-cert/backbone/test_mle_must_not_send_icmpv6_destination_unreachable.py new file mode 100644 index 000000000..8780c7b6e --- /dev/null +++ b/tests/scripts/thread-cert/backbone/test_mle_must_not_send_icmpv6_destination_unreachable.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2020, The OpenThread Authors. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# This test verifies that no ICMPv6 message is sent for MLE. +# +import unittest + +import thread_cert +from pktverify.consts import ICMPV6_TYPE_DESTINATION_UNREACHABLE +from pktverify.packet_verifier import PacketVerifier + +PBBR = 1 +ROUTER = 2 + + +class TestMleMustNotSendIcmpv6DestinationUnreachable(thread_cert.TestCase): + USE_MESSAGE_FACTORY = False + + # Topology: + # + # ------(eth)---------- + # | + # PBBR---ROUTER + # + TOPOLOGY = { + PBBR: { + 'name': 'PBBR', + 'allowlist': [ROUTER], + 'is_otbr': True, + 'version': '1.2', + 'router_selection_jitter': 1, + }, + ROUTER: { + 'name': 'ROUTER', + 'allowlist': [PBBR], + 'version': '1.2', + 'router_selection_jitter': 1, + }, + } + + def test(self): + self.nodes[PBBR].start() + self.simulator.go(5) + self.assertEqual('leader', self.nodes[PBBR].get_state()) + self.nodes[PBBR].enable_backbone_router() + self.simulator.go(3) + self.assertTrue(self.nodes[PBBR].is_primary_backbone_router) + + self.nodes[ROUTER].start() + self.simulator.go(5) + self.assertEqual('router', self.nodes[ROUTER].get_state()) + + self.simulator.go(5) + + self.collect_ipaddrs() + + def verify(self, pv: PacketVerifier): + pkts = pv.pkts + pv.add_common_vars() + pv.summary.show() + + with pkts.save_index(): + pv.verify_attached('ROUTER') + + PBBR = pv.vars['PBBR'] + ROUTER = pv.vars['ROUTER'] + + # PBBR MUST NOT send ICMPv6 Destination Unreachable + pkts.filter_wpan_src64(PBBR).filter_wpan_dst64(ROUTER).filter( + f'icmpv6.type == {ICMPV6_TYPE_DESTINATION_UNREACHABLE}').must_not_next() + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/scripts/thread-cert/pktverify/consts.py b/tests/scripts/thread-cert/pktverify/consts.py index 23a4cea22..3ae841d96 100644 --- a/tests/scripts/thread-cert/pktverify/consts.py +++ b/tests/scripts/thread-cert/pktverify/consts.py @@ -281,6 +281,9 @@ CSL_IE_ID = 0x1a # Thread Version TLV value THREAD_VERSION_1_2 = 3 +# ICMPv6 Types +ICMPV6_TYPE_DESTINATION_UNREACHABLE = 1 + if __name__ == '__main__': from pktverify.addrs import Ipv6Addr diff --git a/tests/scripts/thread-cert/pktverify/packet_filter.py b/tests/scripts/thread-cert/pktverify/packet_filter.py index 4e61f9571..0076a9f03 100644 --- a/tests/scripts/thread-cert/pktverify/packet_filter.py +++ b/tests/scripts/thread-cert/pktverify/packet_filter.py @@ -26,6 +26,7 @@ # POSSIBILITY OF SUCH DAMAGE. # +import logging import sys from operator import attrgetter from typing import Optional, Callable, Tuple @@ -238,6 +239,9 @@ class PacketFilter(object): if p is None: return else: + logging.error("Found unexpected packet at #%s", self.index) + p.show() + p.debug_fields() raise errors.UnexpectedPacketFound(self.index, p) def _on_found_next(self, idx: int, p: Packet):