aboutsummaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
authorArjun Shankar <arjun@redhat.com>2023-10-02 14:55:27 +0200
committerArjun Shankar <arjun@redhat.com>2023-10-24 12:31:00 +0200
commit7f602256ab5b85db1dbfb5f40bd109c4b37b68c8 (patch)
tree88cf9fb3bc04eae6ae9ca3816fac75d78f691740 /sysdeps
parent1d74d2f042a405982661267394e16126db70dc5f (diff)
downloadglibc-7f602256ab5b85db1dbfb5f40bd109c4b37b68c8.tar.xz
glibc-7f602256ab5b85db1dbfb5f40bd109c4b37b68c8.zip
Move getaddrinfo from 'posix' into 'nss'
getaddrinfo is an entry point for nss functionality. This commit moves it from 'sysdeps/posix' to 'nss', gets rid of the stub in 'posix', and moves all associated tests as well. Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/posix/getaddrinfo.c2625
1 files changed, 0 insertions, 2625 deletions
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
deleted file mode 100644
index 531124958d..0000000000
--- a/sysdeps/posix/getaddrinfo.c
+++ /dev/null
@@ -1,2625 +0,0 @@
-/* Host and service name lookups using Name Service Switch modules.
- Copyright (C) 1996-2023 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <https://www.gnu.org/licenses/>. */
-
-/* The Inner Net License, Version 2.00
-
- The author(s) grant permission for redistribution and use in source and
-binary forms, with or without modification, of the software and documentation
-provided that the following conditions are met:
-
-0. If you receive a version of the software that is specifically labelled
- as not being for redistribution (check the version message and/or README),
- you are not permitted to redistribute that version of the software in any
- way or form.
-1. All terms of the all other applicable copyrights and licenses must be
- followed.
-2. Redistributions of source code must retain the authors' copyright
- notice(s), this list of conditions, and the following disclaimer.
-3. Redistributions in binary form must reproduce the authors' copyright
- notice(s), this list of conditions, and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-4. [The copyright holder has authorized the removal of this clause.]
-5. Neither the name(s) of the author(s) nor the names of its contributors
- may be used to endorse or promote products derived from this software
- without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS ``AS IS'' AND ANY
-EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- If these license terms cause you a real problem, contact the author. */
-
-/* This software is Copyright 1996 by Craig Metz, All Rights Reserved. */
-
-#include <assert.h>
-#include <ctype.h>
-#include <errno.h>
-#include <ifaddrs.h>
-#include <netdb.h>
-#include <nss.h>
-#include <resolv/resolv-internal.h>
-#include <resolv/resolv_context.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdio_ext.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <arpa/inet.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include <sys/utsname.h>
-#include <unistd.h>
-#include <nsswitch.h>
-#include <libc-lock.h>
-#include <not-cancel.h>
-#include <nscd/nscd-client.h>
-#include <nscd/nscd_proto.h>
-#include <scratch_buffer.h>
-#include <inet/net-internal.h>
-
-/* Former AI_IDN_ALLOW_UNASSIGNED and AI_IDN_USE_STD3_ASCII_RULES
- flags, now ignored. */
-#define DEPRECATED_AI_IDN 0x300
-
-#if IS_IN (libc)
-# define feof_unlocked(fp) __feof_unlocked (fp)
-#endif
-
-struct gaih_service
- {
- const char *name;
- int num;
- };
-
-struct gaih_servtuple
- {
- int socktype;
- int protocol;
- int port;
- bool set;
- };
-
-
-struct gaih_typeproto
- {
- int socktype;
- int protocol;
- uint8_t protoflag;
- bool defaultflag;
- char name[8];
- };
-
-struct gaih_result
-{
- struct gaih_addrtuple *at;
- char *canon;
- char *h_name;
- bool free_at;
- bool got_ipv6;
-};
-
-/* Values for `protoflag'. */
-#define GAI_PROTO_NOSERVICE 1
-#define GAI_PROTO_PROTOANY 2
-
-static const struct gaih_typeproto gaih_inet_typeproto[] =
-{
- { 0, 0, 0, false, "" },
- { SOCK_STREAM, IPPROTO_TCP, 0, true, "tcp" },
- { SOCK_DGRAM, IPPROTO_UDP, 0, true, "udp" },
-#if defined SOCK_DCCP && defined IPPROTO_DCCP
- { SOCK_DCCP, IPPROTO_DCCP, 0, false, "dccp" },
-#endif
-#ifdef IPPROTO_UDPLITE
- { SOCK_DGRAM, IPPROTO_UDPLITE, 0, false, "udplite" },
-#endif
-#ifdef IPPROTO_SCTP
- { SOCK_STREAM, IPPROTO_SCTP, 0, false, "sctp" },
- { SOCK_SEQPACKET, IPPROTO_SCTP, 0, false, "sctp" },
-#endif
- { SOCK_RAW, 0, GAI_PROTO_PROTOANY|GAI_PROTO_NOSERVICE, true, "raw" },
- { 0, 0, 0, false, "" }
-};
-
-static const struct addrinfo default_hints =
- {
- .ai_flags = AI_DEFAULT,
- .ai_family = PF_UNSPEC,
- .ai_socktype = 0,
- .ai_protocol = 0,
- .ai_addrlen = 0,
- .ai_addr = NULL,
- .ai_canonname = NULL,
- .ai_next = NULL
- };
-
-static void
-gaih_result_reset (struct gaih_result *res)
-{
- if (res->free_at)
- free (res->at);
- free (res->canon);
- free (res->h_name);
- memset (res, 0, sizeof (*res));
-}
-
-static int
-gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
- const struct addrinfo *req, struct gaih_servtuple *st,
- struct scratch_buffer *tmpbuf)
-{
- struct servent *s;
- struct servent ts;
- int r;
-
- do
- {
- r = __getservbyname_r (servicename, tp->name, &ts,
- tmpbuf->data, tmpbuf->length, &s);
- if (r != 0 || s == NULL)
- {
- if (r == ERANGE)
- {
- if (!scratch_buffer_grow (tmpbuf))
- return -EAI_MEMORY;
- }
- else
- return -EAI_SERVICE;
- }
- }
- while (r);
-
- st->socktype = tp->socktype;
- st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
- ? req->ai_protocol : tp->protocol);
- st->port = s->s_port;
- st->set = true;
-
- return 0;
-}
-
-/* Convert struct hostent to a list of struct gaih_addrtuple objects. 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_result *res)
-{
- /* Count the number of addresses in h->h_addr_list. */
- size_t count = 0;
- for (char **p = h->h_addr_list; *p != NULL; ++p)
- ++count;
-
- /* Report no data if no addresses are available, or if the incoming
- address size is larger than what we can store. */
- if (count == 0 || h->h_length > sizeof (((struct gaih_addrtuple) {}).addr))
- return true;
-
- struct gaih_addrtuple *array = res->at;
- size_t old = 0;
-
- while (array != NULL)
- {
- old++;
- array = array->next;
- }
-
- array = realloc (res->at, (old + count) * sizeof (*array));
-
- if (array == NULL)
- return false;
-
- res->got_ipv6 = family == AF_INET6;
- res->at = array;
- res->free_at = true;
-
- /* Duplicate h_name because it may get reclaimed when the underlying storage
- is freed. */
- if (res->h_name == NULL)
- {
- res->h_name = __strdup (h->h_name);
- if (res->h_name == NULL)
- return false;
- }
-
- /* Update the next pointers on reallocation. */
- for (size_t i = 0; i < old; i++)
- array[i].next = array + i + 1;
-
- array += old;
-
- memset (array, 0, count * sizeof (*array));
-
- for (size_t i = 0; i < count; ++i)
- {
- if (family == AF_INET && req->ai_family == AF_INET6)
- {
- /* Perform address mapping. */
- array[i].family = AF_INET6;
- memcpy(array[i].addr + 3, h->h_addr_list[i], sizeof (uint32_t));
- array[i].addr[2] = htonl (0xffff);
- }
- else
- {
- array[i].family = family;
- memcpy (array[i].addr, h->h_addr_list[i], h->h_length);
- }
- array[i].next = array + i + 1;
- }
- array[count - 1].next = NULL;
-
- return true;
-}
-
-static int
-gethosts (nss_gethostbyname3_r fct, int family, const char *name,
- const struct addrinfo *req, struct scratch_buffer *tmpbuf,
- struct gaih_result *res, enum nss_status *statusp, int *no_datap)
-{
- struct hostent th;
- char *localcanon = NULL;
- enum nss_status status;
-
- *no_datap = 0;
- while (1)
- {
- *statusp = status = DL_CALL_FCT (fct, (name, family, &th,
- tmpbuf->data, tmpbuf->length,
- &errno, &h_errno, NULL,
- &localcanon));
- if (status != NSS_STATUS_TRYAGAIN || h_errno != NETDB_INTERNAL
- || errno != ERANGE)
- break;
- if (!scratch_buffer_grow (tmpbuf))
- return -EAI_MEMORY;
- }
- if (status == NSS_STATUS_NOTFOUND
- || status == NSS_STATUS_TRYAGAIN || status == NSS_STATUS_UNAVAIL)
- {
- if (h_errno == NETDB_INTERNAL)
- return -EAI_SYSTEM;
- if (h_errno == TRY_AGAIN)
- *no_datap = EAI_AGAIN;
- else
- *no_datap = h_errno == NO_DATA;
- }
- else if (status == NSS_STATUS_SUCCESS)
- {
- if (!convert_hostent_to_gaih_addrtuple (req, family, &th, res))
- return -EAI_MEMORY;
-
- if (localcanon != NULL && res->canon == NULL)
- {
- char *canonbuf = __strdup (localcanon);
- if (canonbuf == NULL)
- return -EAI_MEMORY;
- res->canon = canonbuf;
- }
- }
-
- return 0;
-}
-
-/* This function is called if a canonical name is requested, but if
- the service function did not provide it. It tries to obtain the
- name using getcanonname_r from the same service NIP. If the name
- cannot be canonicalized, return a copy of NAME. Return NULL on
- memory allocation failure. The returned string is allocated on the
- heap; the caller has to free it. */
-static char *
-getcanonname (nss_action_list nip, const char *hname, const char *name)
-{
- nss_getcanonname_r *cfct = __nss_lookup_function (nip, "getcanonname_r");
- char *s = (char *) name;
- if (cfct != NULL)
- {
- char buf[256];
- if (DL_CALL_FCT (cfct, (hname ?: name, buf, sizeof (buf), &s, &errno,
- &h_errno)) != NSS_STATUS_SUCCESS)
- /* If the canonical name cannot be determined, use the passed
- string. */
- s = (char *) name;
- }
- return __strdup (s);
-}
-
-/* Process looked up canonical name and if necessary, decode to IDNA. Result
- is a new string written to CANONP and the earlier string is freed. */
-
-static int
-process_canonname (const struct addrinfo *req, const char *orig_name,
- struct gaih_result *res)
-{
- char *canon = res->canon;
-
- if ((req->ai_flags & AI_CANONNAME) != 0)
- {
- bool do_idn = req->ai_flags & AI_CANONIDN;
- if (do_idn)
- {
- char *out;
- int rc = __idna_from_dns_encoding (canon ?: orig_name, &out);
- if (rc == 0)
- {
- free (canon);
- canon = out;
- }
- else if (rc == EAI_IDN_ENCODE)
- /* Use the punycode name as a fallback. */
- do_idn = false;
- else
- return -rc;
- }
- if (!do_idn && canon == NULL && (canon = __strdup (orig_name)) == NULL)
- return -EAI_MEMORY;
- }
-
- res->canon = canon;
- return 0;
-}
-
-static int
-get_servtuples (const struct gaih_service *service, const struct addrinfo *req,
- struct gaih_servtuple *st, struct scratch_buffer *tmpbuf)
-{
- int i;
- const struct gaih_typeproto *tp = gaih_inet_typeproto;
-
- if (req->ai_protocol || req->ai_socktype)
- {
- ++tp;
-
- while (tp->name[0]
- && ((req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
- || (req->ai_protocol != 0
- && !(tp->protoflag & GAI_PROTO_PROTOANY)
- && req->ai_protocol != tp->protocol)))
- ++tp;
-
- if (! tp->name[0])
- {
- if (req->ai_socktype)
- return -EAI_SOCKTYPE;
- else
- return -EAI_SERVICE;
- }
- }
-
- if (service != NULL && (tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
- return -EAI_SERVICE;
-
- if (service == NULL || service->num >= 0)
- {
- int port = service != NULL ? htons (service->num) : 0;
-
- if (req->ai_socktype || req->ai_protocol)
- {
- st[0].socktype = tp->socktype;
- st[0].protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
- ? req->ai_protocol : tp->protocol);
- st[0].port = port;
- st[0].set = true;
-
- return 0;
- }
-
- /* Neither socket type nor protocol is set. Return all socket types
- we know about. */
- for (i = 0, ++tp; tp->name[0]; ++tp)
- if (tp->defaultflag)
- {
- st[i].socktype = tp->socktype;
- st[i].protocol = tp->protocol;
- st[i].port = port;
- st[i++].set = true;
- }
-
- return 0;
- }
-
- if (tp->name[0])
- return gaih_inet_serv (service->name, tp, req, st, tmpbuf);
-
- for (i = 0, tp++; tp->name[0]; tp++)
- {
- if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
- continue;
-
- if (req->ai_socktype != 0
- && req->ai_socktype != tp->socktype)
- continue;
- if (req->ai_protocol != 0
- && !(tp->protoflag & GAI_PROTO_PROTOANY)
- && req->ai_protocol != tp->protocol)
- continue;
-
- if (gaih_inet_serv (service->name,
- tp, req, &st[i], tmpbuf) != 0)
- continue;
-
- i++;
- }
-
- if (!st[0].set)
- return -EAI_SERVICE;
-
- return 0;
-}
-
-#ifdef USE_NSCD
-/* Query addresses from nscd cache, returning a non-zero value on error.
- RES members have the lookup result; RES->AT is NULL if there were no errors
- but also no results. */
-
-static int
-get_nscd_addresses (const char *name, const struct addrinfo *req,
- struct gaih_result *res)
-{
- if (__nss_not_use_nscd_hosts > 0
- && ++__nss_not_use_nscd_hosts > NSS_NSCD_RETRY)
- __nss_not_use_nscd_hosts = 0;
-
- res->at = NULL;
-
- if (__nss_not_use_nscd_hosts || __nss_database_custom[NSS_DBSIDX_hosts])
- return 0;
-
- /* Try to use nscd. */
- struct nscd_ai_result *air = NULL;
- int err = __nscd_getai (name, &air, &h_errno);
-
- if (__glibc_unlikely (air == NULL))
- {
- /* The database contains a negative entry. */
- if (err == 0)
- return -EAI_NONAME;
- if (__nss_not_use_nscd_hosts == 0)
- {
- if (h_errno == NETDB_INTERNAL && errno == ENOMEM)
- return -EAI_MEMORY;
- if (h_errno == TRY_AGAIN)
- return -EAI_AGAIN;
- return -EAI_SYSTEM;
- }
- return 0;
- }
-
- /* Transform into gaih_addrtuple list. */
- int result = 0;
- char *addrs = air->addrs;
-
- struct gaih_addrtuple *addrfree = calloc (air->naddrs, sizeof (*addrfree));
- struct gaih_addrtuple *at = calloc (air->naddrs, sizeof (*at));
- if (at == NULL)
- {
- result = -EAI_MEMORY;
- goto out;
- }
-
- res->free_at = true;
-
- int count = 0;
- for (int i = 0; i < air->naddrs; ++i)
- {
- socklen_t size = (air->family[i] == AF_INET
- ? INADDRSZ : IN6ADDRSZ);
-
- if (!((air->family[i] == AF_INET
- && req->ai_family == AF_INET6
- && (req->ai_flags & AI_V4MAPPED) != 0)
- || req->ai_family == AF_UNSPEC
- || air->family[i] == req->ai_family))
- {
- /* Skip over non-matching result. */
- addrs += size;
- continue;
- }
-
- if (air->family[i] == AF_INET && req->ai_family == AF_INET6
- && (req->ai_flags & AI_V4MAPPED))
- {
- at[count].family = AF_INET6;
- at[count].addr[3] = *(uint32_t *) addrs;
- at[count].addr[2] = htonl (0xffff);
- }
- else if (req->ai_family == AF_UNSPEC
- || air->family[i] == req->ai_family)
- {
- at[count].family = air->family[i];
- memcpy (at[count].addr, addrs, size);
- if (air->family[i] == AF_INET6)
- res->got_ipv6 = true;
- }
- at[count].next = at + count + 1;
- count++;
- addrs += size;
- }
-
- if ((req->ai_flags & AI_CANONNAME) && air->canon != NULL)
- {
- char *canonbuf = __strdup (air->canon);
- if (canonbuf == NULL)
- {
- result = -EAI_MEMORY;
- goto out;
- }
- res->canon = canonbuf;
- }
-
- if (count == 0)
- {
- result = -EAI_NONAME;
- goto out;
- }
-
- at[count - 1].next = NULL;
-
- res->at = at;
-
-out:
- free (air);
- if (result != 0)
- {
- free (at);
- res->free_at = false;
- }
-
- return result;
-}
-#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)
- {
- if ((result = gethosts (fct, AF_INET6, name, req, tmpbuf,
- res, &status, &no_data)) != 0)
- {
- __resolv_context_put (res_ctx);
- goto out;
- }
- 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)))
- {
- if ((resu