mirror of
https://github.com/zeromq/libzmq.git
synced 2024-12-29 00:32:34 +08: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
64
src/ip.cpp
64
src/ip.cpp
@ -213,7 +213,7 @@ static int resolve_nic_name (struct sockaddr* addr_, char const *interface_,
|
||||
#endif
|
||||
|
||||
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.
|
||||
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;
|
||||
socklen_t out_addrlen;
|
||||
|
||||
// Initialise IPv4-format family/port.
|
||||
sockaddr_in ip4_addr;
|
||||
memset (&ip4_addr, 0, sizeof (ip4_addr));
|
||||
ip4_addr.sin_family = AF_INET;
|
||||
ip4_addr.sin_port = sin_port;
|
||||
ip4_addr.sin_addr.s_addr = htonl (INADDR_ANY);
|
||||
// Initialise IP-format family/port and populate temporary output pointers
|
||||
// with the address.
|
||||
if (ipv4only_) {
|
||||
sockaddr_in ip4_addr;
|
||||
memset (&ip4_addr, 0, sizeof (ip4_addr));
|
||||
ip4_addr.sin_family = AF_INET;
|
||||
ip4_addr.sin_port = sin_port;
|
||||
ip4_addr.sin_addr.s_addr = htonl (INADDR_ANY);
|
||||
out_addrlen = (socklen_t) sizeof (ip4_addr);
|
||||
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);
|
||||
}
|
||||
|
||||
// Populate temporary output pointers with ip4_addr.
|
||||
out_addrlen = (socklen_t) sizeof (ip4_addr);
|
||||
memcpy (out_addr, &ip4_addr, out_addrlen);
|
||||
|
||||
// * resolves to INADDR_ANY.
|
||||
// * resolves to INADDR_ANY or in6addr_any.
|
||||
if (iface.compare("*") == 0) {
|
||||
zmq_assert (out_addrlen <= (socklen_t) sizeof (*addr_));
|
||||
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.
|
||||
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)
|
||||
return rc;
|
||||
if (rc == 0) {
|
||||
@ -281,8 +290,9 @@ int zmq::resolve_ip_interface (sockaddr_storage* addr_, socklen_t *addr_len_,
|
||||
#endif
|
||||
memset (&req, 0, sizeof (req));
|
||||
|
||||
// We only support IPv4 addresses for now.
|
||||
req.ai_family = AF_INET;
|
||||
// Choose IPv4 or IPv6 protocol family. Note that IPv6 allows for
|
||||
// IPv4-in-IPv6 addresses.
|
||||
req.ai_family = ipv4only_ ? AF_INET : AF_INET6;
|
||||
|
||||
// Arbitrary, not used in the output, but avoids duplicate results.
|
||||
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.
|
||||
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
|
||||
// of error, however, there's no way to report EAI errors via errno.
|
||||
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_,
|
||||
const char *hostname_)
|
||||
const char *hostname_, bool ipv4only_)
|
||||
{
|
||||
// Find the ':' that separates hostname name from service.
|
||||
const char *delimiter = strrchr (hostname_, ':');
|
||||
@ -329,8 +348,9 @@ int zmq::resolve_ip_hostname (sockaddr_storage *addr_, socklen_t *addr_len_,
|
||||
addrinfo req;
|
||||
memset (&req, 0, sizeof (req));
|
||||
|
||||
// We only support IPv4 addresses for now.
|
||||
req.ai_family = AF_INET;
|
||||
// Choose IPv4 or IPv6 protocol family. Note that IPv6 allows for
|
||||
// IPv4-in-IPv6 addresses.
|
||||
req.ai_family = ipv4only_ ? AF_INET : AF_INET6;
|
||||
|
||||
// Need to choose one to avoid duplicate results from getaddrinfo() - this
|
||||
// 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.
|
||||
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,
|
||||
// however, there's no way to report EAI errors via errno.
|
||||
addrinfo *res;
|
||||
|
@ -51,12 +51,12 @@ namespace zmq
|
||||
// Resolves network interface name in <nic-name>:<port> format. Symbol "*"
|
||||
// (asterisk) resolves to INADDR_ANY (all network interfaces).
|
||||
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.
|
||||
// Hostname can be either the name of the host or its IP address.
|
||||
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.
|
||||
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_)
|
||||
{
|
||||
return resolve_ip_hostname (&addr, &addr_len, addr_);
|
||||
return resolve_ip_hostname (&addr, &addr_len, addr_, options.ipv4only);
|
||||
}
|
||||
|
||||
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_)
|
||||
{
|
||||
// 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)
|
||||
return -1;
|
||||
|
||||
|
@ -92,7 +92,8 @@ int zmq::vtcp_connecter_t::set_address (const char *addr_)
|
||||
addr_str += ":9220";
|
||||
std::string subport_str (delimiter + 1);
|
||||
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)
|
||||
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 subport_str (delimiter + 1);
|
||||
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)
|
||||
return -1;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user