[posix] add IPv6 address helper functions in Ip6Utils (#9917)

These helpers are used in `posix/platform/udp.cpp` module.
This commit is contained in:
Abtin Keshavarzian
2024-03-12 14:13:44 -07:00
committed by GitHub
parent be06d7c29a
commit 2e24098edc
3 changed files with 81 additions and 17 deletions
+64
View File
@@ -33,11 +33,75 @@
#include "platform-posix.h"
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <openthread/ip6.h>
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.
*
+13 -17
View File
@@ -69,10 +69,6 @@ void *FdToHandle(int aFd) { return reinterpret_cast<void *>(aFd); }
int FdFromHandle(void *aHandle) { return static_cast<int>(reinterpret_cast<long>(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<struct sockaddr *>(&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)
{
@@ -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