On Mon, Jan 17, 2022 at 05:45:58PM +0100, Laszlo Ersek wrote:
On 01/17/22 15:03, Richard W.M. Jones wrote:
> On Mon, Jan 17, 2022 at 02:51:49PM +0100, Laszlo Ersek wrote:
>> Hi,
>>
>> we do we have have AI_ADDRCONFIG in nbdkit, from historical commit
>> 999797badf48 ("Implement nbdkit server.", 2013-06-21)?
>>
>> It prevents nbdkit from binding ::1, either automatically (when -i is
>> not specified at all), or in response to a manual request ("-i ::1"):
>>
>> nbdkit: getaddrinfo: ::1: 32776: Address family for hostname not supported
>>
>> Based on the explanation in
>> <
https://bugzilla.redhat.com/show_bug.cgi?id=808147>, this behavior is
>> actually expected of getaddrinfo() when the host has no public IPv6
>> address configured.
>>
>> So I think it's wrong for nbdkit to use AI_ADDRCONFIG -- why restrict
>> nbdkit to binding public IPv6 addresses, and exclude ::1?
>>
>> The POSIX spec is terse on this:
>>
>>
https://pubs.opengroup.org/onlinepubs/9699919799/functions/freeaddrinfo.html
>>
>> If the AI_ADDRCONFIG flag is specified, IPv4 addresses shall be
>> returned only if an IPv4 address is configured on the local system,
>> [IP6] [Option Start] and IPv6 addresses shall be returned only if
>> an IPv6 address is configured on the local system. [Option End]
>>
>> Ulrich Drepper's IPv6 programming intro says:
>>
>>
https://akkadia.org/drepper/userapi-ipv6.html
>>
>> AI_ADDRCONFIG
>>
>> This flag should always be set when the returned values are needed
>> to make connections. If no specific protocol is requested, the Linux
>> getaddrinfo implementation returns both IPv4 and IPv6 addresses.
>> This can be less than optimal and is certainly slower if the machine
>> has only interfaces for one protocol. These days there are still
>> many systems which have no configured IPv6 address at all. In that
>> case using an IPv6 address will always fail. Worse, it might cause
>> the IPv6 kernel module to be loaded unnecessarily. Using
>> AI_ADDRCONFIG avoids this by determining what protocols are
>> supported by the currently configured network interfaces and return
>> only addresses for those.
>>
>> But in nbdkit's case, we're not making connections -- we're binding
>> interfaces and listening to / accepting connections. In
>> bind_tcpip_socket(), we have
>>
>> hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
>>
>> ... Here's another bit of info:
>>
>>
https://fedoraproject.org/wiki/QA/Networking/NameResolution/ADDRCONFIG
>>
>> Note under "Proposed solutions":
>>
>>
https://fedoraproject.org/wiki/QA/Networking/NameResolution/ADDRCONFIG#Pr...
>>
>> (1a) Remove all code that deals with AI_ADDRCONFIG, effectively
>> disabling it in the general getaddrinfo() code [then links a bugzilla
>> attachment for glibc, AFAICT!]
>>
>> (2a) Remove AI_ADDRCONFIG in all software that uses it. Deprecate
>> AI_ADDRCONFIG and prevent/reject modifications that add it to any software.
>>
>> My reason to ask about this: on my Fedora 34 host, which has no public
>> IPv6 address assigned, the connect-tcp6 test case always fails.
>
> I have noticed this test failing too, but it only failed on some
> machines and not on others and I was never able to get to the bottom
> of why this happened.
>
>> It is not possible for me to skip it (from the make check command
>> line), and this failure masks further test failures -- as it
>> prevents the rest of the test suite from running. I could create a
>> local branch that simply exits with code 77, but I think using
>> AI_ADDRCONFIG is wrong in the first place.
>
> Almost certainly it's there because it was copied from some other
> place and I didn't look into whether it was needed. It sounds from
> the description above as if it should not be there.
More digging:
(1) Re-read the problem statement (the intended use of AI_ADDRCONFIG) at
<
https://fedoraproject.org/wiki/QA/Networking/NameResolution/ADDRCONFIG>:
"AI_ADDRCONFIG was added in order to optimise DNS query traffic, so that
only useful addresses are queried for. In other words, an IPv4-only node
should not query its upstream resolver for IN AAAA resource records,
while an IPv6-only node should not query for IN A resource records. "
So the idea is to filter out IPv6 addresses from a name lookup result
set if the host will then be unable to make a connection to that
address, and vice versa for IPv4.
In nbdkit's case, we totally don't care about *connecting*. We want to
bind, and listen, and accept. So the only case that could fail for us
(and *surprise* the user at that is the following):
The "-i" option is specified with an FQDN option-argument (not an IPv4
or IPv6 address), AND the DNS response contains at least one IPvX
address, AND the host doing the querying does not have that particular
IPvX address associated with any interface.
This seems very far-fetched. The "-i" option is meant for specifying a
local interface's address, so the user would quite likely not use an
FQDN (needing an actual DNS query) for it. Second, even if the user
specified an FQDN (for example because they use some kind of DynDNS, and
using that name is convenient for them), then the FQDN that the user is
resolving in the Domain Name System, for referring to their own machine,
exists in the first place *because* the IPvX address under that FQDN is
associated with the machine.
So dropping the option should just be fine.
Dropping AI_ADDRCONFIG (not the -i option)?
(Note also that the Windows compat layer for nbdkit, from commit
a5112e9048b9e, simply calls AI_ADDRCONFIG an obscure feature for IPv6,
and simply defines that macro as zero.)
(2) This problem -- even the *bind*-side of the problem -- certainly
exists for other network-enabled applications, so what do they do?
The "netcat" utility now lives in nmap:
https://github.com/nmap/nmap/tree/master/ncat
Netcat does not use AI_ADDRCONFIG. (It does use getaddrinfo(), and,
optionally, AI_NUMERICHOST.) Instead, netcat exposes two options to the
user (both optional), "-4" and "-6". What these options do (AIUI) is
restrict the "ai_family" member, going into the getaddrinfo() call, from
AF_UNSPEC to AF_INET or AF_INET6.
In other words, in the above-described situation, where the DNS result
list may contain an IPvX address for which the user's host has no
support (for either connecting or binding), netcat chooses to fail, and
then the user becomes responsible for passing in -4 or -6 -- and then
getaddrinfo() will filter the DNS results based on "ai_family" (= user
preference), not *guesswork*.
Currently nbdkit sets af_family to zero, implicitly:
memset (&hints, 0, sizeof hints);
because of "/usr/include/bits/socket.h":
#define PF_UNSPEC 0 /* Unspecified. */
#define AF_UNSPEC PF_UNSPEC
So we should
- just drop AI_ADDRCONFIG from hints,
Certainly sounds like we should do this.
- and *IF* we think users like to pass such domain names with
"-i",
referring to their own machine, that cannot be resolved from /etc/hosts
but need actual DNS lookups, then we can add options like "-4" and
"-6".
(I consider this highly unlikely, as the long option name for "-i" is
"--ip-addr", which indicates it was never really meant for passing FQDNs.)
I'm happy to submit a patch; please advise me on whether we want -4 / -6
as well.
The intention behind the -i option was that you could specify local
interfaces that you want to listen on, eg. if you have virbr0, wifi0
and eth0, you might only want to listen on eth0 so you would specify
that (somehow - using the IP address? interface name?). I don't think
I've ever used this option in anger.
So I'm not greatly attached to how -i currently works, so whatever
would be sensible to make it work, if that involves adding -4/-6 or
not or something else.
Rich.
--
Richard Jones, Virtualization Group, Red Hat
http://people.redhat.com/~rjones
Read my programming and virtualization blog:
http://rwmj.wordpress.com
virt-builder quickly builds VMs from scratch
http://libguestfs.org/virt-builder.1.html