1cb5caa98Sdjl /* 2cb5caa98Sdjl * CDDL HEADER START 3cb5caa98Sdjl * 4cb5caa98Sdjl * The contents of this file are subject to the terms of the 5cb5caa98Sdjl * Common Development and Distribution License (the "License"). 6cb5caa98Sdjl * You may not use this file except in compliance with the License. 7cb5caa98Sdjl * 8cb5caa98Sdjl * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9cb5caa98Sdjl * or http://www.opensolaris.org/os/licensing. 10cb5caa98Sdjl * See the License for the specific language governing permissions 11cb5caa98Sdjl * and limitations under the License. 12cb5caa98Sdjl * 13cb5caa98Sdjl * When distributing Covered Code, include this CDDL HEADER in each 14cb5caa98Sdjl * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15cb5caa98Sdjl * If applicable, add the following below this CDDL HEADER, with the 16cb5caa98Sdjl * fields enclosed by brackets "[]" replaced with your own identifying 17cb5caa98Sdjl * information: Portions Copyright [yyyy] [name of copyright owner] 18cb5caa98Sdjl * 19cb5caa98Sdjl * CDDL HEADER END 20cb5caa98Sdjl */ 21cb5caa98Sdjl /* 22cb5caa98Sdjl * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23cb5caa98Sdjl * Use is subject to license terms. 24cb5caa98Sdjl */ 25cb5caa98Sdjl 26cb5caa98Sdjl #pragma ident "%Z%%M% %I% %E% SMI" 27cb5caa98Sdjl 28cb5caa98Sdjl #include <stdlib.h> 29cb5caa98Sdjl #include <alloca.h> 30cb5caa98Sdjl #include <signal.h> 31cb5caa98Sdjl #include <sys/stat.h> 32cb5caa98Sdjl #include <unistd.h> 33cb5caa98Sdjl #include <pthread.h> 34cb5caa98Sdjl #include <time.h> 35cb5caa98Sdjl #include <errno.h> 36cb5caa98Sdjl #include <door.h> 37cb5caa98Sdjl #include <zone.h> 38cb5caa98Sdjl #include <resolv.h> 39cb5caa98Sdjl #include <sys/socket.h> 40cb5caa98Sdjl #include <net/route.h> 41cb5caa98Sdjl #include <string.h> 42cb5caa98Sdjl #include <net/if.h> 43cb5caa98Sdjl #include <sys/stat.h> 44cb5caa98Sdjl #include <fcntl.h> 45cb5caa98Sdjl #include "nscd_common.h" 46cb5caa98Sdjl #include "nscd_door.h" 47cb5caa98Sdjl #include "nscd_config.h" 48cb5caa98Sdjl #include "nscd_switch.h" 49cb5caa98Sdjl #include "nscd_log.h" 50cb5caa98Sdjl #include "nscd_selfcred.h" 51cb5caa98Sdjl #include "nscd_frontend.h" 52cb5caa98Sdjl #include "nscd_admin.h" 53cb5caa98Sdjl 54cb5caa98Sdjl static void rts_mon(void); 55cb5caa98Sdjl static void keep_open_dns_socket(void); 56cb5caa98Sdjl 57cb5caa98Sdjl extern nsc_ctx_t *cache_ctx_p[]; 58cb5caa98Sdjl 59cb5caa98Sdjl /* 60cb5caa98Sdjl * Current active Configuration data for the frontend component 61cb5caa98Sdjl */ 62cb5caa98Sdjl static nscd_cfg_global_frontend_t frontend_cfg_g; 63cb5caa98Sdjl static nscd_cfg_frontend_t *frontend_cfg; 64cb5caa98Sdjl 65cb5caa98Sdjl static int max_servers = 0; 66cb5caa98Sdjl static int max_servers_set = 0; 67cb5caa98Sdjl static int per_user_is_on = 1; 68cb5caa98Sdjl 69cb5caa98Sdjl static char *main_execname; 70cb5caa98Sdjl static char **main_argv; 71cb5caa98Sdjl extern int _whoami; 72cb5caa98Sdjl extern long activity; 73cb5caa98Sdjl extern mutex_t activity_lock; 74cb5caa98Sdjl 75cb5caa98Sdjl static sema_t common_sema; 76cb5caa98Sdjl 77cb5caa98Sdjl static thread_key_t lookup_state_key; 78cb5caa98Sdjl static mutex_t create_lock = DEFAULTMUTEX; 79cb5caa98Sdjl static int num_servers = 0; 80cb5caa98Sdjl static thread_key_t server_key; 81cb5caa98Sdjl 82cb5caa98Sdjl /* 83cb5caa98Sdjl * Bind a TSD value to a server thread. This enables the destructor to 84cb5caa98Sdjl * be called if/when this thread exits. This would be a programming 85cb5caa98Sdjl * error, but better safe than sorry. 86cb5caa98Sdjl */ 87cb5caa98Sdjl /*ARGSUSED*/ 88cb5caa98Sdjl static void * 89cb5caa98Sdjl server_tsd_bind(void *arg) 90cb5caa98Sdjl { 91cb5caa98Sdjl static void *value = 0; 92cb5caa98Sdjl 93cb5caa98Sdjl /* disable cancellation to avoid hangs if server threads disappear */ 94cb5caa98Sdjl (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 95cb5caa98Sdjl (void) thr_setspecific(server_key, value); 96cb5caa98Sdjl (void) door_return(NULL, 0, NULL, 0); 97cb5caa98Sdjl 98cb5caa98Sdjl /* make lint happy */ 99cb5caa98Sdjl return (NULL); 100cb5caa98Sdjl } 101cb5caa98Sdjl 102cb5caa98Sdjl /* 103cb5caa98Sdjl * Server threads are created here. 104cb5caa98Sdjl */ 105cb5caa98Sdjl /*ARGSUSED*/ 106cb5caa98Sdjl static void 107cb5caa98Sdjl server_create(door_info_t *dip) 108cb5caa98Sdjl { 109cb5caa98Sdjl (void) mutex_lock(&create_lock); 110cb5caa98Sdjl if (++num_servers > max_servers) { 111cb5caa98Sdjl num_servers--; 112cb5caa98Sdjl (void) mutex_unlock(&create_lock); 113cb5caa98Sdjl return; 114cb5caa98Sdjl } 115cb5caa98Sdjl (void) mutex_unlock(&create_lock); 116cb5caa98Sdjl (void) thr_create(NULL, 0, server_tsd_bind, NULL, 117cb5caa98Sdjl THR_BOUND|THR_DETACHED, NULL); 118cb5caa98Sdjl } 119cb5caa98Sdjl 120cb5caa98Sdjl /* 121cb5caa98Sdjl * Server thread are destroyed here 122cb5caa98Sdjl */ 123cb5caa98Sdjl /*ARGSUSED*/ 124cb5caa98Sdjl static void 125cb5caa98Sdjl server_destroy(void *arg) 126cb5caa98Sdjl { 127cb5caa98Sdjl (void) mutex_lock(&create_lock); 128cb5caa98Sdjl num_servers--; 129cb5caa98Sdjl (void) mutex_unlock(&create_lock); 130cb5caa98Sdjl } 131cb5caa98Sdjl 132cb5caa98Sdjl /* 133cb5caa98Sdjl * get clearance 134cb5caa98Sdjl */ 135cb5caa98Sdjl int 136cb5caa98Sdjl _nscd_get_clearance(sema_t *sema) { 137cb5caa98Sdjl if (sema_trywait(&common_sema) == 0) { 138cb5caa98Sdjl (void) thr_setspecific(lookup_state_key, NULL); 139cb5caa98Sdjl return (0); 140cb5caa98Sdjl } 141cb5caa98Sdjl 142cb5caa98Sdjl if (sema_trywait(sema) == 0) { 143cb5caa98Sdjl (void) thr_setspecific(lookup_state_key, (void*)1); 144cb5caa98Sdjl return (0); 145cb5caa98Sdjl } 146cb5caa98Sdjl 147cb5caa98Sdjl return (1); 148cb5caa98Sdjl } 149cb5caa98Sdjl 150cb5caa98Sdjl 151cb5caa98Sdjl /* 152cb5caa98Sdjl * release clearance 153cb5caa98Sdjl */ 154cb5caa98Sdjl int 155cb5caa98Sdjl _nscd_release_clearance(sema_t *sema) { 156cb5caa98Sdjl int which; 157cb5caa98Sdjl 158cb5caa98Sdjl (void) thr_getspecific(lookup_state_key, (void**)&which); 159cb5caa98Sdjl if (which == 0) /* from common pool */ { 160cb5caa98Sdjl (void) sema_post(&common_sema); 161cb5caa98Sdjl return (0); 162cb5caa98Sdjl } 163cb5caa98Sdjl 164cb5caa98Sdjl (void) sema_post(sema); 165cb5caa98Sdjl return (1); 166cb5caa98Sdjl } 167cb5caa98Sdjl 168cb5caa98Sdjl static void 169cb5caa98Sdjl dozip(void) 170cb5caa98Sdjl { 171cb5caa98Sdjl /* not much here */ 172cb5caa98Sdjl } 173cb5caa98Sdjl 174cb5caa98Sdjl static void 175cb5caa98Sdjl restart_if_cfgfile_changed() 176cb5caa98Sdjl { 177cb5caa98Sdjl 178cb5caa98Sdjl static mutex_t nsswitch_lock = DEFAULTMUTEX; 179cb5caa98Sdjl static time_t last_nsswitch_check = 0; 180cb5caa98Sdjl static time_t last_nsswitch_modified = 0; 181cb5caa98Sdjl static time_t last_resolv_modified = 0; 182cb5caa98Sdjl time_t now = time(NULL); 183cb5caa98Sdjl char *me = "restart_if_cfgfile_changed"; 184cb5caa98Sdjl 185cb5caa98Sdjl if (now - last_nsswitch_check <= _NSC_FILE_CHECK_TIME) 186cb5caa98Sdjl return; 187cb5caa98Sdjl 188cb5caa98Sdjl (void) mutex_lock(&nsswitch_lock); 189cb5caa98Sdjl 190cb5caa98Sdjl if (now - last_nsswitch_check > _NSC_FILE_CHECK_TIME) { 191cb5caa98Sdjl struct stat nss_buf; 192cb5caa98Sdjl struct stat res_buf; 193cb5caa98Sdjl 194cb5caa98Sdjl last_nsswitch_check = now; 195cb5caa98Sdjl 196cb5caa98Sdjl (void) mutex_unlock(&nsswitch_lock); /* let others continue */ 197cb5caa98Sdjl 198cb5caa98Sdjl /* 199cb5caa98Sdjl * This code keeps us from statting resolv.conf 200cb5caa98Sdjl * if it doesn't exist, yet prevents us from ignoring 201cb5caa98Sdjl * it if it happens to disappear later on for a bit. 202cb5caa98Sdjl */ 203cb5caa98Sdjl 204cb5caa98Sdjl if (last_resolv_modified >= 0) { 205cb5caa98Sdjl if (stat("/etc/resolv.conf", &res_buf) < 0) { 206cb5caa98Sdjl if (last_resolv_modified == 0) 207cb5caa98Sdjl last_resolv_modified = -1; 208cb5caa98Sdjl else 209cb5caa98Sdjl res_buf.st_mtime = last_resolv_modified; 210cb5caa98Sdjl } else if (last_resolv_modified == 0) { 211cb5caa98Sdjl last_resolv_modified = res_buf.st_mtime; 212cb5caa98Sdjl } 213cb5caa98Sdjl } 214cb5caa98Sdjl 215cb5caa98Sdjl if (stat("/etc/nsswitch.conf", &nss_buf) < 0) { 216cb5caa98Sdjl 217cb5caa98Sdjl /*EMPTY*/; 218cb5caa98Sdjl 219cb5caa98Sdjl } else if (last_nsswitch_modified == 0) { 220cb5caa98Sdjl 221cb5caa98Sdjl last_nsswitch_modified = nss_buf.st_mtime; 222cb5caa98Sdjl 223cb5caa98Sdjl } else if ((last_nsswitch_modified < nss_buf.st_mtime) || 224cb5caa98Sdjl ((last_resolv_modified > 0) && 225cb5caa98Sdjl (last_resolv_modified < res_buf.st_mtime))) { 226cb5caa98Sdjl static mutex_t exit_lock = DEFAULTMUTEX; 227cb5caa98Sdjl char *fmri; 228cb5caa98Sdjl 229cb5caa98Sdjl /* 230cb5caa98Sdjl * if in self cred mode, kill the forker and 231cb5caa98Sdjl * child nscds 232cb5caa98Sdjl */ 233cb5caa98Sdjl if (_nscd_is_self_cred_on(0, NULL)) { 234cb5caa98Sdjl _nscd_kill_forker(); 235cb5caa98Sdjl _nscd_kill_all_children(); 236cb5caa98Sdjl } 237cb5caa98Sdjl 238cb5caa98Sdjl /* 239cb5caa98Sdjl * time for restart 240cb5caa98Sdjl */ 241cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_INFO) 242cb5caa98Sdjl (me, "nscd restart due to %s or %s change\n", 243cb5caa98Sdjl "/etc/nsswitch.conf", "resolv.conf"); 244cb5caa98Sdjl /* 245cb5caa98Sdjl * try to restart under smf 246cb5caa98Sdjl */ 247cb5caa98Sdjl if ((fmri = getenv("SMF_FMRI")) == NULL) { 248cb5caa98Sdjl /* not running under smf - reexec */ 249cb5caa98Sdjl (void) execv(main_execname, main_argv); 250cb5caa98Sdjl exit(1); /* just in case */ 251cb5caa98Sdjl } 252cb5caa98Sdjl 253cb5caa98Sdjl /* prevent multiple restarts */ 254cb5caa98Sdjl (void) mutex_lock(&exit_lock); 255cb5caa98Sdjl 256cb5caa98Sdjl if (smf_restart_instance(fmri) == 0) 257cb5caa98Sdjl (void) sleep(10); /* wait a bit */ 258cb5caa98Sdjl exit(1); /* give up waiting for resurrection */ 259cb5caa98Sdjl } 260cb5caa98Sdjl 261cb5caa98Sdjl } else 262cb5caa98Sdjl (void) mutex_unlock(&nsswitch_lock); 263cb5caa98Sdjl } 264cb5caa98Sdjl 265cb5caa98Sdjl uid_t 266cb5caa98Sdjl _nscd_get_client_euid() 267cb5caa98Sdjl { 268cb5caa98Sdjl ucred_t *uc = NULL; 269cb5caa98Sdjl uid_t id; 270cb5caa98Sdjl char *me = "get_client_euid"; 271cb5caa98Sdjl 272cb5caa98Sdjl if (door_ucred(&uc) != 0) { 273cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) 274cb5caa98Sdjl (me, "door_ucred: %s\n", strerror(errno)); 275cb5caa98Sdjl return ((uid_t)-1); 276cb5caa98Sdjl } 277cb5caa98Sdjl 278cb5caa98Sdjl id = ucred_geteuid(uc); 279cb5caa98Sdjl ucred_free(uc); 280cb5caa98Sdjl return (id); 281cb5caa98Sdjl } 282cb5caa98Sdjl 283cb5caa98Sdjl static void 284cb5caa98Sdjl N2N_check_priv( 285cb5caa98Sdjl void *buf, 286cb5caa98Sdjl char *dc_str) 287cb5caa98Sdjl { 288cb5caa98Sdjl nss_pheader_t *phdr = (nss_pheader_t *)buf; 289cb5caa98Sdjl ucred_t *uc = NULL; 290cb5caa98Sdjl const priv_set_t *eset; 291cb5caa98Sdjl zoneid_t zoneid; 292cb5caa98Sdjl int errnum; 293cb5caa98Sdjl char *me = "N2N_check_priv"; 294cb5caa98Sdjl 295cb5caa98Sdjl if (door_ucred(&uc) != 0) { 296cb5caa98Sdjl errnum = errno; 297cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) 298cb5caa98Sdjl (me, "door_ucred: %s\n", strerror(errno)); 299cb5caa98Sdjl 300cb5caa98Sdjl NSCD_RETURN_STATUS(phdr, NSS_ERROR, errnum); 301cb5caa98Sdjl } 302cb5caa98Sdjl 303cb5caa98Sdjl eset = ucred_getprivset(uc, PRIV_EFFECTIVE); 304cb5caa98Sdjl zoneid = ucred_getzoneid(uc); 305cb5caa98Sdjl 306cb5caa98Sdjl if ((zoneid != GLOBAL_ZONEID && zoneid != getzoneid()) || 307cb5caa98Sdjl eset != NULL ? !priv_ismember(eset, PRIV_SYS_ADMIN) : 308cb5caa98Sdjl ucred_geteuid(uc) != 0) { 309cb5caa98Sdjl 310cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ALERT) 311cb5caa98Sdjl (me, "%s call failed(cred): caller pid %d, uid %d, " 312cb5caa98Sdjl "euid %d, zoneid %d\n", dc_str, ucred_getpid(uc), 313cb5caa98Sdjl ucred_getruid(uc), ucred_geteuid(uc), zoneid); 314cb5caa98Sdjl ucred_free(uc); 315cb5caa98Sdjl 316cb5caa98Sdjl NSCD_RETURN_STATUS(phdr, NSS_ERROR, EACCES); 317cb5caa98Sdjl } 318cb5caa98Sdjl 319cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) 320cb5caa98Sdjl (me, "nscd received %s cmd from pid %d, uid %d, " 321cb5caa98Sdjl "euid %d, zoneid %d\n", dc_str, ucred_getpid(uc), 322cb5caa98Sdjl ucred_getruid(uc), ucred_geteuid(uc), zoneid); 323cb5caa98Sdjl 324cb5caa98Sdjl ucred_free(uc); 325cb5caa98Sdjl 326cb5caa98Sdjl NSCD_RETURN_STATUS_SUCCESS(phdr); 327cb5caa98Sdjl } 328cb5caa98Sdjl 329*e37190e5Smichen void 330*e37190e5Smichen _nscd_APP_check_cred( 331cb5caa98Sdjl void *buf, 332cb5caa98Sdjl pid_t *pidp, 333*e37190e5Smichen char *dc_str, 334*e37190e5Smichen int log_comp, 335*e37190e5Smichen int log_level) 336cb5caa98Sdjl { 337cb5caa98Sdjl nss_pheader_t *phdr = (nss_pheader_t *)buf; 338cb5caa98Sdjl ucred_t *uc = NULL; 339cb5caa98Sdjl uid_t ruid; 340cb5caa98Sdjl uid_t euid; 341*e37190e5Smichen pid_t pid; 342cb5caa98Sdjl int errnum; 343*e37190e5Smichen char *me = "_nscd_APP_check_cred"; 344cb5caa98Sdjl 345cb5caa98Sdjl if (door_ucred(&uc) != 0) { 346cb5caa98Sdjl errnum = errno; 347*e37190e5Smichen _NSCD_LOG(log_comp, NSCD_LOG_LEVEL_ERROR) 348cb5caa98Sdjl (me, "door_ucred: %s\n", strerror(errno)); 349cb5caa98Sdjl 350cb5caa98Sdjl NSCD_RETURN_STATUS(phdr, NSS_ERROR, errnum); 351cb5caa98Sdjl } 352cb5caa98Sdjl 353*e37190e5Smichen NSCD_SET_STATUS_SUCCESS(phdr); 354*e37190e5Smichen pid = ucred_getpid(uc); 355cb5caa98Sdjl if (NSS_PACKED_CRED_CHECK(buf, ruid = ucred_getruid(uc), 356cb5caa98Sdjl euid = ucred_geteuid(uc))) { 357*e37190e5Smichen if (pidp != NULL) { 358*e37190e5Smichen if (*pidp == (pid_t)-1) 359*e37190e5Smichen *pidp = pid; 360*e37190e5Smichen else if (*pidp != pid) { 361*e37190e5Smichen NSCD_SET_STATUS(phdr, NSS_ERROR, EACCES); 362*e37190e5Smichen } 363*e37190e5Smichen } 364*e37190e5Smichen } else { 365*e37190e5Smichen NSCD_SET_STATUS(phdr, NSS_ERROR, EACCES); 366cb5caa98Sdjl } 367cb5caa98Sdjl 368cb5caa98Sdjl ucred_free(uc); 369cb5caa98Sdjl 370*e37190e5Smichen if (NSCD_STATUS_IS_NOT_OK(phdr)) { 371*e37190e5Smichen _NSCD_LOG(log_comp, log_level) 372*e37190e5Smichen (me, "%s call failed: caller pid %d (input pid = %d), ruid %d, " 373*e37190e5Smichen "euid %d, header ruid %d, header euid %d\n", dc_str, 374*e37190e5Smichen pid, (pidp != NULL) ? *pidp : -1, ruid, euid, 375*e37190e5Smichen ((nss_pheader_t *)(buf))->p_ruid, 376*e37190e5Smichen ((nss_pheader_t *)(buf))->p_euid); 377*e37190e5Smichen } 378cb5caa98Sdjl } 379cb5caa98Sdjl 380cb5caa98Sdjl static void 381cb5caa98Sdjl lookup(char *argp, size_t arg_size) 382cb5caa98Sdjl { 383cb5caa98Sdjl nsc_lookup_args_t largs; 384cb5caa98Sdjl char space[NSCD_LOOKUP_BUFSIZE]; 385cb5caa98Sdjl nss_pheader_t *phdr = (nss_pheader_t *)(void *)argp; 386cb5caa98Sdjl 387cb5caa98Sdjl NSCD_ALLOC_LOOKUP_BUFFER(argp, arg_size, phdr, space, 388cb5caa98Sdjl sizeof (space)); 389cb5caa98Sdjl 390cb5caa98Sdjl (void) memset(&largs, 0, sizeof (largs)); 391cb5caa98Sdjl largs.buffer = argp; 392cb5caa98Sdjl largs.bufsize = arg_size; 393cb5caa98Sdjl nsc_lookup(&largs, 0); 394cb5caa98Sdjl 395cb5caa98Sdjl /* 396cb5caa98Sdjl * only the PUN needs to keep track of the 397cb5caa98Sdjl * activity count to determine when to 398cb5caa98Sdjl * terminate itself 399cb5caa98Sdjl */ 400cb5caa98Sdjl if (_whoami == NSCD_CHILD) { 401cb5caa98Sdjl (void) mutex_lock(&activity_lock); 402cb5caa98Sdjl ++activity; 403cb5caa98Sdjl (void) mutex_unlock(&activity_lock); 404cb5caa98Sdjl } 405cb5caa98Sdjl 406cb5caa98Sdjl NSCD_SET_RETURN_ARG(phdr, arg_size); 407cb5caa98Sdjl (void) door_return(argp, arg_size, NULL, 0); 408cb5caa98Sdjl } 409cb5caa98Sdjl 410cb5caa98Sdjl static void 411cb5caa98Sdjl getent(char *argp, size_t arg_size) 412cb5caa98Sdjl { 413cb5caa98Sdjl char space[NSCD_LOOKUP_BUFSIZE]; 414cb5caa98Sdjl nss_pheader_t *phdr = (nss_pheader_t *)(void *)argp; 415cb5caa98Sdjl 416cb5caa98Sdjl NSCD_ALLOC_LOOKUP_BUFFER(argp, arg_size, phdr, 417cb5caa98Sdjl space, sizeof (space)); 418cb5caa98Sdjl 419cb5caa98Sdjl nss_pgetent(argp, arg_size); 420cb5caa98Sdjl 421cb5caa98Sdjl NSCD_SET_RETURN_ARG(phdr, arg_size); 422cb5caa98Sdjl (void) door_return(argp, arg_size, NULL, 0); 423cb5caa98Sdjl } 424cb5caa98Sdjl 425cb5caa98Sdjl static int 426cb5caa98Sdjl is_db_per_user(void *buf, char *dblist) 427cb5caa98Sdjl { 428cb5caa98Sdjl nss_pheader_t *phdr = (nss_pheader_t *)buf; 429cb5caa98Sdjl nss_dbd_t *pdbd; 430cb5caa98Sdjl char *dbname, *dbn; 431cb5caa98Sdjl int len; 432cb5caa98Sdjl 433cb5caa98Sdjl /* copy db name into a temp buffer */ 434cb5caa98Sdjl pdbd = (nss_dbd_t *)((void *)((char *)buf + phdr->dbd_off)); 435cb5caa98Sdjl dbname = (char *)pdbd + pdbd->o_name; 436cb5caa98Sdjl len = strlen(dbname); 437cb5caa98Sdjl dbn = alloca(len + 2); 438cb5caa98Sdjl (void) memcpy(dbn, dbname, len); 439cb5caa98Sdjl 440cb5caa98Sdjl /* check if <dbname> + ',' can be found in the dblist string */ 441cb5caa98Sdjl dbn[len] = ','; 442cb5caa98Sdjl dbn[len + 1] = '\0'; 443cb5caa98Sdjl if (strstr(dblist, dbn) != NULL) 444cb5caa98Sdjl return (1); 445cb5caa98Sdjl 446cb5caa98Sdjl /* 447cb5caa98Sdjl * check if <dbname> can be found in the last part 448cb5caa98Sdjl * of the dblist string 449cb5caa98Sdjl */ 450cb5caa98Sdjl dbn[len] = '\0'; 451cb5caa98Sdjl if (strstr(dblist, dbn) != NULL) 452cb5caa98Sdjl return (1); 453cb5caa98Sdjl 454cb5caa98Sdjl return (0); 455cb5caa98Sdjl } 456cb5caa98Sdjl 457cb5caa98Sdjl /* 458cb5caa98Sdjl * Check to see if all conditions are met for processing per-user 459cb5caa98Sdjl * requests. Returns 1 if yes, -1 if backend is not configured, 460cb5caa98Sdjl * 0 otherwise. 461cb5caa98Sdjl */ 462cb5caa98Sdjl static int 463cb5caa98Sdjl need_per_user_door(void *buf, int whoami, uid_t uid, char **dblist) 464cb5caa98Sdjl { 465cb5caa98Sdjl nss_pheader_t *phdr = (nss_pheader_t *)buf; 466cb5caa98Sdjl 467cb5caa98Sdjl NSCD_SET_STATUS_SUCCESS(phdr); 468cb5caa98Sdjl 469cb5caa98Sdjl /* if already a per-user nscd, no need to get per-user door */ 470cb5caa98Sdjl if (whoami == NSCD_CHILD) 471cb5caa98Sdjl return (0); 472cb5caa98Sdjl 473cb5caa98Sdjl /* forker shouldn't be asked */ 474cb5caa98Sdjl if (whoami == NSCD_FORKER) { 475cb5caa98Sdjl NSCD_SET_STATUS(phdr, NSS_ERROR, ENOTSUP); 476cb5caa98Sdjl return (0); 477cb5caa98Sdjl } 478cb5caa98Sdjl 479cb5caa98Sdjl /* if door client is root, no need for a per-user door */ 480cb5caa98Sdjl if (uid == 0) 481cb5caa98Sdjl return (0); 482cb5caa98Sdjl 483cb5caa98Sdjl /* 484cb5caa98Sdjl * if per-user lookup is not configured, no per-user 485cb5caa98Sdjl * door available 486cb5caa98Sdjl */ 487cb5caa98Sdjl if (_nscd_is_self_cred_on(0, dblist) == 0) 488cb5caa98Sdjl return (-1); 489cb5caa98Sdjl 490cb5caa98Sdjl /* 491cb5caa98Sdjl * if per-user lookup is not configured for the db, 492cb5caa98Sdjl * don't bother 493cb5caa98Sdjl */ 494cb5caa98Sdjl if (is_db_per_user(phdr, *dblist) == 0) 495cb5caa98Sdjl return (0); 496cb5caa98Sdjl 497cb5caa98Sdjl return (1); 498cb5caa98Sdjl } 499cb5caa98Sdjl 500cb5caa98Sdjl static void 501cb5caa98Sdjl if_selfcred_return_per_user_door(char *argp, size_t arg_size, 502cb5caa98Sdjl door_desc_t *dp, int whoami) 503cb5caa98Sdjl { 504cb5caa98Sdjl nss_pheader_t *phdr = (nss_pheader_t *)((void *)argp); 505cb5caa98Sdjl char *dblist; 506cb5caa98Sdjl int door = -1; 507cb5caa98Sdjl int rc = 0; 508cb5caa98Sdjl door_desc_t desc; 509cb5caa98Sdjl char space[1024*4]; 510cb5caa98Sdjl 511cb5caa98Sdjl /* 512cb5caa98Sdjl * check to see if self-cred is configured and 513cb5caa98Sdjl * need to return an alternate PUN door 514cb5caa98Sdjl */ 515cb5caa98Sdjl if (per_user_is_on == 1) { 516cb5caa98Sdjl rc = need_per_user_door(argp, whoami, 517cb5caa98Sdjl _nscd_get_client_euid(), &dblist); 518cb5caa98Sdjl if (rc == -1) 519cb5caa98Sdjl per_user_is_on = 0; 520cb5caa98Sdjl } 521cb5caa98Sdjl if (rc <= 0) { 522cb5caa98Sdjl /* 523cb5caa98Sdjl * self-cred not configured, and no error detected, 524cb5caa98Sdjl * return to continue the door call processing 525cb5caa98Sdjl */ 526cb5caa98Sdjl if (NSCD_STATUS_IS_OK(phdr)) 527cb5caa98Sdjl return; 528cb5caa98Sdjl else 529cb5caa98Sdjl /* 530cb5caa98Sdjl * configured but error detected, 531cb5caa98Sdjl * stop the door call processing 532cb5caa98Sdjl */ 533cb5caa98Sdjl (void) door_return(argp, phdr->data_off, NULL, 0); 534cb5caa98Sdjl } 535cb5caa98Sdjl 536cb5caa98Sdjl /* get the alternate PUN door */ 537cb5caa98Sdjl _nscd_proc_alt_get(argp, &door); 538cb5caa98Sdjl if (NSCD_GET_STATUS(phdr) != NSS_ALTRETRY) { 539cb5caa98Sdjl (void) door_return(argp, phdr->data_off, NULL, 0); 540cb5caa98Sdjl } 541cb5caa98Sdjl 542cb5caa98Sdjl /* return the alternate door descriptor */ 543cb5caa98Sdjl (void) memcpy(space, phdr, NSCD_PHDR_LEN(phdr)); 544cb5caa98Sdjl argp = space; 545cb5caa98Sdjl phdr = (nss_pheader_t *)(void *)space; 546cb5caa98Sdjl dp = &desc; 547cb5caa98Sdjl dp->d_attributes = DOOR_DESCRIPTOR; 548cb5caa98Sdjl dp->d_data.d_desc.d_descriptor = door; 549cb5caa98Sdjl phdr->data_len = strlen(dblist) + 1; 550cb5caa98Sdjl (void) strcpy(((char *)phdr) + NSCD_PHDR_LEN(phdr), dblist); 551cb5caa98Sdjl 552cb5caa98Sdjl arg_size = NSCD_PHDR_LEN(phdr) + NSCD_DATA_LEN(phdr); 553cb5caa98Sdjl (void) door_return(argp, arg_size, dp, 1); 554cb5caa98Sdjl } 555cb5caa98Sdjl 556cb5caa98Sdjl /*ARGSUSED*/ 557cb5caa98Sdjl static void 558cb5caa98Sdjl switcher(void *cookie, char *argp, size_t arg_size, 559cb5caa98Sdjl door_desc_t *dp, uint_t n_desc) 560cb5caa98Sdjl { 561cb5caa98Sdjl int iam; 562cb5caa98Sdjl pid_t ent_pid = -1; 563cb5caa98Sdjl nss_pheader_t *phdr = (nss_pheader_t *)((void *)argp); 564cb5caa98Sdjl void *uptr; 565cb5caa98Sdjl int buflen, len; 566cb5caa98Sdjl int callnum; 567cb5caa98Sdjl char *me = "switcher"; 568cb5caa98Sdjl 569cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) 570cb5caa98Sdjl (me, "switcher ...\n"); 571cb5caa98Sdjl 572cb5caa98Sdjl if (argp == DOOR_UNREF_DATA) { 573cb5caa98Sdjl (void) printf("Door Slam... exiting\n"); 574cb5caa98Sdjl exit(0); 575cb5caa98Sdjl } 576cb5caa98Sdjl 577cb5caa98Sdjl if (argp == NULL) { /* empty door call */ 578cb5caa98Sdjl (void) door_return(NULL, 0, 0, 0); /* return the favor */ 579cb5caa98Sdjl } 580cb5caa98Sdjl 581cb5caa98Sdjl /* 582cb5caa98Sdjl * need to restart if main nscd and config file(s) changed 583cb5caa98Sdjl */ 584cb5caa98Sdjl if (_whoami == NSCD_MAIN) 585cb5caa98Sdjl restart_if_cfgfile_changed(); 586cb5caa98Sdjl 587cb5caa98Sdjl if ((phdr->nsc_callnumber & NSCDV2CATMASK) == NSCD_CALLCAT_APP) { 588cb5caa98Sdjl switch (phdr->nsc_callnumber) { 589cb5caa98Sdjl case NSCD_SEARCH: 590cb5caa98Sdjl 591cb5caa98Sdjl /* if a fallback to main nscd, skip per-user setup */ 592cb5caa98Sdjl if (phdr->p_status != NSS_ALTRETRY) 593cb5caa98Sdjl if_selfcred_return_per_user_door(argp, arg_size, 594cb5caa98Sdjl dp, _whoami); 595cb5caa98Sdjl lookup(argp, arg_size); 596cb5caa98Sdjl 597cb5caa98Sdjl break; 598cb5caa98Sdjl 599cb5caa98Sdjl case NSCD_SETENT: 600cb5caa98Sdjl 601*e37190e5Smichen _nscd_APP_check_cred(argp, &ent_pid, "NSCD_SETENT", 602*e37190e5Smichen NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ALERT); 603cb5caa98Sdjl if (NSCD_STATUS_IS_OK(phdr)) { 604cb5caa98Sdjl if_selfcred_return_per_user_door(argp, arg_size, 605cb5caa98Sdjl dp, _whoami); 606cb5caa98Sdjl nss_psetent(argp, arg_size, ent_pid); 607cb5caa98Sdjl } 608cb5caa98Sdjl break; 609cb5caa98Sdjl 610cb5caa98Sdjl case NSCD_GETENT: 611cb5caa98Sdjl 612cb5caa98Sdjl getent(argp, arg_size); 613cb5caa98Sdjl break; 614cb5caa98Sdjl 615cb5caa98Sdjl case NSCD_ENDENT: 616cb5caa98Sdjl 617cb5caa98Sdjl nss_pendent(argp, arg_size); 618cb5caa98Sdjl break; 619cb5caa98Sdjl 620cb5caa98Sdjl case NSCD_PUT: 621cb5caa98Sdjl 622cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 623cb5caa98Sdjl (me, "door call NSCD_PUT not supported yet\n"); 624cb5caa98Sdjl 625cb5caa98Sdjl NSCD_SET_STATUS(phdr, NSS_ERROR, ENOTSUP); 626cb5caa98Sdjl break; 627cb5caa98Sdjl 628cb5caa98Sdjl case NSCD_GETHINTS: 629cb5caa98Sdjl 630cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 631cb5caa98Sdjl (me, "door call NSCD_GETHINTS not supported yet\n"); 632cb5caa98Sdjl 633cb5caa98Sdjl NSCD_SET_STATUS(phdr, NSS_ERROR, ENOTSUP); 634cb5caa98Sdjl break; 635cb5caa98Sdjl 636cb5caa98Sdjl default: 637cb5caa98Sdjl 638cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 639cb5caa98Sdjl (me, "Unknown name service door call op %x\n", 640cb5caa98Sdjl phdr->nsc_callnumber); 641cb5caa98Sdjl 642cb5caa98Sdjl NSCD_SET_STATUS(phdr, NSS_ERROR, EINVAL); 643cb5caa98Sdjl break; 644cb5caa98Sdjl } 645cb5caa98Sdjl 646cb5caa98Sdjl (void) door_return(argp, arg_size, NULL, 0); 647cb5caa98Sdjl } 648cb5caa98Sdjl 649cb5caa98Sdjl iam = NSCD_MAIN; 650cb5caa98Sdjl callnum = phdr->nsc_callnumber & ~NSCD_WHOAMI; 651cb5caa98Sdjl if (callnum == NSCD_IMHERE || 652cb5caa98Sdjl callnum == NSCD_PULSE || callnum == NSCD_FORK) 653cb5caa98Sdjl iam = phdr->nsc_callnumber & NSCD_WHOAMI; 654cb5caa98Sdjl else 655cb5caa98Sdjl callnum = phdr->nsc_callnumber; 656cb5caa98Sdjl 657cb5caa98Sdjl /* nscd -> nscd v2 calls */ 658cb5caa98Sdjl switch (callnum) { 659cb5caa98Sdjl 660cb5caa98Sdjl case NSCD_PING: 661cb5caa98Sdjl NSCD_SET_STATUS_SUCCESS(phdr); 662cb5caa98Sdjl break; 663cb5caa98Sdjl 664cb5caa98Sdjl case NSCD_IMHERE: 665cb5caa98Sdjl _nscd_proc_iamhere(argp, dp, n_desc, iam); 666cb5caa98Sdjl break; 667cb5caa98Sdjl 668cb5caa98Sdjl case NSCD_PULSE: 669cb5caa98Sdjl N2N_check_priv(argp, "NSCD_PULSE"); 670cb5caa98Sdjl if (NSCD_STATUS_IS_OK(phdr)) 671cb5caa98Sdjl _nscd_proc_pulse(argp, iam); 672cb5caa98Sdjl break; 673cb5caa98Sdjl 674cb5caa98Sdjl case NSCD_FORK: 675cb5caa98Sdjl N2N_check_priv(argp, "NSCD_FORK"); 676cb5caa98Sdjl if (NSCD_STATUS_IS_OK(phdr)) 677cb5caa98Sdjl _nscd_proc_fork(argp, iam); 678cb5caa98Sdjl break; 679cb5caa98Sdjl 680cb5caa98Sdjl case NSCD_KILL: 681cb5caa98Sdjl N2N_check_priv(argp, "NSCD_KILL"); 682cb5caa98Sdjl if (NSCD_STATUS_IS_OK(phdr)) 683cb5caa98Sdjl exit(0); 684cb5caa98Sdjl break; 685cb5caa98Sdjl 686cb5caa98Sdjl case NSCD_REFRESH: 687cb5caa98Sdjl if (_nscd_refresh() != NSCD_SUCCESS) 688cb5caa98Sdjl exit(1); 689cb5caa98Sdjl NSCD_SET_STATUS_SUCCESS(phdr); 690cb5caa98Sdjl break; 691cb5caa98Sdjl 692cb5caa98Sdjl case NSCD_GETPUADMIN: 693cb5caa98Sdjl 694cb5caa98Sdjl if (_nscd_is_self_cred_on(0, NULL)) { 695cb5caa98Sdjl _nscd_peruser_getadmin(argp, sizeof (nscd_admin_t)); 696cb5caa98Sdjl } else { 697cb5caa98Sdjl NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, 698cb5caa98Sdjl NSCD_SELF_CRED_NOT_CONFIGURED); 699cb5caa98Sdjl } 700cb5caa98Sdjl break; 701cb5caa98Sdjl 702cb5caa98Sdjl case NSCD_GETADMIN: 703cb5caa98Sdjl 704cb5caa98Sdjl len = _nscd_door_getadmin((void *)argp); 705cb5caa98Sdjl if (len == 0) 706cb5caa98Sdjl break; 707cb5caa98Sdjl 708cb5caa98Sdjl /* size of door buffer not big enough, allocate one */ 709cb5caa98Sdjl NSCD_ALLOC_DOORBUF(NSCD_GETADMIN, len, uptr, buflen); 710cb5caa98Sdjl 711cb5caa98Sdjl /* copy packed header */ 712cb5caa98Sdjl *(nss_pheader_t *)uptr = *(nss_pheader_t *)((void *)argp); 713cb5caa98Sdjl 714cb5caa98Sdjl /* set new buffer size */ 715cb5caa98Sdjl ((nss_pheader_t *)uptr)->pbufsiz = buflen; 716cb5caa98Sdjl 717cb5caa98Sdjl /* try one more time */ 718cb5caa98Sdjl (void) _nscd_door_getadmin((void *)uptr); 719cb5caa98Sdjl (void) door_return(uptr, buflen, NULL, 0); 720cb5caa98Sdjl break; 721cb5caa98Sdjl 722cb5caa98Sdjl case NSCD_SETADMIN: 723cb5caa98Sdjl N2N_check_priv(argp, "NSCD_SETADMIN"); 724cb5caa98Sdjl if (NSCD_STATUS_IS_OK(phdr)) 725cb5caa98Sdjl _nscd_door_setadmin(argp); 726cb5caa98Sdjl break; 727cb5caa98Sdjl 728cb5caa98Sdjl case NSCD_KILLSERVER: 729cb5caa98Sdjl N2N_check_priv(argp, "NSCD_KILLSERVER"); 730cb5caa98Sdjl if (NSCD_STATUS_IS_OK(phdr)) { 731cb5caa98Sdjl /* also kill the forker nscd if one is running */ 732cb5caa98Sdjl _nscd_kill_forker(); 733cb5caa98Sdjl exit(0); 734cb5caa98Sdjl } 735cb5caa98Sdjl break; 736cb5caa98Sdjl 737cb5caa98Sdjl default: 738cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 739cb5caa98Sdjl (me, "Unknown name service door call op %d\n", 740cb5caa98Sdjl phdr->nsc_callnumber); 741cb5caa98Sdjl 742cb5caa98Sdjl NSCD_SET_STATUS(phdr, NSS_ERROR, EINVAL); 743cb5caa98Sdjl 744cb5caa98Sdjl (void) door_return(argp, arg_size, NULL, 0); 745cb5caa98Sdjl break; 746cb5caa98Sdjl 747cb5caa98Sdjl } 748cb5caa98Sdjl (void) door_return(argp, arg_size, NULL, 0); 749cb5caa98Sdjl } 750cb5caa98Sdjl 751cb5caa98Sdjl int 752cb5caa98Sdjl _nscd_setup_server(char *execname, char **argv) 753cb5caa98Sdjl { 754cb5caa98Sdjl 755cb5caa98Sdjl int fd; 756cb5caa98Sdjl int errnum; 757cb5caa98Sdjl int bind_failed = 0; 758cb5caa98Sdjl struct stat buf; 759cb5caa98Sdjl sigset_t myset; 760cb5caa98Sdjl struct sigaction action; 761cb5caa98Sdjl char *me = "_nscd_setup_server"; 762cb5caa98Sdjl 763cb5caa98Sdjl main_execname = execname; 764cb5caa98Sdjl main_argv = argv; 765cb5caa98Sdjl 766cb5caa98Sdjl keep_open_dns_socket(); 767cb5caa98Sdjl 768cb5caa98Sdjl /* 769cb5caa98Sdjl * the max number of server threads should be fixed now, so 770cb5caa98Sdjl * set flag to indicate that no in-flight change is allowed 771cb5caa98Sdjl */ 772cb5caa98Sdjl max_servers_set = 1; 773cb5caa98Sdjl 774cb5caa98Sdjl (void) thr_keycreate(&lookup_state_key, NULL); 775cb5caa98Sdjl (void) sema_init(&common_sema, 776cb5caa98Sdjl frontend_cfg_g.common_worker_threads, 777cb5caa98Sdjl USYNC_THREAD, 0); 778cb5caa98Sdjl 779cb5caa98Sdjl /* Establish server thread pool */ 780cb5caa98Sdjl (void) door_server_create(server_create); 781cb5caa98Sdjl if (thr_keycreate(&server_key, server_destroy) != 0) { 782cb5caa98Sdjl errnum = errno; 783cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 784cb5caa98Sdjl (me, "thr_keycreate (server thread): %s\n", 785cb5caa98Sdjl strerror(errnum)); 786cb5caa98Sdjl return (-1); 787cb5caa98Sdjl } 788cb5caa98Sdjl 789cb5caa98Sdjl /* Create a door */ 790cb5caa98Sdjl if ((fd = door_create(switcher, NAME_SERVICE_DOOR_COOKIE, 791cb5caa98Sdjl DOOR_UNREF | DOOR_NO_CANCEL)) < 0) { 792cb5caa98Sdjl errnum = errno; 793cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 794cb5caa98Sdjl (me, "door_create: %s\n", strerror(errnum)); 795cb5caa98Sdjl return (-1); 796cb5caa98Sdjl } 797cb5caa98Sdjl 798cb5caa98Sdjl /* if not main nscd, no more setup to do */ 799cb5caa98Sdjl if (_whoami != NSCD_MAIN) 800cb5caa98Sdjl return (fd); 801cb5caa98Sdjl 802cb5caa98Sdjl /* bind to file system */ 803cb5caa98Sdjl if (is_system_labeled()) { 804cb5caa98Sdjl if (stat(TSOL_NAME_SERVICE_DOOR, &buf) < 0) { 805cb5caa98Sdjl int newfd; 806cb5caa98Sdjl if ((newfd = creat(TSOL_NAME_SERVICE_DOOR, 0444)) < 0) { 807cb5caa98Sdjl errnum = errno; 808cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, 809cb5caa98Sdjl NSCD_LOG_LEVEL_ERROR) 810cb5caa98Sdjl (me, "Cannot create %s: %s\n", 811cb5caa98Sdjl TSOL_NAME_SERVICE_DOOR, 812cb5caa98Sdjl strerror(errnum)); 813cb5caa98Sdjl bind_failed = 1; 814cb5caa98Sdjl } 815cb5caa98Sdjl (void) close(newfd); 816cb5caa98Sdjl } 817cb5caa98Sdjl if (symlink(TSOL_NAME_SERVICE_DOOR, NAME_SERVICE_DOOR) != 0) { 818cb5caa98Sdjl if (errno != EEXIST) { 819cb5caa98Sdjl errnum = errno; 820cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, 821cb5caa98Sdjl NSCD_LOG_LEVEL_ERROR) 822cb5caa98Sdjl (me, "Cannot symlink %s: %s\n", 823cb5caa98Sdjl NAME_SERVICE_DOOR, 824cb5caa98Sdjl strerror(errnum)); 825cb5caa98Sdjl bind_failed = 1; 826cb5caa98Sdjl } 827cb5caa98Sdjl } 828cb5caa98Sdjl } else if (stat(NAME_SERVICE_DOOR, &buf) < 0) { 829cb5caa98Sdjl int newfd; 830cb5caa98Sdjl if ((newfd = creat(NAME_SERVICE_DOOR, 0444)) < 0) { 831cb5caa98Sdjl errnum = errno; 832cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 833cb5caa98Sdjl (me, "Cannot create %s: %s\n", NAME_SERVICE_DOOR, 834cb5caa98Sdjl strerror(errnum)); 835cb5caa98Sdjl bind_failed = 1; 836cb5caa98Sdjl } 837cb5caa98Sdjl (void) close(newfd); 838cb5caa98Sdjl } 839cb5caa98Sdjl 840cb5caa98Sdjl if (bind_failed == 1) { 841cb5caa98Sdjl (void) door_revoke(fd); 842cb5caa98Sdjl return (-1); 843cb5caa98Sdjl } 844cb5caa98Sdjl 845cb5caa98Sdjl if (fattach(fd, NAME_SERVICE_DOOR) < 0) { 846cb5caa98Sdjl if ((errno != EBUSY) || 847cb5caa98Sdjl (fdetach(NAME_SERVICE_DOOR) < 0) || 848cb5caa98Sdjl (fattach(fd, NAME_SERVICE_DOOR) < 0)) { 849cb5caa98Sdjl errnum = errno; 850cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, 851cb5caa98Sdjl NSCD_LOG_LEVEL_ERROR) 852cb5caa98Sdjl (me, "fattach: %s\n", strerror(errnum)); 853cb5caa98Sdjl (void) door_revoke(fd); 854cb5caa98Sdjl return (-1); 855cb5caa98Sdjl } 856cb5caa98Sdjl } 857cb5caa98Sdjl 858cb5caa98Sdjl /* 859cb5caa98Sdjl * kick off routing socket monitor thread 860cb5caa98Sdjl */ 861cb5caa98Sdjl if (thr_create(NULL, NULL, 862cb5caa98Sdjl (void *(*)(void *))rts_mon, 0, 0, NULL) != 0) { 863cb5caa98Sdjl errnum = errno; 864cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 865cb5caa98Sdjl (me, "thr_create (routing socket monitor): %s\n", 866cb5caa98Sdjl strerror(errnum)); 867cb5caa98Sdjl 868cb5caa98Sdjl (void) door_revoke(fd); 869cb5caa98Sdjl return (-1); 870cb5caa98Sdjl } 871cb5caa98Sdjl 872cb5caa98Sdjl /* 873cb5caa98Sdjl * set up signal handler for SIGHUP 874cb5caa98Sdjl */ 875cb5caa98Sdjl action.sa_handler = dozip; 876cb5caa98Sdjl action.sa_flags = 0; 877cb5caa98Sdjl (void) sigemptyset(&action.sa_mask); 878cb5caa98Sdjl (void) sigemptyset(&myset); 879cb5caa98Sdjl (void) sigaddset(&myset, SIGHUP); 880cb5caa98Sdjl 881cb5caa98Sdjl if (sigaction(SIGHUP, &action, NULL) < 0) { 882cb5caa98Sdjl errnum = errno; 883cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 884cb5caa98Sdjl (me, "sigaction (SIGHUP): %s\n", strerror(errnum)); 885cb5caa98Sdjl 886cb5caa98Sdjl (void) door_revoke(fd); 887cb5caa98Sdjl return (-1); 888cb5caa98Sdjl } 889cb5caa98Sdjl 890cb5caa98Sdjl return (fd); 891cb5caa98Sdjl } 892cb5caa98Sdjl 893cb5caa98Sdjl int 894cb5caa98Sdjl _nscd_setup_child_server(int did) 895cb5caa98Sdjl { 896cb5caa98Sdjl 897cb5caa98Sdjl int errnum; 898cb5caa98Sdjl int fd; 899cb5caa98Sdjl nscd_rc_t rc; 900cb5caa98Sdjl char *me = "_nscd_setup_child_server"; 901cb5caa98Sdjl 902cb5caa98Sdjl /* Re-establish our own server thread pool */ 903cb5caa98Sdjl (void) door_server_create(server_create); 904cb5caa98Sdjl if (thr_keycreate(&server_key, server_destroy) != 0) { 905cb5caa98Sdjl errnum = errno; 906cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) 907cb5caa98Sdjl (me, "thr_keycreate failed: %s", strerror(errnum)); 908cb5caa98Sdjl return (-1); 909cb5caa98Sdjl } 910cb5caa98Sdjl 911cb5caa98Sdjl /* 912cb5caa98Sdjl * Create a new door. 913cb5caa98Sdjl * Keep DOOR_REFUSE_DESC (self-cred nscds don't fork) 914cb5caa98Sdjl */ 915cb5caa98Sdjl (void) close(did); 916cb5caa98Sdjl if ((fd = door_create(switcher, 917cb5caa98Sdjl NAME_SERVICE_DOOR_COOKIE, 918cb5caa98Sdjl DOOR_REFUSE_DESC|DOOR_UNREF|DOOR_NO_CANCEL)) < 0) { 919cb5caa98Sdjl errnum = errno; 920cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) 921cb5caa98Sdjl (me, "door_create failed: %s", strerror(errnum)); 922cb5caa98Sdjl return (-1); 923cb5caa98Sdjl } 924cb5caa98Sdjl 925cb5caa98Sdjl /* 926cb5caa98Sdjl * kick off routing socket monitor thread 927cb5caa98Sdjl */ 928cb5caa98Sdjl if (thr_create(NULL, NULL, 929cb5caa98Sdjl (void *(*)(void *))rts_mon, 0, 0, NULL) != 0) { 930cb5caa98Sdjl errnum = errno; 931cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 932cb5caa98Sdjl (me, "thr_create (routing socket monitor): %s\n", 933cb5caa98Sdjl strerror(errnum)); 934cb5caa98Sdjl (void) door_revoke(fd); 935cb5caa98Sdjl return (-1); 936cb5caa98Sdjl } 937cb5caa98Sdjl 938cb5caa98Sdjl /* 939cb5caa98Sdjl * start monitoring the states of the name service clients 940cb5caa98Sdjl */ 941cb5caa98Sdjl rc = _nscd_init_smf_monitor(); 942cb5caa98Sdjl if (rc != NSCD_SUCCESS) { 943cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 944cb5caa98Sdjl (me, "unable to start the SMF monitor (rc = %d)\n", rc); 945cb5caa98Sdjl 946cb5caa98Sdjl (void) door_revoke(fd); 947cb5caa98Sdjl return (-1); 948cb5caa98Sdjl } 949cb5caa98Sdjl 950cb5caa98Sdjl return (fd); 951cb5caa98Sdjl } 952cb5caa98Sdjl 953cb5caa98Sdjl nscd_rc_t 954cb5caa98Sdjl _nscd_alloc_frontend_cfg() 955cb5caa98Sdjl { 956cb5caa98Sdjl frontend_cfg = calloc(NSCD_NUM_DB, sizeof (nscd_cfg_frontend_t)); 957cb5caa98Sdjl if (frontend_cfg == NULL) 958cb5caa98Sdjl return (NSCD_NO_MEMORY); 959cb5caa98Sdjl 960cb5caa98Sdjl return (NSCD_SUCCESS); 961cb5caa98Sdjl } 962cb5caa98Sdjl 963cb5caa98Sdjl 964cb5caa98Sdjl /* ARGSUSED */ 965cb5caa98Sdjl nscd_rc_t 966cb5caa98Sdjl _nscd_cfg_frontend_notify( 967cb5caa98Sdjl void *data, 968cb5caa98Sdjl struct nscd_cfg_param_desc *pdesc, 969cb5caa98Sdjl nscd_cfg_id_t *nswdb, 970cb5caa98Sdjl nscd_cfg_flag_t dflag, 971cb5caa98Sdjl nscd_cfg_error_t **errorp, 972cb5caa98Sdjl void *cookie) 973cb5caa98Sdjl { 974cb5caa98Sdjl void *dp; 975cb5caa98Sdjl 976cb5caa98Sdjl /* 977cb5caa98Sdjl * At init time, the whole group of config params are received. 978cb5caa98Sdjl * At update time, group or individual parameter value could 979cb5caa98Sdjl * be received. 980cb5caa98Sdjl */ 981cb5caa98Sdjl 982cb5caa98Sdjl if (_nscd_cfg_flag_is_set(dflag, NSCD_CFG_DFLAG_INIT) || 983cb5caa98Sdjl _nscd_cfg_flag_is_set(dflag, NSCD_CFG_DFLAG_GROUP)) { 984cb5caa98Sdjl /* 985cb5caa98Sdjl * group data is received, copy in the 986cb5caa98Sdjl * entire strcture 987cb5caa98Sdjl */ 988cb5caa98Sdjl if (_nscd_cfg_flag_is_set(pdesc->pflag, 989cb5caa98Sdjl NSCD_CFG_PFLAG_GLOBAL)) 990cb5caa98Sdjl frontend_cfg_g = 991cb5caa98Sdjl *(nscd_cfg_global_frontend_t *)data; 992cb5caa98Sdjl else 993cb5caa98Sdjl frontend_cfg[nswdb->index] = 994cb5caa98Sdjl *(nscd_cfg_frontend_t *)data; 995cb5caa98Sdjl 996cb5caa98Sdjl } else { 997cb5caa98Sdjl /* 998cb5caa98Sdjl * individual paramater is received: copy in the 999cb5caa98Sdjl * parameter value. 1000cb5caa98Sdjl */ 1001cb5caa98Sdjl if (_nscd_cfg_flag_is_set(pdesc->pflag, 1002cb5caa98Sdjl NSCD_CFG_PFLAG_GLOBAL)) 1003cb5caa98Sdjl dp = (char *)&frontend_cfg_g + pdesc->p_offset; 1004cb5caa98Sdjl else 1005cb5caa98Sdjl dp = (char *)&frontend_cfg[nswdb->index] + 1006cb5caa98Sdjl pdesc->p_offset; 1007cb5caa98Sdjl (void) memcpy(dp, data, pdesc->p_size); 1008cb5caa98Sdjl } 1009cb5caa98Sdjl 1010cb5caa98Sdjl return (NSCD_SUCCESS); 1011cb5caa98Sdjl } 1012cb5caa98Sdjl 1013cb5caa98Sdjl /* ARGSUSED */ 1014cb5caa98Sdjl nscd_rc_t 1015cb5caa98Sdjl _nscd_cfg_frontend_verify( 1016cb5caa98Sdjl void *data, 1017cb5caa98Sdjl struct nscd_cfg_param_desc *pdesc, 1018cb5caa98Sdjl nscd_cfg_id_t *nswdb, 1019cb5caa98Sdjl nscd_cfg_flag_t dflag, 1020cb5caa98Sdjl nscd_cfg_error_t **errorp, 1021cb5caa98Sdjl void **cookie) 1022cb5caa98Sdjl { 1023cb5caa98Sdjl 1024cb5caa98Sdjl char *me = "_nscd_cfg_frontend_verify"; 1025cb5caa98Sdjl 1026cb5caa98Sdjl /* 1027cb5caa98Sdjl * if max. number of server threads is set and in effect, 1028cb5caa98Sdjl * don't allow changing of the frontend configuration 1029cb5caa98Sdjl */ 1030cb5caa98Sdjl if (max_servers_set) { 1031cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_INFO) 1032cb5caa98Sdjl (me, "changing of the frontend configuration not allowed now"); 1033cb5caa98Sdjl 1034cb5caa98Sdjl return (NSCD_CFG_CHANGE_NOT_ALLOWED); 1035cb5caa98Sdjl } 1036cb5caa98Sdjl 1037cb5caa98Sdjl return (NSCD_SUCCESS); 1038cb5caa98Sdjl } 1039cb5caa98Sdjl 1040cb5caa98Sdjl /* ARGSUSED */ 1041cb5caa98Sdjl nscd_rc_t 1042cb5caa98Sdjl _nscd_cfg_frontend_get_stat( 1043cb5caa98Sdjl void **stat, 1044cb5caa98Sdjl struct nscd_cfg_stat_desc *sdesc, 1045cb5caa98Sdjl nscd_cfg_id_t *nswdb, 1046cb5caa98Sdjl nscd_cfg_flag_t *dflag, 1047cb5caa98Sdjl void (**free_stat)(void *stat), 1048cb5caa98Sdjl nscd_cfg_error_t **errorp) 1049cb5caa98Sdjl { 1050cb5caa98Sdjl return (NSCD_SUCCESS); 1051cb5caa98Sdjl } 1052cb5caa98Sdjl 1053cb5caa98Sdjl void 1054cb5caa98Sdjl _nscd_init_cache_sema(sema_t *sema, char *cache_name) 1055cb5caa98Sdjl { 1056cb5caa98Sdjl int i, j; 1057cb5caa98Sdjl char *dbn; 1058cb5caa98Sdjl 1059cb5caa98Sdjl if (max_servers == 0) 1060cb5caa98Sdjl max_servers = frontend_cfg_g.common_worker_threads + 1061cb5caa98Sdjl frontend_cfg_g.cache_hit_threads; 1062cb5caa98Sdjl 1063cb5caa98Sdjl for (i = 0; i < NSCD_NUM_DB; i++) { 1064cb5caa98Sdjl 1065cb5caa98Sdjl dbn = NSCD_NSW_DB_NAME(i); 1066cb5caa98Sdjl if (strcasecmp(dbn, cache_name) == 0) { 1067cb5caa98Sdjl j = frontend_cfg[i].worker_thread_per_nsw_db; 1068cb5caa98Sdjl (void) sema_init(sema, j, USYNC_THREAD, 0); 1069cb5caa98Sdjl max_servers += j; 1070cb5caa98Sdjl break; 1071cb5caa98Sdjl } 1072cb5caa98Sdjl } 1073cb5caa98Sdjl } 1074cb5caa98Sdjl 1075cb5caa98Sdjl /* 1076cb5caa98Sdjl * Monitor the routing socket. Address lists stored in the ipnodes 1077cb5caa98Sdjl * cache are sorted based on destination address selection rules, 1078cb5caa98Sdjl * so when things change that could affect that sorting (interfaces 1079cb5caa98Sdjl * go up or down, flags change, etc.), we clear that cache so the 1080cb5caa98Sdjl * list will be re-ordered the next time the hostname is resolved. 1081cb5caa98Sdjl */ 1082cb5caa98Sdjl static void 1083cb5caa98Sdjl rts_mon(void) 1084cb5caa98Sdjl { 1085cb5caa98Sdjl int rt_sock, rdlen, idx; 1086cb5caa98Sdjl union { 1087cb5caa98Sdjl struct { 1088cb5caa98Sdjl struct rt_msghdr rtm; 1089cb5caa98Sdjl struct sockaddr_storage addrs[RTA_NUMBITS]; 1090cb5caa98Sdjl } r; 1091cb5caa98Sdjl struct if_msghdr ifm; 1092cb5caa98Sdjl struct ifa_msghdr ifam; 1093cb5caa98Sdjl } mbuf; 1094cb5caa98Sdjl struct ifa_msghdr *ifam = &mbuf.ifam; 1095cb5caa98Sdjl char *me = "rts_mon"; 1096cb5caa98Sdjl 1097cb5caa98Sdjl rt_sock = socket(PF_ROUTE, SOCK_RAW, 0); 1098cb5caa98Sdjl if (rt_sock < 0) { 1099cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 1100cb5caa98Sdjl (me, "Failed to open routing socket: %s\n", strerror(errno)); 1101cb5caa98Sdjl thr_exit(0); 1102cb5caa98Sdjl } 1103cb5caa98Sdjl 1104cb5caa98Sdjl for (;;) { 1105cb5caa98Sdjl rdlen = read(rt_sock, &mbuf, sizeof (mbuf)); 1106cb5caa98Sdjl if (rdlen <= 0) { 1107cb5caa98Sdjl if (rdlen == 0 || (errno != EINTR && errno != EAGAIN)) { 1108cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, 1109cb5caa98Sdjl NSCD_LOG_LEVEL_ERROR) 1110cb5caa98Sdjl (me, "routing socket read: %s\n", 1111cb5caa98Sdjl strerror(errno)); 1112cb5caa98Sdjl thr_exit(0); 1113cb5caa98Sdjl } 1114cb5caa98Sdjl continue; 1115cb5caa98Sdjl } 1116cb5caa98Sdjl if (ifam->ifam_version != RTM_VERSION) { 1117cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, 1118cb5caa98Sdjl NSCD_LOG_LEVEL_ERROR) 1119cb5caa98Sdjl (me, "rx unknown version (%d) on " 1120cb5caa98Sdjl "routing socket.\n", 1121cb5caa98Sdjl ifam->ifam_version); 1122cb5caa98Sdjl continue; 1123cb5caa98Sdjl } 1124cb5caa98Sdjl switch (ifam->ifam_type) { 1125cb5caa98Sdjl case RTM_NEWADDR: 1126cb5caa98Sdjl case RTM_DELADDR: 1127cb5caa98Sdjl /* if no ipnodes cache, then nothing to do */ 1128cb5caa98Sdjl idx = get_cache_idx("ipnodes"); 1129cb5caa98Sdjl if (cache_ctx_p[idx] == NULL || 1130cb5caa98Sdjl cache_ctx_p[idx]->reaper_on != nscd_true) 1131cb5caa98Sdjl break; 1132cb5caa98Sdjl nsc_invalidate(cache_ctx_p[idx], NULL, NULL); 1133cb5caa98Sdjl break; 1134cb5caa98Sdjl case RTM_ADD: 1135cb5caa98Sdjl case RTM_DELETE: 1136cb5caa98Sdjl case RTM_CHANGE: 1137cb5caa98Sdjl case RTM_GET: 1138cb5caa98Sdjl case RTM_LOSING: 1139cb5caa98Sdjl case RTM_REDIRECT: 1140cb5caa98Sdjl case RTM_MISS: 1141cb5caa98Sdjl case RTM_LOCK: 1142cb5caa98Sdjl case RTM_OLDADD: 1143cb5caa98Sdjl case RTM_OLDDEL: 1144cb5caa98Sdjl case RTM_RESOLVE: 1145cb5caa98Sdjl case RTM_IFINFO: 1146cb5caa98Sdjl break; 1147cb5caa98Sdjl default: 1148cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 1149cb5caa98Sdjl (me, "rx unknown msg type (%d) on routing socket.\n", 1150cb5caa98Sdjl ifam->ifam_type); 1151cb5caa98Sdjl break; 1152cb5caa98Sdjl } 1153cb5caa98Sdjl } 1154cb5caa98Sdjl } 1155cb5caa98Sdjl 1156cb5caa98Sdjl static void 1157cb5caa98Sdjl keep_open_dns_socket(void) 1158cb5caa98Sdjl { 1159cb5caa98Sdjl _res.options |= RES_STAYOPEN; /* just keep this udp socket open */ 1160cb5caa98Sdjl } 1161