LCOV - code coverage report
Current view: top level - inet - InetInterface.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 163 194 84.0 %
Date: 2024-02-15 08:20:41 Functions: 30 33 90.9 %

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

Generated by: LCOV version 1.14