From 6f7f3cf529cd559683459f86b3af139b42f89cd2 Mon Sep 17 00:00:00 2001 From: NoAnyLove Date: Sun, 12 Oct 2025 20:21:21 -0500 Subject: [PATCH 1/3] Fix dish socket multicast bind issue --- src/udp_engine.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/udp_engine.cpp b/src/udp_engine.cpp index fe0a536a6e..4a90fff909 100644 --- a/src/udp_engine.cpp +++ b/src/udp_engine.cpp @@ -133,7 +133,6 @@ void zmq::udp_engine_t::plug (io_thread_t *io_thread_, session_base_t *session_) rc = rc | set_udp_reuse_address (_fd, true); const ip_addr_t *bind_addr = udp_addr->bind_addr (); - ip_addr_t any = ip_addr_t::any (bind_addr->family ()); const ip_addr_t *real_bind_addr; const bool multicast = udp_addr->is_mcast (); @@ -143,11 +142,10 @@ void zmq::udp_engine_t::plug (io_thread_t *io_thread_, session_base_t *session_) // one port as all ports should receive the message rc = rc | set_udp_reuse_port (_fd, true); - // In multicast we should bind ANY and use the mreq struct to - // specify the interface - any.set_port (bind_addr->port ()); + // In multicast we should bind the target address and use the + // mreq struct to specify the interface - real_bind_addr = &any; + real_bind_addr = udp_addr->target_addr (); } else { real_bind_addr = bind_addr; } From 5610f471439430adc04d43a6504feb1aac473bb3 Mon Sep 17 00:00:00 2001 From: NoAnyLove Date: Mon, 13 Oct 2025 17:03:09 -0500 Subject: [PATCH 2/3] Try to fix IPv6 multicast --- src/udp_address.cpp | 10 ++++++---- tests/test_radio_dish.cpp | 2 +- unittests/unittest_udp_address.cpp | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/udp_address.cpp b/src/udp_address.cpp index 6a5c604e15..71b482b2d8 100644 --- a/src/udp_address.cpp +++ b/src/udp_address.cpp @@ -125,7 +125,6 @@ int zmq::udp_address_t::resolve (const char *name_, bool bind_, bool ipv6_) if (_is_multicast || !bind_) { _bind_address = ip_addr_t::any (_target_address.family ()); _bind_address.set_port (port); - _bind_interface = 0; } else { // If we were asked for a bind socket and the address // provided was not multicast then it was really meant as @@ -141,9 +140,12 @@ int zmq::udp_address_t::resolve (const char *name_, bool bind_, bool ipv6_) // For IPv6 multicast we *must* have an interface index since we can't // bind by address. - if (ipv6_ && _is_multicast && _bind_interface < 0) { - errno = ENODEV; - return -1; + if (ipv6_ && _is_multicast && bind_) { + if (_bind_interface < 0) { + errno = ENODEV; + return -1; + } + _target_address.ipv6.sin6_scope_id = _bind_interface; } return 0; diff --git a/tests/test_radio_dish.cpp b/tests/test_radio_dish.cpp index b84b1b1448..2e5ead9d40 100644 --- a/tests/test_radio_dish.cpp +++ b/tests/test_radio_dish.cpp @@ -261,7 +261,7 @@ MAKE_TEST_V4V6 (test_radio_dish_udp) static const char *mcast_url (int ipv6_) { if (ipv6_) { - return "udp://[" MCAST_IPV6 "]:5555"; + return "udp://eth0;[" MCAST_IPV6 "]:5555"; } return "udp://" MCAST_IPV4 ":5555"; } diff --git a/unittests/unittest_udp_address.cpp b/unittests/unittest_udp_address.cpp index c26605006f..c5a3d169b9 100644 --- a/unittests/unittest_udp_address.cpp +++ b/unittests/unittest_udp_address.cpp @@ -232,7 +232,7 @@ static void test_resolve_ipv6_mcast_src_connect () } zmq::udp_address_t addr; - int rc = addr.resolve ("[1:2:3::4];[ff01::1]:5555", false, true); + int rc = addr.resolve ("[1:2:3::4];[ff01::1]:5555", true, true); // For the time being this fails because we only support binding multicast // by interface name, not interface IP From 5366c37fb4902e03f99208326c6c6979030bbdb0 Mon Sep 17 00:00:00 2001 From: NoAnyLove Date: Mon, 13 Oct 2025 18:14:11 -0500 Subject: [PATCH 3/3] Try to fix test --- unittests/unittest_udp_address.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/unittests/unittest_udp_address.cpp b/unittests/unittest_udp_address.cpp index c5a3d169b9..3b94103ce7 100644 --- a/unittests/unittest_udp_address.cpp +++ b/unittests/unittest_udp_address.cpp @@ -23,7 +23,8 @@ static void test_resolve (bool bind_, const char *target_addr_, uint16_t expected_port_, const char *bind_addr_, - bool multicast_) + bool multicast_, + uint16_t expected_zone = 0) { if (family_ == AF_INET6 && !is_ipv6_available ()) { TEST_IGNORE_MESSAGE ("ipv6 is not available"); @@ -53,7 +54,7 @@ static void test_resolve (bool bind_, } validate_address (family_, addr.target_addr (), target_addr_, - expected_port_); + expected_port_, expected_zone); validate_address (family_, addr.bind_addr (), bind_addr_, expected_port_); } @@ -62,10 +63,11 @@ static void test_resolve_bind (int family_, const char *dest_addr_, uint16_t expected_port_ = 0, const char *bind_addr_ = NULL, - bool multicast_ = false) + bool multicast_ = false, + uint16_t expected_zone = 0) { test_resolve (true, family_, name_, dest_addr_, expected_port_, bind_addr_, - multicast_); + multicast_, expected_zone); } static void test_resolve_connect (int family_, @@ -172,7 +174,7 @@ static void test_resolve_ipv4_bind_mcast () static void test_resolve_ipv6_bind_mcast () { - test_resolve_bind (AF_INET6, "[ff00::1]:1234", "ff00::1", 1234, "::", true); + test_resolve_bind (AF_INET6, "eth0;[ff00::1]:1234", "ff00::1", 1234, "fe80::", true, 2); } static void test_resolve_ipv4_connect_mcast ()