2e9afc
commit 5a4c6d53f50b264d60cf6453576ca2810c7890b7
2e9afc
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
2e9afc
Date:   Thu Nov 28 17:18:12 2013 +0530
2e9afc
2e9afc
    Get canonical name in getaddrinfo from hosts file for AF_INET (fixes 16077)
2e9afc
    
2e9afc
    AF_INET lookup in hosts file uses _nss_files_gethostbyname2_r, which
2e9afc
    is not capable of returning a canonical name if it has found one.
2e9afc
    This change adds _nss_files_gethostbyname3_r, which wraps around
2e9afc
    _nss_files_gethostbyname2_r and then returns result.h_name as the
2e9afc
    canonical name.
2e9afc
12745e
diff --git glibc-2.17-c758a686/nss/Versions glibc-2.17-c758a686/nss/Versions
2e9afc
index d13d570..f8ababc 100644
12745e
--- glibc-2.17-c758a686/nss/Versions
12745e
+++ glibc-2.17-c758a686/nss/Versions
2e9afc
@@ -40,6 +40,7 @@ libnss_files {
2e9afc
     _nss_files_endhostent;
2e9afc
     _nss_files_gethostbyaddr_r;
2e9afc
     _nss_files_gethostbyname2_r;
2e9afc
+    _nss_files_gethostbyname3_r;
2e9afc
     _nss_files_gethostbyname4_r;
2e9afc
     _nss_files_gethostbyname_r;
2e9afc
     _nss_files_gethostent_r;
12745e
diff --git glibc-2.17-c758a686/nss/nss_files/files-hosts.c glibc-2.17-c758a686/nss/nss_files/files-hosts.c
2e9afc
index 6db2535..957c9aa 100644
12745e
--- glibc-2.17-c758a686/nss/nss_files/files-hosts.c
12745e
+++ glibc-2.17-c758a686/nss/nss_files/files-hosts.c
2e9afc
@@ -97,262 +97,12 @@ LINE_PARSER
2e9afc
    STRING_FIELD (result->h_name, isspace, 1);
2e9afc
  })
2e9afc
 
