Bug 12398

Summary: getaddrinfo("127.0.0.1") and/or getaddrinfo("::1) may fail with AI_ADDRCONFIG
Product: glibc Reporter: Tore Anderson <tore>
Component: networkAssignee: Pavel Šimerda <psimerda>
Status: NEW ---    
Severity: normal CC: gaofeng, metadings, neleai, nick.jones, orion, phattanon, psimerda
Priority: P2 Flags: fweimer: security-
Version: 2.13   
Target Milestone: ---   
Host: Target:
Build: Last reconfirmed:
Attachments: a temporary fix to ignore the whole AI_ADDRCONFIG thing
Move AI_ADDRCONFIG into gaih_inet()

Description Tore Anderson 2011-01-13 20:03:04 UTC
getaddrinfo() will disregard the loopback addresses ::1 and 127.0.0.1 when attempting to figure out which address families are present on the host, when being called with the AI_ADDRCONFIG flag.

This makes a lot of sense when looking up an external hostname.  However, it makes very little sense when connecting to the hostname "localhost".  I've learned that the browser vendors will avoid using AI_ADDRCONFIG or do it while using workarounds for the localhost case, see for instance:

https://bugzilla.mozilla.org/show_bug.cgi?id=614526

Without such a workaround, connecting to a IPv4-only service listening on 127.0.0.1 using the hostname "localhost" will fail unless the machine also has external IPv4 connectivity.  Which is not what a user would expect, since the (lack of) external connectivity is irrelevant to the accessibility to the loopback interface.

Therefore, when looking up "localhost", the loopback addresses ::1 and 127.0.0.1 should not be ignored by getaddrinfo() when using AI_ADDRCONFIG

Tore
Comment 1 Pavel Šimerda 2012-07-27 14:11:30 UTC
The same applies to *all* link-local IPv6 addresses as well as link-local IPv4 addresses.

The same applies for all alternative names for localhost:

For example on Fedora:

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

People even use FQDNs for their localhost address to test their stuff without
network connection.

See also comments in bug 12377.
Comment 2 Pavel Šimerda 2012-07-28 10:12:58 UTC
Currently with glibc-2.15-51.fc17.x86_64 I can reproduce it with:

  hints.ai_family = AF_INET6;
  hints.ai_flags = AI_ADDRCONFIG; // and optional AI_V4MAPPED

I can no longer reproduce with SSH (possibly because of some updates
that affect SSH's networking, i don't know).

My feeling is that we should *never* discard literal IP adresses
based on AI_ADDRCONFIG. At least not unless we check against
*family* together with *scope* but even then it's very doubtful
to go directly against user's input.

As for names like 'localhost', 'localhost4' and various names you can
use for node-local and link-local addresses, I'm strictly against trying
to enumerate them as you cannot guess all possible names. Would
you for example check the suffix ".local" and treat the result as a
link-local FQDN? But it may be a global address also.

I actually don't believe in any checks that work with the name and
not the address. When you have the address, you can check it against
several rules to guess (and usually know) the scope.
Comment 3 Pavel Šimerda 2012-09-22 15:42:40 UTC
Created attachment 6647 [details]
a temporary fix to ignore the whole AI_ADDRCONFIG thing

Until this issue is resolved, I'm building GLIBC with this patch to avoid problems with node-local and link-local networking.
Comment 4 Pavel Šimerda 2012-11-20 23:13:20 UTC
By the way, I just learned that the current behavior is not mandated by POSIX. Thanks to Jeff Law for valuable information he provided:

http://pubs.opengroup.org/onlinepubs/9699919799/

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]

Jeff: It may also be the case that we need to involve the "Austin Group" if we need further clarification of the standard (link-local handling comes to mind).

My summary is:

Filtering of non-DNS addresses in getaddrinfo() has no real use
and it only causes problems. There's no reason to filter over the
mere existence of addresses. Filtering over global address existence
may only be desirable for global address resolution, which is DNS. But
that should be done by the DNS resolver that only asks for addresses
that make sense and only accepts addresses that it asks for.
Comment 5 Pavel Šimerda 2012-11-20 23:32:57 UTC
Changed the comment. Currently, I'm using the following patch to fix my
node-local IPv4/IPv6 networking (link-local networking is currently not
broken in Fedora since they removed the patch to also disregard link-local
addresses). I'm proposing this patch as a temporary solution until this
s fixed properly with the following notes:

* It breaks POSIX1-2008 (which requires checking for any IPv4/IPv6 address)
* It breaks informational RFC 3493 (which requires the same but disregards the loopback interface)
* It ignores the older informational RFC 2553 (which requires the same as RFC 3494 but only for DNS lookups)

