diff --git a/src/posix/platform/mdns_socket.cpp b/src/posix/platform/mdns_socket.cpp index 2a7c15541..17fc827f6 100644 --- a/src/posix/platform/mdns_socket.cpp +++ b/src/posix/platform/mdns_socket.cpp @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -41,6 +42,8 @@ #include #include +#include + #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(addr->ifa_addr)->sin6_addr, ip6Addr); + } + else if (addr->ifa_addr->sa_family == AF_INET) + { + memcpy(&ip4Addr, &reinterpret_cast(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(aTimeout.tv_sec) * OT_US_PER_S + static_cast(aTimeout.tv_usec); + + if (remaining < timeout) + { + aTimeout.tv_sec = static_cast(remaining / OT_US_PER_S); + aTimeout.tv_usec = static_cast(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 diff --git a/src/posix/platform/mdns_socket.hpp b/src/posix/platform/mdns_socket.hpp index 8e8327ed5..341ec925e 100644 --- a/src/posix/platform/mdns_socket.hpp +++ b/src/posix/platform/mdns_socket.hpp @@ -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 diff --git a/src/posix/platform/openthread-posix-config.h b/src/posix/platform/openthread-posix-config.h index c1955ae9a..7a41ebb92 100644 --- a/src/posix/platform/openthread-posix-config.h +++ b/src/posix/platform/openthread-posix-config.h @@ -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.