From 1eb946b93509b94db2bddce741f2f3b483418a6d Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Sat, 10 May 2008 23:27:39 +0000 Subject: * 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. --- nis/nss_nis/nis-hosts.c | 118 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 108 insertions(+), 10 deletions(-) (limited to 'nis/nss_nis/nis-hosts.c') diff --git a/nis/nss_nis/nis-hosts.c b/nis/nss_nis/nis-hosts.c index 7bf4af786d..24d13634d7 100644 --- a/nis/nss_nis/nis-hosts.c +++ b/nis/nss_nis/nis-hosts.c @@ -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 , 1996. @@ -17,6 +18,7 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include #include #include /* The following is an ugly trick to avoid a prototype declaration for @@ -61,9 +63,12 @@ LINE_PARSER 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 @@ LINE_PARSER 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 bool_t new_start = 1; static char *oldkey = NULL; static int oldkeylen = 0; + enum nss_status _nss_nis_sethostent (int stayopen) { @@ -124,6 +130,7 @@ _nss_nis_sethostent (int stayopen) 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 internal_nis_gethostent_r (struct hostent *host, char *buffer, @@ -216,6 +223,7 @@ internal_nis_gethostent_r (struct hostent *host, char *buffer, return NSS_STATUS_SUCCESS; } + enum nss_status _nss_nis_gethostent_r (struct hostent *host, char *buffer, size_t buflen, int *errnop, int *h_errnop) @@ -233,6 +241,7 @@ _nss_nis_gethostent_r (struct hostent *host, char *buffer, size_t buflen, return status; } + static enum nss_status internal_gethostbyname2_r (const char *name, int af, struct hostent *host, char *buffer, size_t buflen, int *errnop, @@ -323,16 +332,24 @@ internal_gethostbyname2_r (const char *name, int af, struct hostent *host, 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, size_t buflen, int *errnop, int *h_errnop) @@ -351,6 +368,7 @@ _nss_nis_gethostbyname_r (const char *name, struct hostent *host, char *buffer, errnop, h_errnop, 0); } + enum nss_status _nss_nis_gethostbyaddr_r (const void *addr, socklen_t addrlen, int af, struct hostent *host, char *buffer, size_t buflen, @@ -430,13 +448,93 @@ _nss_nis_gethostbyaddr_r (const void *addr, socklen_t addrlen, int af, 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) +_nss_nis_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, + char *buffer, size_t buflen, int *errnop, + int *herrnop, int32_t *ttlp) { - return internal_gethostbyname2_r (name, af, result, buffer, buflen, - errnop, herrnop, flags); + 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; } -#endif -- cgit v1.2.3