2e9afc
-
2e9afc
-
2e9afc
-#define HOST_DB_LOOKUP(name, keysize, keypattern, break_if_match, proto...) \
2e9afc
-enum nss_status								      \
2e9afc
-_nss_files_get##name##_r (proto,					      \
2e9afc
-			  struct STRUCTURE *result, char *buffer,	      \
2e9afc
-			  size_t buflen, int *errnop H_ERRNO_PROTO)	      \
2e9afc
-{									      \
2e9afc
-  uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct hostent_data);    \
2e9afc
-  buffer += pad;							      \
2e9afc
-  buflen = buflen > pad ? buflen - pad : 0;				      \
2e9afc
-									      \
2e9afc
-  __libc_lock_lock (lock);						      \
2e9afc
-									      \
2e9afc
-  /* Reset file pointer to beginning or open file.  */			      \
2e9afc
-  enum nss_status status = internal_setent (keep_stream);		      \
2e9afc
-									      \
2e9afc
-  if (status == NSS_STATUS_SUCCESS)					      \
2e9afc
-    {									      \
2e9afc
-      /* Tell getent function that we have repositioned the file pointer.  */ \
2e9afc
-      last_use = getby;							      \
2e9afc
-									      \
2e9afc
-      while ((status = internal_getent (result, buffer, buflen, errnop	      \
2e9afc
-					H_ERRNO_ARG EXTRA_ARGS_VALUE))	      \
2e9afc
-	     == NSS_STATUS_SUCCESS)					      \
2e9afc
-	{ break_if_match }						      \
2e9afc
-									      \
2e9afc
-      if (status == NSS_STATUS_SUCCESS					      \
2e9afc
-	  && _res_hconf.flags & HCONF_FLAG_MULTI)			      \
2e9afc
-	{								      \
2e9afc
-	  /* We have to get all host entries from the file.  */		      \
2e9afc
-	  size_t tmp_buflen = MIN (buflen, 4096);			      \
2e9afc
-	  char tmp_buffer_stack[tmp_buflen]				      \
2e9afc
-	    __attribute__ ((__aligned__ (__alignof__ (struct hostent_data))));\
2e9afc
-	  char *tmp_buffer = tmp_buffer_stack;				      \
2e9afc
-	  struct hostent tmp_result_buf;				      \
2e9afc
-	  int naddrs = 1;						      \
2e9afc
-	  int naliases = 0;						      \
2e9afc
-	  char *bufferend;						      \
2e9afc
-	  bool tmp_buffer_malloced = false;				      \
2e9afc
-									      \
2e9afc
-	  while (result->h_aliases[naliases] != NULL)			      \
2e9afc
-	    ++naliases;							      \
2e9afc
-									      \
2e9afc
-	  bufferend = (char *) &result->h_aliases[naliases + 1];	      \
2e9afc
-									      \
2e9afc
-	again:								      \
2e9afc
-	  while ((status = internal_getent (&tmp_result_buf, tmp_buffer,      \
2e9afc
-					    tmp_buflen, errnop H_ERRNO_ARG    \
2e9afc
-					    EXTRA_ARGS_VALUE))		      \
2e9afc
-		 == NSS_STATUS_SUCCESS)					      \
2e9afc
-	    {								      \
2e9afc
-	      int matches = 1;						      \
2e9afc
-	      struct hostent *old_result = result;			      \
2e9afc
-	      result = &tmp_result_buf;					      \
2e9afc
-	      /* The following piece is a bit clumsy but we want to use the   \
2e9afc
-		 `break_if_match' value.  The optimizer should do its	      \
2e9afc
-		 job.  */						      \
2e9afc
-	      do							      \
2e9afc
-		{							      \
2e9afc
-		  break_if_match					      \
2e9afc
-		  result = old_result;					      \
2e9afc
-		}							      \
2e9afc
-	      while ((matches = 0));					      \
2e9afc
-									      \
2e9afc
-	      if (matches)						      \
2e9afc
-		{							      \
2e9afc
-		  /* We could be very clever and try to recycle a few bytes   \
2e9afc
-		     in the buffer instead of generating new arrays.  But     \
2e9afc
-		     we are not doing this here since it's more work than     \
2e9afc
-		     it's worth.  Simply let the user provide a bit bigger    \
2e9afc
-		     buffer.  */					      \
2e9afc
-		  char **new_h_addr_list;				      \
2e9afc
-		  char **new_h_aliases;					      \
2e9afc
-		  int newaliases = 0;					      \
2e9afc
-		  size_t newstrlen = 0;					      \
2e9afc
-		  int cnt;						      \
2e9afc
-									      \
2e9afc
-		  /* Count the new aliases and the length of the strings.  */ \
2e9afc
-		  while (tmp_result_buf.h_aliases[newaliases] != NULL)	      \
2e9afc
-		    {							      \
2e9afc
-		      char *cp = tmp_result_buf.h_aliases[newaliases];	      \
2e9afc
-		      ++newaliases;					      \
2e9afc
-		      newstrlen += strlen (cp) + 1;			      \
2e9afc
-		    }							      \
2e9afc
-		  /* If the real name is different add it also to the	      \
2e9afc
-		     aliases.  This means that there is a duplication	      \
2e9afc
-		     in the alias list but this is really the user's	      \
2e9afc
-		     problem.  */					      \
2e9afc
-		  if (strcmp (old_result->h_name,			      \
2e9afc
-			      tmp_result_buf.h_name) != 0)		      \
2e9afc
-		    {							      \
2e9afc
-		      ++newaliases;					      \
2e9afc
-		      newstrlen += strlen (tmp_result_buf.h_name) + 1;	      \
2e9afc
-		    }							      \
2e9afc
-									      \
2e9afc
-		  /* Make sure bufferend is aligned.  */		      \
2e9afc
-		  assert ((bufferend - (char *) 0) % sizeof (char *) == 0);   \
2e9afc
-									      \
2e9afc
-		  /* Now we can check whether the buffer is large enough.     \
2e9afc
-		     16 is the maximal size of the IP address.  */	      \
2e9afc
-		  if (bufferend + 16 + (naddrs + 2) * sizeof (char *)	      \
2e9afc
-		      + roundup (newstrlen, sizeof (char *))		      \
2e9afc
-		      + (naliases + newaliases + 1) * sizeof (char *)	      \
2e9afc
-		      >= buffer + buflen)				      \
2e9afc
-		    {							      \
2e9afc
-		      *errnop = ERANGE;					      \
2e9afc
-		      *herrnop = NETDB_INTERNAL;			      \
2e9afc
-		      status = NSS_STATUS_TRYAGAIN;			      \
2e9afc
-		      goto out;						      \
2e9afc
-		    }							      \
2e9afc
-									      \
2e9afc
-		  new_h_addr_list =					      \
2e9afc
-		    (char **) (bufferend				      \
2e9afc
-			       + roundup (newstrlen, sizeof (char *))	      \
2e9afc
-			       + 16);					      \
2e9afc
-		  new_h_aliases =					      \
2e9afc
-		    (char **) ((char *) new_h_addr_list			      \
2e9afc
-			       + (naddrs + 2) * sizeof (char *));	      \
2e9afc
-									      \
2e9afc
-		  /* Copy the old data in the new arrays.  */		      \
2e9afc
-		  for (cnt = 0; cnt < naddrs; ++cnt)			      \
2e9afc
-		    new_h_addr_list[cnt] = old_result->h_addr_list[cnt];      \
2e9afc
-									      \
2e9afc
-		  for (cnt = 0; cnt < naliases; ++cnt)			      \
2e9afc
-		    new_h_aliases[cnt] = old_result->h_aliases[cnt];	      \
2e9afc
-									      \
2e9afc
-		  /* Store the new strings.  */				      \
2e9afc
-		  cnt = 0;						      \
2e9afc
-		  while (tmp_result_buf.h_aliases[cnt] != NULL)		      \
2e9afc
-		    {							      \
2e9afc
-		      new_h_aliases[naliases++] = bufferend;		      \
2e9afc
-		      bufferend = (__stpcpy (bufferend,			      \
2e9afc
-					     tmp_result_buf.h_aliases[cnt])   \
2e9afc
-				   + 1);				      \
2e9afc
-		      ++cnt;						      \
2e9afc
-		    }							      \
2e9afc
-									      \
2e9afc
-		  if (cnt < newaliases)					      \
2e9afc
-		    {							      \
2e9afc
-		      new_h_aliases[naliases++] = bufferend;		      \
2e9afc
-		      bufferend = __stpcpy (bufferend,			      \
2e9afc
-					    tmp_result_buf.h_name) + 1;	      \
2e9afc
-		    }							      \
2e9afc
-									      \
2e9afc
-		  /* Final NULL pointer.  */				      \
2e9afc
-		  new_h_aliases[naliases] = NULL;			      \
2e9afc
-									      \
2e9afc
-		  /* Round up the buffer end address.  */		      \
2e9afc
-		  bufferend += (sizeof (char *)				      \
2e9afc
-				- ((bufferend - (char *) 0)		      \
2e9afc
-				   % sizeof (char *))) % sizeof (char *);     \
2e9afc
-									      \
2e9afc
-		  /* Now the new address.  */				      \
2e9afc
-		  new_h_addr_list[naddrs++] =				      \
2e9afc
-		    memcpy (bufferend, tmp_result_buf.h_addr,		      \
2e9afc
-			    tmp_result_buf.h_length);			      \
2e9afc
-									      \
2e9afc
-		  /* Also here a final NULL pointer.  */		      \
2e9afc
-		  new_h_addr_list[naddrs] = NULL;			      \
2e9afc
-									      \
2e9afc
-		  /* Store the new array pointers.  */			      \
2e9afc
-		  old_result->h_aliases = new_h_aliases;		      \
2e9afc
-		  old_result->h_addr_list = new_h_addr_list;		      \
2e9afc
-									      \
2e9afc
-		  /* Compute the new buffer end.  */			      \
2e9afc
-		  bufferend = (char *) &new_h_aliases[naliases + 1];	      \
2e9afc
-		  assert (bufferend <= buffer + buflen);		      \
2e9afc
-									      \
2e9afc
-		  result = old_result;					      \
2e9afc
-		}							      \
2e9afc
-	    }								      \
2e9afc
-									      \
2e9afc
-	  if (status == NSS_STATUS_TRYAGAIN)				      \
2e9afc
-	    {								      \
2e9afc
-	      size_t newsize = 2 * tmp_buflen;				      \
2e9afc
-	      if (tmp_buffer_malloced)					      \
2e9afc
-		{							      \
2e9afc
-		  char *newp = realloc (tmp_buffer, newsize);		      \
2e9afc
-		  if (newp != NULL)					      \
2e9afc
-		    {							      \
2e9afc
-		      assert ((((uintptr_t) newp)			      \
2e9afc
-			       & (__alignof__ (struct hostent_data) - 1))     \
2e9afc
-			      == 0);					      \
2e9afc
-		      tmp_buffer = newp;				      \
2e9afc
-		      tmp_buflen = newsize;				      \
2e9afc
-		      goto again;					      \
2e9afc
-		    }							      \
2e9afc
-		}							      \
2e9afc
-	      else if (!__libc_use_alloca (buflen + newsize))		      \
2e9afc
-		{							      \
2e9afc
-		  tmp_buffer = malloc (newsize);			      \
2e9afc
-		  if (tmp_buffer != NULL)				      \
2e9afc
-		    {							      \
2e9afc
-		      assert ((((uintptr_t) tmp_buffer)			      \
2e9afc
-			       & (__alignof__ (struct hostent_data) - 1))     \
2e9afc
-			      == 0);					      \
2e9afc
-		      tmp_buffer_malloced = true;			      \
2e9afc
-		      tmp_buflen = newsize;				      \
2e9afc
-		      goto again;					      \
2e9afc
-		    }							      \
2e9afc
-		}							      \
2e9afc
-	      else							      \
2e9afc
-		{							      \
2e9afc
-		  tmp_buffer						      \
2e9afc
-		    = extend_alloca (tmp_buffer, tmp_buflen,		      \
2e9afc
-				     newsize				      \
2e9afc
-				     + __alignof__ (struct hostent_data));    \
2e9afc
-		  tmp_buffer = (char *) (((uintptr_t) tmp_buffer	      \
2e9afc
-					  + __alignof__ (struct hostent_data) \
2e9afc
-					  - 1)				      \
2e9afc
-					 & ~(__alignof__ (struct hostent_data)\
2e9afc
-					     - 1));			      \
2e9afc
-		  goto again;						      \
2e9afc
-		}							      \
2e9afc
-	    }								      \
2e9afc
-	  else								      \
2e9afc
-	    status = NSS_STATUS_SUCCESS;				      \
2e9afc
-	out:								      \
2e9afc
-	  if (tmp_buffer_malloced)					      \
2e9afc
-	    free (tmp_buffer);						      \
2e9afc
-	}								      \
2e9afc
-									      \
2e9afc
-									      \
2e9afc
-      if (! keep_stream)						      \
2e9afc
-	internal_endent ();						      \
2e9afc
-    }									      \
2e9afc
-									      \
2e9afc
-  __libc_lock_unlock (lock);						      \
2e9afc
-									      \
2e9afc
-  return status;							      \
2e9afc
-}
2e9afc
-
2e9afc
-
2e9afc
 #define EXTRA_ARGS_VALUE \
