From 2e24098edcee9764ee2a0fa880395e9d296aa668 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Tue, 12 Mar 2024 14:13:44 -0700 Subject: [PATCH] [posix] add IPv6 address helper functions in `Ip6Utils` (#9917) These helpers are used in `posix/platform/udp.cpp` module. --- src/posix/platform/ip6_utils.hpp | 64 +++++++++++++++++++ src/posix/platform/udp.cpp | 30 ++++----- .../openthread-core-toranj-config-posix.h | 4 ++ 3 files changed, 81 insertions(+), 17 deletions(-) diff --git a/src/posix/platform/ip6_utils.hpp b/src/posix/platform/ip6_utils.hpp index 4626a8361..841c317be 100644 --- a/src/posix/platform/ip6_utils.hpp +++ b/src/posix/platform/ip6_utils.hpp @@ -33,11 +33,75 @@ #include "platform-posix.h" #include +#include +#include + +#include namespace ot { namespace Posix { namespace Ip6Utils { +/** + * Indicates whether or not the IPv6 address scope is Link-Local. + * + * @param[in] aAddress The IPv6 address to check. + * + * @retval TRUE If the IPv6 address scope is Link-Local. + * @retval FALSE If the IPv6 address scope is not Link-Local. + * + */ +inline bool IsIp6AddressLinkLocal(const otIp6Address &aAddress) +{ + return (aAddress.mFields.m8[0] == 0xfe) && ((aAddress.mFields.m8[1] & 0xc0) == 0x80); +} + +/** + * Indicates whether or not the IPv6 address is multicast. + * + * @param[in] aAddress The IPv6 address to check. + * + * @retval TRUE If the IPv6 address scope is multicast. + * @retval FALSE If the IPv6 address scope is not multicast. + * + */ +inline bool IsIp6AddressMulticast(const otIp6Address &aAddress) { return (aAddress.mFields.m8[0] == 0xff); } + +/** + * Indicates whether or not the IPv6 address is unspecified. + * + * @param[in] aAddress The IPv6 address to check. + * + * @retval TRUE If the IPv6 address scope is unspecified. + * @retval FALSE If the IPv6 address scope is not unspecified. + * + */ +inline bool IsIp6AddressUnspecified(const otIp6Address &aAddress) { return otIp6IsAddressUnspecified(&aAddress); } + +/** + * Copies the IPv6 address bytes into a given buffer. + * + * @param[in] aAddress The IPv6 address to copy. + * @param[in] aBuffer A pointer to buffer to copy the address to. + * + */ +inline void CopyIp6AddressTo(const otIp6Address &aAddress, void *aBuffer) +{ + memcpy(aBuffer, &aAddress, sizeof(otIp6Address)); +} + +/** + * Reads and set the the IPv6 address bytes from a given buffer. + * + * @param[in] aBuffer A pointer to buffer to read from. + * @param[out] aAddress A reference to populate with the read IPv6 address. + * + */ +inline void ReadIp6AddressFrom(const void *aBuffer, otIp6Address &aAddress) +{ + memcpy(&aAddress, aBuffer, sizeof(otIp6Address)); +} + /** * This utility class converts binary IPv6 address to text format. * diff --git a/src/posix/platform/udp.cpp b/src/posix/platform/udp.cpp index 4161672eb..177f4e3ef 100644 --- a/src/posix/platform/udp.cpp +++ b/src/posix/platform/udp.cpp @@ -69,10 +69,6 @@ void *FdToHandle(int aFd) { return reinterpret_cast(aFd); } int FdFromHandle(void *aHandle) { return static_cast(reinterpret_cast(aHandle)); } -bool IsLinkLocal(const struct in6_addr &aAddress) { return aAddress.s6_addr[0] == 0xfe && aAddress.s6_addr[1] == 0x80; } - -bool IsMulticast(const otIp6Address &aAddress) { return aAddress.mFields.m8[0] == 0xff; } - otError transmitPacket(int aFd, uint8_t *aPayload, uint16_t aLength, const otMessageInfo &aMessageInfo) { #ifdef __APPLE__ @@ -93,9 +89,9 @@ otError transmitPacket(int aFd, uint8_t *aPayload, uint16_t aLength, const otMes memset(&peerAddr, 0, sizeof(peerAddr)); peerAddr.sin6_port = htons(aMessageInfo.mPeerPort); peerAddr.sin6_family = AF_INET6; - memcpy(&peerAddr.sin6_addr, &aMessageInfo.mPeerAddr, sizeof(peerAddr.sin6_addr)); + CopyIp6AddressTo(aMessageInfo.mPeerAddr, &peerAddr.sin6_addr); - if (IsLinkLocal(peerAddr.sin6_addr) && !aMessageInfo.mIsHostInterface) + if (IsIp6AddressLinkLocal(aMessageInfo.mPeerAddr) && !aMessageInfo.mIsHostInterface) { // sin6_scope_id only works for link local destinations peerAddr.sin6_scope_id = gNetifIndex; @@ -127,8 +123,7 @@ otError transmitPacket(int aFd, uint8_t *aPayload, uint16_t aLength, const otMes controlLength += CMSG_SPACE(sizeof(int)); } - if (!IsMulticast(aMessageInfo.mSockAddr) && - memcmp(&aMessageInfo.mSockAddr, &in6addr_any, sizeof(aMessageInfo.mSockAddr))) + if (!IsIp6AddressMulticast(aMessageInfo.mSockAddr) && !IsIp6AddressUnspecified(aMessageInfo.mSockAddr)) { struct in6_pktinfo pktinfo; @@ -139,7 +134,7 @@ otError transmitPacket(int aFd, uint8_t *aPayload, uint16_t aLength, const otMes pktinfo.ipi6_ifindex = aMessageInfo.mIsHostInterface ? 0 : gNetifIndex; - memcpy(&pktinfo.ipi6_addr, &aMessageInfo.mSockAddr, sizeof(pktinfo.ipi6_addr)); + CopyIp6AddressTo(aMessageInfo.mSockAddr, &pktinfo.ipi6_addr); memcpy(CMSG_DATA(cmsg), &pktinfo, sizeof(pktinfo)); controlLength += CMSG_SPACE(sizeof(pktinfo)); @@ -206,13 +201,13 @@ otError receivePacket(int aFd, uint8_t *aPayload, uint16_t &aLength, otMessageIn memcpy(&pktinfo, CMSG_DATA(cmsg), sizeof(pktinfo)); aMessageInfo.mIsHostInterface = (pktinfo.ipi6_ifindex != gNetifIndex); - memcpy(&aMessageInfo.mSockAddr, &pktinfo.ipi6_addr, sizeof(aMessageInfo.mSockAddr)); + ReadIp6AddressFrom(&pktinfo.ipi6_addr, aMessageInfo.mSockAddr); } } } aMessageInfo.mPeerPort = ntohs(peerAddr.sin6_port); - memcpy(&aMessageInfo.mPeerAddr, &peerAddr.sin6_addr, sizeof(aMessageInfo.mPeerAddr)); + ReadIp6AddressFrom(&peerAddr.sin6_addr, aMessageInfo.mPeerAddr); exit: return rval > 0 ? OT_ERROR_NONE : OT_ERROR_FAILED; @@ -270,7 +265,8 @@ otError otPlatUdpBind(otUdpSocket *aUdpSocket) memset(&sin6, 0, sizeof(struct sockaddr_in6)); sin6.sin6_port = htons(aUdpSocket->mSockName.mPort); sin6.sin6_family = AF_INET6; - memcpy(&sin6.sin6_addr, &aUdpSocket->mSockName.mAddress, sizeof(sin6.sin6_addr)); + CopyIp6AddressTo(aUdpSocket->mSockName.mAddress, &sin6.sin6_addr); + VerifyOrExit(0 == bind(fd, reinterpret_cast(&sin6), sizeof(sin6)), error = OT_ERROR_FAILED); } @@ -358,8 +354,7 @@ otError otPlatUdpConnect(otUdpSocket *aUdpSocket) otError error = OT_ERROR_NONE; struct sockaddr_in6 sin6; int fd; - bool isDisconnect = memcmp(&aUdpSocket->mPeerName.mAddress, &in6addr_any, sizeof(in6addr_any)) == 0 && - aUdpSocket->mPeerName.mPort == 0; + bool isDisconnect = IsIp6AddressUnspecified(aUdpSocket->mPeerName.mAddress) && (aUdpSocket->mPeerName.mPort == 0); VerifyOrExit(aUdpSocket->mHandle != nullptr, error = OT_ERROR_INVALID_ARGS); @@ -367,10 +362,11 @@ otError otPlatUdpConnect(otUdpSocket *aUdpSocket) memset(&sin6, 0, sizeof(struct sockaddr_in6)); sin6.sin6_port = htons(aUdpSocket->mPeerName.mPort); + if (!isDisconnect) { sin6.sin6_family = AF_INET6; - memcpy(&sin6.sin6_addr, &aUdpSocket->mPeerName.mAddress, sizeof(sin6.sin6_addr)); + CopyIp6AddressTo(aUdpSocket->mPeerName.mAddress, &sin6.sin6_addr); } else { @@ -468,7 +464,7 @@ otError otPlatUdpJoinMulticastGroup(otUdpSocket *aUdpSocket, VerifyOrExit(aUdpSocket->mHandle != nullptr, error = OT_ERROR_INVALID_ARGS); fd = FdFromHandle(aUdpSocket->mHandle); - memcpy(&mreq.ipv6mr_multiaddr, aAddress->mFields.m8, sizeof(mreq.ipv6mr_multiaddr)); + CopyIp6AddressTo(*aAddress, &mreq.ipv6mr_multiaddr); switch (aNetifIdentifier) { @@ -508,7 +504,7 @@ otError otPlatUdpLeaveMulticastGroup(otUdpSocket *aUdpSocket, VerifyOrExit(aUdpSocket->mHandle != nullptr, error = OT_ERROR_INVALID_ARGS); fd = FdFromHandle(aUdpSocket->mHandle); - memcpy(&mreq.ipv6mr_multiaddr, aAddress->mFields.m8, sizeof(mreq.ipv6mr_multiaddr)); + CopyIp6AddressTo(*aAddress, &mreq.ipv6mr_multiaddr); switch (aNetifIdentifier) { diff --git a/tests/toranj/openthread-core-toranj-config-posix.h b/tests/toranj/openthread-core-toranj-config-posix.h index b78bb9955..d56aa4365 100644 --- a/tests/toranj/openthread-core-toranj-config-posix.h +++ b/tests/toranj/openthread-core-toranj-config-posix.h @@ -43,6 +43,10 @@ #define OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE 1 #endif +#ifndef OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE +#define OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE 1 +#endif + #define OPENTHREAD_CONFIG_LOG_OUTPUT OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED #define OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE 1