Matter SDK Coverage Report
Current view: top level - inet - InetInterface.cpp (source / functions) Coverage Total Hit
Test: SHA:09f6fdf93a7e847a42518c076e487f336877a722 Lines: 83.0 % 194 161
Test Date: 2025-06-07 07:10:33 Functions: 90.9 % 33 30

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2020-2022 Project CHIP Authors
       4              :  *    Copyright (c) 2019 Google LLC.
       5              :  *    Copyright (c) 2013-2017 Nest Labs, Inc.
       6              :  *
       7              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       8              :  *    you may not use this file except in compliance with the License.
       9              :  *    You may obtain a copy of the License at
      10              :  *
      11              :  *        http://www.apache.org/licenses/LICENSE-2.0
      12              :  *
      13              :  *    Unless required by applicable law or agreed to in writing, software
      14              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      15              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      16              :  *    See the License for the specific language governing permissions and
      17              :  *    limitations under the License.
      18              :  */
      19              : 
      20              : /**
      21              :  *    @file
      22              :  *      Implementation of network interface abstraction layer.
      23              :  *
      24              :  */
      25              : 
      26              : #include <inet/InetInterface.h>
      27              : 
      28              : #include <inet/IPPrefix.h>
      29              : #include <lib/support/CHIPMem.h>
      30              : #include <lib/support/CHIPMemString.h>
      31              : #include <lib/support/CodeUtils.h>
      32              : #include <lib/support/DLLUtil.h>
      33              : #include <lib/support/SafeInt.h>
      34              : 
      35              : #if CHIP_SYSTEM_CONFIG_USE_LWIP && !CHIP_SYSTEM_CONFIG_USE_OPENTHREAD_ENDPOINT
      36              : #include <lwip/netif.h>
      37              : #include <lwip/sys.h>
      38              : #include <lwip/tcpip.h>
      39              : #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
      40              : 
      41              : #if (CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS
      42              : #include <errno.h>
      43              : #include <fcntl.h>
      44              : #include <sys/socket.h>
      45              : #include <unistd.h>
      46              : #ifdef HAVE_SYS_SOCKIO_H
      47              : #include <sys/sockio.h>
      48              : #endif /* HAVE_SYS_SOCKIO_H */
      49              : #include "InetInterfaceImpl.h"
      50              : #include <ifaddrs.h>
      51              : #include <net/if.h>
      52              : #include <sys/ioctl.h>
      53              : #endif // (CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS
      54              : 
      55              : #if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF
      56              : #include <zephyr/net/net_if.h>
      57              : #endif // CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF
      58              : 
      59              : #if CHIP_SYSTEM_CONFIG_USE_OPENTHREAD_ENDPOINT
      60              : #include <inet/UDPEndPointImplOpenThread.h>
      61              : #endif
      62              : 
      63              : #include <stdio.h>
      64              : #include <string.h>
      65              : 
      66              : namespace chip {
      67              : namespace Inet {
      68              : 
      69              : #if CHIP_SYSTEM_CONFIG_USE_OPENTHREAD_ENDPOINT
      70              : CHIP_ERROR InterfaceId::GetInterfaceName(char * nameBuf, size_t nameBufSize) const
      71              : {
      72              :     if (mPlatformInterface && nameBufSize >= kMaxIfNameLength)
      73              :     {
      74              :         nameBuf[0] = 'o';
      75              :         nameBuf[1] = 't';
      76              :         nameBuf[2] = 0;
      77              :     }
      78              :     else
      79              :     {
      80              :         nameBuf[0] = 0;
      81              :     }
      82              : 
      83              :     return CHIP_NO_ERROR;
      84              : }
      85              : CHIP_ERROR InterfaceId::InterfaceNameToId(const char * intfName, InterfaceId & interface)
      86              : {
      87              :     if (strlen(intfName) < 3)
      88              :     {
      89              :         return INET_ERROR_UNKNOWN_INTERFACE;
      90              :     }
      91              :     char * parseEnd       = nullptr;
      92              :     unsigned long intfNum = strtoul(intfName + 2, &parseEnd, 10);
      93              :     if (*parseEnd != 0 || intfNum > UINT8_MAX)
      94              :     {
      95              :         return INET_ERROR_UNKNOWN_INTERFACE;
      96              :     }
      97              : 
      98              :     interface = InterfaceId(intfNum);
      99              :     if (intfNum == 0)
     100              :     {
     101              :         return INET_ERROR_UNKNOWN_INTERFACE;
     102              :     }
     103              :     return CHIP_NO_ERROR;
     104              : }
     105              : 
     106              : bool InterfaceIterator::Next()
     107              : {
     108              :     // TODO : Cleanup #17346
     109              :     mHasCurrent = false;
     110              :     return false;
     111              : }
     112              : 
     113              : CHIP_ERROR InterfaceIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize)
     114              : {
     115              :     VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE);
     116              :     return InterfaceId(1).GetInterfaceName(nameBuf, nameBufSize);
     117              : }
     118              : 
     119              : InterfaceId InterfaceIterator::GetInterfaceId()
     120              : {
     121              :     // only 1 interface is supported
     122              :     return HasCurrent() ? InterfaceId(1) : InterfaceId::Null();
     123              : }
     124              : 
     125              : bool InterfaceIterator::IsUp()
     126              : {
     127              :     return HasCurrent() && (otThreadGetDeviceRole(Inet::globalOtInstance) != OT_DEVICE_ROLE_DISABLED);
     128              : }
     129              : 
     130              : InterfaceAddressIterator::InterfaceAddressIterator()
     131              : {
     132              :     mNetifAddrList = nullptr;
     133              :     mCurAddr       = nullptr;
     134              : }
     135              : 
     136              : bool InterfaceAddressIterator::HasCurrent()
     137              : {
     138              :     return (mNetifAddrList != nullptr) ? (mCurAddr != nullptr) : Next();
     139              : }
     140              : 
     141              : bool InterfaceAddressIterator::Next()
     142              : {
     143              :     if (mNetifAddrList == nullptr)
     144              :     {
     145              :         if (Inet::globalOtInstance == nullptr)
     146              :             return false;
     147              :         mNetifAddrList = otIp6GetUnicastAddresses(Inet::globalOtInstance);
     148              :         mCurAddr       = mNetifAddrList;
     149              :     }
     150              :     else if (mCurAddr != nullptr)
     151              :     {
     152              :         mCurAddr = mCurAddr->mNext;
     153              :     }
     154              : 
     155              :     return (mCurAddr != nullptr);
     156              : }
     157              : CHIP_ERROR InterfaceAddressIterator::GetAddress(IPAddress & outIPAddress)
     158              : {
     159              :     if (!HasCurrent())
     160              :     {
     161              :         return CHIP_ERROR_SENTINEL;
     162              :     }
     163              : 
     164              :     outIPAddress = IPAddress(mCurAddr->mAddress);
     165              :     return CHIP_NO_ERROR;
     166              : }
     167              : 
     168              : uint8_t InterfaceAddressIterator::GetPrefixLength()
     169              : {
     170              :     // Only 64 bits prefix are supported
     171              :     return 64;
     172              : }
     173              : 
     174              : bool InterfaceAddressIterator::IsUp()
     175              : {
     176              :     return HasCurrent() && (otThreadGetDeviceRole(Inet::globalOtInstance) != OT_DEVICE_ROLE_DISABLED);
     177              : }
     178              : 
     179              : InterfaceId InterfaceAddressIterator::GetInterfaceId()
     180              : {
     181              :     // only 1 interface is supported
     182              :     return HasCurrent() ? InterfaceId(1) : InterfaceId::Null();
     183              : }
     184              : 
     185              : bool InterfaceAddressIterator::HasBroadcastAddress()
     186              : {
     187              :     return HasCurrent() && (otIp6GetMulticastAddresses(Inet::globalOtInstance) != nullptr);
     188              : }
     189              : 
     190              : CHIP_ERROR InterfaceIterator::GetInterfaceType(InterfaceType & type)
     191              : {
     192              :     type = InterfaceType::Thread;
     193              : 
     194              :     return CHIP_NO_ERROR;
     195              : }
     196              : 
     197              : CHIP_ERROR InterfaceIterator::GetHardwareAddress(uint8_t * addressBuffer, uint8_t & addressSize, uint8_t addressBufferSize)
     198              : {
     199              :     VerifyOrReturnError(addressBuffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     200              :     VerifyOrReturnError(addressBufferSize >= sizeof(otExtAddress), CHIP_ERROR_BUFFER_TOO_SMALL);
     201              : 
     202              :     const otExtAddress * extendedAddr = otLinkGetExtendedAddress(Inet::globalOtInstance);
     203              :     memcpy(addressBuffer, extendedAddr, sizeof(otExtAddress));
     204              :     addressSize = sizeof(otExtAddress);
     205              : 
     206              :     return CHIP_NO_ERROR;
     207              : }
     208              : 
     209              : #endif
     210              : 
     211              : #if CHIP_SYSTEM_CONFIG_USE_LWIP && !CHIP_SYSTEM_CONFIG_USE_OPENTHREAD_ENDPOINT
     212              : 
     213              : CHIP_ERROR InterfaceId::GetInterfaceName(char * nameBuf, size_t nameBufSize) const
     214              : {
     215              :     if (mPlatformInterface)
     216              :     {
     217              :         int status = snprintf(nameBuf, nameBufSize, "%c%c%d", mPlatformInterface->name[0], mPlatformInterface->name[1],
     218              :                               mPlatformInterface->num);
     219              :         if (status >= static_cast<int>(nameBufSize))
     220              :             return CHIP_ERROR_BUFFER_TOO_SMALL;
     221              :         return CHIP_NO_ERROR;
     222              :     }
     223              :     if (nameBufSize < 1)
     224              :     {
     225              :         return CHIP_ERROR_BUFFER_TOO_SMALL;
     226              :     }
     227              :     nameBuf[0] = 0;
     228              :     return CHIP_NO_ERROR;
     229              : }
     230              : 
     231              : CHIP_ERROR InterfaceId::InterfaceNameToId(const char * intfName, InterfaceId & interface)
     232              : {
     233              :     if (strlen(intfName) < 3)
     234              :     {
     235              :         return INET_ERROR_UNKNOWN_INTERFACE;
     236              :     }
     237              :     char * parseEnd;
     238              :     unsigned long intfNum = strtoul(intfName + 2, &parseEnd, 10);
     239              :     if (*parseEnd != 0 || intfNum > UINT8_MAX)
     240              :     {
     241              :         return INET_ERROR_UNKNOWN_INTERFACE;
     242              :     }
     243              :     struct netif * intf;
     244              : #if defined(NETIF_FOREACH)
     245              :     NETIF_FOREACH(intf)
     246              : #else
     247              :     for (intf = netif_list; intf != NULL; intf = intf->next)
     248              : #endif
     249              :     {
     250              :         if (intf->name[0] == intfName[0] && intf->name[1] == intfName[1] && intf->num == (uint8_t) intfNum)
     251              :         {
     252              :             interface = InterfaceId(intf);
     253              :             return CHIP_NO_ERROR;
     254              :         }
     255              :     }
     256              :     interface = InterfaceId::Null();
     257              :     return INET_ERROR_UNKNOWN_INTERFACE;
     258              : }
     259              : 
     260              : bool InterfaceIterator::Next()
     261              : {
     262              :     // Lock LwIP stack
     263              :     LOCK_TCPIP_CORE();
     264              : 
     265              :     // Verify the previous netif is still on the list if netifs.  If so,
     266              :     // advance to the next nextif.
     267              :     struct netif * prevNetif = mCurNetif;
     268              : #if defined(NETIF_FOREACH)
     269              :     NETIF_FOREACH(mCurNetif)
     270              : #else
     271              :     for (mCurNetif = netif_list; mCurNetif != nullptr; mCurNetif = mCurNetif->next)
     272              : #endif
     273              :     {
     274              :         if (mCurNetif == prevNetif)
     275              :         {
     276              :             mCurNetif = mCurNetif->next;
     277              :             break;
     278              :         }
     279              :     }
     280              : 
     281              :     // Unlock LwIP stack
     282              :     UNLOCK_TCPIP_CORE();
     283              : 
     284              :     return mCurNetif != nullptr;
     285              : }
     286              : 
     287              : CHIP_ERROR InterfaceIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize)
     288              : {
     289              :     VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE);
     290              :     return InterfaceId(mCurNetif).GetInterfaceName(nameBuf, nameBufSize);
     291              : }
     292              : 
     293              : bool InterfaceIterator::IsUp()
     294              : {
     295              :     return HasCurrent() && netif_is_up(mCurNetif);
     296              : }
     297              : 
     298              : bool InterfaceIterator::SupportsMulticast()
     299              : {
     300              :     return HasCurrent() && (mCurNetif->flags & (NETIF_FLAG_IGMP | NETIF_FLAG_MLD6 | NETIF_FLAG_BROADCAST)) != 0;
     301              : }
     302              : 
     303              : bool InterfaceIterator::HasBroadcastAddress()
     304              : {
     305              :     return HasCurrent() && (mCurNetif->flags & NETIF_FLAG_BROADCAST) != 0;
     306              : }
     307              : 
     308              : CHIP_ERROR InterfaceIterator::GetInterfaceType(InterfaceType & type)
     309              : {
     310              :     return CHIP_ERROR_NOT_IMPLEMENTED;
     311              : }
     312              : 
     313              : CHIP_ERROR InterfaceIterator::GetHardwareAddress(uint8_t * addressBuffer, uint8_t & addressSize, uint8_t addressBufferSize)
     314              : {
     315              :     VerifyOrReturnError(addressBuffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     316              :     VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE);
     317              :     VerifyOrReturnError(addressBufferSize >= mCurNetif->hwaddr_len, CHIP_ERROR_BUFFER_TOO_SMALL);
     318              :     addressSize = mCurNetif->hwaddr_len;
     319              :     memcpy(addressBuffer, mCurNetif->hwaddr, addressSize);
     320              :     return CHIP_NO_ERROR;
     321              : }
     322              : 
     323              : bool InterfaceAddressIterator::HasCurrent()
     324              : {
     325              :     return mIntfIter.HasCurrent() && ((mCurAddrIndex != kBeforeStartIndex) || Next());
     326              : }
     327              : 
     328              : bool InterfaceAddressIterator::Next()
     329              : {
     330              :     mCurAddrIndex++;
     331              : 
     332              :     while (mIntfIter.HasCurrent())
     333              :     {
     334              :         struct netif * curIntf = mIntfIter.GetInterfaceId().GetPlatformInterface();
     335              : 
     336              :         while (mCurAddrIndex < LWIP_IPV6_NUM_ADDRESSES)
     337              :         {
     338              :             if (ip6_addr_isvalid(netif_ip6_addr_state(curIntf, mCurAddrIndex)))
     339              :             {
     340              :                 return true;
     341              :             }
     342              :             mCurAddrIndex++;
     343              :         }
     344              : 
     345              : #if INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4
     346              :         if (mCurAddrIndex == LWIP_IPV6_NUM_ADDRESSES)
     347              :         {
     348              :             if (!ip4_addr_isany(netif_ip4_addr(curIntf)))
     349              :             {
     350              :                 return true;
     351              :             }
     352              :         }
     353              : #endif // INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4
     354              : 
     355              :         mIntfIter.Next();
     356              :         mCurAddrIndex = 0;
     357              :     }
     358              : 
     359              :     return false;
     360              : }
     361              : 
     362              : CHIP_ERROR InterfaceAddressIterator::GetAddress(IPAddress & outIPAddress)
     363              : {
     364              :     if (!HasCurrent())
     365              :     {
     366              :         return CHIP_ERROR_SENTINEL;
     367              :     }
     368              : 
     369              :     struct netif * curIntf = mIntfIter.GetInterfaceId().GetPlatformInterface();
     370              : 
     371              :     if (mCurAddrIndex < LWIP_IPV6_NUM_ADDRESSES)
     372              :     {
     373              :         outIPAddress = IPAddress(*netif_ip6_addr(curIntf, mCurAddrIndex));
     374              :         return CHIP_NO_ERROR;
     375              :     }
     376              : #if INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4
     377              :     outIPAddress = IPAddress(*netif_ip4_addr(curIntf));
     378              :     return CHIP_NO_ERROR;
     379              : #else
     380              :     return CHIP_ERROR_INTERNAL;
     381              : #endif // INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4
     382              : }
     383              : 
     384              : uint8_t InterfaceAddressIterator::GetPrefixLength()
     385              : {
     386              :     if (HasCurrent())
     387              :     {
     388              :         if (mCurAddrIndex < LWIP_IPV6_NUM_ADDRESSES)
     389              :         {
     390              :             return 64;
     391              :         }
     392              : #if INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4
     393              :         struct netif * curIntf = mIntfIter.GetInterfaceId().GetPlatformInterface();
     394              :         return NetmaskToPrefixLength((const uint8_t *) netif_ip4_netmask(curIntf), 4);
     395              : #endif // INET_CONFIG_ENABLE_IPV4 && LWIP_IPV4
     396              :     }
     397              :     return 0;
     398              : }
     399              : 
     400              : InterfaceId InterfaceAddressIterator::GetInterfaceId()
     401              : {
     402              :     return HasCurrent() ? mIntfIter.GetInterfaceId() : InterfaceId::Null();
     403              : }
     404              : 
     405              : CHIP_ERROR InterfaceAddressIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize)
     406              : {
     407              :     VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE);
     408              :     return mIntfIter.GetInterfaceName(nameBuf, nameBufSize);
     409              : }
     410              : 
     411              : bool InterfaceAddressIterator::IsUp()
     412              : {
     413              :     return HasCurrent() && mIntfIter.IsUp();
     414              : }
     415              : 
     416              : bool InterfaceAddressIterator::SupportsMulticast()
     417              : {
     418              :     return HasCurrent() && mIntfIter.SupportsMulticast();
     419              : }
     420              : 
     421              : bool InterfaceAddressIterator::HasBroadcastAddress()
     422              : {
     423              :     return HasCurrent() && mIntfIter.HasBroadcastAddress();
     424              : }
     425              : 
     426              : CHIP_ERROR InterfaceId::GetLinkLocalAddr(IPAddress * llAddr) const
     427              : {
     428              :     VerifyOrReturnError(llAddr != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     429              : 
     430              : #if !LWIP_IPV6
     431              :     return CHIP_ERROR_NOT_IMPLEMENTED;
     432              : #endif //! LWIP_IPV6
     433              : 
     434              :     for (struct netif * intf = netif_list; intf != nullptr; intf = intf->next)
     435              :     {
     436              :         if ((mPlatformInterface != nullptr) && (mPlatformInterface != intf))
     437              :             continue;
     438              :         for (int j = 0; j < LWIP_IPV6_NUM_ADDRESSES; ++j)
     439              :         {
     440              :             if (ip6_addr_isvalid(netif_ip6_addr_state(intf, j)) && ip6_addr_islinklocal(netif_ip6_addr(intf, j)))
     441              :             {
     442              :                 (*llAddr) = IPAddress(*netif_ip6_addr(intf, j));
     443              :                 return CHIP_NO_ERROR;
     444              :             }
     445              :         }
     446              :         if (mPlatformInterface != nullptr)
     447              :         {
     448              :             return INET_ERROR_ADDRESS_NOT_FOUND;
     449              :         }
     450              :     }
     451              : 
     452              :     return CHIP_NO_ERROR;
     453              : }
     454              : 
     455              : #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
     456              : 
     457              : #if (CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS
     458              : 
     459            2 : CHIP_ERROR InterfaceId::GetInterfaceName(char * nameBuf, size_t nameBufSize) const
     460              : {
     461            2 :     if (mPlatformInterface)
     462              :     {
     463              :         char intfName[IF_NAMESIZE];
     464            0 :         if (if_indextoname(mPlatformInterface, intfName) == nullptr)
     465              :         {
     466            0 :             return CHIP_ERROR_POSIX(errno);
     467              :         }
     468            0 :         size_t nameLength = strlen(intfName);
     469            0 :         if (nameLength >= nameBufSize)
     470              :         {
     471            0 :             return CHIP_ERROR_BUFFER_TOO_SMALL;
     472              :         }
     473            0 :         Platform::CopyString(nameBuf, nameBufSize, intfName);
     474            0 :         return CHIP_NO_ERROR;
     475              :     }
     476            2 :     if (nameBufSize < 1)
     477              :     {
     478            1 :         return CHIP_ERROR_BUFFER_TOO_SMALL;
     479              :     }
     480            1 :     nameBuf[0] = 0;
     481            1 :     return CHIP_NO_ERROR;
     482              : }
     483              : 
     484            1 : CHIP_ERROR InterfaceId::InterfaceNameToId(const char * intfName, InterfaceId & interface)
     485              : {
     486              :     // First attempt to parse as a numeric ID:
     487              :     char * parseEnd;
     488            1 :     unsigned long intfNum = strtoul(intfName, &parseEnd, 10);
     489            1 :     if (*parseEnd == 0)
     490              :     {
     491            1 :         if (intfNum > 0 && intfNum < UINT8_MAX && CanCastTo<InterfaceId::PlatformType>(intfNum))
     492              :         {
     493            0 :             interface = InterfaceId(static_cast<InterfaceId::PlatformType>(intfNum));
     494            0 :             return CHIP_NO_ERROR;
     495              :         }
     496              : 
     497            1 :         return INET_ERROR_UNKNOWN_INTERFACE;
     498              :     }
     499              : 
     500              :     // Falling back to name -> ID lookup otherwise (e.g. wlan0)
     501            0 :     unsigned int intfId = if_nametoindex(intfName);
     502            0 :     interface           = InterfaceId(intfId);
     503            0 :     if (intfId == 0)
     504              :     {
     505            0 :         return (errno == ENXIO) ? INET_ERROR_UNKNOWN_INTERFACE : CHIP_ERROR_POSIX(errno);
     506              :     }
     507            0 :     return CHIP_NO_ERROR;
     508              : }
     509              : 
     510              : static int sIOCTLSocket = -1;
     511              : 
     512              : /**
     513              :  * @brief   Returns a global general purpose socket useful for invoking certain network IOCTLs.
     514              :  *
     515              :  * This function is thread-safe on all platforms.
     516              :  */
     517          134 : int GetIOCTLSocket()
     518              : {
     519          134 :     if (sIOCTLSocket == -1)
     520              :     {
     521              :         int s;
     522              : #ifdef SOCK_CLOEXEC
     523            4 :         s = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
     524            4 :         if (s < 0)
     525              : #endif
     526              :         {
     527            0 :             s = socket(AF_INET, SOCK_STREAM, 0);
     528            0 :             fcntl(s, F_SETFD, O_CLOEXEC);
     529              :         }
     530              : 
     531            4 :         if (!__sync_bool_compare_and_swap(&sIOCTLSocket, -1, s))
     532              :         {
     533            0 :             close(s);
     534              :         }
     535              :     }
     536          134 :     return sIOCTLSocket;
     537              : }
     538              : 
     539              : /**
     540              :  * @brief   Close the global socket created by \c GetIOCTLSocket.
     541              :  *
     542              :  * @details
     543              :  *   This function is provided for cases were leaving the global IOCTL socket
     544              :  *   open would register as a leak.
     545              :  *
     546              :  *   NB: This function is NOT thread-safe with respect to \c GetIOCTLSocket.
     547              :  */
     548            0 : void CloseIOCTLSocket()
     549              : {
     550            0 :     if (sIOCTLSocket != -1)
     551              :     {
     552            0 :         close(sIOCTLSocket);
     553            0 :         sIOCTLSocket = -1;
     554              :     }
     555            0 : }
     556              : 
     557           67 : InterfaceIterator::InterfaceIterator()
     558              : {
     559           67 :     mIntfArray       = nullptr;
     560           67 :     mCurIntf         = 0;
     561           67 :     mIntfFlags       = 0;
     562           67 :     mIntfFlagsCached = false;
     563           67 : }
     564              : 
     565           67 : InterfaceIterator::~InterfaceIterator()
     566              : {
     567           67 :     if (mIntfArray != nullptr)
     568              :     {
     569           67 :         if_freenameindexImpl(mIntfArray);
     570           67 :         mIntfArray = nullptr;
     571              :     }
     572           67 : }
     573              : 
     574          919 : bool InterfaceIterator::HasCurrent()
     575              : {
     576          919 :     return (mIntfArray != nullptr) ? mIntfArray[mCurIntf].if_index != 0 : Next();
     577              : }
     578              : 
     579          202 : bool InterfaceIterator::Next()
     580              : {
     581          202 :     if (mIntfArray == nullptr)
     582              :     {
     583           67 :         mIntfArray = if_nameindexImpl();
     584              :     }
     585          135 :     else if (mIntfArray[mCurIntf].if_index != 0)
     586              :     {
     587          134 :         mCurIntf++;
     588          134 :         mIntfFlags       = 0;
     589          134 :         mIntfFlagsCached = false;
     590              :     }
     591          202 :     return (mIntfArray != nullptr && mIntfArray[mCurIntf].if_index != 0);
     592              : }
     593              : 
     594          261 : InterfaceId InterfaceIterator::GetInterfaceId()
     595              : {
     596          261 :     return HasCurrent() ? InterfaceId(mIntfArray[mCurIntf].if_index) : InterfaceId::Null();
     597              : }
     598              : 
     599          135 : CHIP_ERROR InterfaceIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize)
     600              : {
     601          135 :     VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE);
     602          134 :     VerifyOrReturnError(strlen(mIntfArray[mCurIntf].if_name) < nameBufSize, CHIP_ERROR_BUFFER_TOO_SMALL);
     603          134 :     Platform::CopyString(nameBuf, nameBufSize, mIntfArray[mCurIntf].if_name);
     604          134 :     return CHIP_NO_ERROR;
     605              : }
     606              : 
     607          132 : bool InterfaceIterator::IsUp()
     608              : {
     609          132 :     return (GetFlags() & IFF_UP) != 0;
     610              : }
     611              : 
     612            0 : bool InterfaceIterator::IsLoopback()
     613              : {
     614            0 :     return (GetFlags() & IFF_LOOPBACK) != 0;
     615              : }
     616              : 
     617            7 : bool InterfaceIterator::SupportsMulticast()
     618              : {
     619            7 :     return (GetFlags() & IFF_MULTICAST) != 0;
     620              : }
     621              : 
     622            3 : bool InterfaceIterator::HasBroadcastAddress()
     623              : {
     624            3 :     return (GetFlags() & IFF_BROADCAST) != 0;
     625              : }
     626              : 
     627          142 : short InterfaceIterator::GetFlags()
     628              : {
     629              :     struct ifreq intfData;
     630              : 
     631          142 :     if (!mIntfFlagsCached && HasCurrent())
     632              :     {
     633          134 :         Platform::CopyString(intfData.ifr_name, mIntfArray[mCurIntf].if_name);
     634              : 
     635          134 :         int res = ioctl(GetIOCTLSocket(), SIOCGIFFLAGS, &intfData);
     636          134 :         if (res == 0)
     637              :         {
     638          134 :             mIntfFlags       = intfData.ifr_flags;
     639          134 :             mIntfFlagsCached = true;
     640              :         }
     641              : #ifdef __MBED__
     642              :         CloseIOCTLSocket();
     643              : #endif
     644              :     }
     645              : 
     646          142 :     return mIntfFlags;
     647              : }
     648              : 
     649            3 : CHIP_ERROR InterfaceIterator::GetInterfaceType(InterfaceType & type)
     650              : {
     651            3 :     return CHIP_ERROR_NOT_IMPLEMENTED;
     652              : }
     653              : 
     654            3 : CHIP_ERROR InterfaceIterator::GetHardwareAddress(uint8_t * addressBuffer, uint8_t & addressSize, uint8_t addressBufferSize)
     655              : {
     656            3 :     return CHIP_ERROR_NOT_IMPLEMENTED;
     657              : }
     658              : 
     659          486 : InterfaceAddressIterator::InterfaceAddressIterator()
     660              : {
     661          486 :     mAddrsList = nullptr;
     662          486 :     mCurAddr   = nullptr;
     663          486 : }
     664              : 
     665          486 : InterfaceAddressIterator::~InterfaceAddressIterator()
     666              : {
     667          486 :     if (mAddrsList != nullptr)
     668              :     {
     669          386 :         freeifaddrs(mAddrsList);
     670          386 :         mAddrsList = mCurAddr = nullptr;
     671              :     }
     672          486 : }
     673              : 
     674         3552 : bool InterfaceAddressIterator::HasCurrent()
     675              : {
     676         3552 :     return (mAddrsList != nullptr) ? (mCurAddr != nullptr) : Next();
     677              : }
     678              : 
     679         2526 : bool InterfaceAddressIterator::Next()
     680              : {
     681              :     while (true)
     682              :     {
     683         2526 :         if (mAddrsList == nullptr)
     684              :         {
     685          386 :             int res = getifaddrs(&mAddrsList);
     686          386 :             if (res < 0)
     687              :             {
     688            0 :                 return false;
     689              :             }
     690          386 :             mCurAddr = mAddrsList;
     691              :         }
     692         2140 :         else if (mCurAddr != nullptr)
     693              :         {
     694         2139 :             mCurAddr = mCurAddr->ifa_next;
     695              :         }
     696              : 
     697         2526 :         if (mCurAddr == nullptr)
     698              :         {
     699          306 :             return false;
     700              :         }
     701              : 
     702         2220 :         if (mCurAddr->ifa_addr != nullptr &&
     703         2220 :             (mCurAddr->ifa_addr->sa_family == AF_INET6
     704              : #if INET_CONFIG_ENABLE_IPV4
     705         1544 :              || mCurAddr->ifa_addr->sa_family == AF_INET
     706              : #endif // INET_CONFIG_ENABLE_IPV4
     707              :              ))
     708              :         {
     709         1448 :             return true;
     710              :         }
     711          772 :     }
     712              : }
     713              : 
     714          847 : CHIP_ERROR InterfaceAddressIterator::GetAddress(IPAddress & outIPAddress)
     715              : {
     716          847 :     return HasCurrent() ? IPAddress::GetIPAddressFromSockAddr(*mCurAddr->ifa_addr, outIPAddress) : CHIP_ERROR_SENTINEL;
     717              : }
     718              : 
     719          113 : uint8_t InterfaceAddressIterator::GetPrefixLength()
     720              : {
     721          113 :     if (HasCurrent())
     722              :     {
     723          113 :         if (mCurAddr->ifa_addr->sa_family == AF_INET6)
     724              :         {
     725              : #ifndef __MBED__
     726          111 :             struct sockaddr_in6 & netmask = *reinterpret_cast<struct sockaddr_in6 *>(mCurAddr->ifa_netmask);
     727          111 :             return NetmaskToPrefixLength(netmask.sin6_addr.s6_addr, 16);
     728              : #else  // __MBED__
     729              :        // netmask is not available through an API for IPv6 interface in Mbed.
     730              :        // Default prefix length to 64.
     731              :             return 64;
     732              : #endif // !__MBED__
     733              :         }
     734            2 :         if (mCurAddr->ifa_addr->sa_family == AF_INET)
     735              :         {
     736            2 :             struct sockaddr_in & netmask = *reinterpret_cast<struct sockaddr_in *>(mCurAddr->ifa_netmask);
     737            2 :             return NetmaskToPrefixLength(reinterpret_cast<const uint8_t *>(&netmask.sin_addr.s_addr), 4);
     738              :         }
     739              :     }
     740            0 :     return 0;
     741              : }
     742              : 
     743          940 : InterfaceId InterfaceAddressIterator::GetInterfaceId()
     744              : {
     745          940 :     return HasCurrent() ? InterfaceId(if_nametoindex(mCurAddr->ifa_name)) : InterfaceId::Null();
     746              : }
     747              : 
     748            5 : CHIP_ERROR InterfaceAddressIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize)
     749              : {
     750            5 :     VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE);
     751            4 :     VerifyOrReturnError(strlen(mCurAddr->ifa_name) < nameBufSize, CHIP_ERROR_BUFFER_TOO_SMALL);
     752            4 :     Platform::CopyString(nameBuf, nameBufSize, mCurAddr->ifa_name);
     753            4 :     return CHIP_NO_ERROR;
     754              : }
     755              : 
     756            8 : bool InterfaceAddressIterator::IsUp()
     757              : {
     758            8 :     return HasCurrent() && (mCurAddr->ifa_flags & IFF_UP) != 0;
     759              : }
     760              : 
     761            0 : bool InterfaceAddressIterator::IsLoopback()
     762              : {
     763            0 :     return HasCurrent() && (mCurAddr->ifa_flags & IFF_LOOPBACK) != 0;
     764              : }
     765              : 
     766            5 : bool InterfaceAddressIterator::SupportsMulticast()
     767              : {
     768            5 :     return HasCurrent() && (mCurAddr->ifa_flags & IFF_MULTICAST) != 0;
     769              : }
     770              : 
     771            9 : bool InterfaceAddressIterator::HasBroadcastAddress()
     772              : {
     773            9 :     return HasCurrent() && (mCurAddr->ifa_flags & IFF_BROADCAST) != 0;
     774              : }
     775              : 
     776            6 : CHIP_ERROR InterfaceId::GetLinkLocalAddr(IPAddress * llAddr) const
     777              : {
     778            6 :     VerifyOrReturnError(llAddr != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     779              : 
     780              :     struct ifaddrs * ifaddr;
     781            5 :     const int rv = getifaddrs(&ifaddr);
     782            5 :     bool found   = false;
     783              : 
     784            5 :     if (rv == -1)
     785              :     {
     786            0 :         return INET_ERROR_ADDRESS_NOT_FOUND;
     787              :     }
     788              : 
     789           31 :     for (struct ifaddrs * ifaddr_iter = ifaddr; ifaddr_iter != nullptr; ifaddr_iter = ifaddr_iter->ifa_next)
     790              :     {
     791           30 :         if (ifaddr_iter->ifa_addr != nullptr)
     792              :         {
     793           40 :             if ((ifaddr_iter->ifa_addr->sa_family == AF_INET6) &&
     794           10 :                 ((mPlatformInterface == 0) || (mPlatformInterface == if_nametoindex(ifaddr_iter->ifa_name))))
     795              :             {
     796            6 :                 struct in6_addr * sin6_addr = &(reinterpret_cast<struct sockaddr_in6 *>(ifaddr_iter->ifa_addr))->sin6_addr;
     797            6 :                 if ((sin6_addr->s6_addr[0] == 0xfe) && ((sin6_addr->s6_addr[1] & 0xc0) == 0x80)) // Link Local Address
     798              :                 {
     799            4 :                     (*llAddr) = IPAddress((reinterpret_cast<struct sockaddr_in6 *>(ifaddr_iter->ifa_addr))->sin6_addr);
     800            4 :                     found     = true;
     801            4 :                     break;
     802              :                 }
     803              :             }
     804              :         }
     805              :     }
     806            5 :     freeifaddrs(ifaddr);
     807              : 
     808            5 :     return (found) ? CHIP_NO_ERROR : INET_ERROR_ADDRESS_NOT_FOUND;
     809              : }
     810              : 
     811              : #endif // (CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS
     812              : 
     813              : #if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF
     814              : 
     815              : CHIP_ERROR InterfaceId::GetInterfaceName(char * nameBuf, size_t nameBufSize) const
     816              : {
     817              :     if (mPlatformInterface)
     818              :     {
     819              :         net_if * currentInterface = net_if_get_by_index(mPlatformInterface);
     820              :         if (!currentInterface)
     821              :         {
     822              :             return CHIP_ERROR_INCORRECT_STATE;
     823              :         }
     824              :         const char * name = net_if_get_device(currentInterface)->name;
     825              :         size_t nameLength = strlen(name);
     826              :         if (nameLength >= nameBufSize)
     827              :         {
     828              :             return CHIP_ERROR_BUFFER_TOO_SMALL;
     829              :         }
     830              :         Platform::CopyString(nameBuf, nameBufSize, name);
     831              :         return CHIP_NO_ERROR;
     832              :     }
     833              :     if (nameBufSize < 1)
     834              :     {
     835              :         return CHIP_ERROR_BUFFER_TOO_SMALL;
     836              :     }
     837              :     nameBuf[0] = 0;
     838              :     return CHIP_NO_ERROR;
     839              : }
     840              : 
     841              : CHIP_ERROR InterfaceId::InterfaceNameToId(const char * intfName, InterfaceId & interface)
     842              : {
     843              :     int currentId = 0;
     844              :     net_if * currentInterface;
     845              : 
     846              :     while ((currentInterface = net_if_get_by_index(++currentId)) != nullptr)
     847              :     {
     848              :         if (strcmp(net_if_get_device(currentInterface)->name, intfName) == 0)
     849              :         {
     850              :             interface = InterfaceId(currentId);
     851              :             return CHIP_NO_ERROR;
     852              :         }
     853              :     }
     854              :     interface = InterfaceId::Null();
     855              :     return INET_ERROR_UNKNOWN_INTERFACE;
     856              : }
     857              : 
     858              : InterfaceIterator::InterfaceIterator() : mCurrentInterface(net_if_get_by_index(mCurrentId)) {}
     859              : 
     860              : bool InterfaceIterator::HasCurrent(void)
     861              : {
     862              :     return mCurrentInterface != nullptr;
     863              : }
     864              : 
     865              : bool InterfaceIterator::Next()
     866              : {
     867              :     mCurrentInterface = net_if_get_by_index(++mCurrentId);
     868              :     return HasCurrent();
     869              : }
     870              : 
     871              : InterfaceId InterfaceIterator::GetInterfaceId(void)
     872              : {
     873              :     return HasCurrent() ? InterfaceId(mCurrentId) : InterfaceId::Null();
     874              : }
     875              : 
     876              : CHIP_ERROR InterfaceIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize)
     877              : {
     878              :     VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE);
     879              :     return InterfaceId(mCurrentId).GetInterfaceName(nameBuf, nameBufSize);
     880              : }
     881              : 
     882              : bool InterfaceIterator::IsUp()
     883              : {
     884              :     return HasCurrent() && net_if_is_up(mCurrentInterface);
     885              : }
     886              : 
     887              : bool InterfaceIterator::SupportsMulticast()
     888              : {
     889              :     return HasCurrent() && NET_IF_MAX_IPV6_MADDR > 0;
     890              : }
     891              : 
     892              : bool InterfaceIterator::HasBroadcastAddress()
     893              : {
     894              :     // Zephyr seems to handle broadcast address for IPv4 implicitly
     895              :     return HasCurrent() && INET_CONFIG_ENABLE_IPV4;
     896              : }
     897              : 
     898              : CHIP_ERROR InterfaceIterator::GetInterfaceType(InterfaceType & type)
     899              : {
     900              :     VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE);
     901              : 
     902              :     const net_linkaddr * linkAddr = net_if_get_link_addr(mCurrentInterface);
     903              :     if (!linkAddr)
     904              :         return CHIP_ERROR_INCORRECT_STATE;
     905              : 
     906              :     // Do not consider other than WiFi and Thread for now.
     907              :     if (linkAddr->type == NET_LINK_IEEE802154)
     908              :     {
     909              :         type = InterfaceType::Thread;
     910              :     }
     911              :     // Zephyr doesn't define WiFi address type, so it shares the same type as Ethernet.
     912              :     else if (linkAddr->type == NET_LINK_ETHERNET)
     913              :     {
     914              :         type = InterfaceType::WiFi;
     915              :     }
     916              :     else
     917              :     {
     918              :         type = InterfaceType::Unknown;
     919              :     }
     920              : 
     921              :     return CHIP_NO_ERROR;
     922              : }
     923              : 
     924              : CHIP_ERROR InterfaceIterator::GetHardwareAddress(uint8_t * addressBuffer, uint8_t & addressSize, uint8_t addressBufferSize)
     925              : {
     926              :     VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE);
     927              : 
     928              :     if (!addressBuffer)
     929              :         return CHIP_ERROR_INVALID_ARGUMENT;
     930              : 
     931              :     const net_linkaddr * linkAddr = net_if_get_link_addr(mCurrentInterface);
     932              :     if (!linkAddr)
     933              :         return CHIP_ERROR_INCORRECT_STATE;
     934              : 
     935              :     if (linkAddr->len > addressBufferSize)
     936              :         return CHIP_ERROR_BUFFER_TOO_SMALL;
     937              : 
     938              :     addressSize = linkAddr->len;
     939              :     memcpy(addressBuffer, linkAddr->addr, linkAddr->len);
     940              : 
     941              :     return CHIP_NO_ERROR;
     942              : }
     943              : 
     944              : InterfaceAddressIterator::InterfaceAddressIterator() = default;
     945              : 
     946              : bool InterfaceAddressIterator::HasCurrent()
     947              : {
     948              :     return mIntfIter.HasCurrent() && (mCurAddrIndex >= 0 || Next());
     949              : }
     950              : 
     951              : bool InterfaceAddressIterator::Next()
     952              : {
     953              :     while (mIntfIter.HasCurrent())
     954              :     {
     955              :         if (mCurAddrIndex == -1) // first address for the current interface
     956              :         {
     957              :             const net_if_config * config =
     958              :                 net_if_get_config(net_if_get_by_index(mIntfIter.GetInterfaceId().GetPlatformInterface()));
     959              :             mIpv6 = config->ip.ipv6;
     960              :         }
     961              : 
     962              :         if (mIpv6)
     963              :         {
     964              :             while (++mCurAddrIndex < NET_IF_MAX_IPV6_ADDR)
     965              :                 if (mIpv6->unicast[mCurAddrIndex].is_used)
     966              :                     return true;
     967              :         }
     968              : 
     969              :         mCurAddrIndex = -1;
     970              :         mIntfIter.Next();
     971              :     }
     972              : 
     973              :     return false;
     974              : }
     975              : 
     976              : CHIP_ERROR InterfaceAddressIterator::GetAddress(IPAddress & outIPAddress)
     977              : {
     978              :     if (HasCurrent())
     979              :     {
     980              :         outIPAddress = IPAddress(mIpv6->unicast[mCurAddrIndex].address.in6_addr);
     981              :         return CHIP_NO_ERROR;
     982              :     }
     983              :     return CHIP_ERROR_SENTINEL;
     984              : }
     985              : 
     986              : uint8_t InterfaceAddressIterator::GetPrefixLength()
     987              : {
     988              :     if (HasCurrent())
     989              :     {
     990              :         net_if * const iface              = net_if_get_by_index(mIntfIter.GetInterfaceId().GetPlatformInterface());
     991              :         net_if_ipv6_prefix * const prefix = net_if_ipv6_prefix_get(iface, &mIpv6->unicast[mCurAddrIndex].address.in6_addr);
     992              :         return prefix ? prefix->len : 128;
     993              :     }
     994              :     return 0;
     995              : }
     996              : 
     997              : InterfaceId InterfaceAddressIterator::GetInterfaceId()
     998              : {
     999              :     return HasCurrent() ? mIntfIter.GetInterfaceId() : InterfaceId::Null();
    1000              : }
    1001              : 
    1002              : CHIP_ERROR InterfaceAddressIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize)
    1003              : {
    1004              :     VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE);
    1005              :     return mIntfIter.GetInterfaceName(nameBuf, nameBufSize);
    1006              : }
    1007              : 
    1008              : bool InterfaceAddressIterator::IsUp()
    1009              : {
    1010              :     return HasCurrent() && mIntfIter.IsUp();
    1011              : }
    1012              : 
    1013              : bool InterfaceAddressIterator::SupportsMulticast()
    1014              : {
    1015              :     return HasCurrent() && mIntfIter.SupportsMulticast();
    1016              : }
    1017              : 
    1018              : bool InterfaceAddressIterator::HasBroadcastAddress()
    1019              : {
    1020              :     return HasCurrent() && mIntfIter.HasBroadcastAddress();
    1021              : }
    1022              : 
    1023              : CHIP_ERROR InterfaceId::GetLinkLocalAddr(IPAddress * llAddr) const
    1024              : {
    1025              :     VerifyOrReturnError(llAddr != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    1026              : 
    1027              :     net_if * const iface = mPlatformInterface ? net_if_get_by_index(mPlatformInterface) : net_if_get_default();
    1028              :     VerifyOrReturnError(iface != nullptr, INET_ERROR_ADDRESS_NOT_FOUND);
    1029              : 
    1030              :     in6_addr * const ip6_addr = net_if_ipv6_get_ll(iface, NET_ADDR_PREFERRED);
    1031              :     VerifyOrReturnError(ip6_addr != nullptr, INET_ERROR_ADDRESS_NOT_FOUND);
    1032              : 
    1033              :     *llAddr = IPAddress(*ip6_addr);
    1034              : 
    1035              :     return CHIP_NO_ERROR;
    1036              : }
    1037              : 
    1038              : #endif // CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF
    1039              : 
    1040              : // static
    1041            2 : InterfaceId InterfaceId::FromIPAddress(const IPAddress & addr)
    1042              : {
    1043            2 :     InterfaceAddressIterator addrIter;
    1044              : 
    1045            9 :     for (; addrIter.HasCurrent(); addrIter.Next())
    1046              :     {
    1047              :         IPAddress curAddr;
    1048            8 :         if ((addrIter.GetAddress(curAddr) == CHIP_NO_ERROR) && (addr == curAddr))
    1049              :         {
    1050            1 :             return addrIter.GetInterfaceId();
    1051              :         }
    1052              :     }
    1053              : 
    1054            1 :     return InterfaceId::Null();
    1055            2 : }
    1056              : 
    1057              : // static
    1058          110 : bool InterfaceId::MatchLocalIPv6Subnet(const IPAddress & addr)
    1059              : {
    1060          110 :     if (addr.IsIPv6LinkLocal())
    1061            1 :         return true;
    1062              : 
    1063          109 :     InterfaceAddressIterator ifAddrIter;
    1064          545 :     for (; ifAddrIter.HasCurrent(); ifAddrIter.Next())
    1065              :     {
    1066              :         IPPrefix addrPrefix;
    1067          436 :         if (ifAddrIter.GetAddress(addrPrefix.IPAddr) != CHIP_NO_ERROR)
    1068          327 :             continue;
    1069              : #if INET_CONFIG_ENABLE_IPV4
    1070          436 :         if (addrPrefix.IPAddr.IsIPv4())
    1071          218 :             continue;
    1072              : #endif // INET_CONFIG_ENABLE_IPV4
    1073          218 :         if (addrPrefix.IPAddr.IsIPv6LinkLocal())
    1074          109 :             continue;
    1075          109 :         addrPrefix.Length = ifAddrIter.GetPrefixLength();
    1076          109 :         if (addrPrefix.MatchAddress(addr))
    1077            0 :             return true;
    1078              :     }
    1079              : 
    1080          109 :     return false;
    1081          109 : }
    1082              : 
    1083          113 : uint8_t NetmaskToPrefixLength(const uint8_t * netmask, uint16_t netmaskLen)
    1084              : {
    1085          113 :     uint8_t prefixLen = 0;
    1086              : 
    1087         1886 :     for (uint16_t i = 0; i < netmaskLen; i++, prefixLen = static_cast<uint8_t>(prefixLen + 8u))
    1088              :     {
    1089         1775 :         uint8_t b = netmask[i];
    1090         1775 :         if (b != 0xFF)
    1091              :         {
    1092            2 :             if ((b & 0xF0) == 0xF0)
    1093            0 :                 prefixLen = static_cast<uint8_t>(prefixLen + 4u);
    1094              :             else
    1095            2 :                 b = static_cast<uint8_t>(b >> 4);
    1096              : 
    1097            2 :             if ((b & 0x0C) == 0x0C)
    1098            0 :                 prefixLen = static_cast<uint8_t>(prefixLen + 2u);
    1099              :             else
    1100            2 :                 b = static_cast<uint8_t>(b >> 2);
    1101              : 
    1102            2 :             if ((b & 0x02) == 0x02)
    1103            0 :                 prefixLen++;
    1104              : 
    1105            2 :             break;
    1106              :         }
    1107              :     }
    1108              : 
    1109          113 :     return prefixLen;
    1110              : }
    1111              : 
    1112              : } // namespace Inet
    1113              : } // namespace chip
        

Generated by: LCOV version 2.0-1