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

Generated by: LCOV version 2.0-1