[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: ai_flags in calls to getaddrinfo

From: Robin Tarsiger
Subject: Re: ai_flags in calls to getaddrinfo
Date: Fri, 1 Jan 2021 18:19:16 -0600
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.6.0

Eli Zaretskii wrote:
>> I notice that EAI_NODATA isn't mentioned in the Windows docs[1],
> Yes, because Windows has its own codes for socket-related errors.
> Look for WSANO_DATA.  I said "EAI_NODATA" to avoid using Windows
> specific terminology that people might be unfamiliar with.

Ah, I see. In any case it does seem like the same thing.

>>  2. If a program requests a name that exists and has addresses of
>>     some families (such as IPv4 addresses), but the program has
>>     specifically requested another family (such as IPv6)?
> The address returned when AI_V4MAPPED is used is a valid IPv6 address,
> isn't it?  That is, it can be used in IPv6 connections, and will allow
> such connections to work as intended, right?

Basically no; only yes under a very constrained perspective. The socket
mechanism on an OS that supports this compatibility mechanism will do
translation behind the scenes, but that's the extent of it. You should
never see these on the wire, and they are not routable over the IPv6
Internet. If the local host is not running an IPv4 stack, or does not
have an appropriate IPv4 address, they cannot be communicated with from
that host. Any actual IPv6 connectivity on the local host is irrelevant.
They are, in fact, IPv4 addresses in disguise. That's _all_ they are.

Is there a case where an application would ask for the IPv6 family
specifically _without_ caring about the above? Because if it mainly
cares about being able to pass the address into connect(), then it
should just be family-agnostic with a nil FAMILY, and potentially use
locally-available connectivity hints if some mechanism for them is
there, no? (And make-network-process already internalizes the name
lookup.) And if it wants addresses of either family but to specifically
prefer IPv6 addresses if they exist (which is basically what AI_V4MAPPED
does), it can rearrange the list.

>> To put it differently: from my perspective, the main use for AI_V4MAPPED
>> is when there is no IPv4-handling code path at all, and all IPv4 addresses
>> are routed through the "IPv6" path as compatibility-mapped, which can
>> save some complexity and hassle elsewhere.
> > Isn't that the common use case?

Where would you expect to see an IPv6-only code path in an elisp program?
In C, this happens when porting programs out of the IPv4 world, largely
due to type rigidity in C, and then lingers. But in elisp, treating addresses
from families not recognized by the application as opaque is easy, because
of the boxing and dynamic typing; you just don't introspect into them in
the first place. And if the application _does_ want to introspect into them,
then it will want to handle IPv4 addresses by IPv4 standards, at which point
having them represented in native form is better.

(See RFC4038 section 4.2 for a more authoritative description, in the
context of the surrounding section 4 about transition mechanisms.)

Having _both_ v4-mapped addresses and true multi-family address
representation in the same place is the worst of both worlds. Now
you have to handle both families _and_ you have to handle two different
representations for the same IPv4 address. This may not always be
possible to avoid, but we can avoid creating the issue where it didn't
previously exist.

For server sockets it is likely a different trade-off, though even then
I would say that if the Emacs implementation chooses to use a single
"IPv6"-with-dual-stack-underneath socket for C-side simplicity (which
would be reasonable---this in fact would fall into the exact "porting
C code out of the IPv4 world" case), it should then do the detection of
actually-IPv4 addresses and convert them as IPv4 before they hit
the elisp layer. (I haven't checked whether it does this.)

> Lisp programs that want to be so strict will have no problem
> identifying "fake" IPv6 addresses and filtering them out, I think.

This is basically true, but per above it is a needless cost.

>>> On the
>>> system in question, using the patched code and nil as FAMILY in the
>>> network-lookup-address-info yields the expected result, including,
>>> surprisingly, what looks like a valid IPv6 address, even though
>>> specifying 'ipv6 for FAMILY does indeed return a compatibility-hacked
>>> IPv4 address.
>> What happens if you pass nil for FAMILY but without the AI_V4MAPPED
>> patch, on that system?
> I get only an IPv4 address.

Okay, that is interesting. I wonder if the AI_ALL flag on Windows is
overriding some equivalent of AI_ADDRCONFIG, now. I'll see if I can
check this from the C level on my machines too.

Incidentally, distinguishing NXDOMAIN ("name does not exist at all")
from "nothing in any recognized address family" may not be (portably,
reliably) doable with getaddrinfo AFAIK (though the distinction this
would have to the application from the perspective of a "look up
addresses" API is unclear to start with), and distinguishing
"nothing in this address family, maybe-or-maybe-not anything in
others" when an address family _is_ provided may also not be. So
having a warning come from network-lookup-address-info in case of
all successful lookups of nothing is a bit fraught to start with,
but since it is the existing behavior, I think it may be necessary
to look at how existing elisp code uses this function to figure
out what's expected.

The lookup-google test is sort of asking to fail on locked-down
resolver configurations in its current form, too... and I wonder
if lookup-family-specification may want to be separated into
"works for known" and "doesn't work for unknown" and/or use
localhost instead...


reply via email to

[Prev in Thread] Current Thread [Next in Thread]