2e9afc
   , ((_res.options & RES_USE_INET6) ? AF_INET6 : AF_INET),		      \
2e9afc
   ((_res.options & RES_USE_INET6) ? AI_V4MAPPED : 0)
2e9afc
 #include "files-XXX.c"
2e9afc
-HOST_DB_LOOKUP (hostbyname, ,,
2e9afc
-		{
2e9afc
-		  LOOKUP_NAME_CASE (h_name, h_aliases)
2e9afc
-		}, const char *name)
2e9afc
 #undef EXTRA_ARGS_VALUE
2e9afc
 
2e9afc
-
2e9afc
-/* XXX Is using _res to determine whether we want to convert IPv4 addresses
2e9afc
-   to IPv6 addresses really the right thing to do?  */
2e9afc
-#define EXTRA_ARGS_VALUE \
2e9afc
-  , af, ((_res.options & RES_USE_INET6) ? AI_V4MAPPED : 0)
2e9afc
-HOST_DB_LOOKUP (hostbyname2, ,,
2e9afc
-		{
2e9afc
-		  LOOKUP_NAME_CASE (h_name, h_aliases)
2e9afc
-		}, const char *name, int af)
2e9afc
-#undef EXTRA_ARGS_VALUE
2e9afc
-
2e9afc
-
2e9afc
 /* We only need to consider IPv4 mapped addresses if the input to the
2e9afc
    gethostbyaddr() function is an IPv6 address.  */
