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