From 109a8b373b64541e4916f19851ac643277a2650a Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Wed, 3 Aug 2022 20:21:16 -0400 Subject: [PATCH] Listen for group messages on all relevant interfaces in the sockets implementation. (#21611) * Listen for group messages on all relevant interfaces in the sockets implementation. We were listening on the "default" interface if MulticastGroupJoinLeave got called for an enpoint that was bound to the wildcard interface. But that does not work in some situation (e.g. on Mac). Instead, detect that we're dealing with the wildcard interface, and explicitly iterate over all viable interfaces. * Fix build on MbedOS. --- .github/workflows/darwin-tests.yaml | 2 +- .github/workflows/tests.yaml | 2 +- src/inet/UDPEndPointImplSockets.cpp | 95 +++++++++++++++++++++++++---- 3 files changed, 86 insertions(+), 13 deletions(-) diff --git a/.github/workflows/darwin-tests.yaml b/.github/workflows/darwin-tests.yaml index 03eef9107b2d3a..eb8106f6b26fa6 100644 --- a/.github/workflows/darwin-tests.yaml +++ b/.github/workflows/darwin-tests.yaml @@ -102,7 +102,7 @@ jobs: ./scripts/run_in_build_env.sh \ "./scripts/tests/run_test_suite.py \ --chip-tool ./out/darwin-x64-darwin-framework-tool-${BUILD_VARIANT}/darwin-framework-tool \ - --target-skip-glob '{TestGroupMessaging,TestAccessControlConstraints}' \ + --target-skip-glob '{TestAccessControlConstraints}' \ run \ --iterations 1 \ --test-timeout-seconds 120 \ diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 8eb9ba25f233b2..835b5b27415cd5 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -196,7 +196,7 @@ jobs: ./scripts/run_in_build_env.sh \ "./scripts/tests/run_test_suite.py \ --chip-tool ./out/darwin-x64-chip-tool${CHIP_TOOL_VARIANT}-${BUILD_VARIANT}/chip-tool \ - --target-skip-glob '{TestGroupMessaging,Test_TC_DGTHREAD_2_1,Test_TC_DGTHREAD_2_2,Test_TC_DGTHREAD_2_3,Test_TC_DGTHREAD_2_4}' \ + --target-skip-glob '{Test_TC_DGTHREAD_2_1,Test_TC_DGTHREAD_2_2,Test_TC_DGTHREAD_2_3,Test_TC_DGTHREAD_2_4}' \ run \ --iterations 1 \ --test-timeout-seconds 120 \ diff --git a/src/inet/UDPEndPointImplSockets.cpp b/src/inet/UDPEndPointImplSockets.cpp index a9e078cc5f48fd..131e20d9709b23 100644 --- a/src/inet/UDPEndPointImplSockets.cpp +++ b/src/inet/UDPEndPointImplSockets.cpp @@ -46,6 +46,11 @@ #define SOCK_CLOEXEC 0 #endif +// On MbedOS, INADDR_ANY does not seem to exist... +#ifndef INADDR_ANY +#define INADDR_ANY 0 +#endif + #if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_SOCKET_EXTENSIONS #include "ZephyrSocket.h" #endif // CHIP_SYSTEM_CONFIG_USE_ZEPHYR_SOCKET_EXTENSIONS @@ -729,27 +734,39 @@ CHIP_ERROR UDPEndPointImplSockets::SetMulticastLoopback(IPVersion aIPVersion, bo CHIP_ERROR UDPEndPointImplSockets::IPv4JoinLeaveMulticastGroupImpl(InterfaceId aInterfaceId, const IPAddress & aAddress, bool join) { - IPAddress lInterfaceAddress; - bool lInterfaceAddressFound = false; + in_addr interfaceAddr; - for (InterfaceAddressIterator lAddressIterator; lAddressIterator.HasCurrent(); lAddressIterator.Next()) + if (aInterfaceId.IsPresent()) { - IPAddress lCurrentAddress; - if ((lAddressIterator.GetInterfaceId() == aInterfaceId) && (lAddressIterator.GetAddress(lCurrentAddress) == CHIP_NO_ERROR)) + IPAddress lInterfaceAddress; + bool lInterfaceAddressFound = false; + + for (InterfaceAddressIterator lAddressIterator; lAddressIterator.HasCurrent(); lAddressIterator.Next()) { - if (lCurrentAddress.IsIPv4()) + IPAddress lCurrentAddress; + if ((lAddressIterator.GetInterfaceId() == aInterfaceId) && + (lAddressIterator.GetAddress(lCurrentAddress) == CHIP_NO_ERROR)) { - lInterfaceAddressFound = true; - lInterfaceAddress = lCurrentAddress; - break; + if (lCurrentAddress.IsIPv4()) + { + lInterfaceAddressFound = true; + lInterfaceAddress = lCurrentAddress; + break; + } } } + VerifyOrReturnError(lInterfaceAddressFound, INET_ERROR_ADDRESS_NOT_FOUND); + + interfaceAddr = lInterfaceAddress.ToIPv4(); + } + else + { + interfaceAddr.s_addr = htonl(INADDR_ANY); } - VerifyOrReturnError(lInterfaceAddressFound, INET_ERROR_ADDRESS_NOT_FOUND); struct ip_mreq lMulticastRequest; memset(&lMulticastRequest, 0, sizeof(lMulticastRequest)); - lMulticastRequest.imr_interface = lInterfaceAddress.ToIPv4(); + lMulticastRequest.imr_interface = interfaceAddr; lMulticastRequest.imr_multiaddr = aAddress.ToIPv4(); const int command = join ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP; @@ -773,6 +790,62 @@ CHIP_ERROR UDPEndPointImplSockets::IPv6JoinLeaveMulticastGroupImpl(InterfaceId a #endif // CHIP_SYSTEM_CONFIG_USE_PLATFORM_MULTICAST_API #ifdef IPV6_MULTICAST_IMPLEMENTED + if (!aInterfaceId.IsPresent()) + { + // Do it on all the viable interfaces. + bool interfaceFound = false; + + InterfaceIterator interfaceIt; + while (interfaceIt.Next()) + { + if (!interfaceIt.SupportsMulticast() || !interfaceIt.IsUp()) + { + continue; + } + + InterfaceId interfaceId = interfaceIt.GetInterfaceId(); + + IPAddress ifAddr; + if (interfaceId.GetLinkLocalAddr(&ifAddr) != CHIP_NO_ERROR) + { + continue; + } + + if (ifAddr.Type() != IPAddressType::kIPv6) + { + // Not the right sort of interface. + continue; + } + + interfaceFound = true; + + char ifName[InterfaceId::kMaxIfNameLength]; + interfaceIt.GetInterfaceName(ifName, sizeof(ifName)); + + // Ignore errors here, except for logging, because we expect some of + // these interfaces to not work, and some (e.g. loopback) to always + // work. + CHIP_ERROR err = IPv6JoinLeaveMulticastGroupImpl(interfaceId, aAddress, join); + if (err == CHIP_NO_ERROR) + { + ChipLogDetail(Inet, " %s multicast group on interface %s", (join ? "Joined" : "Left"), ifName); + } + else + { + ChipLogError(Inet, " Failed to %s multicast group on interface %s", (join ? "join" : "leave"), ifName); + } + } + + if (interfaceFound) + { + // Assume we're good. + return CHIP_NO_ERROR; + } + + // Else go ahead and try to work with the default interface. + ChipLogError(Inet, "No valid IPv6 multicast interface found"); + } + const InterfaceId::PlatformType lIfIndex = aInterfaceId.GetPlatformInterface(); struct ipv6_mreq lMulticastRequest;