From ef8b0c60fc0be90a4adccdb8df3536afdf7ae242 Mon Sep 17 00:00:00 2001 From: Boris Lytochkin Date: Sun, 9 Apr 2017 11:33:55 +0300 Subject: [PATCH] re-enable AI_V4MAPPED on FreeBSD & DragonFlyBSD Detect AI_V4MAPPED is not supported in getaddrinfo() on the fly and retry query. This issue was seen on ancient FreeBSD releases and current implementation does support this flag correctly. --- src/tcp_address.cpp | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/tcp_address.cpp b/src/tcp_address.cpp index 5ccb1178..7adb63db 100644 --- a/src/tcp_address.cpp +++ b/src/tcp_address.cpp @@ -448,12 +448,10 @@ int zmq::tcp_address_t::resolve_interface (const char *interface_, bool ipv6_, b // service-name irregularity due to indeterminate socktype. req.ai_flags = AI_PASSIVE | AI_NUMERICHOST; -#if defined AI_V4MAPPED && !defined ZMQ_HAVE_FREEBSD && !defined ZMQ_HAVE_DRAGONFLY +#if defined AI_V4MAPPED // 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. - // Note: While the AI_V4MAPPED flag is defined on FreeBSD system, - // it is not supported here. See libzmq issue #331. if (req.ai_family == AF_INET6) req.ai_flags |= AI_V4MAPPED; #endif @@ -463,6 +461,15 @@ int zmq::tcp_address_t::resolve_interface (const char *interface_, bool ipv6_, b rc = getaddrinfo(interface_, NULL, &req, &res); +#if defined AI_V4MAPPED + // Some OS do have AI_V4MAPPED defined but it is not supported in getaddrinfo() + // returning EAI_BADFLAGS. Detect this and retry + if (rc == EAI_BADFLAGS && (req.ai_flags & AI_V4MAPPED)) { + req.ai_flags &= ~AI_V4MAPPED; + rc = getaddrinfo(interface_, NULL, &req, &res); + } +#endif + #if defined ZMQ_HAVE_WINDOWS // Resolve specific case on Windows platform when using IPv4 address // with ZMQ_IPv6 socket option. @@ -509,12 +516,10 @@ int zmq::tcp_address_t::resolve_hostname (const char *hostname_, bool ipv6_, boo // doesn't really matter, since it's not included in the addr-output. req.ai_socktype = SOCK_STREAM; -#if defined AI_V4MAPPED && !defined ZMQ_HAVE_FREEBSD && !defined ZMQ_HAVE_DRAGONFLY +#if defined AI_V4MAPPED // 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. - // Note: While the AI_V4MAPPED flag is defined on FreeBSD system, - // it is not supported here. See libzmq issue #331. if (req.ai_family == AF_INET6) req.ai_flags |= AI_V4MAPPED; #endif @@ -526,7 +531,17 @@ int zmq::tcp_address_t::resolve_hostname (const char *hostname_, bool ipv6_, boo #else addrinfo *res; #endif - const int rc = getaddrinfo (hostname_, NULL, &req, &res); + int rc = getaddrinfo (hostname_, NULL, &req, &res); + +#if defined AI_V4MAPPED + // Some OS do have AI_V4MAPPED defined but it is not supported in getaddrinfo() + // returning EAI_BADFLAGS. Detect this and retry + if (rc == EAI_BADFLAGS && (req.ai_flags & AI_V4MAPPED)) { + req.ai_flags &= ~AI_V4MAPPED; + rc = getaddrinfo(hostname_, NULL, &req, &res); + } +#endif + if (rc) { switch (rc) { case EAI_MEMORY: