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/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; } 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..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 () @@ -232,7 +234,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