(root)/
glibc-2.38/
resolv/
nss_dns/
dns-host.c
       1  /* Copyright (C) 1996-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  /* Parts of this file are plain copies of the file `gethtnamadr.c' from
      19     the bind package and it has the following copyright.  */
      20  
      21  /*
      22   * ++Copyright++ 1985, 1988, 1993
      23   * -
      24   * Copyright (c) 1985, 1988, 1993
      25   *    The Regents of the University of California.  All rights reserved.
      26   *
      27   * Redistribution and use in source and binary forms, with or without
      28   * modification, are permitted provided that the following conditions
      29   * are met:
      30   * 1. Redistributions of source code must retain the above copyright
      31   *    notice, this list of conditions and the following disclaimer.
      32   * 2. Redistributions in binary form must reproduce the above copyright
      33   *    notice, this list of conditions and the following disclaimer in the
      34   *    documentation and/or other materials provided with the distribution.
      35   * 4. Neither the name of the University nor the names of its contributors
      36   *    may be used to endorse or promote products derived from this software
      37   *    without specific prior written permission.
      38   *
      39   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      40   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      41   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      42   * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      43   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      44   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      45   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      46   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      47   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      48   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      49   * SUCH DAMAGE.
      50   * -
      51   * Portions Copyright (c) 1993 by Digital Equipment Corporation.
      52   *
      53   * Permission to use, copy, modify, and distribute this software for any
      54   * purpose with or without fee is hereby granted, provided that the above
      55   * copyright notice and this permission notice appear in all copies, and that
      56   * the name of Digital Equipment Corporation not be used in advertising or
      57   * publicity pertaining to distribution of the document or software without
      58   * specific, written prior permission.
      59   *
      60   * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
      61   * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
      62   * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
      63   * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
      64   * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
      65   * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
      66   * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
      67   * SOFTWARE.
      68   * -
      69   * --Copyright--
      70   */
      71  
      72  #include <alloc_buffer.h>
      73  #include <assert.h>
      74  #include <ctype.h>
      75  #include <errno.h>
      76  #include <netdb.h>
      77  #include <stdio.h>
      78  #include <stdlib.h>
      79  #include <stddef.h>
      80  #include <string.h>
      81  #include <libc-pointer-arith.h>
      82  
      83  #include "nsswitch.h"
      84  #include <arpa/nameser.h>
      85  #include <nss_dns.h>
      86  
      87  #include <resolv/resolv-internal.h>
      88  #include <resolv/resolv_context.h>
      89  
      90  #define RESOLVSORT
      91  
      92  #if PACKETSZ > 65536
      93  # define MAXPACKET	PACKETSZ
      94  #else
      95  # define MAXPACKET	65536
      96  #endif
      97  /* As per RFC 1034 and 1035 a host name cannot exceed 255 octets in length.  */
      98  #ifdef MAXHOSTNAMELEN
      99  # undef MAXHOSTNAMELEN
     100  #endif
     101  #define MAXHOSTNAMELEN 256
     102  
     103  /* For historic reasons, pointers to IP addresses are char *, so use a
     104     single list type for addresses and host names.  */
     105  #define DYNARRAY_STRUCT ptrlist
     106  #define DYNARRAY_ELEMENT char *
     107  #define DYNARRAY_PREFIX ptrlist_
     108  #include <malloc/dynarray-skeleton.c>
     109  
     110  static enum nss_status getanswer_r (unsigned char *packet, size_t packetlen,
     111  				    uint16_t qtype, struct alloc_buffer *abuf,
     112  				    struct ptrlist *addresses,
     113  				    struct ptrlist *aliases,
     114  				    int *errnop, int *h_errnop, int32_t *ttlp);
     115  static void addrsort (struct resolv_context *ctx, char **ap, int num);
     116  static enum nss_status getanswer_ptr (unsigned char *packet, size_t packetlen,
     117  				      struct alloc_buffer *abuf,
     118  				      char **hnamep, int *errnop,
     119  				      int *h_errnop, int32_t *ttlp);
     120  
     121  static enum nss_status gaih_getanswer (unsigned char *packet1,
     122  				       size_t packet1len,
     123  				       unsigned char *packet2,
     124  				       size_t packet2len,
     125  				       struct alloc_buffer *abuf,
     126  				       struct gaih_addrtuple **pat,
     127  				       int *errnop, int *h_errnop,
     128  				       int32_t *ttlp);
     129  static enum nss_status gaih_getanswer_noaaaa (unsigned char *packet,
     130  					      size_t packetlen,
     131  					      struct alloc_buffer *abuf,
     132  					      struct gaih_addrtuple **pat,
     133  					      int *errnop, int *h_errnop,
     134  					      int32_t *ttlp);
     135  
     136  
     137  static enum nss_status gethostbyname3_context (struct resolv_context *ctx,
     138  					       const char *name, int af,
     139  					       struct hostent *result,
     140  					       char *buffer, size_t buflen,
     141  					       int *errnop, int *h_errnop,
     142  					       int32_t *ttlp,
     143  					       char **canonp);
     144  
     145  /* Return the expected RDATA length for an address record type (A or
     146     AAAA).  */
     147  static int
     148  rrtype_to_rdata_length (int type)
     149  {
     150    switch (type)
     151      {
     152      case T_A:
     153        return INADDRSZ;
     154      case T_AAAA:
     155        return IN6ADDRSZ;
     156      default:
     157        return -1;
     158      }
     159  }
     160  
     161  
     162  enum nss_status
     163  _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result,
     164  			   char *buffer, size_t buflen, int *errnop,
     165  			   int *h_errnop, int32_t *ttlp, char **canonp)
     166  {
     167    struct resolv_context *ctx = __resolv_context_get ();
     168    if (ctx == NULL)
     169      {
     170        *errnop = errno;
     171        *h_errnop = NETDB_INTERNAL;
     172        return NSS_STATUS_UNAVAIL;
     173      }
     174    enum nss_status status = gethostbyname3_context
     175      (ctx, name, af, result, buffer, buflen, errnop, h_errnop, ttlp, canonp);
     176    __resolv_context_put (ctx);
     177    return status;
     178  }
     179  libc_hidden_def (_nss_dns_gethostbyname3_r)
     180  
     181  static enum nss_status
     182  gethostbyname3_context (struct resolv_context *ctx,
     183  			const char *name, int af, struct hostent *result,
     184  			char *buffer, size_t buflen, int *errnop,
     185  			int *h_errnop, int32_t *ttlp, char **canonp)
     186  {
     187    char tmp[NS_MAXDNAME];
     188    int size, type, n;
     189    const char *cp;
     190    int olderr = errno;
     191    enum nss_status status;
     192  
     193    switch (af) {
     194    case AF_INET:
     195      size = INADDRSZ;
     196      type = T_A;
     197      break;
     198    case AF_INET6:
     199      size = IN6ADDRSZ;
     200      type = T_AAAA;
     201      break;
     202    default:
     203      *h_errnop = NO_DATA;
     204      *errnop = EAFNOSUPPORT;
     205      return NSS_STATUS_UNAVAIL;
     206    }
     207  
     208    result->h_addrtype = af;
     209    result->h_length = size;
     210  
     211    /*
     212     * if there aren't any dots, it could be a user-level alias.
     213     * this is also done in res_query() since we are not the only
     214     * function that looks up host names.
     215     */
     216    if (strchr (name, '.') == NULL
     217        && (cp = __res_context_hostalias (ctx, name, tmp, sizeof (tmp))) != NULL)
     218      name = cp;
     219  
     220    unsigned char dns_packet_buffer[1024];
     221    unsigned char *alt_dns_packet_buffer = dns_packet_buffer;
     222  
     223    n = __res_context_search (ctx, name, C_IN, type,
     224  			    dns_packet_buffer, sizeof (dns_packet_buffer),
     225  			    &alt_dns_packet_buffer, NULL, NULL, NULL, NULL);
     226    if (n < 0)
     227      {
     228        switch (errno)
     229  	{
     230  	case ESRCH:
     231  	  status = NSS_STATUS_TRYAGAIN;
     232  	  h_errno = TRY_AGAIN;
     233  	  break;
     234  	/* System has run out of file descriptors.  */
     235  	case EMFILE:
     236  	case ENFILE:
     237  	  h_errno = NETDB_INTERNAL;
     238  	  /* Fall through.  */
     239  	case ECONNREFUSED:
     240  	case ETIMEDOUT:
     241  	  status = NSS_STATUS_UNAVAIL;
     242  	  break;
     243  	default:
     244  	  status = NSS_STATUS_NOTFOUND;
     245  	  break;
     246  	}
     247        *h_errnop = h_errno;
     248        if (h_errno == TRY_AGAIN)
     249  	*errnop = EAGAIN;
     250        else
     251  	__set_errno (olderr);
     252      }
     253    else
     254      {
     255        struct alloc_buffer abuf = alloc_buffer_create (buffer, buflen);
     256  
     257        struct ptrlist addresses;
     258        ptrlist_init (&addresses);
     259        struct ptrlist aliases;
     260        ptrlist_init (&aliases);
     261  
     262        status = getanswer_r (alt_dns_packet_buffer, n, type,
     263  			    &abuf, &addresses, &aliases,
     264  			    errnop, h_errnop, ttlp);
     265        if (status == NSS_STATUS_SUCCESS)
     266  	{
     267  	  if (ptrlist_has_failed (&addresses)
     268  	      || ptrlist_has_failed (&aliases))
     269  	    {
     270  	      /* malloc failure.  Do not retry using the ERANGE protocol.  */
     271  	      *errnop = ENOMEM;
     272  	      *h_errnop = NETDB_INTERNAL;
     273  	      status = NSS_STATUS_UNAVAIL;
     274  	    }
     275  
     276  	  /* Reserve the address and alias arrays in the result
     277  	     buffer.  Both are NULL-terminated, but the first element
     278  	     of the alias array is stored in h_name, so no extra space
     279  	     for the NULL terminator is needed there.  */
     280  	  result->h_addr_list
     281  	    = alloc_buffer_alloc_array (&abuf, char *,
     282  					ptrlist_size (&addresses) + 1);
     283  	  result->h_aliases
     284  	    = alloc_buffer_alloc_array (&abuf, char *,
     285  					ptrlist_size (&aliases));
     286  	  if (alloc_buffer_has_failed (&abuf))
     287  	    {
     288  	      /* Retry using the ERANGE protocol.  */
     289  	      *errnop = ERANGE;
     290  	      *h_errnop = NETDB_INTERNAL;
     291  	      status = NSS_STATUS_TRYAGAIN;
     292  	    }
     293  	  else
     294  	    {
     295  	      /* Copy the address list and NULL-terminate it.  */
     296  	      memcpy (result->h_addr_list, ptrlist_begin (&addresses),
     297  		      ptrlist_size (&addresses) * sizeof (char *));
     298  	      result->h_addr_list[ptrlist_size (&addresses)] = NULL;
     299  
     300  	      /* Sort the address list if requested.  */
     301  	      if (type == T_A && __resolv_context_sort_count (ctx) > 0)
     302  		addrsort (ctx, result->h_addr_list, ptrlist_size (&addresses));
     303  
     304  	      /* Copy the aliases,  excluding the last one. */
     305  	      memcpy (result->h_aliases, ptrlist_begin (&aliases),
     306  		      (ptrlist_size (&aliases) - 1) * sizeof (char *));
     307  	      result->h_aliases[ptrlist_size (&aliases) - 1] = NULL;
     308  
     309  	      /* The last alias goes into h_name.  */
     310  	      assert (ptrlist_size (&aliases) >= 1);
     311  	      result->h_name = ptrlist_end (&aliases)[-1];
     312  
     313  	      /* This is also the canonical name.  */
     314  	      if (canonp != NULL)
     315  		*canonp = result->h_name;
     316  	    }
     317  	}
     318  
     319        ptrlist_free (&aliases);
     320        ptrlist_free (&addresses);
     321      }
     322  
     323    if (alt_dns_packet_buffer != dns_packet_buffer)
     324      free (alt_dns_packet_buffer);
     325    return status;
     326  }
     327  
     328  /* Verify that the name looks like a host name.  There is no point in
     329     sending a query which will not produce a usable name in the
     330     response.  */
     331  static enum nss_status
     332  check_name (const char *name, int *h_errnop)
     333  {
     334    if (__libc_res_hnok (name))
     335      return NSS_STATUS_SUCCESS;
     336    *h_errnop = HOST_NOT_FOUND;
     337    return NSS_STATUS_NOTFOUND;
     338  }
     339  
     340  enum nss_status
     341  _nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result,
     342  			   char *buffer, size_t buflen, int *errnop,
     343  			   int *h_errnop)
     344  {
     345    enum nss_status status = check_name (name, h_errnop);
     346    if (status != NSS_STATUS_SUCCESS)
     347      return status;
     348    return _nss_dns_gethostbyname3_r (name, af, result, buffer, buflen, errnop,
     349  				    h_errnop, NULL, NULL);
     350  }
     351  libc_hidden_def (_nss_dns_gethostbyname2_r)
     352  
     353  enum nss_status
     354  _nss_dns_gethostbyname_r (const char *name, struct hostent *result,
     355  			  char *buffer, size_t buflen, int *errnop,
     356  			  int *h_errnop)
     357  {
     358    enum nss_status status = check_name (name, h_errnop);
     359    if (status != NSS_STATUS_SUCCESS)
     360      return status;
     361    struct resolv_context *ctx = __resolv_context_get ();
     362    if (ctx == NULL)
     363      {
     364        *errnop = errno;
     365        *h_errnop = NETDB_INTERNAL;
     366        return NSS_STATUS_UNAVAIL;
     367      }
     368    status = gethostbyname3_context (ctx, name, AF_INET, result, buffer,
     369  				   buflen, errnop, h_errnop, NULL, NULL);
     370    __resolv_context_put (ctx);
     371    return status;
     372  }
     373  libc_hidden_def (_nss_dns_gethostbyname_r)
     374  
     375  enum nss_status
     376  _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
     377  			   char *buffer, size_t buflen, int *errnop,
     378  			   int *herrnop, int32_t *ttlp)
     379  {
     380    enum nss_status status = check_name (name, herrnop);
     381    if (status != NSS_STATUS_SUCCESS)
     382      return status;
     383    struct resolv_context *ctx = __resolv_context_get ();
     384    if (ctx == NULL)
     385      {
     386        *errnop = errno;
     387        *herrnop = NETDB_INTERNAL;
     388        return NSS_STATUS_UNAVAIL;
     389      }
     390  
     391    /*
     392     * if there aren't any dots, it could be a user-level alias.
     393     * this is also done in res_query() since we are not the only
     394     * function that looks up host names.
     395     */
     396    if (strchr (name, '.') == NULL)
     397      {
     398        char *tmp = alloca (NS_MAXDNAME);
     399        const char *cp = __res_context_hostalias (ctx, name, tmp, NS_MAXDNAME);
     400        if (cp != NULL)
     401  	name = cp;
     402      }
     403  
     404    unsigned char dns_packet_buffer[2048];
     405    unsigned char *alt_dns_packet_buffer = dns_packet_buffer;
     406    u_char *ans2p = NULL;
     407    int nans2p = 0;
     408    int resplen2 = 0;
     409    int ans2p_malloced = 0;
     410    struct alloc_buffer abuf = alloc_buffer_create (buffer, buflen);
     411  
     412  
     413    int olderr = errno;
     414    int n;
     415  
     416    if ((ctx->resp->options & RES_NOAAAA) == 0)
     417      {
     418        n = __res_context_search (ctx, name, C_IN, T_QUERY_A_AND_AAAA,
     419  				dns_packet_buffer, sizeof (dns_packet_buffer),
     420  				&alt_dns_packet_buffer, &ans2p, &nans2p,
     421  				&resplen2, &ans2p_malloced);
     422        if (n >= 0)
     423  	status = gaih_getanswer (alt_dns_packet_buffer, n, ans2p, resplen2,
     424  				 &abuf, pat, errnop, herrnop, ttlp);
     425      }
     426    else
     427      {
     428        n = __res_context_search (ctx, name, C_IN, T_A,
     429  				dns_packet_buffer, sizeof (dns_packet_buffer),
     430  				NULL, NULL, NULL, NULL, NULL);
     431        if (n >= 0)
     432  	status = gaih_getanswer_noaaaa (alt_dns_packet_buffer, n,
     433  					&abuf, pat, errnop, herrnop, ttlp);
     434      }
     435    if (n < 0)
     436      {
     437        switch (errno)
     438  	{
     439  	case ESRCH:
     440  	  status = NSS_STATUS_TRYAGAIN;
     441  	  h_errno = TRY_AGAIN;
     442  	  break;
     443  	/* System has run out of file descriptors.  */
     444  	case EMFILE:
     445  	case ENFILE:
     446  	  h_errno = NETDB_INTERNAL;
     447  	  /* Fall through.  */
     448  	case ECONNREFUSED:
     449  	case ETIMEDOUT:
     450  	  status = NSS_STATUS_UNAVAIL;
     451  	  break;
     452  	default:
     453  	  status = NSS_STATUS_NOTFOUND;
     454  	  break;
     455  	}
     456  
     457        *herrnop = h_errno;
     458        if (h_errno == TRY_AGAIN)
     459  	*errnop = EAGAIN;
     460        else
     461  	__set_errno (olderr);
     462      }
     463  
     464    /* Implement the buffer resizing protocol.  */
     465    if (alloc_buffer_has_failed (&abuf))
     466      {
     467        *errnop = ERANGE;
     468        *herrnop = NETDB_INTERNAL;
     469        status = NSS_STATUS_TRYAGAIN;
     470      }
     471  
     472    /* Check whether ans2p was separately allocated.  */
     473    if (ans2p_malloced)
     474      free (ans2p);
     475  
     476    if (alt_dns_packet_buffer != dns_packet_buffer)
     477      free (alt_dns_packet_buffer);
     478  
     479    __resolv_context_put (ctx);
     480    return status;
     481  }
     482  libc_hidden_def (_nss_dns_gethostbyname4_r)
     483  
     484  enum nss_status
     485  _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af,
     486  			   struct hostent *result, char *buffer, size_t buflen,
     487  			   int *errnop, int *h_errnop, int32_t *ttlp)
     488  {
     489    static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
     490    static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
     491    static const u_char v6local[] = { 0,0, 0,1 };
     492    const u_char *uaddr = (const u_char *)addr;
     493    char qbuf[MAXDNAME+1], *qp = NULL;
     494    size_t size;
     495    int n, status;
     496    int olderr = errno;
     497  
     498    /* Prepare the allocation buffer.  Store the pointer array first, to
     499       benefit from buffer alignment.  */
     500    struct alloc_buffer abuf = alloc_buffer_create (buffer, buflen);
     501    char **address_array = alloc_buffer_alloc_array (&abuf, char *, 2);
     502    if (address_array == NULL)
     503      {
     504        *errnop = ERANGE;
     505        *h_errnop = NETDB_INTERNAL;
     506        return NSS_STATUS_TRYAGAIN;
     507      }
     508  
     509    struct resolv_context *ctx = __resolv_context_get ();
     510    if (ctx == NULL)
     511      {
     512        *errnop = errno;
     513        *h_errnop = NETDB_INTERNAL;
     514        return NSS_STATUS_UNAVAIL;
     515      }
     516  
     517    if (af == AF_INET6 && len == IN6ADDRSZ
     518        && (memcmp (uaddr, mapped, sizeof mapped) == 0
     519  	  || (memcmp (uaddr, tunnelled, sizeof tunnelled) == 0
     520  	      && memcmp (&uaddr[sizeof tunnelled], v6local, sizeof v6local))))
     521      {
     522        /* Unmap. */
     523        addr += sizeof mapped;
     524        uaddr += sizeof mapped;
     525        af = AF_INET;
     526        len = INADDRSZ;
     527      }
     528  
     529    switch (af)
     530      {
     531      case AF_INET:
     532        size = INADDRSZ;
     533        break;
     534      case AF_INET6:
     535        size = IN6ADDRSZ;
     536        break;
     537      default:
     538        *errnop = EAFNOSUPPORT;
     539        *h_errnop = NETDB_INTERNAL;
     540        __resolv_context_put (ctx);
     541        return NSS_STATUS_UNAVAIL;
     542      }
     543    if (size > len)
     544      {
     545        *errnop = EAFNOSUPPORT;
     546        *h_errnop = NETDB_INTERNAL;
     547        __resolv_context_put (ctx);
     548        return NSS_STATUS_UNAVAIL;
     549      }
     550  
     551    switch (af)
     552      {
     553      case AF_INET:
     554        sprintf (qbuf, "%u.%u.%u.%u.in-addr.arpa", (uaddr[3] & 0xff),
     555  	       (uaddr[2] & 0xff), (uaddr[1] & 0xff), (uaddr[0] & 0xff));
     556        break;
     557      case AF_INET6:
     558        qp = qbuf;
     559        for (n = IN6ADDRSZ - 1; n >= 0; n--)
     560  	{
     561  	  static const char nibblechar[16] = "0123456789abcdef";
     562  	  *qp++ = nibblechar[uaddr[n] & 0xf];
     563  	  *qp++ = '.';
     564  	  *qp++ = nibblechar[(uaddr[n] >> 4) & 0xf];
     565  	  *qp++ = '.';
     566  	}
     567        strcpy(qp, "ip6.arpa");
     568        break;
     569      default:
     570        /* Cannot happen.  */
     571        break;
     572      }
     573  
     574    unsigned char dns_packet_buffer[1024];
     575    unsigned char *alt_dns_packet_buffer = dns_packet_buffer;
     576    n = __res_context_query (ctx, qbuf, C_IN, T_PTR,
     577  			   dns_packet_buffer, sizeof (dns_packet_buffer),
     578  			   &alt_dns_packet_buffer,
     579  			   NULL, NULL, NULL, NULL);
     580    if (n < 0)
     581      {
     582        *h_errnop = h_errno;
     583        __set_errno (olderr);
     584        if (alt_dns_packet_buffer != dns_packet_buffer)
     585  	free (alt_dns_packet_buffer);
     586        __resolv_context_put (ctx);
     587        return errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
     588      }
     589  
     590    status = getanswer_ptr (alt_dns_packet_buffer, n,
     591  			  &abuf, &result->h_name, errnop, h_errnop, ttlp);
     592  
     593    if (alt_dns_packet_buffer != dns_packet_buffer)
     594      free (alt_dns_packet_buffer);
     595    __resolv_context_put (ctx);
     596  
     597    if (status != NSS_STATUS_SUCCESS)
     598      return status;
     599  
     600    /* result->h_name has already been set by getanswer_ptr.  */
     601    result->h_addrtype = af;
     602    result->h_length = len;
     603    /* Increase the alignment to 4, in case there are applications out
     604       there that expect at least this level of address alignment.  */
     605    address_array[0] = (char *) alloc_buffer_next (&abuf, uint32_t);
     606    alloc_buffer_copy_bytes (&abuf, uaddr, len);
     607    address_array[1] = NULL;
     608  
     609    /* This check also covers allocation failure in getanswer_ptr.  */
     610    if (alloc_buffer_has_failed (&abuf))
     611      {
     612        *errnop = ERANGE;
     613        *h_errnop = NETDB_INTERNAL;
     614        return NSS_STATUS_TRYAGAIN;
     615      }
     616    result->h_addr_list = address_array;
     617    result->h_aliases = &address_array[1]; /* Points to NULL.  */
     618  
     619    *h_errnop = NETDB_SUCCESS;
     620    return NSS_STATUS_SUCCESS;
     621  }
     622  libc_hidden_def (_nss_dns_gethostbyaddr2_r)
     623  
     624  
     625  enum nss_status
     626  _nss_dns_gethostbyaddr_r (const void *addr, socklen_t len, int af,
     627  			  struct hostent *result, char *buffer, size_t buflen,
     628  			  int *errnop, int *h_errnop)
     629  {
     630    return _nss_dns_gethostbyaddr2_r (addr, len, af, result, buffer, buflen,
     631  				    errnop, h_errnop, NULL);
     632  }
     633  libc_hidden_def (_nss_dns_gethostbyaddr_r)
     634  
     635  static void
     636  addrsort (struct resolv_context *ctx, char **ap, int num)
     637  {
     638    int i, j;
     639    char **p;
     640    short aval[MAX_NR_ADDRS];
     641    int needsort = 0;
     642    size_t nsort = __resolv_context_sort_count (ctx);
     643  
     644    p = ap;
     645    if (num > MAX_NR_ADDRS)
     646      num = MAX_NR_ADDRS;
     647    for (i = 0; i < num; i++, p++)
     648      {
     649        for (j = 0 ; (unsigned)j < nsort; j++)
     650  	{
     651  	  struct resolv_sortlist_entry e
     652  	    = __resolv_context_sort_entry (ctx, j);
     653  	  if (e.addr.s_addr == (((struct in_addr *)(*p))->s_addr & e.mask))
     654  	    break;
     655  	}
     656        aval[i] = j;
     657        if (needsort == 0 && i > 0 && j < aval[i-1])
     658  	needsort = i;
     659      }
     660    if (!needsort)
     661      return;
     662  
     663    while (needsort++ < num)
     664      for (j = needsort - 2; j >= 0; j--)
     665        if (aval[j] > aval[j+1])
     666  	{
     667  	  char *hp;
     668  
     669  	  i = aval[j];
     670  	  aval[j] = aval[j+1];
     671  	  aval[j+1] = i;
     672  
     673  	  hp = ap[j];
     674  	  ap[j] = ap[j+1];
     675  	  ap[j+1] = hp;
     676  	}
     677        else
     678  	break;
     679  }
     680  
     681  /* Convert the uncompressed, binary domain name CDNAME into its
     682     textual representation and add it to the end of ALIASES, allocating
     683     space for a copy of the name from ABUF.  Skip adding the name if it
     684     is not a valid host name, and return false in that case, otherwise
     685     true.  */
     686  static bool
     687  getanswer_r_store_alias (const unsigned char *cdname,
     688  			 struct alloc_buffer *abuf,
     689  			 struct ptrlist *aliases)
     690  {
     691    /* Filter out domain names that are not host names.  */
     692    if (!__res_binary_hnok (cdname))
     693      return false;
     694  
     695    /* Note: Not NS_MAXCDNAME, so that __ns_name_ntop implicitly checks
     696       for length.  */
     697    char dname[MAXHOSTNAMELEN + 1];
     698    if (__ns_name_ntop (cdname, dname, sizeof (dname)) < 0)
     699      return false;
     700    /* Do not report an error on allocation failure, instead store NULL
     701       or do nothing.  getanswer_r's caller will see NSS_STATUS_SUCCESS
     702       and detect the memory allocation failure or buffer space
     703       exhaustion, and report it accordingly.  */
     704    ptrlist_add (aliases, alloc_buffer_copy_string (abuf, dname));
     705    return true;
     706  }
     707  
     708  static enum nss_status __attribute__ ((noinline))
     709  getanswer_r (unsigned char *packet, size_t packetlen, uint16_t qtype,
     710  	     struct alloc_buffer *abuf,
     711  	     struct ptrlist *addresses, struct ptrlist *aliases,
     712  	     int *errnop, int *h_errnop, int32_t *ttlp)
     713  {
     714    struct ns_rr_cursor c;
     715    if (!__ns_rr_cursor_init (&c, packet, packetlen))
     716      {
     717        /* This should not happen because __res_context_query already
     718  	 performs response validation.  */
     719        *h_errnop = NO_RECOVERY;
     720        return NSS_STATUS_UNAVAIL;
     721      }
     722  
     723    /* Treat the QNAME just like an alias.  Error out if it is not a
     724       valid host name.  */
     725    if (ns_rr_cursor_rcode (&c) == NXDOMAIN
     726        || !getanswer_r_store_alias (ns_rr_cursor_qname (&c), abuf, aliases))
     727      {
     728        if (ttlp != NULL)
     729  	/* No negative caching.  */
     730  	*ttlp = 0;
     731        *h_errnop = HOST_NOT_FOUND;
     732        *errnop = ENOENT;
     733        return NSS_STATUS_NOTFOUND;
     734      }
     735  
     736    int ancount = ns_rr_cursor_ancount (&c);
     737    const unsigned char *expected_name = ns_rr_cursor_qname (&c);
     738    /* expected_name may be updated to point into this buffer.  */
     739    unsigned char name_buffer[NS_MAXCDNAME];
     740  
     741    for (; ancount > 0; --ancount)
     742      {
     743        struct ns_rr_wire rr;
     744        if (!__ns_rr_cursor_next (&c, &rr))
     745  	{
     746  	  *h_errnop = NO_RECOVERY;
     747  	  return NSS_STATUS_UNAVAIL;
     748  	}
     749  
     750        /* Skip over records with the wrong class.  */
     751        if (rr.rclass != C_IN)
     752  	continue;
     753  
     754        /* Update TTL for recognized record types.  */
     755        if ((rr.rtype == T_CNAME || rr.rtype == qtype)
     756  	  && ttlp != NULL && *ttlp > rr.ttl)
     757  	*ttlp = rr.ttl;
     758  
     759        if (rr.rtype == T_CNAME)
     760  	{
     761  	  /* NB: No check for owner name match, based on historic
     762  	     precedent.  Record the CNAME target as the new expected
     763  	     name.  */
     764  	  int n = __ns_name_unpack (c.begin, c.end, rr.rdata,
     765  				    name_buffer, sizeof (name_buffer));
     766  	  if (n < 0)
     767  	    {
     768  	      *h_errnop = NO_RECOVERY;
     769  	      return NSS_STATUS_UNAVAIL;
     770  	    }
     771  	  /* And store the new name as an alias.  */
     772  	  getanswer_r_store_alias (name_buffer, abuf, aliases);
     773  	  expected_name = name_buffer;
     774  	}
     775        else if (rr.rtype == qtype
     776  	       && __ns_samebinaryname (rr.rname, expected_name)
     777  	       && rr.rdlength == rrtype_to_rdata_length (qtype))
     778  	{
     779  	  /* Make a copy of the address and store it.  Increase the
     780  	     alignment to 4, in case there are applications out there
     781  	     that expect at least this level of address alignment.  */
     782  	  ptrlist_add (addresses, (char *) alloc_buffer_next (abuf, uint32_t));
     783  	  alloc_buffer_copy_bytes (abuf, rr.rdata, rr.rdlength);
     784  	}
     785      }
     786  
     787    if (ptrlist_size (addresses) == 0)
     788      {
     789        /* No address record found.  */
     790        if (ttlp != NULL)
     791  	/* No caching of negative responses.  */
     792  	*ttlp = 0;
     793  
     794        *h_errnop = NO_RECOVERY;
     795        *errnop = ENOENT;
     796        return NSS_STATUS_TRYAGAIN;
     797      }
     798    else
     799      {
     800        *h_errnop = NETDB_SUCCESS;
     801        return NSS_STATUS_SUCCESS;
     802      }
     803  }
     804  
     805  static enum nss_status
     806  getanswer_ptr (unsigned char *packet, size_t packetlen,
     807  	       struct alloc_buffer *abuf, char **hnamep,
     808  	       int *errnop, int *h_errnop, int32_t *ttlp)
     809  {
     810    struct ns_rr_cursor c;
     811    if (!__ns_rr_cursor_init (&c, packet, packetlen))
     812      {
     813        /* This should not happen because __res_context_query already
     814  	 performs response validation.  */
     815        *h_errnop = NO_RECOVERY;
     816        return NSS_STATUS_UNAVAIL;
     817      }
     818    int ancount = ns_rr_cursor_ancount (&c);
     819    const unsigned char *expected_name = ns_rr_cursor_qname (&c);
     820    /* expected_name may be updated to point into this buffer.  */
     821    unsigned char name_buffer[NS_MAXCDNAME];
     822  
     823    while (ancount > 0)
     824      {
     825        struct ns_rr_wire rr;
     826        if (!__ns_rr_cursor_next (&c, &rr))
     827  	{
     828  	  *h_errnop = NO_RECOVERY;
     829  	  return NSS_STATUS_UNAVAIL;
     830  	}
     831  
     832        /* Skip over records with the wrong class.  */
     833        if (rr.rclass != C_IN)
     834  	continue;
     835  
     836        /* Update TTL for known record types.  */
     837        if ((rr.rtype == T_CNAME || rr.rtype == T_PTR)
     838  	  && ttlp != NULL && *ttlp > rr.ttl)
     839  	*ttlp = rr.ttl;
     840  
     841        if (rr.rtype == T_CNAME)
     842  	{
     843  	  /* NB: No check for owner name match, based on historic
     844  	     precedent.  Record the CNAME target as the new expected
     845  	     name.  */
     846  	  int n = __ns_name_unpack (c.begin, c.end, rr.rdata,
     847  				    name_buffer, sizeof (name_buffer));
     848  	  if (n < 0)
     849  	    {
     850  	      *h_errnop = NO_RECOVERY;
     851  	      return NSS_STATUS_UNAVAIL;
     852  	    }
     853  	  expected_name = name_buffer;
     854  	}
     855        else if (rr.rtype == T_PTR
     856  	       && __ns_samebinaryname (rr.rname, expected_name))
     857  	{
     858  	  /* Decompress the target of the PTR record.  This is the
     859  	     host name we are looking for.  We can only use it if it
     860  	     is syntactically valid.  Historically, only one host name
     861  	     is returned here.  If the recursive resolver performs DNS
     862  	     record rotation, the returned host name is essentially
     863  	     random, which is why multiple PTR records are rarely
     864  	     used.  Use MAXHOSTNAMELEN instead of NS_MAXCDNAME for
     865  	     additional length checking.  */
     866  	  char hname[MAXHOSTNAMELEN + 1];
     867  	  if (__ns_name_unpack (c.begin, c.end, rr.rdata,
     868  				name_buffer, sizeof (name_buffer)) < 0
     869  	      || !__res_binary_hnok (expected_name)
     870  	      || __ns_name_ntop (name_buffer, hname, sizeof (hname)) < 0)
     871  	    {
     872  	      *h_errnop = NO_RECOVERY;
     873  	      return NSS_STATUS_UNAVAIL;
     874  	    }
     875  	  /* Successful allocation is checked by the caller.  */
     876  	  *hnamep = alloc_buffer_copy_string (abuf, hname);
     877  	  return NSS_STATUS_SUCCESS;
     878  	}
     879      }
     880  
     881    /* No PTR record found.  */
     882    if (ttlp != NULL)
     883      /* No caching of negative responses.  */
     884      *ttlp = 0;
     885  
     886    *h_errnop = NO_RECOVERY;
     887    *errnop = ENOENT;
     888    return NSS_STATUS_TRYAGAIN;
     889  }
     890  
     891  /* Parses DNS data found in PACKETLEN bytes at PACKET in struct
     892     gaih_addrtuple address tuples.  The new address tuples are linked
     893     from **TAILP, with backing store allocated from ABUF, and *TAILP is
     894     updated to point where the next tuple pointer should be stored.  If
     895     TTLP is not null, *TTLP is updated to reflect the minimum TTL.  If
     896     STORE_CANON is true, the canonical name is stored as part of the
     897     first address tuple being written.  */
     898  static enum nss_status
     899  gaih_getanswer_slice (unsigned char *packet, size_t packetlen,
     900  		      struct alloc_buffer *abuf,
     901  		      struct gaih_addrtuple ***tailp,
     902  		      int *errnop, int *h_errnop, int32_t *ttlp,
     903  		      bool store_canon)
     904  {
     905    struct ns_rr_cursor c;
     906    if (!__ns_rr_cursor_init (&c, packet, packetlen))
     907      {
     908        /* This should not happen because __res_context_query already
     909  	 performs response validation.  */
     910        *h_errnop = NO_RECOVERY;
     911        return NSS_STATUS_UNAVAIL;
     912      }
     913    bool haveanswer = false; /* Set to true if at least one address.  */
     914    uint16_t qtype = ns_rr_cursor_qtype (&c);
     915    int ancount = ns_rr_cursor_ancount (&c);
     916    const unsigned char *expected_name = ns_rr_cursor_qname (&c);
     917    /* expected_name may be updated to point into this buffer.  */
     918    unsigned char name_buffer[NS_MAXCDNAME];
     919  
     920    /* This is a pointer to a possibly-compressed name in the packet.
     921       Eventually it is equivalent to the canonical name.  If needed, it
     922       is uncompressed and translated to text form when the first
     923       address tuple is encountered.  */
     924    const unsigned char *compressed_alias_name = expected_name;
     925  
     926    if (ancount == 0 || !__res_binary_hnok (compressed_alias_name))
     927      {
     928        *h_errnop = HOST_NOT_FOUND;
     929        return NSS_STATUS_NOTFOUND;
     930      }
     931  
     932    for (; ancount > -0; --ancount)
     933      {
     934        struct ns_rr_wire rr;
     935        if (!__ns_rr_cursor_next (&c, &rr))
     936  	{
     937  	  *h_errnop = NO_RECOVERY;
     938  	  return NSS_STATUS_UNAVAIL;
     939  	}
     940  
     941        /* Update TTL for known record types.  */
     942        if ((rr.rtype == T_CNAME || rr.rtype == qtype)
     943  	  && ttlp != NULL && *ttlp > rr.ttl)
     944  	*ttlp = rr.ttl;
     945  
     946        if (rr.rtype == T_CNAME)
     947  	{
     948  	  /* NB: No check for owner name match, based on historic
     949  	     precedent.  Record the CNAME target as the new expected
     950  	     name.  */
     951  	  int n = __ns_name_unpack (c.begin, c.end, rr.rdata,
     952  				    name_buffer, sizeof (name_buffer));
     953  	  if (n < 0)
     954  	    {
     955  	      *h_errnop = NO_RECOVERY;
     956  	      return NSS_STATUS_UNAVAIL;
     957  	    }
     958  	  expected_name = name_buffer;
     959  	  if (store_canon && __res_binary_hnok (name_buffer))
     960  	    /* This name can be used as a canonical name.  Do not
     961  	       translate to text form here to conserve buffer space.
     962  	       Point to the compressed name because name_buffer can be
     963  	       overwritten with an unusable name later.  */
     964  	    compressed_alias_name = rr.rdata;
     965  	}
     966        else if (rr.rtype == qtype
     967  	       && __ns_samebinaryname (rr.rname, expected_name)
     968  	       && rr.rdlength == rrtype_to_rdata_length (qtype))
     969  	{
     970  	  struct gaih_addrtuple *ntup
     971  	    = alloc_buffer_alloc (abuf, struct gaih_addrtuple);
     972  	  /* Delay error reporting to the callers (they implement the
     973  	     ERANGE buffer resizing handshake).  */
     974  	  if (ntup != NULL)
     975  	    {
     976  	      ntup->next = NULL;
     977  	      if (store_canon && compressed_alias_name != NULL)
     978  		{
     979  		  /* This assumes that all the CNAME records come
     980  		     first.  Use MAXHOSTNAMELEN instead of
     981  		     NS_MAXCDNAME for additional length checking.
     982  		     However, these checks are not expected to fail
     983  		     because all size NS_MAXCDNAME names should into
     984  		     the hname buffer because no escaping is
     985  		     needed.  */
     986  		  char unsigned nbuf[NS_MAXCDNAME];
     987  		  char hname[MAXHOSTNAMELEN + 1];
     988  		  if (__ns_name_unpack (c.begin, c.end,
     989  					compressed_alias_name,
     990  					nbuf, sizeof (nbuf)) >= 0
     991  		      && __ns_name_ntop (nbuf, hname, sizeof (hname)) >= 0)
     992  		    /* Space checking is performed by the callers.  */
     993  		    ntup->name = alloc_buffer_copy_string (abuf, hname);
     994  		  store_canon = false;
     995  		}
     996  	      else
     997  		ntup->name = NULL;
     998  	      if (rr.rdlength == 4)
     999  		ntup->family = AF_INET;
    1000  	      else
    1001  		ntup->family = AF_INET6;
    1002  	      memcpy (ntup->addr, rr.rdata, rr.rdlength);
    1003  	      ntup->scopeid = 0;
    1004  
    1005  	      /* Link in the new tuple, and update the tail pointer to
    1006  		 point to its next field.  */
    1007  	      **tailp = ntup;
    1008  	      *tailp = &ntup->next;
    1009  
    1010  	      haveanswer = true;
    1011  	    }
    1012  	}
    1013      }
    1014  
    1015    if (haveanswer)
    1016      {
    1017        *h_errnop = NETDB_SUCCESS;
    1018        return NSS_STATUS_SUCCESS;
    1019      }
    1020    else
    1021      {
    1022        /* Special case here: if the resolver sent a result but it only
    1023  	 contains a CNAME while we are looking for a T_A or T_AAAA
    1024  	 record, we fail with NOTFOUND.  */
    1025        *h_errnop = HOST_NOT_FOUND;
    1026        return NSS_STATUS_NOTFOUND;
    1027      }
    1028  }
    1029  
    1030  
    1031  static enum nss_status
    1032  gaih_getanswer (unsigned char *packet1, size_t packet1len,
    1033  		unsigned char *packet2, size_t packet2len,
    1034  		struct alloc_buffer *abuf, struct gaih_addrtuple **pat,
    1035  		int *errnop, int *h_errnop, int32_t *ttlp)
    1036  {
    1037    enum nss_status status = NSS_STATUS_NOTFOUND;
    1038  
    1039    /* Combining the NSS status of two distinct queries requires some
    1040       compromise and attention to symmetry (A or AAAA queries can be
    1041       returned in any order).  What follows is a breakdown of how this
    1042       code is expected to work and why. We discuss only SUCCESS,
    1043       TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns
    1044       that apply (though RETURN and MERGE exist).  We make a distinction
    1045       between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable).
    1046       A recoverable TRYAGAIN is almost always due to buffer size issues
    1047       and returns ERANGE in errno and the caller is expected to retry
    1048       with a larger buffer.  (The caller, _nss_dns_gethostbyname4_r,
    1049       ignores the return status if it detects that the result buffer
    1050       has been exhausted and generates a TRYAGAIN failure with an
    1051       ERANGE code.)
    1052  
    1053       Lastly, you may be tempted to make significant changes to the
    1054       conditions in this code to bring about symmetry between responses.
    1055       Please don't change anything without due consideration for
    1056       expected application behaviour.  Some of the synthesized responses
    1057       aren't very well thought out and sometimes appear to imply that
    1058       IPv4 responses are always answer 1, and IPv6 responses are always
    1059       answer 2, but that's not true (see the implementation of send_dg
    1060       and send_vc to see response can arrive in any order, particularly
    1061       for UDP). However, we expect it holds roughly enough of the time
    1062       that this code works, but certainly needs to be fixed to make this
    1063       a more robust implementation.
    1064  
    1065       ----------------------------------------------
    1066       | Answer 1 Status /   | Synthesized | Reason |
    1067       | Answer 2 Status     | Status      |        |
    1068       |--------------------------------------------|
    1069       | SUCCESS/SUCCESS     | SUCCESS     | [1]    |
    1070       | SUCCESS/TRYAGAIN    | TRYAGAIN    | [5]    |
    1071       | SUCCESS/TRYAGAIN'   | SUCCESS     | [1]    |
    1072       | SUCCESS/NOTFOUND    | SUCCESS     | [1]    |
    1073       | SUCCESS/UNAVAIL     | SUCCESS     | [1]    |
    1074       | TRYAGAIN/SUCCESS    | TRYAGAIN    | [2]    |
    1075       | TRYAGAIN/TRYAGAIN   | TRYAGAIN    | [2]    |
    1076       | TRYAGAIN/TRYAGAIN'  | TRYAGAIN    | [2]    |
    1077       | TRYAGAIN/NOTFOUND   | TRYAGAIN    | [2]    |
    1078       | TRYAGAIN/UNAVAIL    | TRYAGAIN    | [2]    |
    1079       | TRYAGAIN'/SUCCESS   | SUCCESS     | [3]    |
    1080       | TRYAGAIN'/TRYAGAIN  | TRYAGAIN    | [3]    |
    1081       | TRYAGAIN'/TRYAGAIN' | TRYAGAIN'   | [3]    |
    1082       | TRYAGAIN'/NOTFOUND  | TRYAGAIN'   | [3]    |
    1083       | TRYAGAIN'/UNAVAIL   | UNAVAIL     | [3]    |
    1084       | NOTFOUND/SUCCESS    | SUCCESS     | [3]    |
    1085       | NOTFOUND/TRYAGAIN   | TRYAGAIN    | [3]    |
    1086       | NOTFOUND/TRYAGAIN'  | TRYAGAIN'   | [3]    |
    1087       | NOTFOUND/NOTFOUND   | NOTFOUND    | [3]    |
    1088       | NOTFOUND/UNAVAIL    | UNAVAIL     | [3]    |
    1089       | UNAVAIL/SUCCESS     | UNAVAIL     | [4]    |
    1090       | UNAVAIL/TRYAGAIN    | UNAVAIL     | [4]    |
    1091       | UNAVAIL/TRYAGAIN'   | UNAVAIL     | [4]    |
    1092       | UNAVAIL/NOTFOUND    | UNAVAIL     | [4]    |
    1093       | UNAVAIL/UNAVAIL     | UNAVAIL     | [4]    |
    1094       ----------------------------------------------
    1095  
    1096       [1] If the first response is a success we return success.
    1097  	 This ignores the state of the second answer and in fact
    1098  	 incorrectly sets errno and h_errno to that of the second
    1099  	 answer.  However because the response is a success we ignore
    1100  	 *errnop and *h_errnop (though that means you touched errno on
    1101  	 success).  We are being conservative here and returning the
    1102  	 likely IPv4 response in the first answer as a success.
    1103  
    1104       [2] If the first response is a recoverable TRYAGAIN we return
    1105  	 that instead of looking at the second response.  The
    1106  	 expectation here is that we have failed to get an IPv4 response
    1107  	 and should retry both queries.
    1108  
    1109       [3] If the first response was not a SUCCESS and the second
    1110  	 response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN,
    1111  	 or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the
    1112  	 result from the second response, otherwise the first responses
    1113  	 status is used.  Again we have some odd side-effects when the
    1114  	 second response is NOTFOUND because we overwrite *errnop and
    1115  	 *h_errnop that means that a first answer of NOTFOUND might see
    1116  	 its *errnop and *h_errnop values altered.  Whether it matters
    1117  	 in practice that a first response NOTFOUND has the wrong
    1118  	 *errnop and *h_errnop is undecided.
    1119  
    1120       [4] If the first response is UNAVAIL we return that instead of
    1121  	 looking at the second response.  The expectation here is that
    1122  	 it will have failed similarly e.g. configuration failure.
    1123  
    1124       [5] Testing this code is complicated by the fact that truncated
    1125  	 second response buffers might be returned as SUCCESS if the
    1126  	 first answer is a SUCCESS.  To fix this we add symmetry to
    1127  	 TRYAGAIN with the second response.  If the second response
    1128  	 is a recoverable error we now return TRYAGIN even if the first
    1129  	 response was SUCCESS.  */
    1130  
    1131    if (packet1len > 0)
    1132      {
    1133        status = gaih_getanswer_slice (packet1, packet1len,
    1134  				     abuf, &pat, errnop, h_errnop, ttlp, true);
    1135        if (alloc_buffer_has_failed (abuf))
    1136  	/* Do not try parsing the second packet if a larger result
    1137  	   buffer is needed.  The caller implements the resizing
    1138  	   protocol because *abuf has been exhausted.  */
    1139  	return NSS_STATUS_TRYAGAIN; /* Ignored by the caller.  */
    1140      }
    1141  
    1142    if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND)
    1143        && packet2 != NULL && packet2len > 0)
    1144      {
    1145        enum nss_status status2
    1146  	= gaih_getanswer_slice (packet2, packet2len,
    1147  				abuf, &pat, errnop, h_errnop, ttlp,
    1148  				/* Success means that data with a
    1149  				   canonical name has already been
    1150  				   stored.  Do not store the name again.  */
    1151  				status != NSS_STATUS_SUCCESS);
    1152        /* Use the second response status in some cases.  */
    1153        if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND)
    1154  	status = status2;
    1155      }
    1156  
    1157    return status;
    1158  }
    1159  
    1160  /* Variant of gaih_getanswer without a second (AAAA) response.  */
    1161  static enum nss_status
    1162  gaih_getanswer_noaaaa (unsigned char *packet, size_t packetlen,
    1163  		       struct alloc_buffer *abuf, struct gaih_addrtuple **pat,
    1164  		       int *errnop, int *h_errnop, int32_t *ttlp)
    1165  {
    1166    enum nss_status status = NSS_STATUS_NOTFOUND;
    1167    if (packetlen > 0)
    1168      status = gaih_getanswer_slice (packet, packetlen,
    1169  				   abuf, &pat, errnop, h_errnop, ttlp, true);
    1170    return status;
    1171  }