[RFC,0/4,BZ,17083] Make getaddrinfo(3) return zone id from /etc/hosts for link-local IPv6 addresses
mbox series

Message ID 20170905160530.19525-1-stlman@poczta.fm
Headers show
Series
  • Make getaddrinfo(3) return zone id from /etc/hosts for link-local IPv6 addresses
Related show

Message

Łukasz Stelmach Sept. 5, 2017, 4:05 p.m. UTC
Hello,

The aim of the following patches is to enable retrieving zone
(interface) information stored in /etc/hosts along with link-local IPv6
addresses. This requires changes in several places in resolver and NSS.

First the parse_line() function needs to detect the scope delimiter,
parse what follows and find the network interface index, that later is
going to be assigned to sin6_scope_id field of a sockaddr_in6 structure.
The easiest way to do this is to use getaddrinfo(3) with AI_NUMERICHOST
flag that prevents any DB queries.

There is a slight mismatch in naming of variables. The field in the
sockaddr_in6 structure is sin6_scope_id while I've decided to use
in6_zone_id which better corresponds with the terms used in IPv6 related
RFCs. If you think the term "scope" should be used instead of "zone", I
am fine with it.

When parsed, the zone information needs to be delivered to
getaddrinfo(3). It calls NSS functions gethostbyname4_r,
gethostbyname3_r and gethostbyname2_r. Only the first of them can return
the information because it uses ritcher gaih_addrtupple structure
instead of an old hostent. However, gethostname4_r is used only if
ai_family hint is set to PF_UNSPEC. Which makes the whole API work weird
a bit. With the following entries in /etc/hosts

--8<---------------cut here---------------start------------->8---
192.168.0.1 foo
fe80::0203:04ff:fe05:0607%eth0 foo
--8<---------------cut here---------------end--------------->8---

querying for AF_INET6 address of host foo won't return any results,
which is counterintuitive if not plain wrong. The comment in
getaddrinfo.c suggests, that getaddrinfo4_r should not be used unless
ai_family is set to PF_UNSPEC, to avoid unnecessary DNS queries.

The only way to solve the problem of less capable gethostbyname[23]_r
and too verbose gethosbyname4_r is to introduce gethostbynamet5_r which
accepts all the arguments of gethostbyname4_r AND an address family
(af). So I renamed gethostbyname4_r to gethostbyname5_r and defined
gethostbyname4_r as a wrapper for gethostbyname5_r in all four glibc NSS
modlues (i.e. files, dns, nis and nisplus). gethostbyname5_r passes the
af argument to respective underlying "parsers". Unfotunately I was
unable to test NIS/NIS+ modules, so please do it for me.

The last bit is to make getaddrinfo(3) call gethostbyname5_r. In theory,
with the new function in place, all other code paths are
unnecessary. However, as I understand, different non-glibc NSS modules
provide different sets of functions so I've left the code paths intact.

Łukasz Stelmach (4):
  getaddrinfo: Add comments for #else and #endif directives
  NSS: Parse zone identifier of IPv6 addresses in /etc/hosts
  NSS: Introduce gethostbyname5_r function
  getaddrinfo: Use the new getaddrinfo5_r NSS function

 nis/Versions                    |  3 +-
 nis/nss_nis/nis-hosts.c         | 13 ++++++--
 nis/nss_nisplus/nisplus-hosts.c | 13 ++++++--
 nss/Versions                    |  1 +
 nss/nss_files/files-hosts.c     | 66 +++++++++++++++++++++++++++++++++++------
 resolv/Versions                 |  2 +-
 resolv/nss_dns/dns-host.c       | 32 ++++++++++++++++++--
 sysdeps/posix/getaddrinfo.c     | 54 ++++++++++++++++++++-------------
 8 files changed, 146 insertions(+), 38 deletions(-)