* nis/nss_nis/nis-service.c (_nss_nis_getservbyname_r): Correct

computation of keylen.
This commit is contained in:
Ulrich Drepper 2007-01-14 05:26:04 +00:00
parent 23691ab23b
commit b21fa963c4
24 changed files with 1011 additions and 142 deletions

View File

@ -1,5 +1,8 @@
2007-01-13 Ulrich Drepper <drepper@redhat.com>
* nis/nss_nis/nis-service.c (_nss_nis_getservbyname_r): Correct
computation of keylen.
* include/string.h: Only redefine strndupa if this is really for
libc code.

4
NEWS
View File

@ -1,4 +1,4 @@
GNU C Library NEWS -- history of user-visible changes. 2006-10-11
GNU C Library NEWS -- history of user-visible changes. 2007-1-13
Copyright (C) 1992-2002,2003,2004,2005,2006 Free Software Foundation, Inc.
See the end for copying conditions.
@ -9,6 +9,8 @@ Version 2.6
* New Linux interfaces: epoll_pwait.
* nscd can now cache the services database. Implemented by Ulrich Drepper.
Version 2.5

View File

@ -1,4 +1,4 @@
# Copyright (C) 1991-2002, 2003, 2004, 2006 Free Software Foundation, Inc.
# Copyright (C) 1991-2006, 2007 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# The GNU C Library is free software; you can redistribute it and/or
@ -79,6 +79,8 @@ CFLAGS-getrpcent_r.c = -fexceptions
CFLAGS-getrpcent.c = -fexceptions
CFLAGS-getservent_r.c = -fexceptions
CFLAGS-getservent.c = -fexceptions
CFLAGS-getsrvbynm_r.c = -DUSE_NSCD=1
CFLAGS-getsrvbypt_r.c = -DUSE_NSCD=1
CFLAGS-getprtent_r.c = -fexceptions
CFLAGS-getprtent.c = -fexceptions
CFLAGS-either_ntoh.c = -fexceptions

View File

