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 260dfdd7f3Smichen #include <nss_common.h> 270dfdd7f3Smichen #include <dlfcn.h> 280dfdd7f3Smichen #include <alloca.h> 290dfdd7f3Smichen 30cb5caa98Sdjl #include <stdlib.h> 31cb5caa98Sdjl #include <libscf_priv.h> 32cb5caa98Sdjl #include <string.h> 33cb5caa98Sdjl #include <assert.h> 34cb5caa98Sdjl #include "nscd_switch.h" 35cb5caa98Sdjl #include "nscd_log.h" 36cb5caa98Sdjl #include "nscd_db.h" 37cb5caa98Sdjl 38cb5caa98Sdjl /* 390dfdd7f3Smichen * _nscd_nss_finders is used to replace the nss_default_finders in libc 400dfdd7f3Smichen * to allow nscd to have more control over the dl handles when using 410dfdd7f3Smichen * dlsym to get the address of the nss backend instance constructors 420dfdd7f3Smichen */ 430dfdd7f3Smichen static nss_backend_constr_t _nscd_per_src_lookup(void *, 440dfdd7f3Smichen const char *, const char *, void **); 450dfdd7f3Smichen static void _nscd_per_src_delete(void *, nss_backend_constr_t); 460dfdd7f3Smichen 470dfdd7f3Smichen static nss_backend_finder_t _nscd_per_src = { 480dfdd7f3Smichen _nscd_per_src_lookup, 490dfdd7f3Smichen _nscd_per_src_delete, 500dfdd7f3Smichen 0, 510dfdd7f3Smichen 0 }; 520dfdd7f3Smichen 530dfdd7f3Smichen nss_backend_finder_t *_nscd_nss_finders = &_nscd_per_src; 540dfdd7f3Smichen 550dfdd7f3Smichen /* 56cb5caa98Sdjl * nscd database for each source. It contains backend 57cb5caa98Sdjl * info (nscd_be_info_t) for each naming database. 58cb5caa98Sdjl * Protected by nscd_src_backend_db_lock. 59cb5caa98Sdjl */ 60cb5caa98Sdjl nscd_db_t ***nscd_src_backend_db; 610dfdd7f3Smichen int *nscd_src_backend_db_loaded; 62cb5caa98Sdjl static rwlock_t nscd_src_backend_db_lock = DEFAULTRWLOCK; 63cb5caa98Sdjl 64cb5caa98Sdjl /* 65cb5caa98Sdjl * nsswitch config monitored by nscd. Protected by 66cb5caa98Sdjl * readers/writer lock nscd_nsw_config_lock 67cb5caa98Sdjl */ 68cb5caa98Sdjl nscd_nsw_config_t ***nscd_nsw_config; 69cb5caa98Sdjl static rwlock_t nscd_nsw_config_lock = DEFAULTRWLOCK; 70cb5caa98Sdjl 71cb5caa98Sdjl /* 72cb5caa98Sdjl * nsswitch source index/name array 73d2ba247cSmichen * (allow 32 foreign nsswitch sources/backends) 74cb5caa98Sdjl */ 75d2ba247cSmichen #define NSCD_NUM_SRC_FOREIGN 32 76cb5caa98Sdjl nscd_cfg_id_t *_nscd_cfg_nsw_src_all; 77cb5caa98Sdjl int _nscd_cfg_num_nsw_src_all; 78cb5caa98Sdjl 79cb5caa98Sdjl static void 80cb5caa98Sdjl free_nscd_nsw_config( 81cb5caa98Sdjl nscd_acc_data_t *data) 82cb5caa98Sdjl { 83cb5caa98Sdjl 84cb5caa98Sdjl nscd_nsw_config_t *nsw_cfg = *(nscd_nsw_config_t **)data; 85cb5caa98Sdjl char *me = "free_nscd_nsw_config"; 86cb5caa98Sdjl 87cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 88cb5caa98Sdjl (me, "freeing nscd nsw config %p \n", nsw_cfg); 89cb5caa98Sdjl if (nsw_cfg == NULL) 90cb5caa98Sdjl return; 91cb5caa98Sdjl 92cb5caa98Sdjl if (nsw_cfg->db_name != NULL) 93cb5caa98Sdjl free(nsw_cfg->db_name); 94cb5caa98Sdjl if (nsw_cfg->nsw_cfg_str != NULL) 95cb5caa98Sdjl free(nsw_cfg->nsw_cfg_str); 96cb5caa98Sdjl if (nsw_cfg->nsw_config != NULL) 97cb5caa98Sdjl (void) __nsw_freeconfig_v1(nsw_cfg->nsw_config); 98cb5caa98Sdjl if (nsw_cfg->src_idx != NULL) 99cb5caa98Sdjl free(nsw_cfg->src_idx); 100cb5caa98Sdjl 101cb5caa98Sdjl free(nsw_cfg); 102cb5caa98Sdjl } 103cb5caa98Sdjl 104cb5caa98Sdjl 105cb5caa98Sdjl void 106cb5caa98Sdjl _nscd_free_nsw_config( 107cb5caa98Sdjl nscd_nsw_config_t *nswcfg) 108cb5caa98Sdjl { 109cb5caa98Sdjl free_nscd_nsw_config((nscd_acc_data_t *)&nswcfg); 110cb5caa98Sdjl } 111cb5caa98Sdjl 112cb5caa98Sdjl void 113cb5caa98Sdjl _nscd_free_all_nsw_config() 114cb5caa98Sdjl { 115cb5caa98Sdjl 116cb5caa98Sdjl nscd_nsw_config_t **nsw_cfg; 117cb5caa98Sdjl int i; 118cb5caa98Sdjl char *me = "_nscd_free_all_nsw_config"; 119cb5caa98Sdjl 120cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 121cb5caa98Sdjl (me, "freeing all nscd nsw config \n"); 122cb5caa98Sdjl 123cb5caa98Sdjl (void) rw_wrlock(&nscd_nsw_config_lock); 124cb5caa98Sdjl for (i = 0; i < NSCD_NUM_DB; i++) { 125cb5caa98Sdjl 126cb5caa98Sdjl if ((nsw_cfg = nscd_nsw_config[i]) == NULL) 127cb5caa98Sdjl continue; 128cb5caa98Sdjl 129cb5caa98Sdjl nscd_nsw_config[i] = (nscd_nsw_config_t **)_nscd_set( 130cb5caa98Sdjl (nscd_acc_data_t *)nsw_cfg, NULL); 131cb5caa98Sdjl } 132cb5caa98Sdjl (void) rw_unlock(&nscd_nsw_config_lock); 133cb5caa98Sdjl } 134cb5caa98Sdjl 135cb5caa98Sdjl 136cb5caa98Sdjl static void 137cb5caa98Sdjl free_nsw_backend_info_db(nscd_acc_data_t *data) 138cb5caa98Sdjl { 139cb5caa98Sdjl 140cb5caa98Sdjl nscd_db_t *db = *(nscd_db_t **)data; 141cb5caa98Sdjl char *me = "free_nsw_backend_info_db"; 142cb5caa98Sdjl 143cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 144cb5caa98Sdjl (me, "freeing nsw backend info db %p\n", db); 145cb5caa98Sdjl 146cb5caa98Sdjl if (db == NULL) 147cb5caa98Sdjl return; 148cb5caa98Sdjl 149cb5caa98Sdjl _nscd_free_db(db); 150cb5caa98Sdjl 151cb5caa98Sdjl } 152cb5caa98Sdjl 153cb5caa98Sdjl void 154cb5caa98Sdjl _nscd_free_all_nsw_backend_info_db() 155cb5caa98Sdjl { 156cb5caa98Sdjl 157cb5caa98Sdjl nscd_db_t **db; 158cb5caa98Sdjl int i; 159cb5caa98Sdjl char *me = " _nscd_free_all_nsw_backend_info_db"; 160cb5caa98Sdjl 161cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 162cb5caa98Sdjl (me, "freeing all nsw backend info db\n"); 163cb5caa98Sdjl 164cb5caa98Sdjl (void) rw_wrlock(&nscd_src_backend_db_lock); 165cb5caa98Sdjl for (i = 0; i < NSCD_NUM_SRC; i++) { 166cb5caa98Sdjl 167cb5caa98Sdjl if ((db = nscd_src_backend_db[i]) == NULL) 168cb5caa98Sdjl continue; 169cb5caa98Sdjl 170cb5caa98Sdjl nscd_src_backend_db[i] = (nscd_db_t **)_nscd_set( 171cb5caa98Sdjl (nscd_acc_data_t *)db, NULL); 1720dfdd7f3Smichen nscd_src_backend_db_loaded[i] = 0; 173cb5caa98Sdjl } 174cb5caa98Sdjl (void) rw_unlock(&nscd_src_backend_db_lock); 175cb5caa98Sdjl } 176cb5caa98Sdjl 177cb5caa98Sdjl /* 178cb5caa98Sdjl * Populate the backend info db for the 'NSCD_NSW_SRC_NAME(srci)' 179cb5caa98Sdjl * source. Create one entry for each source/database pair 180cb5caa98Sdjl * (e.g., ldap:passwd, nis:hosts, etc). 181cb5caa98Sdjl */ 182cb5caa98Sdjl static nscd_rc_t 183cb5caa98Sdjl _nscd_populate_nsw_backend_info_db(int srci) 184cb5caa98Sdjl { 185cb5caa98Sdjl nscd_be_info_t be_info, *bi; 186cb5caa98Sdjl nss_backend_finder_t *bf; 187cb5caa98Sdjl nscd_nsw_config_t *nsw_cfg; 188cb5caa98Sdjl int i, size; 189cb5caa98Sdjl nscd_db_entry_t *db_entry; 190cb5caa98Sdjl char *src = NSCD_NSW_SRC_NAME(srci); 191cb5caa98Sdjl const char *dbn; 192cb5caa98Sdjl char *me = "_nscd_populate_nsw_backend_info_db"; 1930dfdd7f3Smichen void *handle = NULL; 194d2ba247cSmichen nss_backend_constr_t c; 195d2ba247cSmichen void *be_version = &_nscd_be_version; 196d2ba247cSmichen 197d2ba247cSmichen /* get the version number of the backend (if available) */ 198d2ba247cSmichen if (srci >= _nscd_cfg_num_nsw_src) { /* a foreign backend */ 199d2ba247cSmichen c = _nscd_per_src_lookup(handle, NULL, src, &handle); 200d2ba247cSmichen if (c == NULL) 201d2ba247cSmichen be_version = NULL; 202d2ba247cSmichen else 203d2ba247cSmichen be_version = (void *)c; 204d2ba247cSmichen 205d2ba247cSmichen _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 206d2ba247cSmichen (me, "foreign backend: _nss_%s_version = %p ", src, be_version); 207d2ba247cSmichen } 208cb5caa98Sdjl 209cb5caa98Sdjl for (i = 0; i < NSCD_NUM_DB; i++) { 210cb5caa98Sdjl 211*cfed26cbSMichen Chang /* no nsswitch configuration, no backend info db population */ 212*cfed26cbSMichen Chang if (nscd_nsw_config[i] == NULL || *nscd_nsw_config[i] == NULL) 213cb5caa98Sdjl continue; 214cb5caa98Sdjl 215cb5caa98Sdjl nsw_cfg = *nscd_nsw_config[i]; 216cb5caa98Sdjl dbn = NSCD_NSW_DB_NAME(i); 217cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 218cb5caa98Sdjl (me, "adding backend info for <%s : %s>\n", src, dbn); 219cb5caa98Sdjl 220cb5caa98Sdjl (void) memset(&be_info, 0, sizeof (be_info)); 221cb5caa98Sdjl 222d2ba247cSmichen for (bf = nsw_cfg->fe_params.finders; bf != 0; bf = bf->next) { 223cb5caa98Sdjl 2240dfdd7f3Smichen c = (*bf->lookup)(handle, dbn, src, &handle); 225cb5caa98Sdjl 226cb5caa98Sdjl if (c != 0) { 227cb5caa98Sdjl be_info.be_constr = c; 228cb5caa98Sdjl be_info.finder = bf; 2290dfdd7f3Smichen be_info.finder_priv = handle; 230d2ba247cSmichen be_info.be_version = be_version; 231cb5caa98Sdjl break; 232cb5caa98Sdjl } 233cb5caa98Sdjl } 234cb5caa98Sdjl if (be_info.be_constr == NULL) { 235cb5caa98Sdjl /* 236cb5caa98Sdjl * Couldn't find the backend anywhere. 237cb5caa98Sdjl * This is fine, some backend just don't 238cb5caa98Sdjl * support certain databases. 239cb5caa98Sdjl */ 240cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 241cb5caa98Sdjl (me, "unable to find backend info " 242cb5caa98Sdjl "for <%s : %s>\n", src, dbn); 243cb5caa98Sdjl } 244cb5caa98Sdjl 245cb5caa98Sdjl size = sizeof (nscd_be_info_t); 246cb5caa98Sdjl 247cb5caa98Sdjl db_entry = _nscd_alloc_db_entry(NSCD_DATA_BACKEND_INFO, 248cb5caa98Sdjl dbn, size, 1, 1); 249cb5caa98Sdjl 250cb5caa98Sdjl if (db_entry == NULL) { 251cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 252cb5caa98Sdjl (me, "unable to allocate db entry for " 253cb5caa98Sdjl "<%s : %s>\n", src, dbn); 254cb5caa98Sdjl return (NSCD_NO_MEMORY); 255cb5caa98Sdjl } 256cb5caa98Sdjl 257cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 258cb5caa98Sdjl (me, "adding be db entry %p for <%s : %s> to db %p: " 259cb5caa98Sdjl "constr = %p\n", db_entry, src, dbn, 260cb5caa98Sdjl *nscd_src_backend_db[srci], be_info.be_constr); 261cb5caa98Sdjl 262cb5caa98Sdjl bi = (nscd_be_info_t *)*(db_entry->data_array); 263cb5caa98Sdjl *bi = be_info; 264cb5caa98Sdjl 2650dfdd7f3Smichen (void) _nscd_wrlock((nscd_acc_data_t *) 266cb5caa98Sdjl nscd_src_backend_db[srci]); 2670dfdd7f3Smichen nscd_src_backend_db_loaded[srci] = 1; 268cb5caa98Sdjl (void) _nscd_add_db_entry(*nscd_src_backend_db[srci], 269cb5caa98Sdjl dbn, db_entry, NSCD_ADD_DB_ENTRY_LAST); 270cb5caa98Sdjl (void) _nscd_rw_unlock((nscd_acc_data_t *) 271cb5caa98Sdjl nscd_src_backend_db[srci]); 272cb5caa98Sdjl } 273cb5caa98Sdjl 274cb5caa98Sdjl return (NSCD_SUCCESS); 275cb5caa98Sdjl } 276cb5caa98Sdjl 277cb5caa98Sdjl /* 278cb5caa98Sdjl * create data structures (used by the switch engine) based 279cb5caa98Sdjl * on the input switch policy configuration and database 280cb5caa98Sdjl * name and indexes 281cb5caa98Sdjl */ 282cb5caa98Sdjl nscd_rc_t 283cb5caa98Sdjl _nscd_create_sw_struct( 284cb5caa98Sdjl int dbi, 285ad0e80f7Smichen int compat_basei, 286cb5caa98Sdjl const char *dbn, 287cb5caa98Sdjl const char *cfgstr, 288cb5caa98Sdjl void *swcfgv1, 289cb5caa98Sdjl nscd_nsw_params_t *params) 290cb5caa98Sdjl { 291cb5caa98Sdjl char *me = "_nscd_create_sw_struct"; 292cb5caa98Sdjl nscd_rc_t rc = NSCD_SUCCESS; 293cb5caa98Sdjl nscd_nsw_config_t *nsw_cfg = NULL; 294cb5caa98Sdjl nscd_nsw_config_t **nsw_cfg_p = NULL; 295cb5caa98Sdjl struct __nsw_switchconfig_v1 *swcfg = NULL; 296cb5caa98Sdjl struct __nsw_lookup_v1 *lkp; 297cb5caa98Sdjl enum __nsw_parse_err err; 298cb5caa98Sdjl int maxsrc; 299cb5caa98Sdjl int *src_idx_a = NULL; 300cb5caa98Sdjl int j, k; 301cb5caa98Sdjl 302cb5caa98Sdjl /* 303cb5caa98Sdjl * if the nsw config string has been parsed into 304cb5caa98Sdjl * a struct __nsw_switchconfig_v1, use it. If not, 305cb5caa98Sdjl * create the struct. 306cb5caa98Sdjl */ 307cb5caa98Sdjl if (swcfgv1 != NULL) 308cb5caa98Sdjl swcfg = (struct __nsw_switchconfig_v1 *)swcfgv1; 309cb5caa98Sdjl else { 310cb5caa98Sdjl char *cstr; 311cb5caa98Sdjl 312cb5caa98Sdjl cstr = strdup(cfgstr); 313cb5caa98Sdjl if (cstr == NULL) 314cb5caa98Sdjl return (NSCD_NO_MEMORY); 315cb5caa98Sdjl 316cb5caa98Sdjl /* 317cb5caa98Sdjl * parse the nsw config string and create 318cb5caa98Sdjl * a struct __nsw_switchconfig_v1 319cb5caa98Sdjl */ 320cb5caa98Sdjl swcfg = _nsw_getoneconfig_v1(dbn, cstr, &err); 321cb5caa98Sdjl free(cstr); 322cb5caa98Sdjl if (swcfg == NULL) { 323cb5caa98Sdjl rc = NSCD_CFG_SYNTAX_ERROR; 324cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 325cb5caa98Sdjl (me, "error: unable to process nsw config string\n"); 326cb5caa98Sdjl goto error_exit; 327cb5caa98Sdjl } 328cb5caa98Sdjl } 329cb5caa98Sdjl 330cb5caa98Sdjl /* allocate the space for a nscd_nsw_config_t */ 331cb5caa98Sdjl nsw_cfg = calloc(1, sizeof (nscd_nsw_config_t)); 332cb5caa98Sdjl if (nsw_cfg == NULL) { 333cb5caa98Sdjl rc = NSCD_NO_MEMORY; 334cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 335cb5caa98Sdjl (me, "error: unable to allocate an nscd_nsw_config_t\n"); 336cb5caa98Sdjl goto error_exit; 337cb5caa98Sdjl } 338cb5caa98Sdjl 339cb5caa98Sdjl /* need to know how many backends (sources) */ 340cb5caa98Sdjl maxsrc = swcfg->num_lookups; 341cb5caa98Sdjl nsw_cfg->max_src = maxsrc; 342cb5caa98Sdjl 343cb5caa98Sdjl /* 344cb5caa98Sdjl * allocate an array to store the index for each 345cb5caa98Sdjl * backend (source) 346cb5caa98Sdjl */ 347cb5caa98Sdjl src_idx_a = calloc(1, maxsrc * sizeof (int)); 348cb5caa98Sdjl if (src_idx_a == NULL) { 349cb5caa98Sdjl rc = NSCD_NO_MEMORY; 350cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 351cb5caa98Sdjl (me, "error: unable to allocate an array for source index\n"); 352cb5caa98Sdjl goto error_exit; 353cb5caa98Sdjl } 354cb5caa98Sdjl 355cb5caa98Sdjl /* 356cb5caa98Sdjl * set the index for each backend (source) 357cb5caa98Sdjl */ 358cb5caa98Sdjl lkp = swcfg->lookups; 359cb5caa98Sdjl for (j = 0; j < maxsrc; j++) { 360cb5caa98Sdjl char *usrc; 361cb5caa98Sdjl 362d2ba247cSmichen for (k = 0; k < NSCD_NUM_SRC && NSCD_NSW_SRC_NAME(k) != NULL && 363d2ba247cSmichen strcmp(lkp->service_name, NSCD_NSW_SRC_NAME(k)) != 0; 364d2ba247cSmichen k++) { 365d2ba247cSmichen /* empty */ 366d2ba247cSmichen } 367cb5caa98Sdjl 368d2ba247cSmichen if (k < NSCD_NUM_SRC && nscd_src_backend_db_loaded[k] == 0) { 369cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 370d2ba247cSmichen (me, "unknown nsw source name %s\n", lkp->service_name); 371cb5caa98Sdjl usrc = strdup(lkp->service_name); 372cb5caa98Sdjl if (usrc == NULL) { 373cb5caa98Sdjl rc = NSCD_NO_MEMORY; 374d2ba247cSmichen _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 375cb5caa98Sdjl (me, "unable to strdup() source name\n"); 376cb5caa98Sdjl goto error_exit; 377cb5caa98Sdjl } 378cb5caa98Sdjl NSCD_NSW_SRC_NAME(k) = usrc; 379cb5caa98Sdjl 380cb5caa98Sdjl rc = _nscd_populate_nsw_backend_info_db(k); 381cb5caa98Sdjl if (rc != NSCD_SUCCESS) { 382cb5caa98Sdjl free(usrc); 383cb5caa98Sdjl NSCD_NSW_SRC_NAME(k) = NULL; 384cb5caa98Sdjl goto error_exit; 385cb5caa98Sdjl } 386cb5caa98Sdjl } else if (NSCD_NSW_SRC_NAME(k) == NULL) { 387cb5caa98Sdjl /* 388cb5caa98Sdjl * number of user-defined source exceeded 389cb5caa98Sdjl */ 390cb5caa98Sdjl rc = NSCD_CFG_SYNTAX_ERROR; 391cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 392cb5caa98Sdjl (me, "error: number of user_defined source exceeded\n"); 393cb5caa98Sdjl 394cb5caa98Sdjl goto error_exit; 395cb5caa98Sdjl } 396cb5caa98Sdjl 397cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 398cb5caa98Sdjl (me, "setting source index array [%d] = %d (%s)\n", 399cb5caa98Sdjl j, k, lkp->service_name); 400cb5caa98Sdjl 401cb5caa98Sdjl src_idx_a[j] = k; 402cb5caa98Sdjl 403cb5caa98Sdjl lkp = lkp->next; 404cb5caa98Sdjl if (lkp == NULL) break; 405cb5caa98Sdjl 406cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 407cb5caa98Sdjl (me, "number of nsw sources = %d\n", nsw_cfg->max_src); 408cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 409cb5caa98Sdjl (me, "next nsw source is %s\n", lkp->service_name); 410cb5caa98Sdjl } 411cb5caa98Sdjl 412cb5caa98Sdjl /* set it up to reference count the switch policy config */ 413d2ba247cSmichen nsw_cfg_p = (nscd_nsw_config_t **)_nscd_alloc(NSCD_DATA_NSW_CONFIG, 414d2ba247cSmichen sizeof (nscd_nsw_config_t **), free_nscd_nsw_config, 415cb5caa98Sdjl NSCD_ALLOC_RWLOCK); 416cb5caa98Sdjl 417cb5caa98Sdjl if (nsw_cfg_p == NULL) { 418cb5caa98Sdjl rc = NSCD_NO_MEMORY; 419cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 420cb5caa98Sdjl (me, "unable to allocate a new nsw config DB\n"); 421cb5caa98Sdjl goto error_exit; 422cb5caa98Sdjl } 423cb5caa98Sdjl *nsw_cfg_p = nsw_cfg; 424cb5caa98Sdjl 425cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 426cb5caa98Sdjl (me, "new nsw config DB %p allocated\n", nsw_cfg_p); 427cb5caa98Sdjl 428cb5caa98Sdjl /* save all the data in the new nscd_nsw_config_t */ 429cb5caa98Sdjl nsw_cfg->db_name = strdup(dbn); 430cb5caa98Sdjl nsw_cfg->nsw_cfg_str = strdup(cfgstr); 431cb5caa98Sdjl if (nsw_cfg->db_name == NULL || nsw_cfg->nsw_cfg_str == NULL) { 432cb5caa98Sdjl rc = NSCD_NO_MEMORY; 433cb5caa98Sdjl goto error_exit; 434cb5caa98Sdjl } 435cb5caa98Sdjl 436cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 437cb5caa98Sdjl (me, "switch policy \"%s\" for database is \"%s\"\n", 438cb5caa98Sdjl nsw_cfg->db_name, nsw_cfg->nsw_cfg_str); 439cb5caa98Sdjl 440cb5caa98Sdjl nsw_cfg->nsw_config = swcfg; 441cb5caa98Sdjl nsw_cfg->src_idx = src_idx_a; 442cb5caa98Sdjl 443cb5caa98Sdjl /* 444cb5caa98Sdjl * set default frontend params and if necessary call initf() 445cb5caa98Sdjl * to initialize or override 446cb5caa98Sdjl */ 447cb5caa98Sdjl nsw_cfg->fe_params.max_active_per_src = 10; 448cb5caa98Sdjl nsw_cfg->fe_params.max_dormant_per_src = 1; 4490dfdd7f3Smichen nsw_cfg->fe_params.finders = _nscd_nss_finders; 450cb5caa98Sdjl if (params != NULL) { 451cb5caa98Sdjl nsw_cfg->fe_params = params->p; 452cb5caa98Sdjl 453cb5caa98Sdjl if (params->p.flags & NSS_USE_DEFAULT_CONFIG) { 454cb5caa98Sdjl params->nswcfg = nsw_cfg_p; 455cb5caa98Sdjl /* 456cb5caa98Sdjl * this nsw_cfg is not meant to last long, no need 457cb5caa98Sdjl * to set up the nsw state and getent bases, just 458cb5caa98Sdjl * exit with NSCD_SUCCESS 459cb5caa98Sdjl */ 460cb5caa98Sdjl nsw_cfg->nobase = 1; 461cb5caa98Sdjl goto error_exit; 462cb5caa98Sdjl } 463cb5caa98Sdjl } else 464cb5caa98Sdjl (void) (nscd_nss_db_initf[dbi])(&nsw_cfg->fe_params); 465cb5caa98Sdjl 466cb5caa98Sdjl /* 467cb5caa98Sdjl * also create a new nsw state base 468cb5caa98Sdjl */ 469ad0e80f7Smichen if ((rc = _nscd_init_nsw_state_base(dbi, compat_basei, 1)) != 470ad0e80f7Smichen NSCD_SUCCESS) { 471cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 472cb5caa98Sdjl (me, "unable to initialize a nsw state base(%d)\n", dbi); 473cb5caa98Sdjl goto error_exit; 474cb5caa98Sdjl } 475cb5caa98Sdjl 476cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 477cb5caa98Sdjl (me, "new nsw state base(%d) %p created\n", dbi, 478cb5caa98Sdjl nscd_nsw_state_base[dbi]); 479cb5caa98Sdjl 480cb5caa98Sdjl /* 481cb5caa98Sdjl * also create a new getent context base 482cb5caa98Sdjl */ 483cb5caa98Sdjl if ((rc = _nscd_init_getent_ctx_base(dbi, 1)) != NSCD_SUCCESS) { 484cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 485cb5caa98Sdjl (me, "unable to initialize a getent context base(%d)\n", dbi); 486cb5caa98Sdjl goto error_exit; 487cb5caa98Sdjl } 488cb5caa98Sdjl 489cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 490cb5caa98Sdjl (me, "new getent context base(%d) %p created\n", dbi, 491cb5caa98Sdjl nscd_getent_ctx_base[dbi]); 492cb5caa98Sdjl 493cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 494cb5caa98Sdjl (me, "new nsw config created (database = %s, " 495cb5caa98Sdjl "config = %s)\n", dbn, cfgstr); 496cb5caa98Sdjl 497*cfed26cbSMichen Chang /* 498*cfed26cbSMichen Chang * Activate the new nscd_nsw_config_t and make it the 499*cfed26cbSMichen Chang * current nsswitch config. The old one pointed to by 500*cfed26cbSMichen Chang * nscd_nsw_config[dbi] will either be destroyed 501*cfed26cbSMichen Chang * immediately or left on the side line (and be 502*cfed26cbSMichen Chang * destroyed eventually). __nscd_set() will set the 503*cfed26cbSMichen Chang * associated flags to make it happen. 504*cfed26cbSMichen Chang */ 505*cfed26cbSMichen Chang nscd_nsw_config[dbi] = (nscd_nsw_config_t **)_nscd_set( 506*cfed26cbSMichen Chang (nscd_acc_data_t *)nscd_nsw_config[dbi], 507*cfed26cbSMichen Chang (nscd_acc_data_t *)nsw_cfg_p); 508cb5caa98Sdjl 509cb5caa98Sdjl error_exit: 510cb5caa98Sdjl 511cb5caa98Sdjl if (rc != NSCD_SUCCESS) { 512cb5caa98Sdjl 513cb5caa98Sdjl if (swcfgv1 == NULL && swcfg != NULL) 514cb5caa98Sdjl (void) __nsw_freeconfig_v1(swcfg); 515cb5caa98Sdjl if (src_idx_a != NULL) 516cb5caa98Sdjl free(src_idx_a); 517cb5caa98Sdjl if (nsw_cfg_p) 518cb5caa98Sdjl free(nsw_cfg_p); 519cb5caa98Sdjl if (nsw_cfg != NULL) { 520cb5caa98Sdjl if (nsw_cfg->db_name != NULL) 521cb5caa98Sdjl free(nsw_cfg->db_name); 522cb5caa98Sdjl if (nsw_cfg->nsw_cfg_str != NULL) 523cb5caa98Sdjl free(nsw_cfg->nsw_cfg_str); 524cb5caa98Sdjl free(nsw_cfg); 525cb5caa98Sdjl } 526cb5caa98Sdjl 527cb5caa98Sdjl return (rc); 528cb5caa98Sdjl } else 529cb5caa98Sdjl return (NSCD_SUCCESS); 530cb5caa98Sdjl } 531cb5caa98Sdjl 532cb5caa98Sdjl static nscd_rc_t 533cb5caa98Sdjl create_nsw_config(int dbi) 534cb5caa98Sdjl { 535cb5caa98Sdjl 536cb5caa98Sdjl nscd_nsw_config_t *nsw_cfg = NULL; 537cb5caa98Sdjl nscd_nsw_config_t **nsw_cfg_p = NULL; 538cb5caa98Sdjl char *me = "create_nsw_config"; 539cb5caa98Sdjl 540cb5caa98Sdjl /* 541*cfed26cbSMichen Chang * Allocate a pointer space for saving a pointer to a 542*cfed26cbSMichen Chang * nscd_nsw_config_t. _nscd_alloc() will also create 543*cfed26cbSMichen Chang * a nscd_access_t header with a rwlock_t and mutex_t 544*cfed26cbSMichen Chang * for controlling later access to the data pointed 545*cfed26cbSMichen Chang * to by the pointer. 546cb5caa98Sdjl */ 547*cfed26cbSMichen Chang nsw_cfg_p = (nscd_nsw_config_t **)_nscd_alloc(NSCD_DATA_NSW_CONFIG, 548*cfed26cbSMichen Chang sizeof (nscd_nsw_config_t **), free_nscd_nsw_config, 549*cfed26cbSMichen Chang NSCD_ALLOC_RWLOCK | NSCD_ALLOC_MUTEX); 550*cfed26cbSMichen Chang 551*cfed26cbSMichen Chang if (nsw_cfg_p == NULL) { 552*cfed26cbSMichen Chang _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 553*cfed26cbSMichen Chang (me, "unable to allocate a space for a nsw config pointer\n"); 554*cfed26cbSMichen Chang return (NSCD_NO_MEMORY); 555*cfed26cbSMichen Chang } 556*cfed26cbSMichen Chang _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 557*cfed26cbSMichen Chang (me, "addr for saving nsw config pointer = %p\n", nsw_cfg_p); 558*cfed26cbSMichen Chang 559*cfed26cbSMichen Chang /* 560*cfed26cbSMichen Chang * If pseudo-databases (initf function not defined), 561*cfed26cbSMichen Chang * no need to create a nscd_nsw_config_t yet, 562*cfed26cbSMichen Chang * so put a NULL pointer in the pointer space. 563*cfed26cbSMichen Chang */ 564*cfed26cbSMichen Chang if (nscd_nss_db_initf[dbi] == NULL) { 565*cfed26cbSMichen Chang *nsw_cfg_p = NULL; 566*cfed26cbSMichen Chang nscd_nsw_config[dbi] = (nscd_nsw_config_t **)_nscd_set( 567*cfed26cbSMichen Chang (nscd_acc_data_t *)nscd_nsw_config[dbi], 568*cfed26cbSMichen Chang (nscd_acc_data_t *)nsw_cfg_p); 569*cfed26cbSMichen Chang 570*cfed26cbSMichen Chang _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 571*cfed26cbSMichen Chang (me, "pointer to nsw config has been set to NULL\n"); 572*cfed26cbSMichen Chang 573cb5caa98Sdjl return (NSCD_SUCCESS); 574*cfed26cbSMichen Chang } 575cb5caa98Sdjl 576cb5caa98Sdjl /* allocate the space for a nscd_nsw_config_t */ 577cb5caa98Sdjl nsw_cfg = calloc(1, sizeof (nscd_nsw_config_t)); 578cb5caa98Sdjl if (nsw_cfg == NULL) { 579cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 580cb5caa98Sdjl (me, "unable to allocate a nsw config structure\n"); 581cb5caa98Sdjl return (NSCD_NO_MEMORY); 582cb5caa98Sdjl } 583cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 584cb5caa98Sdjl (me, "nsw config structure %pallocated\n", nsw_cfg); 585cb5caa98Sdjl 586cb5caa98Sdjl nsw_cfg->db_name = strdup(NSCD_NSW_DB_NAME(dbi)); 587cb5caa98Sdjl if (nsw_cfg->db_name == NULL) { 588cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 589cb5caa98Sdjl (me, "unable to strdup the db name\n"); 590cb5caa98Sdjl return (NSCD_NO_MEMORY); 591cb5caa98Sdjl } 592cb5caa98Sdjl 593cb5caa98Sdjl /* 594cb5caa98Sdjl * set default frontend params and then call initf() 595cb5caa98Sdjl * to initialize or override 596cb5caa98Sdjl */ 597cb5caa98Sdjl nsw_cfg->fe_params.max_active_per_src = 10; 598cb5caa98Sdjl nsw_cfg->fe_params.max_dormant_per_src = 1; 5990dfdd7f3Smichen nsw_cfg->fe_params.finders = _nscd_nss_finders; 600cb5caa98Sdjl (void) (nscd_nss_db_initf[dbi])(&nsw_cfg->fe_params); 601cb5caa98Sdjl 602cb5caa98Sdjl /* 603cb5caa98Sdjl * activate the new nscd_nsw_config_t 604cb5caa98Sdjl */ 605cb5caa98Sdjl *nsw_cfg_p = nsw_cfg; 606cb5caa98Sdjl nscd_nsw_config[dbi] = (nscd_nsw_config_t **)_nscd_set( 607cb5caa98Sdjl (nscd_acc_data_t *)nscd_nsw_config[dbi], 608cb5caa98Sdjl (nscd_acc_data_t *)nsw_cfg_p); 609cb5caa98Sdjl 610cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 611cb5caa98Sdjl (me, "nsw config %p activated\n", nsw_cfg); 612cb5caa98Sdjl 613cb5caa98Sdjl return (NSCD_SUCCESS); 614cb5caa98Sdjl } 615cb5caa98Sdjl 616cb5caa98Sdjl nscd_rc_t 617cb5caa98Sdjl _nscd_init_all_nsw_config(void) 618cb5caa98Sdjl { 619cb5caa98Sdjl nscd_rc_t rc; 620cb5caa98Sdjl int i; 621cb5caa98Sdjl char *me = "_nscd_init_all_nsw_config"; 622cb5caa98Sdjl 623cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 624cb5caa98Sdjl (me, "initializing all nsw config\n"); 625cb5caa98Sdjl 626cb5caa98Sdjl for (i = 0; i < NSCD_NUM_DB; i++) { 627cb5caa98Sdjl if ((rc = create_nsw_config(i)) != NSCD_SUCCESS) 628cb5caa98Sdjl return (rc); 629cb5caa98Sdjl } 630cb5caa98Sdjl 631cb5caa98Sdjl return (NSCD_SUCCESS); 632cb5caa98Sdjl } 633cb5caa98Sdjl 634cb5caa98Sdjl static nscd_rc_t 635cb5caa98Sdjl init_nsw_be_info_db(int srci) 636cb5caa98Sdjl { 637cb5caa98Sdjl nscd_db_t *ret, **db_p; 638cb5caa98Sdjl char *me = "init_nsw_be_info_db"; 639cb5caa98Sdjl 640cb5caa98Sdjl ret = _nscd_alloc_db(NSCD_DB_SIZE_SMALL); 641cb5caa98Sdjl 642cb5caa98Sdjl if (ret == NULL) { 643cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 644cb5caa98Sdjl (me, "unable to allocate a nsw be info database\n"); 645cb5caa98Sdjl return (NSCD_NO_MEMORY); 646cb5caa98Sdjl } 647cb5caa98Sdjl 648cb5caa98Sdjl /* set up to reference count the backend info db */ 649d2ba247cSmichen db_p = (nscd_db_t **)_nscd_alloc(NSCD_DATA_BACKEND_INFO_DB, 650d2ba247cSmichen sizeof (nscd_db_t **), free_nsw_backend_info_db, 651cb5caa98Sdjl NSCD_ALLOC_RWLOCK); 652cb5caa98Sdjl 653cb5caa98Sdjl if (db_p == NULL) { 654cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 655cb5caa98Sdjl (me, "unable to allocate the pointer to the nsw " 656cb5caa98Sdjl "be info database\n"); 657cb5caa98Sdjl return (NSCD_NO_MEMORY); 658cb5caa98Sdjl } 659cb5caa98Sdjl 660cb5caa98Sdjl *db_p = ret; 661cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 662cb5caa98Sdjl (me, "backend database (db_p = %p, db = %p)\n", db_p, *db_p); 663cb5caa98Sdjl 664cb5caa98Sdjl nscd_src_backend_db[srci] = (nscd_db_t **)_nscd_set( 665cb5caa98Sdjl (nscd_acc_data_t *)nscd_src_backend_db[srci], 666cb5caa98Sdjl (nscd_acc_data_t *)db_p); 667cb5caa98Sdjl 668cb5caa98Sdjl return (NSCD_SUCCESS); 669cb5caa98Sdjl } 670cb5caa98Sdjl 671cb5caa98Sdjl nscd_rc_t 672cb5caa98Sdjl _nscd_init_all_nsw_be_info_db(void) 673cb5caa98Sdjl { 674cb5caa98Sdjl 675cb5caa98Sdjl int i; 676cb5caa98Sdjl nscd_rc_t rc; 677cb5caa98Sdjl char *me = "_nscd_init_all_nsw_be_info_db"; 678cb5caa98Sdjl 679cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 680cb5caa98Sdjl (me, "initializing all nsw be info databases\n"); 681cb5caa98Sdjl 682cb5caa98Sdjl for (i = 0; i < NSCD_NUM_SRC; i++) { 683cb5caa98Sdjl if ((rc = init_nsw_be_info_db(i)) != NSCD_SUCCESS) 684cb5caa98Sdjl return (rc); 685cb5caa98Sdjl } 686cb5caa98Sdjl 687cb5caa98Sdjl return (NSCD_SUCCESS); 688cb5caa98Sdjl } 689cb5caa98Sdjl 690cb5caa98Sdjl 691cb5caa98Sdjl nscd_rc_t 692cb5caa98Sdjl _nscd_alloc_nsw_config() 693cb5caa98Sdjl { 694cb5caa98Sdjl nscd_nsw_config = calloc(NSCD_NUM_DB, sizeof (nscd_nsw_config_t **)); 695cb5caa98Sdjl if (nscd_nsw_config == NULL) 696cb5caa98Sdjl return (NSCD_NO_MEMORY); 697cb5caa98Sdjl 698cb5caa98Sdjl return (NSCD_SUCCESS); 699cb5caa98Sdjl } 700cb5caa98Sdjl 701cb5caa98Sdjl nscd_rc_t 702cb5caa98Sdjl _nscd_alloc_nsw_be_info_db() 703cb5caa98Sdjl { 704cb5caa98Sdjl int i; 705cb5caa98Sdjl 706d2ba247cSmichen _nscd_cfg_num_nsw_src_all = _nscd_cfg_num_nsw_src + 707d2ba247cSmichen NSCD_NUM_SRC_FOREIGN; 708cb5caa98Sdjl nscd_src_backend_db = calloc(NSCD_NUM_SRC, sizeof (nscd_db_t **)); 709cb5caa98Sdjl if (nscd_src_backend_db == NULL) 710cb5caa98Sdjl return (NSCD_NO_MEMORY); 7110dfdd7f3Smichen nscd_src_backend_db_loaded = calloc(NSCD_NUM_SRC, sizeof (int)); 7120dfdd7f3Smichen if (nscd_src_backend_db_loaded == NULL) { 7130dfdd7f3Smichen free(nscd_src_backend_db); 7140dfdd7f3Smichen return (NSCD_NO_MEMORY); 7150dfdd7f3Smichen } 716cb5caa98Sdjl 717cb5caa98Sdjl /* also allocate/init the nsswitch source index/name array */ 718cb5caa98Sdjl _nscd_cfg_nsw_src_all = (nscd_cfg_id_t *)calloc( 719cb5caa98Sdjl _nscd_cfg_num_nsw_src_all + 1, sizeof (nscd_cfg_id_t)); 720cb5caa98Sdjl for (i = 0; i < _nscd_cfg_num_nsw_src_all + 1; i++) 721cb5caa98Sdjl (_nscd_cfg_nsw_src_all + i)->index = -1; 722cb5caa98Sdjl 723cb5caa98Sdjl (void) memcpy(_nscd_cfg_nsw_src_all, _nscd_cfg_nsw_src, 724cb5caa98Sdjl _nscd_cfg_num_nsw_src * sizeof (nscd_cfg_id_t)); 725cb5caa98Sdjl return (NSCD_SUCCESS); 726cb5caa98Sdjl } 727cb5caa98Sdjl 728cb5caa98Sdjl nscd_rc_t 729cb5caa98Sdjl _nscd_populate_nsw_backend_info() 730cb5caa98Sdjl { 731cb5caa98Sdjl int i; 732cb5caa98Sdjl nscd_rc_t rc; 733cb5caa98Sdjl 734cb5caa98Sdjl for (i = 0; i < NSCD_NUM_SRC; i++) { 735cb5caa98Sdjl if (NSCD_NSW_SRC_NAME(i) == NULL) 736cb5caa98Sdjl continue; 737cb5caa98Sdjl rc = _nscd_populate_nsw_backend_info_db(i); 738cb5caa98Sdjl if (rc != NSCD_SUCCESS) 739cb5caa98Sdjl return (rc); 740cb5caa98Sdjl } 741cb5caa98Sdjl 742cb5caa98Sdjl return (NSCD_SUCCESS); 743cb5caa98Sdjl } 7440dfdd7f3Smichen 7450dfdd7f3Smichen /* 7460dfdd7f3Smichen * The following defines nscd's own lookup and delete functions 7470dfdd7f3Smichen * that are to be stored in nss_backend_finder_t which is used 7480dfdd7f3Smichen * by _nscd_populate_nsw_backend_info_db() to initialize the 7490dfdd7f3Smichen * various nss backend instances 7500dfdd7f3Smichen */ 7510dfdd7f3Smichen 7520dfdd7f3Smichen static const int dlopen_version = 1; 7530dfdd7f3Smichen #ifndef NSS_DLOPEN_FORMAT 7540dfdd7f3Smichen #define NSS_DLOPEN_FORMAT "nss_%s.so.%d" 7550dfdd7f3Smichen #endif 7560dfdd7f3Smichen #ifndef NSS_DLSYM_FORMAT 7570dfdd7f3Smichen #define NSS_DLSYM_FORMAT "_nss_%s_%s_constr" 758d2ba247cSmichen #define NSS_DLSYM_FORMAT_V "_nss_%s_version" 7590dfdd7f3Smichen #endif 7600dfdd7f3Smichen static const char dlopen_format[] = NSS_DLOPEN_FORMAT; 7610dfdd7f3Smichen static const char dlsym_format [] = NSS_DLSYM_FORMAT; 762d2ba247cSmichen static const char dlsym_format_v [] = NSS_DLSYM_FORMAT_V; 763d2ba247cSmichen static const size_t format_maxlen = sizeof (dlsym_format); 7640dfdd7f3Smichen 7650dfdd7f3Smichen /*ARGSUSED*/ 7660dfdd7f3Smichen static nss_backend_constr_t 7670dfdd7f3Smichen _nscd_per_src_lookup(void *handle, const char *db_name, const char *src_name, 7680dfdd7f3Smichen void **delete_privp) 7690dfdd7f3Smichen { 7700dfdd7f3Smichen char *name; 7710dfdd7f3Smichen void *dlhandle; 7720dfdd7f3Smichen void *sym; 7730dfdd7f3Smichen size_t len; 7740dfdd7f3Smichen nss_backend_constr_t res = NULL; 7750dfdd7f3Smichen 776d2ba247cSmichen len = format_maxlen + strlen(src_name); 777d2ba247cSmichen if (db_name != NULL) 778d2ba247cSmichen len += strlen(db_name); 7790dfdd7f3Smichen name = alloca(len); 7800dfdd7f3Smichen dlhandle = handle; 7810dfdd7f3Smichen if ((dlhandle = handle) == NULL) { 7820dfdd7f3Smichen (void) sprintf(name, dlopen_format, src_name, dlopen_version); 7830dfdd7f3Smichen dlhandle = dlopen(name, RTLD_LAZY); 7840dfdd7f3Smichen } 7850dfdd7f3Smichen 7860dfdd7f3Smichen if (dlhandle != NULL) { 787d2ba247cSmichen if (db_name != NULL) 7880dfdd7f3Smichen (void) sprintf(name, dlsym_format, src_name, db_name); 789d2ba247cSmichen else 790d2ba247cSmichen (void) sprintf(name, dlsym_format_v, src_name); 7910dfdd7f3Smichen if ((sym = dlsym(dlhandle, name)) == 0) { 7920dfdd7f3Smichen if (handle == NULL) 7930dfdd7f3Smichen (void) dlclose(dlhandle); 7940dfdd7f3Smichen } else { 7950dfdd7f3Smichen *delete_privp = dlhandle; 7960dfdd7f3Smichen res = (nss_backend_constr_t)sym; 7970dfdd7f3Smichen } 7980dfdd7f3Smichen } 7990dfdd7f3Smichen return (res); 8000dfdd7f3Smichen } 8010dfdd7f3Smichen 8020dfdd7f3Smichen /*ARGSUSED*/ 8030dfdd7f3Smichen static void 8040dfdd7f3Smichen _nscd_per_src_delete(void *delete_priv, nss_backend_constr_t dummy) 8050dfdd7f3Smichen { 8060dfdd7f3Smichen (void) dlclose(delete_priv); 8070dfdd7f3Smichen } 808