Skip to content

Commit

Permalink
Inet: Move some InterfaceId functions out of InetLayer (#11673)
Browse files Browse the repository at this point in the history
* Inet: Move some InterfaceId functions out of InetLayer

#### Problem

`InetLayer` contains some operations involving `InterfaceId`
that don't use any `InetLayer` state.

This is a step toward #7715 _Virtualize System and Inet interfaces_.

#### Change overview

Move these methods from `InetLayer` to `InterfaceId`:
- `GetLinkLocalAddr()`
- `MatchLocalIPv6Subnet()`
- `GetInterfaceFromAddr()`, renamed `InterfaceId::FromIPAddress()`

#### Testing

CI; no changes to functionality.

* restyle
  • Loading branch information
kpschoedel authored and pull[bot] committed Jan 24, 2022
1 parent ff50b89 commit 3784387
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 169 deletions.
118 changes: 118 additions & 0 deletions src/inet/InetInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,35 @@ bool InterfaceAddressIterator::HasBroadcastAddress()
return HasCurrent() && mIntfIter.HasBroadcastAddress();
}

CHIP_ERROR InterfaceId::GetLinkLocalAddr(IPAddress * llAddr)
{
VerifyOrReturnError(llAddr != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

#if !LWIP_IPV6
return CHIP_ERROR_NOT_IMPLEMENTED;
#endif //! LWIP_IPV6

for (struct netif * intf = netif_list; intf != nullptr; intf = intf->next)
{
if ((mPlatformInterface != nullptr) && (mPlatformInterface != intf))
continue;
for (int j = 0; j < LWIP_IPV6_NUM_ADDRESSES; ++j)
{
if (ip6_addr_isvalid(netif_ip6_addr_state(intf, j)) && ip6_addr_islinklocal(netif_ip6_addr(intf, j)))
{
(*llAddr) = IPAddress(*netif_ip6_addr(intf, j));
return CHIP_NO_ERROR;
}
}
if (mPlatformInterface != nullptr)
{
return INET_ERROR_ADDRESS_NOT_FOUND;
}
}

return CHIP_NO_ERROR;
}

#endif // CHIP_SYSTEM_CONFIG_USE_LWIP

#if CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS
Expand Down Expand Up @@ -704,6 +733,38 @@ bool InterfaceAddressIterator::HasBroadcastAddress()
return HasCurrent() && (mCurAddr->ifa_flags & IFF_BROADCAST) != 0;
}

CHIP_ERROR InterfaceId::GetLinkLocalAddr(IPAddress * llAddr)
{
VerifyOrReturnError(llAddr != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

struct ifaddrs * ifaddr;
const int rv = getifaddrs(&ifaddr);
if (rv == -1)
{
return INET_ERROR_ADDRESS_NOT_FOUND;
}

for (struct ifaddrs * ifaddr_iter = ifaddr; ifaddr_iter != nullptr; ifaddr_iter = ifaddr_iter->ifa_next)
{
if (ifaddr_iter->ifa_addr != nullptr)
{
if ((ifaddr_iter->ifa_addr->sa_family == AF_INET6) &&
((mPlatformInterface == 0) || (mPlatformInterface == if_nametoindex(ifaddr_iter->ifa_name))))
{
struct in6_addr * sin6_addr = &(reinterpret_cast<struct sockaddr_in6 *>(ifaddr_iter->ifa_addr))->sin6_addr;
if (sin6_addr->s6_addr[0] == 0xfe && (sin6_addr->s6_addr[1] & 0xc0) == 0x80) // Link Local Address
{
(*llAddr) = IPAddress((reinterpret_cast<struct sockaddr_in6 *>(ifaddr_iter->ifa_addr))->sin6_addr);
break;
}
}
}
}
freeifaddrs(ifaddr);

return CHIP_NO_ERROR;
}

#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS

#if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF
Expand Down Expand Up @@ -865,8 +926,65 @@ bool InterfaceAddressIterator::HasBroadcastAddress()
return HasCurrent() && mIntfIter.HasBroadcastAddress();
}

