Skip to content

Commit

Permalink
Include interface ID in the PeerAddress that gets handed up from UDP/…
Browse files Browse the repository at this point in the history
…TCP code (#7389)

* Include the interface id in the PeerAddress UDP passes up the stack.

Without this, we end up sending a message, getting a response,
clobbering our PeerAddress with one without interface info, and then
not being able to send the CRMP standalone ack properly.

* Include the interface id in the PeerAddress TCP passes up the stack.
  • Loading branch information
bzbarsky-apple authored and pull[bot] committed Jun 17, 2021
1 parent f79213f commit 1121536
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 4 deletions.
61 changes: 61 additions & 0 deletions src/inet/TCPEndPoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,67 @@ INET_ERROR TCPEndPoint::GetLocalInfo(IPAddress * retAddr, uint16_t * retPort)
return res;
}

INET_ERROR TCPEndPoint::GetInterfaceId(InterfaceId * retInterface)
{
if (!IsConnected())
return INET_ERROR_INCORRECT_STATE;

#if CHIP_SYSTEM_CONFIG_USE_LWIP
// TODO: Does netif_get_by_index(mTCP->netif_idx) do the right thing? I
// can't quite tell whether LwIP supports a specific interface id for TCP at
// all. For now just claim no particular interface id.
*retInterface = INET_NULL_INTERFACEID;
return INET_NO_ERROR;
#endif // CHIP_SYSTEM_CONFIG_USE_LWIP

#if CHIP_SYSTEM_CONFIG_USE_SOCKETS
union
{
sockaddr any;
sockaddr_in6 in6;
#if INET_CONFIG_ENABLE_IPV4
sockaddr_in in;
#endif // INET_CONFIG_ENABLE_IPV4
} sa;

memset(&sa, 0, sizeof(sa));
socklen_t saLen = sizeof(sa);

if (getpeername(mSocket, &sa.any, &saLen) != 0)
{
return chip::System::MapErrorPOSIX(errno);
}

if (sa.any.sa_family == AF_INET6)
{
if (IPAddress::FromIPv6(sa.in6.sin6_addr).IsIPv6LinkLocal())
{
*retInterface = sa.in6.sin6_scope_id;
}
else
{
// TODO: Is there still a meaningful interface id in this case?
*retInterface = INET_NULL_INTERFACEID;
}
return INET_NO_ERROR;
}

#if INET_CONFIG_ENABLE_IPV4
if (sa.any.sa_family == AF_INET)
{
// No interface id available for IPv4 sockets.
*retInterface = INET_NULL_INTERFACEID;
}
#endif // INET_CONFIG_ENABLE_IPV4

return INET_ERROR_INCORRECT_STATE;

#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS

*retInterface = INET_NULL_INTERFACEID;
return INET_NO_ERROR;
}

INET_ERROR TCPEndPoint::Send(System::PacketBufferHandle && data, bool push)
{
INET_ERROR res = INET_NO_ERROR;
Expand Down
11 changes: 11 additions & 0 deletions src/inet/TCPEndPoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,17 @@ class DLL_EXPORT TCPEndPoint : public EndPointBasis
*/
INET_ERROR GetLocalInfo(IPAddress * retAddr, uint16_t * retPort);

/**
* @brief Extract the interface id of the TCP endpoint.
*
* @param[out] retInterface The interface id.
*
* @retval INET_NO_ERROR success: address and port extracted.
* @retval INET_ERROR_INCORRECT_STATE TCP connection not established.
* @retval INET_ERROR_CONNECTION_ABORTED TCP connection no longer open.
*/
INET_ERROR GetInterfaceId(InterfaceId * retInterface);

/**
* @brief Send message text on TCP connection.
*
Expand Down
4 changes: 4 additions & 0 deletions src/transport/raw/PeerAddress.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,10 @@ class PeerAddress
}
static PeerAddress TCP(const Inet::IPAddress & addr) { return PeerAddress(addr, Type::kTcp); }
static PeerAddress TCP(const Inet::IPAddress & addr, uint16_t port) { return TCP(addr).SetPort(port); }
static PeerAddress TCP(const Inet::IPAddress & addr, uint16_t port, Inet::InterfaceId interface)
{
return TCP(addr).SetPort(port).SetInterface(interface);
}

private:
Inet::IPAddress mIPAddress;
Expand Down
12 changes: 9 additions & 3 deletions src/transport/raw/TCP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,9 +356,11 @@ INET_ERROR TCPBase::OnTcpReceive(Inet::TCPEndPoint * endPoint, System::PacketBuf
{
Inet::IPAddress ipAddress;
uint16_t port;
Inet::InterfaceId interfaceId = INET_NULL_INTERFACEID;

endPoint->GetPeerInfo(&ipAddress, &port);
PeerAddress peerAddress = PeerAddress::TCP(ipAddress, port);
endPoint->GetInterfaceId(&interfaceId);
PeerAddress peerAddress = PeerAddress::TCP(ipAddress, port, interfaceId);

TCPBase * tcp = reinterpret_cast<TCPBase *>(endPoint->AppState);
CHIP_ERROR err = tcp->ProcessReceivedBuffer(endPoint, peerAddress, std::move(buffer));
Expand All @@ -379,9 +381,11 @@ void TCPBase::OnConnectionComplete(Inet::TCPEndPoint * endPoint, INET_ERROR inet
TCPBase * tcp = reinterpret_cast<TCPBase *>(endPoint->AppState);
Inet::IPAddress ipAddress;
uint16_t port;
Inet::InterfaceId interfaceId = INET_NULL_INTERFACEID;

endPoint->GetPeerInfo(&ipAddress, &port);
PeerAddress addr = PeerAddress::TCP(ipAddress, port);
endPoint->GetInterfaceId(&interfaceId);
PeerAddress addr = PeerAddress::TCP(ipAddress, port, interfaceId);

// Send any pending packets
for (size_t i = 0; i < tcp->mPendingPacketsSize; i++)
Expand Down Expand Up @@ -507,9 +511,11 @@ void TCPBase::Disconnect(const PeerAddress & address)
{
Inet::IPAddress ipAddress;
uint16_t port;
Inet::InterfaceId interfaceId = INET_NULL_INTERFACEID;

mActiveConnections[i].mEndPoint->GetPeerInfo(&ipAddress, &port);
if (address == PeerAddress::TCP(ipAddress, port))
mActiveConnections[i].mEndPoint->GetInterfaceId(&interfaceId);
if (address == PeerAddress::TCP(ipAddress, port, interfaceId))
{
// NOTE: this leaves the socket in TIME_WAIT.
// Calling Abort() would clean it since SO_LINGER would be set to 0,
Expand Down
2 changes: 1 addition & 1 deletion src/transport/raw/UDP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ void UDP::OnUdpReceive(Inet::IPEndPointBasis * endPoint, System::PacketBufferHan
{
CHIP_ERROR err = CHIP_NO_ERROR;
UDP * udp = reinterpret_cast<UDP *>(endPoint->AppState);
PeerAddress peerAddress = PeerAddress::UDP(pktInfo->SrcAddress, pktInfo->SrcPort);
PeerAddress peerAddress = PeerAddress::UDP(pktInfo->SrcAddress, pktInfo->SrcPort, pktInfo->Interface);

udp->HandleMessageReceived(peerAddress, std::move(buffer));

Expand Down

0 comments on commit 1121536

Please sign in to comment.