[posix] implement address monitoring in MdnsSocket (#11641)

This commit introduces an initial implementation in `Posix::MdnsSocket`
to monitor and report all IPv4 and IPv6 addresses assigned to the
infrastructure network interface. This mechanism is used by OpenThread's
native mDNS module and was added in PRs #11353 and #11394.

A new configuration, `OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR`, is
added to select the monitoring strategy. This commit implements the
`OT_POSIX_MDNS_ADDR_MONITOR_PERIODIC` approach, where `getifaddrs()`
is used to enumerate addresses periodically. The polling interval
is configured by `OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR_PERIOD`.

Note that the OpenThread mDNS module itself tracks the list of
reported addresses and will only take action when there is a change
from what was previously announced. This allows the platform to
simply report the full list of current addresses at each interval.
This commit is contained in:
Abtin Keshavarzian
2025-06-26 13:41:44 -07:00
committed by GitHub
parent 02da4ce5c6
commit e06a5bbb11
3 changed files with 147 additions and 2 deletions
+98
View File
@@ -32,6 +32,7 @@
#include <arpa/inet.h>
#include <errno.h>
#include <ifaddrs.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdio.h>
@@ -41,6 +42,8 @@
#include <sys/types.h>
#include <unistd.h>
#include <openthread/platform/time.h>
#include "ip6_utils.hpp"
#include "platform-posix.h"
#include "common/code_utils.hpp"
@@ -149,6 +152,10 @@ void MdnsSocket::Update(otSysMainloopContext &aContext)
aContext.mMaxFd = mFd4;
}
#if (OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR == OT_POSIX_MDNS_ADDR_MONITOR_PERIODIC)
UpdateTimeout(aContext.mTimeout);
#endif
exit:
return;
}
@@ -177,6 +184,10 @@ void MdnsSocket::Process(const otSysMainloopContext &aContext)
ReceiveMessage(kIp4Msg);
}
#if (OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR == OT_POSIX_MDNS_ADDR_MONITOR_PERIODIC)
ProcessTimeout();
#endif
exit:
return;
}
@@ -214,6 +225,8 @@ otError MdnsSocket::Enable(uint32_t aInfraIfIndex)
mEnabled = true;
mInfraIfIndex = aInfraIfIndex;
StartAddressMonitoring();
LogInfo("Enabled");
exit:
@@ -237,6 +250,8 @@ void MdnsSocket::Disable(uint32_t aInfraIfIndex)
mEnabled = false;
StopAddressMonitoring();
LogInfo("Disabled");
}
@@ -490,6 +505,89 @@ exit:
}
}
//---------------------------------------------------------------------------------------------------------------------
// Monitoring address on infra netif
#if (OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR == OT_POSIX_MDNS_ADDR_MONITOR_PERIODIC)
void MdnsSocket::ReportInfraIfAddresses(void)
{
struct ifaddrs *ifAddrs = nullptr;
mNextReportTime = otPlatTimeGet() + kAddrMonitorPeriod * OT_US_PER_MS;
if (getifaddrs(&ifAddrs) < 0)
{
LogWarn("Failed to get netif addresses: %s", strerror(errno));
ExitNow();
}
otPlatMdnsHandleHostAddressRemoveAll(mInstance, mInfraIfIndex);
for (struct ifaddrs *addr = ifAddrs; addr != nullptr; addr = addr->ifa_next)
{
otIp6Address ip6Addr;
otIp4Address ip4Addr;
if ((addr->ifa_addr == nullptr) || (if_nametoindex(addr->ifa_name) != mInfraIfIndex))
{
continue;
}
if (addr->ifa_addr->sa_family == AF_INET6)
{
ReadIp6AddressFrom(&reinterpret_cast<sockaddr_in6 *>(addr->ifa_addr)->sin6_addr, ip6Addr);
}
else if (addr->ifa_addr->sa_family == AF_INET)
{
memcpy(&ip4Addr, &reinterpret_cast<sockaddr_in *>(addr->ifa_addr)->sin_addr.s_addr, sizeof(otIp4Address));
otIp4ToIp4MappedIp6Address(&ip4Addr, &ip6Addr);
}
else
{
continue;
}
otPlatMdnsHandleHostAddressEvent(mInstance, &ip6Addr, /* aAdded */ true, mInfraIfIndex);
}
exit:
if (ifAddrs != nullptr)
{
freeifaddrs(ifAddrs);
}
}
void MdnsSocket::UpdateTimeout(struct timeval &aTimeout)
{
uint64_t now = otPlatTimeGet();
uint64_t remaining = 1;
uint64_t timeout;
if (mNextReportTime > now)
{
remaining = mNextReportTime - now;
}
timeout = static_cast<uint64_t>(aTimeout.tv_sec) * OT_US_PER_S + static_cast<uint64_t>(aTimeout.tv_usec);
if (remaining < timeout)
{
aTimeout.tv_sec = static_cast<time_t>(remaining / OT_US_PER_S);
aTimeout.tv_usec = static_cast<suseconds_t>(remaining % OT_US_PER_S);
}
}
void MdnsSocket::ProcessTimeout(void)
{
if (mNextReportTime <= otPlatTimeGet())
{
ReportInfraIfAddresses();
}
}
#endif // (OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR == OT_POSIX_MDNS_ADDR_MONITOR_PERIODIC)
//---------------------------------------------------------------------------------------------------------------------
// Socket helpers
+23 -2
View File
@@ -43,6 +43,15 @@
namespace ot {
namespace Posix {
#define OT_POSIX_MDNS_ADDR_MONITOR_PERIODIC 1
#define OT_POSIX_MDNS_ADDR_MONITOR_NETLINK 2
#if (OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR == OT_POSIX_MDNS_ADDR_MONITOR_NETLINK)
#error "The `OT_POSIX_MDNS_ADDR_MONITOR_NETLINK` is not supported yet"
#elif (OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR != OT_POSIX_MDNS_ADDR_MONITOR_PERIODIC)
#error "The `OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR` is not valid. MUST be one of `OT_POSIX_MDNS_ADDR_MONITOR_*`"
#endif
/**
* Implements platform mDNS socket APIs.
*/
@@ -106,8 +115,9 @@ public:
void SendUnicast(otMessage *aMessage, const otPlatMdnsAddressInfo *aAddress);
private:
static constexpr uint16_t kMaxMessageLength = 2000;
static constexpr uint16_t kMdnsPort = 5353;
static constexpr uint16_t kMaxMessageLength = 2000;
static constexpr uint16_t kMdnsPort = 5353;
static constexpr uint64_t kAddrMonitorPeriod = OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR_PERIOD;
enum MsgType : uint8_t
{
@@ -131,6 +141,14 @@ private:
void SendQueuedMessages(MsgType aMsgType);
void ReceiveMessage(MsgType aMsgType);
#if (OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR == OT_POSIX_MDNS_ADDR_MONITOR_PERIODIC)
void StartAddressMonitoring(void) { ReportInfraIfAddresses(); }
void StopAddressMonitoring(void) {}
void ReportInfraIfAddresses(void);
void UpdateTimeout(struct timeval &aTimeout);
void ProcessTimeout(void);
#endif
otError OpenIp4Socket(uint32_t aInfraIfIndex);
otError JoinOrLeaveIp4MulticastGroup(bool aJoin, uint32_t aInfraIfIndex);
void CloseIp4Socket(void);
@@ -163,6 +181,9 @@ private:
otIp6Address mMulticastIp6Address;
otIp4Address mMulticastIp4Address;
otInstance *mInstance;
#if (OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR == OT_POSIX_MDNS_ADDR_MONITOR_PERIODIC)
uint64_t mNextReportTime;
#endif
};
} // namespace Posix
@@ -454,6 +454,32 @@
#define OPENTHREAD_POSIX_CONFIG_RESOLV_CONF_ENABLED_INIT (!OPENTHREAD_POSIX_CONFIG_ANDROID_ENABLE)
#endif
/**
* @def OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR
*
* Specifies the behavior of `MdnsSocket` and how it implements monitoring and reporting of infra-interface IPv4 and
* IPv6 addresses.
*
* The valid values for this config, `OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR_*`, are defined in
* `posix/platform/mdns_socket.h`.
*/
#ifndef OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR
#define OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR OT_POSIX_MDNS_ADDR_MONITOR_PERIODIC
#endif
/**
* @def OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR_PERIOD
*
* Specifies the duration in milliseconds (ms) for the periodic check used by the `MdnsSocket` implementation to
* monitor and report the infra-interface IPv4 and IPv6 addresses.
*
* This is applicable only when `OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR` is set to
* `OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR_PERIODIC`.
*/
#ifndef OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR_PERIOD
#define OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR_PERIOD (5000)
#endif
//---------------------------------------------------------------------------------------------------------------------
// Removed or renamed POSIX specific configs.