diff --git a/examples/chip-tool/commands/common/Command.cpp b/examples/chip-tool/commands/common/Command.cpp index 9d3b862d56ac2a..376e3fab3c63b0 100644 --- a/examples/chip-tool/commands/common/Command.cpp +++ b/examples/chip-tool/commands/common/Command.cpp @@ -123,7 +123,7 @@ static bool ParseAddressWithInterface(const char * addressString, Command::Addre { struct sockaddr_in6 * addr = reinterpret_cast(result->ai_addr); address->address = ::chip::Inet::IPAddress::FromSockAddr(*addr); - address->interfaceId = ::chip::Inet::InterfaceId(addr->sin6_scope_id); + address->interfaceId = ::chip::Inet::PlatformNetworkInterface::ToInterfaceId(addr->sin6_scope_id); } #if INET_CONFIG_ENABLE_IPV4 else if (result->ai_family == AF_INET) diff --git a/examples/minimal-mdns/AllInterfaceListener.h b/examples/minimal-mdns/AllInterfaceListener.h index 4744583a7f0762..c2574b918f1cb5 100644 --- a/examples/minimal-mdns/AllInterfaceListener.h +++ b/examples/minimal-mdns/AllInterfaceListener.h @@ -100,7 +100,7 @@ class AllInterfaces : public mdns::Minimal::ListenIterator return true; // not a usable interface } - char name[chip::Inet::InterfaceId::kMaxIfNameLength]; + char name[chip::Inet::PlatformNetworkInterface::kMaxNameLength]; if (mIterator.GetInterfaceName(name, sizeof(name)) != CHIP_NO_ERROR) { printf("!!!! FAILED TO GET INTERFACE NAME\n"); diff --git a/examples/minimal-mdns/client.cpp b/examples/minimal-mdns/client.cpp index 1a98bc539764df..6460b234bc9807 100644 --- a/examples/minimal-mdns/client.cpp +++ b/examples/minimal-mdns/client.cpp @@ -187,7 +187,7 @@ class ReportDelegate : public mdns::Minimal::ServerDelegate info->SrcAddress.ToString(addr, sizeof(addr)); char ifName[64]; - VerifyOrDie(info->Interface.GetInterfaceName(ifName, sizeof(ifName)) == CHIP_NO_ERROR); + VerifyOrDie(Inet::PlatformNetworkInterface::GetInterfaceName(info->Interface, ifName, sizeof(ifName)) == CHIP_NO_ERROR); printf("QUERY from: %-15s on port %d, via interface %s\n", addr, info->SrcPort, ifName); Report("QUERY: ", data); @@ -199,7 +199,7 @@ class ReportDelegate : public mdns::Minimal::ServerDelegate info->SrcAddress.ToString(addr, sizeof(addr)); char ifName[64]; - VerifyOrDie(info->Interface.GetInterfaceName(ifName, sizeof(ifName)) == CHIP_NO_ERROR); + VerifyOrDie(Inet::PlatformNetworkInterface::GetInterfaceName(info->Interface, ifName, sizeof(ifName)) == CHIP_NO_ERROR); printf("RESPONSE from: %-15s on port %d, via interface %s\n", addr, info->SrcPort, ifName); Report("RESPONSE: ", data); diff --git a/examples/minimal-mdns/server.cpp b/examples/minimal-mdns/server.cpp index afc84b75261716..300ceaf040c723 100644 --- a/examples/minimal-mdns/server.cpp +++ b/examples/minimal-mdns/server.cpp @@ -116,7 +116,7 @@ class ReplyDelegate : public mdns::Minimal::ServerDelegate, public mdns::Minimal info->SrcAddress.ToString(addr, sizeof(addr)); char ifName[64]; - VerifyOrDie(info->Interface.GetInterfaceName(ifName, sizeof(ifName)) == CHIP_NO_ERROR); + VerifyOrDie(Inet::PlatformNetworkInterface::GetInterfaceName(info->Interface, ifName, sizeof(ifName)) == CHIP_NO_ERROR); printf("QUERY from: %-15s on port %d, via interface %s\n", addr, info->SrcPort, ifName); Report("QUERY: ", data); @@ -135,7 +135,7 @@ class ReplyDelegate : public mdns::Minimal::ServerDelegate, public mdns::Minimal info->SrcAddress.ToString(addr, sizeof(addr)); char ifName[64]; - VerifyOrDie(info->Interface.GetInterfaceName(ifName, sizeof(ifName)) == CHIP_NO_ERROR); + VerifyOrDie(Inet::PlatformNetworkInterface::GetInterfaceName(info->Interface, ifName, sizeof(ifName)) == CHIP_NO_ERROR); printf("RESPONSE from: %-15s on port %d, via interface %s\n", addr, info->SrcPort, ifName); } diff --git a/src/controller/python/chip/discovery/NodeResolution.cpp b/src/controller/python/chip/discovery/NodeResolution.cpp index 7e794b77c8981c..801298fc0a1a4a 100644 --- a/src/controller/python/chip/discovery/NodeResolution.cpp +++ b/src/controller/python/chip/discovery/NodeResolution.cpp @@ -47,7 +47,7 @@ class PythonResolverDelegate : public ResolverDelegate mSuccessCallback( // nodeData.mPeerId.GetCompressedFabricId(), // nodeData.mPeerId.GetNodeId(), // - nodeData.mInterfaceId.GetPlatformInterface(), // + Inet::PlatformNetworkInterface::FromInterfaceId(nodeData.mInterfaceId), // nodeData.mAddress[0].ToString(ipAddressBuffer, sizeof(ipAddressBuffer)), // nodeData.mPort // ); diff --git a/src/include/platform/DiagnosticDataProvider.h b/src/include/platform/DiagnosticDataProvider.h index adf0cd3532f834..2daaa9fbe9a81f 100644 --- a/src/include/platform/DiagnosticDataProvider.h +++ b/src/include/platform/DiagnosticDataProvider.h @@ -44,7 +44,7 @@ struct ThreadMetrics : public app::Clusters::SoftwareDiagnostics::Structs::Threa struct NetworkInterface : public app::Clusters::GeneralDiagnostics::Structs::NetworkInterfaceType::Type { - char Name[Inet::InterfaceId::kMaxIfNameLength]; + char Name[Inet::PlatformNetworkInterface::kMaxNameLength]; uint8_t MacAddress[kMaxHardwareAddrSize]; NetworkInterface * Next; /* Pointer to the next structure. */ }; diff --git a/src/inet/BUILD.gn b/src/inet/BUILD.gn index 164c0076c5a546..0cb3b2058e7122 100644 --- a/src/inet/BUILD.gn +++ b/src/inet/BUILD.gn @@ -54,7 +54,10 @@ buildconfig_header("inet_buildconfig") { [ "INET_PLATFORM_CONFIG_INCLUDE=${chip_inet_platform_config_include}" ] } - defines += [ "INET_TCP_END_POINT_IMPL_CONFIG_FILE=" ] + defines += [ + "INET_INTERFACE_IMPL_CONFIG_FILE=", + "INET_TCP_END_POINT_IMPL_CONFIG_FILE=", + ] if (chip_system_config_use_open_thread_udp) { defines += [ "INET_UDP_END_POINT_IMPL_CONFIG_FILE=", @@ -62,6 +65,26 @@ buildconfig_header("inet_buildconfig") { } else { defines += [ "INET_UDP_END_POINT_IMPL_CONFIG_FILE=" ] } + + if (chip_system_config_inet_interface == "LwIP") { + defines += [ + "CHIP_SYSTEM_CONFIG_USE_LWIP=1", + "CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS=0", + "CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF=0", + ] + } else if (chip_system_config_inet_interface == "IFAddrs") { + defines += [ + "CHIP_SYSTEM_CONFIG_USE_LWIP=0", + "CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS=1", + "CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF=0", + ] + } else if (chip_system_config_inet_interface == "Zephyr") { + defines += [ + "CHIP_SYSTEM_CONFIG_USE_LWIP=0", + "CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS=0", + "CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF=1", + ] + } } source_set("inet_config_header") { @@ -97,6 +120,8 @@ static_library("inet") { "InetFaultInjection.h", "InetInterface.cpp", "InetInterface.h", + "InetInterfaceImpl${chip_system_config_inet_interface}.cpp", + "InetInterfaceImpl${chip_system_config_inet_interface}.h", "InetLayer.h", "arpa-inet-compatibility.h", ] diff --git a/src/inet/InetInterface.cpp b/src/inet/InetInterface.cpp index be344cbe43b983..c5810bd78c9775 100644 --- a/src/inet/InetInterface.cpp +++ b/src/inet/InetInterface.cpp @@ -30,988 +30,10 @@ #include #include -#include -#include -#include - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#include -#include -#include -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS -#include -#include -#include -#include -#ifdef HAVE_SYS_SOCKIO_H -#include -#endif /* HAVE_SYS_SOCKIO_H */ -#include -#include -#include -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS - -#if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF -#include -#endif // CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF - -#include -#include namespace chip { namespace Inet { -#if CHIP_SYSTEM_CONFIG_USE_LWIP - -CHIP_ERROR InterfaceId::GetInterfaceName(char * nameBuf, size_t nameBufSize) const -{ - if (mPlatformInterface) - { - int status = snprintf(nameBuf, nameBufSize, "%c%c%d", mPlatformInterface->name[0], mPlatformInterface->name[1], - mPlatformInterface->num); - if (status >= static_cast(nameBufSize)) - return CHIP_ERROR_BUFFER_TOO_SMALL; - return CHIP_NO_ERROR; - } - if (nameBufSize < 1) - { - return CHIP_ERROR_BUFFER_TOO_SMALL; - } - nameBuf[0] = 0; - return CHIP_NO_ERROR; -} - -CHIP_ERROR InterfaceId::InterfaceNameToId(const char * intfName, InterfaceId & interface) -{ - if (strlen(intfName) < 3) - { - return INET_ERROR_UNKNOWN_INTERFACE; - } - char * parseEnd; - unsigned long intfNum = strtoul(intfName + 2, &parseEnd, 10); - if (*parseEnd != 0 || intfNum > UINT8_MAX) - { - return INET_ERROR_UNKNOWN_INTERFACE; - } - struct netif * intf; -#if defined(NETIF_FOREACH) - NETIF_FOREACH(intf) -#else - for (intf = netif_list; intf != NULL; intf = intf->next) -#endif - { - if (intf->name[0] == intfName[0] && intf->name[1] == intfName[1] && intf->num == (uint8_t) intfNum) - { - interface = InterfaceId(intf); - return CHIP_NO_ERROR; - } - } - interface = InterfaceId::Null(); - return INET_ERROR_UNKNOWN_INTERFACE; -} - -bool InterfaceIterator::Next() -{ - // Lock LwIP stack - LOCK_TCPIP_CORE(); - - // Verify the previous netif is still on the list if netifs. If so, - // advance to the next nextif. - struct netif * prevNetif = mCurNetif; -#if defined(NETIF_FOREACH) - NETIF_FOREACH(mCurNetif) -#else - for (mCurNetif = netif_list; mCurNetif != NULL; mCurNetif = mCurNetif->next) -#endif - { - if (mCurNetif == prevNetif) - { - mCurNetif = mCurNetif->next; - break; - } - } - - // Unlock LwIP stack - UNLOCK_TCPIP_CORE(); - - return mCurNetif != NULL; -} - -CHIP_ERROR InterfaceIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize) -{ - VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE); - return InterfaceId(mCurNetif).GetInterfaceName(nameBuf, nameBufSize); -} - -bool InterfaceIterator::IsUp() -{ - return HasCurrent() && netif_is_up(mCurNetif); -} - -bool InterfaceIterator::SupportsMulticast() -{ - return HasCurrent() && (mCurNetif->flags & (NETIF_FLAG_IGMP | NETIF_FLAG_MLD6 | NETIF_FLAG_BROADCAST)) != 0; -} - -bool InterfaceIterator::HasBroadcastAddress() -{ - return HasCurrent() && (mCurNetif->flags & NETIF_FLAG_BROADCAST) != 0; -} - -CHIP_ERROR InterfaceIterator::GetInterfaceType(InterfaceType & type) -{ - return CHIP_ERROR_NOT_IMPLEMENTED; -} - -CHIP_ERROR InterfaceIterator::GetHardwareAddress(uint8_t * addressBuffer, uint8_t & addressSize, uint8_t addressBufferSize) -{ - VerifyOrReturnError(addressBuffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(addressBufferSize >= mCurNetif->hwaddr_len, CHIP_ERROR_BUFFER_TOO_SMALL); - addressSize = mCurNetif->hwaddr_len; - memcpy(addressBuffer, mCurNetif->hwaddr, addressSize); - return CHIP_NO_ERROR; -} - -bool InterfaceAddressIterator::HasCurrent() -{ - return mIntfIter.HasCurrent() && ((mCurAddrIndex != kBeforeStartIndex) || Next()); -} - -bool InterfaceAddressIterator::Next() -{ - mCurAddrIndex++; - - while (mIntfIter.HasCurrent()) - { - struct netif * curIntf = mIntfIter.GetInterfaceId().GetPlatformInterface(); - - while (mCurAddrIndex < LWIP_IPV6_NUM_ADDRESSES) - { - if (ip6_addr_isvalid(netif_ip6_addr_state(curIntf, mCurAddrIndex))) - { - return true; - } - mCurAddrIndex++; - } - -#if INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4 - if (mCurAddrIndex == LWIP_IPV6_NUM_ADDRESSES) - { - if (!ip4_addr_isany(netif_ip4_addr(curIntf))) - { - return true; - } - } -#endif // INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4 - - mIntfIter.Next(); - mCurAddrIndex = 0; - } - - return false; -} - -CHIP_ERROR InterfaceAddressIterator::GetAddress(IPAddress & outIPAddress) -{ - if (!HasCurrent()) - { - return CHIP_ERROR_SENTINEL; - } - - struct netif * curIntf = mIntfIter.GetInterfaceId().GetPlatformInterface(); - - if (mCurAddrIndex < LWIP_IPV6_NUM_ADDRESSES) - { - outIPAddress = IPAddress(*netif_ip6_addr(curIntf, mCurAddrIndex)); - return CHIP_NO_ERROR; - } -#if INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4 - else - { - outIPAddress = IPAddress(*netif_ip4_addr(curIntf)); - return CHIP_NO_ERROR; - } -#endif // INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4 - return CHIP_ERROR_INTERNAL; -} - -uint8_t InterfaceAddressIterator::GetPrefixLength() -{ - if (HasCurrent()) - { - if (mCurAddrIndex < LWIP_IPV6_NUM_ADDRESSES) - { - return 64; - } -#if INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4 - else - { - struct netif * curIntf = mIntfIter.GetInterfaceId().GetPlatformInterface(); - return NetmaskToPrefixLength((const uint8_t *) netif_ip4_netmask(curIntf), 4); - } -#endif // INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4 - } - return 0; -} - -InterfaceId InterfaceAddressIterator::GetInterfaceId() -{ - return HasCurrent() ? mIntfIter.GetInterfaceId() : InterfaceId::Null(); -} - -CHIP_ERROR InterfaceAddressIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize) -{ - VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE); - return mIntfIter.GetInterfaceName(nameBuf, nameBufSize); -} - -bool InterfaceAddressIterator::IsUp() -{ - return HasCurrent() && mIntfIter.IsUp(); -} - -bool InterfaceAddressIterator::SupportsMulticast() -{ - return HasCurrent() && mIntfIter.SupportsMulticast(); -} - -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 - -CHIP_ERROR InterfaceId::GetInterfaceName(char * nameBuf, size_t nameBufSize) const -{ - if (mPlatformInterface) - { - char intfName[IF_NAMESIZE]; - if (if_indextoname(mPlatformInterface, intfName) == nullptr) - { - return CHIP_ERROR_POSIX(errno); - } - size_t nameLength = strlen(intfName); - if (nameLength >= nameBufSize) - { - return CHIP_ERROR_BUFFER_TOO_SMALL; - } - strncpy(nameBuf, intfName, nameLength + 1); - return CHIP_NO_ERROR; - } - if (nameBufSize < 1) - { - return CHIP_ERROR_BUFFER_TOO_SMALL; - } - nameBuf[0] = 0; - return CHIP_NO_ERROR; -} - -CHIP_ERROR InterfaceId::InterfaceNameToId(const char * intfName, InterfaceId & interface) -{ - unsigned int intfId = if_nametoindex(intfName); - interface = InterfaceId(intfId); - if (intfId == 0) - { - return (errno == ENXIO) ? INET_ERROR_UNKNOWN_INTERFACE : CHIP_ERROR_POSIX(errno); - } - return CHIP_NO_ERROR; -} - -static int sIOCTLSocket = -1; - -/** - * @brief Returns a global general purpose socket useful for invoking certain network IOCTLs. - * - * This function is thread-safe on all platforms. - */ -int GetIOCTLSocket() -{ - if (sIOCTLSocket == -1) - { - int s; -#ifdef SOCK_CLOEXEC - s = socket(AF_INET, SOCK_STREAM, SOCK_CLOEXEC); - if (s < 0) -#endif - { - s = socket(AF_INET, SOCK_STREAM, 0); - fcntl(s, O_CLOEXEC); - } - - if (!__sync_bool_compare_and_swap(&sIOCTLSocket, -1, s)) - { - close(s); - } - } - return sIOCTLSocket; -} - -/** - * @brief Close the global socket created by \c GetIOCTLSocket. - * - * @details - * This function is provided for cases were leaving the global IOCTL socket - * open would register as a leak. - * - * NB: This function is NOT thread-safe with respect to \c GetIOCTLSocket. - */ -void CloseIOCTLSocket() -{ - if (sIOCTLSocket != -1) - { - close(sIOCTLSocket); - sIOCTLSocket = -1; - } -} - -#if __ANDROID__ && __ANDROID_API__ < 24 - -static struct if_nameindex * backport_if_nameindex(void); -static void backport_if_freenameindex(struct if_nameindex *); - -static void backport_if_freenameindex(struct if_nameindex * inArray) -{ - if (inArray == NULL) - { - return; - } - - for (size_t i = 0; inArray[i].if_index != 0; i++) - { - if (inArray[i].if_name != NULL) - { - free(inArray[i].if_name); - } - } - - free(inArray); -} - -static struct if_nameindex * backport_if_nameindex(void) -{ - int err; - unsigned index; - size_t intfIter = 0; - size_t maxIntfNum = 0; - size_t numIntf = 0; - size_t numAddrs = 0; - struct if_nameindex * retval = NULL; - struct if_nameindex * tmpval = NULL; - struct ifaddrs * addrList = NULL; - struct ifaddrs * addrIter = NULL; - const char * lastIntfName = ""; - - err = getifaddrs(&addrList); - VerifyOrExit(err >= 0, ); - - // coalesce on consecutive interface names - for (addrIter = addrList; addrIter != NULL; addrIter = addrIter->ifa_next) - { - numAddrs++; - if (strcmp(addrIter->ifa_name, lastIntfName) == 0) - { - continue; - } - numIntf++; - lastIntfName = addrIter->ifa_name; - } - - tmpval = (struct if_nameindex *) malloc((numIntf + 1) * sizeof(struct if_nameindex)); - VerifyOrExit(tmpval != NULL, ); - memset(tmpval, 0, (numIntf + 1) * sizeof(struct if_nameindex)); - - lastIntfName = ""; - for (addrIter = addrList; addrIter != NULL; addrIter = addrIter->ifa_next) - { - if (strcmp(addrIter->ifa_name, lastIntfName) == 0) - { - continue; - } - - index = if_nametoindex(addrIter->ifa_name); - if (index != 0) - { - tmpval[intfIter].if_index = index; - tmpval[intfIter].if_name = strdup(addrIter->ifa_name); - intfIter++; - } - lastIntfName = addrIter->ifa_name; - } - - // coalesce on interface index - maxIntfNum = 0; - for (size_t i = 0; tmpval[i].if_index != 0; i++) - { - if (maxIntfNum < tmpval[i].if_index) - { - maxIntfNum = tmpval[i].if_index; - } - } - - retval = (struct if_nameindex *) malloc((maxIntfNum + 1) * sizeof(struct if_nameindex)); - VerifyOrExit(retval != NULL, ); - memset(retval, 0, (maxIntfNum + 1) * sizeof(struct if_nameindex)); - - for (size_t i = 0; tmpval[i].if_index != 0; i++) - { - struct if_nameindex * intf = &tmpval[i]; - if (retval[intf->if_index - 1].if_index == 0) - { - retval[intf->if_index - 1] = *intf; - } - else - { - free(intf->if_name); - intf->if_index = 0; - intf->if_name = 0; - } - } - - intfIter = 0; - - // coalesce potential gaps between indeces - for (size_t i = 0; i < maxIntfNum; i++) - { - if (retval[i].if_index != 0) - { - retval[intfIter] = retval[i]; - intfIter++; - } - } - - for (size_t i = intfIter; i < maxIntfNum; i++) - { - retval[i].if_index = 0; - retval[i].if_name = NULL; - } - -exit: - if (tmpval != NULL) - { - free(tmpval); - } - - if (addrList != NULL) - { - freeifaddrs(addrList); - } - - return retval; -} - -#endif // __ANDROID__ && __ANDROID_API__ < 24 - -InterfaceIterator::InterfaceIterator() -{ - mIntfArray = nullptr; - mCurIntf = 0; - mIntfFlags = 0; - mIntfFlagsCached = false; -} - -InterfaceIterator::~InterfaceIterator() -{ - if (mIntfArray != nullptr) - { -#if __ANDROID__ && __ANDROID_API__ < 24 - backport_if_freenameindex(mIntfArray); -#else - if_freenameindex(mIntfArray); -#endif - mIntfArray = nullptr; - } -} - -bool InterfaceIterator::HasCurrent() -{ - return (mIntfArray != nullptr) ? mIntfArray[mCurIntf].if_index != 0 : Next(); -} - -bool InterfaceIterator::Next() -{ - if (mIntfArray == nullptr) - { -#if __ANDROID__ && __ANDROID_API__ < 24 - mIntfArray = backport_if_nameindex(); -#else - mIntfArray = if_nameindex(); -#endif - } - else if (mIntfArray[mCurIntf].if_index != 0) - { - mCurIntf++; - mIntfFlags = 0; - mIntfFlagsCached = false; - } - return (mIntfArray != nullptr && mIntfArray[mCurIntf].if_index != 0); -} - -InterfaceId InterfaceIterator::GetInterfaceId() -{ - return HasCurrent() ? InterfaceId(mIntfArray[mCurIntf].if_index) : InterfaceId::Null(); -} - -CHIP_ERROR InterfaceIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize) -{ - VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(strlen(mIntfArray[mCurIntf].if_name) < nameBufSize, CHIP_ERROR_BUFFER_TOO_SMALL); - strncpy(nameBuf, mIntfArray[mCurIntf].if_name, nameBufSize); - return CHIP_NO_ERROR; -} - -bool InterfaceIterator::IsUp() -{ - return (GetFlags() & IFF_UP) != 0; -} - -bool InterfaceIterator::SupportsMulticast() -{ - return (GetFlags() & IFF_MULTICAST) != 0; -} - -bool InterfaceIterator::HasBroadcastAddress() -{ - return (GetFlags() & IFF_BROADCAST) != 0; -} - -short InterfaceIterator::GetFlags() -{ - struct ifreq intfData; - - if (!mIntfFlagsCached && HasCurrent()) - { - strncpy(intfData.ifr_name, mIntfArray[mCurIntf].if_name, IFNAMSIZ); - intfData.ifr_name[IFNAMSIZ - 1] = '\0'; - - int res = ioctl(GetIOCTLSocket(), SIOCGIFFLAGS, &intfData); - if (res == 0) - { - mIntfFlags = intfData.ifr_flags; - mIntfFlagsCached = true; - } -#if __MBED__ - CloseIOCTLSocket(); -#endif - } - - return mIntfFlags; -} - -CHIP_ERROR InterfaceIterator::GetInterfaceType(InterfaceType & type) -{ - return CHIP_ERROR_NOT_IMPLEMENTED; -} - -CHIP_ERROR InterfaceIterator::GetHardwareAddress(uint8_t * addressBuffer, uint8_t & addressSize, uint8_t addressBufferSize) -{ - return CHIP_ERROR_NOT_IMPLEMENTED; -} - -InterfaceAddressIterator::InterfaceAddressIterator() -{ - mAddrsList = nullptr; - mCurAddr = nullptr; -} - -InterfaceAddressIterator::~InterfaceAddressIterator() -{ - if (mAddrsList != nullptr) - { - freeifaddrs(mAddrsList); - mAddrsList = mCurAddr = nullptr; - } -} - -bool InterfaceAddressIterator::HasCurrent() -{ - return (mAddrsList != nullptr) ? (mCurAddr != nullptr) : Next(); -} - -bool InterfaceAddressIterator::Next() -{ - while (true) - { - if (mAddrsList == nullptr) - { - int res = getifaddrs(&mAddrsList); - if (res < 0) - { - return false; - } - mCurAddr = mAddrsList; - } - else if (mCurAddr != nullptr) - { - mCurAddr = mCurAddr->ifa_next; - } - - if (mCurAddr == nullptr) - { - return false; - } - - if (mCurAddr->ifa_addr != nullptr && - (mCurAddr->ifa_addr->sa_family == AF_INET6 -#if INET_CONFIG_ENABLE_IPV4 - || mCurAddr->ifa_addr->sa_family == AF_INET -#endif // INET_CONFIG_ENABLE_IPV4 - )) - { - return true; - } - } -} - -CHIP_ERROR InterfaceAddressIterator::GetAddress(IPAddress & outIPAddress) -{ - return HasCurrent() ? IPAddress::GetIPAddressFromSockAddr(*mCurAddr->ifa_addr, outIPAddress) : CHIP_ERROR_SENTINEL; -} - -uint8_t InterfaceAddressIterator::GetPrefixLength() -{ - if (HasCurrent()) - { - if (mCurAddr->ifa_addr->sa_family == AF_INET6) - { -#if !__MBED__ - struct sockaddr_in6 & netmask = *reinterpret_cast(mCurAddr->ifa_netmask); - return NetmaskToPrefixLength(netmask.sin6_addr.s6_addr, 16); -#else // __MBED__ - // netmask is not available through an API for IPv6 interface in Mbed. - // Default prefix length to 64. - return 64; -#endif // !__MBED__ - } - if (mCurAddr->ifa_addr->sa_family == AF_INET) - { - struct sockaddr_in & netmask = *reinterpret_cast(mCurAddr->ifa_netmask); - return NetmaskToPrefixLength(reinterpret_cast(&netmask.sin_addr.s_addr), 4); - } - } - return 0; -} - -InterfaceId InterfaceAddressIterator::GetInterfaceId() -{ - return HasCurrent() ? InterfaceId(if_nametoindex(mCurAddr->ifa_name)) : InterfaceId::Null(); -} - -CHIP_ERROR InterfaceAddressIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize) -{ - VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(strlen(mCurAddr->ifa_name) < nameBufSize, CHIP_ERROR_BUFFER_TOO_SMALL); - strncpy(nameBuf, mCurAddr->ifa_name, nameBufSize); - return CHIP_NO_ERROR; -} - -bool InterfaceAddressIterator::IsUp() -{ - return HasCurrent() && (mCurAddr->ifa_flags & IFF_UP) != 0; -} - -bool InterfaceAddressIterator::SupportsMulticast() -{ - return HasCurrent() && (mCurAddr->ifa_flags & IFF_MULTICAST) != 0; -} - -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 - -CHIP_ERROR InterfaceId::GetInterfaceName(char * nameBuf, size_t nameBufSize) const -{ - if (mPlatformInterface) - { - net_if * currentInterface = net_if_get_by_index(mPlatformInterface); - if (!currentInterface) - { - return CHIP_ERROR_INCORRECT_STATE; - } - const char * name = net_if_get_device(currentInterface)->name; - size_t nameLength = strlen(name); - if (nameLength >= nameBufSize) - { - return CHIP_ERROR_BUFFER_TOO_SMALL; - } - strncpy(nameBuf, name, nameLength + 1); - return CHIP_NO_ERROR; - } - if (nameBufSize < 1) - { - return CHIP_ERROR_BUFFER_TOO_SMALL; - } - nameBuf[0] = 0; - return CHIP_NO_ERROR; -} - -CHIP_ERROR InterfaceId::InterfaceNameToId(const char * intfName, InterfaceId & interface) -{ - int currentId = 0; - net_if * currentInterface; - - while ((currentInterface = net_if_get_by_index(++currentId)) != nullptr) - { - if (strcmp(net_if_get_device(currentInterface)->name, intfName) == 0) - { - interface = InterfaceId(currentId); - return CHIP_NO_ERROR; - } - } - interface = InterfaceId::Null(); - return INET_ERROR_UNKNOWN_INTERFACE; -} - -InterfaceIterator::InterfaceIterator() : mCurrentInterface(net_if_get_by_index(mCurrentId)) {} - -bool InterfaceIterator::HasCurrent(void) -{ - return mCurrentInterface != nullptr; -} - -bool InterfaceIterator::Next() -{ - mCurrentInterface = net_if_get_by_index(++mCurrentId); - return HasCurrent(); -} - -InterfaceId InterfaceIterator::GetInterfaceId(void) -{ - return HasCurrent() ? InterfaceId(mCurrentId) : InterfaceId::Null(); -} - -CHIP_ERROR InterfaceIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize) -{ - VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE); - return InterfaceId(mCurrentId).GetInterfaceName(nameBuf, nameBufSize); -} - -bool InterfaceIterator::IsUp() -{ - return HasCurrent() && net_if_is_up(mCurrentInterface); -} - -bool InterfaceIterator::SupportsMulticast() -{ - return HasCurrent() && NET_IF_MAX_IPV6_MADDR > 0; -} - -bool InterfaceIterator::HasBroadcastAddress() -{ - // Zephyr seems to handle broadcast address for IPv4 implicitly - return HasCurrent() && INET_CONFIG_ENABLE_IPV4; -} - -CHIP_ERROR InterfaceIterator::GetInterfaceType(InterfaceType & type) -{ - VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE); - - const net_linkaddr * linkAddr = net_if_get_link_addr(mCurrentInterface); - if (!linkAddr) - return CHIP_ERROR_INCORRECT_STATE; - - // Do not consider other than WiFi and Thread for now. - if (linkAddr->type == NET_LINK_IEEE802154) - { - type = InterfaceType::Thread; - } - // Zephyr doesn't define WiFi address type, so it shares the same type as Ethernet. - else if (linkAddr->type == NET_LINK_ETHERNET) - { - type = InterfaceType::WiFi; - } - else - { - type = InterfaceType::Unknown; - } - - return CHIP_NO_ERROR; -} - -CHIP_ERROR InterfaceIterator::GetHardwareAddress(uint8_t * addressBuffer, uint8_t & addressSize, uint8_t addressBufferSize) -{ - VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE); - - if (!addressBuffer) - return CHIP_ERROR_INVALID_ARGUMENT; - - const net_linkaddr * linkAddr = net_if_get_link_addr(mCurrentInterface); - if (!linkAddr) - return CHIP_ERROR_INCORRECT_STATE; - - if (linkAddr->len > addressBufferSize) - return CHIP_ERROR_BUFFER_TOO_SMALL; - - addressSize = linkAddr->len; - memcpy(addressBuffer, linkAddr->addr, linkAddr->len); - - return CHIP_NO_ERROR; -} - -InterfaceAddressIterator::InterfaceAddressIterator() = default; - -bool InterfaceAddressIterator::HasCurrent() -{ - return mIntfIter.HasCurrent() && (mCurAddrIndex >= 0 || Next()); -} - -bool InterfaceAddressIterator::Next() -{ - while (mIntfIter.HasCurrent()) - { - if (mCurAddrIndex == -1) // first address for the current interface - { - const net_if_config * config = - net_if_get_config(net_if_get_by_index(mIntfIter.GetInterfaceId().GetPlatformInterface())); - mIpv6 = config->ip.ipv6; - } - - while (++mCurAddrIndex < NET_IF_MAX_IPV6_ADDR) - if (mIpv6->unicast[mCurAddrIndex].is_used) - return true; - - mCurAddrIndex = -1; - mIntfIter.Next(); - } - - return false; -} - -CHIP_ERROR InterfaceAddressIterator::GetAddress(IPAddress & outIPAddress) -{ - if (HasCurrent()) - { - outIPAddress = IPAddress(mIpv6->unicast[mCurAddrIndex].address.in6_addr); - return CHIP_NO_ERROR; - } - return CHIP_ERROR_SENTINEL; -} - -uint8_t InterfaceAddressIterator::GetPrefixLength() -{ - if (HasCurrent()) - { - net_if * const iface = net_if_get_by_index(mIntfIter.GetInterfaceId().GetPlatformInterface()); - net_if_ipv6_prefix * const prefix = net_if_ipv6_prefix_get(iface, &mIpv6->unicast[mCurAddrIndex].address.in6_addr); - return prefix ? prefix->len : 128; - } - return 0; -} - -InterfaceId InterfaceAddressIterator::GetInterfaceId() -{ - return HasCurrent() ? mIntfIter.GetInterfaceId() : InterfaceId::Null(); -} - -CHIP_ERROR InterfaceAddressIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize) -{ - VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE); - return mIntfIter.GetInterfaceName(nameBuf, nameBufSize); -} - -bool InterfaceAddressIterator::IsUp() -{ - return HasCurrent() && mIntfIter.IsUp(); -} - -bool InterfaceAddressIterator::SupportsMulticast() -{ - return HasCurrent() && mIntfIter.SupportsMulticast(); -} - -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) { diff --git a/src/inet/InetInterface.h b/src/inet/InetInterface.h index 1189b0a9024e45..981ad3c88a39f8 100644 --- a/src/inet/InetInterface.h +++ b/src/inet/InetInterface.h @@ -32,23 +32,6 @@ #include #include -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#include -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS -struct if_nameindex; -struct ifaddrs; -#endif // CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS - -#if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF -#include - -struct net_if; -struct net_if_ipv4; -struct net_if_ipv6; -#endif // CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF - #include #include @@ -76,78 +59,25 @@ enum class InterfaceType class InterfaceId { public: -#if CHIP_SYSTEM_CONFIG_USE_LWIP - using PlatformType = struct netif *; - static constexpr size_t kMaxIfNameLength = 13; // Names are formatted as %c%c%d -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS - using PlatformType = unsigned int; - static constexpr size_t kMaxIfNameLength = IF_NAMESIZE; -#endif // CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS - -#if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF - using PlatformType = int; - static constexpr size_t kMaxIfNameLength = Z_DEVICE_MAX_NAME_LEN; -#endif - -public: + constexpr InterfaceId() : mInternalId(kInvalidInterface) {} ~InterfaceId() = default; - constexpr InterfaceId() : mPlatformInterface(kPlatformNull) {} - explicit constexpr InterfaceId(PlatformType interface) : mPlatformInterface(interface) {} - - constexpr InterfaceId(const InterfaceId & other) : mPlatformInterface(other.mPlatformInterface) {} + constexpr InterfaceId(const InterfaceId & other) : mInternalId(other.mInternalId) {} constexpr InterfaceId & operator=(const InterfaceId & other) { - mPlatformInterface = other.mPlatformInterface; + mInternalId = other.mInternalId; return *this; } static constexpr InterfaceId Null() { return InterfaceId(); } - constexpr bool operator==(const InterfaceId & other) const { return mPlatformInterface == other.mPlatformInterface; } - constexpr bool operator!=(const InterfaceId & other) const { return mPlatformInterface != other.mPlatformInterface; } + constexpr bool operator==(const InterfaceId & other) const { return mInternalId == other.mInternalId; } + constexpr bool operator!=(const InterfaceId & other) const { return mInternalId != other.mInternalId; } /** * Test for inequivalence with the null interface. */ - bool IsPresent() const { return mPlatformInterface != kPlatformNull; } - - /** - * Get the underlying platform representation of the interface. - */ - PlatformType GetPlatformInterface() const { return mPlatformInterface; } - - /** - * Get the name of the network interface - * - * @param[in] nameBuf Region of memory to write the interface name. - * @param[in] nameBufSize Size of the region denoted by \c nameBuf. - * - * @retval CHIP_NO_ERROR Successful result, interface name written. - * @retval CHIP_ERROR_BUFFER_TOO_SMALL Buffer is too small for the interface name. - * @retval other Another system or platform error. - * - * Writes the name of the network interface as a \c NUL terminated text string at \c nameBuf. - * The name of the unspecified network interface is the empty string. - */ - CHIP_ERROR GetInterfaceName(char * nameBuf, size_t nameBufSize) const; - - /** - * Search the list of network interfaces for the indicated name. - * - * @param[in] intfName Name of the network interface to find. - * @param[out] intfId Indicator of the network interface to assign. - * - * @retval CHIP_NO_ERROR Success, network interface indicated. - * @retval INET_ERROR_UNKNOWN_INTERFACE No network interface found. - * @retval other Another system or platform error. - * - * @note - * On LwIP, this function must be called with the LwIP stack lock acquired. - */ - static CHIP_ERROR InterfaceNameToId(const char * intfName, InterfaceId & intfId); + bool IsPresent() const { return mInternalId != kInvalidInterface; } /** * Get the interface identifier for the specified IP address. If the @@ -168,35 +98,98 @@ class InterfaceId */ 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); + uintptr_t GetInternalId() const { return mInternalId; } + static constexpr InterfaceId FromInternalId(uintptr_t id) { return InterfaceId(id); } private: -#if CHIP_SYSTEM_CONFIG_USE_LWIP - static constexpr PlatformType kPlatformNull = nullptr; -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS - static constexpr PlatformType kPlatformNull = 0; -#endif // CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS - -#if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF - static constexpr PlatformType kPlatformNull = 0; -#endif - PlatformType mPlatformInterface; + static constexpr uintptr_t kInvalidInterface = 0; + + constexpr InterfaceId(uintptr_t id) : mInternalId(id) {} + + uintptr_t mInternalId; }; +namespace PlatformNetworkInterface { + +// Declaration of implementation-specific adjuncts to `InterfaceId`. + +/** + * @var kMaxNameLength + * @brief + * A `constexpr` of type `size_t` that gives the maximum length of the name of a network interface. + */ + +/** + * @typedef Type + * + * @brief + * Data type of a platform-specific representation of a network interface. + */ + +/** + * @fn Type FromInterfaceId(InterfaceId interface) + * + * @brief + * Map a network interface ID from platform-independent InterfaceId to a platform-specific Type. + */ + +/** + * @fn Type ToInterfaceId(Type interface) + * + * @brief + * Map a network interface ID from platform-specific Type to a platform-independent InterfaceId. + */ + +/** + * Get the name of a network interface + * + * @param[in] interface InterfaceId to get the name of. + * @param[in] nameBuf Region of memory to write the interface name. + * @param[in] nameBufSize Size of the region denoted by \c nameBuf. + * + * @retval CHIP_NO_ERROR Successful result, interface name written. + * @retval CHIP_ERROR_BUFFER_TOO_SMALL Buffer is too small for the interface name. + * @retval other Another system or platform error. + * + * Writes the name of the network interface as a \c NUL terminated text string at \c nameBuf. + * The name of the unspecified network interface is the empty string. + */ +CHIP_ERROR GetInterfaceName(InterfaceId interface, char * nameBuf, size_t nameBufSize); + +/** + * Search the list of network interfaces for the indicated name. + * + * @param[in] intfName Name of the network interface to find. + * @param[out] intfId Indicator of the network interface to assign. + * + * @retval CHIP_NO_ERROR Success, network interface indic + + * @retval INET_ERROR_UNKNOWN_INTERFACE No network interface found. + * @retval other Another system or platform error + + * + * @note + * On LwIP, this function must be called with the LwIP stack lock acquired. + */ +CHIP_ERROR InterfaceNameToId(const char * intfName, InterfaceId & intfId); + +/** + * Get the link local IPv6 address of an interface. + * + * @param[in] interface InterfaceId to get the address of. + * @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(InterfaceId interface, IPAddress * llAddr); + +} // namespace PlatformNetworkInterface + /** * Compute a prefix length from a variable-length netmask. */ @@ -223,7 +216,7 @@ extern uint8_t NetmaskToPrefixLength(const uint8_t * netmask, uint16_t netmaskLe * selected interface is removed from the list, in which case iteration ends * immediately. */ -class InterfaceIterator +class InterfaceIteratorBase { public: /** @@ -232,8 +225,8 @@ class InterfaceIterator * Starts the iterator at the first network interface. On some platforms, * this constructor may allocate resources recycled by the destructor. */ - InterfaceIterator(); - ~InterfaceIterator(); + InterfaceIteratorBase() = default; + virtual ~InterfaceIteratorBase() = default; /** * Test whether the iterator is positioned on an interface @@ -241,7 +234,7 @@ class InterfaceIterator * @return \c true if the iterator is positioned on an interface; * \c false if positioned beyond the end of the interface list. */ - bool HasCurrent(); + virtual bool HasCurrent() = 0; /** * Advance the iterator to the next network interface. @@ -260,7 +253,7 @@ class InterfaceIterator * interfaces, *except* in the case of LwIP systems when the currently selected * interface is removed from the list, which causes iteration to end immediately. */ - bool Next(); + virtual bool Next() = 0; /** * InterfaceId InterfaceIterator::GetInterfaceId(void) @@ -270,7 +263,7 @@ class InterfaceIterator * @retval id The current network interface id. * @retval InterfaceId() If advanced beyond the end of the list. */ - InterfaceId GetInterfaceId(); + virtual InterfaceId GetInterfaceId() = 0; /** * Get the name of the current network interface @@ -285,7 +278,7 @@ class InterfaceIterator * * Writes the name of the network interface as \c NUL terminated text string at \c nameBuf. */ - CHIP_ERROR GetInterfaceName(char * nameBuf, size_t nameBufSize); + virtual CHIP_ERROR GetInterfaceName(char * nameBuf, size_t nameBufSize) = 0; /** * Returns whether the current network interface is up. @@ -293,7 +286,7 @@ class InterfaceIterator * @return \c true if current network interface is up, \c false if not * or if the iterator is positioned beyond the end of the list. */ - bool IsUp(); + virtual bool IsUp() = 0; /** * Returns whether the current network interface supports multicast. @@ -301,7 +294,7 @@ class InterfaceIterator * @return \c true if current network interface supports multicast, \c false * if not, or if the iterator is positioned beyond the end of the list. */ - bool SupportsMulticast(); + virtual bool SupportsMulticast() = 0; /** * Returns whether the current network interface has a broadcast address. @@ -309,14 +302,14 @@ class InterfaceIterator * @return \c true if current network interface has a broadcast address, \c false * if not, or if the iterator is positioned beyond the end of the list. */ - bool HasBroadcastAddress(); + virtual bool HasBroadcastAddress() = 0; /** * Get the interface type of the current network interface. * * @param[out] type Object to save the interface type. */ - CHIP_ERROR GetInterfaceType(InterfaceType & type); + virtual CHIP_ERROR GetInterfaceType(InterfaceType & type) = 0; /** * Get the hardware address of the current network interface @@ -325,26 +318,11 @@ class InterfaceIterator * @param[out] addressSize Size of the address saved to a buffer. * @param[in] addressBufferSize Maximum size of a buffer to save data. */ - CHIP_ERROR GetHardwareAddress(uint8_t * addressBuffer, uint8_t & addressSize, uint8_t addressBufferSize); - -protected: -#if CHIP_SYSTEM_CONFIG_USE_LWIP - struct netif * mCurNetif; -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS - struct if_nameindex * mIntfArray; - size_t mCurIntf; - short mIntfFlags; - bool mIntfFlagsCached; - - short GetFlags(); -#endif // CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS - -#if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF - InterfaceId::PlatformType mCurrentId = 1; - net_if * mCurrentInterface = nullptr; -#endif // CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF + virtual CHIP_ERROR GetHardwareAddress(uint8_t * addressBuffer, uint8_t & addressSize, uint8_t addressBufferSize) = 0; + +private: + InterfaceIteratorBase(const InterfaceIteratorBase &) = delete; + InterfaceIteratorBase & operator=(const InterfaceIteratorBase &) = delete; }; /** @@ -369,7 +347,7 @@ class InterfaceIterator * associated with the current address is removed, in which case iteration may * end prematurely. */ -class DLL_EXPORT InterfaceAddressIterator +class DLL_EXPORT InterfaceAddressIteratorBase { public: /** @@ -378,14 +356,14 @@ class DLL_EXPORT InterfaceAddressIterator * Starts the iterator at the first network address. On some platforms, * this constructor may allocate resources recycled by the destructor. */ - InterfaceAddressIterator(); + InterfaceAddressIteratorBase() = default; /** * Destroys an InterfaceAddressIterator object. * * Recycles any resources allocated by the constructor. */ - ~InterfaceAddressIterator(); + virtual ~InterfaceAddressIteratorBase() = default; /** * Test whether the iterator is positioned on an interface address @@ -393,12 +371,10 @@ class DLL_EXPORT InterfaceAddressIterator * @return \c true if the iterator is positioned on an interface address; * \c false if positioned beyond the end of the address list. */ - bool HasCurrent(); + virtual bool HasCurrent() = 0; /** - * @fn bool InterfaceAddressIterator::Next(void) - * - * @brief Advance the iterator to the next interface address. + * Advance the iterator to the next interface address. * * @return \c false if advanced beyond the end, else \c true. * @@ -411,12 +387,10 @@ class DLL_EXPORT InterfaceAddressIterator * themselves are never destroyed. Additionally, iteration on LwIP systems * will terminate early if the current interface is removed from the list. */ - bool Next(); + virtual bool Next() = 0; /** - * @fn IPAddress InterfaceAddressIterator::GetAddress(void) - * - * @brief Get the current interface address. + * Get the current interface address. * * @param[out] outIPAddress The current interface address * @@ -424,12 +398,10 @@ class DLL_EXPORT InterfaceAddressIterator * @return CHIP_ERROR_SENTINEL if the iterator is positioned beyond the end of the address list. * @return other error from lower-level code */ - CHIP_ERROR GetAddress(IPAddress & outIPAddress); + virtual CHIP_ERROR GetAddress(IPAddress & outIPAddress) = 0; /** - * @fn uint8_t InterfaceAddressIterator::GetPrefixLength(void) - * - * @brief Gets the network prefix associated with the current interface address. + * Gets the network prefix associated with the current interface address. * * @return the network prefix (in bits) or 0 if the iterator is positioned beyond * the end of the address list. @@ -443,24 +415,18 @@ class DLL_EXPORT InterfaceAddressIterator * something else. On most platforms, the system's interface address * structure can represent arbitrary prefix lengths between 0 and 128. */ - uint8_t GetPrefixLength(); + virtual uint8_t GetPrefixLength() = 0; /** - * @fn InterfaceId InterfaceAddressIterator::GetInterfaceId(void) - * - * @brief Returns the network interface id associated with the current - * interface address. + * Returns the network interface id associated with the current interface address. * * @return the interface id or \c InterfaceId() if the iterator * is positioned beyond the end of the address list. */ - InterfaceId GetInterfaceId(); + virtual InterfaceId GetInterfaceId() = 0; /** - * @fn CHIP_ERROR InterfaceAddressIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize) - * - * @brief Get the name of the network interface associated with the - * current interface address. + * Get the name of the network interface associated with the current interface address. * * @param[in] nameBuf region of memory to write the interface name * @param[in] nameBufSize size of the region denoted by \c nameBuf @@ -476,7 +442,7 @@ class DLL_EXPORT InterfaceAddressIterator * Writes the name of the network interface as \c NUL terminated text string * at \c nameBuf. */ - CHIP_ERROR GetInterfaceName(char * nameBuf, size_t nameBufSize); + virtual CHIP_ERROR GetInterfaceName(char * nameBuf, size_t nameBufSize) = 0; /** * Returns whether the network interface associated with the current interface address is up. @@ -484,7 +450,7 @@ class DLL_EXPORT InterfaceAddressIterator * @return \c true if current network interface is up, \c false if not, or * if the iterator is not positioned on an interface address. */ - bool IsUp(); + virtual bool IsUp() = 0; /** * Returns whether the network interface associated with the current interface address supports multicast. @@ -492,7 +458,7 @@ class DLL_EXPORT InterfaceAddressIterator * @return \c true if multicast is supported, \c false if not, or * if the iterator is not positioned on an interface address. */ - bool SupportsMulticast(); + virtual bool SupportsMulticast() = 0; /** * Returns whether the network interface associated with the current interface address has an IPv4 broadcast address. @@ -500,63 +466,18 @@ class DLL_EXPORT InterfaceAddressIterator * @return \c true if the interface has a broadcast address, \c false if not, or * if the iterator is not positioned on an interface address. */ - bool HasBroadcastAddress(); + virtual bool HasBroadcastAddress() = 0; private: -#if CHIP_SYSTEM_CONFIG_USE_LWIP - enum - { - kBeforeStartIndex = -1 - }; - - InterfaceIterator mIntfIter; - int mCurAddrIndex; -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS - struct ifaddrs * mAddrsList; - struct ifaddrs * mCurAddr; -#endif // CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS - -#if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF - InterfaceIterator mIntfIter; - net_if_ipv6 * mIpv6 = nullptr; - int mCurAddrIndex = -1; -#endif // CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF + InterfaceAddressIteratorBase(const InterfaceAddressIteratorBase &) = delete; + InterfaceAddressIteratorBase & operator=(const InterfaceAddressIteratorBase &) = delete; }; -#if CHIP_SYSTEM_CONFIG_USE_LWIP - -inline InterfaceIterator::InterfaceIterator(void) -{ - mCurNetif = netif_list; -} - -inline InterfaceIterator::~InterfaceIterator(void) {} - -inline bool InterfaceIterator::HasCurrent(void) -{ - return mCurNetif != NULL; -} - -inline InterfaceId InterfaceIterator::GetInterfaceId(void) -{ - return InterfaceId(mCurNetif); -} - -inline InterfaceAddressIterator::InterfaceAddressIterator(void) -{ - mCurAddrIndex = kBeforeStartIndex; -} - -inline InterfaceAddressIterator::~InterfaceAddressIterator(void) {} - -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF -inline InterfaceIterator::~InterfaceIterator() = default; -inline InterfaceAddressIterator::~InterfaceAddressIterator() = default; -#endif // CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF - } // namespace Inet } // namespace chip + +#ifdef INET_INTERFACE_IMPL_CONFIG_FILE +#include INET_INTERFACE_IMPL_CONFIG_FILE +#else // INET_INTERFACE_IMPL_CONFIG_FILE +#error "INET_INTERFACE_IMPL_CONFIG_FILE not defined" +#endif // INET_INTERFACE_IMPL_CONFIG_FILE diff --git a/src/inet/InetInterfaceImplIFAddrs.cpp b/src/inet/InetInterfaceImplIFAddrs.cpp new file mode 100644 index 00000000000000..97f47f823c120c --- /dev/null +++ b/src/inet/InetInterfaceImplIFAddrs.cpp @@ -0,0 +1,528 @@ +/* + * + * Copyright (c) 2020-2021 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * Copyright (c) 2013-2017 Nest Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Implementation of network interface abstraction layer. + * + */ + +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS +#endif + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SYS_SOCKIO_H +#include +#endif /* HAVE_SYS_SOCKIO_H */ + +namespace chip { +namespace Inet { + +namespace PlatformNetworkInterface { + +CHIP_ERROR GetInterfaceName(unsigned int interface, char * nameBuf, size_t nameBufSize) +{ + if (interface) + { + char intfName[IF_NAMESIZE]; + if (if_indextoname(interface, intfName) == nullptr) + { + return CHIP_ERROR_POSIX(errno); + } + size_t nameLength = strlen(intfName); + if (nameLength >= nameBufSize) + { + return CHIP_ERROR_BUFFER_TOO_SMALL; + } + strncpy(nameBuf, intfName, nameLength + 1); + return CHIP_NO_ERROR; + } + if (nameBufSize < 1) + { + return CHIP_ERROR_BUFFER_TOO_SMALL; + } + nameBuf[0] = 0; + return CHIP_NO_ERROR; +} + +CHIP_ERROR InterfaceNameToId(const char * intfName, InterfaceId & interface) +{ + unsigned int intfId = if_nametoindex(intfName); + if (intfId == 0) + { + interface = InterfaceId::Null(); + return (errno == ENXIO) ? INET_ERROR_UNKNOWN_INTERFACE : CHIP_ERROR_POSIX(errno); + } + interface = ToInterfaceId(intfId); + return CHIP_NO_ERROR; +} + +CHIP_ERROR GetLinkLocalAddr(unsigned int interface, 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) && + ((interface == 0) || (interface == 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; +} + +} // namespace PlatformNetworkInterface + +static int sIOCTLSocket = -1; + +/** + * @brief Returns a global general purpose socket useful for invoking certain network IOCTLs. + * + * This function is thread-safe on all platforms. + */ +int GetIOCTLSocket() +{ + if (sIOCTLSocket == -1) + { + int s; +#ifdef SOCK_CLOEXEC + s = socket(AF_INET, SOCK_STREAM, SOCK_CLOEXEC); + if (s < 0) +#endif + { + s = socket(AF_INET, SOCK_STREAM, 0); + fcntl(s, O_CLOEXEC); + } + + if (!__sync_bool_compare_and_swap(&sIOCTLSocket, -1, s)) + { + close(s); + } + } + return sIOCTLSocket; +} + +/** + * @brief Close the global socket created by \c GetIOCTLSocket. + * + * @details + * This function is provided for cases were leaving the global IOCTL socket + * open would register as a leak. + * + * NB: This function is NOT thread-safe with respect to \c GetIOCTLSocket. + */ +void CloseIOCTLSocket() +{ + if (sIOCTLSocket != -1) + { + close(sIOCTLSocket); + sIOCTLSocket = -1; + } +} + +#if __ANDROID__ && __ANDROID_API__ < 24 + +static struct if_nameindex * backport_if_nameindex(void); +static void backport_if_freenameindex(struct if_nameindex *); + +static void backport_if_freenameindex(struct if_nameindex * inArray) +{ + if (inArray == NULL) + { + return; + } + + for (size_t i = 0; inArray[i].if_index != 0; i++) + { + if (inArray[i].if_name != NULL) + { + free(inArray[i].if_name); + } + } + + free(inArray); +} + +static struct if_nameindex * backport_if_nameindex(void) +{ + int err; + unsigned index; + size_t intfIter = 0; + size_t maxIntfNum = 0; + size_t numIntf = 0; + size_t numAddrs = 0; + struct if_nameindex * retval = NULL; + struct if_nameindex * tmpval = NULL; + struct ifaddrs * addrList = NULL; + struct ifaddrs * addrIter = NULL; + const char * lastIntfName = ""; + + err = getifaddrs(&addrList); + VerifyOrExit(err >= 0, ); + + // coalesce on consecutive interface names + for (addrIter = addrList; addrIter != NULL; addrIter = addrIter->ifa_next) + { + numAddrs++; + if (strcmp(addrIter->ifa_name, lastIntfName) == 0) + { + continue; + } + numIntf++; + lastIntfName = addrIter->ifa_name; + } + + tmpval = (struct if_nameindex *) malloc((numIntf + 1) * sizeof(struct if_nameindex)); + VerifyOrExit(tmpval != NULL, ); + memset(tmpval, 0, (numIntf + 1) * sizeof(struct if_nameindex)); + + lastIntfName = ""; + for (addrIter = addrList; addrIter != NULL; addrIter = addrIter->ifa_next) + { + if (strcmp(addrIter->ifa_name, lastIntfName) == 0) + { + continue; + } + + index = if_nametoindex(addrIter->ifa_name); + if (index != 0) + { + tmpval[intfIter].if_index = index; + tmpval[intfIter].if_name = strdup(addrIter->ifa_name); + intfIter++; + } + lastIntfName = addrIter->ifa_name; + } + + // coalesce on interface index + maxIntfNum = 0; + for (size_t i = 0; tmpval[i].if_index != 0; i++) + { + if (maxIntfNum < tmpval[i].if_index) + { + maxIntfNum = tmpval[i].if_index; + } + } + + retval = (struct if_nameindex *) malloc((maxIntfNum + 1) * sizeof(struct if_nameindex)); + VerifyOrExit(retval != NULL, ); + memset(retval, 0, (maxIntfNum + 1) * sizeof(struct if_nameindex)); + + for (size_t i = 0; tmpval[i].if_index != 0; i++) + { + struct if_nameindex * intf = &tmpval[i]; + if (retval[intf->if_index - 1].if_index == 0) + { + retval[intf->if_index - 1] = *intf; + } + else + { + free(intf->if_name); + intf->if_index = 0; + intf->if_name = 0; + } + } + + intfIter = 0; + + // coalesce potential gaps between indeces + for (size_t i = 0; i < maxIntfNum; i++) + { + if (retval[i].if_index != 0) + { + retval[intfIter] = retval[i]; + intfIter++; + } + } + + for (size_t i = intfIter; i < maxIntfNum; i++) + { + retval[i].if_index = 0; + retval[i].if_name = NULL; + } + +exit: + if (tmpval != NULL) + { + free(tmpval); + } + + if (addrList != NULL) + { + freeifaddrs(addrList); + } + + return retval; +} + +#endif // __ANDROID__ && __ANDROID_API__ < 24 + +InterfaceIteratorImplIFAddrs::InterfaceIteratorImplIFAddrs() +{ + mIntfArray = nullptr; + mCurIntf = 0; + mIntfFlags = 0; + mIntfFlagsCached = false; +} + +InterfaceIteratorImplIFAddrs::~InterfaceIteratorImplIFAddrs() +{ + if (mIntfArray != nullptr) + { +#if __ANDROID__ && __ANDROID_API__ < 24 + backport_if_freenameindex(mIntfArray); +#else + if_freenameindex(mIntfArray); +#endif + mIntfArray = nullptr; + } +} + +bool InterfaceIteratorImplIFAddrs::HasCurrent() +{ + return (mIntfArray != nullptr) ? mIntfArray[mCurIntf].if_index != 0 : Next(); +} + +bool InterfaceIteratorImplIFAddrs::Next() +{ + if (mIntfArray == nullptr) + { +#if __ANDROID__ && __ANDROID_API__ < 24 + mIntfArray = backport_if_nameindex(); +#else + mIntfArray = if_nameindex(); +#endif + } + else if (mIntfArray[mCurIntf].if_index != 0) + { + mCurIntf++; + mIntfFlags = 0; + mIntfFlagsCached = false; + } + return (mIntfArray != nullptr && mIntfArray[mCurIntf].if_index != 0); +} + +InterfaceId InterfaceIteratorImplIFAddrs::GetInterfaceId() +{ + return HasCurrent() ? PlatformNetworkInterface::ToInterfaceId(mIntfArray[mCurIntf].if_index) : InterfaceId::Null(); +} + +CHIP_ERROR InterfaceIteratorImplIFAddrs::GetInterfaceName(char * nameBuf, size_t nameBufSize) +{ + VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(strlen(mIntfArray[mCurIntf].if_name) < nameBufSize, CHIP_ERROR_BUFFER_TOO_SMALL); + strncpy(nameBuf, mIntfArray[mCurIntf].if_name, nameBufSize); + return CHIP_NO_ERROR; +} + +bool InterfaceIteratorImplIFAddrs::IsUp() +{ + return (GetFlags() & IFF_UP) != 0; +} + +bool InterfaceIteratorImplIFAddrs::SupportsMulticast() +{ + return (GetFlags() & IFF_MULTICAST) != 0; +} + +bool InterfaceIteratorImplIFAddrs::HasBroadcastAddress() +{ + return (GetFlags() & IFF_BROADCAST) != 0; +} + +short InterfaceIteratorImplIFAddrs::GetFlags() +{ + struct ifreq intfData; + + if (!mIntfFlagsCached && HasCurrent()) + { + strncpy(intfData.ifr_name, mIntfArray[mCurIntf].if_name, IFNAMSIZ); + intfData.ifr_name[IFNAMSIZ - 1] = '\0'; + + int res = ioctl(GetIOCTLSocket(), SIOCGIFFLAGS, &intfData); + if (res == 0) + { + mIntfFlags = intfData.ifr_flags; + mIntfFlagsCached = true; + } +#if __MBED__ + CloseIOCTLSocket(); +#endif + } + + return mIntfFlags; +} + +CHIP_ERROR InterfaceIteratorImplIFAddrs::GetInterfaceType(InterfaceType & type) +{ + return CHIP_ERROR_NOT_IMPLEMENTED; +} + +CHIP_ERROR InterfaceIteratorImplIFAddrs::GetHardwareAddress(uint8_t * addressBuffer, uint8_t & addressSize, + uint8_t addressBufferSize) +{ + return CHIP_ERROR_NOT_IMPLEMENTED; +} + +InterfaceAddressIteratorImplIFAddrs::InterfaceAddressIteratorImplIFAddrs() +{ + mAddrsList = nullptr; + mCurAddr = nullptr; +} + +InterfaceAddressIteratorImplIFAddrs::~InterfaceAddressIteratorImplIFAddrs() +{ + if (mAddrsList != nullptr) + { + freeifaddrs(mAddrsList); + mAddrsList = mCurAddr = nullptr; + } +} + +bool InterfaceAddressIteratorImplIFAddrs::HasCurrent() +{ + return (mAddrsList != nullptr) ? (mCurAddr != nullptr) : Next(); +} + +bool InterfaceAddressIteratorImplIFAddrs::Next() +{ + while (true) + { + if (mAddrsList == nullptr) + { + int res = getifaddrs(&mAddrsList); + if (res < 0) + { + return false; + } + mCurAddr = mAddrsList; + } + else if (mCurAddr != nullptr) + { + mCurAddr = mCurAddr->ifa_next; + } + + if (mCurAddr == nullptr) + { + return false; + } + + if (mCurAddr->ifa_addr != nullptr && + (mCurAddr->ifa_addr->sa_family == AF_INET6 +#if INET_CONFIG_ENABLE_IPV4 + || mCurAddr->ifa_addr->sa_family == AF_INET +#endif // INET_CONFIG_ENABLE_IPV4 + )) + { + return true; + } + } +} + +CHIP_ERROR InterfaceAddressIteratorImplIFAddrs::GetAddress(IPAddress & outIPAddress) +{ + return HasCurrent() ? IPAddress::GetIPAddressFromSockAddr(*mCurAddr->ifa_addr, outIPAddress) : CHIP_ERROR_SENTINEL; +} + +uint8_t InterfaceAddressIteratorImplIFAddrs::GetPrefixLength() +{ + if (HasCurrent()) + { + if (mCurAddr->ifa_addr->sa_family == AF_INET6) + { +#if !__MBED__ + struct sockaddr_in6 & netmask = *reinterpret_cast(mCurAddr->ifa_netmask); + return NetmaskToPrefixLength(netmask.sin6_addr.s6_addr, 16); +#else // __MBED__ + // netmask is not available through an API for IPv6 interface in Mbed. + // Default prefix length to 64. + return 64; +#endif // !__MBED__ + } + if (mCurAddr->ifa_addr->sa_family == AF_INET) + { + struct sockaddr_in & netmask = *reinterpret_cast(mCurAddr->ifa_netmask); + return NetmaskToPrefixLength(reinterpret_cast(&netmask.sin_addr.s_addr), 4); + } + } + return 0; +} + +InterfaceId InterfaceAddressIteratorImplIFAddrs::GetInterfaceId() +{ + return HasCurrent() ? PlatformNetworkInterface::ToInterfaceId(if_nametoindex(mCurAddr->ifa_name)) : InterfaceId::Null(); +} + +CHIP_ERROR InterfaceAddressIteratorImplIFAddrs::GetInterfaceName(char * nameBuf, size_t nameBufSize) +{ + VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(strlen(mCurAddr->ifa_name) < nameBufSize, CHIP_ERROR_BUFFER_TOO_SMALL); + strncpy(nameBuf, mCurAddr->ifa_name, nameBufSize); + return CHIP_NO_ERROR; +} + +bool InterfaceAddressIteratorImplIFAddrs::IsUp() +{ + return HasCurrent() && (mCurAddr->ifa_flags & IFF_UP) != 0; +} + +bool InterfaceAddressIteratorImplIFAddrs::SupportsMulticast() +{ + return HasCurrent() && (mCurAddr->ifa_flags & IFF_MULTICAST) != 0; +} + +bool InterfaceAddressIteratorImplIFAddrs::HasBroadcastAddress() +{ + return HasCurrent() && (mCurAddr->ifa_flags & IFF_BROADCAST) != 0; +} + +} // namespace Inet +} // namespace chip diff --git a/src/inet/InetInterfaceImplIFAddrs.h b/src/inet/InetInterfaceImplIFAddrs.h new file mode 100644 index 00000000000000..a671d00bce5819 --- /dev/null +++ b/src/inet/InetInterfaceImplIFAddrs.h @@ -0,0 +1,120 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * Copyright (c) 2013-2017 Nest Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * This file defines the Inet::InterfaceId type alias and related + * classes for iterating on the list of system network interfaces and the list + * of system interface addresses. + */ + +#pragma once + +#include + +struct if_nameindex; +struct ifaddrs; + +namespace chip { +namespace Inet { + +namespace PlatformNetworkInterface { + +constexpr size_t kMaxNameLength = IF_NAMESIZE; +using Type = unsigned int; + +inline Type FromInterfaceId(InterfaceId interface) +{ + return static_cast(interface.GetInternalId()); +} + +inline InterfaceId ToInterfaceId(Type interface) +{ + return InterfaceId::FromInternalId(static_cast(interface)); +} + +CHIP_ERROR GetInterfaceName(unsigned int interface, char * nameBuf, size_t nameBufSize); + +inline CHIP_ERROR GetInterfaceName(InterfaceId interface, char * nameBuf, size_t nameBufSize) +{ + return GetInterfaceName(FromInterfaceId(interface), nameBuf, nameBufSize); +} + +CHIP_ERROR GetLinkLocalAddr(unsigned int interface, IPAddress * llAddr); + +inline CHIP_ERROR GetLinkLocalAddr(InterfaceId interface, IPAddress * llAddr) +{ + return GetLinkLocalAddr(FromInterfaceId(interface), llAddr); +} + +} // namespace PlatformNetworkInterface + +class InterfaceIteratorImplIFAddrs : public InterfaceIteratorBase +{ +public: + InterfaceIteratorImplIFAddrs(); + ~InterfaceIteratorImplIFAddrs(); + + // InterfaceIteratorBase overrides. + bool HasCurrent() override; + bool Next() override; + InterfaceId GetInterfaceId() override; + CHIP_ERROR GetInterfaceName(char * nameBuf, size_t nameBufSize) override; + bool IsUp() override; + bool SupportsMulticast() override; + bool HasBroadcastAddress() override; + CHIP_ERROR GetInterfaceType(InterfaceType & type) override; + CHIP_ERROR GetHardwareAddress(uint8_t * addressBuffer, uint8_t & addressSize, uint8_t addressBufferSize) override; + +private: + short GetFlags(); + + struct if_nameindex * mIntfArray; + size_t mCurIntf; + short mIntfFlags; + bool mIntfFlagsCached; +}; + +using InterfaceIterator = InterfaceIteratorImplIFAddrs; + +class InterfaceAddressIteratorImplIFAddrs : public InterfaceAddressIteratorBase +{ +public: + InterfaceAddressIteratorImplIFAddrs(); + ~InterfaceAddressIteratorImplIFAddrs(); + + bool HasCurrent() override; + bool Next() override; + CHIP_ERROR GetAddress(IPAddress & outIPAddress) override; + uint8_t GetPrefixLength() override; + InterfaceId GetInterfaceId() override; + CHIP_ERROR GetInterfaceName(char * nameBuf, size_t nameBufSize) override; + bool IsUp() override; + bool SupportsMulticast() override; + bool HasBroadcastAddress() override; + +private: + struct ifaddrs * mAddrsList; + struct ifaddrs * mCurAddr; +}; + +using InterfaceAddressIterator = InterfaceAddressIteratorImplIFAddrs; + +} // namespace Inet +} // namespace chip diff --git a/src/inet/InetInterfaceImplLwIP.cpp b/src/inet/InetInterfaceImplLwIP.cpp new file mode 100644 index 00000000000000..704d953583ba3a --- /dev/null +++ b/src/inet/InetInterfaceImplLwIP.cpp @@ -0,0 +1,295 @@ +/* + * + * Copyright (c) 2020-2021 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * Copyright (c) 2013-2017 Nest Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Implementation of network interface abstraction layer. + * + */ + +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS +#endif + +#include + +#include + +#include +#include +#include + +#include +#include + +namespace chip { +namespace Inet { + +namespace PlatformNetworkInterface { + +CHIP_ERROR GetInterfaceName(struct netif * interface, char * nameBuf, size_t nameBufSize) +{ + if (interface) + { + int status = snprintf(nameBuf, nameBufSize, "%c%c%d", interface->name[0], interface->name[1], interface->num); + if (status >= static_cast(nameBufSize)) + return CHIP_ERROR_BUFFER_TOO_SMALL; + return CHIP_NO_ERROR; + } + if (nameBufSize < 1) + { + return CHIP_ERROR_BUFFER_TOO_SMALL; + } + nameBuf[0] = 0; + return CHIP_NO_ERROR; +} + +CHIP_ERROR InterfaceNameToId(const char * intfName, InterfaceId & interface) +{ + if (strlen(intfName) < 3) + { + return INET_ERROR_UNKNOWN_INTERFACE; + } + char * parseEnd; + unsigned long intfNum = strtoul(intfName + 2, &parseEnd, 10); + if (*parseEnd != 0 || intfNum > UINT8_MAX) + { + return INET_ERROR_UNKNOWN_INTERFACE; + } + struct netif * intf; +#if defined(NETIF_FOREACH) + NETIF_FOREACH(intf) +#else + for (intf = netif_list; intf != NULL; intf = intf->next) +#endif + { + if (intf->name[0] == intfName[0] && intf->name[1] == intfName[1] && intf->num == (uint8_t) intfNum) + { + interface = ToInterfaceId(intf); + return CHIP_NO_ERROR; + } + } + interface = InterfaceId::Null(); + return INET_ERROR_UNKNOWN_INTERFACE; +} + +CHIP_ERROR GetLinkLocalAddr(struct netif * interface, 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 ((interface != nullptr) && (interface != 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 (interface != nullptr) + { + return INET_ERROR_ADDRESS_NOT_FOUND; + } + } + + return CHIP_NO_ERROR; +} + +} // namespace PlatformNetworkInterface + +bool InterfaceIteratorImplLwIP::Next() +{ + // Lock LwIP stack + LOCK_TCPIP_CORE(); + + // Verify the previous netif is still on the list if netifs. If so, + // advance to the next nextif. + struct netif * prevNetif = mCurNetif; +#if defined(NETIF_FOREACH) + NETIF_FOREACH(mCurNetif) +#else + for (mCurNetif = netif_list; mCurNetif != NULL; mCurNetif = mCurNetif->next) +#endif + { + if (mCurNetif == prevNetif) + { + mCurNetif = mCurNetif->next; + break; + } + } + + // Unlock LwIP stack + UNLOCK_TCPIP_CORE(); + + return mCurNetif != NULL; +} + +CHIP_ERROR InterfaceIteratorImplLwIP::GetInterfaceName(char * nameBuf, size_t nameBufSize) +{ + VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE); + return PlatformNetworkInterface::GetInterfaceName(mCurNetif, nameBuf, nameBufSize); +} + +bool InterfaceIteratorImplLwIP::IsUp() +{ + return HasCurrent() && netif_is_up(mCurNetif); +} + +bool InterfaceIteratorImplLwIP::SupportsMulticast() +{ + return HasCurrent() && (mCurNetif->flags & (NETIF_FLAG_IGMP | NETIF_FLAG_MLD6 | NETIF_FLAG_BROADCAST)) != 0; +} + +bool InterfaceIteratorImplLwIP::HasBroadcastAddress() +{ + return HasCurrent() && (mCurNetif->flags & NETIF_FLAG_BROADCAST) != 0; +} + +CHIP_ERROR InterfaceIteratorImplLwIP::GetInterfaceType(InterfaceType & type) +{ + return CHIP_ERROR_NOT_IMPLEMENTED; +} + +CHIP_ERROR InterfaceIteratorImplLwIP::GetHardwareAddress(uint8_t * addressBuffer, uint8_t & addressSize, uint8_t addressBufferSize) +{ + VerifyOrReturnError(addressBuffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(addressBufferSize >= mCurNetif->hwaddr_len, CHIP_ERROR_BUFFER_TOO_SMALL); + addressSize = mCurNetif->hwaddr_len; + memcpy(addressBuffer, mCurNetif->hwaddr, addressSize); + return CHIP_NO_ERROR; +} + +bool InterfaceAddressIteratorImplLwIP::HasCurrent() +{ + return mIntfIter.HasCurrent() && ((mCurAddrIndex != kBeforeStartIndex) || Next()); +} + +bool InterfaceAddressIteratorImplLwIP::Next() +{ + mCurAddrIndex++; + + while (mIntfIter.HasCurrent()) + { + struct netif * curIntf = PlatformNetworkInterface::FromInterfaceId(mIntfIter.GetInterfaceId()); + + while (mCurAddrIndex < LWIP_IPV6_NUM_ADDRESSES) + { + if (ip6_addr_isvalid(netif_ip6_addr_state(curIntf, mCurAddrIndex))) + { + return true; + } + mCurAddrIndex++; + } + +#if INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4 + if (mCurAddrIndex == LWIP_IPV6_NUM_ADDRESSES) + { + if (!ip4_addr_isany(netif_ip4_addr(curIntf))) + { + return true; + } + } +#endif // INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4 + + mIntfIter.Next(); + mCurAddrIndex = 0; + } + + return false; +} + +CHIP_ERROR InterfaceAddressIteratorImplLwIP::GetAddress(IPAddress & outIPAddress) +{ + if (!HasCurrent()) + { + return CHIP_ERROR_SENTINEL; + } + + struct netif * curIntf = PlatformNetworkInterface::FromInterfaceId(mIntfIter.GetInterfaceId()); + + if (mCurAddrIndex < LWIP_IPV6_NUM_ADDRESSES) + { + outIPAddress = IPAddress(*netif_ip6_addr(curIntf, mCurAddrIndex)); + return CHIP_NO_ERROR; + } +#if INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4 + else + { + outIPAddress = IPAddress(*netif_ip4_addr(curIntf)); + return CHIP_NO_ERROR; + } +#endif // INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4 + return CHIP_ERROR_INTERNAL; +} + +uint8_t InterfaceAddressIteratorImplLwIP::GetPrefixLength() +{ + if (HasCurrent()) + { + if (mCurAddrIndex < LWIP_IPV6_NUM_ADDRESSES) + { + return 64; + } +#if INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4 + else + { + struct netif * curIntf = PlatformNetworkInterface::FromInterfaceId(mIntfIter.GetInterfaceId()); + return NetmaskToPrefixLength((const uint8_t *) netif_ip4_netmask(curIntf), 4); + } +#endif // INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4 + } + return 0; +} + +InterfaceId InterfaceAddressIteratorImplLwIP::GetInterfaceId() +{ + return HasCurrent() ? mIntfIter.GetInterfaceId() : InterfaceId::Null(); +} + +CHIP_ERROR InterfaceAddressIteratorImplLwIP::GetInterfaceName(char * nameBuf, size_t nameBufSize) +{ + VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE); + return mIntfIter.GetInterfaceName(nameBuf, nameBufSize); +} + +bool InterfaceAddressIteratorImplLwIP::IsUp() +{ + return HasCurrent() && mIntfIter.IsUp(); +} + +bool InterfaceAddressIteratorImplLwIP::SupportsMulticast() +{ + return HasCurrent() && mIntfIter.SupportsMulticast(); +} + +bool InterfaceAddressIteratorImplLwIP::HasBroadcastAddress() +{ + return HasCurrent() && mIntfIter.HasBroadcastAddress(); +} + +} // namespace Inet +} // namespace chip diff --git a/src/inet/InetInterfaceImplLwIP.h b/src/inet/InetInterfaceImplLwIP.h new file mode 100644 index 00000000000000..a7f5a8a6ab596a --- /dev/null +++ b/src/inet/InetInterfaceImplLwIP.h @@ -0,0 +1,117 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * Copyright (c) 2013-2017 Nest Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * This file defines the Inet::InterfaceId type alias and related + * classes for iterating on the list of system network interfaces and the list + * of system interface addresses. + */ + +#pragma once + +#include + +namespace chip { +namespace Inet { + +namespace PlatformNetworkInterface { + +using Type = struct netif *; +constexpr size_t kMaxNameLength = 13; // Names are formatted as %c%c%d + +inline Type FromInterfaceId(InterfaceId interface) +{ + return reinterpret_cast(interface.GetInternalId()); +} + +inline InterfaceId ToInterfaceId(Type interface) +{ + return InterfaceId::FromInternalId(reinterpret_cast(interface)); +} + +CHIP_ERROR GetInterfaceName(struct netif * interface, char * nameBuf, size_t nameBufSize); + +inline CHIP_ERROR GetInterfaceName(InterfaceId interface, char * nameBuf, size_t nameBufSize) +{ + return GetInterfaceName(FromInterfaceId(interface), nameBuf, nameBufSize); +} + +CHIP_ERROR GetLinkLocalAddr(struct netif * interface, IPAddress * llAddr); + +inline CHIP_ERROR GetLinkLocalAddr(InterfaceId interface, IPAddress * llAddr) +{ + return GetLinkLocalAddr(FromInterfaceId(interface), llAddr); +} + +} // namespace PlatformNetworkInterface + +class InterfaceIteratorImplLwIP : public InterfaceIteratorBase +{ +public: + InterfaceIteratorImplLwIP() { mCurNetif = netif_list; } + ~InterfaceIteratorImplLwIP() {} + + // InterfaceIteratorBase overrides. + bool HasCurrent() override { return mCurNetif != NULL; } + bool Next() override; + InterfaceId GetInterfaceId() override { return PlatformNetworkInterface::ToInterfaceId(mCurNetif); } + CHIP_ERROR GetInterfaceName(char * nameBuf, size_t nameBufSize) override; + bool IsUp() override; + bool SupportsMulticast() override; + bool HasBroadcastAddress() override; + CHIP_ERROR GetInterfaceType(InterfaceType & type) override; + CHIP_ERROR GetHardwareAddress(uint8_t * addressBuffer, uint8_t & addressSize, uint8_t addressBufferSize) override; + +private: + struct netif * mCurNetif; +}; + +using InterfaceIterator = InterfaceIteratorImplLwIP; + +class InterfaceAddressIteratorImplLwIP : public InterfaceAddressIteratorBase +{ +public: + InterfaceAddressIteratorImplLwIP() : mCurAddrIndex(kBeforeStartIndex) {} + ~InterfaceAddressIteratorImplLwIP() = default; + + bool HasCurrent() override; + bool Next() override; + CHIP_ERROR GetAddress(IPAddress & outIPAddress) override; + uint8_t GetPrefixLength() override; + InterfaceId GetInterfaceId() override; + CHIP_ERROR GetInterfaceName(char * nameBuf, size_t nameBufSize) override; + bool IsUp() override; + bool SupportsMulticast() override; + bool HasBroadcastAddress() override; + +private: + enum + { + kBeforeStartIndex = -1 + }; + + InterfaceIterator mIntfIter; + int mCurAddrIndex; +}; + +using InterfaceAddressIterator = InterfaceAddressIteratorImplLwIP; + +} // namespace Inet +} // namespace chip diff --git a/src/inet/InetInterfaceImplZephyr.cpp b/src/inet/InetInterfaceImplZephyr.cpp new file mode 100644 index 00000000000000..87914afb6c708c --- /dev/null +++ b/src/inet/InetInterfaceImplZephyr.cpp @@ -0,0 +1,268 @@ +/* + * + * Copyright (c) 2020-2021 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * Copyright (c) 2013-2017 Nest Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Implementation of network interface abstraction layer. + * + */ + +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS +#endif + +#include + +#include + +#include + +#include +#include + +namespace chip { +namespace Inet { + +namespace PlatformNetworkInterface { + +CHIP_ERROR GetInterfaceName(int interface, char * nameBuf, size_t nameBufSize) +{ + if (interface) + { + net_if * currentInterface = net_if_get_by_index(interface); + if (!currentInterface) + { + return CHIP_ERROR_INCORRECT_STATE; + } + const char * name = net_if_get_device(currentInterface)->name; + size_t nameLength = strlen(name); + if (nameLength >= nameBufSize) + { + return CHIP_ERROR_BUFFER_TOO_SMALL; + } + strncpy(nameBuf, name, nameLength + 1); + return CHIP_NO_ERROR; + } + if (nameBufSize < 1) + { + return CHIP_ERROR_BUFFER_TOO_SMALL; + } + nameBuf[0] = 0; + return CHIP_NO_ERROR; +} + +CHIP_ERROR InterfaceNameToId(const char * intfName, InterfaceId & interface) +{ + int currentId = 0; + net_if * currentInterface; + + while ((currentInterface = net_if_get_by_index(++currentId)) != nullptr) + { + if (strcmp(net_if_get_device(currentInterface)->name, intfName) == 0) + { + interface = PlatformNetworkInterface::ToInterfaceId(currentId); + return CHIP_NO_ERROR; + } + } + interface = InterfaceId::Null(); + return INET_ERROR_UNKNOWN_INTERFACE; +} + +CHIP_ERROR GetLinkLocalAddr(int interface, IPAddress * llAddr) +{ + VerifyOrReturnError(llAddr != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + + net_if * const iface = interface ? net_if_get_by_index(interface) : 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; +} + +} // namespace PlatformNetworkInterface + +InterfaceIteratorImplZephyr::InterfaceIteratorImplZephyr() : mCurrentInterface(net_if_get_by_index(mCurrentId)) {} + +bool InterfaceIteratorImplZephyr::HasCurrent(void) +{ + return mCurrentInterface != nullptr; +} + +bool InterfaceIteratorImplZephyr::Next() +{ + mCurrentInterface = net_if_get_by_index(++mCurrentId); + return HasCurrent(); +} + +InterfaceId InterfaceIteratorImplZephyr::GetInterfaceId(void) +{ + return HasCurrent() ? PlatformNetworkInterface::ToInterfaceId(mCurrentId) : InterfaceId::Null(); +} + +CHIP_ERROR InterfaceIteratorImplZephyr::GetInterfaceName(char * nameBuf, size_t nameBufSize) +{ + VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE); + return PlatformNetworkInterface::GetInterfaceName(mCurrentId, nameBuf, nameBufSize); +} + +bool InterfaceIteratorImplZephyr::IsUp() +{ + return HasCurrent() && net_if_is_up(mCurrentInterface); +} + +bool InterfaceIteratorImplZephyr::SupportsMulticast() +{ + return HasCurrent() && NET_IF_MAX_IPV6_MADDR > 0; +} + +bool InterfaceIteratorImplZephyr::HasBroadcastAddress() +{ + // Zephyr seems to handle broadcast address for IPv4 implicitly + return HasCurrent() && INET_CONFIG_ENABLE_IPV4; +} + +CHIP_ERROR InterfaceIteratorImplZephyr::GetInterfaceType(InterfaceType & type) +{ + VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE); + + const net_linkaddr * linkAddr = net_if_get_link_addr(mCurrentInterface); + if (!linkAddr) + return CHIP_ERROR_INCORRECT_STATE; + + // Do not consider other than WiFi and Thread for now. + if (linkAddr->type == NET_LINK_IEEE802154) + { + type = InterfaceType::Thread; + } + // Zephyr doesn't define WiFi address type, so it shares the same type as Ethernet. + else if (linkAddr->type == NET_LINK_ETHERNET) + { + type = InterfaceType::WiFi; + } + else + { + type = InterfaceType::Unknown; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR InterfaceIteratorImplZephyr::GetHardwareAddress(uint8_t * addressBuffer, uint8_t & addressSize, + uint8_t addressBufferSize) +{ + VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE); + + if (!addressBuffer) + return CHIP_ERROR_INVALID_ARGUMENT; + + const net_linkaddr * linkAddr = net_if_get_link_addr(mCurrentInterface); + if (!linkAddr) + return CHIP_ERROR_INCORRECT_STATE; + + if (linkAddr->len > addressBufferSize) + return CHIP_ERROR_BUFFER_TOO_SMALL; + + addressSize = linkAddr->len; + memcpy(addressBuffer, linkAddr->addr, linkAddr->len); + + return CHIP_NO_ERROR; +} + +InterfaceAddressIteratorImplZephyr::InterfaceAddressIteratorImplZephyr() = default; + +bool InterfaceAddressIteratorImplZephyr::HasCurrent() +{ + return mIntfIter.HasCurrent() && (mCurAddrIndex >= 0 || Next()); +} + +bool InterfaceAddressIteratorImplZephyr::Next() +{ + while (mIntfIter.HasCurrent()) + { + if (mCurAddrIndex == -1) // first address for the current interface + { + const net_if_config * config = + net_if_get_config(net_if_get_by_index(PlatformNetworkInterface::FromInterfaceId(mIntfIter.GetInterfaceId()))); + mIpv6 = config->ip.ipv6; + } + + while (++mCurAddrIndex < NET_IF_MAX_IPV6_ADDR) + if (mIpv6->unicast[mCurAddrIndex].is_used) + return true; + + mCurAddrIndex = -1; + mIntfIter.Next(); + } + + return false; +} + +CHIP_ERROR InterfaceAddressIteratorImplZephyr::GetAddress(IPAddress & outIPAddress) +{ + if (HasCurrent()) + { + outIPAddress = IPAddress(mIpv6->unicast[mCurAddrIndex].address.in6_addr); + return CHIP_NO_ERROR; + } + return CHIP_ERROR_SENTINEL; +} + +uint8_t InterfaceAddressIteratorImplZephyr::GetPrefixLength() +{ + if (HasCurrent()) + { + net_if * const iface = net_if_get_by_index(PlatformNetworkInterface::FromInterfaceId(mIntfIter.GetInterfaceId())); + net_if_ipv6_prefix * const prefix = net_if_ipv6_prefix_get(iface, &mIpv6->unicast[mCurAddrIndex].address.in6_addr); + return prefix ? prefix->len : 128; + } + return 0; +} + +InterfaceId InterfaceAddressIteratorImplZephyr::GetInterfaceId() +{ + return HasCurrent() ? mIntfIter.GetInterfaceId() : InterfaceId::Null(); +} + +CHIP_ERROR InterfaceAddressIteratorImplZephyr::GetInterfaceName(char * nameBuf, size_t nameBufSize) +{ + VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE); + return mIntfIter.GetInterfaceName(nameBuf, nameBufSize); +} + +bool InterfaceAddressIteratorImplZephyr::IsUp() +{ + return HasCurrent() && mIntfIter.IsUp(); +} + +bool InterfaceAddressIteratorImplZephyr::SupportsMulticast() +{ + return HasCurrent() && mIntfIter.SupportsMulticast(); +} + +bool InterfaceAddressIteratorImplZephyr::HasBroadcastAddress() +{ + return HasCurrent() && mIntfIter.HasBroadcastAddress(); +} + +} // namespace Inet +} // namespace chip diff --git a/src/inet/InetInterfaceImplZephyr.h b/src/inet/InetInterfaceImplZephyr.h new file mode 100644 index 00000000000000..41c6cf51fe31c5 --- /dev/null +++ b/src/inet/InetInterfaceImplZephyr.h @@ -0,0 +1,117 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2019 Google LLC. + * Copyright (c) 2013-2017 Nest Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * This file defines the Inet::InterfaceId type alias and related + * classes for iterating on the list of system network interfaces and the list + * of system interface addresses. + */ + +#pragma once + +#include + +struct net_if; +struct net_if_ipv4; +struct net_if_ipv6; + +namespace chip { +namespace Inet { +namespace PlatformNetworkInterface { + +constexpr size_t kMaxNameLength = Z_DEVICE_MAX_NAME_LEN; +using Type = int; + +inline Type FromInterfaceId(InterfaceId interface) +{ + return static_cast(interface.GetInternalId()); +} + +inline InterfaceId ToInterfaceId(Type interface) +{ + return InterfaceId::FromInternalId(static_cast(interface)); +} + +CHIP_ERROR GetInterfaceName(int interface, char * nameBuf, size_t nameBufSize); + +inline CHIP_ERROR GetInterfaceName(InterfaceId interface, char * nameBuf, size_t nameBufSize) +{ + return GetInterfaceName(FromInterfaceId(interface), nameBuf, nameBufSize); +} + +CHIP_ERROR GetLinkLocalAddr(int interface, IPAddress * llAddr); + +inline CHIP_ERROR GetLinkLocalAddr(InterfaceId interface, IPAddress * llAddr) +{ + return GetLinkLocalAddr(FromInterfaceId(interface), llAddr); +} + +} // namespace PlatformNetworkInterface + +class InterfaceIteratorImplZephyr : public InterfaceIteratorBase +{ +public: + InterfaceIteratorImplZephyr(); + ~InterfaceIteratorImplZephyr() = default; + + // InterfaceIteratorBase overrides. + bool HasCurrent() override; + bool Next() override; + InterfaceId GetInterfaceId() override; + CHIP_ERROR GetInterfaceName(char * nameBuf, size_t nameBufSize) override; + bool IsUp() override; + bool SupportsMulticast() override; + bool HasBroadcastAddress() override; + CHIP_ERROR GetInterfaceType(InterfaceType & type) override; + CHIP_ERROR GetHardwareAddress(uint8_t * addressBuffer, uint8_t & addressSize, uint8_t addressBufferSize) override; + +private: + PlatformNetworkInterface::Type mCurrentId = 1; + net_if * mCurrentInterface = nullptr; +}; + +using InterfaceIterator = InterfaceIteratorImplZephyr; + +class InterfaceAddressIteratorImplZephyr : public InterfaceAddressIteratorBase +{ +public: + InterfaceAddressIteratorImplZephyr(); + ~InterfaceAddressIteratorImplZephyr() = default; + + bool HasCurrent() override; + bool Next() override; + CHIP_ERROR GetAddress(IPAddress & outIPAddress) override; + uint8_t GetPrefixLength() override; + InterfaceId GetInterfaceId() override; + CHIP_ERROR GetInterfaceName(char * nameBuf, size_t nameBufSize) override; + bool IsUp() override; + bool SupportsMulticast() override; + bool HasBroadcastAddress() override; + +private: + InterfaceIterator mIntfIter; + net_if_ipv6 * mIpv6 = nullptr; + int mCurAddrIndex = -1; +}; + +using InterfaceAddressIterator = InterfaceAddressIteratorImplZephyr; + +} // namespace Inet +} // namespace chip diff --git a/src/inet/TCPEndPointImplLwIP.cpp b/src/inet/TCPEndPointImplLwIP.cpp index cc454552b3fb32..5c285e01b0aab8 100644 --- a/src/inet/TCPEndPointImplLwIP.cpp +++ b/src/inet/TCPEndPointImplLwIP.cpp @@ -116,7 +116,7 @@ CHIP_ERROR TCPEndPointImplLwIP::ConnectImpl(const IPAddress & addr, uint16_t por if (!addr.IsIPv6LinkLocal() || mState == State::kBound) return CHIP_ERROR_NOT_IMPLEMENTED; - res = intfId.GetLinkLocalAddr(&intfLLAddr); + res = PlatformNetworkInterface::GetLinkLocalAddr(intfId, &intfLLAddr); if (res != CHIP_NO_ERROR) return res; diff --git a/src/inet/TCPEndPointImplSockets.cpp b/src/inet/TCPEndPointImplSockets.cpp index d5d41fcc98afa1..920b355aaab33c 100644 --- a/src/inet/TCPEndPointImplSockets.cpp +++ b/src/inet/TCPEndPointImplSockets.cpp @@ -209,7 +209,7 @@ CHIP_ERROR TCPEndPointImplSockets::ConnectImpl(const IPAddress & addr, uint16_t struct ::ifreq ifr; memset(&ifr, 0, sizeof(ifr)); - ReturnErrorOnFailure(intfId.GetInterfaceName(ifr.ifr_name, sizeof(ifr.ifr_name))); + ReturnErrorOnFailure(PlatformNetworkInterface::GetInterfaceName(intfId, ifr.ifr_name, sizeof(ifr.ifr_name))); // Attempt to bind to the interface using SO_BINDTODEVICE which requires privileged access. // If the permission is denied(EACCES) because CHIP is running in a context @@ -254,7 +254,7 @@ CHIP_ERROR TCPEndPointImplSockets::ConnectImpl(const IPAddress & addr, uint16_t sa.in6.sin6_port = htons(port); sa.in6.sin6_flowinfo = 0; sa.in6.sin6_addr = addr.ToIPv6(); - sa.in6.sin6_scope_id = intfId.GetPlatformInterface(); + sa.in6.sin6_scope_id = PlatformNetworkInterface::FromInterfaceId(intfId); sockaddrsize = sizeof(sockaddr_in6); sockaddrptr = reinterpret_cast(&sa.in6); } @@ -368,7 +368,7 @@ CHIP_ERROR TCPEndPointImplSockets::GetInterfaceId(InterfaceId * retInterface) { if (IPAddress(sa.in6.sin6_addr).IsIPv6LinkLocal()) { - *retInterface = InterfaceId(sa.in6.sin6_scope_id); + *retInterface = PlatformNetworkInterface::ToInterfaceId(sa.in6.sin6_scope_id); } else { diff --git a/src/inet/UDPEndPointImplLwIP.cpp b/src/inet/UDPEndPointImplLwIP.cpp index f21185741ceeaa..51dabf3dbd4132 100644 --- a/src/inet/UDPEndPointImplLwIP.cpp +++ b/src/inet/UDPEndPointImplLwIP.cpp @@ -133,9 +133,9 @@ CHIP_ERROR UDPEndPointImplLwIP::LwIPBindInterface(struct udp_pcb * aUDP, Interfa InterfaceId UDPEndPointImplLwIP::GetBoundInterface() const { #if HAVE_LWIP_UDP_BIND_NETIF - return InterfaceId(netif_get_by_index(mUDP->netif_idx)); + return PlatformNetworkInterface::ToInterfaceId(netif_get_by_index(mUDP->netif_idx)); #else - return InterfaceId(mUDP->intf_filter); + return PlatformNetworkInterface::ToInterfaceId(mUDP->intf_filter); #endif } @@ -208,7 +208,7 @@ CHIP_ERROR UDPEndPointImplLwIP::SendMsgImpl(const IPPacketInfo * pktInfo, System if (intfId.IsPresent()) { lwipErr = udp_sendto_if(mUDP, System::LwIPPacketBufferView::UnsafeGetLwIPpbuf(msg), &lwipDestAddr, destPort, - intfId.GetPlatformInterface()); + PlatformNetworkInterface::FromInterfaceId(intfId)); } else { @@ -366,7 +366,7 @@ void UDPEndPointImplLwIP::LwIPReceiveUDPMessage(void * arg, struct udp_pcb * pcb { pktInfo->SrcAddress = IPAddress(*addr); pktInfo->DestAddress = IPAddress(*ip_current_dest_addr()); - pktInfo->Interface = InterfaceId(ip_current_netif()); + pktInfo->Interface = PlatformNetworkInterface::ToInterfaceId(ip_current_netif()); pktInfo->SrcPort = port; pktInfo->DestPort = pcb->local_port; } @@ -456,13 +456,14 @@ struct netif * UDPEndPointImplLwIP::FindNetifFromInterfaceId(InterfaceId aInterf #if defined(NETIF_FOREACH) NETIF_FOREACH(lRetval) { - if (lRetval == aInterfaceId.GetPlatformInterface()) + if (lRetval == PlatformNetworkInterface::FromInterfaceId(aInterfaceId)) { break; } } #else // defined(NETIF_FOREACH) - for (lRetval = netif_list; lRetval != nullptr && lRetval != aInterfaceId.GetPlatformInterface(); lRetval = lRetval->next) + for (lRetval = netif_list; lRetval != nullptr && lRetval != PlatformNetworkInterface::FromInterfaceId(aInterfaceId); + lRetval = lRetval->next) ; #endif // defined(NETIF_FOREACH) diff --git a/src/inet/UDPEndPointImplSockets.cpp b/src/inet/UDPEndPointImplSockets.cpp index 93b0828f5a1e21..53fdd796f0baeb 100644 --- a/src/inet/UDPEndPointImplSockets.cpp +++ b/src/inet/UDPEndPointImplSockets.cpp @@ -84,10 +84,10 @@ CHIP_ERROR IPv6Bind(int socket, const IPAddress & address, uint16_t port, Interf { struct sockaddr_in6 sa; memset(&sa, 0, sizeof(sa)); - sa.sin6_family = AF_INET6; - sa.sin6_port = htons(port); - sa.sin6_addr = address.ToIPv6(); - InterfaceId::PlatformType interfaceId = interface.GetPlatformInterface(); + sa.sin6_family = AF_INET6; + sa.sin6_port = htons(port); + sa.sin6_addr = address.ToIPv6(); + PlatformNetworkInterface::Type interfaceId = PlatformNetworkInterface::FromInterfaceId(interface); if (!CanCastTo(interfaceId)) { return CHIP_ERROR_INCORRECT_STATE; @@ -236,7 +236,7 @@ CHIP_ERROR UDPEndPointImplSockets::BindInterfaceImpl(IPAddressType addressType, { // Start filtering on the passed interface. char interfaceName[IF_NAMESIZE]; - if (if_indextoname(interfaceId.GetPlatformInterface(), interfaceName) == nullptr) + if (if_indextoname(PlatformNetworkInterface::FromInterfaceId(interfaceId), interfaceName) == nullptr) { status = CHIP_ERROR_POSIX(errno); } @@ -315,10 +315,10 @@ CHIP_ERROR UDPEndPointImplSockets::SendMsgImpl(const IPPacketInfo * aPktInfo, Sy msgHeader.msg_name = &peerSockAddr; if (mAddrType == IPAddressType::kIPv6) { - peerSockAddr.in6.sin6_family = AF_INET6; - peerSockAddr.in6.sin6_port = htons(aPktInfo->DestPort); - peerSockAddr.in6.sin6_addr = aPktInfo->DestAddress.ToIPv6(); - InterfaceId::PlatformType intfId = aPktInfo->Interface.GetPlatformInterface(); + peerSockAddr.in6.sin6_family = AF_INET6; + peerSockAddr.in6.sin6_port = htons(aPktInfo->DestPort); + peerSockAddr.in6.sin6_addr = aPktInfo->DestAddress.ToIPv6(); + PlatformNetworkInterface::Type intfId = PlatformNetworkInterface::FromInterfaceId(aPktInfo->Interface); VerifyOrReturnError(CanCastTo(intfId), CHIP_ERROR_INCORRECT_STATE); peerSockAddr.in6.sin6_scope_id = static_cast(intfId); msgHeader.msg_namelen = sizeof(sockaddr_in6); @@ -355,8 +355,8 @@ CHIP_ERROR UDPEndPointImplSockets::SendMsgImpl(const IPPacketInfo * aPktInfo, Sy msgHeader.msg_control = controlData; msgHeader.msg_controllen = sizeof(controlData); - struct cmsghdr * controlHdr = CMSG_FIRSTHDR(&msgHeader); - InterfaceId::PlatformType intfId = intf.GetPlatformInterface(); + struct cmsghdr * controlHdr = CMSG_FIRSTHDR(&msgHeader); + PlatformNetworkInterface::Type intfId = PlatformNetworkInterface::FromInterfaceId(intf); #if INET_CONFIG_ENABLE_IPV4 @@ -648,12 +648,13 @@ void UDPEndPointImplSockets::HandlePendingIO(System::SocketEvents events) if (controlHdr->cmsg_level == IPPROTO_IP && controlHdr->cmsg_type == IP_PKTINFO) { auto * inPktInfo = reinterpret_cast CMSG_DATA(controlHdr); - if (!CanCastTo(inPktInfo->ipi_ifindex)) + if (!CanCastTo(inPktInfo->ipi_ifindex)) { lStatus = CHIP_ERROR_INCORRECT_STATE; break; } - lPacketInfo.Interface = InterfaceId(static_cast(inPktInfo->ipi_ifindex)); + lPacketInfo.Interface = PlatformNetworkInterface::ToInterfaceId( + static_cast(inPktInfo->ipi_ifindex)); lPacketInfo.DestAddress = IPAddress(inPktInfo->ipi_addr); continue; } @@ -664,12 +665,13 @@ void UDPEndPointImplSockets::HandlePendingIO(System::SocketEvents events) if (controlHdr->cmsg_level == IPPROTO_IPV6 && controlHdr->cmsg_type == IPV6_PKTINFO) { auto * in6PktInfo = reinterpret_cast CMSG_DATA(controlHdr); - if (!CanCastTo(in6PktInfo->ipi6_ifindex)) + if (!CanCastTo(in6PktInfo->ipi6_ifindex)) { lStatus = CHIP_ERROR_INCORRECT_STATE; break; } - lPacketInfo.Interface = InterfaceId(static_cast(in6PktInfo->ipi6_ifindex)); + lPacketInfo.Interface = PlatformNetworkInterface::ToInterfaceId( + static_cast(in6PktInfo->ipi6_ifindex)); lPacketInfo.DestAddress = IPAddress(in6PktInfo->ipi6_addr); continue; } @@ -797,7 +799,7 @@ CHIP_ERROR UDPEndPointImplSockets::IPv6JoinLeaveMulticastGroupImpl(InterfaceId a #endif // CHIP_SYSTEM_CONFIG_USE_PLATFORM_MULTICAST_API #ifdef IPV6_MULTICAST_IMPLEMENTED - const InterfaceId::PlatformType lIfIndex = aInterfaceId.GetPlatformInterface(); + const PlatformNetworkInterface::Type lIfIndex = PlatformNetworkInterface::FromInterfaceId(aInterfaceId); struct ipv6_mreq lMulticastRequest; memset(&lMulticastRequest, 0, sizeof(lMulticastRequest)); diff --git a/src/inet/inet.gni b/src/inet/inet.gni index 997ae034c8eaa4..88cebe6091b5ab 100644 --- a/src/inet/inet.gni +++ b/src/inet/inet.gni @@ -29,7 +29,14 @@ declare_args() { # Inet implementation type. if (chip_system_config_use_lwip) { chip_system_config_inet = "LwIP" + chip_system_config_inet_interface = "LwIP" + assert(chip_system_config_event_loop == "LwIP", "Unsupported combination") } else { chip_system_config_inet = "Sockets" + if (current_os == "zephyr") { + chip_system_config_inet_interface = "Zephyr" + } else { + chip_system_config_inet_interface = "IFAddrs" + } } } diff --git a/src/inet/tests/TestInetCommonPosix.cpp b/src/inet/tests/TestInetCommonPosix.cpp index 86120482e8e55d..8f2dba3a797481 100644 --- a/src/inet/tests/TestInetCommonPosix.cpp +++ b/src/inet/tests/TestInetCommonPosix.cpp @@ -175,7 +175,7 @@ void ShutdownSystemLayer() #if CHIP_SYSTEM_CONFIG_USE_LWIP static void PrintNetworkState() { - char intfName[chip::Inet::InterfaceId::kMaxIfNameLength]; + char intfName[chip::Inet::PlatformNetworkInterface::kMaxNameLength]; for (size_t j = 0; j < gNetworkOptions.TapDeviceName.size(); j++) { @@ -188,7 +188,7 @@ static void PrintNetworkState() TapInterface * tapIF = &(sTapIFs[j]); #endif // CHIP_TARGET_STYLE_UNIX - InterfaceId(netIF).GetInterfaceName(intfName, sizeof(intfName)); + chip::Inet::PlatformNetworkInterface::GetInterfaceName(netIF, intfName, sizeof(intfName)); printf("LwIP interface ready\n"); printf(" Interface Name: %s\n", intfName); diff --git a/src/inet/tests/TestInetEndPoint.cpp b/src/inet/tests/TestInetEndPoint.cpp index 1e4ef41b8997d3..739a015615368d 100644 --- a/src/inet/tests/TestInetEndPoint.cpp +++ b/src/inet/tests/TestInetEndPoint.cpp @@ -127,7 +127,7 @@ static void TestInetInterface(nlTestSuite * inSuite, void * inContext) { InterfaceIterator intIterator; InterfaceAddressIterator addrIterator; - char intName[chip::Inet::InterfaceId::kMaxIfNameLength]; + char intName[chip::Inet::PlatformNetworkInterface::kMaxNameLength]; InterfaceId intId; IPAddress addr; InterfaceType intType; @@ -140,20 +140,20 @@ static void TestInetInterface(nlTestSuite * inSuite, void * inContext) #ifndef __MBED__ // Mbed interface name has different format - err = InterfaceId::InterfaceNameToId("0", intId); + err = PlatformNetworkInterface::InterfaceNameToId("0", intId); NL_TEST_ASSERT(inSuite, err != CHIP_NO_ERROR); #endif - err = InterfaceId::Null().GetInterfaceName(intName, 0); + err = PlatformNetworkInterface::GetInterfaceName(InterfaceId::Null(), intName, 0); NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL); - err = InterfaceId::Null().GetInterfaceName(intName, sizeof(intName)); + err = PlatformNetworkInterface::GetInterfaceName(InterfaceId::Null(), intName, sizeof(intName)); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR && intName[0] == '\0'); intId = InterfaceId::FromIPAddress(addr); NL_TEST_ASSERT(inSuite, !intId.IsPresent()); - err = intId.GetLinkLocalAddr(nullptr); + err = PlatformNetworkInterface::GetLinkLocalAddr(intId, nullptr); NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INVALID_ARGUMENT); printf(" Interfaces:\n"); @@ -165,15 +165,10 @@ static void TestInetInterface(nlTestSuite * inSuite, void * inContext) err = intIterator.GetInterfaceName(intName, sizeof(intName)); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); printf(" interface id: 0x%" PRIxPTR ", interface name: %s, interface state: %s, %s multicast, %s broadcast addr\n", -#if CHIP_SYSTEM_CONFIG_USE_LWIP - reinterpret_cast(intId.GetPlatformInterface()), -#else - static_cast(intId.GetPlatformInterface()), -#endif - intName, intIterator.IsUp() ? "UP" : "DOWN", intIterator.SupportsMulticast() ? "supports" : "no", - intIterator.HasBroadcastAddress() ? "has" : "no"); + intId.GetInternalId(), intName, intIterator.IsUp() ? "UP" : "DOWN", + intIterator.SupportsMulticast() ? "supports" : "no", intIterator.HasBroadcastAddress() ? "has" : "no"); - intId.GetLinkLocalAddr(&addr); + PlatformNetworkInterface::GetLinkLocalAddr(intId, &addr); InterfaceId::MatchLocalIPv6Subnet(addr); // Not all platforms support getting interface type and hardware address @@ -221,14 +216,8 @@ static void TestInetInterface(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, intName[0] != '\0' && memchr(intName, '\0', sizeof(intName)) != nullptr); printf(" %s/%d, interface id: 0x%" PRIxPTR ", interface name: %s, interface state: %s, %s multicast, %s broadcast addr\n", - addrStr, addrWithPrefix.Length, -#if CHIP_SYSTEM_CONFIG_USE_LWIP - reinterpret_cast(intId.GetPlatformInterface()), -#else - static_cast(intId.GetPlatformInterface()), -#endif - intName, addrIterator.IsUp() ? "UP" : "DOWN", addrIterator.SupportsMulticast() ? "supports" : "no", - addrIterator.HasBroadcastAddress() ? "has" : "no"); + addrStr, addrWithPrefix.Length, intId.GetInternalId(), intName, addrIterator.IsUp() ? "UP" : "DOWN", + addrIterator.SupportsMulticast() ? "supports" : "no", addrIterator.HasBroadcastAddress() ? "has" : "no"); } NL_TEST_ASSERT(inSuite, !addrIterator.Next()); NL_TEST_ASSERT(inSuite, addrIterator.GetAddress(addr) == CHIP_ERROR_SENTINEL); @@ -264,7 +253,7 @@ static void TestInetEndPointInternal(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, SYSTEM_STATS_TEST_IN_USE(System::Stats::kInetLayer_NumUDPEps, 1)); - err = InterfaceId::Null().GetLinkLocalAddr(&addr); + err = PlatformNetworkInterface::GetLinkLocalAddr(InterfaceId::Null(), &addr); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); intId = InterfaceId::FromIPAddress(addr); NL_TEST_ASSERT(inSuite, intId.IsPresent()); diff --git a/src/inet/tests/TestInetLayer.cpp b/src/inet/tests/TestInetLayer.cpp index 82f3f35091d0fd..ecb3be27617f9d 100644 --- a/src/inet/tests/TestInetLayer.cpp +++ b/src/inet/tests/TestInetLayer.cpp @@ -277,7 +277,7 @@ int main(int argc, char * argv[]) if (gInterfaceName != nullptr) { - lStatus = InterfaceId::InterfaceNameToId(gInterfaceName, gInterfaceId); + lStatus = PlatformNetworkInterface::InterfaceNameToId(gInterfaceName, gInterfaceId); if (lStatus != CHIP_NO_ERROR) { PrintArgError("%s: unknown network interface %s\n", kToolName, gInterfaceName); diff --git a/src/lib/dnssd/AllInterfacesListenIterator.h b/src/lib/dnssd/AllInterfacesListenIterator.h index 7366a3ca037605..333f68e9410a2a 100644 --- a/src/lib/dnssd/AllInterfacesListenIterator.h +++ b/src/lib/dnssd/AllInterfacesListenIterator.h @@ -33,7 +33,7 @@ bool IsCurrentInterfaceUsable(T & iterator) { return false; // not a usable interface } - char name[chip::Inet::InterfaceId::kMaxIfNameLength]; + char name[chip::Inet::PlatformNetworkInterface::kMaxNameLength]; if (iterator.GetInterfaceName(name, sizeof(name)) != CHIP_NO_ERROR) { ChipLogError(Discovery, "Failed to get interface name."); diff --git a/src/lib/dnssd/MinimalMdnsServer.h b/src/lib/dnssd/MinimalMdnsServer.h index e956fa017d9cf7..14771bfb44868c 100644 --- a/src/lib/dnssd/MinimalMdnsServer.h +++ b/src/lib/dnssd/MinimalMdnsServer.h @@ -32,7 +32,7 @@ bool IsCurrentInterfaceUsable(T & iterator) { return false; // not a usable interface } - char name[chip::Inet::InterfaceId::kMaxIfNameLength]; + char name[chip::Inet::PlatformNetworkInterface::kMaxNameLength]; if (iterator.GetInterfaceName(name, sizeof(name)) != CHIP_NO_ERROR) { ChipLogError(Discovery, "Failed to get interface name."); diff --git a/src/lib/dnssd/minimal_mdns/Server.cpp b/src/lib/dnssd/minimal_mdns/Server.cpp index 816feac1e71e77..760ab9b17a36a0 100644 --- a/src/lib/dnssd/minimal_mdns/Server.cpp +++ b/src/lib/dnssd/minimal_mdns/Server.cpp @@ -236,8 +236,8 @@ CHIP_ERROR ServerBase::Listen(chip::Inet::EndPointManagerName, ifa->name, Inet::InterfaceId::kMaxIfNameLength); - ifp->Name[Inet::InterfaceId::kMaxIfNameLength - 1] = '\0'; + strncpy(ifp->Name, ifa->name, Inet::PlatformNetworkInterface::kMaxNameLength); + ifp->Name[Inet::PlatformNetworkInterface::kMaxNameLength - 1] = '\0'; ifp->name = CharSpan(ifp->Name, strlen(ifp->Name)); ifp->fabricConnected = true; diff --git a/src/platform/Darwin/DnssdImpl.cpp b/src/platform/Darwin/DnssdImpl.cpp index 931631307b3cd0..4929bca525b3d9 100644 --- a/src/platform/Darwin/DnssdImpl.cpp +++ b/src/platform/Darwin/DnssdImpl.cpp @@ -45,7 +45,8 @@ bool IsSupportedProtocol(DnssdServiceProtocol protocol) uint32_t GetInterfaceId(chip::Inet::InterfaceId interfaceId) { - return interfaceId.IsPresent() ? interfaceId.GetPlatformInterface() : kDNSServiceInterfaceIndexAny; + return interfaceId.IsPresent() ? chip::Inet::PlatformNetworkInterface::FromInterfaceId(interfaceId) + : kDNSServiceInterfaceIndexAny; } std::string GetFullType(const char * type, DnssdServiceProtocol protocol) @@ -311,7 +312,7 @@ void OnBrowseAdd(BrowseContext * context, const char * name, const char * type, chip::Inet::InterfaceId interfaceId) { ChipLogDetail(DeviceLayer, "Mdns: %s name: %s, type: %s, domain: %s, interface: %d", __func__, name, type, domain, - interfaceId.GetPlatformInterface()); + chip::Inet::PlatformNetworkInterface::FromInterfaceId(interfaceId)); VerifyOrReturn(strcmp(kLocalDot, domain) == 0); @@ -339,7 +340,7 @@ void OnBrowseRemove(BrowseContext * context, const char * name, const char * typ chip::Inet::InterfaceId interfaceId) { ChipLogDetail(DeviceLayer, "Mdns: %s name: %s, type: %s, domain: %s, interface: %d", __func__, name, type, domain, - interfaceId.GetPlatformInterface()); + chip::Inet::PlatformNetworkInterface::FromInterfaceId(interfaceId)); VerifyOrReturn(strcmp(kLocalDot, domain) == 0); @@ -355,8 +356,9 @@ static void OnBrowse(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interf BrowseContext * sdCtx = reinterpret_cast(context); VerifyOrReturn(CheckForSuccess(sdCtx, __func__, err, true)); - (flags & kDNSServiceFlagsAdd) ? OnBrowseAdd(sdCtx, name, type, domain, Inet::InterfaceId(interfaceId)) - : OnBrowseRemove(sdCtx, name, type, domain, Inet::InterfaceId(interfaceId)); + (flags & kDNSServiceFlagsAdd) + ? OnBrowseAdd(sdCtx, name, type, domain, Inet::PlatformNetworkInterface::ToInterfaceId(interfaceId)) + : OnBrowseRemove(sdCtx, name, type, domain, Inet::PlatformNetworkInterface::ToInterfaceId(interfaceId)); if (!(flags & kDNSServiceFlagsMoreComing)) { @@ -407,7 +409,7 @@ static void OnGetAddrInfo(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t i service.mAddress.SetValue(ip); Platform::CopyString(service.mName, sdCtx->name); Platform::CopyString(service.mHostName, hostname); - service.mInterface = Inet::InterfaceId(sdCtx->interfaceId); + service.mInterface = Inet::PlatformNetworkInterface::ToInterfaceId(sdCtx->interfaceId); sdCtx->callback(sdCtx->context, &service, status); MdnsContexts::GetInstance().Remove(sdCtx); diff --git a/src/platform/ESP32/DiagnosticDataProviderImpl.cpp b/src/platform/ESP32/DiagnosticDataProviderImpl.cpp index eb99c5597e8e8d..c5d7da90cea3ff 100644 --- a/src/platform/ESP32/DiagnosticDataProviderImpl.cpp +++ b/src/platform/ESP32/DiagnosticDataProviderImpl.cpp @@ -207,13 +207,13 @@ CHIP_ERROR DiagnosticDataProviderImpl::GetNetworkInterfaces(NetworkInterface ** for (esp_netif_t * ifa = netif; ifa != NULL; ifa = esp_netif_next(ifa)) { NetworkInterface * ifp = new NetworkInterface(); - strncpy(ifp->Name, esp_netif_get_ifkey(ifa), Inet::InterfaceId::kMaxIfNameLength); - ifp->Name[Inet::InterfaceId::kMaxIfNameLength - 1] = '\0'; - ifp->name = CharSpan(ifp->Name, strlen(ifp->Name)); - ifp->fabricConnected = true; - ifp->type = GetInterfaceType(esp_netif_get_desc(ifa)); - ifp->offPremiseServicesReachableIPv4 = false; - ifp->offPremiseServicesReachableIPv6 = false; + strncpy(ifp->Name, esp_netif_get_ifkey(ifa), Inet::PlatformNetworkInterface::kMaxNameLength); + ifp->Name[Inet::PlatformNetworkInterface::kMaxNameLength - 1] = '\0'; + ifp->name = CharSpan(ifp->Name, strlen(ifp->Name)); + ifp->fabricConnected = true; + ifp->type = GetInterfaceType(esp_netif_get_desc(ifa)); + ifp->offPremiseServicesReachableIPv4 = false; + ifp->offPremiseServicesReachableIPv6 = false; if (esp_netif_get_mac(ifa, ifp->MacAddress) != ESP_OK) { ChipLogError(DeviceLayer, "Failed to get network hardware address"); diff --git a/src/platform/Linux/ConnectivityManagerImpl.cpp b/src/platform/Linux/ConnectivityManagerImpl.cpp index 1496f04dad35e1..9d89ef7e0bd206 100644 --- a/src/platform/Linux/ConnectivityManagerImpl.cpp +++ b/src/platform/Linux/ConnectivityManagerImpl.cpp @@ -1123,7 +1123,7 @@ void ConnectivityManagerImpl::PostNetworkConnect() // This should be removed or find a better place once we depercate the rendezvous session. for (chip::Inet::InterfaceAddressIterator it; it.HasCurrent(); it.Next()) { - char ifName[chip::Inet::InterfaceId::kMaxIfNameLength]; + char ifName[chip::Inet::PlatformNetworkInterface::kMaxNameLength]; if (it.IsUp() && CHIP_NO_ERROR == it.GetInterfaceName(ifName, sizeof(ifName)) && strncmp(ifName, sWiFiIfName, sizeof(ifName)) == 0) { diff --git a/src/platform/Linux/DiagnosticDataProviderImpl.cpp b/src/platform/Linux/DiagnosticDataProviderImpl.cpp index 53f05524a4d354..28d57831672f1e 100644 --- a/src/platform/Linux/DiagnosticDataProviderImpl.cpp +++ b/src/platform/Linux/DiagnosticDataProviderImpl.cpp @@ -429,8 +429,8 @@ CHIP_ERROR DiagnosticDataProviderImpl::GetNetworkInterfaces(NetworkInterface ** { NetworkInterface * ifp = new NetworkInterface(); - strncpy(ifp->Name, ifa->ifa_name, Inet::InterfaceId::kMaxIfNameLength); - ifp->Name[Inet::InterfaceId::kMaxIfNameLength - 1] = '\0'; + strncpy(ifp->Name, ifa->ifa_name, Inet::PlatformNetworkInterface::kMaxNameLength); + ifp->Name[Inet::PlatformNetworkInterface::kMaxNameLength - 1] = '\0'; ifp->name = CharSpan(ifp->Name, strlen(ifp->Name)); ifp->fabricConnected = ifa->ifa_flags & IFF_RUNNING; diff --git a/src/platform/Linux/DnssdImpl.cpp b/src/platform/Linux/DnssdImpl.cpp index 7709a8eee6a0c1..f975f2429f0a60 100644 --- a/src/platform/Linux/DnssdImpl.cpp +++ b/src/platform/Linux/DnssdImpl.cpp @@ -460,8 +460,9 @@ CHIP_ERROR MdnsAvahi::PublishService(const DnssdService & service) std::string type = GetFullType(service.mType, service.mProtocol); CHIP_ERROR error = CHIP_NO_ERROR; AvahiStringList * text = nullptr; - AvahiIfIndex interface = - service.mInterface.IsPresent() ? static_cast(service.mInterface.GetPlatformInterface()) : AVAHI_IF_UNSPEC; + AvahiIfIndex interface = service.mInterface.IsPresent() + ? static_cast(Inet::PlatformNetworkInterface::FromInterfaceId(service.mInterface)) + : AVAHI_IF_UNSPEC; keyBuilder << service.mName << "." << type << service.mPort << "." << interface; key = keyBuilder.str(); @@ -530,7 +531,7 @@ CHIP_ERROR MdnsAvahi::Browse(const char * type, DnssdServiceProtocol protocol, c { AvahiServiceBrowser * browser; BrowseContext * browseContext = chip::Platform::New(); - AvahiIfIndex avahiInterface = static_cast(interface.GetPlatformInterface()); + AvahiIfIndex avahiInterface = static_cast(Inet::PlatformNetworkInterface::FromInterfaceId(interface)); browseContext->mInstance = this; browseContext->mContext = context; @@ -620,7 +621,7 @@ void MdnsAvahi::HandleBrowse(AvahiServiceBrowser * browser, AvahiIfIndex interfa service.mInterface = Inet::InterfaceId::Null(); if (interface != AVAHI_IF_UNSPEC) { - service.mInterface = static_cast(interface); + service.mInterface = Inet::PlatformNetworkInterface::ToInterfaceId(interface); } service.mType[kDnssdTypeMaxSize] = 0; context->mServices.push_back(service); @@ -652,7 +653,7 @@ CHIP_ERROR MdnsAvahi::Resolve(const char * name, const char * type, DnssdService void * context) { AvahiServiceResolver * resolver; - AvahiIfIndex avahiInterface = static_cast(interface.GetPlatformInterface()); + AvahiIfIndex avahiInterface = static_cast(Inet::PlatformNetworkInterface::FromInterfaceId(interface)); ResolveContext * resolveContext = chip::Platform::New(); CHIP_ERROR error = CHIP_NO_ERROR; @@ -730,7 +731,7 @@ void MdnsAvahi::HandleResolve(AvahiServiceResolver * resolver, AvahiIfIndex inte result.mTtlSeconds = AVAHI_DEFAULT_TTL_HOST_NAME; if (interface != AVAHI_IF_UNSPEC) { - result.mInterface = static_cast(interface); + result.mInterface = Inet::PlatformNetworkInterface::ToInterfaceId(interface); } Platform::CopyString(result.mHostName, host_name); // Returned value is full QName, want only host part. diff --git a/src/platform/Tizen/DnssdImpl.cpp b/src/platform/Tizen/DnssdImpl.cpp index 7eaaeb409e6f30..32ff488afc4c8d 100644 --- a/src/platform/Tizen/DnssdImpl.cpp +++ b/src/platform/Tizen/DnssdImpl.cpp @@ -217,7 +217,7 @@ void OnBrowseAdd(BrowseContext * context, dnssd_service_h service, const char * char * tokens = strdup(type); char * regtype = strtok(tokens, "."); - chip::Inet::InterfaceId platformInterface(interfaceId); + chip::Inet::InterfaceId platformInterface(chip::Inet::PlatformNetworkInterface::ToInterfaceId(interfaceId)); DnssdService mdnsService = {}; g_strlcpy(mdnsService.mType, regtype, sizeof(mdnsService.mType)); @@ -238,7 +238,7 @@ void OnBrowseRemove(BrowseContext * context, dnssd_service_h service, const char auto it = std::remove_if( context->services.begin(), context->services.end(), [name, type, interfaceId](const DnssdService & mdnsService) { return strcmp(name, mdnsService.mName) == 0 && type == GetFullType(mdnsService.mType, mdnsService.mProtocol) && - interfaceId == mdnsService.mInterface.GetPlatformInterface(); + interfaceId == chip::Inet::PlatformNetworkInterface::FromInterfaceId(mdnsService.mInterface); }); context->services.erase(it); @@ -731,8 +731,9 @@ CHIP_ERROR ChipDnssdPublishService(const DnssdService * service) std::string regtype = GetFullType(service->mType, service->mProtocol); - return RegisterService(regtype.c_str(), service->mName, service->mPort, service->mInterface.GetPlatformInterface(), - service->mTextEntries, service->mTextEntrySize); + return RegisterService(regtype.c_str(), service->mName, service->mPort, + chip::Inet::PlatformNetworkInterface::FromInterfaceId(service->mInterface), service->mTextEntries, + service->mTextEntrySize); } CHIP_ERROR ChipDnssdRemoveServices() @@ -754,7 +755,7 @@ CHIP_ERROR ChipDnssdBrowse(const char * type, DnssdServiceProtocol protocol, chi std::string regtype = GetFullType(type, protocol); - return Browse(interfaceId.GetPlatformInterface(), regtype.c_str(), protocol, callback, context); + return Browse(chip::Inet::PlatformNetworkInterface::FromInterfaceId(interfaceId), regtype.c_str(), protocol, callback, context); } CHIP_ERROR ChipDnssdResolve(DnssdService * service, chip::Inet::InterfaceId interfaceId, DnssdResolveCallback callback, @@ -765,7 +766,8 @@ CHIP_ERROR ChipDnssdResolve(DnssdService * service, chip::Inet::InterfaceId inte std::string regtype = GetFullType(service->mType, service->mProtocol); - return Resolve(interfaceId.GetPlatformInterface(), regtype.c_str(), service->mName, callback, context); + return Resolve(chip::Inet::PlatformNetworkInterface::FromInterfaceId(interfaceId), regtype.c_str(), service->mName, callback, + context); } void GetDnssdTimeout(timeval & timeout) diff --git a/src/platform/Zephyr/DiagnosticDataProviderImpl.cpp b/src/platform/Zephyr/DiagnosticDataProviderImpl.cpp index 44fad86762e98e..1235e2102fe677 100644 --- a/src/platform/Zephyr/DiagnosticDataProviderImpl.cpp +++ b/src/platform/Zephyr/DiagnosticDataProviderImpl.cpp @@ -169,7 +169,7 @@ CHIP_ERROR DiagnosticDataProviderImpl::GetNetworkInterfaces(NetworkInterface ** { NetworkInterface * ifp = new NetworkInterface(); - interfaceIterator.GetInterfaceName(ifp->Name, Inet::InterfaceId::kMaxIfNameLength); + interfaceIterator.GetInterfaceName(ifp->Name, Inet::PlatformNetworkInterface::kMaxNameLength); ifp->name = CharSpan(ifp->Name, strlen(ifp->Name)); ifp->fabricConnected = true; Inet::InterfaceType interfaceType; diff --git a/src/transport/raw/PeerAddress.h b/src/transport/raw/PeerAddress.h index 69318d027da747..51a78a52a675f1 100644 --- a/src/transport/raw/PeerAddress.h +++ b/src/transport/raw/PeerAddress.h @@ -113,15 +113,15 @@ class PeerAddress /// Maximum size of the string outputes by ToString. Format is of the form: /// "UDP::" - static constexpr size_t kMaxToStringSize = 3 // type: UDP/TCP/BLE - + 1 // splitter : - + 2 // brackets around address - + Inet::IPAddress::kMaxStringLength // address - + 1 // splitter % - + Inet::InterfaceId::kMaxIfNameLength // interface - + 1 // splitter : - + 5 // port: 16 bit interger - + 1; // NullTerminator + static constexpr size_t kMaxToStringSize = 3 // type: UDP/TCP/BLE + + 1 // splitter : + + 2 // brackets around address + + Inet::IPAddress::kMaxStringLength // address + + 1 // splitter % + + Inet::PlatformNetworkInterface::kMaxNameLength // interface + + 1 // splitter : + + 5 // port: 16 bit interger + + 1; // NullTerminator template inline void ToString(char (&buf)[N]) const @@ -133,12 +133,12 @@ class PeerAddress { char ip_addr[Inet::IPAddress::kMaxStringLength]; - char interface[Inet::InterfaceId::kMaxIfNameLength + 1] = {}; // +1 to prepend '%' + char interface[Inet::PlatformNetworkInterface::kMaxNameLength + 1] = {}; // +1 to prepend '%' if (mInterface.IsPresent()) { interface[0] = '%'; interface[1] = 0; - CHIP_ERROR err = mInterface.GetInterfaceName(interface + 1, sizeof(interface) - 1); + CHIP_ERROR err = Inet::PlatformNetworkInterface::GetInterfaceName(mInterface, interface + 1, sizeof(interface) - 1); if (err != CHIP_NO_ERROR) { Platform::CopyString(interface, sizeof(interface), "%(err)");