Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/udp_address.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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_) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interface index is only needed if it's IPv6 multicast and the socket needs to perform bind(), i.e., the DISH socket.

if (_bind_interface < 0) {
errno = ENODEV;
return -1;
}
_target_address.ipv6.sin6_scope_id = _bind_interface;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To bind on multicast group in IPv6, it requires to set the scope id to the network interface index, otherwise it will fail.

}

return 0;
Expand Down
8 changes: 3 additions & 5 deletions src/udp_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 ();
Expand All @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion tests/test_radio_dish.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the DISH socket now must specify the network interface for bind with this change.

I'm concerned about hard-coding the network interface name here, as it might break on other OS or if the host use different names. Not sure if there is any better choice.

Besides, it seems we cannot bind on lo, as it will result Network is unreachable on my box (not sue if it's a common case or just on my box).

}
return "udp://" MCAST_IPV4 ":5555";
}
Expand Down
14 changes: 8 additions & 6 deletions unittests/unittest_udp_address.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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_);
}

Expand All @@ -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_,
Expand Down Expand Up @@ -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 ()
Expand Down Expand Up @@ -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);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change bind from false to true. It won't trigger the ENODEV error when bind is false, as RADIO socket does not require the interface for bind.


// For the time being this fails because we only support binding multicast
// by interface name, not interface IP
Expand Down
Loading