diff options
Diffstat (limited to 'usr/src/cmd/nscd/server.c')
-rw-r--r-- | usr/src/cmd/nscd/server.c | 1922 |
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 (¤t_admin.passwd); - - if (strncmp(caches[1], s, strlen(caches[1])) == 0) - return (¤t_admin.group); - - if (strncmp(caches[2], s, strlen(caches[2])) == 0) - return (¤t_admin.host); - - if (strncmp(caches[3], s, strlen(caches[3])) == 0) - return (¤t_admin.node); - - if (strncmp(caches[4], s, strlen(caches[4])) == 0) - return (¤t_admin.exec); - - if (strncmp(caches[5], s, strlen(caches[5])) == 0) - return (¤t_admin.prof); - - if (strncmp(caches[6], s, strlen(caches[6])) == 0) - return (¤t_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(¤t_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(¤t_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(¤t_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(¤t_admin); - } - - if (doset) { - if (client_setadmin(¤t_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(¤t_admin, - current_admin.logfile); - } else { - if (strlen(current_admin.logfile) == 0) - (void) strcpy(current_admin.logfile, "/dev/null"); - (void) nscd_set_lf(¤t_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, ¤t_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 = ¤t_admin.exec; - new = &new_admin->exec; - invalidate_func = getexec_invalidate; - break; - case 2: - dbname = NSS_DBNAM_PROFATTR; - cache = ¤t_admin.prof; - new = &new_admin->prof; - invalidate_func = getprof_invalidate; - break; - case 3: - dbname = NSS_DBNAM_USERATTR; - cache = ¤t_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(¤t_admin, new->logfile) < 0) || - nscd_set_dl(¤t_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(¤t_admin.passwd, - "passwd", - new->passwd.nsc_pos_ttl) < 0 || - nscd_set_ttl_negative(¤t_admin.passwd, - "passwd", - new->passwd.nsc_neg_ttl) < 0 || - nscd_set_khc(¤t_admin.passwd, - "passwd", - new->passwd.nsc_keephot) < 0 || - nscd_set_odo(¤t_admin.passwd, - "passwd", - new->passwd.nsc_old_data_ok) < 0 || - nscd_set_ec(¤t_admin.passwd, - "passwd", - new->passwd.nsc_enabled) < 0 || - nscd_set_ss(¤t_admin.passwd, - "passwd", - new->passwd.nsc_suggestedsize) < 0 || - - nscd_set_ttl_positive(¤t_admin.group, - "group", - new->group.nsc_pos_ttl) < 0 || - nscd_set_ttl_negative(¤t_admin.group, - "group", - new->group.nsc_neg_ttl) < 0 || - nscd_set_khc(¤t_admin.group, - "group", - new->group.nsc_keephot) < 0 || - nscd_set_odo(¤t_admin.group, - "group", - new->group.nsc_old_data_ok) < 0 || - nscd_set_ec(¤t_admin.group, - "group", - new->group.nsc_enabled) < 0 || - nscd_set_ss(¤t_admin.group, - "group", - new->group.nsc_suggestedsize) < 0 || - - nscd_set_ttl_positive(¤t_admin.node, - "ipnodes", - new->node.nsc_pos_ttl) < 0 || - nscd_set_ttl_negative(¤t_admin.node, - "ipnodes", - new->node.nsc_neg_ttl) < 0 || - nscd_set_khc(¤t_admin.node, - "ipnodes", - new->node.nsc_keephot) < 0 || - nscd_set_odo(¤t_admin.node, - "ipnodes", - new->node.nsc_old_data_ok) < 0 || - nscd_set_ec(¤t_admin.node, - "ipnodes", - new->node.nsc_enabled) < 0 || - nscd_set_ss(¤t_admin.node, - "ipnodes", - new->node.nsc_suggestedsize) < 0 || - - nscd_set_ttl_positive(¤t_admin.host, - "hosts", - new->host.nsc_pos_ttl) < 0 || - nscd_set_ttl_negative(¤t_admin.host, - "hosts", - new->host.nsc_neg_ttl) < 0 || - nscd_set_khc(¤t_admin.host, - "hosts", - new->host.nsc_keephot) < 0 || - nscd_set_odo(¤t_admin.host, - "hosts", - new->host.nsc_old_data_ok) < 0 || - nscd_set_ec(¤t_admin.host, - "hosts", - new->host.nsc_enabled) < 0 || - nscd_set_ss(¤t_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); + } } |