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