diff --git a/include/openthread/instance.h b/include/openthread/instance.h index ae50bbf8d2b..ab0d5f63be4 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -53,7 +53,7 @@ extern "C" { * @note This number versions both OpenThread platform and user APIs. * */ -#define OPENTHREAD_API_VERSION (409) +#define OPENTHREAD_API_VERSION (410) /** * @addtogroup api-instance diff --git a/include/openthread/thread_ftd.h b/include/openthread/thread_ftd.h index 0928acc88ae..14aab130762 100644 --- a/include/openthread/thread_ftd.h +++ b/include/openthread/thread_ftd.h @@ -851,6 +851,36 @@ void otThreadSetCcmEnabled(otInstance *aInstance, bool aEnabled); */ void otThreadSetThreadVersionCheckEnabled(otInstance *aInstance, bool aEnabled); +/** + * Enables or disables the filter to drop TMF UDP messages from untrusted origin. + * + * TMF messages are only trusted when they originate from a trusted source, such as the Thread interface. In + * special cases, such as when a device uses platform UDP socket to send TMF messages, they will be dropped due + * to untrusted origin. This filter is enabled by default. + * + * When this filter is disabled, UDP messages sent to the TMF port that originate from untrusted origin (such as + * host, CLI or an external IPv6 node) will be allowed. + * + * @note This API requires `OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE` and is only used by Thread Test Harness + * to test network behavior by sending special TMF messages from the CLI on a POSIX host. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aEnabled TRUE to enable filter, FALSE otherwise. + * + */ +void otThreadSetTmfOriginFilterEnabled(otInstance *aInstance, bool aEnabled); + +/** + * Indicates whether the filter that drops TMF UDP messages from untrusted origin is enabled or not. + * + * This is intended for testing only and available when `OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE` config is enabled. + * + * @retval TRUE The filter is enabled. + * @retval FALSE The filter is not enabled. + * + */ +bool otThreadIsTmfOriginFilterEnabled(otInstance *aInstance); + /** * Gets the range of router IDs that are allowed to assign to nodes within the thread network. * diff --git a/src/cli/README.md b/src/cli/README.md index 2921b19a641..272d4063fdc 100644 --- a/src/cli/README.md +++ b/src/cli/README.md @@ -121,6 +121,7 @@ Done - [srp](README_SRP.md) - [tcat](README_TCAT.md) - [tcp](README_TCP.md) +- [test](#test-tmforiginfilter-enabledisable) - [thread](#thread-start) - [timeinqueue](#timeinqueue) - [trel](#trel) @@ -3609,6 +3610,38 @@ Try to switch to state `detached`, `child`, `router` or `leader`. Done ``` +### test tmforiginfilter \[enable|disable\] + +Enable/disable filter that drops UDP messages sent to the TMF port from untrusted origin. Also get the current state of the filter if no argument is specified. + +Note: This filter is enabled by default. + +This command is intended for testing only. `OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE` is required for all `test` sub-commands. + +Get the current state of the filter. + +``` +> test tmforiginfilter +Enabled +``` + +Enable or disable the filter. + +``` +> test tmforiginfilter enable +Done +> +> test tmforiginfilter +Enabled +> +> test tmforiginfilter disable +Done +> +> test tmforiginfilter +Disabled +> +``` + ### thread start Enable Thread protocol operation and attach to a Thread network. @@ -3821,7 +3854,7 @@ Done ### tvcheck disable -Enable thread version check when upgrading to router or leader. +Disable thread version check when upgrading to router or leader. Note: Thread version check is enabled by default. diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index 79a29693656..c1aaecf5eec 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -1251,6 +1251,42 @@ template <> otError Interpreter::Process(Arg aArgs[]) return ProcessEnableDisable(aArgs, otThreadSetCcmEnabled); } +template <> otError Interpreter::Process(Arg aArgs[]) +{ + otError error = OT_ERROR_NONE; + + /** + * @cli test tmforiginfilter + * @code + * test tmforiginfilter + * Enabled + * @endcode + * @code + * test tmforiginfilter enable + * Done + * @endcode + * @code + * test tmforiginfilter disable + * Done + * @endcode + * @cparam test tmforiginfilter [@ca{enable|disable}] + * @par + * Enables or disables the filter to drop TMF UDP messages from untrusted origin. + * @par + * By default the filter that drops TMF UDP messages from untrusted origin + * is enabled. When disabled, UDP messages sent to the TMF port that originate + * from untrusted origin (such as host, CLI or an external IPv6 node) will be + * allowed. + * @note `OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE` is required. + */ + if (aArgs[0] == "tmforiginfilter") + { + error = ProcessEnableDisable(aArgs + 1, otThreadIsTmfOriginFilterEnabled, otThreadSetTmfOriginFilterEnabled); + } + + return error; +} + /** * @cli tvcheck (enable,disable) * @code @@ -8694,6 +8730,9 @@ otError Interpreter::ProcessCommand(Arg aArgs[]) #endif #if OPENTHREAD_CONFIG_TCP_ENABLE && OPENTHREAD_CONFIG_CLI_TCP_ENABLE CmdEntry("tcp"), +#endif +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE + CmdEntry("test"), #endif CmdEntry("thread"), #if OPENTHREAD_CONFIG_TX_QUEUE_STATISTICS_ENABLE diff --git a/src/core/api/thread_ftd_api.cpp b/src/core/api/thread_ftd_api.cpp index 1b19693cd25..ec3b9b4d4c3 100644 --- a/src/core/api/thread_ftd_api.cpp +++ b/src/core/api/thread_ftd_api.cpp @@ -388,6 +388,16 @@ void otThreadSetThreadVersionCheckEnabled(otInstance *aInstance, bool aEnabled) AsCoreType(aInstance).Get().SetThreadVersionCheckEnabled(aEnabled); } +void otThreadSetTmfOriginFilterEnabled(otInstance *aInstance, bool aEnabled) +{ + AsCoreType(aInstance).Get().SetTmfOriginFilterEnabled(aEnabled); +} + +bool otThreadIsTmfOriginFilterEnabled(otInstance *aInstance) +{ + return AsCoreType(aInstance).Get().IsTmfOriginFilterEnabled(); +} + void otThreadGetRouterIdRange(otInstance *aInstance, uint8_t *aMinRouterId, uint8_t *aMaxRouterId) { AssertPointerIsNotNull(aMinRouterId); diff --git a/src/core/net/ip6.cpp b/src/core/net/ip6.cpp index d5b2e27ed63..74d3e4fe60d 100644 --- a/src/core/net/ip6.cpp +++ b/src/core/net/ip6.cpp @@ -68,6 +68,9 @@ RegisterLogModule("Ip6"); Ip6::Ip6(Instance &aInstance) : InstanceLocator(aInstance) , mIsReceiveIp6FilterEnabled(false) +#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE + , mTmfOriginFilterEnabled(true) +#endif , mSendQueueTask(aInstance) , mIcmp(aInstance) , mUdp(aInstance) @@ -1239,7 +1242,11 @@ Error Ip6::HandleDatagram(OwnedPtr aMessagePtr, bool aIsReassembled) error = aMessagePtr->Read(aMessagePtr->GetOffset() + Udp::Header::kDestPortFieldOffset, destPort)); destPort = BigEndian::HostSwap16(destPort); - if (destPort == Tmf::kUdpPort) + if (destPort == Tmf::kUdpPort +#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE + && mTmfOriginFilterEnabled +#endif + ) { LogNote("Dropping TMF message from untrusted origin"); ExitNow(error = kErrorDrop); diff --git a/src/core/net/ip6.hpp b/src/core/net/ip6.hpp index de04eef8dd3..6e484ea9896 100644 --- a/src/core/net/ip6.hpp +++ b/src/core/net/ip6.hpp @@ -350,6 +350,26 @@ class Ip6 : public InstanceLocator, private NonCopyable void ResetBorderRoutingCounters(void) { ClearAllBytes(mBorderRoutingCounters); } #endif +#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE + + /** + * Enables or disables the filter that drops TMF UDP messages from untrusted origin. + * + * @param[in] aEnabled TRUE to enable filter, FALSE otherwise. + * + */ + void SetTmfOriginFilterEnabled(bool aEnabled) { mTmfOriginFilterEnabled = aEnabled; } + + /** + * Indicates whether the filter that drops TMF UDP messages from untrusted origin is enabled or not. + * + * @returns TRUE if the filter is enabled, FALSE otherwise. + * + */ + bool IsTmfOriginFilterEnabled(void) { return mTmfOriginFilterEnabled; } + +#endif + private: static constexpr uint8_t kDefaultHopLimit = OPENTHREAD_CONFIG_IP6_HOP_LIMIT_DEFAULT; static constexpr uint8_t kIp6ReassemblyTimeout = OPENTHREAD_CONFIG_IP6_REASSEMBLY_TIMEOUT; @@ -402,6 +422,10 @@ class Ip6 : public InstanceLocator, private NonCopyable bool mIsReceiveIp6FilterEnabled; +#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE + bool mTmfOriginFilterEnabled : 1; +#endif + Callback mReceiveIp6DatagramCallback; #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE