diff --git a/src/inet/InetInterface.cpp b/src/inet/InetInterface.cpp index 8deff392f258fd..e769a0b369c8e2 100644 --- a/src/inet/InetInterface.cpp +++ b/src/inet/InetInterface.cpp @@ -275,6 +275,35 @@ bool InterfaceAddressIterator::HasBroadcastAddress() return HasCurrent() && mIntfIter.HasBroadcastAddress(); } +CHIP_ERROR InterfaceId::GetLinkLocalAddr(IPAddress * llAddr) +{ + VerifyOrReturnError(llAddr != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + +#if !LWIP_IPV6 + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif //! LWIP_IPV6 + + for (struct netif * intf = netif_list; intf != nullptr; intf = intf->next) + { + if ((mPlatformInterface != nullptr) && (mPlatformInterface != intf)) + continue; + for (int j = 0; j < LWIP_IPV6_NUM_ADDRESSES; ++j) + { + if (ip6_addr_isvalid(netif_ip6_addr_state(intf, j)) && ip6_addr_islinklocal(netif_ip6_addr(intf, j))) + { + (*llAddr) = IPAddress(*netif_ip6_addr(intf, j)); + return CHIP_NO_ERROR; + } + } + if (mPlatformInterface != nullptr) + { + return INET_ERROR_ADDRESS_NOT_FOUND; + } + } + + return CHIP_NO_ERROR; +} + #endif // CHIP_SYSTEM_CONFIG_USE_LWIP #if CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS @@ -704,6 +733,38 @@ bool InterfaceAddressIterator::HasBroadcastAddress() return HasCurrent() && (mCurAddr->ifa_flags & IFF_BROADCAST) != 0; } +CHIP_ERROR InterfaceId::GetLinkLocalAddr(IPAddress * llAddr) +{ + VerifyOrReturnError(llAddr != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + + struct ifaddrs * ifaddr; + const int rv = getifaddrs(&ifaddr); + if (rv == -1) + { + return INET_ERROR_ADDRESS_NOT_FOUND; + } + + for (struct ifaddrs * ifaddr_iter = ifaddr; ifaddr_iter != nullptr; ifaddr_iter = ifaddr_iter->ifa_next) + { + if (ifaddr_iter->ifa_addr != nullptr) + { + if ((ifaddr_iter->ifa_addr->sa_family == AF_INET6) && + ((mPlatformInterface == 0) || (mPlatformInterface == if_nametoindex(ifaddr_iter->ifa_name)))) + { + struct in6_addr * sin6_addr = &(reinterpret_cast(ifaddr_iter->ifa_addr))->sin6_addr; + if (sin6_addr->s6_addr[0] == 0xfe && (sin6_addr->s6_addr[1] & 0xc0) == 0x80) // Link Local Address + { + (*llAddr) = IPAddress((reinterpret_cast(ifaddr_iter->ifa_addr))->sin6_addr); + break; + } + } + } + } + freeifaddrs(ifaddr); + + return CHIP_NO_ERROR; +} + #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS #if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF @@ -865,8 +926,65 @@ bool InterfaceAddressIterator::HasBroadcastAddress() return HasCurrent() && mIntfIter.HasBroadcastAddress(); } +CHIP_ERROR InterfaceId::GetLinkLocalAddr(IPAddress * llAddr) +{ + VerifyOrReturnError(llAddr != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + + net_if * const iface = mPlatformInterface ? net_if_get_by_index(mPlatformInterface) : net_if_get_default(); + VerifyOrReturnError(iface != nullptr, INET_ERROR_ADDRESS_NOT_FOUND); + + in6_addr * const ip6_addr = net_if_ipv6_get_ll(iface, NET_ADDR_PREFERRED); + VerifyOrReturnError(ip6_addr != nullptr, INET_ERROR_ADDRESS_NOT_FOUND); + + *llAddr = IPAddress(*ip6_addr); + + return CHIP_NO_ERROR; +} + #endif // CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF +// static +InterfaceId InterfaceId::FromIPAddress(const IPAddress & addr) +{ + InterfaceAddressIterator addrIter; + + for (; addrIter.HasCurrent(); addrIter.Next()) + { + IPAddress curAddr = addrIter.GetAddress(); + if (addr == curAddr) + { + return addrIter.GetInterfaceId(); + } + } + + return InterfaceId::Null(); +} + +// static +bool InterfaceId::MatchLocalIPv6Subnet(const IPAddress & addr) +{ + if (addr.IsIPv6LinkLocal()) + return true; + + InterfaceAddressIterator ifAddrIter; + for (; ifAddrIter.HasCurrent(); ifAddrIter.Next()) + { + IPPrefix addrPrefix; + addrPrefix.IPAddr = ifAddrIter.GetAddress(); +#if INET_CONFIG_ENABLE_IPV4 + if (addrPrefix.IPAddr.IsIPv4()) + continue; +#endif // INET_CONFIG_ENABLE_IPV4 + if (addrPrefix.IPAddr.IsIPv6LinkLocal()) + continue; + addrPrefix.Length = ifAddrIter.GetPrefixLength(); + if (addrPrefix.MatchAddress(addr)) + return true; + } + + return false; +} + void InterfaceAddressIterator::GetAddressWithPrefix(IPPrefix & addrWithPrefix) { if (HasCurrent()) diff --git a/src/inet/InetInterface.h b/src/inet/InetInterface.h index 1de4b17ef63be3..29a9b76bf9c878 100644 --- a/src/inet/InetInterface.h +++ b/src/inet/InetInterface.h @@ -137,6 +137,39 @@ class InterfaceId */ static CHIP_ERROR InterfaceNameToId(const char * intfName, InterfaceId & intfId); + /** + * Get the interface identifier for the specified IP address. If the + * interface identifier cannot be derived it is set to the default InterfaceId. + * + * @note + * This function fetches the first interface (from the configured list + * of interfaces) that matches the specified IP address. + */ + static InterfaceId FromIPAddress(const IPAddress & addr); + + /** + * Check if there is a prefix match between the specified IPv6 address and any of + * the locally configured IPv6 addresses. + * + * @param[in] addr The IPv6 address to check for the prefix-match. + * @return true if a successful match is found, otherwise false. + */ + static bool MatchLocalIPv6Subnet(const IPAddress & addr); + + /** + * Get the link local IPv6 address. + * + * @param[out] llAddr The link local IPv6 address for the link. + * + * @retval #CHIP_ERROR_NOT_IMPLEMENTED If IPv6 is not supported. + * @retval #CHIP_ERROR_INVALID_ARGUMENT If the link local address + * is nullptr. + * @retval #INET_ERROR_ADDRESS_NOT_FOUND If the link does not have + * any address configured. + * @retval #CHIP_NO_ERROR On success. + */ + CHIP_ERROR GetLinkLocalAddr(IPAddress * llAddr); + private: #if CHIP_SYSTEM_CONFIG_USE_LWIP static constexpr PlatformType kPlatformNull = nullptr; diff --git a/src/inet/InetLayer.cpp b/src/inet/InetLayer.cpp index 7f5481b888511b..75e2d0d1afeb75 100644 --- a/src/inet/InetLayer.cpp +++ b/src/inet/InetLayer.cpp @@ -219,91 +219,6 @@ bool InetLayer::IsIdleTimerRunning() } #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT && INET_TCP_IDLE_CHECK_INTERVAL > 0 -/** - * Get the link local IPv6 address for a specified link or interface. - * - * @param[in] interface The interface for which the link local IPv6 - * address is being sought. - * - * @param[out] llAddr The link local IPv6 address for the link. - * - * @retval #CHIP_ERROR_NOT_IMPLEMENTED If IPv6 is not supported. - * @retval #CHIP_ERROR_INVALID_ARGUMENT If the link local address - * is nullptr. - * @retval #INET_ERROR_ADDRESS_NOT_FOUND If the link does not have - * any address configured. - * @retval #CHIP_NO_ERROR On success. - * - */ -CHIP_ERROR InetLayer::GetLinkLocalAddr(InterfaceId interface, IPAddress * llAddr) -{ - VerifyOrReturnError(llAddr != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#if !LWIP_IPV6 - return CHIP_ERROR_NOT_IMPLEMENTED; -#endif //! LWIP_IPV6 - - struct netif * link = interface.GetPlatformInterface(); - for (struct netif * intf = netif_list; intf != NULL; intf = intf->next) - { - if ((link != NULL) && (link != intf)) - continue; - for (int j = 0; j < LWIP_IPV6_NUM_ADDRESSES; ++j) - { - if (ip6_addr_isvalid(netif_ip6_addr_state(intf, j)) && ip6_addr_islinklocal(netif_ip6_addr(intf, j))) - { - (*llAddr) = IPAddress(*netif_ip6_addr(intf, j)); - return CHIP_NO_ERROR; - } - } - if (link != NULL) - { - return INET_ERROR_ADDRESS_NOT_FOUND; - } - } -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS - struct ifaddrs * ifaddr; - const int rv = getifaddrs(&ifaddr); - if (rv == -1) - { - return INET_ERROR_ADDRESS_NOT_FOUND; - } - - for (struct ifaddrs * ifaddr_iter = ifaddr; ifaddr_iter != nullptr; ifaddr_iter = ifaddr_iter->ifa_next) - { - if (ifaddr_iter->ifa_addr != nullptr) - { - if ((ifaddr_iter->ifa_addr->sa_family == AF_INET6) && - (!interface.IsPresent() || (if_nametoindex(ifaddr_iter->ifa_name) == interface.GetPlatformInterface()))) - { - struct in6_addr * sin6_addr = &(reinterpret_cast(ifaddr_iter->ifa_addr))->sin6_addr; - if (sin6_addr->s6_addr[0] == 0xfe && (sin6_addr->s6_addr[1] & 0xc0) == 0x80) // Link Local Address - { - (*llAddr) = IPAddress((reinterpret_cast(ifaddr_iter->ifa_addr))->sin6_addr); - break; - } - } - } - } - freeifaddrs(ifaddr); -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS - -#if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF - net_if * const iface = interface.IsPresent() ? net_if_get_by_index(interface.GetPlatformInterface()) : net_if_get_default(); - VerifyOrReturnError(iface != nullptr, INET_ERROR_ADDRESS_NOT_FOUND); - - in6_addr * const ip6_addr = net_if_ipv6_get_ll(iface, NET_ADDR_PREFERRED); - VerifyOrReturnError(ip6_addr != nullptr, INET_ERROR_ADDRESS_NOT_FOUND); - - *llAddr = IPAddress(*ip6_addr); -#endif // CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF - - return CHIP_NO_ERROR; -} - #if INET_CONFIG_ENABLE_TCP_ENDPOINT /** * Creates a new TCPEndPoint object. @@ -382,74 +297,6 @@ CHIP_ERROR InetLayer::NewUDPEndPoint(UDPEndPoint ** retEndPoint) } #endif // INET_CONFIG_ENABLE_UDP_ENDPOINT -/** - * Get the interface identifier for the specified IP address. If the - * interface identifier cannot be derived it is set to the default - * InterfaceId. - * - * @note - * This function fetches the first interface (from the configured list - * of interfaces) that matches the specified IP address. - * - * @param[in] addr A reference to the IPAddress object. - * - * @param[out] intfId A reference to the InterfaceId object. - * - * @return #CHIP_NO_ERROR unconditionally. - * - */ -CHIP_ERROR InetLayer::GetInterfaceFromAddr(const IPAddress & addr, InterfaceId & intfId) -{ - InterfaceAddressIterator addrIter; - - for (; addrIter.HasCurrent(); addrIter.Next()) - { - IPAddress curAddr = addrIter.GetAddress(); - if (addr == curAddr) - { - intfId = addrIter.GetInterfaceId(); - return CHIP_NO_ERROR; - } - } - - intfId = InterfaceId::Null(); - - return CHIP_NO_ERROR; -} - -/** - * Check if there is a prefix match between the specified IPv6 address and any of - * the locally configured IPv6 addresses. - * - * @param[in] addr The IPv6 address to check for the prefix-match. - * - * @return true if a successful match is found, otherwise false. - * - */ -bool InetLayer::MatchLocalIPv6Subnet(const IPAddress & addr) -{ - if (addr.IsIPv6LinkLocal()) - return true; - - InterfaceAddressIterator ifAddrIter; - for (; ifAddrIter.HasCurrent(); ifAddrIter.Next()) - { - IPPrefix addrPrefix; - addrPrefix.IPAddr = ifAddrIter.GetAddress(); -#if INET_CONFIG_ENABLE_IPV4 - if (addrPrefix.IPAddr.IsIPv4()) - continue; -#endif // INET_CONFIG_ENABLE_IPV4 - if (addrPrefix.IPAddr.IsIPv6LinkLocal()) - continue; - addrPrefix.Length = ifAddrIter.GetPrefixLength(); - if (addrPrefix.MatchAddress(addr)) - return true; - } - - return false; -} - #if INET_CONFIG_ENABLE_TCP_ENDPOINT && INET_TCP_IDLE_CHECK_INTERVAL > 0 void InetLayer::HandleTCPInactivityTimer(chip::System::Layer * aSystemLayer, void * aAppState) { diff --git a/src/inet/InetLayer.h b/src/inet/InetLayer.h index 5372f9c388d388..9ebbff3f136f58 100644 --- a/src/inet/InetLayer.h +++ b/src/inet/InetLayer.h @@ -125,13 +125,6 @@ class DLL_EXPORT InetLayer CHIP_ERROR NewUDPEndPoint(UDPEndPoint ** retEndPoint); #endif // INET_CONFIG_ENABLE_UDP_ENDPOINT - // DNS Resolution - - CHIP_ERROR GetInterfaceFromAddr(const IPAddress & addr, InterfaceId & intfId); - - CHIP_ERROR GetLinkLocalAddr(InterfaceId link, IPAddress * llAddr); - bool MatchLocalIPv6Subnet(const IPAddress & addr); - void * GetPlatformData(); void SetPlatformData(void * aPlatformData); diff --git a/src/inet/TCPEndPoint.cpp b/src/inet/TCPEndPoint.cpp index f93f68805c5d71..2eca44961e2718 100644 --- a/src/inet/TCPEndPoint.cpp +++ b/src/inet/TCPEndPoint.cpp @@ -195,12 +195,11 @@ CHIP_ERROR TCPEndPoint::ConnectImpl(const IPAddress & addr, uint16_t port, Inter if (intfId.IsPresent()) { IPAddress intfLLAddr; - InetLayer & lInetLayer = Layer(); if (!addr.IsIPv6LinkLocal() || mState == State::kBound) return CHIP_ERROR_NOT_IMPLEMENTED; - res = lInetLayer.GetLinkLocalAddr(intfId, &intfLLAddr); + res = intfId.GetLinkLocalAddr(&intfLLAddr); if (res != CHIP_NO_ERROR) return res; diff --git a/src/inet/tests/TestInetEndPoint.cpp b/src/inet/tests/TestInetEndPoint.cpp index 48bd06561a4d9b..25c7b8bf8e5dbb 100644 --- a/src/inet/tests/TestInetEndPoint.cpp +++ b/src/inet/tests/TestInetEndPoint.cpp @@ -142,10 +142,10 @@ static void TestInetInterface(nlTestSuite * inSuite, void * inContext) err = InterfaceId::Null().GetInterfaceName(intName, sizeof(intName)); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR && intName[0] == '\0'); - err = gInet.GetInterfaceFromAddr(addr, intId); + intId = InterfaceId::FromIPAddress(addr); NL_TEST_ASSERT(inSuite, !intId.IsPresent()); - err = gInet.GetLinkLocalAddr(intId, nullptr); + err = intId.GetLinkLocalAddr(nullptr); NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INVALID_ARGUMENT); printf(" Interfaces:\n"); @@ -165,8 +165,8 @@ static void TestInetInterface(nlTestSuite * inSuite, void * inContext) intName, intIterator.IsUp() ? "UP" : "DOWN", intIterator.SupportsMulticast() ? "supports" : "no", intIterator.HasBroadcastAddress() ? "has" : "no"); - gInet.GetLinkLocalAddr(intId, &addr); - gInet.MatchLocalIPv6Subnet(addr); + intId.GetLinkLocalAddr(&addr); + InterfaceId::MatchLocalIPv6Subnet(addr); } NL_TEST_ASSERT(inSuite, !intIterator.Next()); NL_TEST_ASSERT(inSuite, intIterator.GetInterfaceId() == InterfaceId::Null()); @@ -229,10 +229,10 @@ static void TestInetEndPointInternal(nlTestSuite * inSuite, void * inContext) err = gInet.NewTCPEndPoint(&testTCPEP1); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - err = gInet.GetLinkLocalAddr(InterfaceId::Null(), &addr); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - err = gInet.GetInterfaceFromAddr(addr, intId); + err = InterfaceId::Null().GetLinkLocalAddr(&addr); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + intId = InterfaceId::FromIPAddress(addr); + NL_TEST_ASSERT(inSuite, intId.IsPresent()); #if INET_CONFIG_ENABLE_IPV4 NL_TEST_ASSERT(inSuite, IPAddress::FromString("10.0.0.1", addr_v4));