mirror of
https://github.com/espressif/openthread.git
synced 2026-08-05 18:37:45 +00:00
[posix] implement Posix::Dhcp6PdSocket for otPlatInfraIfDhcp6Pd* (#11607)
This commit implements `ot::Posix::Dhcp6PdSocket`, which provides the `otPlatInfraIfDhcp6PdClient*` socket-like APIs for use by the core `Dhcp6PdClient` module. The `Posix::Dhcp6PdSocket` is a sub-component of `Posix::InfraNetif`.
This commit is contained in:
@@ -129,6 +129,7 @@ add_library(openthread-posix
|
||||
configuration.cpp
|
||||
config_file.cpp
|
||||
daemon.cpp
|
||||
dhcp6_pd_socket.cpp
|
||||
entropy.cpp
|
||||
firewall.cpp
|
||||
hdlc_interface.cpp
|
||||
|
||||
@@ -0,0 +1,435 @@
|
||||
/*
|
||||
* Copyright (c) 2025, 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.
|
||||
*/
|
||||
|
||||
#include "dhcp6_pd_socket.hpp"
|
||||
|
||||
#if OT_POSIX_CONFIG_DHCP6_PD_SOCKET_ENABLE
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <openthread/platform/infra_if.h>
|
||||
|
||||
#include "infra_if.hpp"
|
||||
#include "ip6_utils.hpp"
|
||||
#include "platform-posix.h"
|
||||
#include "common/code_utils.hpp"
|
||||
|
||||
extern "C" void otPlatInfraIfDhcp6PdClientSetListeningEnabled(otInstance *aInstance,
|
||||
bool aEnable,
|
||||
uint32_t aInfraIfIndex)
|
||||
{
|
||||
ot::Posix::InfraNetif::GetDhcp6PdSocket().SetListeningEnabled(aInstance, aEnable, aInfraIfIndex);
|
||||
}
|
||||
|
||||
extern "C" void otPlatInfraIfDhcp6PdClientSend(otInstance *aInstance,
|
||||
otMessage *aMessage,
|
||||
otIp6Address *aDestAddress,
|
||||
uint32_t aInfraIfIndex)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
return ot::Posix::InfraNetif::GetDhcp6PdSocket().Send(aMessage, aDestAddress, aInfraIfIndex);
|
||||
}
|
||||
|
||||
namespace ot {
|
||||
namespace Posix {
|
||||
|
||||
using namespace ot::Posix::Ip6Utils;
|
||||
|
||||
const char Dhcp6PdSocket::kLogModuleName[] = "Dhcp6PdSocket";
|
||||
|
||||
void Dhcp6PdSocket::Init(void)
|
||||
{
|
||||
mEnabled = false;
|
||||
mInfraIfIndex = 0;
|
||||
mFd6 = -1;
|
||||
mPendingTx = false;
|
||||
|
||||
// `All_DHCP_Relay_Agents_and_Servers` "ff02::1:2"
|
||||
memset(&mMulticastAddress, 0, sizeof(otIp6Address));
|
||||
mMulticastAddress.mFields.m8[0] = 0xff;
|
||||
mMulticastAddress.mFields.m8[1] = 0x02;
|
||||
mMulticastAddress.mFields.m8[13] = 0x01;
|
||||
mMulticastAddress.mFields.m8[15] = 0x02;
|
||||
|
||||
memset(&mTxQueue, 0, sizeof(mTxQueue));
|
||||
}
|
||||
|
||||
void Dhcp6PdSocket::SetUp(void) { otMessageQueueInit(&mTxQueue); }
|
||||
|
||||
void Dhcp6PdSocket::TearDown(void)
|
||||
{
|
||||
if (mEnabled)
|
||||
{
|
||||
ClearTxQueue();
|
||||
mEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Dhcp6PdSocket::Deinit(void) { CloseSocket(); }
|
||||
|
||||
void Dhcp6PdSocket::Update(otSysMainloopContext &aContext)
|
||||
{
|
||||
VerifyOrExit(mEnabled);
|
||||
|
||||
FD_SET(mFd6, &aContext.mReadFdSet);
|
||||
|
||||
if (mPendingTx)
|
||||
{
|
||||
FD_SET(mFd6, &aContext.mWriteFdSet);
|
||||
}
|
||||
|
||||
if (aContext.mMaxFd < mFd6)
|
||||
{
|
||||
aContext.mMaxFd = mFd6;
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Dhcp6PdSocket::Process(const otSysMainloopContext &aContext)
|
||||
{
|
||||
VerifyOrExit(mEnabled);
|
||||
|
||||
if (FD_ISSET(mFd6, &aContext.mWriteFdSet))
|
||||
{
|
||||
SendQueuedMessages();
|
||||
}
|
||||
|
||||
if (FD_ISSET(mFd6, &aContext.mReadFdSet))
|
||||
{
|
||||
ReceiveMessage();
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Dhcp6PdSocket::SetListeningEnabled(otInstance *aInstance, bool aEnable, uint32_t aInfraIfIndex)
|
||||
{
|
||||
VerifyOrExit(aEnable != mEnabled);
|
||||
mInstance = aInstance;
|
||||
|
||||
if (aEnable)
|
||||
{
|
||||
Enable(aInfraIfIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
Disable(aInfraIfIndex);
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Dhcp6PdSocket::Enable(uint32_t aInfraIfIndex)
|
||||
{
|
||||
SuccessOrDie(OpenSocket(aInfraIfIndex));
|
||||
SuccessOrDie(JoinOrLeaveMulticastGroup(/* aJoin */ true, aInfraIfIndex));
|
||||
|
||||
mEnabled = true;
|
||||
mInfraIfIndex = aInfraIfIndex;
|
||||
|
||||
LogInfo("Enabled");
|
||||
}
|
||||
|
||||
void Dhcp6PdSocket::Disable(uint32_t aInfraIfIndex)
|
||||
{
|
||||
ClearTxQueue();
|
||||
|
||||
IgnoreError(JoinOrLeaveMulticastGroup(/* aJoin */ false, aInfraIfIndex));
|
||||
CloseSocket();
|
||||
|
||||
mEnabled = false;
|
||||
|
||||
LogInfo("Disabled");
|
||||
}
|
||||
|
||||
void Dhcp6PdSocket::Send(otMessage *aMessage, const otIp6Address *aAddress, uint32_t aInfraIfIndex)
|
||||
{
|
||||
Metadata metadata;
|
||||
uint16_t length;
|
||||
|
||||
VerifyOrExit(mEnabled);
|
||||
VerifyOrExit(aInfraIfIndex == mInfraIfIndex);
|
||||
|
||||
length = otMessageGetLength(aMessage);
|
||||
|
||||
if (length > kMaxMessageLength)
|
||||
{
|
||||
LogWarn("Msg length %u is longer than max %u", length, kMaxMessageLength);
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
memset(&metadata, 0, sizeof(Metadata));
|
||||
|
||||
metadata.mAddress = *aAddress;
|
||||
metadata.mPort = kServerPort;
|
||||
|
||||
SuccessOrExit(otMessageAppend(aMessage, &metadata, sizeof(Metadata)));
|
||||
|
||||
mPendingTx = true;
|
||||
|
||||
otMessageQueueEnqueue(&mTxQueue, aMessage);
|
||||
aMessage = NULL;
|
||||
|
||||
exit:
|
||||
if (aMessage != NULL)
|
||||
{
|
||||
otMessageFree(aMessage);
|
||||
}
|
||||
}
|
||||
|
||||
void Dhcp6PdSocket::ClearTxQueue(void)
|
||||
{
|
||||
otMessage *message;
|
||||
|
||||
while ((message = otMessageQueueGetHead(&mTxQueue)) != NULL)
|
||||
{
|
||||
otMessageQueueDequeue(&mTxQueue, message);
|
||||
otMessageFree(message);
|
||||
}
|
||||
|
||||
mPendingTx = false;
|
||||
}
|
||||
|
||||
void Dhcp6PdSocket::SendQueuedMessages(void)
|
||||
{
|
||||
otMessage *message;
|
||||
|
||||
while ((message = otMessageQueueGetHead(&mTxQueue)) != nullptr)
|
||||
{
|
||||
uint16_t length;
|
||||
uint16_t offset;
|
||||
int bytesSent;
|
||||
Metadata metadata;
|
||||
uint8_t buffer[kMaxMessageLength];
|
||||
struct sockaddr_in6 addr6;
|
||||
|
||||
length = otMessageGetLength(message);
|
||||
|
||||
offset = length - sizeof(Metadata);
|
||||
length -= sizeof(Metadata);
|
||||
|
||||
otMessageRead(message, offset, &metadata, sizeof(Metadata));
|
||||
otMessageRead(message, 0, buffer, length);
|
||||
|
||||
memset(&addr6, 0, sizeof(addr6));
|
||||
addr6.sin6_family = AF_INET6;
|
||||
addr6.sin6_port = htons(metadata.mPort);
|
||||
CopyIp6AddressTo(metadata.mAddress, &addr6.sin6_addr);
|
||||
|
||||
bytesSent = sendto(mFd6, buffer, length, 0, reinterpret_cast<struct sockaddr *>(&addr6), sizeof(addr6));
|
||||
VerifyOrExit(bytesSent == length);
|
||||
|
||||
otMessageQueueDequeue(&mTxQueue, message);
|
||||
otMessageFree(message);
|
||||
}
|
||||
|
||||
mPendingTx = false;
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Dhcp6PdSocket::ReceiveMessage(void)
|
||||
{
|
||||
otMessage *message = nullptr;
|
||||
uint8_t buffer[kMaxMessageLength];
|
||||
uint16_t length = 0;
|
||||
struct sockaddr_in6 sockaddr6;
|
||||
socklen_t len;
|
||||
ssize_t rval;
|
||||
|
||||
len = sizeof(sockaddr6);
|
||||
memset(&sockaddr6, 0, sizeof(sockaddr6));
|
||||
|
||||
rval = recvfrom(mFd6, reinterpret_cast<char *>(&buffer), sizeof(buffer), 0,
|
||||
reinterpret_cast<struct sockaddr *>(&sockaddr6), &len);
|
||||
|
||||
VerifyOrExit(rval >= 0, LogCrit("recvfrom() for IPv6 socket failed, errno: %s", strerror(errno)));
|
||||
length = static_cast<uint16_t>(rval);
|
||||
|
||||
VerifyOrExit(length > 0);
|
||||
|
||||
message = otIp6NewMessage(mInstance, nullptr);
|
||||
VerifyOrExit(message != nullptr);
|
||||
|
||||
SuccessOrExit(otMessageAppend(message, buffer, length));
|
||||
|
||||
otPlatInfraIfDhcp6PdClientHandleReceived(mInstance, message, mInfraIfIndex);
|
||||
|
||||
message = nullptr;
|
||||
|
||||
exit:
|
||||
if (message != nullptr)
|
||||
{
|
||||
otMessageFree(message);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// Socket helpers
|
||||
|
||||
otError Dhcp6PdSocket::OpenSocket(uint32_t aInfraIfIndex)
|
||||
{
|
||||
otError error = OT_ERROR_FAILED;
|
||||
struct sockaddr_in6 addr6;
|
||||
int fd;
|
||||
int ifindex = static_cast<int>(aInfraIfIndex);
|
||||
|
||||
fd = socket(AF_INET6, SOCK_DGRAM, 0);
|
||||
VerifyOrExit(fd >= 0, LogCrit("Failed to create socket"));
|
||||
|
||||
#ifdef __linux__
|
||||
{
|
||||
char nameBuffer[IF_NAMESIZE];
|
||||
const char *ifname;
|
||||
|
||||
ifname = if_indextoname(aInfraIfIndex, nameBuffer);
|
||||
VerifyOrExit(ifname != NULL, LogCrit("if_indextoname() failed"));
|
||||
|
||||
error = SetSocketOptionValue(fd, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname), "SO_BINDTODEVICE");
|
||||
SuccessOrExit(error);
|
||||
}
|
||||
#else
|
||||
{
|
||||
SuccessOrExit(error = SetSocketOption<int>(fd, IPPROTO_IPV6, IPV6_BOUND_IF, ifindex, "IPV6_BOUND_IF"));
|
||||
}
|
||||
#endif
|
||||
|
||||
SuccessOrExit(error = SetSocketOption<int>(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 255, "IPV6_MULTICAST_HOPS"));
|
||||
SuccessOrExit(error = SetSocketOption<int>(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 255, "IPV6_UNICAST_HOPS"));
|
||||
SuccessOrExit(error = SetSocketOption<int>(fd, IPPROTO_IPV6, IPV6_V6ONLY, 1, "IPV6_V6ONLY"));
|
||||
SuccessOrExit(error = SetSocketOption<int>(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, ifindex, "IPV6_MULTICAST_IF"));
|
||||
SuccessOrExit(error = SetSocketOption<int>(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, 1, "IPV6_MULTICAST_LOOP"));
|
||||
SuccessOrExit(error = SetReuseAddrPortOptions(fd));
|
||||
|
||||
memset(&addr6, 0, sizeof(addr6));
|
||||
addr6.sin6_family = AF_INET6;
|
||||
addr6.sin6_port = htons(kClientPort);
|
||||
|
||||
if (bind(fd, reinterpret_cast<struct sockaddr *>(&addr6), sizeof(addr6)) < 0)
|
||||
{
|
||||
LogCrit("bind() to DHCPv6 Client port for IPv6 socket failed, errno: %s", strerror(errno));
|
||||
error = OT_ERROR_FAILED;
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
mFd6 = fd;
|
||||
|
||||
LogInfo("Successfully opened IPv6 socket");
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#ifndef IPV6_ADD_MEMBERSHIP
|
||||
#ifdef IPV6_JOIN_GROUP
|
||||
#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef IPV6_DROP_MEMBERSHIP
|
||||
#ifdef IPV6_LEAVE_GROUP
|
||||
#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
|
||||
#endif
|
||||
#endif
|
||||
|
||||
otError Dhcp6PdSocket::JoinOrLeaveMulticastGroup(bool aJoin, uint32_t aInfraIfIndex)
|
||||
{
|
||||
struct ipv6_mreq mreq6;
|
||||
|
||||
memset(&mreq6, 0, sizeof(mreq6));
|
||||
Ip6Utils::CopyIp6AddressTo(mMulticastAddress, &mreq6.ipv6mr_multiaddr);
|
||||
|
||||
mreq6.ipv6mr_interface = static_cast<int>(aInfraIfIndex);
|
||||
|
||||
if (aJoin)
|
||||
{
|
||||
// Suggested workaround for netif not dropping
|
||||
// a previous multicast membership.
|
||||
setsockopt(mFd6, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq6, sizeof(mreq6));
|
||||
}
|
||||
|
||||
return SetSocketOptionValue(mFd6, IPPROTO_IPV6, aJoin ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP, &mreq6,
|
||||
sizeof(mreq6), "IP6_ADD/DROP_MEMBERSHIP");
|
||||
}
|
||||
|
||||
void Dhcp6PdSocket::CloseSocket(void)
|
||||
{
|
||||
if (mFd6 >= 0)
|
||||
{
|
||||
close(mFd6);
|
||||
mFd6 = -1;
|
||||
}
|
||||
}
|
||||
|
||||
otError Dhcp6PdSocket::SetReuseAddrPortOptions(int aFd)
|
||||
{
|
||||
otError error;
|
||||
|
||||
SuccessOrExit(error = SetSocketOption<int>(aFd, SOL_SOCKET, SO_REUSEADDR, 1, "SO_REUSEADDR"));
|
||||
SuccessOrExit(error = SetSocketOption<int>(aFd, SOL_SOCKET, SO_REUSEPORT, 1, "SO_REUSEPORT"));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError Dhcp6PdSocket::SetSocketOptionValue(int aFd,
|
||||
int aLevel,
|
||||
int aOption,
|
||||
const void *aValue,
|
||||
uint32_t aValueLength,
|
||||
const char *aOptionName)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
if (setsockopt(aFd, aLevel, aOption, aValue, aValueLength) != 0)
|
||||
{
|
||||
error = OT_ERROR_FAILED;
|
||||
LogCrit("Failed to setsockopt(%s) - errno: %s", aOptionName, strerror(errno));
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
} // namespace Posix
|
||||
} // namespace ot
|
||||
|
||||
#endif // OT_POSIX_CONFIG_DHCP6_PD_SOCKET_ENABLE
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (c) 2025, 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.
|
||||
*/
|
||||
#ifndef OT_POSIX_PLATFORM_DHCP6_PD_SOCKET_HPP_
|
||||
#define OT_POSIX_PLATFORM_DHCP6_PD_SOCKET_HPP_
|
||||
|
||||
#include "openthread-posix-config.h"
|
||||
|
||||
#ifdef OT_POSIX_CONFIG_DHCP6_PD_SOCKET_ENABLE
|
||||
#error "OT_POSIX_CONFIG_DHCP6_PD_SOCKET_ENABLE MUST NOT be defined directly. It is derived from other configs"
|
||||
#endif
|
||||
|
||||
#define OT_POSIX_CONFIG_DHCP6_PD_SOCKET_ENABLE \
|
||||
(OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE && \
|
||||
OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_CLIENT_ENABLE)
|
||||
|
||||
#if OT_POSIX_CONFIG_DHCP6_PD_SOCKET_ENABLE
|
||||
|
||||
#include <openthread/ip6.h>
|
||||
|
||||
#include "logger.hpp"
|
||||
#include "mainloop.hpp"
|
||||
|
||||
#include "core/common/non_copyable.hpp"
|
||||
|
||||
namespace ot {
|
||||
namespace Posix {
|
||||
|
||||
/**
|
||||
* Implements platform infra-if DHCPv6 Prefix Delegation (PD) socket APIs.
|
||||
*
|
||||
* This is sub-component of `ot::Posix::InfraNetif` class.
|
||||
*/
|
||||
class Dhcp6PdSocket : public Logger<Dhcp6PdSocket>, private NonCopyable
|
||||
{
|
||||
public:
|
||||
static const char kLogModuleName[]; ///< Module name used for logging.
|
||||
|
||||
/**
|
||||
* Initializes the `Dhcp6PdSocket`.
|
||||
*
|
||||
* Called before OpenThread instance is created.
|
||||
*/
|
||||
void Init(void);
|
||||
|
||||
/**
|
||||
* Sets up the `Dhcp6PdSocket`.
|
||||
*
|
||||
* Called after OpenThread instance is created.
|
||||
*/
|
||||
void SetUp(void);
|
||||
|
||||
/**
|
||||
* Tears down the `Dhcp6PdSocket`.
|
||||
*
|
||||
* Called before OpenThread instance is destructed.
|
||||
*/
|
||||
void TearDown(void);
|
||||
|
||||
/**
|
||||
* Deinitializes the `Dhcp6PdSocket`.
|
||||
*
|
||||
* Called after OpenThread instance is destructed.
|
||||
*/
|
||||
void Deinit(void);
|
||||
|
||||
/**
|
||||
* Updates the fd_set and timeout for mainloop.
|
||||
*
|
||||
* @param[in,out] aContext A reference to the mainloop context.
|
||||
*/
|
||||
void Update(otSysMainloopContext &aContext);
|
||||
|
||||
/**
|
||||
* Performs `Dhcp6PdSocket` processing.
|
||||
*
|
||||
* @param[in] aContext A reference to the mainloop context.
|
||||
*/
|
||||
void Process(const otSysMainloopContext &aContext);
|
||||
|
||||
// otPlatInfraIfDhcp6PdClient APIs
|
||||
void SetListeningEnabled(otInstance *aInstance, bool aEnable, uint32_t aInfraIfIndex);
|
||||
void Send(otMessage *aMessage, const otIp6Address *aDstAddress, uint32_t aInfraIfIndex);
|
||||
|
||||
private:
|
||||
static constexpr uint16_t kMaxMessageLength = 2000;
|
||||
static constexpr uint16_t kClientPort = 546;
|
||||
static constexpr uint16_t kServerPort = 547;
|
||||
|
||||
struct Metadata
|
||||
{
|
||||
otIp6Address mAddress;
|
||||
uint16_t mPort;
|
||||
};
|
||||
|
||||
bool mEnabled;
|
||||
bool mPendingTx;
|
||||
uint32_t mInfraIfIndex;
|
||||
int mFd6;
|
||||
otMessageQueue mTxQueue;
|
||||
otIp6Address mMulticastAddress;
|
||||
otInstance *mInstance;
|
||||
|
||||
void Enable(uint32_t aInfraIfIndex);
|
||||
void Disable(uint32_t aInfraIfIndex);
|
||||
void ClearTxQueue(void);
|
||||
void SendQueuedMessages(void);
|
||||
void ReceiveMessage(void);
|
||||
|
||||
otError OpenSocket(uint32_t aInfraIfIndex);
|
||||
otError JoinOrLeaveMulticastGroup(bool aJoin, uint32_t aInfraIfIndex);
|
||||
void CloseSocket(void);
|
||||
|
||||
static otError SetReuseAddrPortOptions(int aFd);
|
||||
|
||||
template <typename ValueType>
|
||||
static otError SetSocketOption(int aFd, int aLevel, int aOption, const ValueType &aValue, const char *aOptionName)
|
||||
{
|
||||
return SetSocketOptionValue(aFd, aLevel, aOption, &aValue, sizeof(ValueType), aOptionName);
|
||||
}
|
||||
|
||||
static otError SetSocketOptionValue(int aFd,
|
||||
int aLevel,
|
||||
int aOption,
|
||||
const void *aValue,
|
||||
uint32_t aValueLength,
|
||||
const char *aOptionName);
|
||||
};
|
||||
|
||||
} // namespace Posix
|
||||
} // namespace ot
|
||||
|
||||
#endif // OT_POSIX_CONFIG_DHCP6_PD_SOCKET_ENABLE
|
||||
|
||||
#endif // OT_POSIX_PLATFORM_DHCP6_PD_SOCKET_HPP_
|
||||
@@ -414,6 +414,10 @@ void InfraNetif::Init(void)
|
||||
#ifdef __linux__
|
||||
mNetLinkSocket = CreateNetLinkSocket();
|
||||
#endif
|
||||
|
||||
#if OT_POSIX_CONFIG_DHCP6_PD_SOCKET_ENABLE
|
||||
mDhcp6PdSocket.Init();
|
||||
#endif
|
||||
}
|
||||
|
||||
void InfraNetif::SetInfraNetif(const char *aIfName, int aIcmp6Socket)
|
||||
@@ -473,6 +477,10 @@ void InfraNetif::SetUp(void)
|
||||
mMulticastRoutingManager.SetUp();
|
||||
#endif
|
||||
|
||||
#if OT_POSIX_CONFIG_DHCP6_PD_SOCKET_ENABLE
|
||||
mDhcp6PdSocket.SetUp();
|
||||
#endif
|
||||
|
||||
Mainloop::Manager::Get().Add(*this);
|
||||
|
||||
ExitNow(); // To silence unused `exit` label warning.
|
||||
@@ -487,6 +495,10 @@ void InfraNetif::TearDown(void)
|
||||
IgnoreError(otBorderRoutingSetEnabled(gInstance, false));
|
||||
#endif
|
||||
|
||||
#if OT_POSIX_CONFIG_DHCP6_PD_SOCKET_ENABLE
|
||||
mDhcp6PdSocket.TearDown();
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_POSIX_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
|
||||
mMulticastRoutingManager.TearDown();
|
||||
#endif
|
||||
@@ -496,6 +508,10 @@ void InfraNetif::TearDown(void)
|
||||
|
||||
void InfraNetif::Deinit(void)
|
||||
{
|
||||
#if OT_POSIX_CONFIG_DHCP6_PD_SOCKET_ENABLE
|
||||
mDhcp6PdSocket.Deinit();
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
if (mInfraIfIcmp6Socket != -1)
|
||||
{
|
||||
@@ -518,6 +534,10 @@ void InfraNetif::Deinit(void)
|
||||
|
||||
void InfraNetif::Update(Mainloop::Context &aContext)
|
||||
{
|
||||
#if OT_POSIX_CONFIG_DHCP6_PD_SOCKET_ENABLE
|
||||
mDhcp6PdSocket.Update(aContext);
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
VerifyOrExit(mNetLinkSocket != -1);
|
||||
#endif
|
||||
@@ -682,6 +702,10 @@ void InfraNetif::SetInfraNetifIcmp6SocketForBorderRouting(int aIcmp6Socket)
|
||||
|
||||
void InfraNetif::Process(const Mainloop::Context &aContext)
|
||||
{
|
||||
#if OT_POSIX_CONFIG_DHCP6_PD_SOCKET_ENABLE
|
||||
mDhcp6PdSocket.Process(aContext);
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
VerifyOrExit(mInfraIfIcmp6Socket != -1);
|
||||
#endif
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
|
||||
#include "core/common/non_copyable.hpp"
|
||||
|
||||
#include "dhcp6_pd_socket.hpp"
|
||||
#include "logger.hpp"
|
||||
#include "mainloop.hpp"
|
||||
#include "multicast_routing.hpp"
|
||||
@@ -182,6 +183,15 @@ public:
|
||||
*/
|
||||
static InfraNetif &Get(void);
|
||||
|
||||
#if OT_POSIX_CONFIG_DHCP6_PD_SOCKET_ENABLE
|
||||
/**
|
||||
* Gets the singleton `Dhcp6PdSocket` associated with `InfraNetif`.
|
||||
*
|
||||
* @returns The singleton `Dhcp6PdSocket`.
|
||||
*/
|
||||
static Dhcp6PdSocket &GetDhcp6PdSocket(void) { return Get().mDhcp6PdSocket; }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Creates a socket for sending/receiving ICMPv6 messages.
|
||||
*
|
||||
@@ -211,6 +221,10 @@ private:
|
||||
MulticastRoutingManager mMulticastRoutingManager;
|
||||
#endif
|
||||
|
||||
#if OT_POSIX_CONFIG_DHCP6_PD_SOCKET_ENABLE
|
||||
Dhcp6PdSocket mDhcp6PdSocket;
|
||||
#endif
|
||||
|
||||
bool HasLinkLocalAddress(void) const;
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
@@ -1109,8 +1109,9 @@ exit:
|
||||
}
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE || \
|
||||
(OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE)
|
||||
#if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE || \
|
||||
(OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE && \
|
||||
!OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_CLIENT_ENABLE)
|
||||
static constexpr uint8_t kIpVersion4 = 4;
|
||||
static constexpr uint8_t kIpVersion6 = 6;
|
||||
|
||||
@@ -1126,7 +1127,8 @@ static uint8_t getIpVersion(const uint8_t *data)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE && \
|
||||
!OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_CLIENT_ENABLE
|
||||
|
||||
/**
|
||||
* Returns nullptr if data does not point to a valid ICMPv6 RA message.
|
||||
@@ -1171,7 +1173,7 @@ static otError tryProcessIcmp6RaMessage(otInstance *aInstance, const uint8_t *da
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE && ...
|
||||
|
||||
#ifdef __linux__
|
||||
/**
|
||||
@@ -1237,7 +1239,8 @@ static void processTransmit(otInstance *aInstance)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE && \
|
||||
!OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_CLIENT_ENABLE
|
||||
if (tryProcessIcmp6RaMessage(aInstance, reinterpret_cast<uint8_t *>(&packet[offset]), rval) == OT_ERROR_NONE)
|
||||
{
|
||||
ExitNow();
|
||||
|
||||
@@ -49,8 +49,6 @@
|
||||
|
||||
#define OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE 1
|
||||
|
||||
#define OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_CLIENT_ENABLE 1
|
||||
|
||||
#define OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE 1
|
||||
|
||||
#define OPENTHREAD_CONFIG_PLATFORM_DNSSD_ALLOW_RUN_TIME_SELECTION 1
|
||||
|
||||
@@ -56,6 +56,8 @@
|
||||
|
||||
#define OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE 1
|
||||
|
||||
#define OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_CLIENT_ENABLE 1
|
||||
|
||||
#define OPENTHREAD_CONFIG_BORDER_ROUTING_TESTING_API_ENABLE 1
|
||||
|
||||
#define OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE 1
|
||||
|
||||
Reference in New Issue
Block a user