@ -271,7 +271,7 @@ _nss_nis_getservbyname_r (const char *name, const char *protocol,
/* If the protocol is given, we could try if our NIS server knows
about services.byservicename map. If yes, we only need one query. */
size_t keylen = strlen (name) + 1 + (protocol ? strlen (protocol) : 0);
size_t keylen = strlen (name) + (protocol ? 1 + strlen (protocol) : 0);
char key[keylen + 1];
/* key is: "name/proto" */

View File

@ -1,4 +1,4 @@
# Copyright (C) 1998,2000,2002,2003,2004,2005,2006
# Copyright (C) 1998,2000,2002,2003,2004,2005,2006,2007
# Free Software Foundation, Inc.
# This file is part of the GNU C Library.
@ -22,7 +22,8 @@
#
subdir := nscd
routines := nscd_getpw_r nscd_getgr_r nscd_gethst_r nscd_getai nscd_initgroups
routines := nscd_getpw_r nscd_getgr_r nscd_gethst_r nscd_getai \
nscd_initgroups nscd_getserv_r
aux := nscd_helper
include ../Makeconfig
@ -32,6 +33,7 @@ vpath %.c ../locale/programs
nscd-modules := nscd connections pwdcache getpwnam_r getpwuid_r grpcache \
getgrnam_r getgrgid_r hstcache gethstbyad_r gethstbynm2_r \
getsrvbynm_r getsrvbypt_r servicescache \
dbg_log nscd_conf nscd_stat cache mem nscd_setup_thread \
xmalloc xstrdup aicache initgrcache gai
@ -117,6 +119,9 @@ CFLAGS-aicache.c += $(nscd-cflags)
CFLAGS-selinux.c += $(nscd-cflags)
CFLAGS-initgrcache.c += $(nscd-cflags)
CFLAGS-gai.c += $(nscd-cflags)
CFLAGS-servicescache.c += $(nscd-cflags)
CFLAGS-getsrvbynm_r.c += $(nscd-cflags)
CFLAGS-getsrvbypt_r.c += $(nscd-cflags)
ifeq (yesyes,$(have-fpie)$(build-shared))
relro-LDFLAGS += -Wl,-z,now

View File

@ -1,4 +1,4 @@
/* Copyright (c) 1998, 1999, 2003-2005, 2006 Free Software Foundation, Inc.
/* Copyright (c) 1998, 1999, 2003-2006, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
@ -40,6 +40,25 @@
unsigned int reload_count = DEFAULT_RELOAD_LIMIT;
static void (*const readdfcts[LASTREQ]) (struct database_dyn *,
struct hashentry *,
struct datahead *) =
{
[GETPWBYNAME] = readdpwbyname,
[GETPWBYUID] = readdpwbyuid,
[GETGRBYNAME] = readdgrbyname,
[GETGRBYGID] = readdgrbygid,
[GETHOSTBYNAME] = readdhstbyname,
[GETHOSTBYNAMEv6] = readdhstbynamev6,
[GETHOSTBYADDR] = readdhstbyaddr,
[GETHOSTBYADDRv6] = readdhstbyaddrv6,
[GETAI] = readdhstai,
[INITGROUPS] = readdinitgroups,
[GETSERVBYNAME] = readdservbyname,
[GETSERVBYPORT] = readdservbyport
};
/* Search the cache for a matching entry and return it when found. If
this fails search the negative cache and return (void *) -1 if this
search was successful. Otherwise return NULL.
@ -328,51 +347,10 @@ prune_cache (struct database_dyn *table, time_t now, int fd)
/* Reload the value. We do this only for the
initially used key, not the additionally
added derived value. */
switch (runp->type)
{
case GETPWBYNAME:
readdpwbyname (table, runp, dh);
break;
assert (runp->type < LASTREQ
&& readdfcts[runp->type] != NULL);
case GETPWBYUID:
readdpwbyuid (table, runp, dh);
break;
case GETGRBYNAME:
readdgrbyname (table, runp, dh);
break;
case GETGRBYGID:
readdgrbygid (table, runp, dh);
break;
case GETHOSTBYNAME:
readdhstbyname (table, runp, dh);
break;
case GETHOSTBYNAMEv6:
readdhstbynamev6 (table, runp, dh);
break;
case GETHOSTBYADDR:
readdhstbyaddr (table, runp, dh);
break;
case GETHOSTBYADDRv6:
readdhstbyaddrv6 (table, runp, dh);
break;
case GETAI:
readdhstai (table, runp, dh);
break;
case INITGROUPS:
readdinitgroups (table, runp, dh);
break;
default:
assert (! "should never happen");
}
readdfcts[runp->type] (table, runp, dh);
/* If the entry has been replaced, we might need
cleanup. */

View File

@ -75,7 +75,7 @@ static void begin_drop_privileges (void);
static void finish_drop_privileges (void);
/* Map request type to a string. */
const char *serv2str[LASTREQ] =
const char *const serv2str[LASTREQ] =
{
[GETPWBYNAME] = "GETPWBYNAME",
[GETPWBYUID] = "GETPWBYUID",
@ -92,7 +92,10 @@ const char *serv2str[LASTREQ] =
[GETFDGR] = "GETFDGR",
[GETFDHST] = "GETFDHST",
[GETAI] = "GETAI",
[INITGROUPS] = "INITGROUPS"
[INITGROUPS] = "INITGROUPS",
[GETSERVBYNAME] = "GETSERVBYNAME",
[GETSERVBYPORT] = "GETSERVBYPORT",
[GETFDSERV] = "GETFDSERV"
};
/* The control data structures for the services. */
@ -107,6 +110,7 @@ struct database_dyn dbs[lastdb] =
.propagate = 1,
.shared = 0,
.max_db_size = DEFAULT_MAX_DB_SIZE,
.reset_res = 0,
.filename = "/etc/passwd",
.db_filename = _PATH_NSCD_PASSWD_DB,
.disabled_iov = &pwd_iov_disabled,
@ -125,6 +129,7 @@ struct database_dyn dbs[lastdb] =
.propagate = 1,
.shared = 0,
.max_db_size = DEFAULT_MAX_DB_SIZE,
.reset_res = 0,
.filename = "/etc/group",
.db_filename = _PATH_NSCD_GROUP_DB,
.disabled_iov = &grp_iov_disabled,
@ -143,6 +148,7 @@ struct database_dyn dbs[lastdb] =
.propagate = 0, /* Not used. */
.shared = 0,
.max_db_size = DEFAULT_MAX_DB_SIZE,
.reset_res = 1,
.filename = "/etc/hosts",
.db_filename = _PATH_NSCD_HOSTS_DB,
.disabled_iov = &hst_iov_disabled,
@ -151,6 +157,25 @@ struct database_dyn dbs[lastdb] =
.wr_fd = -1,
.ro_fd = -1,
.mmap_used = false
},
[servdb] = {
.lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP,
.prunelock = PTHREAD_MUTEX_INITIALIZER,
.enabled = 0,
.check_file = 1,
.persistent = 0,
.propagate = 0, /* Not used. */
.shared = 0,
.max_db_size = DEFAULT_MAX_DB_SIZE,
.reset_res = 0,
.filename = "/etc/services",
.db_filename = _PATH_NSCD_SERVICES_DB,
.disabled_iov = &serv_iov_disabled,
.postimeout = 28800,
.negtimeout = 20,
.wr_fd = -1,
.ro_fd = -1,
.mmap_used = false
}
};
@ -170,7 +195,10 @@ static struct database_dyn *const serv2db[LASTREQ] =
[GETFDGR] = &dbs[grpdb],
[GETFDHST] = &dbs[hstdb],
[GETAI] = &dbs[hstdb],
[INITGROUPS] = &dbs[grpdb]
[INITGROUPS] = &dbs[grpdb],
[GETSERVBYNAME] = &dbs[servdb],
[GETSERVBYPORT] = &dbs[servdb],
[GETFDSERV] = &dbs[servdb]
};
@ -305,7 +333,7 @@ check_use (const char *data, nscd_ssize_t first_free, uint8_t *usemap,
static int
verify_persistent_db (void *mem, struct database_pers_head *readhead, int dbnr)
{
assert (dbnr == pwddb || dbnr == grpdb || dbnr == hstdb);
assert (dbnr == pwddb || dbnr == grpdb || dbnr == hstdb || dbnr == servdb);
time_t now = time (NULL);
@ -821,18 +849,16 @@ invalidate_cache (char *key, int fd)
dbtype number;
int32_t resp;
if (strcmp (key, "passwd") == 0)
number = pwddb;
else if (strcmp (key, "group") == 0)
number = grpdb;
else if (__builtin_expect (strcmp (key, "hosts"), 0) == 0)
{
number = hstdb;
for (number = pwddb; number < lastdb; ++number)
if (strcmp (key, dbnames[number]) == 0)
{
if (dbs[number].reset_res)
res_init ();
/* Re-initialize the resolver. resolv.conf might have changed. */
res_init ();
}
else
break;
}
if (number == lastdb)
{
resp = EINVAL;
writeall (fd, &resp, sizeof (resp));
@ -922,8 +948,9 @@ cannot handle old request version %d; current version is %d"),
// XXX Clean up so that each new command need not introduce a
// XXX new conditional.
if ((__builtin_expect (req->type, GETPWBYNAME) >= GETPWBYNAME
&& __builtin_expect (req->type, LASTDBREQ) <= LASTDBREQ)
|| req->type == GETAI || req->type == INITGROUPS)
&& __builtin_expect (req->type, GETHOSTBYADDRv6) <= GETHOSTBYADDRv6)
|| req->type == GETAI || req->type == INITGROUPS
|| req->type == GETSERVBYNAME || req->type == GETSERVBYPORT)
{
if (__builtin_expect (debug_level, 0) > 0)
{
@ -1067,6 +1094,14 @@ cannot handle old request version %d; current version is %d"),
addinitgroups (db, fd, req, key, uid);
break;
case GETSERVBYNAME:
addservbyname (db, fd, req, key, uid);
break;
case GETSERVBYPORT:
addservbyport (db, fd, req, key, uid);
break;
case GETSTAT:
case SHUTDOWN:
case INVALIDATE:
@ -1112,6 +1147,7 @@ cannot handle old request version %d; current version is %d"),
case GETFDPW:
case GETFDGR:
case GETFDHST:
case GETFDSERV:
#ifdef SCM_RIGHTS
send_ro_fd (serv2db[req->type], key, fd);
#endif
@ -1153,7 +1189,7 @@ cannot open /proc/self/cmdline: %s; disabling paranoia mode"),
if (n == -1)
{
dbg_log (_("\
cannot open /proc/self/cmdline: %s; disabling paranoia mode"),
cannot read /proc/self/cmdline: %s; disabling paranoia mode"),
strerror (errno));
close (fd);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
/* Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 2004.
@ -17,7 +17,6 @@
/* This file uses the getaddrinfo code but it compiles it without NSCD
support. We just need a few symbol renames. */
#define __getservbyname_r getservbyname_r
#define __inet_aton inet_aton
#define __getsockname getsockname
#define __socket socket

27
nscd/getsrvbynm_r.c Normal file
View File

@ -0,0 +1,27 @@
/* Copyright (C) 1996, 1997, 2002, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <netdb.h>
#define LOOKUP_TYPE struct servent
#define FUNCTION_NAME getservbyname
#define DATABASE_NAME services
#define ADD_PARAMS const char *name, const char *proto
#define ADD_VARIABLES name, proto
#include "../nss/getXXbyYY_r.c"

27
nscd/getsrvbypt_r.c Normal file
View File

@ -0,0 +1,27 @@
/* Copyright (C) 1996, 1997, 2002, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <netdb.h>
#define LOOKUP_TYPE struct servent
#define FUNCTION_NAME getservbyport
#define DATABASE_NAME services
#define ADD_PARAMS int port, const char *proto
#define ADD_VARIABLES port, proto
#include "../nss/getXXbyYY_r.c"

View File

@ -1,5 +1,5 @@
/* Cache handling for group lookup.
Copyright (C) 1998-2005, 2006 Free Software Foundation, Inc.
Copyright (C) 1998-2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
@ -445,23 +445,14 @@ addgrbyX (struct database_dyn *db, int fd, request_header *req,
dbg_log (_("Reloading \"%s\" in group cache!"), keystr);
}
#if 0
uid_t oldeuid = 0;
if (db->secure)
{
oldeuid = geteuid ();
pthread_seteuid_np (uid);
}
#endif
while (lookup (req->type, key, &resultbuf, buffer, buflen, &grp) != 0
&& (errval = errno) == ERANGE)
{
char *old_buffer = buffer;
errno = 0;
if (__builtin_expect (buflen > 32768, 0))
{
char *old_buffer = buffer;
buflen *= 2;
buffer = (char *) realloc (use_malloc ? buffer : NULL, buflen);
if (buffer == NULL)
@ -486,11 +477,6 @@ addgrbyX (struct database_dyn *db, int fd, request_header *req,
buffer = (char *) extend_alloca (buffer, buflen, 2 * buflen);
}
#if 0
if (db->secure)
pthread_seteuid_np (oldeuid);
#endif
cache_addgr (db, fd, req, keystr, grp, uid, he, dh, errval);
if (use_malloc)

View File

@ -1,5 +1,5 @@
/* Cache handling for host lookup.
Copyright (C) 1998-2005, 2006 Free Software Foundation, Inc.
Copyright (C) 1998-2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
@ -463,24 +463,15 @@ addhstbyX (struct database_dyn *db, int fd, request_header *req,
dbg_log (_("Reloading \"%s\" in hosts cache!"), (char *) str);
}
#if 0
uid_t oldeuid = 0;
if (db->secure)
{
oldeuid = geteuid ();
pthread_seteuid_np (uid);
}
#endif
while (lookup (req->type, key, &resultbuf, buffer, buflen, &hst) != 0
&& h_errno == NETDB_INTERNAL
&& (errval = errno) == ERANGE)
{
char *old_buffer = buffer;
errno = 0;
if (__builtin_expect (buflen > 32768, 0))
{
char *old_buffer = buffer;
buflen *= 2;
buffer = (char *) realloc (use_malloc ? buffer : NULL, buflen);
if (buffer == NULL)
@ -505,11 +496,6 @@ addhstbyX (struct database_dyn *db, int fd, request_header *req,
buffer = (char *) extend_alloca (buffer, buflen, 2 * buflen);
}
#if 0
if (db->secure)
pthread_seteuid_np (oldeuid);
#endif
cache_addhst (db, fd, req, key, hst, uid, he, dh,
h_errno == TRY_AGAIN ? errval : 0);

View File

@ -1,4 +1,4 @@
/* Copyright (c) 1998, 1999, 2000, 2003, 2004, 2005, 2006
/* Copyright (c) 1998, 1999, 2000, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998.
@ -56,7 +56,6 @@ typedef enum
GETHOSTBYNAMEv6,
GETHOSTBYADDR,
GETHOSTBYADDRv6,
LASTDBREQ = GETHOSTBYADDRv6,
SHUTDOWN, /* Shut the server down. */
GETSTAT, /* Get the server statistic. */
INVALIDATE, /* Invalidate one special cache. */
@ -65,6 +64,9 @@ typedef enum
GETFDHST,
GETAI,
INITGROUPS,
GETSERVBYNAME,
GETSERVBYPORT,
GETFDSERV,
LASTREQ
} request_type;
@ -153,6 +155,19 @@ typedef struct
} initgr_response_header;
/* Structure sent in reply to services query. Note that this struct is
sent also if the service is disabled or there is no record found. */
typedef struct
{
int32_t version;
int32_t found;
nscd_ssize_t s_name_len;
nscd_ssize_t s_proto_len;
nscd_ssize_t s_aliases_cnt;
int32_t s_port;
} serv_response_header;
/* Type for offsets in data part of database. */
typedef uint32_t ref_t;
/* Value for invalid/no reference. */
@ -186,6 +201,7 @@ struct datahead
hst_response_header hstdata;
ai_response_header aidata;
initgr_response_header initgrdata;
serv_response_header servdata;
nscd_ssize_t align1;
nscd_time_t align2;
} data[0];

View File

@ -332,15 +332,15 @@ parse_opt (int key, char *arg, struct argp_state *state)
exit (EXIT_FAILURE);
request_header req;
if (strcmp (arg, "passwd") == 0)
req.key_len = sizeof "passwd";
else if (strcmp (arg, "group") == 0)
req.key_len = sizeof "group";
else if (strcmp (arg, "hosts") == 0)
req.key_len = sizeof "hosts";
else
dbtype cnt;
for (cnt = pwddb; cnt < lastdb; ++cnt)
if (strcmp (arg, dbnames[cnt]) == 0)
break;
if (cnt == lastdb)
return ARGP_ERR_UNKNOWN;
req.key_len = strlen (arg) + 1;
req.version = NSCD_VERSION;
req.type = INVALIDATE;

View File

@ -26,7 +26,7 @@
# max-db-size <service> <number bytes>
# auto-propagate <service> <yes|no>
#
# Currently supported cache names (services): passwd, group, hosts
# Currently supported cache names (services): passwd, group, hosts, services
#
@ -68,3 +68,12 @@
persistent hosts yes
shared hosts yes
max-db-size hosts 33554432
enable-cache services yes
positive-time-to-live services 28800
negative-time-to-live services 20
suggested-size services 211
check-files services yes
persistent services yes
shared services yes
max-db-size services 33554432

View File

@ -1,4 +1,4 @@
/* Copyright (c) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006
/* Copyright (c) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998.
@ -38,6 +38,7 @@ typedef enum
pwddb,
grpdb,
hstdb,
servdb,
lastdb
} dbtype;
@ -65,7 +66,8 @@ struct database_dyn
int persistent;
int shared;
int propagate;
const char filename[12];
int reset_res;
const char filename[16];
const char *db_filename;
time_t file_mtime;
size_t suggested_module;
@ -92,6 +94,7 @@ struct database_dyn
#define _PATH_NSCD_PASSWD_DB "/var/db/nscd/passwd"
#define _PATH_NSCD_GROUP_DB "/var/db/nscd/group"
#define _PATH_NSCD_HOSTS_DB "/var/db/nscd/hosts"
#define _PATH_NSCD_SERVICES_DB "/var/db/nscd/services"
/* Path used when not using persistent storage. */
#define _PATH_NSCD_XYZ_DB_TMP "/var/run/nscd/dbXXXXXX"
@ -110,12 +113,13 @@ struct database_dyn
/* Global variables. */
extern struct database_dyn dbs[lastdb];
extern const char *dbnames[lastdb];
extern const char *serv2str[LASTREQ];
extern const char *const dbnames[lastdb];
extern const char *const serv2str[LASTREQ];
extern const struct iovec pwd_iov_disabled;
extern const struct iovec grp_iov_disabled;
extern const struct iovec hst_iov_disabled;
extern const struct iovec serv_iov_disabled;
/* Initial number of threads to run. */
@ -238,6 +242,16 @@ extern void addinitgroups (struct database_dyn *db, int fd,
extern void readdinitgroups (struct database_dyn *db, struct hashentry *he,
struct datahead *dh);
/* servicecache.c */
extern void addservbyname (struct database_dyn *db, int fd,
request_header *req, void *key, uid_t uid);
extern void readdservbyname (struct database_dyn *db, struct hashentry *he,
struct datahead *dh);
extern void addservbyport (struct database_dyn *db, int fd,
request_header *req, void *key, uid_t uid);
extern void readdservbyport (struct database_dyn *db, struct hashentry *he,
struct datahead *dh);
/* mem.c */
extern void *mempool_alloc (struct database_dyn *db, size_t len);
extern void gc (struct database_dyn *db);

View File

@ -1,4 +1,4 @@
/* Copyright (c) 1998,2000,2003,2004,2005,2006 Free Software Foundation, Inc.
/* Copyright (c) 1998, 2000, 2003-2006, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998.
@ -37,11 +37,12 @@ extern char *xstrdup (const char *s);
/* Names of the databases. */
const char *dbnames[lastdb] =
const char *const dbnames[lastdb] =
{
[pwddb] = "passwd",
[grpdb] = "group",
[hstdb] = "hosts"
[hstdb] = "hosts",
[servdb] = "services"
};
@ -52,7 +53,7 @@ find_db (const char *name)
if (strcmp (name, dbnames[cnt]) == 0)
return cnt;
error (0, 0, _("database %s is not supported\n"), name);
error (0, 0, _("database %s is not supported"), name);
return -1;
}

306
nscd/nscd_getserv_r.c Normal file
View File

@ -0,0 +1,306 @@
/* Copyright (C) 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2007.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <string.h>
#include <not-cancel.h>
#include <stdio-common/_itoa.h>
#include "nscd-client.h"
#include "nscd_proto.h"
int __nss_not_use_nscd_services;
static int nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
request_type type, struct servent *resultbuf,
char *buf, size_t buflen, struct servent **result);
int
__nscd_getservbyname_r (const char *name, const char *proto,
struct servent *result_buf, char *buf, size_t buflen,
struct servent **result)
{
return nscd_getserv_r (name, strlen (name), proto, GETSERVBYNAME, result_buf,
buf, buflen, result);
}
int
__nscd_getservbyport_r (int port, const char *proto,
struct servent *result_buf, char *buf, size_t buflen,
struct servent **result)
{
char portstr[3 * sizeof (int) + 2];
portstr[sizeof (portstr) - 1] = '\0';
char *cp = _itoa_word (port, portstr + sizeof (portstr) - 1, 10, 0);
return nscd_getserv_r (portstr, portstr + sizeof (portstr) - cp, proto,
GETSERVBYPORT, result_buf, buf, buflen, result);
}
libc_locked_map_ptr (, __serv_map_handle) attribute_hidden;
/* Note that we only free the structure if necessary. The memory
mapping is not removed since it is not visible to the malloc
handling. */
libc_freeres_fn (serv_map_free)
{
if (__serv_map_handle.mapped != NO_MAPPING)
{
void *p = __serv_map_handle.mapped;
__serv_map_handle.mapped = NO_MAPPING;
free (p);
}
}
static int
nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
request_type type, struct servent *resultbuf,
char *buf, size_t buflen, struct servent **result)
{
int gc_cycle;
int nretries = 0;
/* If the mapping is available, try to search there instead of
communicating with the nscd. */
struct mapped_database *mapped;
mapped = __nscd_get_map_ref (GETFDSERV, "services", &__serv_map_handle,
&gc_cycle);
size_t protolen = proto == NULL ? 0 : strlen (proto);
size_t keylen = critlen + 1 + protolen + 1;
char *key = alloca (keylen);
memcpy (__mempcpy (__mempcpy (key, crit, critlen),
"/", 1), proto ?: "", protolen + 1);
retry:;
const serv_response_header *serv_resp = NULL;
const char *s_name = NULL;
const char *s_proto = NULL;
const uint32_t *aliases_len = NULL;
const char *aliases_list = NULL;
int retval = -1;
const char *recend = (const char *) ~UINTMAX_C (0);
int sock = -1;
if (mapped != NO_MAPPING)
{
const struct datahead *found = __nscd_cache_search (type, key, keylen,
mapped);
if (found != NULL)
{
serv_resp = &found->data[0].servdata;
s_name = (char *) (serv_resp + 1);
s_proto = s_name + serv_resp->s_name_len;
aliases_len = (uint32_t *) (s_proto + serv_resp->s_proto_len);
aliases_list = ((char *) aliases_len
+ serv_resp->s_aliases_cnt * sizeof (uint32_t));
#ifndef _STRING_ARCH_unaligned
/* The aliases_len array in the mapped database might very
well be unaligned. We will access it word-wise so on
platforms which do not tolerate unaligned accesses we
need to make an aligned copy. */
if (((uintptr_t) aliases_len & (__alignof__ (*aliases_len) - 1))
!= 0)
{
uint32_t *tmp = alloca (hst_resp->h_aliases_cnt
* sizeof (uint32_t));
aliases_len = memcpy (tmp, aliases_len,
hst_resp->h_aliases_cnt
* sizeof (uint32_t));
}
#endif
recend = (const char *) found->data + found->recsize;
if (__builtin_expect ((const char *) aliases_len
+ serv_resp->s_aliases_cnt * sizeof (uint32_t)
> recend, 0))
goto out_close;
}
}
serv_response_header serv_resp_mem;
if (serv_resp == NULL)
{
sock = __nscd_open_socket (key, keylen, type, &serv_resp_mem,
sizeof (serv_resp_mem));
if (sock == -1)
{
__nss_not_use_nscd_services = 1;
goto out;
}
serv_resp = &serv_resp_mem;
}
/* No value found so far. */
*result = NULL;
if (__builtin_expect (serv_resp->found == -1, 0))
{
/* The daemon does not cache this database. */
__nss_not_use_nscd_services = 1;
goto out_close;
}
if (serv_resp->found == 1)
{
char *cp = buf;
uintptr_t align1;
uintptr_t align2;
size_t total_len;
ssize_t cnt;
int n;
/* A first check whether the buffer is sufficiently large is possible. */
/* Now allocate the buffer the array for the group members. We must
align the pointer and the base of the h_addr_list pointers. */
align1 = ((__alignof__ (char *) - (cp - ((char *) 0)))
& (__alignof__ (char *) - 1));
align2 = ((__alignof__ (char *) - ((cp + align1 + serv_resp->s_name_len
+ serv_resp->s_proto_len)
- ((char *) 0)))
& (__alignof__ (char *) - 1));
if (buflen < (align1 + serv_resp->s_name_len + serv_resp->s_proto_len
+ align2
+ (serv_resp->s_aliases_cnt + 1) * sizeof (char *)))
{
no_room:
__set_errno (ERANGE);
retval = ERANGE;
goto out_close;
}
cp += align1;
/* Prepare the result as far as we can. */
resultbuf->s_aliases = (char **) cp;
cp += (serv_resp->s_aliases_cnt + 1) * sizeof (char *);
resultbuf->s_name = cp;
cp += serv_resp->s_name_len;
resultbuf->s_proto = cp;
cp += serv_resp->s_proto_len + align2;
resultbuf->s_port = serv_resp->s_port;
if (s_name == NULL)
{
struct iovec vec[2];
vec[0].iov_base = resultbuf->s_name;
vec[0].iov_len = serv_resp->s_name_len + serv_resp->s_proto_len;
total_len = vec[0].iov_len;
n = 1;
if (serv_resp->s_aliases_cnt > 0)
{
aliases_len = alloca (serv_resp->s_aliases_cnt
* sizeof (uint32_t));
vec[n].iov_base = (void *) aliases_len;
vec[n].iov_len = serv_resp->s_aliases_cnt * sizeof (uint32_t);
total_len += serv_resp->s_aliases_cnt * sizeof (uint32_t);
++n;
}
if ((size_t) __readvall (sock, vec, n) != total_len)
goto out_close;
}
else
memcpy (resultbuf->s_name, s_name,
serv_resp->s_name_len + serv_resp->s_proto_len);
/* Now we also can read the aliases. */
total_len = 0;
for (cnt = 0; cnt < serv_resp->s_aliases_cnt; ++cnt)
{
resultbuf->s_aliases[cnt] = cp;
cp += aliases_len[cnt];
total_len += aliases_len[cnt];
}
resultbuf->s_aliases[cnt] = NULL;
if (__builtin_expect ((const char *) aliases_list + total_len > recend,
0))
goto out_close;
/* See whether this would exceed the buffer capacity. */
if (__builtin_expect (cp > buf + buflen, 0))
goto no_room;
/* And finally read the aliases. */
if (aliases_list == NULL)
{
if (total_len == 0
|| ((size_t) __readall (sock, resultbuf->s_aliases[0], total_len)
== total_len))
{
retval = 0;
*result = resultbuf;
}
}
else
{
memcpy (resultbuf->s_aliases[0], aliases_list, total_len);
/* Try to detect corrupt databases. */
if (resultbuf->s_name[serv_resp->s_name_len - 1] != '\0'
|| resultbuf->s_proto[serv_resp->s_proto_len - 1] != '\0'
|| ({for (cnt = 0; cnt < serv_resp->s_aliases_cnt; ++cnt)
if (resultbuf->s_aliases[cnt][aliases_len[cnt] - 1]
!= '\0')
break;
cnt < serv_resp->s_aliases_cnt; }))
/* We cannot use the database. */
goto out_close;
retval = 0;
*result = resultbuf;
}
}
else
{
/* The `errno' to some value != ERANGE. */
__set_errno (ENOENT);
/* Even though we have not found anything, the result is zero. */
retval = 0;
}
out_close:
if (sock != -1)
close_not_cancel_no_status (sock);
out:
if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0 && retval != -1)
{
/* When we come here this means there has been a GC cycle while we
were looking for the data. This means the data might have been
inconsistent. Retry if possible. */
if ((gc_cycle & 1) != 0 || ++nretries == 5)
{
/* nscd is just running gc now. Disable using the mapping. */
__nscd_unmap (mapped);
mapped = NO_MAPPING;
}
goto retry;
}
return retval;
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1998, 1999, 2000, 2002, 2004 Free Software Foundation, Inc.
/* Copyright (C) 1998-2000, 2002, 2004, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998.
@ -35,6 +35,7 @@ struct nscd_ai_result;
extern int __nss_not_use_nscd_passwd attribute_hidden;
extern int __nss_not_use_nscd_group attribute_hidden;
extern int __nss_not_use_nscd_hosts attribute_hidden;
extern int __nss_not_use_nscd_services attribute_hidden;
extern int __nscd_getpwnam_r (const char *name, struct passwd *resultbuf,
char *buffer, size_t buflen,
@ -64,4 +65,11 @@ extern int __nscd_getai (const char *key, struct nscd_ai_result **result,
int *h_errnop);
extern int __nscd_getgrouplist (const char *user, gid_t group, long int *size,
gid_t **groupsp, long int limit);
extern int __nscd_getservbyname_r (const char *name, const char *proto,
struct servent *result_buf, char *buf,
size_t buflen, struct servent **result);
extern int __nscd_getservbyport_r (int port, const char *proto,
struct servent *result_buf, char *buf,
size_t buflen, struct servent **result);
#endif /* _NSCD_PROTO_H */

