summaryrefslogtreecommitdiff
path: root/usr/src/cmd/nscd/server.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/nscd/server.c')
-rw-r--r--usr/src/cmd/nscd/server.c1922
1 files changed, 279 insertions, 1643 deletions
diff --git a/usr/src/cmd/nscd/server.c b/usr/src/cmd/nscd/server.c
index d4cba76b85..699579fdfe 100644
--- a/usr/src/cmd/nscd/server.c
+++ b/usr/src/cmd/nscd/server.c
@@ -30,139 +30,44 @@
*/
#include <stdio.h>
-#include <signal.h>
-#include <sys/door.h>
-#include <sys/types.h>
-#include <time.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include <sys/zone.h>
#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
#include <errno.h>
-#include <pthread.h>
-#include <thread.h>
#include <stdarg.h>
-#include <fcntl.h>
-#include <assert.h>
-#include <unistd.h>
-#include <memory.h>
-#include <sys/socket.h>
-#include <net/route.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#include <arpa/nameser.h>
-#include <resolv.h>
-#include <door.h>
-#include "getxby_door.h"
-#include "server_door.h"
-#include "nscd.h"
-/* Includes for filenames of databases */
-#include <shadow.h>
-#include <userdefs.h>
-#include <netdb.h>
-#include <nss_dbdefs.h>
-#include <exec_attr.h>
-#include <prof_attr.h>
-#include <user_attr.h>
-#include <ucred.h>
-#include <priv.h>
-#include <libscf.h>
+#include <locale.h>
#include <tsol/label.h>
#include <zone.h>
-
-#define TSOL_NAME_SERVICE_DOOR "/var/tsol/doors/name_service_door"
+#include "cache.h"
+#include "nscd_log.h"
+#include "nscd_selfcred.h"
+#include "nscd_frontend.h"
+#include "nscd_common.h"
+#include "nscd_admin.h"
+#include "nscd_door.h"
+#include "nscd_switch.h"
extern int optind;
extern int opterr;
extern int optopt;
extern char *optarg;
-static void switcher(void *, char *, size_t, door_desc_t *, uint_t);
-static void rts_mon(void);
-static void usage(char *);
-static int nsc_calllen(nsc_call_t *);
-static int client_getadmin(admin_t *);
-static void getadmin(nsc_return_t *, int, nsc_call_t *);
-static int setadmin(nsc_return_t *, int, nsc_call_t *);
-static void client_killserver(void);
-static int client_setadmin(admin_t *);
-static void client_showstats(admin_t *);
-static void detachfromtty(void);
-
+#define NSCDOPT "S:Kf:c:ge:p:n:i:l:d:s:h:o:GFR"
-admin_t current_admin;
-static int will_become_server;
-
-void
-nsc_reaper(char *tbl_name, hash_t *tbl, nsc_stat_t *admin_ptr,
- mutex_t *hash_lock)
-{
- uint_t count;
- uint_t interval;
+/* assume this is a single nscd or, if multiple, the main nscd */
+int _whoami = NSCD_MAIN;
+int _doorfd = -1;
+extern int _logfd;
+static char *cfgfile = NULL;
- while (1) {
+extern nsc_ctx_t *cache_ctx_p[];
- if (current_admin.debug_level >= DBG_ALL) {
- logit("reaper_%s: %d entries in cache\n",
- tbl_name, admin_ptr->nsc_entries);
- }
- if (admin_ptr->nsc_entries > 0) {
- count = reap_hash(tbl, admin_ptr, hash_lock,
- admin_ptr->nsc_pos_ttl);
- if (current_admin.debug_level >= DBG_ALL) {
- logit("reaper_%s: reaped %d entries\n",
- tbl_name, count);
- }
- } else {
- /*
- * We set a minimum wait of 60 before checking again;
- * we don't want to sleep for no time at all.
- * We don't clamp it for the reaping itself, that is
- * done in reap_hash, and with a different minimum.
- */
- interval = admin_ptr->nsc_pos_ttl;
- if (interval < 60) interval = 60;
- if (current_admin.debug_level >= DBG_ALL) {
- logit(
- "reaper_%s: Nothing to reap, sleep %d\n",
- tbl_name, interval);
- }
- sleep(interval);
- }
- }
-}
-
-nsc_stat_t *
-getcacheptr(char *s)
-{
- static const char *caches[7] = {"passwd", "group", "hosts", "ipnodes",
- "exec_attr", "prof_attr", "user_attr" };
-
- if (strncmp(caches[0], s, strlen(caches[0])) == 0)
- return (&current_admin.passwd);
-
- if (strncmp(caches[1], s, strlen(caches[1])) == 0)
- return (&current_admin.group);
-
- if (strncmp(caches[2], s, strlen(caches[2])) == 0)
- return (&current_admin.host);
-
- if (strncmp(caches[3], s, strlen(caches[3])) == 0)
- return (&current_admin.node);
-
- if (strncmp(caches[4], s, strlen(caches[4])) == 0)
- return (&current_admin.exec);
-
- if (strncmp(caches[5], s, strlen(caches[5])) == 0)
- return (&current_admin.prof);
-
- if (strncmp(caches[6], s, strlen(caches[6])) == 0)
- return (&current_admin.user);
+static void usage(char *);
+static void detachfromtty(void);
- return (NULL);
-}
+static int debug_level = 0;
+static char logfile[128] = { 0 };
+static int will_become_server;
static char *
getcacheopt(char *s)
@@ -173,37 +78,6 @@ getcacheopt(char *s)
}
/*
- * routine to check if server is already running
- */
-
-static int
-nsc_ping(void)
-{
- nsc_data_t data;
- nsc_data_t *dptr;
- int ndata;
- int adata;
-
- data.nsc_call.nsc_callnumber = NULLCALL;
- ndata = sizeof (data);
- adata = sizeof (data);
- dptr = &data;
- return (_nsc_trydoorcall(&dptr, &ndata, &adata));
-}
-
-static void
-dozip(void)
-{
- /* not much here */
-}
-
-static void
-keep_open_dns_socket(void)
-{
- _res.options |= RES_STAYOPEN; /* just keep this udp socket open */
-}
-
-/*
* declaring this causes the files backend to use hashing
* this is of course an utter hack, but provides a nice
* quiet back door to enable this feature for only the nscd.
@@ -211,242 +85,11 @@ keep_open_dns_socket(void)
void
__nss_use_files_hash(void)
{
-
}
-/*
- *
- * The allocation of resources for cache lookups is an interesting
- * problem, and one that has caused several bugs in the beta release
- * of 2.5. In particular, the introduction of a thottle to prevent
- * the creation of excessive numbers of LWPs in the case of a failed
- * name service has led to a denial of service problem when the
- * name service request rate exceeds the name service's ability
- * to respond. As a result, I'm implementing the following
- * algorithm:
- *
- * 1) We cap the number of total threads.
- * 2) We save CACHE_THREADS of those for cache lookups only.
- * 3) We use a common pool of 2/3 of the remain threads that are used first
- * 4) We save the remainder and allocate 1/3 of it for table specific lookups
- *
- * The intent is to prevent the failure of a single name service from
- * causing denial of service, and to always have threads available for
- * cached lookups. If a request comes in and the answer isn't in the
- * cache and we cannot get a thread, we simply return NOSERVER, forcing
- * the client to lookup the
- * data itself. This will prevent the types of starvation seen
- * at UNC due to a single threaded DNS backend, and allows the cache
- * to eventually become filled.
- *
- */
-/* 7 tables: passwd, group, hosts, ipnodes, exec_attr, prof_attr, user_attr */
-#define NSCD_TABLES 7
-#define TABLE_THREADS 10
-#define COMMON_THREADS 20
-#define CACHE_MISS_THREADS (COMMON_THREADS + NSCD_TABLES * TABLE_THREADS)
-#define CACHE_HIT_THREADS 20
-#define MAX_SERVER_THREADS (CACHE_HIT_THREADS + CACHE_MISS_THREADS)
-
-static sema_t common_sema;
-static sema_t passwd_sema;
-static sema_t hosts_sema;
-static sema_t nodes_sema;
-static sema_t group_sema;
-static sema_t exec_sema;
-static sema_t prof_sema;
-static sema_t user_sema;
-static thread_key_t lookup_state_key;
-
-static void
-initialize_lookup_clearance(void)
-{
- thr_keycreate(&lookup_state_key, NULL);
- (void) sema_init(&common_sema, COMMON_THREADS, USYNC_THREAD, 0);
- (void) sema_init(&passwd_sema, TABLE_THREADS, USYNC_THREAD, 0);
- (void) sema_init(&hosts_sema, TABLE_THREADS, USYNC_THREAD, 0);
- (void) sema_init(&nodes_sema, TABLE_THREADS, USYNC_THREAD, 0);
- (void) sema_init(&group_sema, TABLE_THREADS, USYNC_THREAD, 0);
- (void) sema_init(&exec_sema, TABLE_THREADS, USYNC_THREAD, 0);
- (void) sema_init(&prof_sema, TABLE_THREADS, USYNC_THREAD, 0);
- (void) sema_init(&user_sema, TABLE_THREADS, USYNC_THREAD, 0);
-}
-
-int
-get_clearance(int callnumber)
-{
- sema_t *table_sema = NULL;
- char *tab;
-
- if (sema_trywait(&common_sema) == 0) {
- thr_setspecific(lookup_state_key, NULL);
- return (0);
- }
-
- switch (MASKUPDATEBIT(callnumber)) {
-
- case GETPWUID:
- case GETPWNAM:
- tab = "passwd";
- table_sema = &passwd_sema;
- break;
-
- case GETGRNAM:
- case GETGRGID:
- tab = "group";
- table_sema = &group_sema;
- break;
-
- case GETHOSTBYNAME:
- case GETHOSTBYADDR:
- tab = "hosts";
- table_sema = &hosts_sema;
- break;
-
- case GETIPNODEBYNAME:
- case GETIPNODEBYADDR:
- tab = "ipnodes";
- table_sema = &nodes_sema;
- break;
- case GETEXECID:
- tab = "exec_attr";
- table_sema = &exec_sema;
- break;
-
- case GETPROFNAM:
- tab = "prof_attr";
- table_sema = &prof_sema;
- break;
-
- case GETUSERNAM:
- tab = "user_attr";
- table_sema = &user_sema;
- break;
-
- }
-
- if (sema_trywait(table_sema) == 0) {
- thr_setspecific(lookup_state_key, (void*)1);
- return (0);
- }
-
- if (current_admin.debug_level >= DBG_CANT_FIND) {
- logit("get_clearance: throttling load for %s table\n", tab);
- }
- return (-1);
-}
-
-int
-release_clearance(int callnumber)
-{
- int which;
-
- sema_t *table_sema = NULL;
-
- thr_getspecific(lookup_state_key, (void**)&which);
-
- if (which == 0) /* from common pool */ {
- (void) sema_post(&common_sema);
- return (0);
- }
-
- switch (MASKUPDATEBIT(callnumber)) {
-
- case GETPWUID:
- case GETPWNAM:
- table_sema = &passwd_sema;
- break;
-
- case GETGRNAM:
- case GETGRGID:
- table_sema = &group_sema;
- break;
-
- case GETHOSTBYNAME:
- case GETHOSTBYADDR:
- table_sema = &hosts_sema;
- break;
-
- case GETIPNODEBYNAME:
- case GETIPNODEBYADDR:
- table_sema = &nodes_sema;
- break;
-
- case GETEXECID:
- table_sema = &exec_sema;
- break;
-
- case GETPROFNAM:
- table_sema = &prof_sema;
- break;
-
- case GETUSERNAM:
- table_sema = &user_sema;
- break;
- }
-
- (void) sema_post(table_sema);
- return (0);
-}
-
-
-static mutex_t create_lock;
-static int nscd_max_servers = MAX_SERVER_THREADS;
-static int num_servers = 0;
-static thread_key_t server_key;
-
-/*
- * Bind a TSD value to a server thread. This enables the destructor to
- * be called if/when this thread exits. This would be a programming error,
- * but better safe than sorry.
- */
-/*ARGSUSED*/
-static void *
-server_tsd_bind(void *arg)
-{
- static void *value = 0;
-
- /* disable cancellation to avoid hangs if server threads disappear */
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
- thr_setspecific(server_key, value);
- door_return(NULL, 0, NULL, 0);
-
- /* make lint happy */
- return (NULL);
-}
-
-/*
- * Server threads are created here.
- */
-/*ARGSUSED*/
-static void
-server_create(door_info_t *dip)
-{
- (void) mutex_lock(&create_lock);
- if (++num_servers > nscd_max_servers) {
- num_servers--;
- (void) mutex_unlock(&create_lock);
- return;
- }
- (void) mutex_unlock(&create_lock);
- thr_create(NULL, 0, server_tsd_bind, NULL, THR_BOUND|THR_DETACHED,
- NULL);
-}
-
-/*
- * Server thread are destroyed here
- */
-/*ARGSUSED*/
-static void
-server_destroy(void *arg)
-{
- (void) mutex_lock(&create_lock);
- num_servers--;
- (void) mutex_unlock(&create_lock);
-}
-
-static char **saved_argv;
-static char saved_execname[MAXPATHLEN];
+static int saved_argc = 0;
+static char **saved_argv = NULL;
+static char saved_execname[MAXPATHLEN];
static void
save_execname()
@@ -457,23 +100,31 @@ save_execname()
if (name[0] != '/') { /* started w/ relative path */
(void) getcwd(saved_execname, MAXPATHLEN);
- strlcat(saved_execname, "/", MAXPATHLEN);
+ (void) strlcat(saved_execname, "/", MAXPATHLEN);
}
- strlcat(saved_execname, name, MAXPATHLEN);
+ (void) strlcat(saved_execname, name, MAXPATHLEN);
}
int
main(int argc, char ** argv)
{
- int did;
- int opt;
- int errflg = 0;
- int showstats = 0;
- int doset = 0;
- int loaded_config_file = 0;
- struct stat buf;
- sigset_t myset;
- struct sigaction action;
+ int opt;
+ int errflg = 0;
+ int showstats = 0;
+ int doset = 0;
+ nscd_rc_t rc;
+ char *me = "main()";
+ char *ret_locale;
+ char *ret_textdomain;
+ char msg[128];
+
+ ret_locale = setlocale(LC_ALL, "");
+ if (ret_locale == NULL)
+ (void) fprintf(stderr, gettext("Unable to set locale\n"));
+
+ ret_textdomain = textdomain(TEXT_DOMAIN);
+ if (ret_textdomain == NULL)
+ (void) fprintf(stderr, gettext("Unable to set textdomain\n"));
/*
* The admin model for TX is that labeled zones are managed
@@ -482,250 +133,207 @@ main(int argc, char ** argv)
*/
if (is_system_labeled() && (getzoneid() != GLOBAL_ZONEID)) {
(void) fprintf(stderr,
- "With Trusted Extensions nscd runs only in " \
- "the global zone.\n");
+gettext("With Trusted Extensions nscd runs only in the global zone.\n"));
exit(1);
}
/*
- * Special case non-root user here - he can just print stats
+ * Special case non-root user here - he can just print stats
*/
-
if (geteuid()) {
- if (argc != 2 || strcmp(argv[1], "-g")) {
+ if (argc != 2 ||
+ (strcmp(argv[1], "-g") && strcmp(argv[1], "-G"))) {
(void) fprintf(stderr,
- "Must be root to use any option other than "\
- "-g.\n\n");
+ gettext("Must be root to use any option other than -g\n\n"));
usage(argv[0]);
}
- if ((nsc_ping() != SUCCESS) ||
- (client_getadmin(&current_admin) != 0)) {
+ if (_nscd_doorcall(NSCD_PING) != NSS_SUCCESS) {
(void) fprintf(stderr,
- "%s doesn't appear to be running.\n", argv[0]);
+ gettext("%s doesn't appear to be running.\n"),
+ argv[0]);
exit(1);
}
- client_showstats(&current_admin);
+ if (_nscd_client_getadmin(argv[1][1]) != 0) {
+ (void) fprintf(stderr,
+ gettext("unable to get configuration and statistics data\n"));
+ exit(1);
+ }
+
+ _nscd_client_showstats();
exit(0);
}
-
-
/*
- * Determine if there is already a daemon running
+ * Determine if there is already a daemon (main nscd) running.
+ * If not, will start it. Forker NSCD will always become a
+ * daemon.
*/
+ will_become_server = (_nscd_doorcall(NSCD_PING) != NSS_SUCCESS);
+ if (argc >= 2 && strcmp(argv[1], "-F") == 0) {
+ will_become_server = 1;
+ _whoami = NSCD_FORKER;
- will_become_server = (nsc_ping() != SUCCESS);
-
- /*
- * process usual options
- */
+ /*
+ * allow time for the main nscd to get ready
+ * to receive the IMHERE door request this
+ * process will send later
+ */
+ (void) usleep(100000);
+ }
/*
- * load normal config file
+ * first get the config file path. Also detect
+ * invalid option as soon as possible.
*/
+ while ((opt = getopt(argc, argv, NSCDOPT)) != EOF) {
+ switch (opt) {
- if (will_become_server) {
- static const nsc_stat_t defaults = {
- 0, /* stats */
- 0, /* stats */
- 0, /* stats */
- 0, /* stats */
- 0, /* stats */
- 0, /* stats */
- 0, /* stats */
- 211, /* suggested size */
- 1, /* enabled */
- 0, /* invalidate cmd */
- 600, /* positive ttl */
- 10, /* netative ttl */
- 20, /* keep hot */
- 0, /* old data not ok */
- 1 }; /* check files */
-
- current_admin.passwd = defaults;
- current_admin.group = defaults;
- current_admin.host = defaults;
- current_admin.node = defaults;
- current_admin.exec = defaults;
- current_admin.prof = defaults;
- current_admin.user = defaults;
-
- current_admin.logfile[0] = '\0';
-
- if (access("/etc/nscd.conf", R_OK) == 0) {
- if (nscd_parse(argv[0], "/etc/nscd.conf") < 0) {
+ case 'f':
+ if ((cfgfile = strdup(optarg)) == NULL)
exit(1);
+ break;
+ case 'g':
+ if (will_become_server) {
+ (void) fprintf(stderr,
+ gettext("nscd not running, no statistics to show\n\n"));
+ errflg++;
+ }
+ break;
+ case 'i':
+ if (will_become_server) {
+ (void) fprintf(stderr,
+ gettext("nscd not running, no cache to invalidate\n\n"));
+ errflg++;
}
- loaded_config_file++;
+ break;
+
+ case '?':
+ errflg++;
+ break;
}
+
}
+ if (errflg)
+ usage(argv[0]);
+
+ /*
+ * perform more initialization and load configuration
+ * if to become server
+ */
+ if (will_become_server) {
- else {
- if (client_getadmin(&current_admin)) {
+ /* initialize switch engine and config/stats management */
+ if ((rc = _nscd_init(cfgfile)) != NSCD_SUCCESS) {
(void) fprintf(stderr,
- "Cannot contact nscd properly(?)\n");
+ gettext("initialization of switch failed (rc = %d)\n"), rc);
exit(1);
}
- current_admin.logfile[0] = '\0';
+ /*
+ * initialize cache store
+ */
+ if ((rc = init_cache(0)) != NSCD_SUCCESS) {
+ (void) fprintf(stderr,
+ gettext("initialization of cache store failed (rc = %d)\n"), rc);
+ exit(1);
+ }
}
- while ((opt = getopt(argc, argv,
- "S:Kf:c:ge:p:n:i:l:d:s:h:o:")) != EOF) {
- nsc_stat_t *cache;
- char *cacheopt;
+ /*
+ * process usual options
+ */
+ optind = 1; /* this is a rescan */
+ *msg = '\0';
+ while ((opt = getopt(argc, argv, NSCDOPT)) != EOF) {
switch (opt) {
- case 'S': /* undocumented feature */
- doset++;
- cache = getcacheptr(optarg);
- cacheopt = getcacheopt(optarg);
- if (!cache || !cacheopt) {
- errflg++;
- break;
- }
- if (strcmp(cacheopt, "yes") == 0)
- cache->nsc_secure_mode = 1;
- else if (strcmp(cacheopt, "no") == 0)
- cache->nsc_secure_mode = 0;
- else
- errflg++;
- break;
-
case 'K': /* undocumented feature */
- client_killserver();
+ (void) _nscd_doorcall(NSCD_KILLSERVER);
exit(0);
break;
- case 'f':
- doset++;
- loaded_config_file++;
- if (nscd_parse(argv[0], optarg) < 0) {
- exit(1);
- }
- break;
-
+ case 'G':
case 'g':
showstats++;
break;
case 'p':
doset++;
- cache = getcacheptr(optarg);
- cacheopt = getcacheopt(optarg);
- if (!cache || !cacheopt) {
+ if (_nscd_add_admin_mod(optarg, 'p',
+ getcacheopt(optarg),
+ msg, sizeof (msg)) == -1)
errflg++;
- break;
- }
- cache->nsc_pos_ttl = atoi(cacheopt);
break;
case 'n':
doset++;
- cache = getcacheptr(optarg);
- cacheopt = getcacheopt(optarg);
- if (!cache || !cacheopt) {
+ if (_nscd_add_admin_mod(optarg, 'n',
+ getcacheopt(optarg),
+ msg, sizeof (msg)) == -1)
errflg++;
- break;
- }
- cache->nsc_neg_ttl = atoi(cacheopt);
break;
case 'c':
doset++;
- cache = getcacheptr(optarg);
- cacheopt = getcacheopt(optarg);
- if (!cache || !cacheopt) {
+ if (_nscd_add_admin_mod(optarg, 'c',
+ getcacheopt(optarg),
+ msg, sizeof (msg)) == -1)
errflg++;
- break;
- }
-
- if (strcmp(cacheopt, "yes") == 0)
- cache->nsc_check_files = 1;
- else if (strcmp(cacheopt, "no") == 0)
- cache->nsc_check_files = 0;
- else
- errflg++;
break;
-
case 'i':
doset++;
- cache = getcacheptr(optarg);
- if (!cache) {
+ if (_nscd_add_admin_mod(optarg, 'i', NULL,
+ msg, sizeof (msg)) == -1)
errflg++;
- break;
- }
- cache->nsc_invalidate = 1;
break;
case 'l':
doset++;
- (void) strlcpy(current_admin.logfile, optarg, 128);
+ (void) strlcpy(logfile, optarg, 128);
+ (void) _nscd_add_admin_mod(NULL, 'l', optarg,
+ msg, sizeof (msg));
break;
case 'd':
-
doset++;
- current_admin.debug_level = atoi(optarg);
+ debug_level = atoi(optarg);
+ (void) _nscd_add_admin_mod(NULL, 'd', optarg,
+ msg, sizeof (msg));
break;
- case 's':
- doset++;
- cache = getcacheptr(optarg);
- cacheopt = getcacheopt(optarg);
- if (!cache || !cacheopt) {
- errflg++;
- break;
- }
+ case 'S':
+ /* silently ignore secure-mode */
+ break;
- cache->nsc_suggestedsize = atoi(cacheopt);
+ case 's':
+ /* silently ignore suggested-size */
+ break;
+ case 'o':
+ /* silently ignore old-data-ok */
break;
case 'h':
doset++;
- cache = getcacheptr(optarg);
- cacheopt = getcacheopt(optarg);
- if (!cache || !cacheopt) {
+ if (_nscd_add_admin_mod(optarg, 'h',
+ getcacheopt(optarg),
+ msg, sizeof (msg)) == -1)
errflg++;
- break;
- }
- cache->nsc_keephot = atoi(cacheopt);
break;
- case 'o':
+ case 'e':
doset++;
- cache = getcacheptr(optarg);
- cacheopt = getcacheopt(optarg);
- if (!cache || !cacheopt) {
+ if (_nscd_add_admin_mod(optarg, 'e',
+ getcacheopt(optarg),
+ msg, sizeof (msg)) == -1)
errflg++;
- break;
- }
- if (strcmp(cacheopt, "yes") == 0)
- cache->nsc_old_data_ok = 1;
- else if (strcmp(cacheopt, "no") == 0)
- cache->nsc_old_data_ok = 0;
- else
- errflg++;
break;
- case 'e':
- doset++;
- cache = getcacheptr(optarg);
- cacheopt = getcacheopt(optarg);
- if (!cache || !cacheopt) {
- errflg++;
- break;
- }
- if (strcmp(cacheopt, "yes") == 0)
- cache->nsc_enabled = 1;
- else if (strcmp(cacheopt, "no") == 0)
- cache->nsc_enabled = 0;
- else
- errflg++;
+ case 'F':
+ _whoami = NSCD_FORKER;
break;
default:
@@ -735,548 +343,123 @@ main(int argc, char ** argv)
}
- if (errflg)
+ if (errflg) {
+ if (*msg != '\0')
+ (void) fprintf(stderr, "\n%s: %s\n\n", argv[0], msg);
usage(argv[0]);
-
- if (!will_become_server) {
-
- if (showstats) {
- client_showstats(&current_admin);
- }
-
- if (doset) {
- if (client_setadmin(&current_admin) < 0) {
- (void) fprintf(stderr,
- "Error during admin call\n");
- exit(1);
- }
- }
- if (!showstats && !doset) {
- (void) fprintf(stderr,
- "%s already running.... no admin specified\n",
- argv[0]);
- }
- exit(0);
}
/*
- * daemon from here ou
+ * if main nscd already running and not forker nscd,
+ * can only do admin work
*/
+ if (_whoami == NSCD_MAIN) {
+ if (!will_become_server) {
+ if (showstats) {
+ if (_nscd_client_getadmin('g')) {
+ (void) fprintf(stderr,
+ gettext("Cannot contact nscd properly(?)\n"));
+ exit(1);
+ }
+ _nscd_client_showstats();
+ }
- if (!loaded_config_file) {
- (void) fprintf(stderr,
- "No configuration file specifed and /etc/nscd.conf" \
- "not present\n");
- exit(1);
- }
-
- saved_argv = argv;
- save_execname();
-
- if (current_admin.debug_level) {
- /* we're debugging... */
- if (strlen(current_admin.logfile) == 0)
- /* no specified log file */
- (void) strcpy(current_admin.logfile, "stderr");
- else
- (void) nscd_set_lf(&current_admin,
- current_admin.logfile);
- } else {
- if (strlen(current_admin.logfile) == 0)
- (void) strcpy(current_admin.logfile, "/dev/null");
- (void) nscd_set_lf(&current_admin, current_admin.logfile);
- detachfromtty();
- }
-
- /* perform some initialization */
- initialize_lookup_clearance();
- keep_open_dns_socket();
- getpw_init();
- getgr_init();
- gethost_init();
- getnode_init();
- getexec_init();
- getprof_init();
- getuser_init();
-
- /* Establish our own server thread pool */
-
- door_server_create(server_create);
- if (thr_keycreate(&server_key, server_destroy) != 0) {
- perror("thr_keycreate");
- exit(-1);
- }
-
- /* Create a door */
-
- if ((did = door_create(switcher, NAME_SERVICE_DOOR_COOKIE,
- DOOR_UNREF | DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) < 0) {
- perror("door_create");
- exit(-1);
- }
-
- /* bind to file system */
-
- if (is_system_labeled()) {
- if (stat(TSOL_NAME_SERVICE_DOOR, &buf) < 0) {
- int newfd;
- if ((newfd = creat(TSOL_NAME_SERVICE_DOOR, 0444)) < 0) {
- logit("Cannot create %s:%s\n",
- TSOL_NAME_SERVICE_DOOR, strerror(errno));
- exit(1);
+ if (doset) {
+ if (_nscd_client_setadmin() < 0) {
+ (void) fprintf(stderr,
+ gettext("Error during admin call\n"));
+ exit(1);
+ }
}
- (void) close(newfd);
- }
- if (symlink(TSOL_NAME_SERVICE_DOOR, NAME_SERVICE_DOOR) != 0) {
- if (errno != EEXIST) {
- logit("Cannot symlink %s:%s\n",
- NAME_SERVICE_DOOR, strerror(errno));
- exit(1);
+ if (!showstats && !doset) {
+ (void) fprintf(stderr,
+gettext("%s already running.... no administration option specified\n"),
+ argv[0]);
}
+ exit(0);
}
- } else if (stat(NAME_SERVICE_DOOR, &buf) < 0) {
- int newfd;
- if ((newfd = creat(NAME_SERVICE_DOOR, 0444)) < 0) {
- logit("Cannot create %s:%s\n", NAME_SERVICE_DOOR,
- strerror(errno));
- exit(1);
- }
- (void) close(newfd);
- }
-
- if (fattach(did, NAME_SERVICE_DOOR) < 0) {
- if ((errno != EBUSY) ||
- (fdetach(NAME_SERVICE_DOOR) < 0) ||
- (fattach(did, NAME_SERVICE_DOOR) < 0)) {
- perror("door_attach");
- exit(2);
- }
- }
-
- action.sa_handler = dozip;
- action.sa_flags = 0;
- (void) sigemptyset(&action.sa_mask);
- (void) sigemptyset(&myset);
- (void) sigaddset(&myset, SIGHUP);
-
- if (sigaction(SIGHUP, &action, NULL) < 0) {
- perror("sigaction");
- exit(1);
- }
-
- if (thr_sigsetmask(SIG_BLOCK, &myset, NULL) < 0) {
- perror("thr_sigsetmask");
- exit(1);
- }
-
-
- /*
- * kick off revalidate threads
- */
-
- if (thr_create(NULL, NULL,
- (void *(*)(void *))getpw_revalidate, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void *))gethost_revalidate, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void*))getnode_revalidate, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void*))getgr_revalidate, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void*))getexec_revalidate, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void*))getprof_revalidate, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void*))getuser_revalidate, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- /*
- * kick off reaper threads
- */
-
- if (thr_create(NULL, NULL,
- (void *(*)(void *))getpw_uid_reaper, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void *))getpw_nam_reaper, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void *))getgr_uid_reaper, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void *))getgr_nam_reaper, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
-
- if (thr_create(NULL, NULL,
- (void *(*)(void *))gethost_nam_reaper, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void *))gethost_addr_reaper, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void *))getnode_nam_reaper, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void *))getnode_addr_reaper, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void *))getexec_reaper, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void *))getprof_reaper, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
-
- if (thr_create(NULL, NULL,
- (void *(*)(void *))getuser_reaper, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
}
/*
- * kick off routing socket monitor thread
+ * daemon from here on
*/
- if (thr_create(NULL, NULL,
- (void *(*)(void *))rts_mon, 0, 0, NULL) != 0) {
- perror("thr_create");
- exit(1);
- }
+ if (_whoami == NSCD_MAIN) {
- if (thr_sigsetmask(SIG_UNBLOCK, &myset, NULL) < 0) {
- perror("thr_sigsetmask");
- return (1);
- }
-
- for (;;) {
- (void) pause();
- logit("Reloading /etc/nscd.conf\n");
- nscd_parse(argv[0], "/etc/nscd.conf");
- }
-}
-
-
-/*ARGSUSED*/
-static void
-switcher(void *cookie, char *argp, size_t arg_size,
- door_desc_t *dp, uint_t n_desc)
-{
- union {
- nsc_data_t data;
- char space[8192];
- } u;
-
- time_t now;
-
- static time_t last_nsswitch_check;
- static time_t last_nsswitch_modified;
- static time_t last_resolv_modified;
-
- static mutex_t nsswitch_lock;
-
- nsc_call_t *ptr = (nsc_call_t *)argp;
-
- if (argp == DOOR_UNREF_DATA) {
- (void) printf("Door Slam... exiting\n");
- exit(0);
- }
-
- if (ptr == NULL) { /* empty door call */
- (void) door_return(NULL, 0, 0, 0); /* return the favor */
- }
-
- now = time(NULL);
-
- /*
- * just in case check
- */
-
- (void) mutex_lock(&nsswitch_lock);
-
- if (now - last_nsswitch_check > 10) {
- struct stat nss_buf;
- struct stat res_buf;
-
- last_nsswitch_check = now;
-
- (void) mutex_unlock(&nsswitch_lock); /* let others continue */
+ /* save enough info in case need to restart or fork */
+ saved_argc = argc;
+ saved_argv = argv;
+ save_execname();
/*
- * This code keeps us from statting resolv.conf
- * if it doesn't exist, yet prevents us from ignoring
- * it if it happens to disappear later on for a bit.
+ * if a log file is not specified, set it to
+ * "stderr" or "/dev/null" based on debug level
*/
+ if (_logfd < 0 && *logfile == '\0') {
+ if (debug_level != 0)
+ /* we're debugging... */
+ (void) strcpy(logfile, "stderr");
+ else
+ (void) strcpy(logfile, "/dev/null");
- if (last_resolv_modified >= 0) {
- if (stat("/etc/resolv.conf", &res_buf) < 0) {
- if (last_resolv_modified == 0)
- last_resolv_modified = -1;
- else
- res_buf.st_mtime = last_resolv_modified;
- } else if (last_resolv_modified == 0) {
- last_resolv_modified = res_buf.st_mtime;
- }
+ (void) _nscd_add_admin_mod(NULL, 'l', logfile,
+ msg, sizeof (msg));
}
- if (stat("/etc/nsswitch.conf", &nss_buf) < 0) {
-
- /*EMPTY*/;
-
- } else if (last_nsswitch_modified == 0) {
+ /* activate command options */
+ if (_nscd_server_setadmin(NULL) != NSCD_SUCCESS) {
+ (void) fprintf(stderr,
+ gettext("unable to set command line options\n"));
+ exit(1);
+ }
- last_nsswitch_modified = nss_buf.st_mtime;
+ if (debug_level) {
+ /* we're debugging, no forking of nscd */
- } else if ((last_nsswitch_modified < nss_buf.st_mtime) ||
- ((last_resolv_modified > 0) &&
- (last_resolv_modified < res_buf.st_mtime))) {
- static mutex_t exit_lock;
- char *fmri;
/*
- * time for restart
+ * forker nscd will be started if self credential
+ * is configured
*/
- logit("nscd restart due to /etc/nsswitch.conf or "\
- "resolv.conf change\n");
+ _nscd_start_forker(saved_execname, saved_argc,
+ saved_argv);
+ } else {
/*
- * try to restart under smf
+ * daemonize the nscd (forker nscd will also
+ * be started if self credential is configured)
*/
- if ((fmri = getenv("SMF_FMRI")) == NULL) {
- /* not running under smf - reexec */
- execv(saved_execname, saved_argv);
- exit(1); /* just in case */
- }
-
- mutex_lock(&exit_lock); /* prevent multiple restarts */
- if (smf_restart_instance(fmri) == 0)
- sleep(10); /* wait a bit */
- exit(1); /* give up waiting for resurrection */
+ detachfromtty();
}
-
- } else
- (void) mutex_unlock(&nsswitch_lock);
-
- switch (ptr->nsc_callnumber) {
-
- case NULLCALL:
- u.data.nsc_ret.nsc_return_code = SUCCESS;
- u.data.nsc_ret.nsc_bufferbytesused = sizeof (nsc_return_t);
- break;
-
-
- case GETPWNAM:
- *(argp + arg_size - 1) = 0; /* FALLTHROUGH */
- case GETPWUID:
- getpw_lookup(&u.data.nsc_ret, sizeof (u), ptr, now);
- break;
-
- case GETGRNAM:
- *(argp + arg_size - 1) = 0; /* FALLTHROUGH */
- case GETGRGID:
- getgr_lookup(&u.data.nsc_ret, sizeof (u), ptr, now);
- break;
-
- case GETHOSTBYNAME:
- *(argp + arg_size - 1) = 0; /* FALLTHROUGH */
- case GETHOSTBYADDR:
- gethost_lookup(&u.data.nsc_ret, sizeof (u), ptr, now);
- break;
-
- case GETIPNODEBYNAME:
- *(argp + arg_size - 1) = 0; /* FALLTHROUGH */
- case GETIPNODEBYADDR:
- getnode_lookup(&u.data.nsc_ret, sizeof (u), ptr, now);
- break;
-
- case GETEXECID:
- *(argp + arg_size - 1) = 0;
- getexec_lookup(&u.data.nsc_ret, sizeof (u), ptr, now);
- break;
-
- case GETPROFNAM:
- *(argp + arg_size - 1) = 0;
- getprof_lookup(&u.data.nsc_ret, sizeof (u), ptr, now);
- break;
-
- case GETUSERNAM:
- *(argp + arg_size - 1) = 0;
- getuser_lookup(&u.data.nsc_ret, sizeof (u), ptr, now);
- break;
-
- case GETADMIN:
- getadmin(&u.data.nsc_ret, sizeof (u), ptr);
- break;
-
- case SETADMIN:
- case KILLSERVER: {
-
- ucred_t *uc = NULL;
- const priv_set_t *eset;
- zoneid_t zoneid;
-
- if (door_ucred(&uc) != 0) {
- perror("door_ucred");
- u.data.nsc_ret.nsc_return_code = NOTFOUND;
- break;
- }
-
- eset = ucred_getprivset(uc, PRIV_EFFECTIVE);
- zoneid = ucred_getzoneid(uc);
-
- if ((zoneid != GLOBAL_ZONEID && zoneid != getzoneid()) ||
- eset != NULL ? !priv_ismember(eset, PRIV_SYS_ADMIN) :
- ucred_geteuid(uc) != 0) {
- logit("SETADMIN call failed(cred): caller pid %d, "
- "uid %d, euid %d, zoneid %d\n", ucred_getpid(uc),
- ucred_getruid(uc), ucred_geteuid(uc), zoneid);
- u.data.nsc_ret.nsc_return_code = NOTFOUND;
- ucred_free(uc);
- break;
- }
-
- if (ptr->nsc_callnumber == KILLSERVER) {
- logit("Nscd received KILLSERVER cmd from pid %d, "
- "uid %d, euid %d, zoneid %d\n", ucred_getpid(uc),
- ucred_getruid(uc), ucred_geteuid(uc), zoneid);
- exit(0);
- } else {
- if (setadmin(&u.data.nsc_ret, sizeof (u), ptr) != 0)
- logit("SETADMIN call failed\n");
- }
- ucred_free(uc);
- break;
+ } else { /* NSCD_FORKER */
+ (void) open("/dev/null", O_RDWR, 0);
+ (void) dup(0);
+ if (_logfd != 2)
+ (void) dup(0);
}
- default:
- logit("Unknown name service door call op %d\n",
- ptr->nsc_callnumber);
- u.data.nsc_ret.nsc_return_code = -1;
- u.data.nsc_ret.nsc_bufferbytesused = sizeof (nsc_return_t);
- break;
-
+ /* set up door and establish our own server thread pool */
+ if ((_doorfd = _nscd_setup_server(saved_execname, saved_argv)) == -1) {
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to set up door\n");
+ exit(1);
}
- door_return((char *)&u.data, u.data.nsc_ret.nsc_bufferbytesused,
- NULL, 0);
-}
-/*
- * Monitor the routing socket. Address lists stored in the ipnodes
- * cache are sorted based on destination address selection rules,
- * so when things change that could affect that sorting (interfaces
- * go up or down, flags change, etc.), we clear that cache so the
- * list will be re-ordered the next time the hostname is resolved.
- */
-static void
-rts_mon(void)
-{
- int rt_sock, rdlen;
- union {
- struct {
- struct rt_msghdr rtm;
- struct sockaddr_storage addrs[RTA_NUMBITS];
- } r;
- struct if_msghdr ifm;
- struct ifa_msghdr ifam;
- } mbuf;
- struct ifa_msghdr *ifam = &mbuf.ifam;
-
- rt_sock = socket(PF_ROUTE, SOCK_RAW, 0);
- if (rt_sock < 0) {
- logit("Failed to open routing socket: %s\n", strerror(errno));
- thr_exit(0);
+ /* inform the main nscd that this forker is ready */
+ if (_whoami == NSCD_FORKER) {
+ int ret;
+
+ for (ret = NSS_ALTRETRY; ret == NSS_ALTRETRY; )
+ ret = _nscd_doorcall_sendfd(_doorfd,
+ NSCD_IMHERE | (NSCD_FORKER & NSCD_WHOAMI),
+ NULL, 0, NULL);
}
for (;;) {
- rdlen = read(rt_sock, &mbuf, sizeof (mbuf));
- if (rdlen <= 0) {
- if (rdlen == 0 || (errno != EINTR && errno != EAGAIN)) {
- logit("routing socket read: %s\n",
- strerror(errno));
- thr_exit(0);
- }
- continue;
- }
- if (ifam->ifam_version != RTM_VERSION) {
- logit("rx unknown version (%d) on routing socket.\n",
- ifam->ifam_version);
- continue;
- }
- switch (ifam->ifam_type) {
- case RTM_NEWADDR:
- case RTM_DELADDR:
- getnode_name_invalidate();
- break;
- case RTM_ADD:
- case RTM_DELETE:
- case RTM_CHANGE:
- case RTM_GET:
- case RTM_LOSING:
- case RTM_REDIRECT:
- case RTM_MISS:
- case RTM_LOCK:
- case RTM_OLDADD:
- case RTM_OLDDEL:
- case RTM_RESOLVE:
- case RTM_IFINFO:
- break;
- default:
- logit("rx unknown msg type (%d) on routing socket.\n",
- ifam->ifam_type);
- break;
- }
+ (void) pause();
+ (void) _nscd_doorcall(NSCD_REFRESH);
}
+
+ /* NOTREACHED */
+ /*LINTED E_FUNC_HAS_NO_RETURN_STMT*/
}
static void
@@ -1289,609 +472,43 @@ usage(char *s)
(void) fprintf(stderr,
" [-n cachename,negative_time_to_live]\n");
(void) fprintf(stderr,
- " [-i cachename] [-s cachename,suggestedsize]\n");
-
+ " [-i cachename]\n");
(void) fprintf(stderr,
- " [-h cachename,keep_hot_count] "\
- "[-o cachename,\"yes\"|\"no\"]\n");
-
+ " [-h cachename,keep_hot_count]\n");
(void) fprintf(stderr,
" [-e cachename,\"yes\"|\"no\"] [-g] " \
"[-c cachename,\"yes\"|\"no\"]\n");
-
(void) fprintf(stderr,
" [-f configfilename] \n");
-
(void) fprintf(stderr,
- "\n Supported caches: passwd, group, hosts, ipnodes\n");
-
+ "\n Supported caches:\n");
(void) fprintf(stderr,
- " exec_attr, prof_attr, and user_attr.\n");
-
+ " audit_user, auth_attr, bootparams, ethers\n");
+ (void) fprintf(stderr,
+ " exec_attr, group, hosts, ipnodes, netmasks\n");
+ (void) fprintf(stderr,
+ " networks, passwd, printers, prof_attr, project\n");
+ (void) fprintf(stderr,
+ " protocols, rpc, services, tnrhtp, tnrhdb\n");
+ (void) fprintf(stderr,
+ " user_attr\n");
exit(1);
-
-}
-
-
-static int logfd = 2;
-
-int
-nscd_set_lf(admin_t *ptr, char *s)
-{
- int newlogfd;
-
- /*
- * we don't really want to try and open the log file
- * /dev/null since that will fail w/ our security fixes
- */
-
- if (*s == 0) {
- /* ignore empty log file specs */
- /*EMPTY*/;
- } else if (s == NULL || strcmp(s, "/dev/null") == 0) {
- (void) strcpy(current_admin.logfile, "/dev/null");
- (void) close(logfd);
- logfd = -1;
- } else {
- /*
- * In order to open this file securely, we'll try a few tricks
- */
-
- if ((newlogfd = open(s, O_EXCL|O_WRONLY|O_CREAT, 0644)) < 0) {
- /*
- * File already exists... now we need to get cute
- * since opening a file in a world-writeable directory
- * safely is hard = it could be a hard link or a
- * symbolic link to a system file.
- */
- struct stat before;
-
- if (lstat(s, &before) < 0) {
- logit("Cannot open new logfile \"%s\": %sn",
- s, strerror(errno));
- return (-1);
- }
-
- if (S_ISREG(before.st_mode) && /* no symbolic links */
- (before.st_nlink == 1) && /* no hard links */
- (before.st_uid == 0)) { /* owned by root */
- if ((newlogfd =
- open(s, O_APPEND|O_WRONLY, 0644)) < 0) {
- logit("Cannot open new "\
- "logfile \"%s\": %s\n", s,
- strerror(errno));
- return (-1);
- }
- } else {
- logit("Cannot use specified logfile \"%s\": "\
- "file is/has links or isn't owned by "\
- "root\n", s);
- return (-1);
- }
- }
-
- (void) strlcpy(ptr->logfile, s, 128);
- (void) close(logfd);
- logfd = newlogfd;
- logit("Start of new logfile %s\n", s);
- }
- return (0);
-}
-
-void
-logit(char *format, ...)
-{
- static mutex_t loglock;
- struct timeval tv;
-
-#define LOGBUFLEN 1024
- char buffer[LOGBUFLEN];
-
- va_list ap;
- va_start(ap, format);
-
- if (logfd >= 0) {
- int safechars, offset;
- if (gettimeofday(&tv, NULL) != 0 ||
- ctime_r(&tv.tv_sec, buffer, LOGBUFLEN) == NULL) {
- (void) snprintf(buffer, LOGBUFLEN,
- "<time conversion failed>\t");
- } else {
- /*
- * ctime_r() includes some stuff we don't want;
- * adjust length to overwrite " YYYY\n".
- */
- offset = strlen(buffer) - 6;
- safechars = LOGBUFLEN - (offset - 1);
- (void) snprintf(buffer + offset, safechars, ".%.4ld\t",
- tv.tv_usec/100);
- }
- offset = strlen(buffer);
- safechars = LOGBUFLEN - (offset - 1);
- if (vsnprintf(buffer + offset, safechars, format, ap) >
- safechars) {
- (void) strncat(buffer, "...\n", LOGBUFLEN);
- }
-
- (void) mutex_lock(&loglock);
- (void) write(logfd, buffer, strlen(buffer));
- (void) mutex_unlock(&loglock);
- }
-
- va_end(ap);
-#undef LOGBUFLEN
}
-static void
-do_update(nsc_call_t *in)
-{
- union {
- nsc_data_t data;
- char space[8192];
- } u;
-
- time_t now = time(NULL);
-
- switch (MASKUPDATEBIT(in->nsc_callnumber)) {
-
- case GETPWUID:
- case GETPWNAM:
- getpw_lookup(&u.data.nsc_ret, sizeof (u), in, now);
- break;
-
- case GETGRNAM:
- case GETGRGID:
- getgr_lookup(&u.data.nsc_ret, sizeof (u), in, now);
- break;
-
- case GETHOSTBYNAME:
- case GETHOSTBYADDR:
- gethost_lookup(&u.data.nsc_ret, sizeof (u), in, now);
- break;
-
- case GETIPNODEBYNAME:
- case GETIPNODEBYADDR:
- getnode_lookup(&u.data.nsc_ret, sizeof (u), in, now);
- break;
-
- case GETEXECID:
- getexec_lookup(&u.data.nsc_ret, sizeof (u), in, now);
- break;
-
- case GETPROFNAM:
- getprof_lookup(&u.data.nsc_ret, sizeof (u), in, now);
- break;
-
- case GETUSERNAM:
- getuser_lookup(&u.data.nsc_ret, sizeof (u), in, now);
- break;
-
- default:
- assert(0);
- break;
- }
-
- free(in);
-}
-
-int
-launch_update(nsc_call_t *in)
-{
- nsc_call_t *c;
-
- int l = nsc_calllen(in);
-
- in->nsc_callnumber |= UPDATEBIT;
-
- if ((c = malloc(l)) == NULL) {
- logit("thread create failed: %s\n", strerror(errno));
- exit(1);
- }
- (void) memcpy(c, in, l);
-
- if (current_admin.debug_level >= DBG_ALL) {
- logit("launching update\n");
- }
-
- if (thr_create(NULL,
- NULL,
- (void *(*)(void*))do_update,
- c,
- 0|THR_DETACHED, NULL) != 0) {
- logit("thread create failed\n");
- exit(1);
- }
-
- return (0);
-}
-
-static int
-nsc_calllen(nsc_call_t *in)
-{
- switch (MASKUPDATEBIT(in->nsc_callnumber)) {
-
- case GETPWUID:
- case GETGRGID:
- case NULLCALL:
- return (sizeof (*in));
-
- case GETPWNAM:
- case GETGRNAM:
- case GETHOSTBYNAME:
- return (sizeof (*in) + strlen(in->nsc_u.name));
- case GETIPNODEBYNAME:
- return (sizeof (*in) + strlen(in->nsc_u.ipnode.name));
-
- case GETHOSTBYADDR:
- case GETIPNODEBYADDR:
- return (sizeof (*in) + in->nsc_u.addr.a_length);
-
- case GETEXECID:
- case GETPROFNAM:
- case GETUSERNAM:
-
- return (sizeof (*in) + strlen(in->nsc_u.name));
- }
-
- return (0);
-}
-
-static int
-client_getadmin(admin_t *ptr)
-{
- union {
- nsc_data_t data;
- char space[8192];
- } u;
-
- nsc_data_t *dptr;
- int ndata;
- int adata;
-
- u.data.nsc_call.nsc_callnumber = GETADMIN;
- ndata = sizeof (u);
- adata = sizeof (u.data);
- dptr = &u.data;
-
- if (_nsc_trydoorcall(&dptr, &ndata, &adata) != SUCCESS) {
- return (-1);
- }
-
- (void) memcpy(ptr, dptr->nsc_ret.nsc_u.buff, sizeof (*ptr));
- return (0);
-}
-
-/*ARGSUSED*/
-static void
-getadmin(nsc_return_t *out, int size, nsc_call_t *ptr)
-{
- out->nsc_return_code = SUCCESS;
- out->nsc_bufferbytesused = sizeof (current_admin);
- (void) memcpy(out->nsc_u.buff, &current_admin, sizeof (current_admin));
-}
-
-
-static int
-nscd_set_rbac(admin_t *new_admin, int invalidate)
-{
- int i;
- char *dbname = NULL;
- nsc_stat_t *cache = NULL;
- nsc_stat_t *new = NULL;
- void (*invalidate_func)(void);
-
-
- for (i = 1; i <= 3; i++) {
- /*
- * Three of the RBAC databases are cached.
- */
- switch (i) {
- case 1:
- dbname = NSS_DBNAM_EXECATTR;
- cache = &current_admin.exec;
- new = &new_admin->exec;
- invalidate_func = getexec_invalidate;
- break;
- case 2:
- dbname = NSS_DBNAM_PROFATTR;
- cache = &current_admin.prof;
- new = &new_admin->prof;
- invalidate_func = getprof_invalidate;
- break;
- case 3:
- dbname = NSS_DBNAM_USERATTR;
- cache = &current_admin.user;
- new = &new_admin->user;
- invalidate_func = getuser_invalidate;
- break;
- default:
- break;
- }
-
- if (invalidate) {
- if (new->nsc_invalidate) {
- logit("Invalidating %s cache\n", dbname);
- (*invalidate_func)();
- }
- } else {
- if (nscd_set_ttl_positive(cache, dbname,
- new->nsc_pos_ttl) < 0 ||
- nscd_set_ttl_negative(cache, dbname,
- new->nsc_neg_ttl) < 0 ||
- nscd_set_khc(cache, dbname, new->nsc_keephot) < 0 ||
- nscd_set_odo(cache, dbname,
- new->nsc_old_data_ok) < 0 ||
- nscd_set_ec(cache, dbname, new->nsc_enabled) < 0 ||
- nscd_set_ss(cache, dbname,
- new->nsc_suggestedsize) < 0)
- return (-1);
- }
- }
-
- return (0);
-}
-
-/*ARGSUSED*/
-static int
-setadmin(nsc_return_t *out, int size, nsc_call_t *ptr)
-{
- admin_t *new;
-
- out->nsc_return_code = SUCCESS;
- out->nsc_bufferbytesused = sizeof (nsc_return_t);
-
- new = (admin_t *)ptr->nsc_u.name;
-
-
- /*
- * global admin stuff
- */
-
- if ((nscd_set_lf(&current_admin, new->logfile) < 0) ||
- nscd_set_dl(&current_admin, new->debug_level) < 0) {
- out->nsc_return_code = NOTFOUND;
- return (-1);
- }
-
- /*
- * per cache items
- */
-
- if (new->passwd.nsc_invalidate) {
- logit("Invalidating passwd cache\n");
- getpw_invalidate();
- }
-
- if (new->group.nsc_invalidate) {
- logit("Invalidating group cache\n");
- getgr_invalidate();
- }
-
- if (new->host.nsc_invalidate) {
- logit("Invalidating host cache\n");
- gethost_invalidate();
- }
-
- if (new->node.nsc_invalidate) {
- logit("Invalidating ipnodes cache\n");
- getnode_invalidate();
- }
-
- (void) nscd_set_rbac(new, 1); /* invalidate rbac cache */
-
- if (nscd_set_ttl_positive(&current_admin.passwd,
- "passwd",
- new->passwd.nsc_pos_ttl) < 0 ||
- nscd_set_ttl_negative(&current_admin.passwd,
- "passwd",
- new->passwd.nsc_neg_ttl) < 0 ||
- nscd_set_khc(&current_admin.passwd,
- "passwd",
- new->passwd.nsc_keephot) < 0 ||
- nscd_set_odo(&current_admin.passwd,
- "passwd",
- new->passwd.nsc_old_data_ok) < 0 ||
- nscd_set_ec(&current_admin.passwd,
- "passwd",
- new->passwd.nsc_enabled) < 0 ||
- nscd_set_ss(&current_admin.passwd,
- "passwd",
- new->passwd.nsc_suggestedsize) < 0 ||
-
- nscd_set_ttl_positive(&current_admin.group,
- "group",
- new->group.nsc_pos_ttl) < 0 ||
- nscd_set_ttl_negative(&current_admin.group,
- "group",
- new->group.nsc_neg_ttl) < 0 ||
- nscd_set_khc(&current_admin.group,
- "group",
- new->group.nsc_keephot) < 0 ||
- nscd_set_odo(&current_admin.group,
- "group",
- new->group.nsc_old_data_ok) < 0 ||
- nscd_set_ec(&current_admin.group,
- "group",
- new->group.nsc_enabled) < 0 ||
- nscd_set_ss(&current_admin.group,
- "group",
- new->group.nsc_suggestedsize) < 0 ||
-
- nscd_set_ttl_positive(&current_admin.node,
- "ipnodes",
- new->node.nsc_pos_ttl) < 0 ||
- nscd_set_ttl_negative(&current_admin.node,
- "ipnodes",
- new->node.nsc_neg_ttl) < 0 ||
- nscd_set_khc(&current_admin.node,
- "ipnodes",
- new->node.nsc_keephot) < 0 ||
- nscd_set_odo(&current_admin.node,
- "ipnodes",
- new->node.nsc_old_data_ok) < 0 ||
- nscd_set_ec(&current_admin.node,
- "ipnodes",
- new->node.nsc_enabled) < 0 ||
- nscd_set_ss(&current_admin.node,
- "ipnodes",
- new->node.nsc_suggestedsize) < 0 ||
-
- nscd_set_ttl_positive(&current_admin.host,
- "hosts",
- new->host.nsc_pos_ttl) < 0 ||
- nscd_set_ttl_negative(&current_admin.host,
- "hosts",
- new->host.nsc_neg_ttl) < 0 ||
- nscd_set_khc(&current_admin.host,
- "hosts",
- new->host.nsc_keephot) < 0 ||
- nscd_set_odo(&current_admin.host,
- "hosts",
- new->host.nsc_old_data_ok) < 0 ||
- nscd_set_ec(&current_admin.host,
- "hosts",
- new->host.nsc_enabled) < 0 ||
- nscd_set_ss(&current_admin.host,
- "hosts",
- new->host.nsc_suggestedsize) < 0 ||
- nscd_set_rbac(new, 0) < 0) {
- out->nsc_return_code = NOTFOUND;
- return (-1);
- }
- out->nsc_return_code = SUCCESS;
- return (0);
-}
-
-void
-client_killserver(void)
-{
- union {
- nsc_data_t data;
- char space[8192];
- } u;
-
- nsc_data_t *dptr;
- int ndata;
- int adata;
-
- u.data.nsc_call.nsc_callnumber = KILLSERVER;
-
- ndata = sizeof (u);
- adata = sizeof (nsc_call_t);
-
- dptr = &u.data;
-
- _nsc_trydoorcall(&dptr, &ndata, &adata);
-}
-
-
-static int
-client_setadmin(admin_t *ptr)
-{
- union {
- nsc_data_t data;
- char space[8192];
- } u;
-
- nsc_data_t *dptr;
- int ndata;
- int adata;
-
- u.data.nsc_call.nsc_callnumber = SETADMIN;
-
- (void) memcpy(u.data.nsc_call.nsc_u.name, ptr, sizeof (*ptr));
-
- ndata = sizeof (u);
- adata = sizeof (*ptr);
-
- dptr = &u.data;
-
- if (_nsc_trydoorcall(&dptr, &ndata, &adata) != SUCCESS) {
- return (-1);
- }
-
- return (0);
-}
-
-static void
-dump_stat(nsc_stat_t *ptr)
-{
- double hitrate;
- (void) printf("%10s cache is enabled\n",
- (ptr->nsc_enabled?"Yes":"No"));
- (void) printf("%10d cache hits on positive entries\n",
- ptr->nsc_pos_cache_hits);
- (void) printf("%10d cache hits on negative entries\n",
- ptr->nsc_neg_cache_hits);
- (void) printf("%10d cache misses on positive entries\n",
- ptr->nsc_pos_cache_misses);
- (void) printf("%10d cache misses on negative entries\n",
- ptr->nsc_neg_cache_misses);
- hitrate = ptr->nsc_pos_cache_misses + ptr->nsc_neg_cache_misses +
- ptr->nsc_pos_cache_hits + ptr->nsc_neg_cache_hits;
-
- if (hitrate > 0.0)
- hitrate = (100.0 * ((double)ptr->nsc_pos_cache_hits +
- (double)ptr->nsc_neg_cache_hits))/hitrate;
-
- (void) printf("%10.1f%% cache hit rate\n", hitrate);
- (void) printf("%10d queries deferred\n", ptr->nsc_throttle_count);
- (void) printf("%10d total entries\n", ptr->nsc_entries);
- (void) printf("%10d complete cache invalidations\n",
- ptr->nsc_invalidate_count);
- (void) printf("%10d suggested size\n", ptr->nsc_suggestedsize);
- (void) printf("%10d seconds time to live for positive entries\n",
- ptr->nsc_pos_ttl);
- (void) printf("%10d seconds time to live for negative entries\n",
- ptr->nsc_neg_ttl);
- (void) printf("%10d most active entries to be kept valid\n",
- ptr->nsc_keephot);
- (void) printf("%10s check /etc/{passwd, group, hosts, inet/ipnodes} "
- "file for changes\n",
- (ptr->nsc_check_files?"Yes":"No"));
-
- (void) printf("%10s use possibly stale data rather than waiting for "
- "refresh\n",
- (ptr->nsc_old_data_ok?"Yes":"No"));
-}
-
-static void
-client_showstats(admin_t *ptr)
-{
-
- (void) printf("nscd configuration:\n\n");
- (void) printf("%10d server debug level\n", ptr->debug_level);
- (void) printf("\"%s\" is server log file\n", ptr->logfile);
-
- (void) printf("\npasswd cache:\n\n");
- dump_stat(&(ptr->passwd));
- (void) printf("\ngroup cache:\n\n");
- dump_stat(&(ptr->group));
- (void) printf("\nhosts cache:\n\n");
- dump_stat(&(ptr->host));
- (void) printf("\nipnodes cache:\n\n");
- dump_stat(&(ptr->node));
- (void) printf("\nexec_attr cache:\n\n");
- dump_stat(&(ptr->exec));
- (void) printf("\nprof_attr cache:\n\n");
- dump_stat(&(ptr->prof));
- (void) printf("\nuser_attr cache:\n\n");
- dump_stat(&(ptr->user));
-}
-
-
-
/*
* detach from tty
*/
static void
detachfromtty(void)
{
- if (logfd > 0) {
+ nscd_rc_t rc;
+ char *me = "detachfromtty";
+
+ if (_logfd > 0) {
int i;
- for (i = 0; i < logfd; i++)
+ for (i = 0; i < _logfd; i++)
(void) close(i);
- closefrom(logfd+1);
+ closefrom(_logfd + 1);
} else
closefrom(0);
@@ -1899,9 +516,16 @@ detachfromtty(void)
switch (fork1()) {
case (pid_t)-1:
+
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to fork: pid = %d, %s\n",
+ getpid(), strerror(errno));
+
exit(1);
break;
case 0:
+ /* start the forker nscd if so configured */
+ _nscd_start_forker(saved_execname, saved_argc, saved_argv);
break;
default:
exit(0);
@@ -1909,5 +533,17 @@ detachfromtty(void)
(void) setsid();
(void) open("/dev/null", O_RDWR, 0);
(void) dup(0);
- (void) dup(0);
+ if (_logfd != 2)
+ (void) dup(0);
+
+ /*
+ * start monitoring the states of the name service clients
+ */
+ rc = _nscd_init_smf_monitor();
+ if (rc != NSCD_SUCCESS) {
+ _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
+ (me, "unable to start the SMF monitor (rc = %d)\n", rc);
+
+ exit(-1);
+ }
}