mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-21 20:40:05 +00:00
nss_files: Refactor gethostbyname3 multi case into separate function
This is in preparation of further cleanup work.
This commit is contained in:
parent
a8dce6197a
commit
8ed70de2fa
@ -1,3 +1,9 @@
|
|||||||
|
2017-10-10 Florian Weimer <fweimer@redhat.com>
|
||||||
|
|
||||||
|
* nss/nss_files/files-hosts.c (gethostbyname3_multi): New
|
||||||
|
function.
|
||||||
|
(_nss_files_gethostbyname3_r): Call it.
|
||||||
|
|
||||||
2017-10-09 Joseph Myers <joseph@codesourcery.com>
|
2017-10-09 Joseph Myers <joseph@codesourcery.com>
|
||||||
|
|
||||||
* sysdeps/generic/math-type-macros.h [!declare_mgen_alias]: Give
|
* sysdeps/generic/math-type-macros.h [!declare_mgen_alias]: Give
|
||||||
|
@ -115,6 +115,206 @@ DB_LOOKUP (hostbyaddr, ,,,
|
|||||||
}, const void *addr, socklen_t len, int af)
|
}, const void *addr, socklen_t len, int af)
|
||||||
#undef EXTRA_ARGS_VALUE
|
#undef EXTRA_ARGS_VALUE
|
||||||
|
|
||||||
|
static enum nss_status
|
||||||
|
gethostbyname3_multi (FILE * stream, const char *name, int af,
|
||||||
|
struct hostent *result, char *buffer, size_t buflen,
|
||||||
|
int *errnop, int *herrnop, int flags)
|
||||||
|
{
|
||||||
|
/* We have to get all host entries from the file. */
|
||||||
|
size_t tmp_buflen = MIN (buflen, 4096);
|
||||||
|
char tmp_buffer_stack[tmp_buflen]
|
||||||
|
__attribute__ ((__aligned__ (__alignof__ (struct hostent_data))));
|
||||||
|
char *tmp_buffer = tmp_buffer_stack;
|
||||||
|
struct hostent tmp_result_buf;
|
||||||
|
int naddrs = 1;
|
||||||
|
int naliases = 0;
|
||||||
|
char *bufferend;
|
||||||
|
bool tmp_buffer_malloced = false;
|
||||||
|
enum nss_status status;
|
||||||
|
|
||||||
|
while (result->h_aliases[naliases] != NULL)
|
||||||
|
++naliases;
|
||||||
|
|
||||||
|
bufferend = (char *) &result->h_aliases[naliases + 1];
|
||||||
|
|
||||||
|
again:
|
||||||
|
while ((status = internal_getent (stream, &tmp_result_buf, tmp_buffer,
|
||||||
|
tmp_buflen, errnop, herrnop, af,
|
||||||
|
flags))
|
||||||
|
== NSS_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
int matches = 1;
|
||||||
|
struct hostent *old_result = result;
|
||||||
|
result = &tmp_result_buf;
|
||||||
|
/* The following piece is a bit clumsy but we want to use the
|
||||||
|
`LOOKUP_NAME_CASE' value. The optimizer should do its
|
||||||
|
job. */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
LOOKUP_NAME_CASE (h_name, h_aliases)
|
||||||
|
result = old_result;
|
||||||
|
}
|
||||||
|
while ((matches = 0));
|
||||||
|
|
||||||
|
if (matches)
|
||||||
|
{
|
||||||
|
/* We could be very clever and try to recycle a few bytes
|
||||||
|
in the buffer instead of generating new arrays. But
|
||||||
|
we are not doing this here since it's more work than
|
||||||
|
it's worth. Simply let the user provide a bit bigger
|
||||||
|
buffer. */
|
||||||
|
char **new_h_addr_list;
|
||||||
|
char **new_h_aliases;
|
||||||
|
int newaliases = 0;
|
||||||
|
size_t newstrlen = 0;
|
||||||
|
int cnt;
|
||||||
|
|
||||||
|
/* Count the new aliases and the length of the strings. */
|
||||||
|
while (tmp_result_buf.h_aliases[newaliases] != NULL)
|
||||||
|
{
|
||||||
|
char *cp = tmp_result_buf.h_aliases[newaliases];
|
||||||
|
++newaliases;
|
||||||
|
newstrlen += strlen (cp) + 1;
|
||||||
|
}
|
||||||
|
/* If the real name is different add it also to the
|
||||||
|
aliases. This means that there is a duplication
|
||||||
|
in the alias list but this is really the user's
|
||||||
|
problem. */
|
||||||
|
if (strcmp (old_result->h_name,
|
||||||
|
tmp_result_buf.h_name) != 0)
|
||||||
|
{
|
||||||
|
++newaliases;
|
||||||
|
newstrlen += strlen (tmp_result_buf.h_name) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure bufferend is aligned. */
|
||||||
|
assert ((bufferend - (char *) 0) % sizeof (char *) == 0);
|
||||||
|
|
||||||
|
/* Now we can check whether the buffer is large enough.
|
||||||
|
16 is the maximal size of the IP address. */
|
||||||
|
if (bufferend + 16 + (naddrs + 2) * sizeof (char *)
|
||||||
|
+ roundup (newstrlen, sizeof (char *))
|
||||||
|
+ (naliases + newaliases + 1) * sizeof (char *)
|
||||||
|
>= buffer + buflen)
|
||||||
|
{
|
||||||
|
*errnop = ERANGE;
|
||||||
|
*herrnop = NETDB_INTERNAL;
|
||||||
|
status = NSS_STATUS_TRYAGAIN;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_h_addr_list =
|
||||||
|
(char **) (bufferend
|
||||||
|
+ roundup (newstrlen, sizeof (char *))
|
||||||
|
+ 16);
|
||||||
|
new_h_aliases =
|
||||||
|
(char **) ((char *) new_h_addr_list
|
||||||
|
+ (naddrs + 2) * sizeof (char *));
|
||||||
|
|
||||||
|
/* Copy the old data in the new arrays. */
|
||||||
|
for (cnt = 0; cnt < naddrs; ++cnt)
|
||||||
|
new_h_addr_list[cnt] = old_result->h_addr_list[cnt];
|
||||||
|
|
||||||
|
for (cnt = 0; cnt < naliases; ++cnt)
|
||||||
|
new_h_aliases[cnt] = old_result->h_aliases[cnt];
|
||||||
|
|
||||||
|
/* Store the new strings. */
|
||||||
|
cnt = 0;
|
||||||
|
while (tmp_result_buf.h_aliases[cnt] != NULL)
|
||||||
|
{
|
||||||
|
new_h_aliases[naliases++] = bufferend;
|
||||||
|
bufferend = (__stpcpy (bufferend,
|
||||||
|
tmp_result_buf.h_aliases[cnt])
|
||||||
|
+ 1);
|
||||||
|
++cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cnt < newaliases)
|
||||||
|
{
|
||||||
|
new_h_aliases[naliases++] = bufferend;
|
||||||
|
bufferend = __stpcpy (bufferend,
|
||||||
|
tmp_result_buf.h_name) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Final NULL pointer. */
|
||||||
|
new_h_aliases[naliases] = NULL;
|
||||||
|
|
||||||
|
/* Round up the buffer end address. */
|
||||||
|
bufferend += (sizeof (char *)
|
||||||
|
- ((bufferend - (char *) 0)
|
||||||
|
% sizeof (char *))) % sizeof (char *);
|
||||||
|
|
||||||
|
/* Now the new address. */
|
||||||
|
new_h_addr_list[naddrs++] =
|
||||||
|
memcpy (bufferend, tmp_result_buf.h_addr,
|
||||||
|
tmp_result_buf.h_length);
|
||||||
|
|
||||||
|
/* Also here a final NULL pointer. */
|
||||||
|
new_h_addr_list[naddrs] = NULL;
|
||||||
|
|
||||||
|
/* Store the new array pointers. */
|
||||||
|
old_result->h_aliases = new_h_aliases;
|
||||||
|
old_result->h_addr_list = new_h_addr_list;
|
||||||
|
|
||||||
|
/* Compute the new buffer end. */
|
||||||
|
bufferend = (char *) &new_h_aliases[naliases + 1];
|
||||||
|
assert (bufferend <= buffer + buflen);
|
||||||
|
|
||||||
|
result = old_result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == NSS_STATUS_TRYAGAIN)
|
||||||
|
{
|
||||||
|
size_t newsize = 2 * tmp_buflen;
|
||||||
|
if (tmp_buffer_malloced)
|
||||||
|
{
|
||||||
|
char *newp = realloc (tmp_buffer, newsize);
|
||||||
|
if (newp != NULL)
|
||||||
|
{
|
||||||
|
assert ((((uintptr_t) newp)
|
||||||
|
& (__alignof__ (struct hostent_data) - 1))
|
||||||
|
== 0);
|
||||||
|
tmp_buffer = newp;
|
||||||
|
tmp_buflen = newsize;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!__libc_use_alloca (buflen + newsize))
|
||||||
|
{
|
||||||
|
tmp_buffer = malloc (newsize);
|
||||||
|
if (tmp_buffer != NULL)
|
||||||
|
{
|
||||||
|
assert ((((uintptr_t) tmp_buffer)
|
||||||
|
& (__alignof__ (struct hostent_data) - 1))
|
||||||
|
== 0);
|
||||||
|
tmp_buffer_malloced = true;
|
||||||
|
tmp_buflen = newsize;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tmp_buffer
|
||||||
|
= extend_alloca (tmp_buffer, tmp_buflen,
|
||||||
|
newsize
|
||||||
|
+ __alignof__ (struct hostent_data));
|
||||||
|
tmp_buffer = (char *) (((uintptr_t) tmp_buffer
|
||||||
|
+ __alignof__ (struct hostent_data)
|
||||||
|
- 1)
|
||||||
|
& ~(__alignof__ (struct hostent_data)
|
||||||
|
- 1));
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
status = NSS_STATUS_SUCCESS;
|
||||||
|
out:
|
||||||
|
if (tmp_buffer_malloced)
|
||||||
|
free (tmp_buffer);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
enum nss_status
|
enum nss_status
|
||||||
_nss_files_gethostbyname3_r (const char *name, int af, struct hostent *result,
|
_nss_files_gethostbyname3_r (const char *name, int af, struct hostent *result,
|
||||||
char *buffer, size_t buflen, int *errnop,
|
char *buffer, size_t buflen, int *errnop,
|
||||||
@ -143,199 +343,8 @@ _nss_files_gethostbyname3_r (const char *name, int af, struct hostent *result,
|
|||||||
|
|
||||||
if (status == NSS_STATUS_SUCCESS
|
if (status == NSS_STATUS_SUCCESS
|
||||||
&& _res_hconf.flags & HCONF_FLAG_MULTI)
|
&& _res_hconf.flags & HCONF_FLAG_MULTI)
|
||||||
{
|
status = gethostbyname3_multi
|
||||||
/* We have to get all host entries from the file. */
|
(stream, name, af, result, buffer, buflen, errnop, herrnop, flags);
|
||||||
size_t tmp_buflen = MIN (buflen, 4096);
|
|
||||||
char tmp_buffer_stack[tmp_buflen]
|
|
||||||
__attribute__ ((__aligned__ (__alignof__ (struct hostent_data))));
|
|
||||||
char *tmp_buffer = tmp_buffer_stack;
|
|
||||||
struct hostent tmp_result_buf;
|
|
||||||
int naddrs = 1;
|
|
||||||
int naliases = 0;
|
|
||||||
char *bufferend;
|
|
||||||
bool tmp_buffer_malloced = false;
|
|
||||||
|
|
||||||
while (result->h_aliases[naliases] != NULL)
|
|
||||||
++naliases;
|
|
||||||
|
|
||||||
bufferend = (char *) &result->h_aliases[naliases + 1];
|
|
||||||
|
|
||||||
again:
|
|
||||||
while ((status = internal_getent (stream, &tmp_result_buf, tmp_buffer,
|
|
||||||
tmp_buflen, errnop, herrnop, af,
|
|
||||||
flags))
|
|
||||||
== NSS_STATUS_SUCCESS)
|
|
||||||
{
|
|
||||||
int matches = 1;
|
|
||||||
struct hostent *old_result = result;
|
|
||||||
result = &tmp_result_buf;
|
|
||||||
/* The following piece is a bit clumsy but we want to use the
|
|
||||||
`LOOKUP_NAME_CASE' value. The optimizer should do its
|
|
||||||
job. */
|
|
||||||
do
|
|
||||||
{
|
|
||||||
LOOKUP_NAME_CASE (h_name, h_aliases)
|
|
||||||
result = old_result;
|
|
||||||
}
|
|
||||||
while ((matches = 0));
|
|
||||||
|
|
||||||
if (matches)
|
|
||||||
{
|
|
||||||
/* We could be very clever and try to recycle a few bytes
|
|
||||||
in the buffer instead of generating new arrays. But
|
|
||||||
we are not doing this here since it's more work than
|
|
||||||
it's worth. Simply let the user provide a bit bigger
|
|
||||||
buffer. */
|
|
||||||
char **new_h_addr_list;
|
|
||||||
char **new_h_aliases;
|
|
||||||
int newaliases = 0;
|
|
||||||
size_t newstrlen = 0;
|
|
||||||
int cnt;
|
|
||||||
|
|
||||||
/* Count the new aliases and the length of the strings. */
|
|
||||||
while (tmp_result_buf.h_aliases[newaliases] != NULL)
|
|
||||||
{
|
|
||||||
char *cp = tmp_result_buf.h_aliases[newaliases];
|
|
||||||
++newaliases;
|
|
||||||
newstrlen += strlen (cp) + 1;
|
|
||||||
}
|
|
||||||
/* If the real name is different add it also to the
|
|
||||||
aliases. This means that there is a duplication
|
|
||||||
in the alias list but this is really the user's
|
|
||||||
problem. */
|
|
||||||
if (strcmp (old_result->h_name,
|
|
||||||
tmp_result_buf.h_name) != 0)
|
|
||||||
{
|
|
||||||
++newaliases;
|
|
||||||
newstrlen += strlen (tmp_result_buf.h_name) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make sure bufferend is aligned. */
|
|
||||||
assert ((bufferend - (char *) 0) % sizeof (char *) == 0);
|
|
||||||
|
|
||||||
/* Now we can check whether the buffer is large enough.
|
|
||||||
16 is the maximal size of the IP address. */
|
|
||||||
if (bufferend + 16 + (naddrs + 2) * sizeof (char *)
|
|
||||||
+ roundup (newstrlen, sizeof (char *))
|
|
||||||
+ (naliases + newaliases + 1) * sizeof (char *)
|
|
||||||
>= buffer + buflen)
|
|
||||||
{
|
|
||||||
*errnop = ERANGE;
|
|
||||||
*herrnop = NETDB_INTERNAL;
|
|
||||||
status = NSS_STATUS_TRYAGAIN;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
new_h_addr_list =
|
|
||||||
(char **) (bufferend
|
|
||||||
+ roundup (newstrlen, sizeof (char *))
|
|
||||||
+ 16);
|
|
||||||
new_h_aliases =
|
|
||||||
(char **) ((char *) new_h_addr_list
|
|
||||||
+ (naddrs + 2) * sizeof (char *));
|
|
||||||
|
|
||||||
/* Copy the old data in the new arrays. */
|
|
||||||
for (cnt = 0; cnt < naddrs; ++cnt)
|
|
||||||
new_h_addr_list[cnt] = old_result->h_addr_list[cnt];
|
|
||||||
|
|
||||||
for (cnt = 0; cnt < naliases; ++cnt)
|
|
||||||
new_h_aliases[cnt] = old_result->h_aliases[cnt];
|
|
||||||
|
|
||||||
/* Store the new strings. */
|
|
||||||
cnt = 0;
|
|
||||||
while (tmp_result_buf.h_aliases[cnt] != NULL)
|
|
||||||
{
|
|
||||||
new_h_aliases[naliases++] = bufferend;
|
|
||||||
bufferend = (__stpcpy (bufferend,
|
|
||||||
tmp_result_buf.h_aliases[cnt])
|
|
||||||
+ 1);
|
|
||||||
++cnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cnt < newaliases)
|
|
||||||
{
|
|
||||||
new_h_aliases[naliases++] = bufferend;
|
|
||||||
bufferend = __stpcpy (bufferend,
|
|
||||||
tmp_result_buf.h_name) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Final NULL pointer. */
|
|
||||||
new_h_aliases[naliases] = NULL;
|
|
||||||
|
|
||||||
/* Round up the buffer end address. */
|
|
||||||
bufferend += (sizeof (char *)
|
|
||||||
- ((bufferend - (char *) 0)
|
|
||||||
% sizeof (char *))) % sizeof (char *);
|
|
||||||
|
|
||||||
/* Now the new address. */
|
|
||||||
new_h_addr_list[naddrs++] =
|
|
||||||
memcpy (bufferend, tmp_result_buf.h_addr,
|
|
||||||
tmp_result_buf.h_length);
|
|
||||||
|
|
||||||
/* Also here a final NULL pointer. */
|
|
||||||
new_h_addr_list[naddrs] = NULL;
|
|
||||||
|
|
||||||
/* Store the new array pointers. */
|
|
||||||
old_result->h_aliases = new_h_aliases;
|
|
||||||
old_result->h_addr_list = new_h_addr_list;
|
|
||||||
|
|
||||||
/* Compute the new buffer end. */
|
|
||||||
bufferend = (char *) &new_h_aliases[naliases + 1];
|
|
||||||
assert (bufferend <= buffer + buflen);
|
|
||||||
|
|
||||||
result = old_result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status == NSS_STATUS_TRYAGAIN)
|
|
||||||
{
|
|
||||||
size_t newsize = 2 * tmp_buflen;
|
|
||||||
if (tmp_buffer_malloced)
|
|
||||||
{
|
|
||||||
char *newp = realloc (tmp_buffer, newsize);
|
|
||||||
if (newp != NULL)
|
|
||||||
{
|
|
||||||
assert ((((uintptr_t) newp)
|
|
||||||
& (__alignof__ (struct hostent_data) - 1))
|
|
||||||
== 0);
|
|
||||||
tmp_buffer = newp;
|
|
||||||
tmp_buflen = newsize;
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!__libc_use_alloca (buflen + newsize))
|
|
||||||
{
|
|
||||||
tmp_buffer = malloc (newsize);
|
|
||||||
if (tmp_buffer != NULL)
|
|
||||||
{
|
|
||||||
assert ((((uintptr_t) tmp_buffer)
|
|
||||||
& (__alignof__ (struct hostent_data) - 1))
|
|
||||||
== 0);
|
|
||||||
tmp_buffer_malloced = true;
|
|
||||||
tmp_buflen = newsize;
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tmp_buffer
|
|
||||||
= extend_alloca (tmp_buffer, tmp_buflen,
|
|
||||||
newsize
|
|
||||||
+ __alignof__ (struct hostent_data));
|
|
||||||
tmp_buffer = (char *) (((uintptr_t) tmp_buffer
|
|
||||||
+ __alignof__ (struct hostent_data)
|
|
||||||
- 1)
|
|
||||||
& ~(__alignof__ (struct hostent_data)
|
|
||||||
- 1));
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
status = NSS_STATUS_SUCCESS;
|
|
||||||
out:
|
|
||||||
if (tmp_buffer_malloced)
|
|
||||||
free (tmp_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal_endent (&stream);
|
internal_endent (&stream);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user