summaryrefslogtreecommitdiff
path: root/nscd/nscd_gethst_r.c
diff options
context:
space:
mode:
Diffstat (limited to 'nscd/nscd_gethst_r.c')
-rw-r--r--nscd/nscd_gethst_r.c159
1 files changed, 67 insertions, 92 deletions
diff --git a/nscd/nscd_gethst_r.c b/nscd/nscd_gethst_r.c
index 90e1815bdd..5d9d569107 100644
--- a/nscd/nscd_gethst_r.c
+++ b/nscd/nscd_gethst_r.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998-2005, 2006, 2007 Free Software Foundation, Inc.
+/* Copyright (C) 1998-2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
@@ -87,7 +87,7 @@ __nscd_gethostbyaddr_r (const void *addr, socklen_t len, int type,
}
-libc_locked_map_ptr (, __hst_map_handle) attribute_hidden;
+libc_locked_map_ptr (, __hst_map_handle);
/* Note that we only free the structure if necessary. The memory
mapping is not removed since it is not visible to the malloc
handling. */
@@ -118,6 +118,7 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type,
&gc_cycle);
retry:;
+ const hst_response_header *hst_resp = NULL;
const char *h_name = NULL;
const uint32_t *aliases_len = NULL;
const char *addr_list = NULL;
@@ -125,27 +126,18 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type,
int retval = -1;
const char *recend = (const char *) ~UINTMAX_C (0);
int sock = -1;
- hst_response_header hst_resp;
if (mapped != NO_MAPPING)
{
- /* No const qualifier, as it can change during garbage collection. */
- struct datahead *found = __nscd_cache_search (type, key, keylen, mapped);
+ const struct datahead *found = __nscd_cache_search (type, key, keylen,
+ mapped);
if (found != NULL)
{
- h_name = (char *) (&found->data[0].hstdata + 1);
- hst_resp = found->data[0].hstdata;
- aliases_len = (uint32_t *) (h_name + hst_resp.h_name_len);
+ hst_resp = &found->data[0].hstdata;
+ h_name = (char *) (hst_resp + 1);
+ aliases_len = (uint32_t *) (h_name + hst_resp->h_name_len);
addr_list = ((char *) aliases_len
- + hst_resp.h_aliases_cnt * sizeof (uint32_t));
- addr_list_len = hst_resp.h_addr_list_cnt * INADDRSZ;
- recend = (const char *) found->data + found->recsize;
- /* Now check if we can trust hst_resp fields. If GC is
- in progress, it can contain anything. */
- if (mapped->head->gc_cycle != gc_cycle)
- {
- retval = -2;
- goto out;
- }
+ + hst_resp->h_aliases_cnt * sizeof (uint32_t));
+ addr_list_len = hst_resp->h_addr_list_cnt * INADDRSZ;
#ifndef _STRING_ARCH_unaligned
/* The aliases_len array in the mapped database might very
@@ -155,47 +147,51 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type,
if (((uintptr_t) aliases_len & (__alignof__ (*aliases_len) - 1))
!= 0)
{
- uint32_t *tmp = alloca (hst_resp.h_aliases_cnt
+ uint32_t *tmp = alloca (hst_resp->h_aliases_cnt
* sizeof (uint32_t));
aliases_len = memcpy (tmp, aliases_len,
- hst_resp.h_aliases_cnt
+ hst_resp->h_aliases_cnt
* sizeof (uint32_t));
}
#endif
if (type != GETHOSTBYADDR && type != GETHOSTBYNAME)
{
- if (hst_resp.h_length == INADDRSZ)
+ if (hst_resp->h_length == INADDRSZ)
addr_list += addr_list_len;
- addr_list_len = hst_resp.h_addr_list_cnt * IN6ADDRSZ;
+ addr_list_len = hst_resp->h_addr_list_cnt * IN6ADDRSZ;
}
+ recend = (const char *) found->data + found->recsize;
if (__builtin_expect ((const char *) addr_list + addr_list_len
> recend, 0))
- goto out;
+ goto out_close;
}
}
- if (h_name == NULL)
+ hst_response_header hst_resp_mem;
+ if (hst_resp == NULL)
{
- sock = __nscd_open_socket (key, keylen, type, &hst_resp,
- sizeof (hst_resp));
+ sock = __nscd_open_socket (key, keylen, type, &hst_resp_mem,
+ sizeof (hst_resp_mem));
if (sock == -1)
{
__nss_not_use_nscd_hosts = 1;
- goto out;
+ goto out;;
}
+
+ hst_resp = &hst_resp_mem;
}
/* No value found so far. */
*result = NULL;
- if (__builtin_expect (hst_resp.found == -1, 0))
+ if (__builtin_expect (hst_resp->found == -1, 0))
{
/* The daemon does not cache this database. */
__nss_not_use_nscd_hosts = 1;
goto out_close;
}
- if (hst_resp.found == 1)
+ if (hst_resp->found == 1)
{
struct iovec vec[4];
char *cp = buffer;
@@ -211,18 +207,17 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type,
align the pointer and the base of the h_addr_list pointers. */
align1 = ((__alignof__ (char *) - (cp - ((char *) 0)))
& (__alignof__ (char *) - 1));
- align2 = ((__alignof__ (char *) - ((cp + align1 + hst_resp.h_name_len)
+ align2 = ((__alignof__ (char *) - ((cp + align1 + hst_resp->h_name_len)
- ((char *) 0)))
& (__alignof__ (char *) - 1));
- if (buflen < (align1 + hst_resp.h_name_len + align2
- + ((hst_resp.h_aliases_cnt + hst_resp.h_addr_list_cnt
+ if (buflen < (align1 + hst_resp->h_name_len + align2
+ + ((hst_resp->h_aliases_cnt + hst_resp->h_addr_list_cnt
+ 2)
* sizeof (char *))
- + hst_resp.h_addr_list_cnt * (type == AF_INET
- ? INADDRSZ : IN6ADDRSZ)))
+ + hst_resp->h_addr_list_cnt * (type == AF_INET
+ ? INADDRSZ : IN6ADDRSZ)))
{
no_room:
- *h_errnop = NETDB_INTERNAL;
__set_errno (ERANGE);
retval = ERANGE;
goto out_close;
@@ -231,12 +226,12 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type,
/* Prepare the result as far as we can. */
resultbuf->h_aliases = (char **) cp;
- cp += (hst_resp.h_aliases_cnt + 1) * sizeof (char *);
+ cp += (hst_resp->h_aliases_cnt + 1) * sizeof (char *);
resultbuf->h_addr_list = (char **) cp;
- cp += (hst_resp.h_addr_list_cnt + 1) * sizeof (char *);
+ cp += (hst_resp->h_addr_list_cnt + 1) * sizeof (char *);
resultbuf->h_name = cp;
- cp += hst_resp.h_name_len + align2;
+ cp += hst_resp->h_name_len + align2;
if (type == GETHOSTBYADDR || type == GETHOSTBYNAME)
{
@@ -248,7 +243,7 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type,
resultbuf->h_addrtype = AF_INET6;
resultbuf->h_length = IN6ADDRSZ;
}
- for (cnt = 0; cnt < hst_resp.h_addr_list_cnt; ++cnt)
+ for (cnt = 0; cnt < hst_resp->h_addr_list_cnt; ++cnt)
{
resultbuf->h_addr_list[cnt] = cp;
cp += resultbuf->h_length;
@@ -258,63 +253,64 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type,
if (h_name == NULL)
{
vec[0].iov_base = resultbuf->h_name;
- vec[0].iov_len = hst_resp.h_name_len;
- total_len = hst_resp.h_name_len;
+ vec[0].iov_len = hst_resp->h_name_len;
+ total_len = hst_resp->h_name_len;
n = 1;
- if (hst_resp.h_aliases_cnt > 0)
+ if (hst_resp->h_aliases_cnt > 0)
{
- aliases_len = alloca (hst_resp.h_aliases_cnt
+ aliases_len = alloca (hst_resp->h_aliases_cnt
* sizeof (uint32_t));
vec[n].iov_base = (void *) aliases_len;
- vec[n].iov_len = hst_resp.h_aliases_cnt * sizeof (uint32_t);
+ vec[n].iov_len = hst_resp->h_aliases_cnt * sizeof (uint32_t);
- total_len += hst_resp.h_aliases_cnt * sizeof (uint32_t);
+ total_len += hst_resp->h_aliases_cnt * sizeof (uint32_t);
++n;
}
if (type == GETHOSTBYADDR || type == GETHOSTBYNAME)
{
vec[n].iov_base = resultbuf->h_addr_list[0];
- vec[n].iov_len = hst_resp.h_addr_list_cnt * INADDRSZ;
+ vec[n].iov_len = hst_resp->h_addr_list_cnt * INADDRSZ;
- total_len += hst_resp.h_addr_list_cnt * INADDRSZ;
+ total_len += hst_resp->h_addr_list_cnt * INADDRSZ;
++n;
}
else
{
- if (hst_resp.h_length == INADDRSZ)
+ if (hst_resp->h_length == INADDRSZ)
{
- ignore = alloca (hst_resp.h_addr_list_cnt * INADDRSZ);
+ ignore = alloca (hst_resp->h_addr_list_cnt * INADDRSZ);
vec[n].iov_base = ignore;
- vec[n].iov_len = hst_resp.h_addr_list_cnt * INADDRSZ;
+ vec[n].iov_len = hst_resp->h_addr_list_cnt * INADDRSZ;
- total_len += hst_resp.h_addr_list_cnt * INADDRSZ;
+ total_len += hst_resp->h_addr_list_cnt * INADDRSZ;
++n;
}
vec[n].iov_base = resultbuf->h_addr_list[0];
- vec[n].iov_len = hst_resp.h_addr_list_cnt * IN6ADDRSZ;
+ vec[n].iov_len = hst_resp->h_addr_list_cnt * IN6ADDRSZ;
- total_len += hst_resp.h_addr_list_cnt * IN6ADDRSZ;
+ total_len += hst_resp->h_addr_list_cnt * IN6ADDRSZ;
++n;
}
- if ((size_t) __readvall (sock, vec, n) != total_len)
+ if ((size_t) TEMP_FAILURE_RETRY (__readv (sock, vec, n))
+ != total_len)
goto out_close;
}
else
{
- memcpy (resultbuf->h_name, h_name, hst_resp.h_name_len);
+ memcpy (resultbuf->h_name, h_name, hst_resp->h_name_len);
memcpy (resultbuf->h_addr_list[0], addr_list, addr_list_len);
}
/* Now we also can read the aliases. */
total_len = 0;
- for (cnt = 0; cnt < hst_resp.h_aliases_cnt; ++cnt)
+ for (cnt = 0; cnt < hst_resp->h_aliases_cnt; ++cnt)
{
resultbuf->h_aliases[cnt] = cp;
cp += aliases_len[cnt];
@@ -324,32 +320,17 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type,
if (__builtin_expect ((const char *) addr_list + addr_list_len
+ total_len > recend, 0))
- {
- /* aliases_len array might contain garbage during nscd GC cycle,
- retry rather than fail in that case. */
- if (addr_list != NULL && mapped->head->gc_cycle != gc_cycle)
- retval = -2;
- goto out_close;
- }
+ goto out_close;
/* See whether this would exceed the buffer capacity. */
if (__builtin_expect (cp > buffer + buflen, 0))
- {
- /* aliases_len array might contain garbage during nscd GC cycle,
- retry rather than fail in that case. */
- if (addr_list != NULL && mapped->head->gc_cycle != gc_cycle)
- {
- retval = -2;
- goto out_close;
- }
- goto no_room;
- }
+ goto no_room;
/* And finally read the aliases. */
if (addr_list == NULL)
{
- if (total_len == 0
- || ((size_t) __readall (sock, resultbuf->h_aliases[0], total_len)
- == total_len))
+ if ((size_t) TEMP_FAILURE_RETRY (__read (sock,
+ resultbuf->h_aliases[0],
+ total_len)) == total_len)
{
retval = 0;
*result = resultbuf;
@@ -361,18 +342,14 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type,
(const char *) addr_list + addr_list_len, total_len);
/* Try to detect corrupt databases. */
- if (resultbuf->h_name[hst_resp.h_name_len - 1] != '\0'
- || ({for (cnt = 0; cnt < hst_resp.h_aliases_cnt; ++cnt)
+ if (resultbuf->h_name[hst_resp->h_name_len - 1] != '\0'
+ || ({for (cnt = 0; cnt < hst_resp->h_aliases_cnt; ++cnt)
if (resultbuf->h_aliases[cnt][aliases_len[cnt] - 1]
!= '\0')
break;
- cnt < hst_resp.h_aliases_cnt; }))
- {
- /* We cannot use the database. */
- if (mapped->head->gc_cycle != gc_cycle)
- retval = -2;
- goto out_close;
- }
+ cnt < hst_resp->h_aliases_cnt; }))
+ /* We cannot use the database. */
+ goto out_close;
retval = 0;
*result = resultbuf;
@@ -381,7 +358,7 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type,
else
{
/* Store the error number. */
- *h_errnop = hst_resp.error;
+ *h_errnop = hst_resp->error;
/* The `errno' to some value != ERANGE. */
__set_errno (ENOENT);
@@ -393,21 +370,19 @@ nscd_gethst_r (const char *key, size_t keylen, request_type type,
if (sock != -1)
close_not_cancel_no_status (sock);
out:
- if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0)
+ if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0 && retval != -1)
{
/* When we come here this means there has been a GC cycle while we
were looking for the data. This means the data might have been
inconsistent. Retry if possible. */
- if ((gc_cycle & 1) != 0 || ++nretries == 5 || retval == -1)
+ if ((gc_cycle & 1) != 0 || ++nretries == 5)
{
/* nscd is just running gc now. Disable using the mapping. */
- if (atomic_decrement_val (&mapped->counter) == 0)
- __nscd_unmap (mapped);
+ __nscd_unmap (mapped);
mapped = NO_MAPPING;
}
- if (retval != -1)
- goto retry;
+ goto retry;
}
return retval;