AI_V4MAPPED flag makes getaddrinfo fail with EAI_BADFLAGS on FreeBSD 8 and 9
Description
Environment
FreeBSD 9.0 (and 8., but probably not 7.)
Activity
Martin Hurton March 27, 2012 at 3:33 AM
Fixed by c2e9997a3c16d19a80fe5ca51760fd5eb9d7ff46.
Mark Martinec March 8, 2012 at 7:12 PM
> As for removing the AI_V4MAPPED flag, I guess it would mean that you
> won't be able to connect to IPv4 endpoint if ZMQ_IPV4ONLY is set to false.
True when using a host name, although one could still use a numeric
form like tcp://[::ffff:d.d.d.d]:n with ZMQ_IPV4ONLY at true, and
be able to connect a PF_INET6 socket to a PF_INET bound socket.
The issue is only with name resolving, not with sockets.
I think the need to manually flip ZMQ_IPV4ONLY depending on an
IP address family in use is utterly broken (an application needs
to parse socket specification to determine which address family
is required, and flip ZMQ_IPV4ONLY accordingly), but this is
probably a matter for another thread.
Martin Sustrik March 8, 2012 at 6:41 PM
Ah, I recall now. Ignore my previous comment.
The problem with resolving interface name is that there can be several scopes associated with the name (local, global etc.) There are some guideline RFCs about how to do that but it's not exactly easy.
As for removing the AI_V4MAPPED flag, I guess it would mean that you won't be able to connect to IPv4 endpoint if ZMQ_IPV4ONLY is set to false.
Mark Martinec March 8, 2012 at 6:24 PMEdited
> AFAIK the code doesn't resolve names into IPv6 addresses anyway. As for
> IPv6, the only thing that works reliably is using literal addresses.
Actually it does resolve a name: the getaddrinfo call takes care
of it. I just tried a zmq connect to some tcp:host.example.com:33333
where the host name resolved to both an A and an AAAA record.
Depending on the value of a ZMQ_IPV4ONLY socket option, the
connection went to an PF_INET or to an PF_INET6 socket respectively.
Unfortunately this does not work with a zmq bind, only works
with a connect. The bind fails regardless of the setting
of ZMQ_IPV4ONLY if the socket specification uses a (local)
host name, or even just a 'localhost'. Didn't investigate
further, but this is probably a topic for some other PR ticket.
(the bind does work however with 'tcp:*:n' or 'tcp:lo0:n',
obeying the ZMQ_IPV4ONLY)
> Thus, I believe, getting rid of AI_V4MAPPED flag would do no hurt.
Agreed. Please do so.
Martin Sustrik March 7, 2012 at 9:04 PM
AFAIK the code doesn't resolve names into IPv6 addresses anyway. As for IPv6, the only thing that works reliably is using literal addresses. Thus, I believe, getting rid of AI_V4MAPPED flag would do no hurt.
Trying to use zeromq-3.1.0 with IPv6 on a FreeBSD 9.0
(installed the devel/zmq-devel from ports).
Modifying a test program test_pair_tcp.cpp to bind and connect
to [::1] instead of 127.0.0.1, and turning off ZMQ_IPV4ONLY
like this:
int rc;
int ipv4only = 0;
rc = zmq_setsockopt(sb, ZMQ_IPV4ONLY, &ipv4only, sizeof (int));
assert (rc == 0);
rc = zmq_bind (sb, "tcp://[::1]:5560");
assert (rc == 0);
causes a failure:
Assertion failed: (rc == 0), function main,
file test_pair_tcp.cpp, line 40.
The problem is that zmq_bind, as well as the zmq_connect later on,
fails because getaddrinfo (as called from tcp_address.cpp) fails
and returns EAI_BADFLAGS when an AI_V4MAPPED flag is turned on
in req.ai_flags.
Seem like the AI_V4MAPPED flag was still documented but ignored
in FreeBSD 7., but is no longer supported in 8. and 9.0,
and was even removed from the getaddrinfo man page.
Removing both occurrences of:
req.ai_flags |= AI_V4MAPPED;
from tcp_address.cpp avoids the problem. Looks like
this will need to be handled by conditional compilation.
The constant AI_V4MAPPED (and AI_V4MAPPED_CFG) is still
declared in FreeBSD include file netdb.h, but apparently
fell out of grace and must not be specified.
Btw, even though FreeBSD is capable of accepting a PF_INET
connection on an PF_INET6 socket when a sysctl option
net.inet6.ip6.v6only is forced to off, this mode is not
a default. Things behave better when each protocol family
has its own dedicated socket.
My main issue here is to get ZMQ usable on an IPv6-only
host under FreeBSD, where a 127.0.0.1 does not even exist
on a loopback interface.