[PATCH] nss: Use gethostbyname4_r when requesting IPv6 addresses (bug 14413)
Patrick Griffis
pgriffis@igalia.com
Sat Oct 25 00:23:59 GMT 2025
If getaddrinfo() is called with family of AF_INET6 it would return IPv6
addresses lacking scope_id information.
This was a regression caused by bug 14505. That patch avoided calling
gethostbyname4_r unless AF_UNSPEC is passed. The reasoning was that
gethostbyname4_r has no ability to only ask for a specific family.
That is true however gethostbyname3_r returns a list of hostent structs
which lack scope_id information.
The solution is to always use gethostbyname4_r if IPv6 is requested.
This does have the downside of IPv4 addresses being looked up by
modules even when they are not needed.
---
nss/getaddrinfo.c | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/nss/getaddrinfo.c b/nss/getaddrinfo.c
index 6726ace6fd..e7064ea9f5 100644
--- a/nss/getaddrinfo.c
+++ b/nss/getaddrinfo.c
@@ -610,6 +610,7 @@ get_nss_addresses (const char *name, const struct addrinfo *req,
struct resolv_context *res_ctx = NULL;
bool do_merge = false;
int result = 0;
+ bool got_ipv4 = false;
no_more = !__nss_database_get (nss_database_hosts, &nip);
@@ -644,9 +645,12 @@ get_nss_addresses (const char *name, const struct addrinfo *req,
no_data = 0;
nss_gethostbyname4_r *fct4 = NULL;
- /* gethostbyname4_r sends out parallel A and AAAA queries and
- is thus only suitable for PF_UNSPEC. */
- if (req->ai_family == PF_UNSPEC)
+ /* The gethostbyname4_r API is always expected to return both address families
+ * which means we would prefer gethostbyname3_r when requesting only IPv4 addresses.
+ * Unfortunately when requesting IPv6 only we have to use this API for link-local
+ * information (scope_id is not in the hostent struct).
+ * This means we may collect unncessary IPv4 addresses. */
+ if (req->ai_family != AF_INET)
fct4 = __nss_lookup_function (nip, "gethostbyname4_r");
if (fct4 != NULL)
@@ -700,6 +704,9 @@ get_nss_addresses (const char *name, const struct addrinfo *req,
while (*pat != NULL)
{
+ if ((*pat)->family == AF_INET)
+ got_ipv4 = true;
+
if ((*pat)->family == AF_INET
&& req->ai_family == AF_INET6
&& (req->ai_flags & AI_V4MAPPED) != 0)
@@ -856,6 +863,11 @@ get_nss_addresses (const char *name, const struct addrinfo *req,
/* If both requests timed out report this. */
if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
result = -EAI_AGAIN;
+ else if (req->ai_family == AF_INET6 && !res->got_ipv6 && got_ipv4)
+ /* If only IPv6 addresses were requested and we only got IPv4 addresses
+ * we ignore those. This is less accurate but matches previous behavior.
+ * The cause of this is commented above when using gethostbyname4_r */
+ result = -EAI_NONAME;
else
/* We made requests but they turned out no data. The name
is known, though. */
--
2.51.0
More information about the Libc-alpha
mailing list