diff --git a/lib/libc/net/getnameinfo.c b/lib/libc/net/getnameinfo.c --- a/lib/libc/net/getnameinfo.c +++ b/lib/libc/net/getnameinfo.c @@ -229,24 +229,48 @@ case AF_INET6: { const struct sockaddr_in6 *sin6; + sin6 = (const struct sockaddr_in6 *)sa; - switch (sin6->sin6_addr.s6_addr[0]) { - case 0x00: - if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) - ; - else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)) - ; - else - flags |= NI_NUMERICHOST; - break; - default: - if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { - flags |= NI_NUMERICHOST; - } - else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) - flags |= NI_NUMERICHOST; - break; - } + + /* + * https://pubs.opengroup.org/onlinepubs/009604599/functions/getnameinfo.html + * "If the socket address structure contains an IPv4-mapped + * IPv6 address or an IPv4-compatible IPv6 address, + * the implementation shall extract the embedded IPv4 address + * and lookup the node name for that IPv4 address." + * => getipnodebyaddr() handles that case for us. + * + * "Note: The IPv6 unspecified address ( "::" ) and the + * IPv6 loopback address ( "::1" ) are not IPv4-compatible + * addresses." + * => IN6_IS_ADDR_V4COMPAT() handles this (according to + * RFC 2553 6.2 Address-To-Nodename Translation) + * + * "If the address is the IPv6 unspecified address + * ( "::" ), a lookup is not performed, and the [EAI_NONAME] + * error is returned." + * => catch here for proper return value (getipnodebyaddr() + * does as well but not return an appropriate error?) + */ + if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) + return EAI_NONAME; + + /* + * We used to exclude link-local from lookups. + * Even though calles in the resolver chain may not (yet) + * properly deal with them, we no longer do as for link-local + * there is a path to resolve these. See: + * RFC 6303 4.5. IPv6 Link-Local Addresses + * RFC 6762 4. Reverse Address Mapping + * + * XXX For IPv6 MC the only reference found was + * https://www.ietf.org/archive/id/draft-michaelson-as112-ipv6-02.html + * but there are also no "empty zone" for x.0.f.f.ip6.arpa + * in DNS servers. Keep catching it here for now and + * do not attempt name resolution but return address string. + */ + if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) + flags |= NI_NUMERICHOST; } break; #endif