diff options
Diffstat (limited to 'nis/nss_nis')
-rw-r--r-- | nis/nss_nis/nis-hosts.c | 118 |
1 files changed, 108 insertions, 10 deletions
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 <kukuk@suse.de>, 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 @@ 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 |