diff --git a/include/openthread/instance.h b/include/openthread/instance.h index e3acb7c6b..94b175944 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 (123) +#define OPENTHREAD_API_VERSION (124) /** * @addtogroup api-instance diff --git a/include/openthread/udp.h b/include/openthread/udp.h index f11d5d740..02773197d 100644 --- a/include/openthread/udp.h +++ b/include/openthread/udp.h @@ -289,6 +289,18 @@ void otUdpForwardReceive(otInstance * aInstance, const otIp6Address *aPeerAddr, uint16_t aSockPort); +/** + * Determines if the given UDP port is exclusively opened by OpenThread API. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] port UDP port number to verify. + * + * @retval true The port is being used exclusively by OpenThread. + * @retval false The port is not used by any of the OpenThread API or is shared (e.g. is Backbone socket). + * + */ +bool otUdpIsPortInUse(otInstance *aInstance, uint16_t port); + /** * @} * diff --git a/src/core/api/udp_api.cpp b/src/core/api/udp_api.cpp index 43d45ddb5..567a027cc 100644 --- a/src/core/api/udp_api.cpp +++ b/src/core/api/udp_api.cpp @@ -147,3 +147,10 @@ otError otUdpSendDatagram(otInstance *aInstance, otMessage *aMessage, otMessageI return instance.Get().SendDatagram(*static_cast(aMessage), *static_cast(aMessageInfo), Ip6::kProtoUdp); } + +bool otUdpIsPortInUse(otInstance *aInstance, uint16_t port) +{ + Instance &instance = *static_cast(aInstance); + + return instance.Get().IsPortInUse(port); +} diff --git a/src/core/net/ip6.cpp b/src/core/net/ip6.cpp index 71c30f322..3203753f0 100644 --- a/src/core/net/ip6.cpp +++ b/src/core/net/ip6.cpp @@ -49,6 +49,7 @@ #include "net/ip6_filter.hpp" #include "net/netif.hpp" #include "net/udp6.hpp" +#include "openthread/ip6.h" #include "thread/mle.hpp" using IcmpType = ot::Ip6::Icmp::Header::Type; @@ -1029,8 +1030,9 @@ Error Ip6::ProcessReceiveCallback(Message & aMessage, Udp::Header udp; IgnoreError(aMessage.Read(aMessage.GetOffset(), udp)); - VerifyOrExit(Get().ShouldUsePlatformUdp(udp.GetDestinationPort()), error = kErrorNoRoute); - + VerifyOrExit(Get().ShouldUsePlatformUdp(udp.GetDestinationPort()) && + !Get().IsPortInUse(udp.GetDestinationPort()), + error = kErrorNoRoute); break; } diff --git a/src/core/net/udp6.cpp b/src/core/net/udp6.cpp index a99ace197..3df27e59c 100644 --- a/src/core/net/udp6.cpp +++ b/src/core/net/udp6.cpp @@ -480,7 +480,7 @@ Error Udp::HandleMessage(Message &aMessage, MessageInfo &aMessageInfo) aMessageInfo.mSockPort = udpHeader.GetDestinationPort(); #if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE - VerifyOrExit(!ShouldUsePlatformUdp(aMessageInfo.mSockPort)); + VerifyOrExit(!ShouldUsePlatformUdp(aMessageInfo.mSockPort) || IsPortInUse(aMessageInfo.mSockPort)); #endif for (Receiver *receiver = mReceivers.GetHead(); receiver; receiver = receiver->GetNext()) @@ -530,6 +530,22 @@ exit: return; } +bool Udp::IsPortInUse(uint16_t aPort) const +{ + bool found = false; + + for (const SocketHandle *socket = mSockets.GetHead(); socket != nullptr; socket = socket->GetNext()) + { + if (socket->GetSockName().GetPort() == aPort) + { + found = true; + break; + } + } + + return found; +} + bool Udp::ShouldUsePlatformUdp(uint16_t aPort) const { return (aPort != Mle::kUdpPort && aPort != Tmf::kUdpPort diff --git a/src/core/net/udp6.hpp b/src/core/net/udp6.hpp index 178537b60..428500ae8 100644 --- a/src/core/net/udp6.hpp +++ b/src/core/net/udp6.hpp @@ -573,6 +573,18 @@ public: } #endif + /** + * This method returns whether a udp port is being used by OpenThread or any of it's optional + * features, e.g. CoAP API. + * + * @param[in] aPort The udp port + * + * @retval True when port is used by the OpenThread. + * @retval False when the port is not used by OpenThread. + * + */ + bool IsPortInUse(uint16_t aPort) const; + /** * This method returns whether a udp port belongs to the platform or the stack. *