mirror of
https://github.com/zeromq/libzmq.git
synced 2025-07-04 01:27:14 +02:00
Update resolve_ip_interface and resolve_ip_hostname with ipv4only parameter.
Signed-off-by: Steven McCoy <steven.mccoy@miru.hk> Signed-off-by: Martin Sustrik <sustrik@250bpm.com>
This commit is contained in:
parent
9184a54f64
commit
c27b9ac7de
50
src/ip.cpp
50
src/ip.cpp
@ -213,7 +213,7 @@ static int resolve_nic_name (struct sockaddr* addr_, char const *interface_,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
int zmq::resolve_ip_interface (sockaddr_storage* addr_, socklen_t *addr_len_,
|
int zmq::resolve_ip_interface (sockaddr_storage* addr_, socklen_t *addr_len_,
|
||||||
char const *interface_)
|
char const *interface_, bool ipv4only_)
|
||||||
{
|
{
|
||||||
// Find the ':' at end that separates NIC name from service.
|
// Find the ':' at end that separates NIC name from service.
|
||||||
const char *delimiter = strrchr (interface_, ':');
|
const char *delimiter = strrchr (interface_, ':');
|
||||||
@ -241,18 +241,27 @@ int zmq::resolve_ip_interface (sockaddr_storage* addr_, socklen_t *addr_len_,
|
|||||||
sockaddr *out_addr = (sockaddr *) &ss;
|
sockaddr *out_addr = (sockaddr *) &ss;
|
||||||
socklen_t out_addrlen;
|
socklen_t out_addrlen;
|
||||||
|
|
||||||
// Initialise IPv4-format family/port.
|
// Initialise IP-format family/port and populate temporary output pointers
|
||||||
|
// with the address.
|
||||||
|
if (ipv4only_) {
|
||||||
sockaddr_in ip4_addr;
|
sockaddr_in ip4_addr;
|
||||||
memset (&ip4_addr, 0, sizeof (ip4_addr));
|
memset (&ip4_addr, 0, sizeof (ip4_addr));
|
||||||
ip4_addr.sin_family = AF_INET;
|
ip4_addr.sin_family = AF_INET;
|
||||||
ip4_addr.sin_port = sin_port;
|
ip4_addr.sin_port = sin_port;
|
||||||
ip4_addr.sin_addr.s_addr = htonl (INADDR_ANY);
|
ip4_addr.sin_addr.s_addr = htonl (INADDR_ANY);
|
||||||
|
|
||||||
// Populate temporary output pointers with ip4_addr.
|
|
||||||
out_addrlen = (socklen_t) sizeof (ip4_addr);
|
out_addrlen = (socklen_t) sizeof (ip4_addr);
|
||||||
memcpy (out_addr, &ip4_addr, out_addrlen);
|
memcpy (out_addr, &ip4_addr, out_addrlen);
|
||||||
|
} else {
|
||||||
|
sockaddr_in6 ip6_addr;
|
||||||
|
memset (&ip6_addr, 0, sizeof (ip6_addr));
|
||||||
|
ip6_addr.sin6_family = AF_INET6;
|
||||||
|
ip6_addr.sin6_port = sin_port;
|
||||||
|
memcpy (&ip6_addr.sin6_addr, &in6addr_any, sizeof (in6addr_any));
|
||||||
|
out_addrlen = (socklen_t) sizeof (ip6_addr);
|
||||||
|
memcpy (out_addr, &ip6_addr, out_addrlen);
|
||||||
|
}
|
||||||
|
|
||||||
// * resolves to INADDR_ANY.
|
// * resolves to INADDR_ANY or in6addr_any.
|
||||||
if (iface.compare("*") == 0) {
|
if (iface.compare("*") == 0) {
|
||||||
zmq_assert (out_addrlen <= (socklen_t) sizeof (*addr_));
|
zmq_assert (out_addrlen <= (socklen_t) sizeof (*addr_));
|
||||||
memcpy (addr_, out_addr, out_addrlen);
|
memcpy (addr_, out_addr, out_addrlen);
|
||||||
@ -261,7 +270,7 @@ int zmq::resolve_ip_interface (sockaddr_storage* addr_, socklen_t *addr_len_,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Try to resolve the string as a NIC name.
|
// Try to resolve the string as a NIC name.
|
||||||
int rc = resolve_nic_name (out_addr, iface.c_str(), true);
|
int rc = resolve_nic_name (out_addr, iface.c_str(), ipv4only_);
|
||||||
if (rc != 0 && errno != ENODEV)
|
if (rc != 0 && errno != ENODEV)
|
||||||
return rc;
|
return rc;
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
@ -281,8 +290,9 @@ int zmq::resolve_ip_interface (sockaddr_storage* addr_, socklen_t *addr_len_,
|
|||||||
#endif
|
#endif
|
||||||
memset (&req, 0, sizeof (req));
|
memset (&req, 0, sizeof (req));
|
||||||
|
|
||||||
// We only support IPv4 addresses for now.
|
// Choose IPv4 or IPv6 protocol family. Note that IPv6 allows for
|
||||||
req.ai_family = AF_INET;
|
// IPv4-in-IPv6 addresses.
|
||||||
|
req.ai_family = ipv4only_ ? AF_INET : AF_INET6;
|
||||||
|
|
||||||
// Arbitrary, not used in the output, but avoids duplicate results.
|
// Arbitrary, not used in the output, but avoids duplicate results.
|
||||||
req.ai_socktype = SOCK_STREAM;
|
req.ai_socktype = SOCK_STREAM;
|
||||||
@ -291,6 +301,15 @@ int zmq::resolve_ip_interface (sockaddr_storage* addr_, socklen_t *addr_len_,
|
|||||||
// service-name irregularity due to indeterminate socktype.
|
// service-name irregularity due to indeterminate socktype.
|
||||||
req.ai_flags = AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV;
|
req.ai_flags = AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV;
|
||||||
|
|
||||||
|
#ifndef ZMQ_HAVE_WINDOWS
|
||||||
|
// Windows by default maps IPv4 addresses into IPv6. In this API we only
|
||||||
|
// require IPv4-mapped addresses when no native IPv6 interfaces are
|
||||||
|
// available (~AI_ALL). This saves an additional DNS roundtrip for IPv4
|
||||||
|
// addresses.
|
||||||
|
if (req.ai_family == AF_INET6)
|
||||||
|
req.ai_flags |= AI_V4MAPPED;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Resolve the literal address. Some of the error info is lost in case
|
// Resolve the literal address. Some of the error info is lost in case
|
||||||
// of error, however, there's no way to report EAI errors via errno.
|
// of error, however, there's no way to report EAI errors via errno.
|
||||||
rc = getaddrinfo (iface.c_str(), service.c_str(), &req, &res);
|
rc = getaddrinfo (iface.c_str(), service.c_str(), &req, &res);
|
||||||
@ -312,7 +331,7 @@ int zmq::resolve_ip_interface (sockaddr_storage* addr_, socklen_t *addr_len_,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int zmq::resolve_ip_hostname (sockaddr_storage *addr_, socklen_t *addr_len_,
|
int zmq::resolve_ip_hostname (sockaddr_storage *addr_, socklen_t *addr_len_,
|
||||||
const char *hostname_)
|
const char *hostname_, bool ipv4only_)
|
||||||
{
|
{
|
||||||
// Find the ':' that separates hostname name from service.
|
// Find the ':' that separates hostname name from service.
|
||||||
const char *delimiter = strrchr (hostname_, ':');
|
const char *delimiter = strrchr (hostname_, ':');
|
||||||
@ -329,8 +348,9 @@ int zmq::resolve_ip_hostname (sockaddr_storage *addr_, socklen_t *addr_len_,
|
|||||||
addrinfo req;
|
addrinfo req;
|
||||||
memset (&req, 0, sizeof (req));
|
memset (&req, 0, sizeof (req));
|
||||||
|
|
||||||
// We only support IPv4 addresses for now.
|
// Choose IPv4 or IPv6 protocol family. Note that IPv6 allows for
|
||||||
req.ai_family = AF_INET;
|
// IPv4-in-IPv6 addresses.
|
||||||
|
req.ai_family = ipv4only_ ? AF_INET : AF_INET6;
|
||||||
|
|
||||||
// Need to choose one to avoid duplicate results from getaddrinfo() - this
|
// Need to choose one to avoid duplicate results from getaddrinfo() - this
|
||||||
// doesn't really matter, since it's not included in the addr-output.
|
// doesn't really matter, since it's not included in the addr-output.
|
||||||
@ -339,6 +359,14 @@ int zmq::resolve_ip_hostname (sockaddr_storage *addr_, socklen_t *addr_len_,
|
|||||||
// Avoid named services due to unclear socktype.
|
// Avoid named services due to unclear socktype.
|
||||||
req.ai_flags = AI_NUMERICSERV;
|
req.ai_flags = AI_NUMERICSERV;
|
||||||
|
|
||||||
|
#ifndef ZMQ_HAVE_WINDOWS
|
||||||
|
// Windows by default maps IPv4 addresses into IPv6. In this API we only
|
||||||
|
// require IPv4-mapped addresses when no native IPv6 interfaces are
|
||||||
|
// available. This saves an additional DNS roundtrip for IPv4 addresses.
|
||||||
|
if (req.ai_family == AF_INET6)
|
||||||
|
req.ai_flags |= AI_V4MAPPED;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Resolve host name. Some of the error info is lost in case of error,
|
// Resolve host name. Some of the error info is lost in case of error,
|
||||||
// however, there's no way to report EAI errors via errno.
|
// however, there's no way to report EAI errors via errno.
|
||||||
addrinfo *res;
|
addrinfo *res;
|
||||||
|
@ -51,12 +51,12 @@ namespace zmq
|
|||||||
// Resolves network interface name in <nic-name>:<port> format. Symbol "*"
|
// Resolves network interface name in <nic-name>:<port> format. Symbol "*"
|
||||||
// (asterisk) resolves to INADDR_ANY (all network interfaces).
|
// (asterisk) resolves to INADDR_ANY (all network interfaces).
|
||||||
int resolve_ip_interface (sockaddr_storage *addr_, socklen_t *addr_len_,
|
int resolve_ip_interface (sockaddr_storage *addr_, socklen_t *addr_len_,
|
||||||
char const *interface_);
|
char const *interface_, bool ipv4only_);
|
||||||
|
|
||||||
// This function resolves a string in <hostname>:<port-number> format.
|
// This function resolves a string in <hostname>:<port-number> format.
|
||||||
// Hostname can be either the name of the host or its IP address.
|
// Hostname can be either the name of the host or its IP address.
|
||||||
int resolve_ip_hostname (sockaddr_storage *addr_, socklen_t *addr_len_,
|
int resolve_ip_hostname (sockaddr_storage *addr_, socklen_t *addr_len_,
|
||||||
const char *hostname_);
|
const char *hostname_, bool ipv4only_);
|
||||||
|
|
||||||
// This function sets up address for UNIX domain transport.
|
// This function sets up address for UNIX domain transport.
|
||||||
int resolve_local_path (sockaddr_storage *addr_, socklen_t *addr_len_,
|
int resolve_local_path (sockaddr_storage *addr_, socklen_t *addr_len_,
|
||||||
|
@ -179,7 +179,7 @@ int zmq::tcp_connecter_t::get_new_reconnect_ivl ()
|
|||||||
|
|
||||||
int zmq::tcp_connecter_t::set_address (const char *addr_)
|
int zmq::tcp_connecter_t::set_address (const char *addr_)
|
||||||
{
|
{
|
||||||
return resolve_ip_hostname (&addr, &addr_len, addr_);
|
return resolve_ip_hostname (&addr, &addr_len, addr_, options.ipv4only);
|
||||||
}
|
}
|
||||||
|
|
||||||
int zmq::tcp_connecter_t::open ()
|
int zmq::tcp_connecter_t::open ()
|
||||||
|
@ -123,7 +123,7 @@ void zmq::tcp_listener_t::close ()
|
|||||||
int zmq::tcp_listener_t::set_address (const char *addr_)
|
int zmq::tcp_listener_t::set_address (const char *addr_)
|
||||||
{
|
{
|
||||||
// Convert the interface into sockaddr_in structure.
|
// Convert the interface into sockaddr_in structure.
|
||||||
int rc = resolve_ip_interface (&addr, &addr_len, addr_);
|
int rc = resolve_ip_interface (&addr, &addr_len, addr_, options.ipv4only);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -92,7 +92,8 @@ int zmq::vtcp_connecter_t::set_address (const char *addr_)
|
|||||||
addr_str += ":9220";
|
addr_str += ":9220";
|
||||||
std::string subport_str (delimiter + 1);
|
std::string subport_str (delimiter + 1);
|
||||||
subport = (vtcp_subport_t) atoi (subport_str.c_str ());
|
subport = (vtcp_subport_t) atoi (subport_str.c_str ());
|
||||||
int rc = resolve_ip_hostname (&addr, &addr_len, addr_str.c_str ());
|
int rc = resolve_ip_hostname (&addr, &addr_len, addr_str.c_str (),
|
||||||
|
true);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -100,7 +101,8 @@ int zmq::vtcp_connecter_t::set_address (const char *addr_)
|
|||||||
std::string addr_str (addr_, delimiter - addr_);
|
std::string addr_str (addr_, delimiter - addr_);
|
||||||
std::string subport_str (delimiter + 1);
|
std::string subport_str (delimiter + 1);
|
||||||
subport = (vtcp_subport_t) atoi (subport_str.c_str ());
|
subport = (vtcp_subport_t) atoi (subport_str.c_str ());
|
||||||
int rc = resolve_ip_hostname (&addr, &addr_len, addr_str.c_str ());
|
int rc = resolve_ip_hostname (&addr, &addr_len, addr_str.c_str (),
|
||||||
|
true);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user