View File

@ -1,5 +1,5 @@
/* Cache handling for passwd lookup.
Copyright (C) 1998-2005, 2006 Free Software Foundation, Inc.
Copyright (C) 1998-2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
@ -440,23 +440,14 @@ addpwbyX (struct database_dyn *db, int fd, request_header *req,
dbg_log (_("Reloading \"%s\" in password cache!"), keystr);
}
#if 0
uid_t oldeuid = 0;
if (db->secure)
{
oldeuid = geteuid ();
pthread_seteuid_np (c_uid);
}
#endif
while (lookup (req->type, key, &resultbuf, buffer, buflen, &pwd) != 0
&& (errval = errno) == ERANGE)
{
char *old_buffer = buffer;
errno = 0;
if (__builtin_expect (buflen > 32768, 0))
{
char *old_buffer = buffer;
buflen *= 2;
buffer = (char *) realloc (use_malloc ? buffer : NULL, buflen);
if (buffer == NULL)
@ -481,11 +472,6 @@ addpwbyX (struct database_dyn *db, int fd, request_header *req,
buffer = (char *) extend_alloca (buffer, buflen, 2 * buflen);
}
#if 0
if (db->secure)
pthread_seteuid_np (oldeuid);
#endif
/* Add the entry to the cache. */
cache_addpw (db, fd, req, keystr, pwd, c_uid, he, dh, errval);

