[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[commits] r6143 - in /fsf/trunk/libc: ./ include/ include/arpa/ misc/ nis/ nis/nss_nis/ nis/nss_nisplus/ nptl/ nptl/sysdeps/unix/sysv/...
- To: commits@xxxxxxxxxx
- Subject: [commits] r6143 - in /fsf/trunk/libc: ./ include/ include/arpa/ misc/ nis/ nis/nss_nis/ nis/nss_nisplus/ nptl/ nptl/sysdeps/unix/sysv/...
- From: eglibc@xxxxxxxxxx
- Date: Sun, 11 May 2008 07:06:34 -0000
Author: eglibc
Date: Sun May 11 00:06:32 2008
New Revision: 6143
Log:
Import glibc-mainline for 2008-05-11
Modified:
fsf/trunk/libc/ChangeLog
fsf/trunk/libc/NEWS
fsf/trunk/libc/include/arpa/nameser_compat.h
fsf/trunk/libc/include/resolv.h
fsf/trunk/libc/misc/truncate64.c
fsf/trunk/libc/nis/Versions
fsf/trunk/libc/nis/nss_nis/nis-hosts.c
fsf/trunk/libc/nis/nss_nisplus/nisplus-hosts.c
fsf/trunk/libc/nptl/ChangeLog
fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S
fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S
fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S
fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S
fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S
fsf/trunk/libc/nscd/aicache.c
fsf/trunk/libc/nscd/cache.c
fsf/trunk/libc/nscd/grpcache.c
fsf/trunk/libc/nscd/hstcache.c
fsf/trunk/libc/nscd/initgrcache.c
fsf/trunk/libc/nscd/pwdcache.c
fsf/trunk/libc/nscd/servicescache.c
fsf/trunk/libc/nss/Versions
fsf/trunk/libc/nss/nss.h
fsf/trunk/libc/nss/nss_files/files-hosts.c
fsf/trunk/libc/resolv/Versions
fsf/trunk/libc/resolv/gethnamaddr.c
fsf/trunk/libc/resolv/nss_dns/dns-canon.c
fsf/trunk/libc/resolv/nss_dns/dns-host.c
fsf/trunk/libc/resolv/nss_dns/dns-network.c
fsf/trunk/libc/resolv/res_query.c
fsf/trunk/libc/resolv/res_send.c
fsf/trunk/libc/sysdeps/ieee754/ldbl-128/e_j0l.c
fsf/trunk/libc/sysdeps/ieee754/ldbl-128/e_j1l.c
fsf/trunk/libc/sysdeps/ieee754/ldbl-128/s_expm1l.c
fsf/trunk/libc/sysdeps/ieee754/ldbl-128/s_log1pl.c
fsf/trunk/libc/sysdeps/posix/getaddrinfo.c
fsf/trunk/libc/sysdeps/unix/sysv/linux/sys/user.h
Modified: fsf/trunk/libc/ChangeLog
==============================================================================
--- fsf/trunk/libc/ChangeLog (original)
+++ fsf/trunk/libc/ChangeLog Sun May 11 00:06:32 2008
@@ -1,3 +1,79 @@
+2008-05-10 Ulrich Drepper <drepper@xxxxxxxxxx>
+
+ * nscd/cache.c (cache_add): Before returning with failure and this
+ is the first use of the record, mark it as unusable.
+ * nscd/aicache.c: Don't touch the dataset after cache_add returns
+ reporting a failure.
+ * nscd/grpcache.c: Likewise
+ * nscd/hstcache.c: Likewise.
+ * nscd/initgrcache.c: Likewise.
+ * nscd/pwdcache.c: Likewise.
+ * nscd/servicecache.c: Likewise.
+
+2008-05-10 Roland McGrath <roland@xxxxxxxxxx>
+
+ [BZ #6505]
+ * sysdeps/unix/sysv/linux/sys/user.h: Replace with #error stub.
+
+2008-05-08 David S. Miller <davem@xxxxxxxxxxxxx>
+
+ * misc/truncate64.c (truncate64): Use __truncate not truncate.
+
+ * sysdeps/ieee754/ldbl-128/e_j0l.c (__ieee751_j0l): Use __finitel.
+ (__ieee754_y0l): Likewise.
+ * sysdeps/ieee754/ldbl-128/e_j1l.c (__ieee754_j1l): Likewise.
+ (__ieee754_y1l): Likewise.
+ * sysdeps/ieee754/ldbl-128/s_expm1l.c (__expm1l): Use __ldexpl.
+ * sysdeps/ieee754/ldbl-128/s_log1pl.c: Kill bogus prototypes for
+ frexpl and ldexpl. math_private.h provides them and the latter
+ is not even used.
+ (__log1pl): Use __frexpl.
+
+2008-05-10 Ulrich Drepper <drepper@xxxxxxxxxx>
+
+ * include/resolv.h: Adjust __libc_res_nquery and __libc_res_nsend
+ prototypes.
+ * include/arpa/nameser_compat.h: Define T_UNSPEC.
+ * nis/Versions (libnss_nis): Export _nss_nis_gethostbyname4_r.
+ (libnss_nisplus): Export _nss_nisplus_gethostbyname4_r.
+ * nis/nss_nis/nis-hosts.c (LINE_PARSER): Change to also handle
+ af==AF_UNSPEC.
+ (_nss_nis_gethostbyname4_r): New function.
+ * nis/nss_nisplus/nisplus-hosts.c (_nss_nisplus_parse_hostent):
+ Change to also handle af==AF_UNSPEC.
+ (get_tablename): New function. Use it to avoid duplication.
+ (_nss_nisplus_gethostbyname4_r): New function.
+ * nscd/aicache.c (addhstaiX): Use gethostbyname4_r function is
+ available.
+ * nss/Versions (libnss_files): Export _nss_files_gethostbyname4_r.
+ * nss/nss.h: Define struct gaih_addrtuple.
+ * nss/nss_files/files-hosts.c (LINE_PARSER): Change to also handle
+ af==AF_UNSPEC.
+ (_nss_files_gethostbyname4_r): New function.
+ * resolv/Versions (libnss_dns): Export _nss_dns_gethostbyname4_r.
+ * resolv/gethnmaddr.c: Adjust __libc_res_nsearch and __libc_res_nquery
+ calls.
+ * resolv/res_query.c (__libc_res_nquery): Take two additional
+ parameters for second answer buffer. Handle type=T_UNSPEC to mean
+ look up IPv4 and IPv6.
+ Change all callers.
+ * resolv/res_send.c (__libc_res_nsend): Take five aditional parameters
+ for an additional query and answer buffer. Pass to send_vc and
+ send_dg.
+ (send_vc): Send possibly two requests and receive two answers.
+ (send_dg): Likewise.
+ * resolv/nss_dns/dns-host.c: Adjust calls to __libc_res_nsearch and
+ __libc_res_nquery.
+ (_nss_dns_gethostbyname4_r): New function.
+ (gaih_getanswer_slice): Likewise.
+ (gaih_getanswer): Likewise.
+ * resolv/nss_dns/dns-canon.c (_nss_dns_getcanonname_r): Adjust
+ __libc_res_nquery call.
+ * resolv/nss_dns/dns-network.c (_nss_dns_getnetbyaddr_r): Likewise.
+ (_nss_dns_getnetbyname_r): Adjust __libc_res_nsearch call.
+ * sysdeps/posix/getaddrinfo.c: Use gethostbyname4_r function is
+ available.
+
2008-05-05 David S. Miller <davem@xxxxxxxxxxxxx>
* sysdeps/sparc/sparc32/Makefile: Use -mcpu=v7 for initfini.s build.
Modified: fsf/trunk/libc/NEWS
==============================================================================
--- fsf/trunk/libc/NEWS (original)
+++ fsf/trunk/libc/NEWS Sun May 11 00:06:32 2008
@@ -1,9 +1,14 @@
-GNU C Library NEWS -- history of user-visible changes. 2008-4-9
+GNU C Library NEWS -- history of user-visible changes. 2008-5-10
Copyright (C) 1992-2007, 2008 Free Software Foundation, Inc.
See the end for copying conditions.
Please send GNU C library bug reports via <http://sources.redhat.com/bugzilla/>
using `glibc' in the "product" field.
+
+Version 2.9
+
+* Unified lookup for getaddrinfo: IPv4 and IPv6 addresses are now looked
+ up at the same time.
Version 2.8
Modified: fsf/trunk/libc/include/arpa/nameser_compat.h
==============================================================================
--- fsf/trunk/libc/include/arpa/nameser_compat.h (original)
+++ fsf/trunk/libc/include/arpa/nameser_compat.h Sun May 11 00:06:32 2008
@@ -1,1 +1,8 @@
+#ifndef _ARPA_NAMESER_COMPAT_
#include <resolv/arpa/nameser_compat.h>
+
+/* Picksome unused number to represent lookups of IPv4 and IPv6 (i.e.,
+ T_A and T_AAAA). */
+#define T_UNSPEC 62321
+
+#endif
Modified: fsf/trunk/libc/include/resolv.h
==============================================================================
--- fsf/trunk/libc/include/resolv.h (original)
+++ fsf/trunk/libc/include/resolv.h Sun May 11 00:06:32 2008
@@ -58,11 +58,11 @@
libc_hidden_proto (__res_state)
int __libc_res_nquery (res_state, const char *, int, int, u_char *, int,
- u_char **);
+ u_char **, u_char **, int *);
int __libc_res_nsearch (res_state, const char *, int, int, u_char *, int,
- u_char **);
-int __libc_res_nsend (res_state, const u_char *, int, u_char *, int,
- u_char **)
+ u_char **, u_char **, int *);
+int __libc_res_nsend (res_state, const u_char *, int, const u_char *, int,
+ u_char *, int, u_char **, u_char **, int *)
attribute_hidden;
libresolv_hidden_proto (_sethtent)
Modified: fsf/trunk/libc/misc/truncate64.c
==============================================================================
--- fsf/trunk/libc/misc/truncate64.c (original)
+++ fsf/trunk/libc/misc/truncate64.c Sun May 11 00:06:32 2008
@@ -31,5 +31,5 @@
__set_errno (EINVAL);
return -1;
}
- return truncate (path, (off_t) length);
+ return __truncate (path, (off_t) length);
}
Modified: fsf/trunk/libc/nis/Versions
==============================================================================
--- fsf/trunk/libc/nis/Versions (original)
+++ fsf/trunk/libc/nis/Versions Sun May 11 00:06:32 2008
@@ -95,7 +95,7 @@
_nss_nis_setgrent; _nss_nis_sethostent; _nss_nis_setnetent;
_nss_nis_setnetgrent; _nss_nis_setprotoent; _nss_nis_setpwent;
_nss_nis_setrpcent; _nss_nis_setservent; _nss_nis_setspent;
- _nss_nis_initgroups_dyn;
+ _nss_nis_initgroups_dyn; _nss_nis_gethostbyname4_r;
}
}
@@ -126,5 +126,6 @@
_nss_nisplus_setnetent; _nss_nisplus_setnetgrent; _nss_nisplus_setprotoent;
_nss_nisplus_setpwent; _nss_nisplus_setrpcent; _nss_nisplus_setservent;
_nss_nisplus_setspent; _nss_nisplus_initgroups_dyn;
+ _nss_nisplus_gethostbyname4_r;
}
}
Modified: fsf/trunk/libc/nis/nss_nis/nis-hosts.c
==============================================================================
--- fsf/trunk/libc/nis/nss_nis/nis-hosts.c (original)
+++ fsf/trunk/libc/nis/nss_nis/nis-hosts.c Sun May 11 00:06:32 2008
@@ -1,4 +1,5 @@
-/* Copyright (C) 1996-2000, 2002, 2003, 2006, 2007 Free Software Foundation, Inc.
+/* Copyright (C) 1996-2000, 2002, 2003, 2006, 2007, 2008
+ Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Thorsten Kukuk <kukuk@xxxxxxx>, 1996.
@@ -17,6 +18,7 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
+#include <assert.h>
#include <nss.h>
#include <ctype.h>
/* The following is an ugly trick to avoid a prototype declaration for
@@ -61,9 +63,12 @@
STRING_FIELD (addr, isspace, 1);
+ assert (af == AF_INET || af == AF_INET6 || af == AF_UNSPEC);
+
/* Parse address. */
- if (af == AF_INET && inet_pton (AF_INET, addr, entdata->host_addr) > 0)
+ if (af != AF_INET6 && inet_pton (AF_INET, addr, entdata->host_addr) > 0)
{
+ assert ((flags & AI_V4MAPPED) == 0 || af != AF_UNSPEC);
if (flags & AI_V4MAPPED)
{
map_v4v6_address ((char *) entdata->host_addr,
@@ -77,7 +82,7 @@
result->h_length = INADDRSZ;
}
}
- else if (af == AF_INET6
+ else if (af != AF_INET
&& inet_pton (AF_INET6, addr, entdata->host_addr) > 0)
{
result->h_addrtype = AF_INET6;
@@ -102,6 +107,7 @@
static char *oldkey = NULL;
static int oldkeylen = 0;
+
enum nss_status
_nss_nis_sethostent (int stayopen)
{
@@ -123,6 +129,7 @@
even though the prototypes don't match. The argument of sethostent
is used so this makes no difference. */
strong_alias (_nss_nis_sethostent, _nss_nis_endhostent)
+
/* The calling function always need to get a lock first. */
static enum nss_status
@@ -216,6 +223,7 @@
return NSS_STATUS_SUCCESS;
}
+
enum nss_status
_nss_nis_gethostent_r (struct hostent *host, char *buffer, size_t buflen,
int *errnop, int *h_errnop)
@@ -232,6 +240,7 @@
return status;
}
+
static enum nss_status
internal_gethostbyname2_r (const char *name, int af, struct hostent *host,
@@ -323,15 +332,23 @@
return NSS_STATUS_SUCCESS;
}
+
enum nss_status
_nss_nis_gethostbyname2_r (const char *name, int af, struct hostent *host,
char *buffer, size_t buflen, int *errnop,
int *h_errnop)
{
+ if (af != AF_INET && af != AF_INET6)
+ {
+ *h_errnop = HOST_NOT_FOUND;
+ return NSS_STATUS_NOTFOUND;
+ }
+
return internal_gethostbyname2_r (name, af, host, buffer, buflen, errnop,
h_errnop,
((_res.options & RES_USE_INET6) ? AI_V4MAPPED : 0));
}
+
enum nss_status
_nss_nis_gethostbyname_r (const char *name, struct hostent *host, char *buffer,
@@ -350,6 +367,7 @@
return internal_gethostbyname2_r (name, AF_INET, host, buffer, buflen,
errnop, h_errnop, 0);
}
+
enum nss_status
_nss_nis_gethostbyaddr_r (const void *addr, socklen_t addrlen, int af,
@@ -430,13 +448,93 @@
return NSS_STATUS_SUCCESS;
}
-#if 0
+
enum nss_status
-_nss_nis_getipnodebyname_r (const char *name, int af, int flags,
- struct hostent *result, char *buffer,
- size_t buflen, int *errnop, int *herrnop)
-{
- return internal_gethostbyname2_r (name, af, result, buffer, buflen,
- errnop, herrnop, flags);
-}
-#endif
+_nss_nis_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
+ char *buffer, size_t buflen, int *errnop,
+ int *herrnop, int32_t *ttlp)
+{
+ char *domain;
+ if (yp_get_default_domain (&domain))
+ return NSS_STATUS_UNAVAIL;
+
+ /* Convert name to lowercase. */
+ size_t namlen = strlen (name);
+ char name2[namlen + 1];
+ size_t i;
+
+ for (i = 0; i < namlen; ++i)
+ name2[i] = tolower (name[i]);
+ name2[i] = '\0';
+
+ char *result;
+ int len;
+ int yperr = yp_match (domain, "hosts.byname", name2, namlen, &result, &len);
+
+ if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
+ {
+ enum nss_status retval = yperr2nss (yperr);
+
+ if (retval == NSS_STATUS_TRYAGAIN)
+ {
+ *herrnop = TRY_AGAIN;
+ *errnop = errno;
+ }
+ if (retval == NSS_STATUS_NOTFOUND)
+ *herrnop = HOST_NOT_FOUND;
+ return retval;
+ }
+
+ struct parser_data data;
+ struct hostent host;
+ int parse_res = parse_line (result, &host, &data, buflen, errnop, AF_UNSPEC,
+ 0);
+ if (__builtin_expect (parse_res < 1, 0))
+ {
+ if (parse_res == -1)
+ {
+ *herrnop = NETDB_INTERNAL;
+ return NSS_STATUS_TRYAGAIN;
+ }
+ else
+ {
+ *herrnop = HOST_NOT_FOUND;
+ return NSS_STATUS_NOTFOUND;
+ }
+ }
+
+ if (*pat == NULL)
+ {
+ uintptr_t pad = (-(uintptr_t) buffer
+ % __alignof__ (struct gaih_addrtuple));
+ buffer += pad;
+ buflen = buflen > pad ? buflen - pad : 0;
+
+ if (__builtin_expect (buflen < sizeof (struct gaih_addrtuple), 0))
+ {
+ erange:
+ free (result);
+ *errnop = ERANGE;
+ *herrnop = NETDB_INTERNAL;
+ return NSS_STATUS_TRYAGAIN;
+ }
+
+ *pat = (struct gaih_addrtuple *) buffer;
+ buffer += sizeof (struct gaih_addrtuple);
+ buflen -= sizeof (struct gaih_addrtuple);
+ }
+
+ (*pat)->next = NULL;
+ size_t h_name_len = strlen (host.h_name);
+ if (h_name_len >= buflen)
+ goto erange;
+ (*pat)->name = memcpy (buffer, host.h_name, h_name_len + 1);
+ (*pat)->family = host.h_addrtype;
+ memcpy ((*pat)->addr, host.h_addr_list[0], host.h_length);
+ (*pat)->scopeid = 0;
+ assert (host.h_addr_list[1] == NULL);
+
+ free (result);
+
+ return NSS_STATUS_SUCCESS;
+}
Modified: fsf/trunk/libc/nis/nss_nisplus/nisplus-hosts.c
==============================================================================
--- fsf/trunk/libc/nis/nss_nisplus/nisplus-hosts.c (original)
+++ fsf/trunk/libc/nis/nss_nisplus/nisplus-hosts.c Sun May 11 00:06:32 2008
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997-2002, 2003, 2005, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 1997-2003, 2005, 2006, 2008 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Thorsten Kukuk <kukuk@xxxxxxx>, 1997.
@@ -17,6 +17,7 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
+#include <assert.h>
#include <atomic.h>
#include <ctype.h>
#include <errno.h>
@@ -58,15 +59,15 @@
if (result == NULL)
return 0;
- if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) ||
- __type_of (NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ ||
- strcmp(NIS_RES_OBJECT (result)[0].EN_data.en_type, "hosts_tbl") != 0 ||
- NIS_RES_OBJECT (result)[0].EN_data.en_cols.en_cols_len < 4)
+ if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
+ || __type_of (NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
+ || strcmp (NIS_RES_OBJECT (result)[0].EN_data.en_type, "hosts_tbl") != 0
+ || NIS_RES_OBJECT (result)[0].EN_data.en_cols.en_cols_len < 4)
return 0;
char *data = first_unused;
- if (room_left < (af == AF_INET6 || (flags & AI_V4MAPPED) != 0
+ if (room_left < (af != AF_INET || (flags & AI_V4MAPPED) != 0
? IN6ADDRSZ : INADDRSZ))
{
no_more_room:
@@ -75,8 +76,10 @@
}
/* Parse address. */
- if (af == AF_INET && inet_pton (af, NISENTRYVAL (0, 2, result), data) > 0)
- {
+ if (af != AF_INET6
+ && inet_pton (AF_INET, NISENTRYVAL (0, 2, result), data) > 0)
+ {
+ assert ((flags & AI_V4MAPPED) == 0 || af != AF_UNSPEC);
if (flags & AI_V4MAPPED)
{
map_v4v6_address (data, data);
@@ -89,7 +92,7 @@
host->h_length = INADDRSZ;
}
}
- else if (af == AF_INET6
+ else if (af != AF_INET
&& inet_pton (AF_INET6, NISENTRYVAL (0, 2, result), data) > 0)
{
host->h_addrtype = AF_INET6;
@@ -109,27 +112,33 @@
first_unused = __stpncpy (first_unused, NISENTRYVAL (0, 0, result),
NISENTRYLEN (0, 0, result));
*first_unused++ = '\0';
+
room_left -= NISENTRYLEN (0, 0, result) + 1;
-
- /* XXX Rewrite at some point to allocate the array first and then
- copy the strings. It wasteful to first concatenate the strings
- to just split them again later. */
char *line = first_unused;
- for (i = 0; i < NIS_RES_NUMOBJ (result); ++i)
- {
- if (strcmp (NISENTRYVAL (i, 1, result), host->h_name) != 0)
- {
- if (NISENTRYLEN (i, 1, result) + 2 > room_left)
- goto no_more_room;
-
- *first_unused++ = ' ';
- first_unused = __stpncpy (first_unused, NISENTRYVAL (i, 1, result),
- NISENTRYLEN (i, 1, result));
- *first_unused = '\0';
- room_left -= NISENTRYLEN (i, 1, result) + 1;
- }
- }
- *first_unused++ = '\0';
+
+ /* When this is a call to gethostbyname4_r we do not need the aliases. */
+ if (af != AF_UNSPEC)
+ {
+ /* XXX Rewrite at some point to allocate the array first and then
+ copy the strings. It is wasteful to first concatenate the strings
+ to just split them again later. */
+ for (i = 0; i < NIS_RES_NUMOBJ (result); ++i)
+ {
+ if (strcmp (NISENTRYVAL (i, 1, result), host->h_name) != 0)
+ {
+ if (NISENTRYLEN (i, 1, result) + 2 > room_left)
+ goto no_more_room;
+
+ *first_unused++ = ' ';
+ first_unused = __stpncpy (first_unused,
+ NISENTRYVAL (i, 1, result),
+ NISENTRYLEN (i, 1, result));
+ *first_unused = '\0';
+ room_left -= NISENTRYLEN (i, 1, result) + 1;
+ }
+ }
+ *first_unused++ = '\0';
+ }
/* Adjust the pointer so it is aligned for
storing pointers. */
@@ -147,30 +156,34 @@
host->h_addr_list[1] = NULL;
host->h_aliases = &host->h_addr_list[2];
- i = 0;
- while (*line != '\0')
- {
- /* Skip leading blanks. */
- while (isspace (*line))
- ++line;
-
- if (*line == '\0')
- break;
-
- if (room_left < sizeof (char *))
- goto no_more_room;
-
- room_left -= sizeof (char *);
- host->h_aliases[i++] = line;
-
- while (*line != '\0' && *line != ' ')
- ++line;
-
- if (*line == ' ')
- *line++ = '\0';
- }
-
- host->h_aliases[i] = NULL;
+ /* When this is a call to gethostbyname4_r we do not need the aliases. */
+ if (af != AF_UNSPEC)
+ {
+ i = 0;
+ while (*line != '\0')
+ {
+ /* Skip leading blanks. */
+ while (isspace (*line))
+ ++line;
+
+ if (*line == '\0')
+ break;
+
+ if (room_left < sizeof (char *))
+ goto no_more_room;
+
+ room_left -= sizeof (char *);
+ host->h_aliases[i++] = line;
+
+ while (*line != '\0' && *line != ' ')
+ ++line;
+
+ if (*line == ' ')
+ *line++ = '\0';
+ }
+
+ host->h_aliases[i] = NULL;
+ }
return 1;
}
@@ -204,6 +217,7 @@
return NSS_STATUS_SUCCESS;
}
+
enum nss_status
_nss_nisplus_sethostent (int stayopen)
{
@@ -226,6 +240,7 @@
return status;
}
+
enum nss_status
_nss_nisplus_endhostent (void)
{
@@ -241,6 +256,7 @@
return NSS_STATUS_SUCCESS;
}
+
static enum nss_status
internal_nisplus_gethostent_r (struct hostent *host, char *buffer,
@@ -329,6 +345,7 @@
return NSS_STATUS_SUCCESS;
}
+
enum nss_status
_nss_nisplus_gethostent_r (struct hostent *result, char *buffer,
size_t buflen, int *errnop, int *herrnop)
@@ -344,27 +361,34 @@
return status;
}
+
+
+static enum nss_status
+get_tablename (int *herrnop)
+{
+ __libc_lock_lock (lock);
+
+ enum nss_status status = _nss_create_tablename (herrnop);
+
+ __libc_lock_unlock (lock);
+
+ if (status != NSS_STATUS_SUCCESS)
+ *herrnop = NETDB_INTERNAL;
+
+ return status;
+}
+
static enum nss_status
internal_gethostbyname2_r (const char *name, int af, struct hostent *host,
char *buffer, size_t buflen, int *errnop,
int *herrnop, int flags)
{
- int parse_res, retval;
-
if (tablename_val == NULL)
{
- __libc_lock_lock (lock);
-
- enum nss_status status = _nss_create_tablename (errnop);
-
- __libc_lock_unlock (lock);
-
+ enum nss_status status = get_tablename (herrnop);
if (status != NSS_STATUS_SUCCESS)
- {
- *herrnop = NETDB_INTERNAL;
- return NSS_STATUS_UNAVAIL;
- }
+ return status;
}
if (name == NULL)
@@ -374,38 +398,35 @@
return NSS_STATUS_NOTFOUND;
}
- nis_result *result;
char buf[strlen (name) + 10 + tablename_len];
int olderr = errno;
/* Search at first in the alias list, and use the correct name
for the next search. */
snprintf (buf, sizeof (buf), "[name=%s],%s", name, tablename_val);
- result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
+ nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
if (result != NULL)
{
- char *bufptr = buf;
-
/* If we did not find it, try it as original name. But if the
database is correct, we should find it in the first case, too. */
- if ((result->status != NIS_SUCCESS
- && result->status != NIS_S_SUCCESS)
- || __type_of (result->objects.objects_val) != NIS_ENTRY_OBJ
- || strcmp (result->objects.objects_val->EN_data.en_type,
- "hosts_tbl") != 0
- || result->objects.objects_val->EN_data.en_cols.en_cols_len < 3)
- snprintf (buf, sizeof (buf), "[cname=%s],%s", name, tablename_val);
- else
+ char *bufptr = buf;
+ size_t buflen = sizeof (buf);
+
+ if ((result->status == NIS_SUCCESS || result->status == NIS_S_SUCCESS)
+ && __type_of (result->objects.objects_val) == NIS_ENTRY_OBJ
+ && strcmp (result->objects.objects_val->EN_data.en_type,
+ "hosts_tbl") == 0
+ && result->objects.objects_val->EN_data.en_cols.en_cols_len >= 3)
{
/* We need to allocate a new buffer since there is no
- guarantee the returned name has a length limit. */
- const char *entryval = NISENTRYVAL(0, 0, result);
- size_t buflen = strlen (entryval) + 10 + tablename_len;
+ guarantee the returned alias name has a length limit. */
+ name = NISENTRYVAL(0, 0, result);
+ size_t buflen = strlen (name) + 10 + tablename_len;
bufptr = alloca (buflen);
- snprintf (bufptr, buflen, "[cname=%s],%s",
- entryval, tablename_val);
- }
+ }
+
+ snprintf (bufptr, buflen, "[cname=%s],%s", name, tablename_val);
nis_freeresult (result);
result = nis_list (bufptr, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
@@ -417,7 +438,7 @@
return NSS_STATUS_TRYAGAIN;
}
- retval = niserr2nss (result->status);
+ int retval = niserr2nss (result->status);
if (__builtin_expect (retval != NSS_STATUS_SUCCESS, 0))
{
if (retval == NSS_STATUS_TRYAGAIN)
@@ -431,8 +452,8 @@
return retval;
}
- parse_res = _nss_nisplus_parse_hostent (result, af, host, buffer,
- buflen, errnop, flags);
+ int parse_res = _nss_nisplus_parse_hostent (result, af, host, buffer,
+ buflen, errnop, flags);
nis_freeresult (result);
@@ -449,16 +470,24 @@
__set_errno (olderr);
return NSS_STATUS_NOTFOUND;
}
+
enum nss_status
_nss_nisplus_gethostbyname2_r (const char *name, int af, struct hostent *host,
char *buffer, size_t buflen, int *errnop,
int *herrnop)
{
+ if (af != AF_INET && af != AF_INET6)
+ {
+ *herrnop = HOST_NOT_FOUND;
+ return NSS_STATUS_NOTFOUND;
+ }
+
return internal_gethostbyname2_r (name, af, host, buffer, buflen, errnop,
herrnop,
((_res.options & RES_USE_INET6) ? AI_V4MAPPED : 0));
}
+
enum nss_status
_nss_nisplus_gethostbyname_r (const char *name, struct hostent *host,
@@ -480,6 +509,7 @@
buflen, errnop, h_errnop, 0);
}
+
enum nss_status
_nss_nisplus_gethostbyaddr_r (const void *addr, socklen_t addrlen, int af,
struct hostent *host, char *buffer,
@@ -487,12 +517,7 @@
{
if (tablename_val == NULL)
{
- __libc_lock_lock (lock);
-
- enum nss_status status = _nss_create_tablename (errnop);
-
- __libc_lock_unlock (lock);
-
+ enum nss_status status = get_tablename (herrnop);
if (status != NSS_STATUS_SUCCESS)
return status;
}
@@ -547,3 +572,44 @@
__set_errno (olderr);
return NSS_STATUS_NOTFOUND;
}
+
+
+enum nss_status
+_nss_nisplus_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
+ char *buffer, size_t buflen, int *errnop,
+ int *herrnop, int32_t *ttlp)
+{
+ struct hostent host;
+
+ enum nss_status status = internal_gethostbyname2_r (name, AF_UNSPEC, &host,
+ buffer, buflen,
+ errnop, herrnop, 0);
+ if (__builtin_expect (status == NSS_STATUS_SUCCESS, 1))
+ {
+ if (*pat == NULL)
+ {
+ uintptr_t pad = (-(uintptr_t) buffer
+ % __alignof__ (struct gaih_addrtuple));
+ buffer += pad;
+ buflen = buflen > pad ? buflen - pad : 0;
+
+ if (__builtin_expect (buflen < sizeof (struct gaih_addrtuple), 0))
+ {
+ free (result);
+ *errnop = ERANGE;
+ *herrnop = NETDB_INTERNAL;
+ return NSS_STATUS_TRYAGAIN;
+ }
+ }
+
+ (*pat)->next = NULL;
+ (*pat)->name = host.h_name;
+ (*pat)->family = host.h_addrtype;
+
+ memcpy ((*pat)->addr, host.h_addr_list[0], host.h_length);
+ (*pat)->scopeid = 0;
+ assert (host.h_addr_list[1] == NULL);
+ }
+
+ return status;
+}
Modified: fsf/trunk/libc/nptl/ChangeLog
==============================================================================
--- fsf/trunk/libc/nptl/ChangeLog (original)
+++ fsf/trunk/libc/nptl/ChangeLog Sun May 11 00:06:32 2008
@@ -1,3 +1,17 @@
+2008-05-10 Ulrich Drepper <drepper@xxxxxxxxxx>
+
+ * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Access
+ __pshared correctly.
+ * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S:
+ Likewise.
+ * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S:
+ Likewise.
+ * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S:
+ Likewise.
+ * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S:
+ Likewise.
+ Reported by Clemens Kolbitsch <clemens.kol@xxxxxx>.
+
2008-04-14 David S. Miller <davem@xxxxxxxxxxxxx>
* sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c
Modified: fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S
==============================================================================
--- fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S (original)
+++ fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S Sun May 11 00:06:32 2008
@@ -122,7 +122,7 @@
#else
leal MUTEX(%ebx), %edx
#endif
- movl PSHARED(%ebx), %ecx
+ movzbl PSHARED(%ebx), %ecx
call __lll_lock_wait
jmp 2b
@@ -138,7 +138,7 @@
#else
leal MUTEX(%ebx), %eax
#endif
- movl PSHARED(%ebx), %ecx
+ movzbl PSHARED(%ebx), %ecx
call __lll_unlock_wake
jmp 7b
@@ -158,7 +158,7 @@
#else
leal MUTEX(%ebx), %eax
#endif
- movl PSHARED(%ebx), %ecx
+ movzbl PSHARED(%ebx), %ecx
call __lll_unlock_wake
jmp 11b
@@ -168,7 +168,7 @@
#else
leal MUTEX(%ebx), %edx
#endif
- movl PSHARED(%ebx), %ecx
+ movzbl PSHARED(%ebx), %ecx
call __lll_lock_wait
jmp 13b
.size __pthread_rwlock_rdlock,.-__pthread_rwlock_rdlock
Modified: fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S
==============================================================================
--- fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S (original)
+++ fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S Sun May 11 00:06:32 2008
@@ -162,7 +162,7 @@
#else
leal MUTEX(%ebp), %edx
#endif
- movl PSHARED(%ebp), %ecx
+ movzbl PSHARED(%ebp), %ecx
call __lll_lock_wait
jmp 2b
@@ -177,7 +177,7 @@
#else
leal MUTEX(%ebp), %eax
#endif
- movl PSHARED(%ebp), %ecx
+ movzbl PSHARED(%ebp), %ecx
call __lll_unlock_wake
jmp 7b
@@ -197,7 +197,7 @@
#else
leal MUTEX(%ebp), %eax
#endif
- movl PSHARED(%ebp), %ecx
+ movzbl PSHARED(%ebp), %ecx
call __lll_unlock_wake
jmp 11b
@@ -207,7 +207,7 @@
#else
leal MUTEX(%ebp), %edx
#endif
- movl PSHARED(%ebp), %ecx
+ movzbl PSHARED(%ebp), %ecx
call __lll_lock_wait
jmp 13b
Modified: fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S
==============================================================================
--- fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S (original)
+++ fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S Sun May 11 00:06:32 2008
@@ -160,7 +160,7 @@
#else
leal MUTEX(%ebp), %edx
#endif
- movl PSHARED(%ebp), %ecx
+ movzbl PSHARED(%ebp), %ecx
call __lll_lock_wait
jmp 2b
@@ -175,7 +175,7 @@
#else
leal MUTEX(%ebp), %eax
#endif
- movl PSHARED(%ebp), %ecx
+ movzbl PSHARED(%ebp), %ecx
call __lll_unlock_wake
jmp 7b
@@ -190,7 +190,7 @@
#else
leal MUTEX(%ebp), %eax
#endif
- movl PSHARED(%ebp), %ecx
+ movzbl PSHARED(%ebp), %ecx
call __lll_unlock_wake
jmp 11b
@@ -200,7 +200,7 @@
#else
leal MUTEX(%ebp), %edx
#endif
- movl PSHARED(%ebp), %ecx
+ movzbl PSHARED(%ebp), %ecx
call __lll_lock_wait
jmp 13b
Modified: fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S
==============================================================================
--- fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S (original)
+++ fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S Sun May 11 00:06:32 2008
@@ -110,7 +110,7 @@
#else
leal MUTEX(%edi), %edx
#endif
- movl PSHARED(%edi), %ecx
+ movzbl PSHARED(%edi), %ecx
call __lll_lock_wait
jmp 2b
@@ -120,7 +120,7 @@
#else
leal MUTEX(%edi), %eax
#endif
- movl PSHARED(%edi), %ecx
+ movzbl PSHARED(%edi), %ecx
call __lll_unlock_wake
jmp 4b
@@ -130,7 +130,7 @@
#else
leal MUTEX(%edi), %eax
#endif
- movl PSHARED(%edi), %ecx
+ movzbl PSHARED(%edi), %ecx
call __lll_unlock_wake
jmp 8b
Modified: fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S
==============================================================================
--- fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S (original)
+++ fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S Sun May 11 00:06:32 2008
@@ -120,7 +120,7 @@
#else
leal MUTEX(%ebx), %edx
#endif
- movl PSHARED(%ebx), %ecx
+ movzbl PSHARED(%ebx), %ecx
call __lll_lock_wait
jmp 2b
@@ -135,7 +135,7 @@
#else
leal MUTEX(%ebx), %eax
#endif
- movl PSHARED(%ebx), %ecx
+ movzbl PSHARED(%ebx), %ecx
call __lll_unlock_wake
jmp 7b
@@ -149,7 +149,7 @@
#else
leal MUTEX(%ebx), %eax
#endif
- movl PSHARED(%ebx), %ecx
+ movzbl PSHARED(%ebx), %ecx
call __lll_unlock_wake
jmp 11b
@@ -159,7 +159,7 @@
#else
leal MUTEX(%ebx), %edx
#endif
- movl PSHARED(%ebx), %ecx
+ movzbl PSHARED(%ebx), %ecx
call __lll_lock_wait
jmp 13b
.size __pthread_rwlock_wrlock,.-__pthread_rwlock_wrlock
Modified: fsf/trunk/libc/nscd/aicache.c
==============================================================================
--- fsf/trunk/libc/nscd/aicache.c (original)
+++ fsf/trunk/libc/nscd/aicache.c Sun May 11 00:06:32 2008
@@ -21,6 +21,7 @@
#include <errno.h>
#include <libintl.h>
#include <netdb.h>
+#include <nss.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
@@ -33,6 +34,10 @@
#endif
+typedef enum nss_status (*nss_gethostbyname4_r)
+ (const char *name, struct gaih_addrtuple **pat,
+ char *buffer, size_t buflen, int *errnop,
+ int *h_errnop, int32_t *ttlp);
typedef enum nss_status (*nss_gethostbyname3_r)
(const char *name, int af, struct hostent *host,
char *buffer, size_t buflen, int *errnop,
@@ -117,16 +122,104 @@
while (!no_more)
{
+ void *cp;
int status[2] = { NSS_STATUS_UNAVAIL, NSS_STATUS_UNAVAIL };
-
- /* Prefer the function which also returns the TTL and canonical name. */
- nss_gethostbyname3_r fct = __nss_lookup_function (nip,
- "gethostbyname3_r");
- if (fct == NULL)
- fct = __nss_lookup_function (nip, "gethostbyname2_r");
-
- if (fct != NULL)
+ int naddrs = 0;
+ size_t addrslen = 0;
+ size_t canonlen;
+
+ nss_gethostbyname4_r fct4 = __nss_lookup_function (nip,
+ "gethostbyname4_r");
+ if (fct4 != NULL)
{
+ struct gaih_addrtuple *at = NULL;
+ while (1)
+ {
+ rc6 = 0;
+ status[0] = DL_CALL_FCT (fct4, (key, &at, tmpbuf6, tmpbuf6len,
+ &rc6, &herrno, &ttl));
+ if (rc6 != ERANGE || herrno != NETDB_INTERNAL)
+ break;
+ tmpbuf6 = extend_alloca (tmpbuf6, tmpbuf6len, 2 * tmpbuf6len);
+ }
+
+ if (rc6 != 0 && herrno == NETDB_INTERNAL)
+ goto out;
+
+ if (status[0] != NSS_STATUS_SUCCESS)
+ goto next_nip;
+
+ /* We found the data. Count the addresses and the size. */
+ for (struct gaih_addrtuple *at2 = at; at2 != NULL; at2 = at2->next)
+ {
+ ++naddrs;
+ /* We handle unknown types here the best we can: assume
+ the maximum size for the address. */
+ if (at2->family == AF_INET)
+ addrslen += INADDRSZ;
+ else if (at2->family == AF_INET6
+ && IN6ADDRSZ != sizeof (at2->addr))
+ addrslen += IN6ADDRSZ;
+ else
+ addrslen += sizeof (at2->addr);
+ }
+ canon = at->name;
+ canonlen = strlen (canon) + 1;
+
+ total = sizeof (*dataset) + naddrs + addrslen + canonlen;
+
+ /* Now we can allocate the data structure. If the TTL of the
+ entry is reported as zero do not cache the entry at all. */
+ if (ttl != 0 && he == NULL)
+ {
+ dataset = (struct dataset *) mempool_alloc (db, total
+ + req->key_len,
+ IDX_result_data);
+ if (dataset == NULL)
+ ++db->head->addfailed;
+ }
+
+ if (dataset == NULL)
+ {
+ /* We cannot permanently add the result in the moment. But
+ we can provide the result as is. Store the data in some
+ temporary memory. */
+ dataset = (struct dataset *) alloca (total + req->key_len);
+
+ /* We cannot add this record to the permanent database. */
+ alloca_used = true;
+ }
+
+ /* Fill in the address and address families. */
+ char *addrs = (char *) (&dataset->resp + 1);
+ uint8_t *family = (uint8_t *) (addrs + addrslen);
+
+ for (struct gaih_addrtuple *at2 = at; at2 != NULL; at2 = at2->next)
+ {
+ *family++ = at2->family;
+ if (at2->family == AF_INET)
+ addrs = mempcpy (addrs, at2->addr, INADDRSZ);
+ else if (at2->family == AF_INET6
+ && IN6ADDRSZ != sizeof (at2->addr))
+ addrs = mempcpy (addrs, at2->addr, IN6ADDRSZ);
+ else
+ addrs = mempcpy (addrs, at2->addr, sizeof (at2->addr));
+ }
+
+ cp = family;
+ }
+ else
+ {
+ /* Prefer the function which also returns the TTL and
+ canonical name. */
+ nss_gethostbyname3_r fct = __nss_lookup_function (nip,
+ "gethostbyname3_r");
+ if (fct == NULL)
+ fct = __nss_lookup_function (nip, "gethostbyname2_r");
+
+ if (fct == NULL)
+ goto next_nip;
+
struct hostent th[2];
/* Collect IPv6 information first. */
@@ -134,8 +227,8 @@
{
rc6 = 0;
status[0] = DL_CALL_FCT (fct, (key, AF_INET6, &th[0], tmpbuf6,
- tmpbuf6len, &rc6, &herrno,
- &ttl, &canon));
+ tmpbuf6len, &rc6, &herrno, &ttl,
+ &canon));
if (rc6 != ERANGE || herrno != NETDB_INTERNAL)
break;
tmpbuf6 = extend_alloca (tmpbuf6, tmpbuf6len, 2 * tmpbuf6len);
@@ -173,231 +266,226 @@
if (rc4 != 0 && herrno == NETDB_INTERNAL)
goto out;
- if (status[0] == NSS_STATUS_SUCCESS
- || status[1] == NSS_STATUS_SUCCESS)
- {
- /* We found the data. Count the addresses and the size. */
- int naddrs = 0;
- size_t addrslen = 0;
- for (int j = 0; j < 2; ++j)
- if (status[j] == NSS_STATUS_SUCCESS)
- for (int i = 0; th[j].h_addr_list[i] != NULL; ++i)
+ if (status[0] != NSS_STATUS_SUCCESS
+ && status[1] != NSS_STATUS_SUCCESS)
+ goto next_nip;
+
+ /* We found the data. Count the addresses and the size. */
+ for (int j = 0; j < 2; ++j)
+ if (status[j] == NSS_STATUS_SUCCESS)
+ for (int i = 0; th[j].h_addr_list[i] != NULL; ++i)
+ {
+ ++naddrs;
+ addrslen += th[j].h_length;
+ }
+
+ if (canon == NULL)
+ {
+ /* Determine the canonical name. */
+ nss_getcanonname_r cfct;
+ cfct = __nss_lookup_function (nip, "getcanonname_r");
+ if (cfct != NULL)
+ {
+ const size_t max_fqdn_len = 256;
+ char *buf = alloca (max_fqdn_len);
+ char *s;
+ int rc;
+
+ if (DL_CALL_FCT (cfct, (key, buf, max_fqdn_len, &s,
+ &rc, &herrno))
+ == NSS_STATUS_SUCCESS)
+ canon = s;
+ else
+ /* Set to name now to avoid using gethostbyaddr. */
+ canon = key;
+ }
+ else
+ {
+ struct hostent *he = NULL;
+ int herrno;
+ struct hostent he_mem;
+ void *addr;
+ size_t addrlen;
+ int addrfamily;
+
+ if (status[1] == NSS_STATUS_SUCCESS)
{
- ++naddrs;
- addrslen += th[j].h_length;
- }
-
- if (canon == NULL)
- {
- /* Determine the canonical name. */
- nss_getcanonname_r cfct;
- cfct = __nss_lookup_function (nip, "getcanonname_r");
- if (cfct != NULL)
- {
- const size_t max_fqdn_len = 256;
- char *buf = alloca (max_fqdn_len);
- char *s;
- int rc;
-
- if (DL_CALL_FCT (cfct, (key, buf, max_fqdn_len, &s, &rc,
- &herrno)) == NSS_STATUS_SUCCESS)
- canon = s;
- else
- /* Set to name now to avoid using gethostbyaddr. */
- canon = key;
+ addr = th[1].h_addr_list[0];
+ addrlen = sizeof (struct in_addr);
+ addrfamily = AF_INET;
}
else
{
- struct hostent *he = NULL;
- int herrno;
- struct hostent he_mem;
- void *addr;
- size_t addrlen;
- int addrfamily;
-
- if (status[1] == NSS_STATUS_SUCCESS)
- {
- addr = th[1].h_addr_list[0];
- addrlen = sizeof (struct in_addr);
- addrfamily = AF_INET;
- }
+ addr = th[0].h_addr_list[0];
+ addrlen = sizeof (struct in6_addr);
+ addrfamily = AF_INET6;
+ }
+
+ size_t tmpbuflen = 512;
+ char *tmpbuf = alloca (tmpbuflen);
+ int rc;
+ while (1)
+ {
+ rc = __gethostbyaddr2_r (addr, addrlen, addrfamily,
+ &he_mem, tmpbuf, tmpbuflen,
+ &he, &herrno, NULL);
+ if (rc != ERANGE || herrno != NETDB_INTERNAL)
+ break;
+ tmpbuf = extend_alloca (tmpbuf, tmpbuflen,
+ tmpbuflen * 2);
+ }
+
+ if (rc == 0)
+ {
+ if (he != NULL)
+ canon = he->h_name;
else
- {
- addr = th[0].h_addr_list[0];
- addrlen = sizeof (struct in6_addr);
- addrfamily = AF_INET6;
- }
-
- size_t tmpbuflen = 512;
- char *tmpbuf = alloca (tmpbuflen);
- int rc;
- while (1)
- {
- rc = __gethostbyaddr2_r (addr, addrlen, addrfamily,
- &he_mem, tmpbuf, tmpbuflen,
- &he, &herrno, NULL);
- if (rc != ERANGE || herrno != NETDB_INTERNAL)
- break;
- tmpbuf = extend_alloca (tmpbuf, tmpbuflen,
- tmpbuflen * 2);
- }
-
- if (rc == 0)
- {
- if (he != NULL)
- canon = he->h_name;
- else
- canon = key;
- }
+ canon = key;
}
}
- size_t canonlen = canon == NULL ? 0 : (strlen (canon) + 1);
-
- total = sizeof (*dataset) + naddrs + addrslen + canonlen;
-
- /* Now we can allocate the data structure. If the TTL
- of the entry is reported as zero do not cache the
- entry at all. */
- if (ttl != 0 && he == NULL)
+ }
+
+ canonlen = canon == NULL ? 0 : (strlen (canon) + 1);
+
+ total = sizeof (*dataset) + naddrs + addrslen + canonlen;
+
+
+ /* Now we can allocate the data structure. If the TTL of the
+ entry is reported as zero do not cache the entry at all. */
+ if (ttl != 0 && he == NULL)
+ {
+ dataset = (struct dataset *) mempool_alloc (db, total
+ + req->key_len,
+ IDX_result_data);
+ if (dataset == NULL)
+ ++db->head->addfailed;
+ }
+
+ if (dataset == NULL)
+ {
+ /* We cannot permanently add the result in the moment. But
+ we can provide the result as is. Store the data in some
+ temporary memory. */
+ dataset = (struct dataset *) alloca (total + req->key_len);
+
+ /* We cannot add this record to the permanent database. */
+ alloca_used = true;
+ }
+
+ /* Fill in the address and address families. */
+ char *addrs = (char *) (&dataset->resp + 1);
+ uint8_t *family = (uint8_t *) (addrs + addrslen);
+
+ for (int j = 0; j < 2; ++j)
+ if (status[j] == NSS_STATUS_SUCCESS)
+ for (int i = 0; th[j].h_addr_list[i] != NULL; ++i)
{
- dataset = (struct dataset *) mempool_alloc (db,
- total
- + req->key_len,
- IDX_result_data);
- if (dataset == NULL)
- ++db->head->addfailed;
+ addrs = mempcpy (addrs, th[j].h_addr_list[i],
+ th[j].h_length);
+ *family++ = th[j].h_addrtype;
}
- if (dataset == NULL)
+ cp = family;
+ }
+
+ /* Fill in the rest of the dataset. */
+ dataset->head.allocsize = total + req->key_len;
+ dataset->head.recsize = total - offsetof (struct dataset, resp);
+ dataset->head.notfound = false;
+ dataset->head.nreloads = he == NULL ? 0 : (dh->nreloads + 1);
+ dataset->head.usable = true;
+
+ /* Compute the timeout time. */
+ dataset->head.timeout = time (NULL) + (ttl == INT32_MAX
+ ? db->postimeout : ttl);
+
+ dataset->resp.version = NSCD_VERSION;
+ dataset->resp.found = 1;
+ dataset->resp.naddrs = naddrs;
+ dataset->resp.addrslen = addrslen;
+ dataset->resp.canonlen = canonlen;
+ dataset->resp.error = NETDB_SUCCESS;
+
+ if (canon != NULL)
+ cp = mempcpy (cp, canon, canonlen);
+
+ key_copy = memcpy (cp, key, req->key_len);
+
+ /* Now we can determine whether on refill we have to create a
+ new record or not. */
+ if (he != NULL)
+ {
+ assert (fd == -1);
+
+ if (total + req->key_len == dh->allocsize
+ && total - offsetof (struct dataset, resp) == dh->recsize
+ && memcmp (&dataset->resp, dh->data,
+ dh->allocsize - offsetof (struct dataset,
+ resp)) == 0)
+ {
+ /* The data has not changed. We will just bump the
+ timeout value. Note that the new record has been
+ allocated on the stack and need not be freed. */
+ dh->timeout = dataset->head.timeout;
+ ++dh->nreloads;
+ }
+ else
+ {
+ /* We have to create a new record. Just allocate
+ appropriate memory and copy it. */
+ struct dataset *newp
+ = (struct dataset *) mempool_alloc (db, total + req->key_len,
+ IDX_result_data);
+ if (__builtin_expect (newp != NULL, 1))
{
- /* We cannot permanently add the result in the moment. But
- we can provide the result as is. Store the data in some
- temporary memory. */
- dataset = (struct dataset *) alloca (total + req->key_len);
-
- /* We cannot add this record to the permanent database. */
- alloca_used = true;
- }
-
- dataset->head.allocsize = total + req->key_len;
- dataset->head.recsize = total - offsetof (struct dataset, resp);
- dataset->head.notfound = false;
- dataset->head.nreloads = he == NULL ? 0 : (dh->nreloads + 1);
- dataset->head.usable = true;
-
- /* Compute the timeout time. */
- dataset->head.timeout = time (NULL) + (ttl == INT32_MAX
- ? db->postimeout : ttl);
-
- dataset->resp.version = NSCD_VERSION;
- dataset->resp.found = 1;
- dataset->resp.naddrs = naddrs;
- dataset->resp.addrslen = addrslen;
- dataset->resp.canonlen = canonlen;
- dataset->resp.error = NETDB_SUCCESS;
-
- char *addrs = (char *) (&dataset->resp + 1);
- uint8_t *family = (uint8_t *) (addrs + addrslen);
-
- for (int j = 0; j < 2; ++j)
- if (status[j] == NSS_STATUS_SUCCESS)
- for (int i = 0; th[j].h_addr_list[i] != NULL; ++i)
- {
- addrs = mempcpy (addrs, th[j].h_addr_list[i],
- th[j].h_length);
- *family++ = th[j].h_addrtype;
- }
-
- void *cp = family;
- if (canon != NULL)
- cp = mempcpy (cp, canon, canonlen);
-
- key_copy = memcpy (cp, key, req->key_len);
-
- /* Now we can determine whether on refill we have to
- create a new record or not. */
- if (he != NULL)
- {
- assert (fd == -1);
-
- if (total + req->key_len == dh->allocsize
- && total - offsetof (struct dataset, resp) == dh->recsize
- && memcmp (&dataset->resp, dh->data,
- dh->allocsize
- - offsetof (struct dataset, resp)) == 0)
- {
- /* The data has not changed. We will just bump the
- timeout value. Note that the new record has been
- allocated on the stack and need not be freed. */
- dh->timeout = dataset->head.timeout;
- ++dh->nreloads;
- }
- else
- {
- /* We have to create a new record. Just allocate
- appropriate memory and copy it. */
- struct dataset *newp
- = (struct dataset *) mempool_alloc (db,
- total
- + req->key_len,
- IDX_result_data);
- if (__builtin_expect (newp != NULL, 1))
- {
- /* Adjust pointer into the memory block. */
- key_copy = (char *) newp + (key_copy
- - (char *) dataset);
-
- dataset = memcpy (newp, dataset,
- total + req->key_len);
- alloca_used = false;
- }
- else
- ++db->head->addfailed;
-
- /* Mark the old record as obsolete. */
- dh->usable = false;
- }
+ /* Adjust pointer into the memory block. */
+ key_copy = (char *) newp + (key_copy - (char *) dataset);
+
+ dataset = memcpy (newp, dataset, total + req->key_len);
+ alloca_used = false;
}
else
- {
- /* We write the dataset before inserting it to the
- database since while inserting this thread might
- block and so would unnecessarily let the receiver
- wait. */
- assert (fd != -1);
+ ++db->head->addfailed;
+
+ /* Mark the old record as obsolete. */
+ dh->usable = false;
+ }
+ }
+ else
+ {
+ /* We write the dataset before inserting it to the database
+ since while inserting this thread might block and so
+ would unnecessarily let the receiver wait. */
+ assert (fd != -1);
#ifdef HAVE_SENDFILE
- if (__builtin_expect (db->mmap_used, 1) && !alloca_used)
- {
- assert (db->wr_fd != -1);
- assert ((char *) &dataset->resp > (char *) db->data);
- assert ((char *) &dataset->resp - (char *) db->head
- + total
- <= (sizeof (struct database_pers_head)
- + db->head->module * sizeof (ref_t)
- + db->head->data_size));
- ssize_t written;
- written = sendfileall (fd, db->wr_fd,
- (char *) &dataset->resp
- - (char *) db->head, total);
+ if (__builtin_expect (db->mmap_used, 1) && !alloca_used)
+ {
+ assert (db->wr_fd != -1);
+ assert ((char *) &dataset->resp > (char *) db->data);
+ assert ((char *) &dataset->resp - (char *) db->head + total
+ <= (sizeof (struct database_pers_head)
+ + db->head->module * sizeof (ref_t)
+ + db->head->data_size));
+ ssize_t written;
+ written = sendfileall (fd, db->wr_fd, (char *) &dataset->resp
+ - (char *) db->head, total);
# ifndef __ASSUME_SENDFILE
- if (written == -1 && errno == ENOSYS)
- goto use_write;
+ if (written == -1 && errno == ENOSYS)
+ goto use_write;
# endif
- }
- else
+ }
+ else
# ifndef __ASSUME_SENDFILE
- use_write:
+ use_write:
# endif
#endif
- writeall (fd, &dataset->resp, total);
- }
-
- goto out;
- }
-
+ writeall (fd, &dataset->resp, total);
}
+ goto out;
+
+next_nip:
if (nss_next_action (nip, status[1]) == NSS_ACTION_RETURN)
break;
@@ -468,10 +556,8 @@
/* Now get the lock to safely insert the records. */
pthread_rwlock_rdlock (&db->lock);
- if (cache_add (req->type, key_copy, req->key_len, &dataset->head, true,
- db, uid) < 0)
- /* Ensure the data can be recovered. */
- dataset->head.usable = false;
+ (void) cache_add (req->type, key_copy, req->key_len, &dataset->head,
+ true, db, uid);
pthread_rwlock_unlock (&db->lock);
Modified: fsf/trunk/libc/nscd/cache.c
==============================================================================
--- fsf/trunk/libc/nscd/cache.c (original)
+++ fsf/trunk/libc/nscd/cache.c Sun May 11 00:06:32 2008
@@ -161,6 +161,11 @@
{
++table->head->addfailed;
+ /* If necessary mark the entry as unusable so that lookups will
+ not use it. */
+ if (first)
+ packet->usable = false;
+
/* Mark the in-flight memory as unused. */
for (enum in_flight idx = 0; idx < IDX_record_data; ++idx)
mem_in_flight.block[idx].dbidx = -1;
Modified: fsf/trunk/libc/nscd/grpcache.c
==============================================================================
--- fsf/trunk/libc/nscd/grpcache.c (original)
+++ fsf/trunk/libc/nscd/grpcache.c Sun May 11 00:06:32 2008
@@ -146,10 +146,8 @@
/* Now get the lock to safely insert the records. */
pthread_rwlock_rdlock (&db->lock);
- if (cache_add (req->type, &dataset->strdata, req->key_len,
- &dataset->head, true, db, owner) < 0)
- /* Ensure the data can be recovered. */
- dataset->head.usable = false;
+ (void) cache_add (req->type, &dataset->strdata, req->key_len,
+ &dataset->head, true, db, owner);
pthread_rwlock_unlock (&db->lock);
@@ -356,12 +354,7 @@
{
if (cache_add (GETGRBYGID, cp, key_offset, &dataset->head, true,
db, owner) < 0)
- {
- /* Could not allocate memory. Make sure the data gets
- discarded. */
- dataset->head.usable = false;
- goto out;
- }
+ goto out;
first = false;
}
@@ -370,12 +363,7 @@
{
if (cache_add (GETGRBYNAME, key_copy, key_len + 1,
&dataset->head, true, db, owner) < 0)
- {
- /* Could not allocate memory. Make sure the data gets
- discarded. */
- dataset->head.usable = false;
- goto out;
- }
+ goto out;
first = false;
}
@@ -389,12 +377,8 @@
{
if (req->type == GETGRBYNAME && db->propagate)
(void) cache_add (GETGRBYGID, cp, key_offset, &dataset->head,
- req->type != GETGRBYNAME, db, owner);
- }
- else if (first)
- /* Could not allocate memory. Make sure the data gets
- discarded. */
- dataset->head.usable = false;
+ false, db, owner);
+ }
out:
pthread_rwlock_unlock (&db->lock);
Modified: fsf/trunk/libc/nscd/hstcache.c
==============================================================================
--- fsf/trunk/libc/nscd/hstcache.c (original)
+++ fsf/trunk/libc/nscd/hstcache.c Sun May 11 00:06:32 2008
@@ -155,10 +155,8 @@
/* Now get the lock to safely insert the records. */
pthread_rwlock_rdlock (&db->lock);
- if (cache_add (req->type, &dataset->strdata, req->key_len,
- &dataset->head, true, db, owner) < 0)
- /* Ensure the data can be recovered. */
- dataset->head.usable = false;
+ (void) cache_add (req->type, &dataset->strdata, req->key_len,
+ &dataset->head, true, db, owner);
pthread_rwlock_unlock (&db->lock);
@@ -409,11 +407,8 @@
|| req->type == GETHOSTBYADDR
|| req->type == GETHOSTBYADDRv6);
- if (cache_add (req->type, key_copy, req->key_len,
- &dataset->head, true, db, owner) < 0)
- /* Could not allocate memory. Make sure the
- data gets discarded. */
- dataset->head.usable = false;
+ (void) cache_add (req->type, key_copy, req->key_len,
+ &dataset->head, true, db, owner);
pthread_rwlock_unlock (&db->lock);
}
Modified: fsf/trunk/libc/nscd/initgrcache.c
==============================================================================
--- fsf/trunk/libc/nscd/initgrcache.c (original)
+++ fsf/trunk/libc/nscd/initgrcache.c Sun May 11 00:06:32 2008
@@ -230,10 +230,8 @@
/* Now get the lock to safely insert the records. */
pthread_rwlock_rdlock (&db->lock);
- if (cache_add (req->type, key_copy, req->key_len,
- &dataset->head, true, db, uid) < 0)
- /* Ensure the data can be recovered. */
- dataset->head.usable = false;
+ (void) cache_add (req->type, key_copy, req->key_len,
+ &dataset->head, true, db, uid);
pthread_rwlock_unlock (&db->lock);
@@ -399,11 +397,8 @@
/* Now get the lock to safely insert the records. */
pthread_rwlock_rdlock (&db->lock);
- if (cache_add (INITGROUPS, cp, req->key_len, &dataset->head, true,
- db, uid) < 0)
- /* Could not allocate memory. Make sure the data gets
- discarded. */
- dataset->head.usable = false;
+ (void) cache_add (INITGROUPS, cp, req->key_len, &dataset->head, true,
+ db, uid);
pthread_rwlock_unlock (&db->lock);
}
Modified: fsf/trunk/libc/nscd/pwdcache.c
==============================================================================
--- fsf/trunk/libc/nscd/pwdcache.c (original)
+++ fsf/trunk/libc/nscd/pwdcache.c Sun May 11 00:06:32 2008
@@ -153,11 +153,8 @@
/* Now get the lock to safely insert the records. */
pthread_rwlock_rdlock (&db->lock);
- if (cache_add (req->type, key_copy, req->key_len,
- &dataset->head, true, db, owner) < 0)
- /* Ensure the data can be recovered. */
- dataset->head.usable = false;
-
+ (void) cache_add (req->type, key_copy, req->key_len,
+ &dataset->head, true, db, owner);
pthread_rwlock_unlock (&db->lock);
@@ -352,12 +349,7 @@
{
if (cache_add (GETPWBYUID, cp, key_offset, &dataset->head, true,
db, owner) < 0)
- {
- /* Could not allocate memory. Make sure the data gets
- discarded. */
- dataset->head.usable = false;
- goto out;
- }
+ goto out;
first = false;
}
@@ -366,12 +358,7 @@
{
if (cache_add (GETPWBYNAME, key_copy, key_len + 1,
&dataset->head, true, db, owner) < 0)
- {
- /* Could not allocate memory. Make sure the data gets
- discarded. */
- dataset->head.usable = false;
- goto out;
- }
+ goto out;
first = false;
}
@@ -384,12 +371,8 @@
{
if (req->type == GETPWBYNAME && db->propagate)
(void) cache_add (GETPWBYUID, cp, key_offset, &dataset->head,
- req->type != GETPWBYNAME, db, owner);
- }
- else if (first)
- /* Could not allocate memory. Make sure the data gets
- discarded. */
- dataset->head.usable = false;
+ false, db, owner);
+ }
out:
pthread_rwlock_unlock (&db->lock);
Modified: fsf/trunk/libc/nscd/servicescache.c
==============================================================================
--- fsf/trunk/libc/nscd/servicescache.c (original)
+++ fsf/trunk/libc/nscd/servicescache.c Sun May 11 00:06:32 2008
@@ -136,10 +136,8 @@
/* Now get the lock to safely insert the records. */
pthread_rwlock_rdlock (&db->lock);
- if (cache_add (req->type, &dataset->strdata, req->key_len,
- &dataset->head, true, db, owner) < 0)
- /* Ensure the data can be recovered. */
- dataset->head.usable = false;
+ (void) cache_add (req->type, &dataset->strdata, req->key_len,
+ &dataset->head, true, db, owner);
pthread_rwlock_unlock (&db->lock);
@@ -332,11 +330,8 @@
/* Now get the lock to safely insert the records. */
pthread_rwlock_rdlock (&db->lock);
- if (cache_add (req->type, key_copy, req->key_len,
- &dataset->head, true, db, owner) < 0)
- /* Could not allocate memory. Make sure the
- data gets discarded. */
- dataset->head.usable = false;
+ (void) cache_add (req->type, key_copy, req->key_len,
+ &dataset->head, true, db, owner);
pthread_rwlock_unlock (&db->lock);
}
Modified: fsf/trunk/libc/nss/Versions
==============================================================================
--- fsf/trunk/libc/nss/Versions (original)
+++ fsf/trunk/libc/nss/Versions Sun May 11 00:06:32 2008
@@ -38,6 +38,7 @@
_nss_files_endhostent;
_nss_files_gethostbyaddr_r;
_nss_files_gethostbyname2_r;
+ _nss_files_gethostbyname4_r;
_nss_files_gethostbyname_r;
_nss_files_gethostent_r;
_nss_files_gethostton_r;
Modified: fsf/trunk/libc/nss/nss.h
==============================================================================
--- fsf/trunk/libc/nss/nss.h (original)
+++ fsf/trunk/libc/nss/nss.h Sun May 11 00:06:32 2008
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 1999, 2008 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -23,6 +23,7 @@
#define _NSS_H 1
#include <features.h>
+#include <stdint.h>
__BEGIN_DECLS
@@ -38,6 +39,17 @@
};
+/* Data structure used for the 'gethostbyname4_r' function. */
+struct gaih_addrtuple
+ {
+ struct gaih_addrtuple *next;
+ char *name;
+ int family;
+ uint32_t addr[4];
+ uint32_t scopeid;
+ };
+
+
/* Overwrite service selection for database DBNAME using specification
in STRING.
This function should only be used by system programs which have to
Modified: fsf/trunk/libc/nss/nss_files/files-hosts.c
==============================================================================
--- fsf/trunk/libc/nss/nss_files/files-hosts.c (original)
+++ fsf/trunk/libc/nss/nss_files/files-hosts.c Sun May 11 00:06:32 2008
@@ -1,6 +1,5 @@
/* Hosts file parser in nss_files module.
- Copyright (C) 1996-2001, 2003, 2004, 2006, 2007
- Free Software Foundation, Inc.
+ Copyright (C) 1996-2001, 2003-2007, 2008 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -56,7 +55,10 @@
STRING_FIELD (addr, isspace, 1);
/* Parse address. */
- if (inet_pton (af, addr, entdata->host_addr) <= 0)
+ if (inet_pton (af == AF_UNSPEC ? AF_INET : af, addr, entdata->host_addr)
+ > 0)
+ af = af == AF_UNSPEC ? AF_INET : af;
+ else
{
if (af == AF_INET6 && (flags & AI_V4MAPPED) != 0
&& inet_pton (AF_INET, addr, entdata->host_addr) > 0)
@@ -76,6 +78,9 @@
/* Illegal address: ignore line. */
return 0;
}
+ else if (af == AF_UNSPEC
+ && inet_pton (AF_INET6, addr, entdata->host_addr) > 0)
+ af = AF_INET6;
else
/* Illegal address: ignore line. */
return 0;
@@ -101,8 +106,6 @@
struct STRUCTURE *result, char *buffer, \
size_t buflen, int *errnop H_ERRNO_PROTO) \
{ \
- enum nss_status status; \
- \
uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct hostent_data); \
buffer += pad; \
buflen = buflen > pad ? buflen - pad : 0; \
@@ -110,7 +113,7 @@
__libc_lock_lock (lock); \
\
/* Reset file pointer to beginning or open file. */ \
- status = internal_setent (keep_stream); \
+ enum nss_status status = internal_setent (keep_stream); \
\
if (status == NSS_STATUS_SUCCESS) \
{ \
@@ -288,9 +291,9 @@
{
LOOKUP_NAME_CASE (h_name, h_aliases)
}, const char *name)
-
-
#undef EXTRA_ARGS_VALUE
+
+
/* XXX Is using _res to determine whether we want to convert IPv4 addresses
to IPv6 addresses really the right thing to do? */
#define EXTRA_ARGS_VALUE \
@@ -299,8 +302,9 @@
{
LOOKUP_NAME_CASE (h_name, h_aliases)
}, const char *name, int af)
-
#undef EXTRA_ARGS_VALUE
+
+
/* We only need to consider IPv4 mapped addresses if the input to the
gethostbyaddr() function is an IPv6 address. */
#define EXTRA_ARGS_VALUE \
@@ -311,3 +315,116 @@
&& ! memcmp (addr, result->h_addr_list[0], len))
break;
}, const void *addr, socklen_t len, int af)
+#undef EXTRA_ARGS_VALUE
+
+
+enum nss_status
+_nss_files_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
+ char *buffer, size_t buflen, int *errnop,
+ int *herrnop, int32_t *ttlp)
+{
+ __libc_lock_lock (lock);
+
+ /* Reset file pointer to beginning or open file. */
+ enum nss_status status = internal_setent (keep_stream);
+
+ if (status == NSS_STATUS_SUCCESS)
+ {
+ /* Tell getent function that we have repositioned the file pointer. */
+ last_use = getby;
+
+ bool any = false;
+ bool got_canon = false;
+ while (1)
+ {
+ /* Align the buffer for the next record. */
+ uintptr_t pad = (-(uintptr_t) buffer
+ % __alignof__ (struct hostent_data));
+ buffer += pad;
+ buflen = buflen > pad ? buflen - pad : 0;
+
+ struct hostent result;
+ status = internal_getent (&result, buffer, buflen, errnop
+ H_ERRNO_ARG, AF_UNSPEC, 0);
+ if (status != NSS_STATUS_SUCCESS)
+ break;
+
+ int naliases = 0;
+ if (__strcasecmp (name, result.h_name) != 0)
+ {
+ for (; result.h_aliases[naliases] != NULL; ++naliases)
+ if (! __strcasecmp (name, result.h_aliases[naliases]))
+ break;
+ if (result.h_aliases[naliases] == NULL)
+ continue;
+
+ /* We know this alias exist. Count it. */
+ ++naliases;
+ }
+
+ /* Determine how much memory has been used so far. */
+ // XXX It is not necessary to preserve the aliases array
+ while (result.h_aliases[naliases] != NULL)
+ ++naliases;
+ char *bufferend = (char *) &result.h_aliases[naliases + 1];
+ assert (buflen >= bufferend - buffer);
+ buflen -= bufferend - buffer;
+ buffer = bufferend;
+
+ /* We found something. */
+ any = true;
+
+ /* Create the record the caller expects. There is only one
+ address. */
+ assert (result.h_addr_list[1] == NULL);
+ if (*pat == NULL)
+ {
+ uintptr_t pad = (-(uintptr_t) buffer
+ % __alignof__ (struct gaih_addrtuple));
+ buffer += pad;
+ buflen = buflen > pad ? buflen - pad : 0;
+
+ if (__builtin_expect (buflen < sizeof (struct gaih_addrtuple),
+ 0))
+ {
+ *errnop = ERANGE;
+ *herrnop = NETDB_INTERNAL;
+ status = NSS_STATUS_TRYAGAIN;
+ break;
+ }
+
+ *pat = (struct gaih_addrtuple *) buffer;
+ buffer += sizeof (struct gaih_addrtuple);
+ buflen -= sizeof (struct gaih_addrtuple);
+ }
+
+ (*pat)->next = NULL;
+ (*pat)->name = got_canon ? NULL : result.h_name;
+ got_canon = true;
+ (*pat)->family = result.h_addrtype;
+ memcpy ((*pat)->addr, result.h_addr_list[0], result.h_length);
+ (*pat)->scopeid = 0;
+
+ pat = &((*pat)->next);
+
+ /* If we only look for the first matching entry we are done. */
+ if ((_res_hconf.flags & HCONF_FLAG_MULTI) == 0)
+ break;
+ }
+
+ /* If we have to look for multiple records and found one, this
+ is a success. */
+ if (status == NSS_STATUS_NOTFOUND && any)
+ {
+ assert ((_res_hconf.flags & HCONF_FLAG_MULTI) != 0);
+ status = NSS_STATUS_SUCCESS;
+ }
+
+ if (! keep_stream)
+ internal_endent ();
+ }
+
+ __libc_lock_unlock (lock);
+
+ return status;
+}
Modified: fsf/trunk/libc/resolv/Versions
==============================================================================
--- fsf/trunk/libc/resolv/Versions (original)
+++ fsf/trunk/libc/resolv/Versions Sun May 11 00:06:32 2008
@@ -89,6 +89,7 @@
_nss_dns_gethostbyname_r; _nss_dns_getnetbyaddr_r;
_nss_dns_getnetbyname_r; _nss_dns_getcanonname_r;
_nss_dns_gethostbyaddr2_r;
+ _nss_dns_gethostbyname4_r;
}
}
Modified: fsf/trunk/libc/resolv/gethnamaddr.c
==============================================================================
--- fsf/trunk/libc/resolv/gethnamaddr.c (original)
+++ fsf/trunk/libc/resolv/gethnamaddr.c Sun May 11 00:06:32 2008
@@ -621,7 +621,7 @@
buf.buf = origbuf = (querybuf *) alloca (1024);
if ((n = __libc_res_nsearch(&_res, name, C_IN, type, buf.buf->buf, 1024,
- &buf.ptr)) < 0) {
+ &buf.ptr, NULL, NULL)) < 0) {
if (buf.buf != origbuf)
free (buf.buf);
Dprintf("res_nsearch failed (%d)\n", n);
@@ -716,12 +716,12 @@
buf.buf = orig_buf = (querybuf *) alloca (1024);
n = __libc_res_nquery(&_res, qbuf, C_IN, T_PTR, buf.buf->buf, 1024,
- &buf.ptr);
+ &buf.ptr, NULL, NULL);
if (n < 0 && af == AF_INET6 && (_res.options & RES_NOIP6DOTINT) == 0) {
strcpy(qp, "ip6.int");
n = __libc_res_nquery(&_res, qbuf, C_IN, T_PTR, buf.buf->buf,
buf.buf != orig_buf ? MAXPACKET : 1024,
- &buf.ptr);
+ &buf.ptr, NULL, NULL);
}
if (n < 0) {
if (buf.buf != orig_buf)
Modified: fsf/trunk/libc/resolv/nss_dns/dns-canon.c
==============================================================================
--- fsf/trunk/libc/resolv/nss_dns/dns-canon.c (original)
+++ fsf/trunk/libc/resolv/nss_dns/dns-canon.c Sun May 11 00:06:32 2008
@@ -1,4 +1,4 @@
-/* Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 2004, 2006, 2008 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@xxxxxxxxxx>, 2004.
@@ -61,7 +61,7 @@
for (int i = 0; i < nqtypes; ++i)
{
int r = __libc_res_nquery (&_res, name, ns_c_in, qtypes[i],
- buf, sizeof (buf), &ansp.ptr);
+ buf, sizeof (buf), &ansp.ptr, NULL, NULL);
if (r > 0)
{
/* We need to decode the response. Just one question record.
Modified: fsf/trunk/libc/resolv/nss_dns/dns-host.c
==============================================================================
--- fsf/trunk/libc/resolv/nss_dns/dns-host.c (original)
+++ fsf/trunk/libc/resolv/nss_dns/dns-host.c Sun May 11 00:06:32 2008
@@ -71,6 +71,7 @@
* --Copyright--
*/
+#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <netdb.h>
@@ -126,6 +127,14 @@
struct hostent *result, char *buffer,
size_t buflen, int *errnop, int *h_errnop,
int map, int32_t *ttlp, char **canonp);
+
+static enum nss_status gaih_getanswer (const querybuf *answer1, int anslen1,
+ const querybuf *answer2, int anslen2,
+ const char *qname,
+ struct gaih_addrtuple **pat,
+ char *buffer, size_t buflen,
+ int *errnop, int *h_errnop,
+ int32_t *ttlp);
extern enum nss_status _nss_dns_gethostbyname3_r (const char *name, int af,
struct hostent *result,
@@ -186,11 +195,11 @@
host_buffer.buf = orig_host_buffer = (querybuf *) alloca (1024);
n = __libc_res_nsearch (&_res, name, C_IN, type, host_buffer.buf->buf,
- 1024, &host_buffer.ptr);
+ 1024, &host_buffer.ptr, NULL, NULL);
if (n < 0)
{
- enum nss_status status = (errno == ECONNREFUSED
- ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND);
+ status = (errno == ECONNREFUSED
+ ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND);
*h_errnop = h_errno;
if (h_errno == TRY_AGAIN)
*errnop = EAGAIN;
@@ -203,7 +212,8 @@
if (af == AF_INET6 && (_res.options & RES_USE_INET6))
n = __libc_res_nsearch (&_res, name, C_IN, T_A, host_buffer.buf->buf,
host_buffer.buf != orig_host_buffer
- ? MAXPACKET : 1024, &host_buffer.ptr);
+ ? MAXPACKET : 1024, &host_buffer.ptr,
+ NULL, NULL);
if (n < 0)
{
@@ -250,6 +260,70 @@
if (status == NSS_STATUS_NOTFOUND)
status = _nss_dns_gethostbyname3_r (name, AF_INET, result, buffer,
buflen, errnop, h_errnop, NULL, NULL);
+
+ return status;
+}
+
+
+enum nss_status
+_nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
+ char *buffer, size_t buflen, int *errnop,
+ int *herrnop, int32_t *ttlp)
+{
+ if (__res_maybe_init (&_res, 0) == -1)
+ return NSS_STATUS_UNAVAIL;
+
+ char tmp[NS_MAXDNAME];
+
+ /*
+ * if there aren't any dots, it could be a user-level alias.
+ * this is also done in res_query() since we are not the only
+ * function that looks up host names.
+ */
+ if (strchr (name, '.') == NULL)
+ {
+ const char *cp = res_hostalias (&_res, name, tmp, sizeof (tmp));
+ if (cp != NULL)
+ name = cp;
+ }
+
+ union
+ {
+ querybuf *buf;
+ u_char *ptr;
+ } host_buffer;
+ querybuf *orig_host_buffer;
+ host_buffer.buf = orig_host_buffer = (querybuf *) alloca (2048);
+ u_char *ans2p = NULL;
+ int nans2p = 0;
+
+ int olderr = errno;
+ enum nss_status status;
+ int n = __libc_res_nsearch (&_res, name, C_IN, T_UNSPEC,
+ host_buffer.buf->buf, 2048, &host_buffer.ptr,
+ &ans2p, &nans2p);
+ if (n < 0)
+ {
+ status = (errno == ECONNREFUSED
+ ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND);
+ *herrnop = h_errno;
+ if (h_errno == TRY_AGAIN)
+ *errnop = EAGAIN;
+ else
+ __set_errno (olderr);
+
+ if (host_buffer.buf != orig_host_buffer)
+ free (host_buffer.buf);
+
+ return status;
+ }
+
+ status = gaih_getanswer(host_buffer.buf, n, (const querybuf *) ans2p,
+ nans2p, name, pat, buffer, buflen,
+ errnop, herrnop, ttlp);
+
+ if (host_buffer.buf != orig_host_buffer)
+ free (host_buffer.buf);
return status;
}
@@ -342,7 +416,8 @@
qp += sprintf (qp, "%02hhx", uaddr[n]);
strcpy (qp, "].ip6.arpa");
n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR,
- host_buffer.buf->buf, 1024, &host_buffer.ptr);
+ host_buffer.buf->buf, 1024, &host_buffer.ptr,
+ NULL, NULL);
if (n >= 0)
goto got_it_already;
}
@@ -363,13 +438,14 @@
}
n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, host_buffer.buf->buf,
- 1024, &host_buffer.ptr);
+ 1024, &host_buffer.ptr, NULL, NULL);
if (n < 0 && af == AF_INET6 && (_res.options & RES_NOIP6DOTINT) == 0)
{
strcpy (qp, "ip6.int");
n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, host_buffer.buf->buf,
host_buffer.buf != orig_host_buffer
- ? MAXPACKET : 1024, &host_buffer.ptr);
+ ? MAXPACKET : 1024, &host_buffer.ptr,
+ NULL, NULL);
}
if (n < 0)
{
@@ -555,7 +631,8 @@
if (n > 0 && bp[0] == '.')
bp[0] = '\0';
- if (n < 0 || (*name_ok) (bp) == 0)
+ if (__builtin_expect (n < 0 || ((*name_ok) (bp) == 0 && (errno = EBADMSG)),
+ 0))
{
*errnop = errno;
*h_errnop = NO_RECOVERY;
@@ -629,7 +706,7 @@
continue; /* XXX - had_error++ ? */
}
- if ((qtype ==T_A || qtype == T_AAAA) && type == T_CNAME)
+ if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME)
{
if (ap >= &host_data->aliases[MAX_NR_ALIASES - 1])
continue;
@@ -857,3 +934,245 @@
return ((qtype == T_A || qtype == T_AAAA) && ap != host_data->aliases
? NSS_STATUS_NOTFOUND : NSS_STATUS_TRYAGAIN);
}
+
+
+static enum nss_status
+gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
+ struct gaih_addrtuple ***patp,
+ char **bufferp, size_t *buflenp,
+ int *errnop, int *h_errnop, int32_t *ttlp, int *firstp)
+{
+ char *buffer = *bufferp;
+ size_t buflen = *buflenp;
+
+ struct gaih_addrtuple **pat = *patp;
+ const HEADER *hp = &answer->hdr;
+ int ancount = ntohs (hp->ancount);
+ int qdcount = ntohs (hp->qdcount);
+ const u_char *cp = answer->buf + HFIXEDSZ;
+ const u_char *end_of_message = answer->buf + anslen;
+ if (__builtin_expect (qdcount != 1, 0))
+ {
+ *h_errnop = NO_RECOVERY;
+ return NSS_STATUS_UNAVAIL;
+ }
+
+ u_char packtmp[NS_MAXCDNAME];
+ int n = __ns_name_unpack (answer->buf, end_of_message, cp,
+ packtmp, sizeof packtmp);
+ /* We unpack the name to check it for validity. But we do not need
+ it later. */
+ if (n != -1 && __ns_name_ntop (packtmp, buffer, buflen) == -1)
+ {
+ if (__builtin_expect (errno, 0) == EMSGSIZE)
+ {
+ too_small:
+ *errnop = ERANGE;
+ *h_errnop = NETDB_INTERNAL;
+ return NSS_STATUS_TRYAGAIN;
+ }
+
+ n = -1;
+ }
+
+ if (__builtin_expect (n < 0 || (res_hnok (buffer) == 0
+ && (errno = EBADMSG)), 0))
+ {
+ *errnop = errno;
+ *h_errnop = NO_RECOVERY;
+ return NSS_STATUS_UNAVAIL;
+ }
+ cp += n + QFIXEDSZ;
+
+ int haveanswer = 0;
+ int had_error = 0;
+ char *canon = NULL;
+ char *h_name = NULL;
+ int h_namelen = 0;
+
+ while (ancount-- > 0 && cp < end_of_message && had_error == 0)
+ {
+ n = __ns_name_unpack (answer->buf, end_of_message, cp,
+ packtmp, sizeof packtmp);
+ if (n != -1 &&
+ (h_namelen = __ns_name_ntop (packtmp, buffer, buflen)) == -1)
+ {
+ if (__builtin_expect (errno, 0) == EMSGSIZE)
+ goto too_small;
+
+ n = -1;
+ }
+ if (n < 0 || res_hnok (buffer) == 0)
+ {
+ ++had_error;
+ continue;
+ }
+ if (*firstp)
+ {
+ h_name = buffer;
+ buffer += h_namelen;
+ buflen -= h_namelen;
+ }
+
+ cp += n; /* name */
+ int type = ns_get16 (cp);
+ cp += INT16SZ; /* type */
+ int class = ns_get16 (cp);
+ cp += INT16SZ; /* class */
+ int32_t ttl = ns_get32 (cp);
+ cp += INT32SZ; /* TTL */
+ n = ns_get16 (cp);
+ cp += INT16SZ; /* len */
+
+ if (class != C_IN)
+ {
+ cp += n;
+ continue;
+ }
+
+ if (type == T_CNAME)
+ {
+ char tbuf[MAXDNAME];
+ n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf);
+ if (n < 0 || res_hnok (tbuf) == 0)
+ {
+ ++had_error;
+ continue;
+ }
+ cp += n;
+
+ if (*firstp)
+ {
+ /* Reclaim buffer space. */
+ if (h_name + h_namelen == buffer)
+ {
+ buffer = h_name;
+ buflen += h_namelen;
+ }
+
+ n = strlen (tbuf) + 1;
+ if (__builtin_expect (n > buflen, 0))
+ goto too_small;
+ if (__builtin_expect (n >= MAXHOSTNAMELEN, 0))
+ {
+ ++had_error;
+ continue;
+ }
+
+ canon = buffer;
+ buffer = __mempcpy (buffer, tbuf, n);
+ buflen -= n;
+ h_namelen = 0;
+ }
+ continue;
+ }
+ if (__builtin_expect (type == T_SIG, 0)
+ || __builtin_expect (type == T_KEY, 0)
+ || __builtin_expect (type == T_NXT, 0)
+ || __builtin_expect (type == T_PTR, 0))
+ {
+ /* We don't support DNSSEC yet. For now, ignore the record
+ and send a low priority message to syslog.
+
+ We also don't expect T_PTR messages. */
+ syslog (LOG_DEBUG | LOG_AUTH,
+ "getaddrinfo*.gaih_getanswer: got type \"%s\"",
+ p_type (type));
+ cp += n;
+ continue;
+ }
+ if (type != T_A && type != T_AAAA)
+ abort ();
+
+ if (*pat == NULL)
+ {
+ uintptr_t pad = (-(uintptr_t) buffer
+ % __alignof__ (struct gaih_addrtuple));
+ buffer += pad;
+ buflen = buflen > pad ? buflen - pad : 0;
+
+ if (__builtin_expect (buflen < sizeof (struct gaih_addrtuple),
+ 0))
+ {
+ *errnop = ERANGE;
+ *h_errnop = NETDB_INTERNAL;
+ return NSS_STATUS_TRYAGAIN;
+ }
+
+ *pat = (struct gaih_addrtuple *) buffer;
+ buffer += sizeof (struct gaih_addrtuple);
+ buflen -= sizeof (struct gaih_addrtuple);
+ }
+
+ (*pat)->name = NULL;
+ (*pat)->next = NULL;
+
+ if (*firstp)
+ {
+ if (ttl != 0 && ttlp != NULL)
+ *ttlp = ttl;
+
+ if (canon != NULL)
+ {
+ (*pat)->name = canon;
+
+ /* Reclaim buffer space. */
+ if (h_name + h_namelen == buffer)
+ {
+ buffer = h_name;
+ buflen += h_namelen;
+ }
+ }
+ else
+ (*pat)->name = h_name;
+
+ *firstp = 0;
+ }
+
+ (*pat)->family = type == T_A ? AF_INET : AF_INET6;
+ memcpy ((*pat)->addr, cp, n);
+ cp += n;
+ (*pat)->scopeid = 0;
+
+ pat = &((*pat)->next);
+
+ haveanswer = 1;
+ }
+
+ if (haveanswer)
+ {
+ *patp = pat;
+ *bufferp = buffer;
+ *buflenp = buflen;
+
+ *h_errnop = NETDB_SUCCESS;
+ return NSS_STATUS_SUCCESS;
+ }
+
+ /* Special case here: if the resolver sent a result but it only
+ contains a CNAME while we are looking for a T_A or T_AAAA record,
+ we fail with NOTFOUND instead of TRYAGAIN. */
+ return canon == NULL ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
+}
+
+
+static enum nss_status
+gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
+ int anslen2, const char *qname,
+ struct gaih_addrtuple **pat, char *buffer, size_t buflen,
+ int *errnop, int *h_errnop, int32_t *ttlp)
+{
+ int first = 1;
+
+ enum nss_status status = gaih_getanswer_slice(answer1, anslen1, qname,
+ &pat, &buffer, &buflen,
+ errnop, h_errnop, ttlp,
+ &first);
+ if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND)
+ && answer2 != NULL)
+ status = gaih_getanswer_slice(answer2, anslen2, qname,
+ &pat, &buffer, &buflen,
+ errnop, h_errnop, ttlp, &first);
+
+ return status;
+}
Modified: fsf/trunk/libc/resolv/nss_dns/dns-network.c
==============================================================================
--- fsf/trunk/libc/resolv/nss_dns/dns-network.c (original)
+++ fsf/trunk/libc/resolv/nss_dns/dns-network.c Sun May 11 00:06:32 2008
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996, 1997, 1998, 1999, 2002, 2004, 2007
+/* Copyright (C) 1996, 1997, 1998, 1999, 2002, 2004, 2007, 2008
Free Software Foundation, Inc.
This file is part of the GNU C Library.
Extended from original form by Ulrich Drepper <drepper@xxxxxxxxxx>, 1996.
@@ -130,7 +130,7 @@
net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024);
anslen = __libc_res_nsearch (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf,
- 1024, &net_buffer.ptr);
+ 1024, &net_buffer.ptr, NULL, NULL);
if (anslen < 0)
{
/* Nothing found. */
@@ -206,7 +206,7 @@
net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024);
anslen = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf,
- 1024, &net_buffer.ptr);
+ 1024, &net_buffer.ptr, NULL, NULL);
if (anslen < 0)
{
/* Nothing found. */
Modified: fsf/trunk/libc/resolv/res_query.c
==============================================================================
--- fsf/trunk/libc/resolv/res_query.c (original)
+++ fsf/trunk/libc/resolv/res_query.c Sun May 11 00:06:32 2008
@@ -97,7 +97,7 @@
static int
__libc_res_nquerydomain(res_state statp, const char *name, const char *domain,
int class, int type, u_char *answer, int anslen,
- u_char **answerp);
+ u_char **answerp, u_char **answerp2, int *nanswerp2);
/*
* Formulate a normal query, send, and await answer.
@@ -115,15 +115,20 @@
int class, int type, /* class and type of query */
u_char *answer, /* buffer to put answer */
int anslen, /* size of answer buffer */
- u_char **answerp) /* if buffer needs to be enlarged */
+ u_char **answerp, /* if buffer needs to be enlarged */
+ u_char **answerp2,
+ int *nanswerp2)
{
- u_char *buf;
HEADER *hp = (HEADER *) answer;
int n, use_malloc = 0;
u_int oflags = statp->_flags;
- size_t bufsize = QUERYSIZE;
- buf = alloca (bufsize);
+ size_t bufsize = (type == T_UNSPEC ? 2 : 1) * QUERYSIZE;
+ u_char *buf = alloca (bufsize);
+ u_char *query1 = buf;
+ int nquery1 = -1;
+ u_char *query2 = NULL;
+ int nquery2 = 0;
again:
hp->rcode = NOERROR; /* default */
@@ -133,18 +138,47 @@
printf(";; res_query(%s, %d, %d)\n", name, class, type);
#endif
- n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL,
- buf, bufsize);
- if (n > 0
- && (oflags & RES_F_EDNS0ERR) == 0
- && (statp->options & RES_USE_EDNS0) != 0)
- n = __res_nopt(statp, n, buf, bufsize, anslen);
+ if (type == T_UNSPEC)
+ {
+ n = res_nmkquery(statp, QUERY, name, class, T_A, NULL, 0, NULL,
+ query1, bufsize);
+ if (n > 0)
+ {
+ if ((oflags & RES_F_EDNS0ERR) == 0
+ && (statp->options & RES_USE_EDNS0) != 0)
+ n = __res_nopt(statp, n, query1, bufsize, anslen / 2);
+
+ nquery1 = n;
+ query2 = buf + nquery1;
+ n = res_nmkquery(statp, QUERY, name, class, T_AAAA, NULL, 0,
+ NULL, query2, bufsize - n);
+ if (n > 0
+ && (oflags & RES_F_EDNS0ERR) == 0
+ && (statp->options & RES_USE_EDNS0) != 0)
+ n = __res_nopt(statp, n, query2, bufsize - n, anslen / 2);
+ nquery2 = n;
+ }
+ }
+ else
+ {
+ n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL,
+ query1, bufsize);
+
+ if (n > 0
+ && (oflags & RES_F_EDNS0ERR) == 0
+ && (statp->options & RES_USE_EDNS0) != 0)
+ n = __res_nopt(statp, n, query1, bufsize, anslen);
+
+ nquery1 = n;
+ }
+
if (__builtin_expect (n <= 0, 0) && !use_malloc) {
/* Retry just in case res_nmkquery failed because of too
short buffer. Shouldn't happen. */
- bufsize = MAXPACKET;
+ bufsize = (type == T_UNSPEC ? 2 : 1) * MAXPACKET;
buf = malloc (bufsize);
if (buf != NULL) {
+ query1 = buf;
use_malloc = 1;
goto again;
}
@@ -168,7 +202,8 @@
return (n);
}
assert (answerp == NULL || (void *) *answerp == (void *) answer);
- n = __libc_res_nsend(statp, buf, n, answer, anslen, answerp);
+ n = __libc_res_nsend(statp, query1, nquery1, query2, nquery2, answer,
+ anslen, answerp, answerp2, nanswerp2);
if (use_malloc)
free (buf);
if (n < 0) {
@@ -184,20 +219,37 @@
/* __libc_res_nsend might have reallocated the buffer. */
hp = (HEADER *) *answerp;
- if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
+ /* We simplify the following tests by assigning HP to HP2. It
+ is easy to verify that this is the same as ignoring all
+ tests of HP2. */
+ HEADER *hp2 = answerp2 ? (HEADER *) *answerp2 : hp;
+
+ if ((hp->rcode != NOERROR || ntohs(hp->ancount) == 0)
+ && (hp2->rcode != NOERROR || ntohs(hp2->ancount) == 0)) {
#ifdef DEBUG
- if (statp->options & RES_DEBUG)
+ if (statp->options & RES_DEBUG) {
printf(";; rcode = %d, ancount=%d\n", hp->rcode,
ntohs(hp->ancount));
-#endif
- switch (hp->rcode) {
+ if (hp != hp2)
+ printf(";; rcode2 = %d, ancount2=%d\n", hp2->rcode,
+ ntohs(hp2->ancount));
+ }
+#endif
+ switch (hp->rcode == NOERROR ? hp2->rcode : hp->rcode) {
case NXDOMAIN:
+ if ((hp->rcode == NOERROR && ntohs (hp->ancount) != 0)
+ || (hp2->rcode == NOERROR
+ && ntohs (hp2->ancount) != 0))
+ goto success;
RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
break;
case SERVFAIL:
RES_SET_H_ERRNO(statp, TRY_AGAIN);
break;
case NOERROR:
+ if (ntohs (hp->ancount) != 0
+ || ntohs (hp2->ancount) != 0)
+ goto success;
RES_SET_H_ERRNO(statp, NO_DATA);
break;
case FORMERR:
@@ -209,6 +261,7 @@
}
return (-1);
}
+ success:
return (n);
}
libresolv_hidden_def (__libc_res_nquery)
@@ -221,7 +274,7 @@
int anslen) /* size of answer buffer */
{
return __libc_res_nquery(statp, name, class, type, answer, anslen,
- NULL);
+ NULL, NULL, NULL);
}
libresolv_hidden_def (res_nquery)
@@ -233,11 +286,13 @@
*/
int
__libc_res_nsearch(res_state statp,
- const char *name, /* domain name */
- int class, int type, /* class and type of query */
- u_char *answer, /* buffer to put answer */
- int anslen, /* size of answer */
- u_char **answerp)
+ const char *name, /* domain name */
+ int class, int type, /* class and type of query */
+ u_char *answer, /* buffer to put answer */
+ int anslen, /* size of answer */
+ u_char **answerp,
+ u_char **answerp2,
+ int *nanswerp2)
{
const char *cp, * const *domain;
HEADER *hp = (HEADER *) answer;
@@ -260,7 +315,8 @@
/* If there aren't any dots, it could be a user-level alias. */
if (!dots && (cp = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL)
return (__libc_res_nquery(statp, cp, class, type, answer,
- anslen, answerp));
+ anslen, answerp, answerp2,
+ nanswerp2));
#ifdef DEBUG
if (statp->options & RES_DEBUG)
@@ -276,7 +332,8 @@
saved_herrno = -1;
if (dots >= statp->ndots || trailing_dot) {
ret = __libc_res_nquerydomain(statp, name, NULL, class, type,
- answer, anslen, answerp);
+ answer, anslen, answerp,
+ answerp2, nanswerp2);
if (ret > 0 || trailing_dot)
return (ret);
saved_herrno = h_errno;
@@ -285,6 +342,12 @@
answer = *answerp;
anslen = MAXPACKET;
}
+ if (answerp2
+ && (*answerp2 < answer || *answerp2 >= answer + anslen))
+ {
+ free (*answerp2);
+ *answerp2 = NULL;
+ }
}
/*
@@ -307,7 +370,8 @@
ret = __libc_res_nquerydomain(statp, name, *domain,
class, type,
- answer, anslen, answerp);
+ answer, anslen, answerp,
+ answerp2, nanswerp2);
if (ret > 0)
return (ret);
@@ -315,6 +379,13 @@
answer = *answerp;
anslen = MAXPACKET;
}
+ if (answerp2
+ && (*answerp2 < answer
+ || *answerp2 >= answer + anslen))
+ {
+ free (*answerp2);
+ *answerp2 = NULL;
+ }
/*
* If no server present, give up.
@@ -368,7 +439,8 @@
*/
if (dots && !(tried_as_is || root_on_list)) {
ret = __libc_res_nquerydomain(statp, name, NULL, class, type,
- answer, anslen, answerp);
+ answer, anslen, answerp,
+ answerp2, nanswerp2);
if (ret > 0)
return (ret);
}
@@ -380,6 +452,11 @@
* else send back meaningless H_ERRNO, that being the one from
* the last DNSRCH we did.
*/
+ if (answerp2 && (*answerp2 < answer || *answerp2 >= answer + anslen))
+ {
+ free (*answerp2);
+ *answerp2 = NULL;
+ }
if (saved_herrno != -1)
RES_SET_H_ERRNO(statp, saved_herrno);
else if (got_nodata)
@@ -398,7 +475,7 @@
int anslen) /* size of answer */
{
return __libc_res_nsearch(statp, name, class, type, answer,
- anslen, NULL);
+ anslen, NULL, NULL, NULL);
}
libresolv_hidden_def (res_nsearch)
@@ -408,12 +485,14 @@
*/
static int
__libc_res_nquerydomain(res_state statp,
- const char *name,
- const char *domain,
- int class, int type, /* class and type of query */
- u_char *answer, /* buffer to put answer */
- int anslen, /* size of answer */
- u_char **answerp)
+ const char *name,
+ const char *domain,
+ int class, int type, /* class and type of query */
+ u_char *answer, /* buffer to put answer */
+ int anslen, /* size of answer */
+ u_char **answerp,
+ u_char **answerp2,
+ int *nanswerp2)
{
char nbuf[MAXDNAME];
const char *longname = nbuf;
@@ -450,7 +529,7 @@
sprintf(nbuf, "%s.%s", name, domain);
}
return (__libc_res_nquery(statp, longname, class, type, answer,
- anslen, answerp));
+ anslen, answerp, answerp2, nanswerp2));
}
int
@@ -462,7 +541,7 @@
int anslen) /* size of answer */
{
return __libc_res_nquerydomain(statp, name, domain, class, type,
- answer, anslen, NULL);
+ answer, anslen, NULL, NULL, NULL);
}
libresolv_hidden_def (res_nquerydomain)
Modified: fsf/trunk/libc/resolv/res_send.c
==============================================================================
--- fsf/trunk/libc/resolv/res_send.c (original)
+++ fsf/trunk/libc/resolv/res_send.c Sun May 11 00:06:32 2008
@@ -176,10 +176,14 @@
/* Forward. */
static int send_vc(res_state, const u_char *, int,
- u_char **, int *, int *, int, u_char **);
+ const u_char *, int,
+ u_char **, int *, int *, int, u_char **,
+ u_char **, int *, int *);
static int send_dg(res_state, const u_char *, int,
+ const u_char *, int,
u_char **, int *, int *, int,
- int *, int *, u_char **);
+ int *, int *, u_char **,
+ u_char **, int *, int *);
#ifdef DEBUG
static void Aerror(const res_state, FILE *, const char *, int,
const struct sockaddr *);
@@ -334,33 +338,41 @@
int
__libc_res_nsend(res_state statp, const u_char *buf, int buflen,
- u_char *ans, int anssiz, u_char **ansp)
+ const u_char *buf2, int buflen2,
+ u_char *ans, int anssiz, u_char **ansp, u_char **ansp2,
+ int *nansp2)
{
- int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
+ int gotsomewhere, terrno, try, v_circuit, resplen, resplen2, ns, n;
if (statp->nscount == 0) {
__set_errno (ESRCH);
return (-1);
}
- if (anssiz < HFIXEDSZ) {
+ if (anssiz < (buf2 == NULL ? 1 : 2) * HFIXEDSZ) {
__set_errno (EINVAL);
return (-1);
}
- if ((statp->qhook || statp->rhook) && anssiz < MAXPACKET && ansp) {
- u_char *buf = malloc (MAXPACKET);
- if (buf == NULL)
- return (-1);
- memcpy (buf, ans, HFIXEDSZ);
- *ansp = buf;
- ans = buf;
- anssiz = MAXPACKET;
- }
+#ifdef USE_HOOKS
+ if (__builtin_expect (statp->qhook || statp->rhook, 0)) {
+ if (anssiz < MAXPACKET && ansp) {
+ u_char *buf = malloc (MAXPACKET);
+ if (buf == NULL)
+ return (-1);
+ memcpy (buf, ans, HFIXEDSZ);
+ *ansp = buf;
+ ans = buf;
+ anssiz = MAXPACKET;
+ }
+ }
+#endif
DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
(stdout, ";; res_send()\n"), buf, buflen);
- v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ;
+ v_circuit = ((statp->options & RES_USEVC)
+ || buflen > PACKETSZ
+ || buflen2 > PACKETSZ);
gotsomewhere = 0;
terrno = ETIMEDOUT;
@@ -442,7 +454,7 @@
* Some resolvers want to even out the load on their nameservers.
* Note that RES_BLAST overrides RES_ROTATE.
*/
- if ((statp->options & RES_ROTATE) != 0 &&
+ if (__builtin_expect ((statp->options & RES_ROTATE) != 0, 0) &&
(statp->options & RES_BLAST) == 0) {
struct sockaddr_in6 *ina;
unsigned int map;
@@ -479,8 +491,9 @@
if (nsap == NULL)
goto next_ns;
- same_ns:
- if (statp->qhook) {
+ same_ns:
+#ifdef USE_HOOKS
+ if (__builtin_expect (statp->qhook != NULL, 0)) {
int done = 0, loops = 0;
do {
@@ -512,6 +525,7 @@
}
} while (!done);
}
+#endif
#ifdef DEBUG
char tmpbuf[40];
@@ -521,28 +535,33 @@
ns + 1, inet_ntop(AF_INET6, &nsap->sin6_addr,
tmpbuf, sizeof (tmpbuf))));
- if (v_circuit) {
+ if (__builtin_expect (v_circuit, 0)) {
/* Use VC; at most one attempt per server. */
try = statp->retry;
- n = send_vc(statp, buf, buflen, &ans, &anssiz, &terrno,
- ns, ansp);
+ n = send_vc(statp, buf, buflen, buf2, buflen2,
+ &ans, &anssiz, &terrno,
+ ns, ansp, ansp2, nansp2, &resplen2);
if (n < 0)
return (-1);
if (n == 0)
goto next_ns;
- resplen = n;
} else {
/* Use datagrams. */
- n = send_dg(statp, buf, buflen, &ans, &anssiz, &terrno,
- ns, &v_circuit, &gotsomewhere, ansp);
+ n = send_dg(statp, buf, buflen, buf2, buflen2,
+ &ans, &anssiz, &terrno,
+ ns, &v_circuit, &gotsomewhere, ansp,
+ ansp2, nansp2, &resplen2);
if (n < 0)
return (-1);
if (n == 0)
goto next_ns;
if (v_circuit)
+ // XXX Check whether both requests failed or
+ // XXX whether one have been answered successfully
goto same_ns;
- resplen = n;
- }
+ }
+
+ resplen = n;
Dprint((statp->options & RES_DEBUG) ||
((statp->pfcode & RES_PRF_REPLY) &&
@@ -553,6 +572,11 @@
(statp->pfcode & RES_PRF_REPLY),
(stdout, "%s", ""),
ans, (resplen > anssiz) ? anssiz : resplen);
+ if (buf2 != NULL)
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
+ (stdout, "%s", ""),
+ *ansp2, (resplen2 > *nansp2) ? *nansp2 : resplen2);
/*
* If we have temporarily opened a virtual circuit,
@@ -563,7 +587,8 @@
(statp->options & RES_STAYOPEN) == 0) {
__res_iclose(statp, false);
}
- if (statp->rhook) {
+#ifdef USE_HOOKS
+ if (__builtin_expect (statp->rhook, 0)) {
int done = 0, loops = 0;
do {
@@ -593,6 +618,7 @@
} while (!done);
}
+#endif
return (resplen);
next_ns: ;
} /*foreach ns*/
@@ -612,7 +638,8 @@
res_nsend(res_state statp,
const u_char *buf, int buflen, u_char *ans, int anssiz)
{
- return __libc_res_nsend(statp, buf, buflen, ans, anssiz, NULL);
+ return __libc_res_nsend(statp, buf, buflen, NULL, 0, ans, anssiz,
+ NULL, NULL, NULL);
}
libresolv_hidden_def (res_nsend)
@@ -620,17 +647,23 @@
static int
send_vc(res_state statp,
- const u_char *buf, int buflen, u_char **ansp, int *anssizp,
- int *terrno, int ns, u_char **anscp)
+ const u_char *buf, int buflen, const u_char *buf2, int buflen2,
+ u_char **ansp, int *anssizp,
+ int *terrno, int ns, u_char **anscp, u_char **ansp2, int *anssizp2,
+ int *resplen2)
{
const HEADER *hp = (HEADER *) buf;
+ const HEADER *hp2 = (HEADER *) buf2;
u_char *ans = *ansp;
- int anssiz = *anssizp;
+ int orig_anssizp = *anssizp;
+ // XXX REMOVE
+ // int anssiz = *anssizp;
HEADER *anhp = (HEADER *) ans;
struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
int truncating, connreset, resplen, n;
- struct iovec iov[2];
+ struct iovec iov[4];
u_short len;
+ u_short len2;
u_char *cp;
connreset = 0;
@@ -677,11 +710,19 @@
/*
* Send length & message
*/
- ns_put16((u_short)buflen, (u_char*)&len);
+ len = htons ((u_short) buflen);
evConsIovec(&len, INT16SZ, &iov[0]);
evConsIovec((void*)buf, buflen, &iov[1]);
- if (TEMP_FAILURE_RETRY (writev(statp->_vcsock, iov, 2))
- != (INT16SZ + buflen)) {
+ int niov = 2;
+ ssize_t explen = INT16SZ + buflen;
+ if (buf2 != NULL) {
+ len2 = htons ((u_short) buflen2);
+ evConsIovec(&len2, INT16SZ, &iov[2]);
+ evConsIovec((void*)buf2, buflen2, &iov[3]);
+ niov = 4;
+ explen += INT16SZ + buflen2;
+ }
+ if (TEMP_FAILURE_RETRY (writev(statp->_vcsock, iov, niov)) != explen) {
*terrno = errno;
Perror(statp, stderr, "write failed", errno);
__res_iclose(statp, false);
@@ -690,6 +731,8 @@
/*
* Receive length & response
*/
+ int recvresp1 = 0;
+ int recvresp2 = buf2 == NULL;
read_len:
cp = ans;
len = INT16SZ;
@@ -718,30 +761,66 @@
}
return (0);
}
+#ifdef _STRING_ARCH_unaligned
+ resplen = ntohs (*(uint16_t *) ans);
+#else
resplen = ns_get16(ans);
- if (resplen > anssiz) {
+#endif
+
+ int *thisanssizp;
+ u_char **thisansp;
+ int *thisresplenp;
+ if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
+ thisanssizp = anssizp;
+ thisansp = anscp ?: ansp;
+ assert (anscp != NULL || ansp2 == NULL);
+ thisresplenp = &resplen;
+ } else {
+ if (*anssizp != MAXPACKET) {
+ /* No buffer allocated for the first
+ reply. We can try to use the rest
+ of the user-provided buffer. */
+ *anssizp2 = orig_anssizp - resplen;
+ *ansp2 = *ansp + resplen;
+ } else {
+ /* The first reply did not fit into the
+ user-provided buffer. Maybe the second
+ answer will. */
+ *anssizp2 = orig_anssizp;
+ *ansp2 = *ansp;
+ }
+
+ thisanssizp = anssizp2;
+ thisansp = ansp2;
+ thisresplenp = resplen2;
+ }
+ anhp = (HEADER *) *thisansp;
+
+ *thisresplenp = resplen;
+ if (resplen > *thisanssizp) {
+ /* Yes, we test ANSCP here. If we have two buffers
+ both will be allocatable. */
if (anscp) {
- ans = malloc (MAXPACKET);
- if (ans == NULL) {
+ u_char *newp = malloc (MAXPACKET);
+ if (newp == NULL) {
*terrno = ENOMEM;
__res_iclose(statp, false);
return (0);
}
- anssiz = MAXPACKET;
- *anssizp = MAXPACKET;
- *ansp = ans;
- *anscp = ans;
- anhp = (HEADER *) ans;
+ *thisanssizp = MAXPACKET;
+ *thisansp = newp;
+ anhp = (HEADER *) newp;
len = resplen;
} else {
Dprint(statp->options & RES_DEBUG,
(stdout, ";; response truncated\n")
);
truncating = 1;
- len = anssiz;
+ len = *thisanssizp;
}
} else
len = resplen;
+
if (len < HFIXEDSZ) {
/*
* Undersized message.
@@ -752,7 +831,8 @@
__res_iclose(statp, false);
return (0);
}
- cp = ans;
+
+ cp = *thisansp;
while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (int)len)) > 0){
cp += n;
len -= n;
@@ -768,7 +848,7 @@
* Flush rest of answer so connection stays in synch.
*/
anhp->tc = 1;
- len = resplen - anssiz;
+ len = resplen - *thisanssizp;
while (len != 0) {
char junk[PACKETSZ];
@@ -787,13 +867,24 @@
* itself confused, then drop the packet and
* wait for the correct one.
*/
- if (hp->id != anhp->id) {
+ if ((recvresp1 || hp->id != anhp->id)
+ && (recvresp2 || hp2->id != anhp->id)) {
DprintQ((statp->options & RES_DEBUG) ||
(statp->pfcode & RES_PRF_REPLY),
(stdout, ";; old answer (unexpected):\n"),
- ans, (resplen > anssiz) ? anssiz: resplen);
+ *thisansp,
+ (resplen > *thisanssiz) ? *thisanssiz: resplen);
goto read_len;
}
+
+ /* Mark which reply we received. */
+ if (recvresp1 == 0 && hp->id == anhp->id)
+ recvresp1 = 1;
+ else
+ recvresp2 = 1;
+ /* Repeat waiting if we have a second answer to arrive. */
+ if ((recvresp1 & recvresp2) == 0)
+ goto read_len;
/*
* All is well, or the error is fatal. Signal that the
@@ -804,19 +895,20 @@
static int
send_dg(res_state statp,
- const u_char *buf, int buflen, u_char **ansp, int *anssizp,
- int *terrno, int ns, int *v_circuit, int *gotsomewhere, u_char **anscp)
+ const u_char *buf, int buflen, const u_char *buf2, int buflen2,
+ u_char **ansp, int *anssizp,
+ int *terrno, int ns, int *v_circuit, int *gotsomewhere, u_char **anscp,
+ u_char **ansp2, int *anssizp2, int *resplen2)
{
const HEADER *hp = (HEADER *) buf;
+ const HEADER *hp2 = (HEADER *) buf2;
u_char *ans = *ansp;
- int anssiz = *anssizp;
- HEADER *anhp = (HEADER *) ans;
+ int orig_anssizp = *anssizp;
struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
struct timespec now, timeout, finish;
struct pollfd pfd[1];
int ptimeout;
struct sockaddr_in6 from;
- socklen_t fromlen;
int resplen, seconds, n;
if (EXT(statp).nssocks[ns] == -1) {
@@ -879,6 +971,8 @@
evAddTime(&finish, &now, &timeout);
int need_recompute = 0;
int nwritten = 0;
+ int recvresp1 = 0;
+ int recvresp2 = buf2 == NULL;
pfd[0].fd = EXT(statp).nssocks[ns];
pfd[0].events = POLLOUT;
wait:
@@ -918,35 +1012,73 @@
}
__set_errno (0);
if (pfd[0].revents & POLLOUT) {
- if (send (pfd[0].fd, buf, buflen, MSG_NOSIGNAL) != buflen) {
+ ssize_t sr;
+ if (nwritten != 0)
+ sr = send (pfd[0].fd, buf2, buflen2, MSG_NOSIGNAL);
+ else
+ sr = send (pfd[0].fd, buf, buflen, MSG_NOSIGNAL);
+
+ if (sr != buflen) {
if (errno == EINTR || errno == EAGAIN)
goto recompute_resend;
Perror(statp, stderr, "send", errno);
goto err_out;
}
- pfd[0].events = POLLIN;
+ if (nwritten != 0 || buf2 == NULL)
+ pfd[0].events = POLLIN;
+ else
+ pfd[0].events = POLLIN | POLLOUT;
++nwritten;
goto wait;
} else if (pfd[0].revents & POLLIN) {
- fromlen = sizeof(struct sockaddr_in6);
- if (anssiz < MAXPACKET
+ int *thisanssizp;
+ u_char **thisansp;
+ int *thisresplenp;
+
+ if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
+ thisanssizp = anssizp;
+ thisansp = anscp ?: ansp;
+ assert (anscp != NULL || ansp2 == NULL);
+ thisresplenp = &resplen;
+ } else {
+ if (*anssizp != MAXPACKET) {
+ /* No buffer allocated for the first
+ reply. We can try to use the rest
+ of the user-provided buffer. */
+ *anssizp2 = orig_anssizp - resplen;
+ *ansp2 = *ansp + resplen;
+ } else {
+ /* The first reply did not fit into the
+ user-provided buffer. Maybe the second
+ answer will. */
+ *anssizp2 = orig_anssizp;
+ *ansp2 = *ansp;
+ }
+
+ thisanssizp = anssizp2;
+ thisansp = ansp2;
+ thisresplenp = resplen2;
+ }
+
[... 511 lines stripped ...]