|
|
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,
|