2e9afc
 #define EXTRA_ARGS_VALUE \
2e9afc
@@ -365,6 +115,263 @@ DB_LOOKUP (hostbyaddr, ,,,
2e9afc
 	   }, const void *addr, socklen_t len, int af)
2e9afc
 #undef EXTRA_ARGS_VALUE
2e9afc
 
2e9afc
+enum nss_status
2e9afc
+_nss_files_gethostbyname3_r (const char *name, int af, struct hostent *result,
2e9afc
+			     char *buffer, size_t buflen, int *errnop,
2e9afc
+			     int *herrnop, int32_t *ttlp, char **canonp)
2e9afc
+{
2e9afc
+  uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct hostent_data);
2e9afc
+  buffer += pad;
2e9afc
+  buflen = buflen > pad ? buflen - pad : 0;
2e9afc
+
2e9afc
+  __libc_lock_lock (lock);
2e9afc
+
2e9afc
+  /* Reset file pointer to beginning or open file.  */
2e9afc
+  enum nss_status status = internal_setent (keep_stream);
2e9afc
+
2e9afc
+  if (status == NSS_STATUS_SUCCESS)
2e9afc
+    {
2e9afc
+      /* XXX Is using _res to determine whether we want to convert IPv4
2e9afc
+         addresses to IPv6 addresses really the right thing to do?  */
2e9afc
+      int flags = ((_res.options & RES_USE_INET6) ? AI_V4MAPPED : 0);
2e9afc
+
2e9afc
+      /* Tell getent function that we have repositioned the file pointer.  */
2e9afc
+      last_use = getby;
2e9afc
+
2e9afc
+      while ((status = internal_getent (result, buffer, buflen, errnop,
2e9afc
+					herrnop, af, flags))
2e9afc
+	     == NSS_STATUS_SUCCESS)
2e9afc
+	{
2e9afc
+	  LOOKUP_NAME_CASE (h_name, h_aliases)
2e9afc
+	}
2e9afc
+
2e9afc
+      if (status == NSS_STATUS_SUCCESS
2e9afc
+	  && _res_hconf.flags & HCONF_FLAG_MULTI)
2e9afc
+	{
2e9afc
+	  /* We have to get all host entries from the file.  */
2e9afc
+	  size_t tmp_buflen = MIN (buflen, 4096);
2e9afc
+	  char tmp_buffer_stack[tmp_buflen]
2e9afc
+	    __attribute__ ((__aligned__ (__alignof__ (struct hostent_data))));
2e9afc
+	  char *tmp_buffer = tmp_buffer_stack;
2e9afc
+	  struct hostent tmp_result_buf;
2e9afc
+	  int naddrs = 1;
2e9afc
+	  int naliases = 0;
2e9afc
+	  char *bufferend;
2e9afc
+	  bool tmp_buffer_malloced = false;
2e9afc
+
2e9afc
+	  while (result->h_aliases[naliases] != NULL)
2e9afc
+	    ++naliases;
2e9afc
+
2e9afc
+	  bufferend = (char *) &result->h_aliases[naliases + 1];
2e9afc
+
2e9afc
+	again:
2e9afc
+	  while ((status = internal_getent (&tmp_result_buf, tmp_buffer,
2e9afc
+					    tmp_buflen, errnop, herrnop, af,
2e9afc
+					    flags))
2e9afc
+		 == NSS_STATUS_SUCCESS)
2e9afc
+	    {
2e9afc
+	      int matches = 1;
2e9afc
+	      struct hostent *old_result = result;
2e9afc
+	      result = &tmp_result_buf;
2e9afc
+	      /* The following piece is a bit clumsy but we want to use the
2e9afc
+		 `LOOKUP_NAME_CASE' value.  The optimizer should do its
2e9afc
+		 job.  */
2e9afc
+	      do
2e9afc
+		{
2e9afc
+		  LOOKUP_NAME_CASE (h_name, h_aliases)
2e9afc
+		  result = old_result;
2e9afc
+		}
2e9afc
+	      while ((matches = 0));
2e9afc
+
2e9afc
+	      if (matches)
2e9afc
+		{
2e9afc
+		  /* We could be very clever and try to recycle a few bytes
2e9afc
+		     in the buffer instead of generating new arrays.  But
2e9afc
+		     we are not doing this here since it's more work than
2e9afc
+		     it's worth.  Simply let the user provide a bit bigger
2e9afc
+		     buffer.  */
2e9afc
+		  char **new_h_addr_list;
2e9afc
+		  char **new_h_aliases;
2e9afc
+		  int newaliases = 0;
2e9afc
+		  size_t newstrlen = 0;
2e9afc
+		  int cnt;
2e9afc
+
2e9afc
+		  /* Count the new aliases and the length of the strings.  */
2e9afc
+		  while (tmp_result_buf.h_aliases[newaliases] != NULL)
2e9afc
+		    {
2e9afc
+		      char *cp = tmp_result_buf.h_aliases[newaliases];
2e9afc
+		      ++newaliases;
2e9afc
+		      newstrlen += strlen (cp) + 1;
2e9afc
+		    }
2e9afc
+		  /* If the real name is different add it also to the
2e9afc
+		     aliases.  This means that there is a duplication
2e9afc
+		     in the alias list but this is really the user's
2e9afc
+		     problem.  */
2e9afc
+		  if (strcmp (old_result->h_name,
2e9afc
+			      tmp_result_buf.h_name) != 0)
2e9afc
+		    {
2e9afc
+		      ++newaliases;
2e9afc
+		      newstrlen += strlen (tmp_result_buf.h_name) + 1;
2e9afc
+		    }
2e9afc
+
2e9afc
+		  /* Make sure bufferend is aligned.  */
2e9afc
+		  assert ((bufferend - (char *) 0) % sizeof (char *) == 0);
2e9afc
+
2e9afc
+		  /* Now we can check whether the buffer is large enough.
2e9afc
+		     16 is the maximal size of the IP address.  */
2e9afc
+		  if (bufferend + 16 + (naddrs + 2) * sizeof (char *)
2e9afc
+		      + roundup (newstrlen, sizeof (char *))
2e9afc
+		      + (naliases + newaliases + 1) * sizeof (char *)
2e9afc
+		      >= buffer + buflen)
2e9afc
+		    {
2e9afc
+		      *errnop = ERANGE;
2e9afc
+		      *herrnop = NETDB_INTERNAL;
2e9afc
+		      status = NSS_STATUS_TRYAGAIN;
2e9afc
+		      goto out;
2e9afc
+		    }
2e9afc
+
2e9afc
+		  new_h_addr_list =
2e9afc
+		    (char **) (bufferend
2e9afc
+			       + roundup (newstrlen, sizeof (char *))
2e9afc
+			       + 16);
2e9afc
+		  new_h_aliases =
2e9afc
+		    (char **) ((char *) new_h_addr_list
2e9afc
+			       + (naddrs + 2) * sizeof (char *));
2e9afc
+
2e9afc
+		  /* Copy the old data in the new arrays.  */
2e9afc
+		  for (cnt = 0; cnt < naddrs; ++cnt)
2e9afc
+		    new_h_addr_list[cnt] = old_result->h_addr_list[cnt];
2e9afc
+
2e9afc
+		  for (cnt = 0; cnt < naliases; ++cnt)
2e9afc
+		    new_h_aliases[cnt] = old_result->h_aliases[cnt];
2e9afc
+
2e9afc
+		  /* Store the new strings.  */
2e9afc
+		  cnt = 0;
2e9afc
+		  while (tmp_result_buf.h_aliases[cnt] != NULL)
2e9afc
+		    {
2e9afc
+		      new_h_aliases[naliases++] = bufferend;
2e9afc
+		      bufferend = (__stpcpy (bufferend,
2e9afc
+					     tmp_result_buf.h_aliases[cnt])
2e9afc
+				   + 1);
2e9afc
+		      ++cnt;
2e9afc
+		    }
2e9afc
+
2e9afc
+		  if (cnt < newaliases)
2e9afc
+		    {
2e9afc
+		      new_h_aliases[naliases++] = bufferend;
2e9afc
+		      bufferend = __stpcpy (bufferend,
2e9afc
+					    tmp_result_buf.h_name) + 1;
2e9afc
+		    }
2e9afc
+
2e9afc
+		  /* Final NULL pointer.  */
2e9afc
+		  new_h_aliases[naliases] = NULL;
2e9afc
+
2e9afc
+		  /* Round up the buffer end address.  */
2e9afc
+		  bufferend += (sizeof (char *)
2e9afc
+				- ((bufferend - (char *) 0)
2e9afc
+				   % sizeof (char *))) % sizeof (char *);
2e9afc
+
2e9afc
+		  /* Now the new address.  */
2e9afc
+		  new_h_addr_list[naddrs++] =
2e9afc
+		    memcpy (bufferend, tmp_result_buf.h_addr,
2e9afc
+			    tmp_result_buf.h_length);
2e9afc
+
2e9afc
+		  /* Also here a final NULL pointer.  */
2e9afc
+		  new_h_addr_list[naddrs] = NULL;
2e9afc
+
2e9afc
+		  /* Store the new array pointers.  */
2e9afc
+		  old_result->h_aliases = new_h_aliases;
2e9afc
+		  old_result->h_addr_list = new_h_addr_list;
2e9afc
+
2e9afc
+		  /* Compute the new buffer end.  */
2e9afc
+		  bufferend = (char *) &new_h_aliases[naliases + 1];
2e9afc
+		  assert (bufferend <= buffer + buflen);
2e9afc
+
2e9afc
+		  result = old_result;
2e9afc
+		}
2e9afc
+	    }
2e9afc
+
2e9afc
+	  if (status == NSS_STATUS_TRYAGAIN)
2e9afc
+	    {
2e9afc
+	      size_t newsize = 2 * tmp_buflen;
2e9afc
+	      if (tmp_buffer_malloced)
2e9afc
+		{
2e9afc
+		  char *newp = realloc (tmp_buffer, newsize);
2e9afc
+		  if (newp != NULL)
2e9afc
+		    {
2e9afc
+		      assert ((((uintptr_t) newp)
2e9afc
+			       & (__alignof__ (struct hostent_data) - 1))
2e9afc
+			      == 0);
2e9afc
+		      tmp_buffer = newp;
2e9afc
+		      tmp_buflen = newsize;
2e9afc
+		      goto again;
2e9afc
+		    }
2e9afc
+		}
2e9afc
+	      else if (!__libc_use_alloca (buflen + newsize))
2e9afc
+		{
2e9afc
+		  tmp_buffer = malloc (newsize);
2e9afc
+		  if (tmp_buffer != NULL)
2e9afc
+		    {
2e9afc
+		      assert ((((uintptr_t) tmp_buffer)
2e9afc
+			       & (__alignof__ (struct hostent_data) - 1))
2e9afc
+			      == 0);
2e9afc
+		      tmp_buffer_malloced = true;
2e9afc
+		      tmp_buflen = newsize;
2e9afc
+		      goto again;
2e9afc
+		    }
2e9afc
+		}
2e9afc
+	      else
2e9afc
+		{
2e9afc
+		  tmp_buffer
2e9afc
+		    = extend_alloca (tmp_buffer, tmp_buflen,
2e9afc
+				     newsize
2e9afc
+				     + __alignof__ (struct hostent_data));
2e9afc
+		  tmp_buffer = (char *) (((uintptr_t) tmp_buffer
2e9afc
+					  + __alignof__ (struct hostent_data)
2e9afc
+					  - 1)
2e9afc
+					 & ~(__alignof__ (struct hostent_data)
2e9afc
+					     - 1));
2e9afc
+		  goto again;
2e9afc
+		}
2e9afc
+	    }
2e9afc
+	  else
2e9afc
+	    status = NSS_STATUS_SUCCESS;
2e9afc
+	out:
2e9afc
+	  if (tmp_buffer_malloced)
2e9afc
+	    free (tmp_buffer);
2e9afc
+	}
2e9afc
+
2e9afc
+      if (! keep_stream)
2e9afc
+	internal_endent ();
2e9afc
+    }
2e9afc
+
2e9afc
+  if (canonp && status == NSS_STATUS_SUCCESS)
2e9afc
+    *canonp = result->h_name;
2e9afc
+
2e9afc
+  __libc_lock_unlock (lock);
2e9afc
+
2e9afc
+  return status;
2e9afc
+}
2e9afc
+
2e9afc
+enum nss_status
2e9afc
+_nss_files_gethostbyname_r (const char *name, struct hostent *result,
2e9afc
+			    char *buffer, size_t buflen, int *errnop,
2e9afc
+			    int *herrnop)
2e9afc
+{
2e9afc
+  int af = ((_res.options & RES_USE_INET6) ? AF_INET6 : AF_INET);
2e9afc
+
2e9afc
+  return _nss_files_gethostbyname3_r (name, af, result, buffer, buflen,
2e9afc
+				      errnop, herrnop, NULL, NULL);
2e9afc
+}
2e9afc
+
2e9afc
+enum nss_status
2e9afc
+_nss_files_gethostbyname2_r (const char *name, int af, struct hostent *result,
2e9afc
+			     char *buffer, size_t buflen, int *errnop,
2e9afc
+			     int *herrnop)
2e9afc
+{
2e9afc
+  return _nss_files_gethostbyname3_r (name, af, result, buffer, buflen,
2e9afc
+				      errnop, herrnop, NULL, NULL);
2e9afc
+}
2e9afc
 
2e9afc
 enum nss_status
2e9afc
 _nss_files_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,