View File

@ -1,5 +1,5 @@
/* SELinux access controls for nscd.
Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Matthew Rickard <mjricka@epoch.ncsc.mil>, 2004.
@ -63,7 +63,12 @@ static const int perms[LASTREQ] =
[GETFDGR] = NSCD__SHMEMGRP,
[GETFDHST] = NSCD__SHMEMHOST,
[GETAI] = NSCD__GETHOST,
[INITGROUPS] = NSCD__GETGRP
[INITGROUPS] = NSCD__GETGRP,
#ifdef NSCD__GETSERV
[GETSERVBYNAME] = NSCD__GETSERV,
[GETSERVBYPORT] = NSCD__GETSERV,
[GETFDSERV] = NSCD__SHMEMSERV,
#endif
};
/* Store an entry ref to speed AVC decisions. */

473
nscd/servicescache.c Normal file
View File

@ -0,0 +1,473 @@
/* Cache handling for services lookup.
Copyright (C) 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@drepper.com>, 2007.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <alloca.h>
#include <assert.h>
#include <errno.h>
#include <libintl.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/mman.h>
#include "nscd.h"
#include "dbg_log.h"
/* This is the standard reply in case the service is disabled. */
static const serv_response_header disabled =
{
.version = NSCD_VERSION,
.found = -1,
.s_name_len = 0,
.s_proto_len = 0,
.s_aliases_cnt = 0,
.s_port = -1
};
/* This is the struct describing how to write this record. */
const struct iovec serv_iov_disabled =
{
.iov_base = (void *) &disabled,
.iov_len = sizeof (disabled)
};
/* This is the standard reply in case we haven't found the dataset. */
static const serv_response_header notfound =
{
.version = NSCD_VERSION,
.found = 0,
.s_name_len = 0,
.s_proto_len = 0,
.s_aliases_cnt = 0,
.s_port = -1
};
static void
cache_addserv (struct database_dyn *db, int fd, request_header *req,
const void *key, struct servent *serv, uid_t owner,
struct hashentry *he, struct datahead *dh, int errval)
{
ssize_t total;
ssize_t written;
time_t t = time (NULL);
/* We allocate all data in one memory block: the iov vector,
the response header and the dataset itself. */
struct dataset
{
struct datahead head;
serv_response_header resp;
char strdata[0];
} *dataset;
assert (offsetof (struct dataset, resp) == offsetof (struct datahead, data));
if (serv == NULL)
{
if (he != NULL && errval == EAGAIN)
{
/* If we have an old record available but cannot find one
now because the service is not available we keep the old
record and make sure it does not get removed. */
if (reload_count != UINT_MAX)
/* Do not reset the value if we never not reload the record. */
dh->nreloads = reload_count - 1;
written = total = 0;
}
else
{
/* We have no data. This means we send the standard reply for this
case. */
total = sizeof (notfound);
written = TEMP_FAILURE_RETRY (send (fd, &notfound, total,
MSG_NOSIGNAL));
dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len);
/* If we cannot permanently store the result, so be it. */
if (dataset != NULL)
{
dataset->head.allocsize = sizeof (struct dataset) + req->key_len;
dataset->head.recsize = total;
dataset->head.notfound = true;
dataset->head.nreloads = 0;
dataset->head.usable = true;
/* Compute the timeout time. */
dataset->head.timeout = t + db->negtimeout;
/* This is the reply. */
memcpy (&dataset->resp, &notfound, total);
/* Copy the key data. */
memcpy (dataset->strdata, key, req->key_len);
/* If necessary, we also propagate the data to disk. */
if (db->persistent)
{
// XXX async OK?
uintptr_t pval = (uintptr_t) dataset & ~pagesize_m1;
msync ((void *) pval,
((uintptr_t) dataset & pagesize_m1)
+ sizeof (struct dataset) + req->key_len, MS_ASYNC);
}
/* Now get the lock to safely insert the records. */
pthread_rwlock_rdlock (&db->lock);
if (cache_add (req->type, &dataset->strdata, req->key_len,
&dataset->head, true, db, owner) < 0)
/* Ensure the data can be recovered. */
dataset->head.usable = false;
pthread_rwlock_unlock (&db->lock);
/* Mark the old entry as obsolete. */
if (dh != NULL)
dh->usable = false;
}
else
++db->head->addfailed;
}
}
else
{
/* Determine the I/O structure. */
size_t s_name_len = strlen (serv->s_name) + 1;
size_t s_proto_len = strlen (serv->s_proto) + 1;
uint32_t *s_aliases_len;
size_t s_aliases_cnt;
char *aliases;
char *cp;
size_t cnt;
/* Determine the number of aliases. */
s_aliases_cnt = 0;
for (cnt = 0; serv->s_aliases[cnt] != NULL; ++cnt)
++s_aliases_cnt;
/* Determine the length of all aliases. */
s_aliases_len = (uint32_t *) alloca (s_aliases_cnt * sizeof (uint32_t));
total = 0;
for (cnt = 0; cnt < s_aliases_cnt; ++cnt)
{
s_aliases_len[cnt] = strlen (serv->s_aliases[cnt]) + 1;
total += s_aliases_len[cnt];
}
total += (sizeof (struct dataset)
+ s_name_len
+ s_proto_len
+ s_aliases_cnt * sizeof (uint32_t));
written = total;
/* If we refill the cache, first assume the reconrd did not
change. Allocate memory on the cache since it is likely
discarded anyway. If it turns out to be necessary to have a
new record we can still allocate real memory. */
bool alloca_used = false;
dataset = NULL;
if (he == NULL)
{
dataset = (struct dataset *) mempool_alloc (db,
total + req->key_len);
if (dataset == NULL)
++db->head->addfailed;
}
if (dataset == NULL)
{
/* We cannot permanently add the result in the moment. But
we can provide the result as is. Store the data in some
temporary memory. */
dataset = (struct dataset *) alloca (total + req->key_len);
/* We cannot add this record to the permanent database. */
alloca_used = true;
}
dataset->head.allocsize = total + req->key_len;
dataset->head.recsize = total - offsetof (struct dataset, resp);
dataset->head.notfound = false;
dataset->head.nreloads = he == NULL ? 0 : (dh->nreloads + 1);
dataset->head.usable = true;
/* Compute the timeout time. */
dataset->head.timeout = t + db->postimeout;
dataset->resp.version = NSCD_VERSION;
dataset->resp.found = 1;
dataset->resp.s_name_len = s_name_len;
dataset->resp.s_proto_len = s_proto_len;
dataset->resp.s_port = serv->s_port;
dataset->resp.s_aliases_cnt = s_aliases_cnt;
cp = dataset->strdata;
cp = mempcpy (cp, serv->s_name, s_name_len);
cp = mempcpy (cp, serv->s_proto, s_proto_len);
cp = mempcpy (cp, s_aliases_len, s_aliases_cnt * sizeof (uint32_t));
/* Then the aliases. */
aliases = cp;
for (cnt = 0; cnt < s_aliases_cnt; ++cnt)
cp = mempcpy (cp, serv->s_aliases[cnt], s_aliases_len[cnt]);
assert (cp
== dataset->strdata + total - offsetof (struct dataset,
strdata));
char *key_copy = memcpy (cp, key, req->key_len);
/* Now we can determine whether on refill we have to create a new
record or not. */
if (he != NULL)
{
assert (fd == -1);
if (total + req->key_len == dh->allocsize
&& total - offsetof (struct dataset, resp) == dh->recsize
&& memcmp (&dataset->resp, dh->data,
dh->allocsize - offsetof (struct dataset, resp)) == 0)
{
/* The data has not changed. We will just bump the
timeout value. Note that the new record has been
allocated on the stack and need not be freed. */
dh->timeout = dataset->head.timeout;
++dh->nreloads;
}
else
{
/* We have to create a new record. Just allocate
appropriate memory and copy it. */
struct dataset *newp
= (struct dataset *) mempool_alloc (db, total + req->key_len);
if (newp != NULL)
{
/* Adjust pointers into the memory block. */
aliases = (char *) newp + (aliases - (char *) dataset);
if (key_copy != NULL)
key_copy = (char *) newp + (key_copy - (char *) dataset);
dataset = memcpy (newp, dataset, total + req->key_len);
alloca_used = false;
}
/* Mark the old record as obsolete. */
dh->usable = false;
}
}
else
{
/* We write the dataset before inserting it to the database
since while inserting this thread might block and so would
unnecessarily keep the receiver waiting. */
assert (fd != -1);
#ifdef HAVE_SENDFILE
if (__builtin_expect (db->mmap_used, 1) && !alloca_used)
{
assert (db->wr_fd != -1);
assert ((char *) &dataset->resp > (char *) db->data);
assert ((char *) &dataset->resp - (char *) db->head
+ total
<= (sizeof (struct database_pers_head)
+ db->head->module * sizeof (ref_t)
+ db->head->data_size));
written = sendfileall (fd, db->wr_fd,
(char *) &dataset->resp
- (char *) db->head, total);
# ifndef __ASSUME_SENDFILE
if (written == -1 && errno == ENOSYS)
goto use_write;
# endif
}
else
# ifndef __ASSUME_SENDFILE
use_write:
# endif
#endif
written = writeall (fd, &dataset->resp, total);
}
/* Add the record to the database. But only if it has not been
stored on the stack. */
if (! alloca_used)
{
/* If necessary, we also propagate the data to disk. */
if (db->persistent)
{
// XXX async OK?
uintptr_t pval = (uintptr_t) dataset & ~pagesize_m1;
msync ((void *) pval,
((uintptr_t) dataset & pagesize_m1)
+ total + req->key_len, MS_ASYNC);
}
/* Now get the lock to safely insert the records. */
pthread_rwlock_rdlock (&db->lock);
if (cache_add (req->type, key_copy, req->key_len,
&dataset->head, true, db, owner) < 0)
/* Could not allocate memory. Make sure the
data gets discarded. */
dataset->head.usable = false;
pthread_rwlock_unlock (&db->lock);
}
}
if (__builtin_expect (written != total, 0) && debug_level > 0)
{
char buf[256];
dbg_log (_("short write in %s: %s"), __FUNCTION__,
strerror_r (errno, buf, sizeof (buf)));
}
}
static int
lookup (int type, char *key, struct servent *resultbufp, char *buffer,
size_t buflen, struct servent **serv)
{
char *proto = strrchr (key, '/');
if (proto != NULL && proto != key)
{
key = strndupa (key, proto - key);
if (proto[1] == '\0')
proto = NULL;
else
++proto;
}
if (type == GETSERVBYNAME)
return __getservbyname_r (key, proto, resultbufp, buffer, buflen, serv);
assert (type == GETSERVBYPORT);
return __getservbyport_r (atol (key), proto, resultbufp, buffer, buflen,
serv);
}
static void
addservbyX (struct database_dyn *db, int fd, request_header *req,
char *key, uid_t uid, struct hashentry *he, struct datahead *dh)
{
/* Search for the entry matching the key. Please note that we don't
look again in the table whether the dataset is now available. We
simply insert it. It does not matter if it is in there twice. The
pruning function only will look at the timestamp. */
size_t buflen = 1024;
char *buffer = (char *) alloca (buflen);
struct servent resultbuf;
struct servent *serv;
bool use_malloc = false;
int errval = 0;
if (__builtin_expect (debug_level > 0, 0))
{
if (he == NULL)
dbg_log (_("Haven't found \"%s\" in services cache!"), key);
else
dbg_log (_("Reloading \"%s\" in services cache!"), key);
}
while (lookup (req->type, key, &resultbuf, buffer, buflen, &serv) != 0
&& (errval = errno) == ERANGE)
{
errno = 0;
if (__builtin_expect (buflen > 32768, 0))
{
char *old_buffer = buffer;
buflen *= 2;
buffer = (char *) realloc (use_malloc ? buffer : NULL, buflen);
if (buffer == NULL)
{
/* We ran out of memory. We cannot do anything but
sending a negative response. In reality this should
never happen. */
serv = NULL;
buffer = old_buffer;
/* We set the error to indicate this is (possibly) a
temporary error and that it does not mean the entry
is not available at all. */
errval = EAGAIN;
break;
}
use_malloc = true;
}
else
/* Allocate a new buffer on the stack. If possible combine it
with the previously allocated buffer. */
buffer = (char *) extend_alloca (buffer, buflen, 2 * buflen);
}
cache_addserv (db, fd, req, key, serv, uid, he, dh, errval);
if (use_malloc)
free (buffer);
}
void
addservbyname (struct database_dyn *db, int fd, request_header *req,
void *key, uid_t uid)
{
addservbyX (db, fd, req, key, uid, NULL, NULL);
}
void
readdservbyname (struct database_dyn *db, struct hashentry *he,
struct datahead *dh)
{
request_header req =
{
.type = GETSERVBYNAME,
.key_len = he->len
};
addservbyX (db, -1, &req, db->data + he->key, he->owner, he, dh);
}
void
addservbyport (struct database_dyn *db, int fd, request_header *req,
void *key, uid_t uid)
{
addservbyX (db, fd, req, key, uid, NULL, NULL);
}
void
readdservbyport (struct database_dyn *db, struct hashentry *he,
struct datahead *dh)
{
request_header req =
{
.type = GETSERVBYPORT,
.key_len = he->len
};
addservbyX (db, -1, &req, db->data + he->key, he->owner, he, dh);
}

View File

@ -9,7 +9,7 @@ libc {
}
GLIBC_PRIVATE {
_nss_files_parse_grent; _nss_files_parse_pwent; _nss_files_parse_spent;
__nss_disable_nscd; __nss_lookup_function;
__nss_disable_nscd; __nss_lookup_function; __nss_services_lookup;
}
}

View File

@ -1,5 +1,4 @@
/* Copyright (C) 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
/* Copyright (C) 1996-1999, 2001-2006, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
@ -708,6 +707,7 @@ __nss_disable_nscd (void)
__nss_not_use_nscd_passwd = -1;
__nss_not_use_nscd_group = -1;
__nss_not_use_nscd_hosts = -1;
__nss_not_use_nscd_services = -1;
}