Commit 7cfa9335 authored by Sathish Yenna's avatar Sathish Yenna

Add missing support for IPv6 link local addresses (which include % followed by the interface name)

parent 6eeef5eb
...@@ -796,6 +796,8 @@ int zmq::socket_base_t::connect (const char *addr_) ...@@ -796,6 +796,8 @@ int zmq::socket_base_t::connect (const char *addr_)
// Do some basic sanity checks on tcp:// address syntax // Do some basic sanity checks on tcp:// address syntax
// - hostname starts with digit or letter, with embedded '-' or '.' // - hostname starts with digit or letter, with embedded '-' or '.'
// - IPv6 address may contain hex chars and colons. // - IPv6 address may contain hex chars and colons.
// - IPv6 link local address may contain % followed by interface name / zone_id
// (Reference: https://tools.ietf.org/html/rfc4007)
// - IPv4 address may contain decimal digits and dots. // - IPv4 address may contain decimal digits and dots.
// - Address must end in ":port" where port is *, or numeric // - Address must end in ":port" where port is *, or numeric
// - Address may contain two parts separated by ':' // - Address may contain two parts separated by ':'
...@@ -806,8 +808,8 @@ int zmq::socket_base_t::connect (const char *addr_) ...@@ -806,8 +808,8 @@ int zmq::socket_base_t::connect (const char *addr_)
check++; check++;
while (isalnum (*check) while (isalnum (*check)
|| isxdigit (*check) || isxdigit (*check)
|| *check == '.' || *check == '-' || *check == ':'|| *check == ';' || *check == '.' || *check == '-' || *check == ':' || *check == '%'
|| *check == ']') || *check == ';' || *check == ']')
check++; check++;
} }
// Assume the worst, now look for success // Assume the worst, now look for success
......
...@@ -162,6 +162,7 @@ int zmq::tcp_address_t::resolve_nic_name (const char *nic_, bool ipv6_, bool is_ ...@@ -162,6 +162,7 @@ int zmq::tcp_address_t::resolve_nic_name (const char *nic_, bool ipv6_, bool is_
&& defined ZMQ_HAVE_IFADDRS) && defined ZMQ_HAVE_IFADDRS)
#include <ifaddrs.h> #include <ifaddrs.h>
#include <net/if.h>
// On these platforms, network interface name can be queried // On these platforms, network interface name can be queried
// using getifaddrs function. // using getifaddrs function.
...@@ -429,6 +430,23 @@ int zmq::tcp_address_t::resolve (const char *name_, bool local_, bool ipv6_, boo ...@@ -429,6 +430,23 @@ int zmq::tcp_address_t::resolve (const char *name_, bool local_, bool ipv6_, boo
addr_str [addr_str.size () - 1] == ']') addr_str [addr_str.size () - 1] == ']')
addr_str = addr_str.substr (1, addr_str.size () - 2); addr_str = addr_str.substr (1, addr_str.size () - 2);
// Test the '%' to know if we have an interface name / zone_id in the address
// Reference: https://tools.ietf.org/html/rfc4007
std::size_t pos = addr_str.rfind("%");
uint32_t zone_id = 0;
if (pos != std::string::npos) {
std::string if_str = addr_str.substr(pos + 1);
addr_str = addr_str.substr(0, pos);
if (isalpha (if_str.at (0)))
zone_id = if_nametoindex(if_str.c_str());
else
zone_id = (uint32_t) atoi (if_str.c_str ());
if (zone_id == 0) {
errno = EINVAL;
return -1;
}
}
// Allow 0 specifically, to detect invalid port error in atoi if not // Allow 0 specifically, to detect invalid port error in atoi if not
uint16_t port; uint16_t port;
if (port_str == "*" || port_str == "0") if (port_str == "*" || port_str == "0")
...@@ -454,14 +472,18 @@ int zmq::tcp_address_t::resolve (const char *name_, bool local_, bool ipv6_, boo ...@@ -454,14 +472,18 @@ int zmq::tcp_address_t::resolve (const char *name_, bool local_, bool ipv6_, boo
// Set the port into the address structure. // Set the port into the address structure.
if (is_src_) { if (is_src_) {
if (source_address.generic.sa_family == AF_INET6) if (source_address.generic.sa_family == AF_INET6) {
source_address.ipv6.sin6_port = htons (port); source_address.ipv6.sin6_port = htons (port);
source_address.ipv6.sin6_scope_id = zone_id;
}
else else
source_address.ipv4.sin_port = htons (port); source_address.ipv4.sin_port = htons (port);
} }
else { else {
if (address.generic.sa_family == AF_INET6) if (address.generic.sa_family == AF_INET6) {
address.ipv6.sin6_port = htons (port); address.ipv6.sin6_port = htons (port);
address.ipv6.sin6_scope_id = zone_id;
}
else else
address.ipv4.sin_port = htons (port); address.ipv4.sin_port = htons (port);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment