From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from sienna.cherry.relay.mailchannels.net (sienna.cherry.relay.mailchannels.net [23.83.223.165]) by sourceware.org (Postfix) with ESMTPS id 2D31F3857721 for ; Fri, 15 Sep 2023 23:48:10 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 2D31F3857721 Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=sourceware.org Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=sourceware.org X-Sender-Id: dreamhost|x-authsender|siddhesh@gotplt.org Received: from relay.mailchannels.net (localhost [127.0.0.1]) by relay.mailchannels.net (Postfix) with ESMTP id 5C0B0C1C97; Fri, 15 Sep 2023 23:48:09 +0000 (UTC) Received: from pdx1-sub0-mail-a222.dreamhost.com (unknown [127.0.0.6]) (Authenticated sender: dreamhost) by relay.mailchannels.net (Postfix) with ESMTPA id EBE36C1C75; Fri, 15 Sep 2023 23:48:08 +0000 (UTC) ARC-Seal: i=1; s=arc-2022; d=mailchannels.net; t=1694821689; a=rsa-sha256; cv=none; b=+R9/e38ULNWJuvnLiFRxiwmyja0x0jT7t5Q/JdBXL1KYxs0neS3z5qW1NHhLAxc/DejgwC InARLkf1LYvJ2eXCxvzDCA5ZGc+guWIoesHgvmgAy3aeYU882HLho+p///7BbXsJA64xxk bSRAs2j5IUq2xDJRMJ3uFpVq/7+pyVfQmb8x1m9XFHSz366skeGHuIS+d+WLN+qbU0w9rd mlhq6zxG/AKLbMTdkVhmMt0lCt3t19lwym1JRC0JenTPpv8ekLJlVXl1pvQJGQ7UaAy5Hn SESpb1953yC1mEBaZwsN+su6vvj7Kw6/xUqZeKfI6L5CzxlMvBov3YpqTX1+Gw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=mailchannels.net; s=arc-2022; t=1694821688; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=xu+7a0SmIUDhrJVK5Nwt0DUXxc0OC5clQjTnpLsI2Jk=; b=cDqxF4UOiHv1vepJGlUvKm7cHeTR86+9NyIQ+YmLXufZPsHr3Xi9DTwAyld+lK/vqmA0a0 C+K5+CNXYOXLx/x43wDVJWrPfrEsca747mW+sr1Dx8XpR07pLEfzw7WvtwrxirkF10hHnr x/K/n40hYQJFf9ju+7o+RgHInGDBI4MjM53vSqa3524LHtyFP0JrRNqGO6mhfUe9BVslaf 4hnEIOAt27slKOUQ0KGi4NWhqZ9vp8tlDjQW6o/QPFH+yYeOaK0osoORCLhMEVvZQcAp/S 1f6sSjvoWrsuEhcQ+LkQnoHwFCf5oE5erLorYrByvv+TxvFCvOzI99foZxYzXg== ARC-Authentication-Results: i=1; rspamd-7d5dc8fd68-tfld8; auth=pass smtp.auth=dreamhost smtp.mailfrom=siddhesh@sourceware.org X-Sender-Id: dreamhost|x-authsender|siddhesh@gotplt.org X-MC-Relay: Neutral X-MC-Copy: stored-urls X-MailChannels-SenderId: dreamhost|x-authsender|siddhesh@gotplt.org X-MailChannels-Auth-Id: dreamhost X-Cooperative-Keen: 51a8c04b57b0aac1_1694821689208_2312384665 X-MC-Loop-Signature: 1694821689208:3671416489 X-MC-Ingress-Time: 1694821689208 Received: from pdx1-sub0-mail-a222.dreamhost.com (pop.dreamhost.com [64.90.62.162]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384) by 100.119.184.206 (trex/6.9.1); Fri, 15 Sep 2023 23:48:09 +0000 Received: from fedora.redhat.com (bras-vprn-toroon4834w-lp130-02-142-113-138-41.dsl.bell.ca [142.113.138.41]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: siddhesh@gotplt.org) by pdx1-sub0-mail-a222.dreamhost.com (Postfix) with ESMTPSA id 4RnW8m3yd3zDb; Fri, 15 Sep 2023 16:48:08 -0700 (PDT) From: Siddhesh Poyarekar To: libc-stable@sourceware.org Cc: DJ Delorie Subject: [pushed 2.35 08/13] gaih_inet: separate nss lookup loop into its own function Date: Fri, 15 Sep 2023 19:47:50 -0400 Message-ID: <20230915234755.1148216-9-siddhesh@sourceware.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230915234755.1148216-1-siddhesh@sourceware.org> References: <20230915234755.1148216-1-siddhesh@sourceware.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-1172.1 required=5.0 tests=BAYES_00,GIT_PATCH_0,KAM_DMARC_NONE,KAM_DMARC_STATUS,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H5,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_SOFTFAIL,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Signed-off-by: Siddhesh Poyarekar Reviewed-by: DJ Delorie (cherry picked from commit 906cecbe0889e601c91d9aba738049c73ebe4dd2) --- sysdeps/posix/getaddrinfo.c | 563 ++++++++++++++++++------------------ 1 file changed, 286 insertions(+), 277 deletions(-) diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c index 01be932b3f..f70ce2c76b 100644 --- a/sysdeps/posix/getaddrinfo.c +++ b/sysdeps/posix/getaddrinfo.c @@ -159,6 +159,14 @@ static const struct addrinfo default_hints = .ai_next = NULL }; +static void +gaih_result_reset (struct gaih_result *res) +{ + if (res->free_at) + free (res->at); + free (res->canon); + memset (res, 0, sizeof (*res)); +} static int gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp, @@ -197,13 +205,10 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp, /* Convert struct hostent to a list of struct gaih_addrtuple objects. h_name is not copied, and the struct hostent object must not be deallocated - prematurely. The new addresses are appended to the tuple array in - RESULT. */ + prematurely. The new addresses are appended to the tuple array in RES. */ static bool -convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, - int family, - struct hostent *h, - struct gaih_addrtuple **result) +convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, int family, + struct hostent *h, struct gaih_result *res) { /* Count the number of addresses in h->h_addr_list. */ size_t count = 0; @@ -215,7 +220,7 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, if (count == 0 || h->h_length > sizeof (((struct gaih_addrtuple) {}).addr)) return true; - struct gaih_addrtuple *array = *result; + struct gaih_addrtuple *array = res->at; size_t old = 0; while (array != NULL) @@ -224,12 +229,14 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, array = array->next; } - array = realloc (*result, (old + count) * sizeof (*array)); + array = realloc (res->at, (old + count) * sizeof (*array)); if (array == NULL) return false; - *result = array; + res->got_ipv6 = family == AF_INET6; + res->at = array; + res->free_at = true; /* Update the next pointers on reallocation. */ for (size_t i = 0; i < old; i++) @@ -278,7 +285,7 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, { \ __resolv_context_put (res_ctx); \ result = -EAI_MEMORY; \ - goto free_and_return; \ + goto out; \ } \ } \ if (status == NSS_STATUS_NOTFOUND \ @@ -288,7 +295,7 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, { \ __resolv_context_put (res_ctx); \ result = -EAI_SYSTEM; \ - goto free_and_return; \ + goto out; \ } \ if (h_errno == TRY_AGAIN) \ no_data = EAI_AGAIN; \ @@ -297,27 +304,24 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, } \ else if (status == NSS_STATUS_SUCCESS) \ { \ - if (!convert_hostent_to_gaih_addrtuple (req, _family, &th, &addrmem)) \ + if (!convert_hostent_to_gaih_addrtuple (req, _family, &th, res)) \ { \ __resolv_context_put (res_ctx); \ result = -EAI_SYSTEM; \ - goto free_and_return; \ + goto out; \ } \ - *pat = addrmem; \ \ - if (localcanon != NULL && res.canon == NULL) \ + if (localcanon != NULL && res->canon == NULL) \ { \ char *canonbuf = __strdup (localcanon); \ if (canonbuf == NULL) \ { \ __resolv_context_put (res_ctx); \ result = -EAI_SYSTEM; \ - goto free_and_return; \ + goto out; \ } \ - res.canon = canonbuf; \ + res->canon = canonbuf; \ } \ - if (_family == AF_INET6 && *pat != NULL) \ - res.got_ipv6 = true; \ } \ } @@ -590,6 +594,260 @@ out: } #endif +static int +get_nss_addresses (const char *name, const struct addrinfo *req, + struct scratch_buffer *tmpbuf, struct gaih_result *res) +{ + int no_data = 0; + int no_inet6_data = 0; + nss_action_list nip; + enum nss_status inet6_status = NSS_STATUS_UNAVAIL; + enum nss_status status = NSS_STATUS_UNAVAIL; + int no_more; + struct resolv_context *res_ctx = NULL; + bool do_merge = false; + int result = 0; + + no_more = !__nss_database_get (nss_database_hosts, &nip); + + /* If we are looking for both IPv4 and IPv6 address we don't + want the lookup functions to automatically promote IPv4 + addresses to IPv6 addresses, so we use the no_inet6 + function variant. */ + res_ctx = __resolv_context_get (); + if (res_ctx == NULL) + no_more = 1; + + while (!no_more) + { + /* Always start afresh; continue should discard previous results + and the hosts database does not support merge. */ + gaih_result_reset (res); + + if (do_merge) + { + __set_h_errno (NETDB_INTERNAL); + __set_errno (EBUSY); + break; + } + + 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) + fct4 = __nss_lookup_function (nip, "gethostbyname4_r"); + + if (fct4 != NULL) + { + while (1) + { + status = DL_CALL_FCT (fct4, (name, &res->at, + tmpbuf->data, tmpbuf->length, + &errno, &h_errno, + NULL)); + if (status == NSS_STATUS_SUCCESS) + break; + /* gethostbyname4_r may write into AT, so reset it. */ + res->at = NULL; + if (status != NSS_STATUS_TRYAGAIN + || errno != ERANGE || h_errno != NETDB_INTERNAL) + { + if (h_errno == TRY_AGAIN) + no_data = EAI_AGAIN; + else + no_data = h_errno == NO_DATA; + break; + } + + if (!scratch_buffer_grow (tmpbuf)) + { + __resolv_context_put (res_ctx); + result = -EAI_MEMORY; + goto out; + } + } + + if (status == NSS_STATUS_SUCCESS) + { + assert (!no_data); + no_data = 1; + + if ((req->ai_flags & AI_CANONNAME) != 0 && res->canon == NULL) + { + char *canonbuf = __strdup (res->at->name); + if (canonbuf == NULL) + { + __resolv_context_put (res_ctx); + result = -EAI_MEMORY; + goto out; + } + res->canon = canonbuf; + } + + struct gaih_addrtuple **pat = &res->at; + + while (*pat != NULL) + { + if ((*pat)->family == AF_INET + && req->ai_family == AF_INET6 + && (req->ai_flags & AI_V4MAPPED) != 0) + { + uint32_t *pataddr = (*pat)->addr; + (*pat)->family = AF_INET6; + pataddr[3] = pataddr[0]; + pataddr[2] = htonl (0xffff); + pataddr[1] = 0; + pataddr[0] = 0; + pat = &((*pat)->next); + no_data = 0; + } + else if (req->ai_family == AF_UNSPEC + || (*pat)->family == req->ai_family) + { + pat = &((*pat)->next); + + no_data = 0; + if (req->ai_family == AF_INET6) + res->got_ipv6 = true; + } + else + *pat = ((*pat)->next); + } + } + + no_inet6_data = no_data; + } + else + { + nss_gethostbyname3_r *fct = NULL; + if (req->ai_flags & AI_CANONNAME) + /* No need to use this function if we do not look for + the canonical name. The function does not exist in + all NSS modules and therefore the lookup would + often fail. */ + fct = __nss_lookup_function (nip, "gethostbyname3_r"); + if (fct == NULL) + /* We are cheating here. The gethostbyname2_r + function does not have the same interface as + gethostbyname3_r but the extra arguments the + latter takes are added at the end. So the + gethostbyname2_r code will just ignore them. */ + fct = __nss_lookup_function (nip, "gethostbyname2_r"); + + if (fct != NULL) + { + if (req->ai_family == AF_INET6 + || req->ai_family == AF_UNSPEC) + { + gethosts (AF_INET6); + no_inet6_data = no_data; + inet6_status = status; + } + if (req->ai_family == AF_INET + || req->ai_family == AF_UNSPEC + || (req->ai_family == AF_INET6 + && (req->ai_flags & AI_V4MAPPED) + /* Avoid generating the mapped addresses if we + know we are not going to need them. */ + && ((req->ai_flags & AI_ALL) || !res->got_ipv6))) + { + gethosts (AF_INET); + + if (req->ai_family == AF_INET) + { + no_inet6_data = no_data; + inet6_status = status; + } + } + + /* If we found one address for AF_INET or AF_INET6, + don't continue the search. */ + if (inet6_status == NSS_STATUS_SUCCESS + || status == NSS_STATUS_SUCCESS) + { + if ((req->ai_flags & AI_CANONNAME) != 0 + && res->canon == NULL) + { + char *canonbuf = getcanonname (nip, res->at, name); + if (canonbuf == NULL) + { + __resolv_context_put (res_ctx); + result = -EAI_MEMORY; + goto out; + } + res->canon = canonbuf; + } + status = NSS_STATUS_SUCCESS; + } + else + { + /* We can have different states for AF_INET and + AF_INET6. Try to find a useful one for both. */ + if (inet6_status == NSS_STATUS_TRYAGAIN) + status = NSS_STATUS_TRYAGAIN; + else if (status == NSS_STATUS_UNAVAIL + && inet6_status != NSS_STATUS_UNAVAIL) + status = inet6_status; + } + } + else + { + /* Could not locate any of the lookup functions. + The NSS lookup code does not consistently set + errno, so we need to supply our own error + code here. The root cause could either be a + resource allocation failure, or a missing + service function in the DSO (so it should not + be listed in /etc/nsswitch.conf). Assume the + former, and return EBUSY. */ + status = NSS_STATUS_UNAVAIL; + __set_h_errno (NETDB_INTERNAL); + __set_errno (EBUSY); + } + } + + if (nss_next_action (nip, status) == NSS_ACTION_RETURN) + break; + + /* The hosts database does not support MERGE. */ + if (nss_next_action (nip, status) == NSS_ACTION_MERGE) + do_merge = true; + + nip++; + if (nip->module == NULL) + no_more = -1; + } + + __resolv_context_put (res_ctx); + + /* If we have a failure which sets errno, report it using + EAI_SYSTEM. */ + if ((status == NSS_STATUS_TRYAGAIN || status == NSS_STATUS_UNAVAIL) + && h_errno == NETDB_INTERNAL) + { + result = -EAI_SYSTEM; + goto out; + } + + if (no_data != 0 && no_inet6_data != 0) + { + /* If both requests timed out report this. */ + if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN) + result = -EAI_AGAIN; + else + /* We made requests but they turned out no data. The name + is known, though. */ + result = -EAI_NODATA; + } + +out: + if (result != 0) + gaih_result_reset (res); + return result; +} + /* Convert numeric addresses to binary into RES. On failure, RES->AT is set to NULL and an error code is returned. If AI_NUMERIC_HOST is not requested and the function cannot determine a result, RES->AT is set to NULL and 0 @@ -723,7 +981,7 @@ try_simple_gethostbyname (const char *name, const struct addrinfo *req, /* We found data, convert it. RES->AT from the conversion will either be an allocated block or NULL, both of which are safe to pass to free (). */ - if (!convert_hostent_to_gaih_addrtuple (req, AF_INET, h, &res->at)) + if (!convert_hostent_to_gaih_addrtuple (req, AF_INET, h, res)) return -EAI_MEMORY; res->free_at = true; @@ -801,264 +1059,14 @@ gaih_inet (const char *name, const struct gaih_service *service, goto process_list; #endif - int no_data = 0; - int no_inet6_data = 0; - nss_action_list nip; - enum nss_status inet6_status = NSS_STATUS_UNAVAIL; - enum nss_status status = NSS_STATUS_UNAVAIL; - int no_more; - struct resolv_context *res_ctx = NULL; - bool do_merge = false; - - no_more = !__nss_database_get (nss_database_hosts, &nip); - - /* If we are looking for both IPv4 and IPv6 address we don't - want the lookup functions to automatically promote IPv4 - addresses to IPv6 addresses, so we use the no_inet6 - function variant. */ - res_ctx = __resolv_context_get (); - if (res_ctx == NULL) - no_more = 1; - - while (!no_more) - { - /* Always start afresh; continue should discard previous results - and the hosts database does not support merge. */ - res.at = NULL; - free (res.canon); - free (addrmem); - res.canon = NULL; - addrmem = NULL; - got_ipv6 = false; - - if (do_merge) - { - __set_h_errno (NETDB_INTERNAL); - __set_errno (EBUSY); - break; - } - - 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) - fct4 = __nss_lookup_function (nip, "gethostbyname4_r"); - - if (fct4 != NULL) - { - while (1) - { - status = DL_CALL_FCT (fct4, (name, &res.at, - tmpbuf->data, tmpbuf->length, - &errno, &h_errno, - NULL)); - if (status == NSS_STATUS_SUCCESS) - break; - /* gethostbyname4_r may write into AT, so reset it. */ - res.at = NULL; - if (status != NSS_STATUS_TRYAGAIN - || errno != ERANGE || h_errno != NETDB_INTERNAL) - { - if (h_errno == TRY_AGAIN) - no_data = EAI_AGAIN; - else - no_data = h_errno == NO_DATA; - break; - } - - if (!scratch_buffer_grow (tmpbuf)) - { - __resolv_context_put (res_ctx); - result = -EAI_MEMORY; - goto free_and_return; - } - } - - if (status == NSS_STATUS_SUCCESS) - { - assert (!no_data); - no_data = 1; - - if ((req->ai_flags & AI_CANONNAME) != 0 && res.canon == NULL) - { - char *canonbuf = __strdup (res.at->name); - if (canonbuf == NULL) - { - __resolv_context_put (res_ctx); - result = -EAI_MEMORY; - goto free_and_return; - } - res.canon = canonbuf; - } - - struct gaih_addrtuple **pat = &res.at; - - while (*pat != NULL) - { - if ((*pat)->family == AF_INET - && req->ai_family == AF_INET6 - && (req->ai_flags & AI_V4MAPPED) != 0) - { - uint32_t *pataddr = (*pat)->addr; - (*pat)->family = AF_INET6; - pataddr[3] = pataddr[0]; - pataddr[2] = htonl (0xffff); - pataddr[1] = 0; - pataddr[0] = 0; - pat = &((*pat)->next); - no_data = 0; - } - else if (req->ai_family == AF_UNSPEC - || (*pat)->family == req->ai_family) - { - pat = &((*pat)->next); - - no_data = 0; - if (req->ai_family == AF_INET6) - res.got_ipv6 = true; - } - else - *pat = ((*pat)->next); - } - } - - no_inet6_data = no_data; - } - else - { - nss_gethostbyname3_r *fct = NULL; - if (req->ai_flags & AI_CANONNAME) - /* No need to use this function if we do not look for - the canonical name. The function does not exist in - all NSS modules and therefore the lookup would - often fail. */ - fct = __nss_lookup_function (nip, "gethostbyname3_r"); - if (fct == NULL) - /* We are cheating here. The gethostbyname2_r - function does not have the same interface as - gethostbyname3_r but the extra arguments the - latter takes are added at the end. So the - gethostbyname2_r code will just ignore them. */ - fct = __nss_lookup_function (nip, "gethostbyname2_r"); - - if (fct != NULL) - { - struct gaih_addrtuple **pat = &res.at; - - if (req->ai_family == AF_INET6 - || req->ai_family == AF_UNSPEC) - { - gethosts (AF_INET6); - no_inet6_data = no_data; - inet6_status = status; - } - if (req->ai_family == AF_INET - || req->ai_family == AF_UNSPEC - || (req->ai_family == AF_INET6 - && (req->ai_flags & AI_V4MAPPED) - /* Avoid generating the mapped addresses if we - know we are not going to need them. */ - && ((req->ai_flags & AI_ALL) || !res.got_ipv6))) - { - gethosts (AF_INET); - - if (req->ai_family == AF_INET) - { - no_inet6_data = no_data; - inet6_status = status; - } - } - - /* If we found one address for AF_INET or AF_INET6, - don't continue the search. */ - if (inet6_status == NSS_STATUS_SUCCESS - || status == NSS_STATUS_SUCCESS) - { - if ((req->ai_flags & AI_CANONNAME) != 0 - && res.canon == NULL) - { - char *canonbuf = getcanonname (nip, res.at, name); - if (canonbuf == NULL) - { - __resolv_context_put (res_ctx); - result = -EAI_MEMORY; - goto free_and_return; - } - res.canon = canonbuf; - } - status = NSS_STATUS_SUCCESS; - } - else - { - /* We can have different states for AF_INET and - AF_INET6. Try to find a useful one for both. */ - if (inet6_status == NSS_STATUS_TRYAGAIN) - status = NSS_STATUS_TRYAGAIN; - else if (status == NSS_STATUS_UNAVAIL - && inet6_status != NSS_STATUS_UNAVAIL) - status = inet6_status; - } - } - else - { - /* Could not locate any of the lookup functions. - The NSS lookup code does not consistently set - errno, so we need to supply our own error - code here. The root cause could either be a - resource allocation failure, or a missing - service function in the DSO (so it should not - be listed in /etc/nsswitch.conf). Assume the - former, and return EBUSY. */ - status = NSS_STATUS_UNAVAIL; - __set_h_errno (NETDB_INTERNAL); - __set_errno (EBUSY); - } - } - - if (nss_next_action (nip, status) == NSS_ACTION_RETURN) - break; - - /* The hosts database does not support MERGE. */ - if (nss_next_action (nip, status) == NSS_ACTION_MERGE) - do_merge = true; - - nip++; - if (nip->module == NULL) - no_more = -1; - } - - __resolv_context_put (res_ctx); - - /* If we have a failure which sets errno, report it using - EAI_SYSTEM. */ - if ((status == NSS_STATUS_TRYAGAIN || status == NSS_STATUS_UNAVAIL) - && h_errno == NETDB_INTERNAL) - { - result = -EAI_SYSTEM; - goto free_and_return; - } - - if (no_data != 0 && no_inet6_data != 0) - { - /* If both requests timed out report this. */ - if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN) - result = -EAI_AGAIN; - else - /* We made requests but they turned out no data. The name - is known, though. */ - result = -EAI_NODATA; - - goto free_and_return; - } + if ((result = get_nss_addresses (name, req, tmpbuf, &res)) != 0) + goto free_and_return; + else if (res.at != NULL) + goto process_list; - process_list: - if (res.at == NULL) - { - result = -EAI_NONAME; - goto free_and_return; - } + /* None of the lookups worked, so name not found. */ + result = -EAI_NONAME; + goto free_and_return; } else { @@ -1089,6 +1097,7 @@ gaih_inet (const char *name, const struct gaih_service *service, } } +process_list: { /* Set up the canonical name if we need it. */ if ((result = process_canonname (req, orig_name, &res)) != 0) -- 2.41.0