The POSIX1-2008, RFC 3493 and obsolete RFC 2553 are all effectively useless
but the obsolete one is closest to the truth. Whether a global IPv4 address,
a global IPv4 route, or a global IPv4 default gateway is the right sign of
global connectivity, is up to discussion.

I also changed the description of the bug to reflect the actual problem,
not one possible (maybe wrong, but at least POSIX-compliant) solution of that problem.
Comment 6 Pavel Šimerda 2012-11-20 23:36:30 UTC
Upstream bug report:

https://bugzilla.redhat.com/show_bug.cgi?id=721350
Comment 7 Pavel Šimerda 2012-11-20 23:38:58 UTC
Another upstream bug report:

https://bugzilla.redhat.com/show_bug.cgi?id=808147
Comment 8 Tore Anderson 2012-12-16 13:47:03 UTC
Created attachment 6781 [details]
Move AI_ADDRCONFIG into gaih_inet()

Attached patch moves AI_ADDCONFIG processing into gaih_inet(). This improves things by making it not apply to literal IP addresses. However, AI_ADDCONFIG will still be able to suppress results from both address families for things coming out of /etc/hosts like for example "localhost". In order to prevent that I think we'd need to move AI_ADDRCONFIG into _nss_dns_gethostbyname*(), which is beyond my programmings skills to implement I'm afraid.
Comment 9 Pavel Šimerda 2012-12-17 17:30:11 UTC
(In reply to comment #8)
> Created attachment 6781 [details]
> Move AI_ADDRCONFIG into gaih_inet()
> 
> Attached patch moves AI_ADDCONFIG processing into gaih_inet(). This improves
> things by making it not apply to literal IP addresses. However, AI_ADDCONFIG
> will still be able to suppress results from both address families for things
> coming out of /etc/hosts like for example "localhost". In order to prevent that
> I think we'd need to move AI_ADDRCONFIG into _nss_dns_gethostbyname*(), which
> is beyond my programmings skills to implement I'm afraid.

I tested the patch and confirm that I don't see any regressions.
Comment 10 Phattanon Duangdara 2013-02-09 17:53:44 UTC
Can someone point out that this should also fixed this bug ?

http://sourceware.org/bugzilla/show_bug.cgi?id=14212
Comment 11 Pavel Šimerda 2013-02-09 21:10:59 UTC
(In reply to comment #10)
> Can someone point out that this should also fixed this bug ?
> 
> http://sourceware.org/bugzilla/show_bug.cgi?id=14212

This bug report is *not* related to the hosts nss plugin and is rather easy to fix.
Comment 12 Ondrej Bilka 2013-10-20 20:49:04 UTC
Did you send this patch to libc-alpha?
Comment 13 Pavel Šimerda 2013-10-22 10:04:44 UTC
(In reply to Ondrej Bilka from comment #12)
> Did you send this patch to libc-alpha?

Nope. Maybe we could discuss the libc development process some time in Prague or at LinuxAlt Brno? I'm not very familiar with it.
Comment 14 Jackie Rosen 2014-02-16 17:47:22 UTC Comment hidden (spam)
Comment 15 Uli Riehm 2016-04-07 05:14:08 UTC
I have this problem too - with gethostname(). I'm going to make a new DNS service and built a DNS resolver, which must run on localhost.

If I'm disconnected from eth0 and wlan0 and the computer is offline, Firefox doesn't even try to resolve hostnames (on Linux, but also on Windows), whereas nslookup actually does resolve them. I'm using Firefox, but now I suspect this being a problem of libc; and I don't want (but need) to run some virtual interface which is always-up.

I do need this feature, because there maybe services running on localhost - so they are also available in offline mode.
Comment 16 Uli Riehm 2016-04-18 12:50:20 UTC
Otherwise said, glibc and libresolver don't respect if you are running a `resolv.conf` with `nameserver 127.0.1.1`.

If one of `eth0`, `wlan0` are online "up", it's no problem for the resolver to get name `github.com` into `A 192.30.252.130`.

But if all of `eth0`, `wlan0` are offline "down", the resolver doesn't even try to ask `127.0.0.3` for to lookup `github.com`. It just assumes NX.

So to say, if I don't have a connection, you can't access `github.com`.

But what if I'm going to lookup for `my.service.local`, or `my.service.localhost`?

If I do not have ANY connection, there IS a connection to localhost 127/8!

So to say, you MUST remove the restriction, that a service running on localhost 127/8 can't be accessed, just because you (eth0, wlan0) are offline "down"; even if you (lo) should always be online "up".