diff options
Diffstat (limited to 'nis/nss_nis')
-rw-r--r-- | nis/nss_nis/nis-alias.c | 76 | ||||
-rw-r--r-- | nis/nss_nis/nis-ethers.c | 75 | ||||
-rw-r--r-- | nis/nss_nis/nis-grp.c | 256 | ||||
-rw-r--r-- | nis/nss_nis/nis-hosts.c | 136 | ||||
-rw-r--r-- | nis/nss_nis/nis-initgroups.c | 121 | ||||
-rw-r--r-- | nis/nss_nis/nis-netgrp.c | 30 | ||||
-rw-r--r-- | nis/nss_nis/nis-network.c | 115 | ||||
-rw-r--r-- | nis/nss_nis/nis-proto.c | 60 | ||||
-rw-r--r-- | nis/nss_nis/nis-publickey.c | 106 | ||||
-rw-r--r-- | nis/nss_nis/nis-pwd.c | 350 | ||||
-rw-r--r-- | nis/nss_nis/nis-rpc.c | 169 | ||||
-rw-r--r-- | nis/nss_nis/nis-service.c | 254 | ||||
-rw-r--r-- | nis/nss_nis/nis-spwd.c | 66 |
13 files changed, 1038 insertions, 776 deletions
diff --git a/nis/nss_nis/nis-alias.c b/nis/nss_nis/nis-alias.c index 3b0887be04..9286e36ba6 100644 --- a/nis/nss_nis/nis-alias.c +++ b/nis/nss_nis/nis-alias.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996-2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1996-2002, 2003, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. @@ -125,52 +125,53 @@ internal_nis_getaliasent_r (struct aliasent *alias, char *buffer, size_t buflen, int *errnop) { char *domain; - char *result; - int len; - char *outkey; - int keylen; - char *p; - int parse_res; - if (yp_get_default_domain (&domain)) + if (__builtin_expect (yp_get_default_domain (&domain), 0)) return NSS_STATUS_UNAVAIL; alias->alias_local = 0; /* Get the next entry until we found a correct one. */ + int parse_res; do { - enum nss_status retval; + char *result; + int len; + char *outkey; + int keylen; + int yperr; if (new_start) - retval = yperr2nss (yp_first (domain, "mail.aliases", - &outkey, &keylen, &result, &len)); + yperr = yp_first (domain, "mail.aliases", &outkey, &keylen, &result, + &len); else - retval = yperr2nss ( yp_next (domain, "mail.aliases", oldkey, - oldkeylen, &outkey, &keylen, - &result, &len)); - if (retval != NSS_STATUS_SUCCESS) + yperr = yp_next (domain, "mail.aliases", oldkey, oldkeylen, &outkey, + &keylen, &result, &len); + + if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) { + enum nss_status retval = yperr2nss (yperr); + if (retval == NSS_STATUS_TRYAGAIN) *errnop = errno; return retval; } - if ((size_t) (len + 1) > buflen) + if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) { free (result); *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } - p = strncpy (buffer, result, len); + char *p = strncpy (buffer, result, len); buffer[len] = '\0'; while (isspace (*p)) ++p; free (result); - parse_res = _nss_nis_parse_aliasent (outkey, p, alias, buffer, buflen, - errnop); - if (parse_res == -1) + parse_res = _nss_nis_parse_aliasent (outkey, p, alias, buffer, + buflen, errnop); + if (__builtin_expect (parse_res == -1, 0)) { free (outkey); *errnop = ERANGE; @@ -206,56 +207,55 @@ enum nss_status _nss_nis_getaliasbyname_r (const char *name, struct aliasent *alias, char *buffer, size_t buflen, int *errnop) { - enum nss_status retval; - int parse_res; - char *domain; - char *result; - int len; - char *p; - size_t namlen = strlen (name); - char name2[namlen + 1]; - size_t i; - if (name == NULL) { *errnop = EINVAL; return NSS_STATUS_UNAVAIL; } - if (yp_get_default_domain (&domain)) + size_t namlen = strlen (name); + char name2[namlen + 1]; + + char *domain; + if (__builtin_expect (yp_get_default_domain (&domain), 0)) return NSS_STATUS_UNAVAIL; /* Convert name to lowercase. */ + size_t i; for (i = 0; i < namlen; ++i) name2[i] = _tolower (name[i]); name2[i] = '\0'; - retval = yperr2nss (yp_match (domain, "mail.aliases", name2, namlen, - &result, &len)); + char *result; + int len; + int yperr = yp_match (domain, "mail.aliases", name2, namlen, &result, &len); - if (retval != NSS_STATUS_SUCCESS) + if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) { + enum nss_status retval = yperr2nss (yperr); + if (retval == NSS_STATUS_TRYAGAIN) *errnop = errno; return retval; } - if ((size_t) (len + 1) > buflen) + if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) { free (result); *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } - p = strncpy (buffer, result, len); + char *p = strncpy (buffer, result, len); buffer[len] = '\0'; while (isspace (*p)) ++p; free (result); alias->alias_local = 0; - parse_res = _nss_nis_parse_aliasent (name, p, alias, buffer, buflen, errnop); - if (parse_res < 1) + int parse_res = _nss_nis_parse_aliasent (name, p, alias, buffer, buflen, + errnop); + if (__builtin_expect (parse_res < 1, 0)) { if (parse_res == -1) return NSS_STATUS_TRYAGAIN; diff --git a/nis/nss_nis/nis-ethers.c b/nis/nss_nis/nis-ethers.c index def4c22510..a3064282ab 100644 --- a/nis/nss_nis/nis-ethers.c +++ b/nis/nss_nis/nis-ethers.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996-2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 1996-2003, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996. @@ -182,45 +182,46 @@ enum nss_status _nss_nis_gethostton_r (const char *name, struct etherent *eth, char *buffer, size_t buflen, int *errnop) { - struct parser_data *data = (void *) buffer; - enum nss_status retval; - char *domain, *result, *p; - int len, parse_res; - if (name == NULL) { *errnop = EINVAL; return NSS_STATUS_UNAVAIL; } - if (yp_get_default_domain (&domain)) + char *domain; + if (__builtin_expect (yp_get_default_domain (&domain), 0)) return NSS_STATUS_UNAVAIL; - retval = yperr2nss (yp_match (domain, "ethers.byname", name, - strlen (name), &result, &len)); + char *result; + int len; + int yperr = yp_match (domain, "ethers.byname", name, strlen (name), &result, + &len); - if (retval != NSS_STATUS_SUCCESS) + if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) { + enum nss_status retval = yperr2nss (yperr); + if (retval == NSS_STATUS_TRYAGAIN) *errnop = errno; return retval; } - if ((size_t) (len + 1) > buflen) + if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) { free (result); *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } - p = strncpy (buffer, result, len); + char *p = strncpy (buffer, result, len); buffer[len] = '\0'; while (isspace (*p)) ++p; free (result); - parse_res = _nss_files_parse_etherent (p, eth, data, buflen, errnop); - if (parse_res < 1) + int parse_res = _nss_files_parse_etherent (p, eth, (void *) buffer, buflen, + errnop); + if (__builtin_expect (parse_res < 1, 0)) { if (parse_res == -1) return NSS_STATUS_TRYAGAIN; @@ -234,54 +235,54 @@ enum nss_status _nss_nis_getntohost_r (const struct ether_addr *addr, struct etherent *eth, char *buffer, size_t buflen, int *errnop) { - struct parser_data *data = (void *) buffer; - enum nss_status retval; - char *domain, *result, *p; - int len, nlen, parse_res; - char buf[33]; - if (addr == NULL) { *errnop = EINVAL; return NSS_STATUS_UNAVAIL; } - if (yp_get_default_domain (&domain)) + char *domain; + if (__builtin_expect (yp_get_default_domain (&domain), 0)) return NSS_STATUS_UNAVAIL; - nlen = sprintf (buf, "%x:%x:%x:%x:%x:%x", - (int) addr->ether_addr_octet[0], - (int) addr->ether_addr_octet[1], - (int) addr->ether_addr_octet[2], - (int) addr->ether_addr_octet[3], - (int) addr->ether_addr_octet[4], - (int) addr->ether_addr_octet[5]); - - retval = yperr2nss (yp_match (domain, "ethers.byaddr", buf, - nlen, &result, &len)); - - if (retval != NSS_STATUS_SUCCESS) + char buf[33]; + int nlen = snprintf (buf, sizeof (buf), "%x:%x:%x:%x:%x:%x", + (int) addr->ether_addr_octet[0], + (int) addr->ether_addr_octet[1], + (int) addr->ether_addr_octet[2], + (int) addr->ether_addr_octet[3], + (int) addr->ether_addr_octet[4], + (int) addr->ether_addr_octet[5]); + + char *result; + int len; + int yperr = yp_match (domain, "ethers.byaddr", buf, nlen, &result, &len); + + if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) { + enum nss_status retval = yperr2nss (yperr); + if (retval == NSS_STATUS_TRYAGAIN) *errnop = errno; return retval; } - if ((size_t) (len + 1) > buflen) + if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) { free (result); *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } - p = strncpy (buffer, result, len); + char *p = strncpy (buffer, result, len); buffer[len] = '\0'; while (isspace (*p)) ++p; free (result); - parse_res = _nss_files_parse_etherent (p, eth, data, buflen, errnop); - if (parse_res < 1) + int parse_res = _nss_files_parse_etherent (p, eth, (void *) buffer, buflen, + errnop); + if (__builtin_expect (parse_res < 1, 0)) { if (parse_res == -1) return NSS_STATUS_TRYAGAIN; diff --git a/nis/nss_nis/nis-grp.c b/nis/nss_nis/nis-grp.c index 8be7332515..6e36cf828f 100644 --- a/nis/nss_nis/nis-grp.c +++ b/nis/nss_nis/nis-grp.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996-1999, 2001-2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 1996-1999, 2001-2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996. @@ -17,20 +17,17 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include <nss.h> -/* The following is an ugly trick to avoid a prototype declaration for - _nss_nis_endgrent. */ -#define _nss_nis_endgrent _nss_nis_endgrent_XXX -#include <grp.h> -#undef _nss_nis_endgrent #include <ctype.h> #include <errno.h> +#include <grp.h> +#include <nss.h> #include <string.h> #include <bits/libc-lock.h> #include <rpcsvc/yp.h> #include <rpcsvc/ypclnt.h> #include "nss-nis.h" +#include <libnsl.h> /* Get the declaration of the parser function. */ #define ENTNAME grent @@ -44,12 +41,12 @@ __libc_lock_define_initialized (static, lock) static bool_t new_start = 1; static char *oldkey; static int oldkeylen; +static intern_t intern; -enum nss_status -_nss_nis_setgrent (int stayopen) -{ - __libc_lock_lock (lock); +static void +internal_nis_endgrent (void) +{ new_start = 1; if (oldkey != NULL) { @@ -58,72 +55,186 @@ _nss_nis_setgrent (int stayopen) oldkeylen = 0; } + struct response_t *curr = intern.next; + + while (curr != NULL) + { + struct response_t *last = curr; + curr = curr->next; + free (last); + } + + intern.next = intern.start = NULL; +} + + +enum nss_status +_nss_nis_endgrent (void) +{ + __libc_lock_lock (lock); + + internal_nis_endgrent (); + __libc_lock_unlock (lock); return NSS_STATUS_SUCCESS; } -/* Make _nss_nis_endgrent an alias of _nss_nis_setgrent. We do this - even though the prototypes don't match. The argument of setgrent - is not used so this makes no difference. */ -strong_alias (_nss_nis_setgrent, _nss_nis_endgrent) + + +enum nss_status +internal_nis_setgrent (void) +{ + /* We have to read all the data now. */ + char *domain; + if (__builtin_expect (yp_get_default_domain (&domain), 0)) + return NSS_STATUS_UNAVAIL; + + struct ypall_callback ypcb; + + ypcb.foreach = _nis_saveit; + ypcb.data = (char *) &intern; + enum nss_status status = yperr2nss (yp_all (domain, "group.byname", &ypcb)); + + + /* Mark the last buffer as full. */ + if (intern.next != NULL) + intern.next->size = intern.offset; + + intern.next = intern.start; + intern.offset = 0; + + return status; +} + + +enum nss_status +_nss_nis_setgrent (int stayopen) +{ + enum nss_status result = NSS_STATUS_SUCCESS; + + __libc_lock_lock (lock); + + internal_nis_endgrent (); + + if (_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ) + result = internal_nis_setgrent (); + + __libc_lock_unlock (lock); + + return result; +} + static enum nss_status internal_nis_getgrent_r (struct group *grp, char *buffer, size_t buflen, int *errnop) { - struct parser_data *data = (void *) buffer; - char *domain, *result, *outkey; - int len, keylen, parse_res; + /* If we read the entire database at setpwent time we just iterate + over the data we have in memory. */ + bool batch_read = intern.start != NULL; - if (yp_get_default_domain (&domain)) + char *domain = NULL; + if (!batch_read && __builtin_expect (yp_get_default_domain (&domain), 0)) return NSS_STATUS_UNAVAIL; /* Get the next entry until we found a correct one. */ + int parse_res; do { - enum nss_status retval; - char *p; + char *result; + char *outkey; + int len; + int keylen; - if (new_start) - retval = yperr2nss (yp_first (domain, "group.byname", - &outkey, &keylen, &result, &len)); - else - retval = yperr2nss ( yp_next (domain, "group.byname", - oldkey, oldkeylen, - &outkey, &keylen, &result, &len)); + if (batch_read) + { + struct response_t *bucket; - if (retval != NSS_STATUS_SUCCESS) - { - if (retval == NSS_STATUS_TRYAGAIN) - *errnop = errno; - return retval; - } + handle_batch_read: + bucket = intern.next; + + if (__builtin_expect (intern.offset >= bucket->size, 0)) + { + if (bucket->next == NULL) + return NSS_STATUS_NOTFOUND; + + /* We look at all the content in the current bucket. Go on + to the next. */ + bucket = intern.next = bucket->next; + intern.offset = 0; + } - if ((size_t) (len + 1) > buflen) + for (result = &bucket->mem[intern.offset]; isspace (*result); + ++result) + ++intern.offset; + + len = strlen (result); + } + else + { + int yperr; + + if (new_start) + { + /* Maybe we should read the database in one piece. */ + if ((_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ) + && internal_nis_setgrent () == NSS_STATUS_SUCCESS + && intern.start != NULL) + { + batch_read = true; + goto handle_batch_read; + } + + yperr = yp_first (domain, "group.byname", &outkey, &keylen, + &result, &len); + } + else + yperr = yp_next (domain, "group.byname", oldkey, oldkeylen, + &outkey, &keylen, &result, &len); + + if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) + { + enum nss_status retval = yperr2nss (yperr); + + if (retval == NSS_STATUS_TRYAGAIN) + *errnop = errno; + return retval; + } + } + + if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) { free (result); *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } - p = strncpy (buffer, result, len); + char *p = strncpy (buffer, result, len); buffer[len] = '\0'; while (isspace (*p)) ++p; - free (result); + if (!batch_read) + free (result); - parse_res = _nss_files_parse_grent (p, grp, data, buflen, errnop); - if (parse_res == -1) + parse_res = _nss_files_parse_grent (p, grp, (void *) buffer, buflen, + errnop); + if (__builtin_expect (parse_res == -1, 0)) { - free (outkey); + if (!batch_read) + free (outkey); *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } - free (oldkey); - oldkey = outkey; - oldkeylen = keylen; - new_start = 0; + if (batch_read) + intern.offset += len + 1; + else + { + free (oldkey); + oldkey = outkey; + oldkeylen = keylen; + new_start = 0; + } } while (parse_res < 1); @@ -149,45 +260,46 @@ enum nss_status _nss_nis_getgrnam_r (const char *name, struct group *grp, char *buffer, size_t buflen, int *errnop) { - struct parser_data *data = (void *) buffer; - enum nss_status retval; - char *domain, *result, *p; - int len, parse_res; - if (name == NULL) { *errnop = EINVAL; return NSS_STATUS_UNAVAIL; } - if (yp_get_default_domain (&domain)) + char *domain; + if (__builtin_expect (yp_get_default_domain (&domain), 0)) return NSS_STATUS_UNAVAIL; - retval = yperr2nss (yp_match (domain, "group.byname", name, - strlen (name), &result, &len)); + char *result; + int len; + int yperr = yp_match (domain, "group.byname", name, strlen (name), &result, + &len); - if (retval != NSS_STATUS_SUCCESS) + if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) { + enum nss_status retval = yperr2nss (yperr); + if (retval == NSS_STATUS_TRYAGAIN) *errnop = errno; return retval; } - if ((size_t) (len + 1) > buflen) + if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) { free (result); *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } - p = strncpy (buffer, result, len); + char *p = strncpy (buffer, result, len); buffer[len] = '\0'; while (isspace (*p)) ++p; free (result); - parse_res = _nss_files_parse_grent (p, grp, data, buflen, errnop); - if (parse_res < 1) + int parse_res = _nss_files_parse_grent (p, grp, (void *) buffer, buflen, + errnop); + if (__builtin_expect (parse_res < 1, 0)) { if (parse_res == -1) return NSS_STATUS_TRYAGAIN; @@ -201,42 +313,42 @@ enum nss_status _nss_nis_getgrgid_r (gid_t gid, struct group *grp, char *buffer, size_t buflen, int *errnop) { - struct parser_data *data = (void *) buffer; - enum nss_status retval; - char *domain, *result, *p; - int len, nlen, parse_res; - char buf[32]; - - if (yp_get_default_domain (&domain)) + char *domain; + if (__builtin_expect (yp_get_default_domain (&domain), 0)) return NSS_STATUS_UNAVAIL; - nlen = sprintf (buf, "%lu", (unsigned long int) gid); + char buf[32]; + int nlen = sprintf (buf, "%lu", (unsigned long int) gid); - retval = yperr2nss (yp_match (domain, "group.bygid", buf, - nlen, &result, &len)); + char *result; + int len; + int yperr = yp_match (domain, "group.bygid", buf, nlen, &result, &len); - if (retval != NSS_STATUS_SUCCESS) + if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) { + enum nss_status retval = yperr2nss (yperr); + if (retval == NSS_STATUS_TRYAGAIN) *errnop = errno; return retval; } - if ((size_t) (len + 1) > buflen) + if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) { free (result); *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } - p = strncpy (buffer, result, len); + char *p = strncpy (buffer, result, len); buffer[len] = '\0'; while (isspace (*p)) ++p; free (result); - parse_res = _nss_files_parse_grent (p, grp, data, buflen, errnop); - if (parse_res < 1) + int parse_res = _nss_files_parse_grent (p, grp, (void *) buffer, buflen, + errnop); + if (__builtin_expect (parse_res < 1, 0)) { if (parse_res == -1) return NSS_STATUS_TRYAGAIN; diff --git a/nis/nss_nis/nis-hosts.c b/nis/nss_nis/nis-hosts.c index 58a9064f14..bde0a3291f 100644 --- a/nis/nss_nis/nis-hosts.c +++ b/nis/nss_nis/nis-hosts.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996-2000, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1996-2000, 2002, 2003, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996. @@ -131,39 +131,42 @@ internal_nis_gethostent_r (struct hostent *host, char *buffer, int af, int flags) { char *domain; - char *result; - int len, parse_res; - char *outkey; - int keylen; - struct parser_data *data = (void *) buffer; - size_t linebuflen = buffer + buflen - data->linebuffer; - - if (yp_get_default_domain (&domain)) + if (__builtin_expect (yp_get_default_domain (&domain), 0)) return NSS_STATUS_UNAVAIL; - if (buflen < sizeof *data + 1) + uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct parser_data); + buffer += pad; + + struct parser_data *data = (void *) buffer; + if (__builtin_expect (buflen < sizeof *data + 1 + pad, 0)) { *errnop = ERANGE; *h_errnop = NETDB_INTERNAL; return NSS_STATUS_TRYAGAIN; } + buflen -= pad; /* Get the next entry until we found a correct one. */ + const size_t linebuflen = buffer + buflen - data->linebuffer; + int parse_res; do { - enum nss_status retval; - char *p; - + char *result; + int len; + char *outkey; + int keylen; + int yperr; if (new_start) - retval = yperr2nss (yp_first (domain, "hosts.byname", - &outkey, &keylen, &result, &len)); + yperr = yp_first (domain, "hosts.byname", &outkey, &keylen, &result, + &len); else - retval = yperr2nss ( yp_next (domain, "hosts.byname", - oldkey, oldkeylen, - &outkey, &keylen, &result, &len)); + yperr = yp_next (domain, "hosts.byname", oldkey, oldkeylen, &outkey, + &keylen, &result, &len); - if (retval != NSS_STATUS_SUCCESS) + if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) { + enum nss_status retval = yperr2nss (yperr); + switch (retval) { case NSS_STATUS_TRYAGAIN: @@ -180,7 +183,7 @@ internal_nis_gethostent_r (struct hostent *host, char *buffer, return retval; } - if ((size_t) (len + 1) > linebuflen) + if (__builtin_expect ((size_t) (len + 1) > linebuflen, 0)) { free (result); *h_errnop = NETDB_INTERNAL; @@ -188,14 +191,14 @@ internal_nis_gethostent_r (struct hostent *host, char *buffer, return NSS_STATUS_TRYAGAIN; } - p = strncpy (data->linebuffer, result, len); + char *p = strncpy (data->linebuffer, result, len); data->linebuffer[len] = '\0'; while (isspace (*p)) ++p; free (result); parse_res = parse_line (p, host, data, buflen, errnop, af, flags); - if (parse_res == -1) + if (__builtin_expect (parse_res == -1, 0)) { free (outkey); *h_errnop = NETDB_INTERNAL; @@ -235,11 +238,10 @@ internal_gethostbyname2_r (const char *name, int af, struct hostent *host, char *buffer, size_t buflen, int *errnop, int *h_errnop, int flags) { - enum nss_status retval; - char *domain, *result, *p; - int len, parse_res; + uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct parser_data); + buffer += pad; + struct parser_data *data = (void *) buffer; - size_t linebuflen = buffer + buflen - data->linebuffer; if (name == NULL) { @@ -247,33 +249,35 @@ internal_gethostbyname2_r (const char *name, int af, struct hostent *host, return NSS_STATUS_UNAVAIL; } + char *domain; if (yp_get_default_domain (&domain)) return NSS_STATUS_UNAVAIL; - if (buflen < sizeof *data + 1) + if (buflen < sizeof *data + 1 + pad) { *h_errnop = NETDB_INTERNAL; *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } - else - { - /* Convert name to lowercase. */ - size_t namlen = strlen (name); - char name2[namlen + 1]; - size_t i; + buflen -= pad; - for (i = 0; i < namlen; ++i) - name2[i] = tolower (name[i]); - name2[i] = '\0'; + /* Convert name to lowercase. */ + size_t namlen = strlen (name); + char name2[namlen + 1]; + size_t i; - retval = yperr2nss (yp_match (domain, "hosts.byname", name2, - namlen, &result, &len)); + 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 (retval != NSS_STATUS_SUCCESS) + if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) { + enum nss_status retval = yperr2nss (yperr); + if (retval == NSS_STATUS_TRYAGAIN) { *h_errnop = TRY_AGAIN; @@ -284,7 +288,8 @@ internal_gethostbyname2_r (const char *name, int af, struct hostent *host, return retval; } - if ((size_t) (len + 1) > linebuflen) + const size_t linebuflen = buffer + buflen - data->linebuffer; + if (__builtin_expect ((size_t) (len + 1) > linebuflen, 0)) { free (result); *h_errnop = NETDB_INTERNAL; @@ -292,15 +297,15 @@ internal_gethostbyname2_r (const char *name, int af, struct hostent *host, return NSS_STATUS_TRYAGAIN; } - p = strncpy (data->linebuffer, result, len); + char *p = strncpy (data->linebuffer, result, len); data->linebuffer[len] = '\0'; while (isspace (*p)) ++p; free (result); - parse_res = parse_line (p, host, data, buflen, errnop, af, flags); + int parse_res = parse_line (p, host, data, buflen, errnop, af, flags); - if (parse_res < 1 || host->h_addrtype != af) + if (__builtin_expect (parse_res < 1 || host->h_addrtype != af, 0)) { if (parse_res == -1) { @@ -351,42 +356,46 @@ _nss_nis_gethostbyaddr_r (const void *addr, socklen_t addrlen, int af, struct hostent *host, char *buffer, size_t buflen, int *errnop, int *h_errnop) { - enum nss_status retval; - char *domain, *result, *p; - int len, parse_res; - char *buf; - struct parser_data *data = (void *) buffer; - size_t linebuflen = buffer + buflen - data->linebuffer; - - if (yp_get_default_domain (&domain)) + char *domain; + if (__builtin_expect (yp_get_default_domain (&domain), 0)) return NSS_STATUS_UNAVAIL; - if (buflen < sizeof *data + 1) + uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct parser_data); + buffer += pad; + + struct parser_data *data = (void *) buffer; + if (__builtin_expect (buflen < sizeof *data + 1 + pad, 0)) { *errnop = ERANGE; *h_errnop = NETDB_INTERNAL; return NSS_STATUS_TRYAGAIN; } + buflen -= pad; - buf = inet_ntoa (*(const struct in_addr *) addr); + char *buf = inet_ntoa (*(const struct in_addr *) addr); - retval = yperr2nss (yp_match (domain, "hosts.byaddr", buf, - strlen (buf), &result, &len)); + char *result; + int len; + int yperr = yp_match (domain, "hosts.byaddr", buf, strlen (buf), &result, + &len); - if (retval != NSS_STATUS_SUCCESS) + if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) { + enum nss_status retval = yperr2nss (yperr); + if (retval == NSS_STATUS_TRYAGAIN) { *h_errnop = TRY_AGAIN; *errnop = errno; } - if (retval == NSS_STATUS_NOTFOUND) + else if (retval == NSS_STATUS_NOTFOUND) *h_errnop = HOST_NOT_FOUND; return retval; } - if ((size_t) (len + 1) > linebuflen) + const size_t linebuflen = buffer + buflen - data->linebuffer; + if (__builtin_expect ((size_t) (len + 1) > linebuflen, 0)) { free (result); *errnop = ERANGE; @@ -394,15 +403,16 @@ _nss_nis_gethostbyaddr_r (const void *addr, socklen_t addrlen, int af, return NSS_STATUS_TRYAGAIN; } - p = strncpy (data->linebuffer, result, len); + char *p = strncpy (data->linebuffer, result, len); data->linebuffer[len] = '\0'; while (isspace (*p)) ++p; free (result); - parse_res = parse_line (p, host, data, buflen, errnop, af, - ((_res.options & RES_USE_INET6) ? AI_V4MAPPED : 0)); - if (parse_res < 1) + int parse_res = parse_line (p, host, data, buflen, errnop, af, + ((_res.options & RES_USE_INET6) + ? AI_V4MAPPED : 0)); + if (__builtin_expect (parse_res < 1, 0)) { if (parse_res == -1) { diff --git a/nis/nss_nis/nis-initgroups.c b/nis/nss_nis/nis-initgroups.c index 33a9662b4c..a5a3ba6144 100644 --- a/nis/nss_nis/nis-initgroups.c +++ b/nis/nss_nis/nis-initgroups.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998-2000, 2002, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 1998-2000,2002,2003,2004,2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998. @@ -30,6 +30,7 @@ #include <sys/param.h> #include "nss-nis.h" +#include <libnsl.h> /* Get the declaration of the parser function. */ #define ENTNAME grent @@ -37,47 +38,6 @@ #define EXTERN_PARSER #include <nss/nss_files/files-parse.c> -struct response_t -{ - struct response_t *next; - char val[0]; -}; - -struct intern_t -{ - struct response_t *start; - struct response_t *next; -}; -typedef struct intern_t intern_t; - -static int -saveit (int instatus, char *inkey, int inkeylen, char *inval, - int invallen, char *indata) -{ - intern_t *intern = (intern_t *) indata; - - if (instatus != YP_TRUE) - return 1; - - if (inkey && inkeylen > 0 && inval && invallen > 0) - { - struct response_t *newp = malloc (sizeof (struct response_t) - + invallen + 1); - if (newp == NULL) - return 1; /* We have no error code for out of memory */ - - if (intern->start == NULL) - intern->start = newp; - else - intern->next->next = newp; - intern->next = newp; - - newp->next = NULL; - *((char *) mempcpy (newp->val, inval, invallen)) = '\0'; - } - - return 0; -} static enum nss_status internal_setgrent (char *domainname, intern_t *intern) @@ -85,41 +45,72 @@ internal_setgrent (char *domainname, intern_t *intern) struct ypall_callback ypcb; enum nss_status status; - intern->start = NULL; - - ypcb.foreach = saveit; + ypcb.foreach = _nis_saveit; ypcb.data = (char *) intern; status = yperr2nss (yp_all (domainname, "group.byname", &ypcb)); + + /* Mark the last buffer as full. */ + if (intern->next != NULL) + intern->next->size = intern->offset; + intern->next = intern->start; + intern->offset = 0; return status; } + static enum nss_status internal_getgrent_r (struct group *grp, char *buffer, size_t buflen, int *errnop, intern_t *intern) { - struct parser_data *data = (void *) buffer; - int parse_res; - char *p; - if (intern->start == NULL) return NSS_STATUS_NOTFOUND; /* Get the next entry until we found a correct one. */ + int parse_res; do { - if (intern->next == NULL) - return NSS_STATUS_NOTFOUND; + struct response_t *bucket = intern->next; + + if (__builtin_expect (intern->offset >= bucket->size, 0)) + { + if (bucket->next == NULL) + return NSS_STATUS_NOTFOUND; + + /* We look at all the content in the current bucket. Go on + to the next. */ + bucket = intern->next = bucket->next; + intern->offset = 0; + } + + char *p; + for (p = &bucket->mem[intern->offset]; isspace (*p); ++p) + ++intern->offset; - p = strncpy (buffer, intern->next->val, buflen); - while (isspace (*p)) - ++p; + size_t len = strlen (p) + 1; + if (__builtin_expect (len > buflen, 0)) + { + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; + } - parse_res = _nss_files_parse_grent (p, grp, data, buflen, errnop); - if (parse_res == -1) + /* We unfortunately have to copy the data in the user-provided + buffer because that buffer might be around for a very long + time and the servent structure must remain valid. If we would + rely on the BUCKET memory the next 'setservent' or 'endservent' + call would destroy it. + + The important thing is that it is a single NUL-terminated + string. This is what the parsing routine expects. */ + p = memcpy (buffer, &bucket->mem[intern->offset], len); + + parse_res = _nss_files_parse_grent (p, grp, (void *) buffer, buflen, + errnop); + if (__builtin_expect (parse_res == -1, 0)) return NSS_STATUS_TRYAGAIN; - intern->next = intern->next->next; + + intern->offset += len; } while (!parse_res); @@ -166,13 +157,12 @@ initgroups_netid (uid_t uid, gid_t group, long int *start, long int *size, ssize_t keylen = snprintf (key, sizeof (key), "unix.%lu@%s", (unsigned long int) uid, domainname); - enum nss_status retval; char *result; int reslen; - retval = yperr2nss (yp_match (domainname, "netid.byname", key, keylen, - &result, &reslen)); - if (retval != NSS_STATUS_SUCCESS) - return retval; + int yperr = yp_match (domainname, "netid.byname", key, keylen, &result, + &reslen); + if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) + return yperr2nss (yperr); /* Parse the result: following the colon is a comma separated list of group IDs. */ @@ -207,7 +197,6 @@ initgroups_netid (uid_t uid, gid_t group, long int *start, long int *size, if (*start == *size) { /* Need a bigger buffer. */ - gid_t *newgroups; long int newsize; if (limit > 0 && *size == limit) @@ -219,7 +208,7 @@ initgroups_netid (uid_t uid, gid_t group, long int *start, long int *size, else newsize = MIN (limit, 2 * *size); - newgroups = realloc (groups, newsize * sizeof (*groups)); + gid_t *newgroups = realloc (groups, newsize * sizeof (*groups)); if (newgroups == NULL) goto errout; *groupsp = groups = newgroups; @@ -247,7 +236,7 @@ _nss_nis_initgroups_dyn (const char *user, gid_t group, long int *start, return NSS_STATUS_UNAVAIL; /* Check whether we are supposed to use the netid.byname map. */ - if (_nis_default_nss () & NSS_FLAG_NETID_AUTHORITATIVE) + if (_nsl_default_nss () & NSS_FLAG_NETID_AUTHORITATIVE) { /* We need the user ID. */ uid_t uid; @@ -262,7 +251,7 @@ _nss_nis_initgroups_dyn (const char *user, gid_t group, long int *start, size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX); char *tmpbuf; enum nss_status status; - intern_t intern = { NULL, NULL }; + intern_t intern = { NULL, NULL, 0 }; gid_t *groups = *groupsp; status = internal_setgrent (domainname, &intern); diff --git a/nis/nss_nis/nis-netgrp.c b/nis/nss_nis/nis-netgrp.c index d339dd5097..5a88b72d9c 100644 --- a/nis/nss_nis/nis-netgrp.c +++ b/nis/nss_nis/nis-netgrp.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996,1997,1999,2000,2002,2003,2004 +/* Copyright (C) 1996,1997,1999,2000,2002,2003,2004,2005,2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996. @@ -41,41 +41,37 @@ _nss_netgroup_parseline (char **cursor, struct __netgrent *netgrp, static void internal_nis_endnetgrent (struct __netgrent *netgrp) { - if (netgrp->data != NULL) - { - free (netgrp->data); - netgrp->data = NULL; - netgrp->data_size = 0; - netgrp->cursor = NULL; - } + free (netgrp->data); + netgrp->data = NULL; + netgrp->data_size = 0; + netgrp->cursor = NULL; } + enum nss_status _nss_nis_setnetgrent (const char *group, struct __netgrent *netgrp) { - char *domain; int len; enum nss_status status; status = NSS_STATUS_SUCCESS; - if (group == NULL || group[0] == '\0') + if (__builtin_expect (group == NULL || group[0] == '\0', 0)) return NSS_STATUS_UNAVAIL; - if (yp_get_default_domain (&domain)) + char *domain; + if (__builtin_expect (yp_get_default_domain (&domain), 0)) return NSS_STATUS_UNAVAIL; - internal_nis_endnetgrent (netgrp); - status = yperr2nss (yp_match (domain, "netgroup", group, strlen (group), &netgrp->data, &len)); - if (status == NSS_STATUS_SUCCESS) + if (__builtin_expect (status == NSS_STATUS_SUCCESS, 1)) { /* Our implementation of yp_match already allocates a buffer which is one byte larger than the value in LEN specifies and the last byte is filled with NUL. So we can simply use that buffer. */ - assert (len > 0); + assert (len >= 0); assert (malloc_usable_size (netgrp->data) >= len + 1); assert (netgrp->data[len] == '\0'); @@ -95,13 +91,11 @@ _nss_nis_endnetgrent (struct __netgrent *netgrp) return NSS_STATUS_SUCCESS; } + enum nss_status _nss_nis_getnetgrent_r (struct __netgrent *result, char *buffer, size_t buflen, int *errnop) { - if (result->cursor == NULL) - return NSS_STATUS_NOTFOUND; - return _nss_netgroup_parseline (&result->cursor, result, buffer, buflen, errnop); } diff --git a/nis/nss_nis/nis-network.c b/nis/nss_nis/nis-network.c index ed8439c814..9b02302e0b 100644 --- a/nis/nss_nis/nis-network.c +++ b/nis/nss_nis/nis-network.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996-2000, 2001, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1996-2003, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. @@ -73,28 +73,32 @@ internal_nis_getnetent_r (struct netent *net, char *buffer, size_t buflen, int *errnop, int *herrnop) { struct parser_data *data = (void *) buffer; - char *domain, *result, *outkey; - int len, keylen, parse_res; - if (yp_get_default_domain (&domain)) + char *domain; + if (__builtin_expect (yp_get_default_domain (&domain), 0)) return NSS_STATUS_UNAVAIL; /* Get the next entry until we found a correct one. */ + int parse_res; do { - enum nss_status retval; - char *p; + char *result; + char *outkey; + int len; + int keylen; + int yperr; if (new_start) - retval = yperr2nss (yp_first (domain, "networks.byname", - &outkey, &keylen, &result, &len)); + yperr = yp_first (domain, "networks.byname", &outkey, &keylen, &result, + &len); else - retval = yperr2nss ( yp_next (domain, "networks.byname", - oldkey, oldkeylen, - &outkey, &keylen, &result, &len)); + yperr = yp_next (domain, "networks.byname", oldkey, oldkeylen, &outkey, + &keylen, &result, &len); - if (retval != NSS_STATUS_SUCCESS) + if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) { + enum nss_status retval = yperr2nss (yperr); + if (retval == NSS_STATUS_TRYAGAIN) { *herrnop = NETDB_INTERNAL; @@ -103,7 +107,7 @@ internal_nis_getnetent_r (struct netent *net, char *buffer, size_t buflen, return retval; } - if ((size_t) (len + 1) > buflen) + if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) { free (result); *errnop = ERANGE; @@ -111,14 +115,14 @@ internal_nis_getnetent_r (struct netent *net, char *buffer, size_t buflen, return NSS_STATUS_TRYAGAIN; } - p = strncpy (buffer, result, len); + char *p = strncpy (buffer, result, len); buffer[len] = '\0'; while (isspace (*p)) ++p; free (result); parse_res = _nss_files_parse_netent (p, net, data, buflen, errnop); - if (parse_res == -1) + if (__builtin_expect (parse_res == -1, 0)) { free (outkey); *herrnop = NETDB_INTERNAL; @@ -155,11 +159,6 @@ enum nss_status _nss_nis_getnetbyname_r (const char *name, struct netent *net, char *buffer, size_t buflen, int *errnop, int *herrnop) { - enum nss_status retval; - struct parser_data *data = (void *) buffer; - char *domain, *result, *p; - int len, parse_res; - if (name == NULL) { *errnop = EINVAL; @@ -167,33 +166,36 @@ _nss_nis_getnetbyname_r (const char *name, struct netent *net, char *buffer, return NSS_STATUS_UNAVAIL; } - if (yp_get_default_domain (&domain)) + char *domain; + if (__builtin_expect (yp_get_default_domain (&domain), 0)) return NSS_STATUS_UNAVAIL; + struct parser_data *data = (void *) buffer; if (buflen < sizeof *data + 1) { *herrnop = NETDB_INTERNAL; *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } - else - { - /* 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'; + /* Convert name to lowercase. */ + size_t namlen = strlen (name); + char name2[namlen + 1]; + size_t i; - retval = yperr2nss (yp_match (domain, "networks.byname", name2, - namlen, &result, &len)); - } + for (i = 0; i < namlen; ++i) + name2[i] = _tolower (name[i]); + name2[i] = '\0'; + char *result; + int len; + int yperr = yp_match (domain, "networks.byname", name2, namlen, &result, + &len); - if (retval != NSS_STATUS_SUCCESS) + if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) { + enum nss_status retval = yperr2nss (yperr); + if (retval == NSS_STATUS_TRYAGAIN) { *errnop = errno; @@ -202,7 +204,7 @@ _nss_nis_getnetbyname_r (const char *name, struct netent *net, char *buffer, return retval; } - if ((size_t) (len + 1) > buflen) + if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) { free (result); *errnop = ERANGE; @@ -210,15 +212,15 @@ _nss_nis_getnetbyname_r (const char *name, struct netent *net, char *buffer, return NSS_STATUS_TRYAGAIN; } - p = strncpy (buffer, result, len); + char *p = strncpy (buffer, result, len); buffer[len] = '\0'; while (isspace (*p)) ++p; free (result); - parse_res = _nss_files_parse_netent (p, net, data, buflen, errnop); + int parse_res = _nss_files_parse_netent (p, net, data, buflen, errnop); - if (parse_res < 1) + if (__builtin_expect (parse_res < 1, 0)) { *herrnop = NETDB_INTERNAL; if (parse_res == -1) @@ -235,32 +237,26 @@ _nss_nis_getnetbyaddr_r (uint32_t addr, int type, struct netent *net, char *buffer, size_t buflen, int *errnop, int *herrnop) { - struct parser_data *data = (void *) buffer; char *domain; - char *result; - int len; - char buf[256]; - int blen; - struct in_addr in; - char *p; - - if (yp_get_default_domain (&domain)) + if (__builtin_expect (yp_get_default_domain (&domain), 0)) return NSS_STATUS_UNAVAIL; - in = inet_makeaddr (addr, 0); - strcpy (buf, inet_ntoa (in)); - blen = strlen (buf); + struct in_addr in = inet_makeaddr (addr, 0); + char *buf = inet_ntoa (in); + size_t blen = strlen (buf); while (1) { - enum nss_status retval; - int parse_res; + char *result; + int len; - retval = yperr2nss (yp_match (domain, "networks.byaddr", buf, - strlen (buf), &result, &len)); + int yperr = yp_match (domain, "networks.byaddr", buf, blen, &result, + &len); - if (retval != NSS_STATUS_SUCCESS) + if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) { + enum nss_status retval = yperr2nss (yperr); + if (retval == NSS_STATUS_NOTFOUND) { if (buf[blen - 2] == '.' && buf[blen - 1] == '0') @@ -282,7 +278,7 @@ _nss_nis_getnetbyaddr_r (uint32_t addr, int type, struct netent *net, } } - if ((size_t) (len + 1) > buflen) + if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) { free (result); *errnop = ERANGE; @@ -290,15 +286,16 @@ _nss_nis_getnetbyaddr_r (uint32_t addr, int type, struct netent *net, return NSS_STATUS_TRYAGAIN; } - p = strncpy (buffer, result, len); + char *p = strncpy (buffer, result, len); buffer[len] = '\0'; while (isspace (*p)) ++p; free (result); - parse_res = _nss_files_parse_netent (p, net, data, buflen, errnop); + int parse_res = _nss_files_parse_netent (p, net, (void *) buffer, + buflen, errnop); - if (parse_res < 1) + if (__builtin_expect (parse_res < 1, 0)) { *herrnop = NETDB_INTERNAL; if (parse_res == -1) diff --git a/nis/nss_nis/nis-proto.c b/nis/nss_nis/nis-proto.c index f1069283ab..1480a928b5 100644 --- a/nis/nss_nis/nis-proto.c +++ b/nis/nss_nis/nis-proto.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996-1998, 2000-2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 1996-1998, 2000-2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996. @@ -179,45 +179,46 @@ enum nss_status _nss_nis_getprotobyname_r (const char *name, struct protoent *proto, char *buffer, size_t buflen, int *errnop) { - struct parser_data *data = (void *) buffer; - enum nss_status retval; - char *domain, *result, *p; - int len, parse_res; - if (name == NULL) { *errnop = EINVAL; return NSS_STATUS_UNAVAIL; } - if (yp_get_default_domain (&domain)) + char *domain; + if (__builtin_expect (yp_get_default_domain (&domain), 0)) return NSS_STATUS_UNAVAIL; - retval = yperr2nss (yp_match (domain, "protocols.byname", name, - strlen (name), &result, &len)); + char *result; + int len; + int yperr = yp_match (domain, "protocols.byname", name, strlen (name), + &result, &len); - if (retval != NSS_STATUS_SUCCESS) + if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) { + enum nss_status retval = yperr2nss (yperr); + if (retval == NSS_STATUS_TRYAGAIN) *errnop = errno; return retval; } - if ((size_t) (len + 1) > buflen) + if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) { free (result); *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } - p = strncpy (buffer, result, len); + char *p = strncpy (buffer, result, len); buffer[len] = '\0'; while (isspace (*p)) ++p; free (result); - parse_res = _nss_files_parse_protoent (p, proto, data, buflen, errnop); - if (parse_res < 1) + int parse_res = _nss_files_parse_protoent (p, proto, (void *) buffer, buflen, + errnop); + if (__builtin_expect (parse_res < 1, 0)) { if (parse_res == -1) return NSS_STATUS_TRYAGAIN; @@ -231,42 +232,43 @@ enum nss_status _nss_nis_getprotobynumber_r (int number, struct protoent *proto, char *buffer, size_t buflen, int *errnop) { - struct parser_data *data = (void *) buffer; - enum nss_status retval; - char *domain, *result, *p; - int len, nlen, parse_res; - char buf[32]; - - if (yp_get_default_domain (&domain)) + char *domain; + if (__builtin_expect (yp_get_default_domain (&domain), 0)) return NSS_STATUS_UNAVAIL; - nlen = sprintf (buf, "%d", number); + char buf[32]; + int nlen = snprintf (buf, sizeof (buf), "%d", number); - retval = yperr2nss (yp_match (domain, "protocols.bynumber", buf, - nlen, &result, &len)); + char *result; + int len; + int yperr = yp_match (domain, "protocols.bynumber", buf, nlen, &result, + &len); - if (retval != NSS_STATUS_SUCCESS) + if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) { + enum nss_status retval = yperr2nss (yperr); + if (retval == NSS_STATUS_TRYAGAIN) *errnop = errno; return retval; } - if ((size_t) (len + 1) > buflen) + if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) { free (result); *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } - p = strncpy (buffer, result, len); + char *p = strncpy (buffer, result, len); buffer[len] = '\0'; while (isspace (*p)) ++p; free (result); - parse_res = _nss_files_parse_protoent (p, proto, data, buflen, errnop); - if (parse_res < 1) + int parse_res = _nss_files_parse_protoent (p, proto, (void *) buffer, buflen, + errnop); + if (__builtin_expect (parse_res < 1, 0)) { if (parse_res == -1) return NSS_STATUS_TRYAGAIN; diff --git a/nis/nss_nis/nis-publickey.c b/nis/nss_nis/nis-publickey.c index 6e92112d11..f58eb154ad 100644 --- a/nis/nss_nis/nis-publickey.c +++ b/nis/nss_nis/nis-publickey.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996,1997,1998,1999,2001,2002 Free Software Foundation, Inc. +/* Copyright (C) 1996-1999,2001,2002,2005,2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996. @@ -36,10 +36,6 @@ extern int xdecrypt (char *, char *); enum nss_status _nss_nis_getpublickey (const char *netname, char *pkey, int *errnop) { - enum nss_status retval; - char *domain, *result; - int len; - pkey[0] = 0; if (netname == NULL) @@ -48,19 +44,23 @@ _nss_nis_getpublickey (const char *netname, char *pkey, int *errnop) return NSS_STATUS_UNAVAIL; } - domain = strchr (netname, '@'); - if (!domain) + char *domain = strchr (netname, '@'); + if (domain == NULL) { *errnop = EINVAL; return NSS_STATUS_UNAVAIL; } ++domain; - retval = yperr2nss (yp_match (domain, "publickey.byname", netname, - strlen (netname), &result, &len)); + char *result; + int len; + int yperr = yp_match (domain, "publickey.byname", netname, strlen (netname), + &result, &len); - if (retval != NSS_STATUS_SUCCESS) + if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) { + enum nss_status retval = yperr2nss (yperr); + if (retval == NSS_STATUS_TRYAGAIN) *errnop = errno; return retval; @@ -73,6 +73,7 @@ _nss_nis_getpublickey (const char *netname, char *pkey, int *errnop) *p = 0; strncpy (pkey, result, HEXKEYBYTES + 1); pkey[HEXKEYBYTES] = '\0'; + free (result); } return NSS_STATUS_SUCCESS; } @@ -81,11 +82,6 @@ enum nss_status _nss_nis_getsecretkey (const char *netname, char *skey, char *passwd, int *errnop) { - enum nss_status retval; - char buf[2 * (HEXKEYBYTES + 1)]; - char *domain, *result; - int len; - skey[0] = 0; if (netname == NULL || passwd == NULL) @@ -94,19 +90,23 @@ _nss_nis_getsecretkey (const char *netname, char *skey, char *passwd, return NSS_STATUS_UNAVAIL; } - domain = strchr (netname, '@'); - if (!domain) + char *domain = strchr (netname, '@'); + if (domain == NULL) { *errnop = EINVAL; return NSS_STATUS_UNAVAIL; } ++domain; - retval = yperr2nss (yp_match (domain, "publickey.byname", netname, - strlen (netname), &result, &len)); + char *result; + int len; + int yperr = yp_match (domain, "publickey.byname", netname, strlen (netname), + &result, &len); - if (retval != NSS_STATUS_SUCCESS) + if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) { + enum nss_status retval = yperr2nss (yperr); + if (retval == NSS_STATUS_TRYAGAIN) *errnop = errno; return retval; @@ -115,20 +115,22 @@ _nss_nis_getsecretkey (const char *netname, char *skey, char *passwd, if (result != NULL) { char *p = strchr (result, ':'); - if (p == NULL) - return NSS_STATUS_SUCCESS; - - ++p; - strncpy (buf, p, 2 * (HEXKEYBYTES + 1)); - buf[2 * (HEXKEYBYTES + 1)] = '\0'; - if (!xdecrypt (buf, passwd)) - return NSS_STATUS_SUCCESS; - - if (memcmp (buf, &(buf[HEXKEYBYTES]), KEYCHECKSUMSIZE) != 0) - return NSS_STATUS_SUCCESS; - - buf[HEXKEYBYTES] = '\0'; - strcpy (skey, buf); + if (p != NULL) + { + char buf[2 * (HEXKEYBYTES + 1)]; + + ++p; + strncpy (buf, p, 2 * (HEXKEYBYTES + 1)); + buf[2 * HEXKEYBYTES + 1] = '\0'; + if (xdecrypt (buf, passwd) + && memcmp (buf, &(buf[HEXKEYBYTES]), KEYCHECKSUMSIZE) == 0) + { + buf[HEXKEYBYTES] = '\0'; + strcpy (skey, buf); + } + } + + free (result); } return NSS_STATUS_SUCCESS; } @@ -194,13 +196,8 @@ enum nss_status _nss_nis_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp, gid_t *gidp, int *gidlenp, gid_t *gidlist, int *errnop) { - char *domain; - int yperr; - char *lookup; - int len; - - domain = strchr (netname, '@'); - if (!domain) + char *domain = strchr (netname, '@'); + if (domain == NULL) { *errnop = EINVAL; return NSS_STATUS_UNAVAIL; @@ -208,9 +205,10 @@ _nss_nis_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp, /* Point past the '@' character */ ++domain; - lookup = NULL; - yperr = yp_match (domain, "netid.byname", netname, strlen (netname), - &lookup, &len); + char *lookup = NULL; + int len; + int yperr = yp_match (domain, "netid.byname", netname, strlen (netname), + &lookup, &len); switch (yperr) { case YPERR_SUCCESS: @@ -223,17 +221,15 @@ _nss_nis_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp, return NSS_STATUS_UNAVAIL; } - if (lookup) - { - enum nss_status err; - - lookup[len] = '\0'; - err = parse_netid_str (lookup, uidp, gidp, gidlenp, gidlist); - free (lookup); - return err; - } - else + if (lookup == NULL) return NSS_STATUS_NOTFOUND; - return NSS_STATUS_SUCCESS; + + lookup[len] = '\0'; + + enum nss_status err = parse_netid_str (lookup, uidp, gidp, gidlenp, gidlist); + + free (lookup); + + return err; } diff --git a/nis/nss_nis/nis-pwd.c b/nis/nss_nis/nis-pwd.c index 0f56ced014..1b5206ad6d 100644 --- a/nis/nss_nis/nis-pwd.c +++ b/nis/nss_nis/nis-pwd.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996-1998, 2001, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1996-1998,2001,2002,2003,2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. @@ -17,20 +17,18 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include <nss.h> -/* The following is an ugly trick to avoid a prototype declaration for - _nss_nis_endpwent. */ -#define _nss_nis_endpwent _nss_nis_endpwent_XXX -#include <pwd.h> -#undef _nss_nis_endpwent +#include <assert.h> #include <ctype.h> #include <errno.h> +#include <nss.h> +#include <pwd.h> #include <string.h> #include <bits/libc-lock.h> #include <rpcsvc/yp.h> #include <rpcsvc/ypclnt.h> #include "nss-nis.h" +#include <libnsl.h> /* Get the declaration of the parser function. */ #define ENTNAME pwent @@ -44,12 +42,72 @@ __libc_lock_define_initialized (static, lock) static bool_t new_start = 1; static char *oldkey; static int oldkeylen; +static intern_t intern; -enum nss_status -_nss_nis_setpwent (int stayopen) + +int +_nis_saveit (int instatus, char *inkey, int inkeylen, char *inval, + int invallen, char *indata) { - __libc_lock_lock (lock); + intern_t *intern = (intern_t *) indata; + + if (instatus != YP_TRUE) + return 1; + + if (inkey && inkeylen > 0 && inval && invallen > 0) + { + struct response_t *bucket = intern->next; + if (__builtin_expect (bucket == NULL, 0)) + { +#define MINSIZE 4096 - 4 * sizeof (void *) + const size_t minsize = MAX (MINSIZE, 2 * (invallen + 1)); + bucket = malloc (sizeof (struct response_t) + minsize); + if (bucket == NULL) + /* We have no error code for out of memory. */ + return 1; + + bucket->next = NULL; + bucket->size = minsize; + intern->start = intern->next = bucket; + intern->offset = 0; + } + else if (__builtin_expect (invallen + 1 > bucket->size - intern->offset, + 0)) + { + /* We need a new (larger) buffer. */ + const size_t newsize = 2 * MAX (bucket->size, invallen + 1); + struct response_t *newp = malloc (sizeof (struct response_t) + + newsize); + if (newp == NULL) + /* We have no error code for out of memory. */ + return 1; + + /* Mark the old bucket as full. */ + bucket->size = intern->offset; + + newp->next = NULL; + newp->size = newsize; + bucket = intern->next = bucket->next = newp; + intern->offset = 0; + } + + char *p = mempcpy (&bucket->mem[intern->offset], inval, invallen); + if (__builtin_expect (p[-1] != '\0', 0)) + { + *p = '\0'; + ++invallen; + } + intern->offset += invallen; + } + + return 0; +} + + +static void +internal_nis_endpwent (void) +{ new_start = 1; if (oldkey != NULL) { @@ -58,52 +116,159 @@ _nss_nis_setpwent (int stayopen) oldkeylen = 0; } + struct response_t *curr = intern.next; + + while (curr != NULL) + { + struct response_t *last = curr; + curr = curr->next; + free (last); + } + + intern.next = intern.start = NULL; +} + + +enum nss_status +_nss_nis_endpwent (void) +{ + __libc_lock_lock (lock); + + internal_nis_endpwent (); + __libc_lock_unlock (lock); return NSS_STATUS_SUCCESS; } -/* Make _nss_nis_endpwent an alias of _nss_nis_setpwent. We do this - even though the prototypes don't match. The argument of setpwent - is not used so this makes no difference. */ -strong_alias (_nss_nis_setpwent, _nss_nis_endpwent) + + +enum nss_status +internal_nis_setpwent (void) +{ + /* We have to read all the data now. */ + char *domain; + if (__builtin_expect (yp_get_default_domain (&domain), 0)) + return NSS_STATUS_UNAVAIL; + + struct ypall_callback ypcb; + + ypcb.foreach = _nis_saveit; + ypcb.data = (char *) &intern; + enum nss_status status = yperr2nss (yp_all (domain, "passwd.byname", &ypcb)); + + + /* Mark the last buffer as full. */ + if (intern.next != NULL) + intern.next->size = intern.offset; + + intern.next = intern.start; + intern.offset = 0; + + return status; +} + + +enum nss_status +_nss_nis_setpwent (int stayopen) +{ + enum nss_status result = NSS_STATUS_SUCCESS; + + __libc_lock_lock (lock); + + internal_nis_endpwent (); + + if (_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ) + result = internal_nis_setpwent (); + + __libc_lock_unlock (lock); + + return result; +} + static enum nss_status internal_nis_getpwent_r (struct passwd *pwd, char *buffer, size_t buflen, int *errnop) { - struct parser_data *data = (void *) buffer; - char *domain; - int parse_res; + /* If we read the entire database at setpwent time we just iterate + over the data we have in memory. */ + bool batch_read = intern.start != NULL; - if (yp_get_default_domain (&domain)) + char *domain = NULL; + if (!batch_read && __builtin_expect (yp_get_default_domain (&domain), 0)) return NSS_STATUS_UNAVAIL; /* Get the next entry until we found a correct one. */ + int parse_res; do { - enum nss_status retval; - char *result, *outkey, *result2, *p; - int len, keylen, len2; - size_t namelen; + char *result; + char *outkey; + int len; + int keylen; + + if (batch_read) + { + struct response_t *bucket; + + handle_batch_read: + bucket = intern.next; - if (new_start) - retval = yperr2nss (yp_first (domain, "passwd.byname", - &outkey, &keylen, &result, &len)); + if (__builtin_expect (intern.offset >= bucket->size, 0)) + { + if (bucket->next == NULL) + return NSS_STATUS_NOTFOUND; + + /* We look at all the content in the current bucket. Go on + to the next. */ + bucket = intern.next = bucket->next; + intern.offset = 0; + } + + for (result = &bucket->mem[intern.offset]; isspace (*result); + ++result) + ++intern.offset; + + len = strlen (result); + } else - retval = yperr2nss ( yp_next (domain, "passwd.byname", - oldkey, oldkeylen, - &outkey, &keylen, &result, &len)); + { + int yperr; - if (retval != NSS_STATUS_SUCCESS) - { - if (retval == NSS_STATUS_TRYAGAIN) - *errnop = errno; - return retval; - } + if (new_start) + { + /* Maybe we should read the database in one piece. */ + if ((_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ) + && internal_nis_setpwent () == NSS_STATUS_SUCCESS + && intern.start != NULL) + { + batch_read = true; + goto handle_batch_read; + } + + yperr = yp_first (domain, "passwd.byname", &outkey, &keylen, + &result, &len); + } + else + yperr = yp_next (domain, "passwd.byname", oldkey, oldkeylen, + &outkey, &keylen, &result, &len); + + if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) + { + enum nss_status retval = yperr2nss (yperr); + + if (retval == NSS_STATUS_TRYAGAIN) + *errnop = errno; + return retval; + } + } /* Check for adjunct style secret passwords. They can be recognized by a password starting with "##". */ - p = strchr (result, ':'); + char *p = strchr (result, ':'); + size_t namelen; + char *result2; + int len2; if (p != NULL /* This better should be true in all cases. */ && p[1] == '#' && p[2] == '#' && (namelen = p - result, @@ -128,7 +293,8 @@ internal_nis_getpwent_r (struct passwd *pwd, char *buffer, size_t buflen, } restlen = len - (p - result); - if ((size_t) (namelen + (endp - encrypted) + restlen + 2) > buflen) + if (__builtin_expect ((size_t) (namelen + (endp - encrypted) + + restlen + 2) > buflen, 0)) { free (result2); free (result); @@ -136,10 +302,10 @@ internal_nis_getpwent_r (struct passwd *pwd, char *buffer, size_t buflen, return NSS_STATUS_TRYAGAIN; } - __mempcpy (__mempcpy (__mempcpy (__mempcpy (buffer, result, namelen), - ":", 1), - encrypted, endp - encrypted), - p, restlen + 1); + mempcpy (mempcpy (mempcpy (mempcpy (buffer, result, namelen), + ":", 1), + encrypted, endp - encrypted), + p, restlen + 1); p = buffer; free (result2); @@ -147,33 +313,41 @@ internal_nis_getpwent_r (struct passwd *pwd, char *buffer, size_t buflen, else { non_adjunct: - if ((size_t) (len + 1) > buflen) + if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) { free (result); *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } - p = strncpy (buffer, result, len); - buffer[len] = '\0'; + p = buffer; + *((char *) mempcpy (buffer, result, len)) = '\0'; } while (isspace (*p)) ++p; - free (result); + if (!batch_read) + free (result); - parse_res = _nss_files_parse_pwent (p, pwd, data, buflen, errnop); - if (parse_res == -1) + parse_res = _nss_files_parse_pwent (p, pwd, (void *) buffer, buflen, + errnop); + if (__builtin_expect (parse_res == -1, 0)) { - free (outkey); + if (!batch_read) + free (outkey); *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } - free (oldkey); - oldkey = outkey; - oldkeylen = keylen; - new_start = 0; + if (batch_read) + intern.offset += len + 1; + else + { + free (oldkey); + oldkey = outkey; + oldkeylen = keylen; + new_start = 0; + } } while (parse_res < 1); @@ -199,28 +373,26 @@ enum nss_status _nss_nis_getpwnam_r (const char *name, struct passwd *pwd, char *buffer, size_t buflen, int *errnop) { - struct parser_data *data = (void *) buffer; - enum nss_status retval; - char *domain, *result, *result2, *p; - int len, len2, parse_res; - size_t namelen; - if (name == NULL) { *errnop = EINVAL; return NSS_STATUS_UNAVAIL; } - if (yp_get_default_domain (&domain)) + char *domain; + if (__builtin_expect (yp_get_default_domain (&domain), 0)) return NSS_STATUS_UNAVAIL; - namelen = strlen (name); + size_t namelen = strlen (name); - retval = yperr2nss (yp_match (domain, "passwd.byname", name, - namelen, &result, &len)); + char *result; + int len; + int yperr = yp_match (domain, "passwd.byname", name, namelen, &result, &len); - if (retval != NSS_STATUS_SUCCESS) + if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) { + enum nss_status retval = yperr2nss (yperr); + if (retval == NSS_STATUS_TRYAGAIN) *errnop = errno; return retval; @@ -228,7 +400,9 @@ _nss_nis_getpwnam_r (const char *name, struct passwd *pwd, /* Check for adjunct style secret passwords. They can be recognized by a password starting with "##". */ - p = strchr (result, ':'); + char *result2; + int len2; + char *p = strchr (result, ':'); if (p != NULL /* This better should be true in all cases. */ && p[1] == '#' && p[2] == '#' && yp_match (domain, "passwd.adjunct.byname", name, namelen, @@ -238,7 +412,6 @@ _nss_nis_getpwnam_r (const char *name, struct passwd *pwd, therein into original result. */ char *encrypted = strchr (result2, ':'); char *endp; - size_t restlen; if (encrypted == NULL || (endp = strchr (++encrypted, ':')) == NULL @@ -251,8 +424,9 @@ _nss_nis_getpwnam_r (const char *name, struct passwd *pwd, goto non_adjunct; } - restlen = len - (p - result); - if ((size_t) (namelen + (endp - encrypted) + restlen + 2) > buflen) + size_t restlen = len - (p - result); + if (__builtin_expect ((size_t) (namelen + (endp - encrypted) + + restlen + 2) > buflen, 0)) { free (result2); free (result); @@ -271,7 +445,7 @@ _nss_nis_getpwnam_r (const char *name, struct passwd *pwd, else { non_adjunct: - if ((size_t) (len + 1) > buflen) + if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) { free (result); *errnop = ERANGE; @@ -286,8 +460,9 @@ _nss_nis_getpwnam_r (const char *name, struct passwd *pwd, ++p; free (result); - parse_res = _nss_files_parse_pwent (p, pwd, data, buflen, errnop); - if (parse_res < 1) + int parse_res = _nss_files_parse_pwent (p, pwd, (void *) buffer, buflen, + errnop); + if (__builtin_expect (parse_res < 1, 0)) { if (parse_res == -1) return NSS_STATUS_TRYAGAIN; @@ -302,23 +477,21 @@ enum nss_status _nss_nis_getpwuid_r (uid_t uid, struct passwd *pwd, char *buffer, size_t buflen, int *errnop) { - struct parser_data *data = (void *) buffer; - enum nss_status retval; - char *domain, *result, *p, *result2; - int len, nlen, parse_res, len2; - char buf[32]; - size_t namelen; - - if (yp_get_default_domain (&domain)) + char *domain; + if (__builtin_expect (yp_get_default_domain (&domain), 0)) return NSS_STATUS_UNAVAIL; - nlen = sprintf (buf, "%lu", (unsigned long int) uid); + char buf[32]; + int nlen = snprintf (buf, sizeof (buf), "%lu", (unsigned long int) uid); - retval = yperr2nss (yp_match (domain, "passwd.byuid", buf, - nlen, &result, &len)); + char *result; + int len; + int yperr = yp_match (domain, "passwd.byuid", buf, nlen, &result, &len); - if (retval != NSS_STATUS_SUCCESS) + if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) { + enum nss_status retval = yperr2nss (yperr); + if (retval == NSS_STATUS_TRYAGAIN) *errnop = errno; return retval; @@ -326,7 +499,10 @@ _nss_nis_getpwuid_r (uid_t uid, struct passwd *pwd, /* Check for adjunct style secret passwords. They can be recognized by a password starting with "##". */ - p = strchr (result, ':'); + char *result2; + int len2; + size_t namelen; + char *p = strchr (result, ':'); if (p != NULL /* This better should be true in all cases. */ && p[1] == '#' && p[2] == '#' && (namelen = p - result, @@ -351,7 +527,8 @@ _nss_nis_getpwuid_r (uid_t uid, struct passwd *pwd, } restlen = len - (p - result); - if ((size_t) (namelen + (endp - encrypted) + restlen + 2) > buflen) + if (__builtin_expect ((size_t) (namelen + (endp - encrypted) + + restlen + 2) > buflen, 0)) { free (result2); free (result); @@ -370,7 +547,7 @@ _nss_nis_getpwuid_r (uid_t uid, struct passwd *pwd, else { non_adjunct: - if ((size_t) (len + 1) > buflen) + if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) { free (result); *errnop = ERANGE; @@ -385,8 +562,9 @@ _nss_nis_getpwuid_r (uid_t uid, struct passwd *pwd, ++p; free (result); - parse_res = _nss_files_parse_pwent (p, pwd, data, buflen, errnop); - if (parse_res < 1) + int parse_res = _nss_files_parse_pwent (p, pwd, (void *) buffer, buflen, + errnop); + if (__builtin_expect (parse_res < 1, 0)) { if (parse_res == -1) return NSS_STATUS_TRYAGAIN; diff --git a/nis/nss_nis/nis-rpc.c b/nis/nss_nis/nis-rpc.c index d1ab94371a..2fdb16ddde 100644 --- a/nis/nss_nis/nis-rpc.c +++ b/nis/nss_nis/nis-rpc.c @@ -1,4 +1,5 @@ -/* Copyright (C) 1996-1998,2000,2002,2003,2004 Free Software Foundation, Inc. +/* Copyright (C) 1996-1998,2000,2002,2003,2004,2006 + Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996. @@ -35,59 +36,22 @@ __libc_lock_define_initialized (static, lock) -struct response_t -{ - struct response_t *next; - char val[0]; -}; - -struct intern_t -{ - struct response_t *start; - struct response_t *next; -}; -typedef struct intern_t intern_t; - -static intern_t intern = {NULL, NULL}; - -static int -saveit (int instatus, char *inkey, int inkeylen, char *inval, - int invallen, char *indata) -{ - intern_t *intern = (intern_t *)indata; - - if (instatus != YP_TRUE) - return 1; - - if (inkey && inkeylen > 0 && inval && invallen > 0) - { - struct response_t *newp = malloc (sizeof (struct response_t) - + invallen + 1); - if (newp == NULL) - return 1; /* We have no error code for out of memory */ - - if (intern->start == NULL) - intern->start = newp; - else - intern->next->next = newp; - intern->next = newp; +static intern_t intern; - newp->next = NULL; - *((char *) mempcpy (newp->val, inval, invallen)) = '\0'; - } - - return 0; -} static void internal_nis_endrpcent (intern_t *intern) { - while (intern->start != NULL) + struct response_t *curr = intern->next; + + while (curr != NULL) { - intern->next = intern->start; - intern->start = intern->start->next; - free (intern->next); + struct response_t *last = curr; + curr = curr->next; + free (last); } + + intern->next = intern->start = NULL; } static enum nss_status @@ -102,10 +66,16 @@ internal_nis_setrpcent (intern_t *intern) internal_nis_endrpcent (intern); - ypcb.foreach = saveit; - ypcb.data = (char *)intern; - status = yperr2nss (yp_all(domainname, "rpc.bynumber", &ypcb)); + ypcb.foreach = _nis_saveit; + ypcb.data = (char *) intern; + status = yperr2nss (yp_all (domainname, "rpc.bynumber", &ypcb)); + + /* Mark the last buffer as full. */ + if (intern->next != NULL) + intern->next->size = intern->offset; + intern->next = intern->start; + intern->offset = 0; return status; } @@ -138,29 +108,60 @@ _nss_nis_endrpcent (void) static enum nss_status internal_nis_getrpcent_r (struct rpcent *rpc, char *buffer, size_t buflen, - int *errnop, intern_t *data) + int *errnop, intern_t *intern) { struct parser_data *pdata = (void *) buffer; int parse_res; char *p; - if (data->start == NULL) - internal_nis_setrpcent (data); + if (intern->start == NULL) + internal_nis_setrpcent (intern); + + if (intern->next == NULL) + /* Not one entry in the map. */ + return NSS_STATUS_NOTFOUND; /* Get the next entry until we found a correct one. */ do { - if (data->next == NULL) - return NSS_STATUS_NOTFOUND; + struct response_t *bucket = intern->next; - p = strncpy (buffer, data->next->val, buflen); - while (isspace (*p)) - ++p; + if (__builtin_expect (intern->offset >= bucket->size, 0)) + { + if (bucket->next == NULL) + return NSS_STATUS_NOTFOUND; + + /* We look at all the content in the current bucket. Go on + to the next. */ + bucket = intern->next = bucket->next; + intern->offset = 0; + } + + for (p = &bucket->mem[intern->offset]; isspace (*p); ++p) + ++intern->offset; + + size_t len = strlen (p) + 1; + if (__builtin_expect (len > buflen, 0)) + { + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; + } + + /* We unfortunately have to copy the data in the user-provided + buffer because that buffer might be around for a very long + time and the servent structure must remain valid. If we would + rely on the BUCKET memory the next 'setservent' or 'endservent' + call would destroy it. + + The important thing is that it is a single NUL-terminated + string. This is what the parsing routine expects. */ + p = memcpy (buffer, &bucket->mem[intern->offset], len); parse_res = _nss_files_parse_rpcent (p, rpc, pdata, buflen, errnop); - if (parse_res == -1) + if (__builtin_expect (parse_res == -1, 0)) return NSS_STATUS_TRYAGAIN; - data->next = data->next->next; + + intern->offset += len; } while (!parse_res); @@ -186,21 +187,18 @@ enum nss_status _nss_nis_getrpcbyname_r (const char *name, struct rpcent *rpc, char *buffer, size_t buflen, int *errnop) { - intern_t data = {NULL, NULL}; - enum nss_status status; - int found; - if (name == NULL) { *errnop = EINVAL; return NSS_STATUS_UNAVAIL; } - status = internal_nis_setrpcent (&data); - if (status != NSS_STATUS_SUCCESS) + intern_t data = { NULL, NULL, 0 }; + enum nss_status status = internal_nis_setrpcent (&data); + if (__builtin_expect (status != NSS_STATUS_SUCCESS, 0)) return status; - found = 0; + int found = 0; while (!found && ((status = internal_nis_getrpcent_r (rpc, buffer, buflen, errnop, &data)) == NSS_STATUS_SUCCESS)) @@ -226,53 +224,52 @@ _nss_nis_getrpcbyname_r (const char *name, struct rpcent *rpc, internal_nis_endrpcent (&data); - if (!found && status == NSS_STATUS_SUCCESS) + if (__builtin_expect (!found && status == NSS_STATUS_SUCCESS, 0)) return NSS_STATUS_NOTFOUND; - else - return status; + + return status; } enum nss_status _nss_nis_getrpcbynumber_r (int number, struct rpcent *rpc, char *buffer, size_t buflen, int *errnop) { - struct parser_data *data = (void *) buffer; - enum nss_status retval; - char *domain, *result, *p; - int len, nlen, parse_res; - char buf[32]; - - if (yp_get_default_domain (&domain)) + char *domain; + if (__builtin_expect (yp_get_default_domain (&domain), 0)) return NSS_STATUS_UNAVAIL; - nlen = sprintf (buf, "%d", number); + char buf[32]; + int nlen = snprintf (buf, sizeof (buf), "%d", number); - retval = yperr2nss (yp_match (domain, "rpc.bynumber", buf, - nlen, &result, &len)); + char *result; + int len; + int yperr = yp_match (domain, "rpc.bynumber", buf, nlen, &result, &len); - if (retval != NSS_STATUS_SUCCESS) + if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) { + enum nss_status retval = yperr2nss (yperr); + if (retval == NSS_STATUS_TRYAGAIN) *errnop = errno; return retval; } - if ((size_t) (len + 1) > buflen) + if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) { free (result); *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } - p = strncpy (buffer, result, len); + char *p = strncpy (buffer, result, len); buffer[len] = '\0'; while (isspace (*p)) ++p; free (result); - parse_res = _nss_files_parse_rpcent (p, rpc, data, buflen, errnop); - - if (parse_res < 1) + int parse_res = _nss_files_parse_rpcent (p, rpc, (void *) buffer, buflen, + errnop); + if (__builtin_expect (parse_res < 1, 0)) { if (parse_res == -1) return NSS_STATUS_TRYAGAIN; diff --git a/nis/nss_nis/nis-service.c b/nis/nss_nis/nis-service.c index 1e879d04e3..59a598f296 100644 --- a/nis/nss_nis/nis-service.c +++ b/nis/nss_nis/nis-service.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996-2001, 2002, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 1996-2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996. @@ -27,6 +27,7 @@ #include <rpcsvc/ypclnt.h> #include "nss-nis.h" +#include <libnsl.h> /* Get the declaration of the parser function. */ @@ -36,20 +37,7 @@ __libc_lock_define_initialized (static, lock) -struct response_t -{ - struct response_t *next; - char val[0]; -}; - -struct intern_t -{ - struct response_t *start; - struct response_t *next; -}; -typedef struct intern_t intern_t; - -static intern_t intern = { NULL, NULL }; +static intern_t intern; struct search_t { @@ -64,63 +52,31 @@ struct search_t }; static int -saveit (int instatus, char *inkey, int inkeylen, char *inval, - int invallen, char *indata) -{ - intern_t *intern = (intern_t *) indata; - - if (instatus != YP_TRUE) - return 1; - - if (inkey && inkeylen > 0 && inval && invallen > 0) - { - struct response_t *newp = malloc (sizeof (struct response_t) - + invallen + 1); - if (newp == NULL) - return 1; /* We have no error code for out of memory */ - - if (intern->start == NULL) - intern->start = newp; - else - intern->next->next = newp; - intern->next = newp; - - newp->next = NULL; - *((char *) mempcpy (newp->val, inval, invallen)) = '\0'; - } - - return 0; -} - -static int dosearch (int instatus, char *inkey, int inkeylen, char *inval, int invallen, char *indata) { struct search_t *req = (struct search_t *) indata; - if (instatus != YP_TRUE) + if (__builtin_expect (instatus != YP_TRUE, 0)) return 1; if (inkey && inkeylen > 0 && inval && invallen > 0) { - struct parser_data *pdata = (void *) req->buffer; - int parse_res; - char *p; - - if ((size_t) (invallen + 1) > req->buflen) + if (__builtin_expect ((size_t) (invallen + 1) > req->buflen, 0)) { *req->errnop = ERANGE; req->status = NSS_STATUS_TRYAGAIN; return 1; } - p = strncpy (req->buffer, inval, invallen); + char *p = strncpy (req->buffer, inval, invallen); req->buffer[invallen] = '\0'; while (isspace (*p)) ++p; - parse_res = _nss_files_parse_servent (p, req->serv, pdata, req->buflen, - req->errnop); + int parse_res = _nss_files_parse_servent (p, req->serv, + (void *) req->buffer, + req->buflen, req->errnop); if (parse_res == -1) { req->status = NSS_STATUS_TRYAGAIN; @@ -154,35 +110,35 @@ dosearch (int instatus, char *inkey, int inkeylen, char *inval, return 0; } -static enum nss_status -internal_nis_endservent (intern_t * intern) +static void +internal_nis_endservent (void) { - while (intern->start != NULL) + struct response_t *curr = intern.next; + + while (curr != NULL) { - intern->next = intern->start; - intern->start = intern->start->next; - free (intern->next); + struct response_t *last = curr; + curr = curr->next; + free (last); } - return NSS_STATUS_SUCCESS; + intern.next = intern.start = NULL; } enum nss_status _nss_nis_endservent (void) { - enum nss_status status; - __libc_lock_lock (lock); - status = internal_nis_endservent (&intern); + internal_nis_endservent (); __libc_lock_unlock (lock); - return status; + return NSS_STATUS_SUCCESS; } static enum nss_status -internal_nis_setservent (intern_t *intern) +internal_nis_setservent (void) { char *domainname; struct ypall_callback ypcb; @@ -191,12 +147,18 @@ internal_nis_setservent (intern_t *intern) if (yp_get_default_domain (&domainname)) return NSS_STATUS_UNAVAIL; - (void) internal_nis_endservent (intern); + internal_nis_endservent (); - ypcb.foreach = saveit; - ypcb.data = (char *) intern; + ypcb.foreach = _nis_saveit; + ypcb.data = (char *) &intern; status = yperr2nss (yp_all (domainname, "services.byname", &ypcb)); - intern->next = intern->start; + + /* Mark the last buffer as full. */ + if (intern.next != NULL) + intern.next->size = intern.offset; + + intern.next = intern.start; + intern.offset = 0; return status; } @@ -208,7 +170,7 @@ _nss_nis_setservent (int stayopen) __libc_lock_lock (lock); - status = internal_nis_setservent (&intern); + status = internal_nis_setservent (); __libc_lock_unlock (lock); @@ -217,29 +179,60 @@ _nss_nis_setservent (int stayopen) static enum nss_status internal_nis_getservent_r (struct servent *serv, char *buffer, - size_t buflen, int *errnop, intern_t *data) + size_t buflen, int *errnop) { struct parser_data *pdata = (void *) buffer; int parse_res; char *p; - if (data->start == NULL) - internal_nis_setservent (data); + if (intern.start == NULL) + internal_nis_setservent (); - /* Get the next entry until we found a correct one. */ + if (intern.next == NULL) + /* Not one entry in the map. */ + return NSS_STATUS_NOTFOUND; + + /* Get the next entry until we found a correct one. */ do { - if (data->next == NULL) - return NSS_STATUS_NOTFOUND; + struct response_t *bucket = intern.next; - p = strncpy (buffer, data->next->val, buflen); - while (isspace (*p)) - ++p; + if (__builtin_expect (intern.offset >= bucket->size, 0)) + { + if (bucket->next == NULL) + return NSS_STATUS_NOTFOUND; + + /* We look at all the content in the current bucket. Go on + to the next. */ + bucket = intern.next = bucket->next; + intern.offset = 0; + } + + for (p = &bucket->mem[intern.offset]; isspace (*p); ++p) + ++intern.offset; + + size_t len = strlen (p) + 1; + if (__builtin_expect (len > buflen, 0)) + { + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; + } + + /* We unfortunately have to copy the data in the user-provided + buffer because that buffer might be around for a very long + time and the servent structure must remain valid. If we would + rely on the BUCKET memory the next 'setservent' or 'endservent' + call would destroy it. + + The important thing is that it is a single NUL-terminated + string. This is what the parsing routine expects. */ + p = memcpy (buffer, &bucket->mem[intern.offset], len); parse_res = _nss_files_parse_servent (p, serv, pdata, buflen, errnop); - if (parse_res == -1) + if (__builtin_expect (parse_res == -1, 0)) return NSS_STATUS_TRYAGAIN; - data->next = data->next->next; + + intern.offset += len; } while (!parse_res); @@ -254,7 +247,7 @@ _nss_nis_getservent_r (struct servent *serv, char *buffer, size_t buflen, __libc_lock_lock (lock); - status = internal_nis_getservent_r (serv, buffer, buflen, errnop, &intern); + status = internal_nis_getservent_r (serv, buffer, buflen, errnop); __libc_lock_unlock (lock); @@ -266,60 +259,55 @@ _nss_nis_getservbyname_r (const char *name, const char *protocol, struct servent *serv, char *buffer, size_t buflen, int *errnop) { - enum nss_status status; - char *domain; - if (name == NULL) { *errnop = EINVAL; return NSS_STATUS_UNAVAIL; } - if (yp_get_default_domain (&domain)) + char *domain; + if (__builtin_expect (yp_get_default_domain (&domain), 0)) return NSS_STATUS_UNAVAIL; /* If the protocol is given, we could try if our NIS server knows about services.byservicename map. If yes, we only need one query. */ - char key[strlen (name) + (protocol ? strlen (protocol) : 0) + 2]; - char *cp, *result; - size_t keylen, len; - int int_len; + size_t keylen = strlen (name) + (protocol ? 1 + strlen (protocol) : 0); + char key[keylen + 1]; /* key is: "name/proto" */ - cp = stpcpy (key, name); - if (protocol) + char *cp = stpcpy (key, name); + if (protocol != NULL) { *cp++ = '/'; strcpy (cp, protocol); } - keylen = strlen (key); - status = yperr2nss (yp_match (domain, "services.byservicename", key, - keylen, &result, &int_len)); - len = int_len; + + char *result; + int int_len; + int status = yp_match (domain, "services.byservicename", key, + keylen, &result, &int_len); + size_t len = int_len; /* If we found the key, it's ok and parse the result. If not, fall through and parse the complete table. */ - if (status == NSS_STATUS_SUCCESS) + if (__builtin_expect (status == YPERR_SUCCESS, 1)) { - struct parser_data *pdata = (void *) buffer; - int parse_res; - char *p; - - if ((size_t) (len + 1) > buflen) + if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) { free (result); *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } - p = strncpy (buffer, result, len); + char *p = strncpy (buffer, result, len); buffer[len] = '\0'; while (isspace (*p)) ++p; free (result); - parse_res = _nss_files_parse_servent (p, serv, pdata, - buflen, errnop); - if (parse_res < 0) + + int parse_res = _nss_files_parse_servent (p, serv, (void *) buffer, + buflen, errnop); + if (__builtin_expect (parse_res < 0, 0)) { if (parse_res == -1) return NSS_STATUS_TRYAGAIN; @@ -331,8 +319,8 @@ _nss_nis_getservbyname_r (const char *name, const char *protocol, } /* Check if it is safe to rely on services.byservicename. */ - if (_nis_default_nss () & NSS_FLAG_SERVICES_AUTHORITATIVE) - return status; + if (_nsl_default_nss () & NSS_FLAG_SERVICES_AUTHORITATIVE) + return yperr2nss (status); struct ypall_callback ypcb; struct search_t req; @@ -347,10 +335,10 @@ _nss_nis_getservbyname_r (const char *name, const char *protocol, req.buflen = buflen; req.errnop = errnop; req.status = NSS_STATUS_NOTFOUND; - status = yperr2nss (yp_all (domain, "services.byname", &ypcb)); + status = yp_all (domain, "services.byname", &ypcb); - if (status != NSS_STATUS_SUCCESS) - return status; + if (__builtin_expect (status != YPERR_SUCCESS, 0)) + return yperr2nss (status); return req.status; } @@ -360,10 +348,8 @@ _nss_nis_getservbyport_r (int port, const char *protocol, struct servent *serv, char *buffer, size_t buflen, int *errnop) { - enum nss_status status; char *domain; - - if (yp_get_default_domain (&domain)) + if (__builtin_expect (yp_get_default_domain (&domain), 0)) return NSS_STATUS_UNAVAIL; /* If the protocol is given, we only need one query. @@ -372,48 +358,44 @@ _nss_nis_getservbyport_r (int port, const char *protocol, const char *proto = protocol != NULL ? protocol : "tcp"; do { + /* key is: "port/proto" */ char key[sizeof (int) * 3 + strlen (proto) + 2]; + size_t keylen = snprintf (key, sizeof (key), "%d/%s", ntohs (port), + proto); + char *result; - size_t keylen, len; int int_len; - - /* key is: "port/proto" */ - keylen = snprintf (key, sizeof (key), "%d/%s", ntohs (port), proto); - status = yperr2nss (yp_match (domain, "services.byname", key, - keylen, &result, &int_len)); - len = int_len; + int status = yp_match (domain, "services.byname", key, keylen, &result, + &int_len); + size_t len = int_len; /* If we found the key, it's ok and parse the result. If not, fall through and parse the complete table. */ - if (status == NSS_STATUS_SUCCESS) + if (__builtin_expect (status == YPERR_SUCCESS, 1)) { - struct parser_data *pdata = (void *) buffer; - int parse_res; - char *p; - - if ((size_t) (len + 1) > buflen) + if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) { free (result); *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } - p = strncpy (buffer, result, len); + char *p = strncpy (buffer, result, len); buffer[len] = '\0'; while (isspace (*p)) ++p; free (result); - parse_res = _nss_files_parse_servent (p, serv, pdata, - buflen, errnop); - if (parse_res < 0) + int parse_res = _nss_files_parse_servent (p, serv, (void *) buffer, + buflen, errnop); + if (__builtin_expect (parse_res < 0, 0)) { if (parse_res == -1) return NSS_STATUS_TRYAGAIN; else return NSS_STATUS_NOTFOUND; } - else - return NSS_STATUS_SUCCESS; + + return NSS_STATUS_SUCCESS; } } while (protocol == NULL && (proto[0] == 't' ? (proto = "udp") : NULL)); @@ -434,10 +416,10 @@ _nss_nis_getservbyport_r (int port, const char *protocol, req.buflen = buflen; req.errnop = errnop; req.status = NSS_STATUS_NOTFOUND; - status = yperr2nss (yp_all (domain, "services.byname", &ypcb)); + int status = yp_all (domain, "services.byname", &ypcb); - if (status != NSS_STATUS_SUCCESS) - return status; + if (__builtin_expect (status != YPERR_SUCCESS, 0)) + return yperr2nss (status); return req.status; } diff --git a/nis/nss_nis/nis-spwd.c b/nis/nss_nis/nis-spwd.c index 99a9ed5f48..0fc4e17c42 100644 --- a/nis/nss_nis/nis-spwd.c +++ b/nis/nss_nis/nis-spwd.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996-1998, 2001, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1996-1998,2001,2002,2003,2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. @@ -68,49 +68,52 @@ static enum nss_status internal_nis_getspent_r (struct spwd *sp, char *buffer, size_t buflen, int *errnop) { - struct parser_data *data = (void *) buffer; - char *domain, *result, *outkey; - int len, keylen, parse_res; - - if (yp_get_default_domain (&domain)) + char *domain; + if (__builtin_expect (yp_get_default_domain (&domain), 0)) return NSS_STATUS_UNAVAIL; /* Get the next entry until we found a correct one. */ + int parse_res; do { - enum nss_status retval; - char *p; + char *result; + char *outkey; + int len; + int keylen; + int yperr; if (new_start) - retval = yperr2nss (yp_first (domain, "shadow.byname", - &outkey, &keylen, &result, &len)); + yperr = yp_first (domain, "shadow.byname", &outkey, &keylen, &result, + &len); else - retval = yperr2nss ( yp_next (domain, "shadow.byname", - oldkey, oldkeylen, - &outkey, &keylen, &result, &len)); + yperr = yp_next (domain, "shadow.byname", oldkey, oldkeylen, &outkey, + &keylen, &result, &len); - if (retval != NSS_STATUS_SUCCESS) + if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) { + enum nss_status retval = yperr2nss (yperr); + if (retval == NSS_STATUS_TRYAGAIN) *errnop = errno; return retval; } - if ((size_t) (len + 1) > buflen) + if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) { free (result); *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } - p = strncpy (buffer, result, len); + char *p = strncpy (buffer, result, len); buffer[len] = '\0'; while (isspace (*p)) ++p; free (result); - parse_res = _nss_files_parse_spent (p, sp, data, buflen, errnop); - if (parse_res == -1) + parse_res = _nss_files_parse_spent (p, sp, (void *) buffer, buflen, + errnop); + if (__builtin_expect (parse_res == -1, 0)) { free (outkey); *errnop = ERANGE; @@ -146,45 +149,46 @@ enum nss_status _nss_nis_getspnam_r (const char *name, struct spwd *sp, char *buffer, size_t buflen, int *errnop) { - struct parser_data *data = (void *) buffer; - enum nss_status retval; - char *domain, *result, *p; - int len, parse_res; - if (name == NULL) { *errnop = EINVAL; return NSS_STATUS_UNAVAIL; } - if (yp_get_default_domain (&domain)) + char *domain; + if (__builtin_expect (yp_get_default_domain (&domain), 0)) return NSS_STATUS_UNAVAIL; - retval = yperr2nss (yp_match (domain, "shadow.byname", name, - strlen (name), &result, &len)); + char *result; + int len; + int yperr = yp_match (domain, "shadow.byname", name, strlen (name), &result, + &len); - if (retval != NSS_STATUS_SUCCESS) + if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) { + enum nss_status retval = yperr2nss (yperr); + if (retval == NSS_STATUS_TRYAGAIN) *errnop = errno; return retval; } - if ((size_t) (len + 1) > buflen) + if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) { free (result); *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } - p = strncpy (buffer, result, len); + char *p = strncpy (buffer, result, len); buffer[len] = '\0'; while (isspace (*p)) ++p; free (result); - parse_res = _nss_files_parse_spent (p, sp, data, buflen, errnop); - if (parse_res < 1) + int parse_res = _nss_files_parse_spent (p, sp, (void *) buffer, buflen, + errnop); + if (__builtin_expect (parse_res < 1, 0)) { if (parse_res == -1) return NSS_STATUS_TRYAGAIN; |