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

Generated by: LCOV version 2.0-1