It's currently impossible for NSS modules to return useful IPv6 link-local addresses. To be useful they would have to be accompanied by a scope ID, which the gethostbyname4_r() entry point actually allows to pass back to glibc. However, this entry point is used by glibc only if no protocol is specified (more precisely AF_UNSPEC) when looking up the name via getaddinfo(). If a protocol is specified, then gethostbyname3_r() is invoked instead, which however doesn't allow the module to report a scopeid back.
This is a problem for all NSS modules that want to return Ipv6 link-local addresses, such as nss-mdns, and the new nss-mycontainers module that we recently added to systemd (which makes the names of all locally running OS containers resolvable via NSS).
THe problem manifests itself when these modules are used in combination with the "ping6" command. "ping6" uses getaddrinfo, bus rightly specifies AF_INET6 as protocol, which means glibc dispatches it to gethostbyname3_r, and thus no scopeid is available.
I figure what is needed is a gethostbyname5_r() entry point that takes an address family as input parameter, and allows returning a scopeid back. It would thus be a combination of the specific benefits of both gethostbyname3_r() and gethostbyname4_r().
Thanks for the bug. Could you please provide a small test case for us so we have something concerte to use when we look at implementing this? It sound slike you already have a system semi-configured like this, and it would be nice if we could just crib your config notes.
A good test case for this is nss-myhostname, as shipped with current systemd.
The modules' purpose is to resolve the localhost name to all local addresses, including link local ones, with appropriate ifindex. With this module enabled in /etc/nsswitch.conf, I get this behaviour:
lennart@delta $ telnet delta
telnet: connect to address fe80::2ed0:5aff:fe32:d0ea%wlp0s26u1u4i2: Connection refused
telnet: connect to address 172.31.0.125: Connection refused
Here, "delta" is my own hostname. We see that it finds the IPv6 address of the local host, with the correct ifindex. That's because telnet does not specify a protocol when resolving the name, and hence the NSS module's gethostbyname4_r() is called, which can return the ifindex just fine. All is good. (of course the connection fails, because i have no telnet server running, but that's besides the point).
lennart@delta $ ping6 delta
connect: Invalid argument
This fails though, since ping6 actually specifies a protocol family when resolving the name (AF_INET6, of course), which means the NSS modules' gethostbyname3_r() is called instead, which cannot return the ifindex. ping6 tries to connect to the returned link-local Ipv6 address, which lacks an ifindex, which the kernel then refuses on connect() with EINVAL...
The current sources of nss-myhostname you find here:
(note that the version of this currently available in fedora is considerably different, but exposes the same behaviour here, so you can use that to test...)
*** This bug has been marked as a duplicate of bug 843054 ***