CHIP_ERROR InterfaceId::GetLinkLocalAddr(IPAddress * llAddr)
{
VerifyOrReturnError(llAddr != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

net_if * const iface = mPlatformInterface ? net_if_get_by_index(mPlatformInterface) : net_if_get_default();
VerifyOrReturnError(iface != nullptr, INET_ERROR_ADDRESS_NOT_FOUND);

in6_addr * const ip6_addr = net_if_ipv6_get_ll(iface, NET_ADDR_PREFERRED);
VerifyOrReturnError(ip6_addr != nullptr, INET_ERROR_ADDRESS_NOT_FOUND);

*llAddr = IPAddress(*ip6_addr);

return CHIP_NO_ERROR;
}

#endif // CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF

// static
InterfaceId InterfaceId::FromIPAddress(const IPAddress & addr)
{
InterfaceAddressIterator addrIter;

for (; addrIter.HasCurrent(); addrIter.Next())
{
IPAddress curAddr = addrIter.GetAddress();
if (addr == curAddr)
{
return addrIter.GetInterfaceId();
}
}

return InterfaceId::Null();
}

// static
bool InterfaceId::MatchLocalIPv6Subnet(const IPAddress & addr)
{
if (addr.IsIPv6LinkLocal())
return true;

InterfaceAddressIterator ifAddrIter;
for (; ifAddrIter.HasCurrent(); ifAddrIter.Next())
{
IPPrefix addrPrefix;
addrPrefix.IPAddr = ifAddrIter.GetAddress();
#if INET_CONFIG_ENABLE_IPV4
if (addrPrefix.IPAddr.IsIPv4())
continue;
#endif // INET_CONFIG_ENABLE_IPV4
if (addrPrefix.IPAddr.IsIPv6LinkLocal())
continue;
addrPrefix.Length = ifAddrIter.GetPrefixLength();
if (addrPrefix.MatchAddress(addr))
return true;
}

return false;
}

void InterfaceAddressIterator::GetAddressWithPrefix(IPPrefix & addrWithPrefix)
{
if (HasCurrent())
Expand Down
33 changes: 33 additions & 0 deletions src/inet/InetInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,39 @@ class InterfaceId
*/
static CHIP_ERROR InterfaceNameToId(const char * intfName, InterfaceId & intfId);

/**
* Get the interface identifier for the specified IP address. If the
* interface identifier cannot be derived it is set to the default InterfaceId.
*
* @note
* This function fetches the first interface (from the configured list
* of interfaces) that matches the specified IP address.
*/
static InterfaceId FromIPAddress(const IPAddress & addr);

/**
* Check if there is a prefix match between the specified IPv6 address and any of
* the locally configured IPv6 addresses.
*
* @param[in] addr The IPv6 address to check for the prefix-match.
* @return true if a successful match is found, otherwise false.
*/
static bool MatchLocalIPv6Subnet(const IPAddress & addr);

/**
* Get the link local IPv6 address.
*
* @param[out] llAddr The link local IPv6 address for the link.
*
* @retval #CHIP_ERROR_NOT_IMPLEMENTED If IPv6 is not supported.
* @retval #CHIP_ERROR_INVALID_ARGUMENT If the link local address
* is nullptr.
* @retval #INET_ERROR_ADDRESS_NOT_FOUND If the link does not have
* any address configured.
* @retval #CHIP_NO_ERROR On success.
*/
CHIP_ERROR GetLinkLocalAddr(IPAddress * llAddr);

private:
#if CHIP_SYSTEM_CONFIG_USE_LWIP
static constexpr PlatformType kPlatformNull = nullptr;
Expand Down
153 changes: 0 additions & 153 deletions src/inet/InetLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,91 +219,6 @@ bool InetLayer::IsIdleTimerRunning()
}
#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT && INET_TCP_IDLE_CHECK_INTERVAL > 0

/**
* Get the link local IPv6 address for a specified link or interface.
*
* @param[in] interface The interface for which the link local IPv6
* address is being sought.
*
* @param[out] llAddr The link local IPv6 address for the link.
*
* @retval #CHIP_ERROR_NOT_IMPLEMENTED If IPv6 is not supported.
* @retval #CHIP_ERROR_INVALID_ARGUMENT If the link local address
* is nullptr.
* @retval #INET_ERROR_ADDRESS_NOT_FOUND If the link does not have
* any address configured.
* @retval #CHIP_NO_ERROR On success.
*
*/
CHIP_ERROR InetLayer::GetLinkLocalAddr(InterfaceId interface, IPAddress * llAddr)
{
VerifyOrReturnError(llAddr != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

#if CHIP_SYSTEM_CONFIG_USE_LWIP
#if !LWIP_IPV6
return CHIP_ERROR_NOT_IMPLEMENTED;
#endif //! LWIP_IPV6

struct netif * link = interface.GetPlatformInterface();
for (struct netif * intf = netif_list; intf != NULL; intf = intf->next)
{
if ((link != NULL) && (link != intf))
continue;
for (int j = 0; j < LWIP_IPV6_NUM_ADDRESSES; ++j)
{
if (ip6_addr_isvalid(netif_ip6_addr_state(intf, j)) && ip6_addr_islinklocal(netif_ip6_addr(intf, j)))
{
(*llAddr) = IPAddress(*netif_ip6_addr(intf, j));
return CHIP_NO_ERROR;
}
}
if (link != NULL)
{
return INET_ERROR_ADDRESS_NOT_FOUND;
}
}
#endif // CHIP_SYSTEM_CONFIG_USE_LWIP

#if CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS
struct ifaddrs * ifaddr;
const int rv = getifaddrs(&ifaddr);
if (rv == -1)
{
return INET_ERROR_ADDRESS_NOT_FOUND;
}

for (struct ifaddrs * ifaddr_iter = ifaddr; ifaddr_iter != nullptr; ifaddr_iter = ifaddr_iter->ifa_next)
{
if (ifaddr_iter->ifa_addr != nullptr)
{
if ((ifaddr_iter->ifa_addr->sa_family == AF_INET6) &&
(!interface.IsPresent() || (if_nametoindex(ifaddr_iter->ifa_name) == interface.GetPlatformInterface())))
{
struct in6_addr * sin6_addr = &(reinterpret_cast<struct sockaddr_in6 *>(ifaddr_iter->ifa_addr))->sin6_addr;
if (sin6_addr->s6_addr[0] == 0xfe && (sin6_addr->s6_addr[1] & 0xc0) == 0x80) // Link Local Address
{
(*llAddr) = IPAddress((reinterpret_cast<struct sockaddr_in6 *>(ifaddr_iter->ifa_addr))->sin6_addr);
break;
}
}
}
}
freeifaddrs(ifaddr);
#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS

#if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF
net_if * const iface = interface.IsPresent() ? net_if_get_by_index(interface.GetPlatformInterface()) : net_if_get_default();
VerifyOrReturnError(iface != nullptr, INET_ERROR_ADDRESS_NOT_FOUND);

in6_addr * const ip6_addr = net_if_ipv6_get_ll(iface, NET_ADDR_PREFERRED);
VerifyOrReturnError(ip6_addr != nullptr, INET_ERROR_ADDRESS_NOT_FOUND);

*llAddr = IPAddress(*ip6_addr);
#endif // CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF

return CHIP_NO_ERROR;
}

#if INET_CONFIG_ENABLE_TCP_ENDPOINT
/**
* Creates a new TCPEndPoint object.
Expand Down Expand Up @@ -382,74 +297,6 @@ CHIP_ERROR InetLayer::NewUDPEndPoint(UDPEndPoint ** retEndPoint)
}
#endif // INET_CONFIG_ENABLE_UDP_ENDPOINT

/**
* Get the interface identifier for the specified IP address. If the
* interface identifier cannot be derived it is set to the default
* InterfaceId.
*
* @note
* This function fetches the first interface (from the configured list
* of interfaces) that matches the specified IP address.
*
* @param[in] addr A reference to the IPAddress object.
*
* @param[out] intfId A reference to the InterfaceId object.
*
* @return #CHIP_NO_ERROR unconditionally.
*
*/
CHIP_ERROR InetLayer::GetInterfaceFromAddr(const IPAddress & addr, InterfaceId & intfId)
{
InterfaceAddressIterator addrIter;

for (; addrIter.HasCurrent(); addrIter.Next())
{
IPAddress curAddr = addrIter.GetAddress();
if (addr == curAddr)
{
intfId = addrIter.GetInterfaceId();
return CHIP_NO_ERROR;
}
}

intfId = InterfaceId::Null();

return CHIP_NO_ERROR;
}

/**
* Check if there is a prefix match between the specified IPv6 address and any of
* the locally configured IPv6 addresses.
*
* @param[in] addr The IPv6 address to check for the prefix-match.
*
* @return true if a successful match is found, otherwise false.
*
*/
bool InetLayer::MatchLocalIPv6Subnet(const IPAddress & addr)
{
if (addr.IsIPv6LinkLocal())
return true;

InterfaceAddressIterator ifAddrIter;
for (; ifAddrIter.HasCurrent(); ifAddrIter.Next())
{
IPPrefix addrPrefix;
addrPrefix.IPAddr = ifAddrIter.GetAddress();
#if INET_CONFIG_ENABLE_IPV4
if (addrPrefix.IPAddr.IsIPv4())
continue;
#endif // INET_CONFIG_ENABLE_IPV4
if (addrPrefix.IPAddr.IsIPv6LinkLocal())
continue;
addrPrefix.Length = ifAddrIter.GetPrefixLength();
if (addrPrefix.MatchAddress(addr))
return true;
}

return false;
}

#if INET_CONFIG_ENABLE_TCP_ENDPOINT && INET_TCP_IDLE_CHECK_INTERVAL > 0
void InetLayer::HandleTCPInactivityTimer(chip::System::Layer * aSystemLayer, void * aAppState)
{
Expand Down
7 changes: 0 additions & 7 deletions src/inet/InetLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,6 @@ class DLL_EXPORT InetLayer
CHIP_ERROR NewUDPEndPoint(UDPEndPoint ** retEndPoint);
#endif // INET_CONFIG_ENABLE_UDP_ENDPOINT

// DNS Resolution

CHIP_ERROR GetInterfaceFromAddr(const IPAddress & addr, InterfaceId & intfId);

CHIP_ERROR GetLinkLocalAddr(InterfaceId link, IPAddress * llAddr);
bool MatchLocalIPv6Subnet(const IPAddress & addr);

void * GetPlatformData();
void SetPlatformData(void * aPlatformData);

Expand Down
3 changes: 1 addition & 2 deletions src/inet/TCPEndPoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,12 +195,11 @@ CHIP_ERROR TCPEndPoint::ConnectImpl(const IPAddress & addr, uint16_t port, Inter
if (intfId.IsPresent())
{
IPAddress intfLLAddr;
InetLayer & lInetLayer = Layer();

if (!addr.IsIPv6LinkLocal() || mState == State::kBound)
return CHIP_ERROR_NOT_IMPLEMENTED;

res = lInetLayer.GetLinkLocalAddr(intfId, &intfLLAddr);
res = intfId.GetLinkLocalAddr(&intfLLAddr);
if (res != CHIP_NO_ERROR)
return res;

Expand Down
Loading

0 comments on commit 3784387

Please sign in to comment.