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 /* 220dfdd7f3Smichen * Copyright 2007 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 <locale.h> 29cb5caa98Sdjl #include <unistd.h> 30cb5caa98Sdjl #include <string.h> 31e37190e5Smichen #include <time.h> 32cb5caa98Sdjl #include "nscd_common.h" 33cb5caa98Sdjl #include "nscd_config.h" 34cb5caa98Sdjl #include "nscd_log.h" 35cb5caa98Sdjl #include "nscd_switch.h" 36cb5caa98Sdjl #include "nscd_frontend.h" 37cb5caa98Sdjl 38cb5caa98Sdjl static char *cfgfile_save = NULL; 39e37190e5Smichen static mutex_t time_mutex = DEFAULTMUTEX; 40e37190e5Smichen static time_t start_time = 0; 41e37190e5Smichen 42e37190e5Smichen void 43e37190e5Smichen _nscd_set_start_time(int reset) 44e37190e5Smichen { 45e37190e5Smichen (void) mutex_lock(&time_mutex); 46e37190e5Smichen if (start_time == 0 || reset == 1) 47e37190e5Smichen start_time = time(NULL); 48e37190e5Smichen (void) mutex_unlock(&time_mutex); 49e37190e5Smichen } 50e37190e5Smichen 51e37190e5Smichen time_t 52e37190e5Smichen _nscd_get_start_time() 53e37190e5Smichen { 54e37190e5Smichen return (start_time); 55e37190e5Smichen } 56cb5caa98Sdjl 57cb5caa98Sdjl nscd_rc_t 58cb5caa98Sdjl _nscd_init( 59cb5caa98Sdjl char *cfgfile) 60cb5caa98Sdjl { 61cb5caa98Sdjl char *me = "nscd_init"; 62cb5caa98Sdjl nscd_rc_t rc; 63cb5caa98Sdjl nscd_cfg_error_t *err; 64cb5caa98Sdjl 65cb5caa98Sdjl /* 66e37190e5Smichen * remember when main or forker nscd starts. 67e37190e5Smichen */ 68e37190e5Smichen _nscd_set_start_time(0); 69e37190e5Smichen 70e37190e5Smichen /* 71cb5caa98Sdjl * allocate the space for tables 72cb5caa98Sdjl */ 73e37190e5Smichen if ((rc = _nscd_alloc_nsw_config()) != NSCD_SUCCESS || 74e37190e5Smichen (rc = _nscd_alloc_service_state_table()) != NSCD_SUCCESS || 75e37190e5Smichen (rc = _nscd_alloc_nsw_state_base()) != NSCD_SUCCESS || 76e37190e5Smichen (rc = _nscd_alloc_nsw_be_info_db()) != NSCD_SUCCESS || 77e37190e5Smichen (rc = _nscd_alloc_getent_ctx_base()) != NSCD_SUCCESS) 78cb5caa98Sdjl return (rc); 79cb5caa98Sdjl 80cb5caa98Sdjl /* 81cb5caa98Sdjl * allocate the space for local configuration 82cb5caa98Sdjl * and statistics 83cb5caa98Sdjl */ 84e37190e5Smichen if ((rc = _nscd_alloc_switch_cfg()) != NSCD_SUCCESS || 85e37190e5Smichen (rc = _nscd_alloc_frontend_cfg()) != NSCD_SUCCESS || 86e37190e5Smichen (rc = _nscd_alloc_switch_stats()) != NSCD_SUCCESS) 87cb5caa98Sdjl return (rc); 88cb5caa98Sdjl 89cb5caa98Sdjl /* 90cb5caa98Sdjl * Create and init the internal address database to keep 91cb5caa98Sdjl * track of the memory allocated by _nscd_alloc 92cb5caa98Sdjl */ 93cb5caa98Sdjl if (_nscd_create_int_addrDB() == NULL) { 94cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_INT_ADDR, NSCD_LOG_LEVEL_ERROR) 95cb5caa98Sdjl (me, "_nscd_create_int_addrDB failed\n"); 96cb5caa98Sdjl return (NSCD_NO_MEMORY); 97cb5caa98Sdjl } 98cb5caa98Sdjl 99cb5caa98Sdjl /* 100cb5caa98Sdjl * Create and init the internal context database to keep 101cb5caa98Sdjl * track of the getent context currently being used 102cb5caa98Sdjl */ 103cb5caa98Sdjl if (_nscd_create_getent_ctxDB() == NULL) { 104cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_ERROR) 105cb5caa98Sdjl (me, "_nscd_create_getent_ctx_addrDB failed\n"); 106cb5caa98Sdjl return (NSCD_NO_MEMORY); 107cb5caa98Sdjl } 108cb5caa98Sdjl 109cb5caa98Sdjl /* 110cb5caa98Sdjl * Create the backend info database for each possible source 111cb5caa98Sdjl */ 112cb5caa98Sdjl if ((rc = _nscd_init_all_nsw_be_info_db()) != NSCD_SUCCESS) { 113cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR) 114cb5caa98Sdjl (me, "_nscd_init_all_nsw_be_info_db failed (rc = %d)\n", 115cb5caa98Sdjl rc); 116cb5caa98Sdjl return (rc); 117cb5caa98Sdjl } 118cb5caa98Sdjl 119cb5caa98Sdjl /* 120cb5caa98Sdjl * Create the nscd_nsw_config_t for each possible nss database 121cb5caa98Sdjl */ 122cb5caa98Sdjl if ((rc = _nscd_init_all_nsw_config()) != NSCD_SUCCESS) { 123cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR) 124cb5caa98Sdjl (me, "_nscd_init_all_nsw_config failed (rc = %d)\n", rc); 125cb5caa98Sdjl return (rc); 126cb5caa98Sdjl } 127cb5caa98Sdjl 128cb5caa98Sdjl /* 129cb5caa98Sdjl * initialize config/stats management 130cb5caa98Sdjl */ 131cb5caa98Sdjl rc = _nscd_cfg_init(&err); 132cb5caa98Sdjl if (rc != NSCD_SUCCESS) { 133cb5caa98Sdjl if (err != NULL) 134cb5caa98Sdjl _nscd_cfg_free_error(err); 135cb5caa98Sdjl return (rc); 136cb5caa98Sdjl } 137cb5caa98Sdjl 138cb5caa98Sdjl /* 139cb5caa98Sdjl * read in the nsswitch configuration 140cb5caa98Sdjl */ 141cb5caa98Sdjl rc = _nscd_cfg_read_nsswitch_file("/etc/nsswitch.conf", &err); 142cb5caa98Sdjl if (rc != NSCD_SUCCESS) { 143cb5caa98Sdjl (void) printf( 144cb5caa98Sdjl gettext("reading config file %s failed with rc = %d, %s\n"), 145cb5caa98Sdjl "/etc/nsswitch.conf", rc, NSCD_ERR2MSG(err)); 146cb5caa98Sdjl if (err != NULL) 147cb5caa98Sdjl _nscd_cfg_free_error(err); 148cb5caa98Sdjl 149cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 150cb5caa98Sdjl (me, "unable to read /etc/nsswitch.conf (rc = %d)\n", rc); 151cb5caa98Sdjl return (rc); 152cb5caa98Sdjl } 153*80b80bf0Smichen /* 154*80b80bf0Smichen * remember which version of /etc/nsswitch.conf that was read 155*80b80bf0Smichen */ 156*80b80bf0Smichen _nscd_restart_if_cfgfile_changed(); 157cb5caa98Sdjl 158cb5caa98Sdjl /* 159cb5caa98Sdjl * read in the nscd configuration 160cb5caa98Sdjl */ 161cb5caa98Sdjl if (cfgfile == NULL) { 162cb5caa98Sdjl cfgfile = "/etc/nscd.conf"; 163cb5caa98Sdjl if (access(cfgfile, R_OK) != 0) { 164cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 165cb5caa98Sdjl (me, "unable to read /etc/nscd.conf (rc = %d)\n", rc); 166cb5caa98Sdjl 167cb5caa98Sdjl return (NSCD_CFG_FILE_ACCESS_ERROR); 168cb5caa98Sdjl } 169cb5caa98Sdjl } 170cb5caa98Sdjl rc = _nscd_cfg_read_file(cfgfile, &err); 171cb5caa98Sdjl if (rc != NSCD_SUCCESS) { 172cb5caa98Sdjl (void) printf( 173cb5caa98Sdjl gettext("reading config file %s failed with rc = %d, %s\n"), 174cb5caa98Sdjl cfgfile, rc, NSCD_ERR2MSG(err)); 175cb5caa98Sdjl if (err != NULL) 176cb5caa98Sdjl _nscd_cfg_free_error(err); 177cb5caa98Sdjl 178cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) 179cb5caa98Sdjl (me, "unable to read configuration from %s (rc = %d)\n", 180cb5caa98Sdjl cfgfile, rc); 181cb5caa98Sdjl 182cb5caa98Sdjl return (rc); 183cb5caa98Sdjl } 184cb5caa98Sdjl /* 185cb5caa98Sdjl * remember the name of the config file 186cb5caa98Sdjl * in case refresh is requested later 187cb5caa98Sdjl */ 188cb5caa98Sdjl if (cfgfile != NULL) { 189cb5caa98Sdjl cfgfile_save = strdup(cfgfile); 190e37190e5Smichen if (cfgfile_save == NULL) 191cb5caa98Sdjl return (NSCD_NO_MEMORY); 192cb5caa98Sdjl } 193cb5caa98Sdjl 194cb5caa98Sdjl return (NSCD_SUCCESS); 195cb5caa98Sdjl } 196cb5caa98Sdjl 197cb5caa98Sdjl nscd_rc_t 198cb5caa98Sdjl _nscd_refresh() 199cb5caa98Sdjl { 200cb5caa98Sdjl char *me = "nscd_refresh"; 201cb5caa98Sdjl char *cfgfile; 202cb5caa98Sdjl nscd_rc_t rc; 203cb5caa98Sdjl nscd_cfg_error_t *err; 204cb5caa98Sdjl char errmsg[1024]; 205cb5caa98Sdjl 206cb5caa98Sdjl /* 207cb5caa98Sdjl * re-read the nsswitch configuration 208cb5caa98Sdjl */ 209cb5caa98Sdjl rc = _nscd_cfg_read_nsswitch_file("/etc/nsswitch.conf", &err); 210cb5caa98Sdjl if (rc != NSCD_SUCCESS) { 211cb5caa98Sdjl (void) snprintf(errmsg, sizeof (errmsg), 212cb5caa98Sdjl "unable to parse the config file %s (rc = %d), %s\n", 213cb5caa98Sdjl "/etc/nsswitch.conf", rc, NSCD_ERR2MSG(err)); 214cb5caa98Sdjl goto error_exit; 215cb5caa98Sdjl } 216cb5caa98Sdjl 217cb5caa98Sdjl /* 218cb5caa98Sdjl * re-read the nscd configuration 219cb5caa98Sdjl */ 220cb5caa98Sdjl if (cfgfile_save == NULL) 221cb5caa98Sdjl cfgfile = "/etc/nscd.conf"; 222cb5caa98Sdjl else 223cb5caa98Sdjl cfgfile = cfgfile_save; 224cb5caa98Sdjl 225cb5caa98Sdjl if (access(cfgfile, R_OK) != 0) { 226cb5caa98Sdjl (void) snprintf(errmsg, sizeof (errmsg), 227cb5caa98Sdjl "unable to read the config file %s (rc = %d), %s\n", 228cb5caa98Sdjl cfgfile, NSCD_CFG_FILE_ACCESS_ERROR, 229cb5caa98Sdjl strerror(errno)); 230cb5caa98Sdjl 231cb5caa98Sdjl goto error_exit; 232cb5caa98Sdjl } 233cb5caa98Sdjl 234cb5caa98Sdjl rc = _nscd_cfg_read_file(cfgfile, &err); 235cb5caa98Sdjl if (rc != NSCD_SUCCESS) { 236cb5caa98Sdjl (void) snprintf(errmsg, sizeof (errmsg), 237cb5caa98Sdjl "unable to parse the config file %s (rc = %d), %s\n", 238cb5caa98Sdjl cfgfile, rc, NSCD_ERR2MSG(err)); 239cb5caa98Sdjl 240cb5caa98Sdjl goto error_exit; 241cb5caa98Sdjl } 242cb5caa98Sdjl 243cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ALL) 244cb5caa98Sdjl (me, "nsswitch/nscd configuration refreshed successfully\n"); 245cb5caa98Sdjl 246cb5caa98Sdjl return (NSCD_SUCCESS); 247cb5caa98Sdjl 248cb5caa98Sdjl error_exit: 249cb5caa98Sdjl 250cb5caa98Sdjl if (err != NULL) 251cb5caa98Sdjl _nscd_cfg_free_error(err); 252cb5caa98Sdjl 253cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 254cb5caa98Sdjl (me, "%s\n", errmsg); 255cb5caa98Sdjl 256cb5caa98Sdjl return (rc); 257cb5caa98Sdjl } 258