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 /* 228ea0afb9SMichen Chang * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23cb5caa98Sdjl * Use is subject to license terms. 24*33f5ff17SMilan Jurik * Copyright 2012 Milan Jurik. All rights reserved. 25cb5caa98Sdjl */ 26cb5caa98Sdjl 27cb5caa98Sdjl #include <stdio.h> 28cb5caa98Sdjl #include <stdlib.h> 29cb5caa98Sdjl #include <locale.h> /* gettext */ 30cb5caa98Sdjl #include <dlfcn.h> 31cb5caa98Sdjl #include <string.h> 32cb5caa98Sdjl #include <sys/varargs.h> 33cb5caa98Sdjl #include <errno.h> 34cb5caa98Sdjl #include "nscd_db.h" 35cb5caa98Sdjl #include "nscd_config.h" 36cb5caa98Sdjl #include "nscd_cfgdef.h" 37cb5caa98Sdjl #include "nscd_log.h" 38cb5caa98Sdjl 39cb5caa98Sdjl typedef struct { 40cb5caa98Sdjl rwlock_t *global; 41cb5caa98Sdjl rwlock_t *alldb; 42cb5caa98Sdjl rwlock_t *nswdb; 43cb5caa98Sdjl } nscd_cfg_lock_t; 44cb5caa98Sdjl 45cb5caa98Sdjl static rwlock_t cfg_paramDB_rwlock = DEFAULTRWLOCK; 46cb5caa98Sdjl static nscd_db_t *cfg_paramDB = NULL; 47cb5caa98Sdjl 48cb5caa98Sdjl static nscd_cfg_global_data_t *nscd_cfg_global_current; 49cb5caa98Sdjl static nscd_cfg_nsw_db_data_t *nscd_cfg_nsw_db_data_current; 50cb5caa98Sdjl static nscd_cfg_nsw_db_data_t *nscd_cfg_nsw_alldb_current; 51cb5caa98Sdjl static rwlock_t *nscd_cfg_global_rwlock; 52cb5caa98Sdjl static rwlock_t *nscd_cfg_nsw_db_data_rwlock; 53cb5caa98Sdjl static rwlock_t *nscd_cfg_nsw_alldb_rwlock; 54cb5caa98Sdjl 55cb5caa98Sdjl extern int _nscd_cfg_num_nsw_src_all; 56cb5caa98Sdjl extern nscd_cfg_id_t *_nscd_cfg_nsw_src_all; 57cb5caa98Sdjl 58cb5caa98Sdjl nscd_cfg_error_t * 59cb5caa98Sdjl _nscd_cfg_make_error( 60cb5caa98Sdjl nscd_rc_t rc, 61cb5caa98Sdjl char *msg) 62cb5caa98Sdjl { 63cb5caa98Sdjl 64cb5caa98Sdjl nscd_cfg_error_t *ret; 65cb5caa98Sdjl int size, msglen; 66cb5caa98Sdjl 67cb5caa98Sdjl msglen = (msg != NULL ? strlen(msg) + 1 : 0); 68cb5caa98Sdjl 69cb5caa98Sdjl size = sizeof (nscd_cfg_error_t) + msglen; 70cb5caa98Sdjl 71cb5caa98Sdjl ret = calloc(1, size); 72cb5caa98Sdjl if (ret == NULL) 73cb5caa98Sdjl return (NULL); 74cb5caa98Sdjl 75cb5caa98Sdjl ret->rc = rc; 76cb5caa98Sdjl if (msg != NULL) { 77cb5caa98Sdjl ret->msg = (char *)ret + 78cb5caa98Sdjl sizeof (nscd_cfg_error_t); 79cb5caa98Sdjl (void) memcpy(ret->msg, msg, msglen); 80cb5caa98Sdjl } 81cb5caa98Sdjl 82cb5caa98Sdjl return (ret); 83cb5caa98Sdjl } 84cb5caa98Sdjl 85cb5caa98Sdjl static nscd_rc_t 86cb5caa98Sdjl _nscd_cfg_get_list( 87cb5caa98Sdjl nscd_cfg_list_t **list, 88cb5caa98Sdjl nscd_cfg_list_type_t type) 89cb5caa98Sdjl { 90cb5caa98Sdjl char *me = "_nscd_cfg_get_list"; 91cb5caa98Sdjl int i, num, size; 92cb5caa98Sdjl nscd_cfg_id_t *l; 93cb5caa98Sdjl nscd_cfg_list_t *ret; 94cb5caa98Sdjl nscd_cfg_param_desc_t *pl; 95cb5caa98Sdjl nscd_cfg_stat_desc_t *sl; 96cb5caa98Sdjl void *p; 97cb5caa98Sdjl 98cb5caa98Sdjl if (list == NULL) { 99cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 100cb5caa98Sdjl (me, "invalid argument: list = %p\n", list); 101cb5caa98Sdjl 102cb5caa98Sdjl return (NSCD_INVALID_ARGUMENT); 103cb5caa98Sdjl } 104cb5caa98Sdjl *list = NULL; 105cb5caa98Sdjl 106cb5caa98Sdjl switch (type) { 107cb5caa98Sdjl case NSCD_CFG_LIST_NSW_DB: 108cb5caa98Sdjl 109cb5caa98Sdjl num = _nscd_cfg_num_nsw_db; 110cb5caa98Sdjl l = &_nscd_cfg_nsw_db[0]; 111cb5caa98Sdjl break; 112cb5caa98Sdjl 113cb5caa98Sdjl case NSCD_CFG_LIST_NSW_SRC: 114cb5caa98Sdjl 115cb5caa98Sdjl num = _nscd_cfg_num_nsw_src_all; 116cb5caa98Sdjl l = _nscd_cfg_nsw_src_all; 117cb5caa98Sdjl break; 118cb5caa98Sdjl 119cb5caa98Sdjl case NSCD_CFG_LIST_PARAM: 120cb5caa98Sdjl 121cb5caa98Sdjl num = _nscd_cfg_num_param; 122cb5caa98Sdjl pl = &_nscd_cfg_param_desc[0]; 123cb5caa98Sdjl break; 124cb5caa98Sdjl 125cb5caa98Sdjl case NSCD_CFG_LIST_STAT: 126cb5caa98Sdjl 127cb5caa98Sdjl num = _nscd_cfg_num_stat; 128cb5caa98Sdjl sl = &_nscd_cfg_stat_desc[0]; 129cb5caa98Sdjl break; 130cb5caa98Sdjl 131cb5caa98Sdjl default: 132cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 133cb5caa98Sdjl (me, "invalid argument: type (%d)\n", type); 134cb5caa98Sdjl 135cb5caa98Sdjl return (NSCD_INVALID_ARGUMENT); 136cb5caa98Sdjl } 137cb5caa98Sdjl 138cb5caa98Sdjl size = sizeof (nscd_cfg_list_t) + sizeof (nscd_cfg_id_t *) * (num + 1); 139cb5caa98Sdjl 140cb5caa98Sdjl ret = calloc(1, size); 141cb5caa98Sdjl if (ret == NULL) 142cb5caa98Sdjl return (NSCD_NO_MEMORY); 143cb5caa98Sdjl 144cb5caa98Sdjl ret->num = num; 145cb5caa98Sdjl p = (char *)ret + sizeof (nscd_cfg_list_t); 146cb5caa98Sdjl ret->list = (nscd_cfg_id_t **)p; 147cb5caa98Sdjl 148cb5caa98Sdjl if (type == NSCD_CFG_LIST_PARAM) { 149cb5caa98Sdjl for (i = 0; i <= num; i++) 150cb5caa98Sdjl ret->list[i] = (nscd_cfg_id_t *)&pl[i]; 151cb5caa98Sdjl } else if (type == NSCD_CFG_LIST_STAT) { 152cb5caa98Sdjl for (i = 0; i <= num; i++) 153cb5caa98Sdjl ret->list[i] = (nscd_cfg_id_t *)&sl[i]; 154cb5caa98Sdjl } else { 155cb5caa98Sdjl for (i = 0; i <= num; i++) 156cb5caa98Sdjl ret->list[i] = &l[i]; 157cb5caa98Sdjl } 158cb5caa98Sdjl 159cb5caa98Sdjl *list = ret; 160cb5caa98Sdjl 161cb5caa98Sdjl return (NSCD_SUCCESS); 162cb5caa98Sdjl } 163cb5caa98Sdjl 164cb5caa98Sdjl nscd_rc_t 165cb5caa98Sdjl _nscd_cfg_get_param_desc_list( 166cb5caa98Sdjl nscd_cfg_param_desc_list_t **list) 167cb5caa98Sdjl { 168cb5caa98Sdjl return (_nscd_cfg_get_list((nscd_cfg_list_t **)list, 169cb5caa98Sdjl NSCD_CFG_LIST_PARAM)); 170cb5caa98Sdjl } 171cb5caa98Sdjl 172cb5caa98Sdjl /* 173cb5caa98Sdjl * FUNCTION: _nscd_cfg_create_paramDB 174cb5caa98Sdjl * 175cb5caa98Sdjl * Create the internal config parameter database 176cb5caa98Sdjl */ 177cb5caa98Sdjl static nscd_db_t * 178cb5caa98Sdjl _nscd_cfg_create_paramDB() 179cb5caa98Sdjl { 180cb5caa98Sdjl 181cb5caa98Sdjl nscd_db_t *ret; 182cb5caa98Sdjl 183cb5caa98Sdjl (void) rw_wrlock(&cfg_paramDB_rwlock); 184cb5caa98Sdjl 185cb5caa98Sdjl ret = _nscd_alloc_db(NSCD_DB_SIZE_MEDIUM); 186cb5caa98Sdjl 187cb5caa98Sdjl if (ret != NULL) 188cb5caa98Sdjl cfg_paramDB = ret; 189cb5caa98Sdjl 190cb5caa98Sdjl (void) rw_unlock(&cfg_paramDB_rwlock); 191cb5caa98Sdjl 192cb5caa98Sdjl return (ret); 193cb5caa98Sdjl } 194cb5caa98Sdjl 195cb5caa98Sdjl /* 196cb5caa98Sdjl * FUNCTION: _nscd_cfg_add_index_entry 197cb5caa98Sdjl * 198cb5caa98Sdjl * Add a config index entry (a name to index mapping) 199cb5caa98Sdjl * to the internal configuration database. 200cb5caa98Sdjl */ 201cb5caa98Sdjl static nscd_rc_t 202cb5caa98Sdjl _nscd_cfg_add_index_entry( 203cb5caa98Sdjl char *name, 204cb5caa98Sdjl int index, 205cb5caa98Sdjl nscd_cfg_list_type_t type) 206cb5caa98Sdjl { 207cb5caa98Sdjl int *idx; 208cb5caa98Sdjl int size; 209cb5caa98Sdjl int dbe_type; 210cb5caa98Sdjl nscd_db_entry_t *db_entry; 211cb5caa98Sdjl 212cb5caa98Sdjl if (name == NULL) 213cb5caa98Sdjl return (NSCD_INVALID_ARGUMENT); 214cb5caa98Sdjl 215cb5caa98Sdjl if (type == NSCD_CFG_LIST_NSW_DB) 216cb5caa98Sdjl dbe_type = NSCD_DATA_CFG_NSW_DB_INDEX; 217cb5caa98Sdjl else if (type == NSCD_CFG_LIST_NSW_SRC) 218cb5caa98Sdjl dbe_type = NSCD_DATA_CFG_NSW_SRC_INDEX; 219cb5caa98Sdjl else if (type == NSCD_CFG_LIST_PARAM) 220cb5caa98Sdjl dbe_type = NSCD_DATA_CFG_PARAM_INDEX; 221cb5caa98Sdjl else if (type == NSCD_CFG_LIST_STAT) 222cb5caa98Sdjl dbe_type = NSCD_DATA_CFG_STAT_INDEX; 223cb5caa98Sdjl 224cb5caa98Sdjl size = sizeof (int); 225cb5caa98Sdjl 226cb5caa98Sdjl db_entry = _nscd_alloc_db_entry(dbe_type, (const char *)name, 227cb5caa98Sdjl size, 1, 1); 228cb5caa98Sdjl if (db_entry == NULL) 229cb5caa98Sdjl return (NSCD_NO_MEMORY); 230cb5caa98Sdjl 231cb5caa98Sdjl idx = (int *)*(db_entry->data_array); 232cb5caa98Sdjl *idx = index; 233cb5caa98Sdjl 234cb5caa98Sdjl (void) rw_wrlock(&cfg_paramDB_rwlock); 235cb5caa98Sdjl (void) _nscd_add_db_entry(cfg_paramDB, name, db_entry, 236cb5caa98Sdjl NSCD_ADD_DB_ENTRY_FIRST); 237cb5caa98Sdjl (void) rw_unlock(&cfg_paramDB_rwlock); 238cb5caa98Sdjl 239cb5caa98Sdjl return (NSCD_SUCCESS); 240cb5caa98Sdjl } 241cb5caa98Sdjl 242cb5caa98Sdjl /* 243cb5caa98Sdjl * FUNCTION: _nscd_cfg_get_index 244cb5caa98Sdjl * 245cb5caa98Sdjl * Get the index of a config data item by searching the internal config 246cb5caa98Sdjl * database. Do not free the returned data. 247cb5caa98Sdjl */ 248cb5caa98Sdjl static int 249cb5caa98Sdjl _nscd_cfg_get_index( 250cb5caa98Sdjl char *name, 251cb5caa98Sdjl nscd_cfg_list_type_t type) 252cb5caa98Sdjl { 253cb5caa98Sdjl int index = -1, dbe_type; 254cb5caa98Sdjl const nscd_db_entry_t *db_entry; 255cb5caa98Sdjl 256cb5caa98Sdjl if (name == NULL) 257cb5caa98Sdjl return (-1); 258cb5caa98Sdjl 259cb5caa98Sdjl if (type == NSCD_CFG_LIST_NSW_DB) 260cb5caa98Sdjl dbe_type = NSCD_DATA_CFG_NSW_DB_INDEX; 261cb5caa98Sdjl else if (type == NSCD_CFG_LIST_NSW_SRC) 262cb5caa98Sdjl dbe_type = NSCD_DATA_CFG_NSW_SRC_INDEX; 263cb5caa98Sdjl else if (type == NSCD_CFG_LIST_PARAM) 264cb5caa98Sdjl dbe_type = NSCD_DATA_CFG_PARAM_INDEX; 265cb5caa98Sdjl else if (type == NSCD_CFG_LIST_STAT) 266cb5caa98Sdjl dbe_type = NSCD_DATA_CFG_STAT_INDEX; 267cb5caa98Sdjl else 268cb5caa98Sdjl return (-1); 269cb5caa98Sdjl 270cb5caa98Sdjl db_entry = _nscd_get_db_entry(cfg_paramDB, dbe_type, 271cb5caa98Sdjl (const char *)name, NSCD_GET_FIRST_DB_ENTRY, 0); 272cb5caa98Sdjl 273cb5caa98Sdjl if (db_entry != NULL) 274cb5caa98Sdjl index = *(int *)*(db_entry->data_array); 275cb5caa98Sdjl 276cb5caa98Sdjl return (index); 277cb5caa98Sdjl } 278cb5caa98Sdjl 279cb5caa98Sdjl static nscd_rc_t 280cb5caa98Sdjl _nscd_cfg_verify_group_info( 281cb5caa98Sdjl nscd_cfg_group_info_t *g_info, 282cb5caa98Sdjl nscd_cfg_param_desc_t *gdesc) 283cb5caa98Sdjl { 284cb5caa98Sdjl 285cb5caa98Sdjl char *me = "_nscd_cfg_verify_group_info"; 286cb5caa98Sdjl void *vp; 287cb5caa98Sdjl nscd_cfg_group_info_t *gi; 288cb5caa98Sdjl 289cb5caa98Sdjl if (_nscd_cfg_flag_is_set(gdesc->pflag, NSCD_CFG_PFLAG_GLOBAL)) { 290cb5caa98Sdjl vp = (char *)&nscd_cfg_global_default + 291cb5caa98Sdjl gdesc->g_offset; 292cb5caa98Sdjl gi = (nscd_cfg_group_info_t *)vp; 293cb5caa98Sdjl } else { 294cb5caa98Sdjl vp = (char *)&nscd_cfg_nsw_db_data_default + 295cb5caa98Sdjl gdesc->g_offset; 296cb5caa98Sdjl gi = (nscd_cfg_group_info_t *)vp; 297cb5caa98Sdjl 298cb5caa98Sdjl } 299cb5caa98Sdjl 300cb5caa98Sdjl if (g_info->num_param == gi->num_param && 301cb5caa98Sdjl _nscd_cfg_bitmap_is_equal(g_info->bitmap, gi->bitmap)) 302cb5caa98Sdjl return (NSCD_SUCCESS); 303cb5caa98Sdjl 304cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 305cb5caa98Sdjl (me, "ERROR: group (%s) info mismatched: group info " 306cb5caa98Sdjl "(%d, %#6.4x) not equal to that of default configuration data " 307cb5caa98Sdjl "(%d, %#6.4x)\n", gdesc->id.name, g_info->num_param, 308cb5caa98Sdjl _nscd_cfg_bitmap_value(g_info->bitmap), gi->num_param, 309cb5caa98Sdjl _nscd_cfg_bitmap_value(gi->bitmap)); 310cb5caa98Sdjl 311cb5caa98Sdjl return (NSCD_CFG_PARAM_DESC_ERROR); 312cb5caa98Sdjl 313cb5caa98Sdjl } 314cb5caa98Sdjl 315cb5caa98Sdjl 316cb5caa98Sdjl static nscd_rc_t 317cb5caa98Sdjl _nscd_cfg_init_nsw() 318cb5caa98Sdjl { 319cb5caa98Sdjl char *me = "_nscd_cfg_init_nsw"; 320cb5caa98Sdjl int i, j, idx, rc, num; 321cb5caa98Sdjl nscd_cfg_id_t *id; 322cb5caa98Sdjl nscd_cfg_list_type_t type[2] = { NSCD_CFG_LIST_NSW_DB, 323cb5caa98Sdjl NSCD_CFG_LIST_NSW_SRC }; 324cb5caa98Sdjl 325cb5caa98Sdjl nscd_cfg_id_t *list[2] = { _nscd_cfg_nsw_db, NULL}; 326cb5caa98Sdjl 327cb5caa98Sdjl list[1] = _nscd_cfg_nsw_src_all; 328cb5caa98Sdjl 329cb5caa98Sdjl for (j = 0; j < 2; j++) { 330cb5caa98Sdjl 331cb5caa98Sdjl if (j == 0) 332cb5caa98Sdjl num = _nscd_cfg_num_nsw_db + 1; 333cb5caa98Sdjl else 334cb5caa98Sdjl num = _nscd_cfg_num_nsw_src_all; 335cb5caa98Sdjl 336cb5caa98Sdjl for (i = 0; i < num; i++) { 337cb5caa98Sdjl 338cb5caa98Sdjl /* 339cb5caa98Sdjl * _nscd_cfg_nsw_alldb is the id for the 340cb5caa98Sdjl * special ALLDB (defaults for all db) 341cb5caa98Sdjl */ 342cb5caa98Sdjl if (j == 0 && i == _nscd_cfg_num_nsw_db) { 343cb5caa98Sdjl id = &_nscd_cfg_nsw_alldb; 344cb5caa98Sdjl idx = NSCD_CFG_NSW_ALLDB_INDEX; 345cb5caa98Sdjl } else { 346cb5caa98Sdjl id = &(list[j])[i]; 347cb5caa98Sdjl id->index = idx = i; 348cb5caa98Sdjl } 349cb5caa98Sdjl 350cb5caa98Sdjl if (id->name == NULL) 351cb5caa98Sdjl continue; 352cb5caa98Sdjl 353cb5caa98Sdjl if ((rc = _nscd_cfg_add_index_entry(id->name, 354cb5caa98Sdjl idx, type[j])) != NSCD_SUCCESS) { 355cb5caa98Sdjl 356cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, 357cb5caa98Sdjl NSCD_LOG_LEVEL_ERROR) 358cb5caa98Sdjl (me, "unable to add index entry for " 359cb5caa98Sdjl "nsswitch entry %s\n", id->name); 360cb5caa98Sdjl 361cb5caa98Sdjl _nscd_free_db(cfg_paramDB); 362cb5caa98Sdjl return (rc); 363cb5caa98Sdjl } 364cb5caa98Sdjl } 365cb5caa98Sdjl } 366cb5caa98Sdjl 367cb5caa98Sdjl return (NSCD_SUCCESS); 368cb5caa98Sdjl } 369cb5caa98Sdjl 370cb5caa98Sdjl static nscd_rc_t 371cb5caa98Sdjl _nscd_cfg_init_param() 372cb5caa98Sdjl { 373cb5caa98Sdjl char *me = "_nscd_cfg_init_param"; 374cb5caa98Sdjl int i, gi, fn = 0; 375cb5caa98Sdjl nscd_cfg_id_t *id; 376cb5caa98Sdjl nscd_cfg_param_desc_t *desc, *gdesc = NULL; 377cb5caa98Sdjl nscd_cfg_group_info_t g_info; 378cb5caa98Sdjl nscd_cfg_list_type_t type = NSCD_CFG_LIST_PARAM; 379cb5caa98Sdjl nscd_rc_t rc; 380cb5caa98Sdjl void *nfunc, *vfunc; 381cb5caa98Sdjl 382cb5caa98Sdjl if (_nscd_cfg_create_paramDB() == NULL) 383cb5caa98Sdjl return (NSCD_NO_MEMORY); 384cb5caa98Sdjl 385cb5caa98Sdjl desc = &_nscd_cfg_param_desc[0]; 386cb5caa98Sdjl 387cb5caa98Sdjl /* 388cb5caa98Sdjl * need to loop to the last (+1) param description 389cb5caa98Sdjl * which is a fake group and which marks the end 390cb5caa98Sdjl * of list. It is used to signal the end of the 391cb5caa98Sdjl * previous group so that the proper data will be 392cb5caa98Sdjl * set for that group 393cb5caa98Sdjl */ 394cb5caa98Sdjl for (i = 0; i < _nscd_cfg_num_param + 1; i++, desc++) { 395cb5caa98Sdjl 396cb5caa98Sdjl id = (nscd_cfg_id_t *)desc; 397cb5caa98Sdjl 398cb5caa98Sdjl if (_nscd_cfg_flag_is_set(desc->pflag, 399cb5caa98Sdjl NSCD_CFG_PFLAG_GROUP)) { 400cb5caa98Sdjl 401cb5caa98Sdjl if (gdesc != NULL) { 402cb5caa98Sdjl g_info.num_param = fn; 403cb5caa98Sdjl gdesc->p_fn = fn; 404cb5caa98Sdjl 405cb5caa98Sdjl if ((rc = _nscd_cfg_verify_group_info( 406cb5caa98Sdjl &g_info, gdesc)) != NSCD_SUCCESS) 407cb5caa98Sdjl return (rc); 408cb5caa98Sdjl } 409cb5caa98Sdjl 410cb5caa98Sdjl gi = i; 411cb5caa98Sdjl fn = 0; 412cb5caa98Sdjl gdesc = desc; 413cb5caa98Sdjl g_info.bitmap = NSCD_CFG_BITMAP_ZERO; 414cb5caa98Sdjl 415cb5caa98Sdjl /* 416cb5caa98Sdjl * set the notify/verify functions 417cb5caa98Sdjl */ 418cb5caa98Sdjl nfunc = (void *)gdesc->notify; 419cb5caa98Sdjl vfunc = (void *)gdesc->verify; 420cb5caa98Sdjl } else { 421cb5caa98Sdjl if (i == 0) { 422cb5caa98Sdjl 423cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, 424cb5caa98Sdjl NSCD_LOG_LEVEL_ERROR) 425cb5caa98Sdjl (me, "ERROR: first parameter " 426cb5caa98Sdjl "description is not for a group\n"); 427cb5caa98Sdjl 428cb5caa98Sdjl return (NSCD_CFG_PARAM_DESC_ERROR); 429cb5caa98Sdjl } 430cb5caa98Sdjl 431cb5caa98Sdjl /* 432cb5caa98Sdjl * set bitmap: the rightmost bit represents 433cb5caa98Sdjl * the first member (index = 0) in the group, 434cb5caa98Sdjl * the next bit is for the second member 435cb5caa98Sdjl * (index = 1), and so on 436cb5caa98Sdjl */ 437cb5caa98Sdjl _nscd_cfg_bitmap_set_nth(g_info.bitmap, fn); 438cb5caa98Sdjl 439cb5caa98Sdjl desc->p_fn = fn++; 440cb5caa98Sdjl 441cb5caa98Sdjl /* 442cb5caa98Sdjl * set the notify/verify functions 443cb5caa98Sdjl */ 4440dfdd7f3Smichen if (desc->notify == NSCD_CFG_FUNC_NOTIFY_AS_GROUP) { 4450dfdd7f3Smichen (void) memcpy(&desc->notify, &nfunc, 4460dfdd7f3Smichen sizeof (void *)); 447cb5caa98Sdjl } 4480dfdd7f3Smichen if (desc->verify == NSCD_CFG_FUNC_VERIFY_AS_GROUP) { 4490dfdd7f3Smichen (void) memcpy(&desc->verify, &vfunc, 4500dfdd7f3Smichen sizeof (void *)); 451cb5caa98Sdjl } 452cb5caa98Sdjl } 453cb5caa98Sdjl 454cb5caa98Sdjl /* if end of list reached, we are done */ 455cb5caa98Sdjl if (i == _nscd_cfg_num_param) 456cb5caa98Sdjl break; 457cb5caa98Sdjl 458cb5caa98Sdjl desc->g_index = gi; 459cb5caa98Sdjl 460cb5caa98Sdjl id->index = i; 461cb5caa98Sdjl 462cb5caa98Sdjl if ((rc = _nscd_cfg_add_index_entry(id->name, 463cb5caa98Sdjl i, type)) != NSCD_SUCCESS) { 464cb5caa98Sdjl 465cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 466cb5caa98Sdjl (me, "unable to add index entry for parameter " 467cb5caa98Sdjl "%s\n", id->name); 468cb5caa98Sdjl 469cb5caa98Sdjl _nscd_free_db(cfg_paramDB); 470cb5caa98Sdjl return (rc); 471cb5caa98Sdjl } else { 472cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 473cb5caa98Sdjl (me, "index entry for parameter " 474cb5caa98Sdjl "%s added\n", id->name); 475cb5caa98Sdjl } 476cb5caa98Sdjl } 477cb5caa98Sdjl 478cb5caa98Sdjl return (_nscd_cfg_init_nsw()); 479cb5caa98Sdjl } 480cb5caa98Sdjl 481cb5caa98Sdjl static nscd_rc_t 482cb5caa98Sdjl _nscd_cfg_init_stat() 483cb5caa98Sdjl { 484cb5caa98Sdjl char *me = "_nscd_cfg_init_stat"; 485cb5caa98Sdjl int i, gi, fn = 0; 486cb5caa98Sdjl nscd_cfg_id_t *id; 487cb5caa98Sdjl nscd_cfg_stat_desc_t *desc, *gdesc = NULL; 488cb5caa98Sdjl nscd_cfg_group_info_t g_info; 489cb5caa98Sdjl nscd_cfg_list_type_t type = NSCD_CFG_LIST_STAT; 490cb5caa98Sdjl nscd_rc_t rc; 491cb5caa98Sdjl void *gsfunc; 492cb5caa98Sdjl 493cb5caa98Sdjl desc = &_nscd_cfg_stat_desc[0]; 494cb5caa98Sdjl 495cb5caa98Sdjl /* 496cb5caa98Sdjl * need to loop to the last (+1) stat description 497cb5caa98Sdjl * which is a fake group and which marks the end 498cb5caa98Sdjl * of list. It is used to signal the end of the 499cb5caa98Sdjl * previous group so that the proper data will be 500cb5caa98Sdjl * set for that group 501cb5caa98Sdjl */ 502cb5caa98Sdjl for (i = 0; i < _nscd_cfg_num_stat + 1; i++, desc++) { 503cb5caa98Sdjl 504cb5caa98Sdjl id = (nscd_cfg_id_t *)desc; 505cb5caa98Sdjl 506cb5caa98Sdjl if (_nscd_cfg_flag_is_set(desc->sflag, 507cb5caa98Sdjl NSCD_CFG_SFLAG_GROUP)) { 508cb5caa98Sdjl 509cb5caa98Sdjl if (gdesc != NULL) { 510cb5caa98Sdjl g_info.num_param = fn; 511cb5caa98Sdjl gdesc->s_fn = fn; 512cb5caa98Sdjl 513cb5caa98Sdjl if (g_info.num_param != 514cb5caa98Sdjl gdesc->gi.num_param || 515cb5caa98Sdjl !_nscd_cfg_bitmap_is_equal( 516cb5caa98Sdjl g_info.bitmap, gdesc->gi.bitmap)) { 517cb5caa98Sdjl 518cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, 519cb5caa98Sdjl NSCD_LOG_LEVEL_ERROR) 520cb5caa98Sdjl (me, "ERROR: group (%s) " 521cb5caa98Sdjl "info mismatched: " 522cb5caa98Sdjl "group info (%d, %#6.4x) not " 523cb5caa98Sdjl "equal to the predefined one " 524cb5caa98Sdjl "(%d, %#6.4x)\n", gdesc->id.name, 525cb5caa98Sdjl g_info.num_param, 5268ea0afb9SMichen Chang _nscd_cfg_bitmap_value( 5278ea0afb9SMichen Chang g_info.bitmap), 528cb5caa98Sdjl gdesc->gi.num_param, 529cb5caa98Sdjl _nscd_cfg_bitmap_value( 530cb5caa98Sdjl gdesc->gi.bitmap)); 531cb5caa98Sdjl 532cb5caa98Sdjl exit(1); 533cb5caa98Sdjl return (NSCD_CFG_STAT_DESC_ERROR); 534cb5caa98Sdjl } 535cb5caa98Sdjl } 536cb5caa98Sdjl 537cb5caa98Sdjl gi = i; 538cb5caa98Sdjl fn = 0; 539cb5caa98Sdjl gdesc = desc; 540cb5caa98Sdjl g_info.bitmap = NSCD_CFG_BITMAP_ZERO; 541cb5caa98Sdjl 542cb5caa98Sdjl /* 543cb5caa98Sdjl * set the get_stat function 544cb5caa98Sdjl */ 545cb5caa98Sdjl gsfunc = (void *)gdesc->get_stat; 546cb5caa98Sdjl } else { 547cb5caa98Sdjl if (i == 0) { 548cb5caa98Sdjl 549cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, 550cb5caa98Sdjl NSCD_LOG_LEVEL_ERROR) 551cb5caa98Sdjl (me, "ERROR: first stat " 552cb5caa98Sdjl "description is not for a group\n"); 553cb5caa98Sdjl 554cb5caa98Sdjl return (NSCD_CFG_STAT_DESC_ERROR); 555cb5caa98Sdjl } 556cb5caa98Sdjl 557cb5caa98Sdjl /* 558cb5caa98Sdjl * set bitmap: the rightmost bit represents 559cb5caa98Sdjl * the first member (index = 0) in the group, 560cb5caa98Sdjl * the next bit is for the second member 561cb5caa98Sdjl * (index = 1), and so on 562cb5caa98Sdjl */ 563cb5caa98Sdjl _nscd_cfg_bitmap_set_nth(g_info.bitmap, fn); 564cb5caa98Sdjl 565cb5caa98Sdjl desc->s_fn = fn++; 566cb5caa98Sdjl 567cb5caa98Sdjl /* 568cb5caa98Sdjl * set the get_stat function 569cb5caa98Sdjl */ 5700dfdd7f3Smichen if (desc->get_stat == NSCD_CFG_FUNC_GET_STAT_AS_GROUP) { 5710dfdd7f3Smichen (void) memcpy(&desc->get_stat, &gsfunc, 5720dfdd7f3Smichen sizeof (void *)); 573cb5caa98Sdjl } 574cb5caa98Sdjl } 575cb5caa98Sdjl 576cb5caa98Sdjl /* if end of list reached, we are done */ 577cb5caa98Sdjl if (i == _nscd_cfg_num_stat) 578cb5caa98Sdjl break; 579cb5caa98Sdjl 580cb5caa98Sdjl desc->g_index = gi; 581cb5caa98Sdjl 582cb5caa98Sdjl id->index = i; 583cb5caa98Sdjl 584cb5caa98Sdjl if ((rc = _nscd_cfg_add_index_entry(id->name, 585cb5caa98Sdjl i, type)) != NSCD_SUCCESS) { 586cb5caa98Sdjl 587cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 588cb5caa98Sdjl (me, "unable to add index entry for stat " 589cb5caa98Sdjl "description %s\n", id->name); 590cb5caa98Sdjl 591cb5caa98Sdjl _nscd_free_db(cfg_paramDB); 592cb5caa98Sdjl return (rc); 593cb5caa98Sdjl } else { 594cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 595cb5caa98Sdjl (me, "index entry for stat description " 596cb5caa98Sdjl "%s added\n", id->name); 597cb5caa98Sdjl } 598cb5caa98Sdjl } 599cb5caa98Sdjl 600cb5caa98Sdjl return (NSCD_SUCCESS); 601cb5caa98Sdjl } 602cb5caa98Sdjl 603cb5caa98Sdjl static nscd_rc_t 604cb5caa98Sdjl _nscd_cfg_copy_vlen_data( 605cb5caa98Sdjl void *data, 606cb5caa98Sdjl void **new_data_p, 607cb5caa98Sdjl nscd_cfg_param_desc_t *desc, 608cb5caa98Sdjl int *data_len, 609cb5caa98Sdjl nscd_bool_t in) 610cb5caa98Sdjl { 611cb5caa98Sdjl int len, dlen; 612cb5caa98Sdjl nscd_cfg_vlen_data_t *v = NULL; 613cb5caa98Sdjl 614cb5caa98Sdjl *new_data_p = NULL; 615cb5caa98Sdjl *data_len = 0; 616cb5caa98Sdjl 617cb5caa98Sdjl /* it is OK if there is nothing to copy */ 618cb5caa98Sdjl if (data == NULL) 619cb5caa98Sdjl return (NSCD_SUCCESS); 620cb5caa98Sdjl 621cb5caa98Sdjl /* 622cb5caa98Sdjl * if copy to the config store we need to allocate space 623cb5caa98Sdjl * for the extra vlen header 624cb5caa98Sdjl */ 625cb5caa98Sdjl if (desc->type == NSCD_CFG_DATA_STRING) { 626cb5caa98Sdjl len = dlen = strlen((char *)data) + 1; 627cb5caa98Sdjl if (in == nscd_true) 628cb5caa98Sdjl len += sizeof (nscd_cfg_vlen_data_t); 629cb5caa98Sdjl } else { 630cb5caa98Sdjl /* 631cb5caa98Sdjl * should not be here, since for now 632cb5caa98Sdjl * only string variable length data 633cb5caa98Sdjl * is supported 634cb5caa98Sdjl */ 635cb5caa98Sdjl *new_data_p = NULL; 636cb5caa98Sdjl return (NSCD_CFG_PARAM_DESC_ERROR); 637cb5caa98Sdjl } 638cb5caa98Sdjl 639cb5caa98Sdjl v = calloc(1, len); 640cb5caa98Sdjl if (v == NULL) { 641cb5caa98Sdjl *new_data_p = NULL; 642cb5caa98Sdjl return (NSCD_NO_MEMORY); 643cb5caa98Sdjl } 644cb5caa98Sdjl 645cb5caa98Sdjl /* 646cb5caa98Sdjl * if copy to the config store, set up 647cb5caa98Sdjl * the extra vlen header in which the 648cb5caa98Sdjl * pointer to, and length of, the real 649cb5caa98Sdjl * data are kept. The pointer to the real 650cb5caa98Sdjl * data, not the vlen header, is returned. 651cb5caa98Sdjl */ 652cb5caa98Sdjl if (in == nscd_true) { 653cb5caa98Sdjl v->ptr = (char *)v + sizeof (nscd_cfg_vlen_data_t); 654cb5caa98Sdjl v->len = dlen; 655cb5caa98Sdjl (void) memcpy(v->ptr, data, dlen); 656cb5caa98Sdjl *new_data_p = v->ptr; 657cb5caa98Sdjl } else { 658cb5caa98Sdjl (void) memcpy(v, data, dlen); 659cb5caa98Sdjl *new_data_p = v; 660cb5caa98Sdjl } 661cb5caa98Sdjl *data_len = dlen; 662cb5caa98Sdjl 663cb5caa98Sdjl return (NSCD_SUCCESS); 664cb5caa98Sdjl } 665cb5caa98Sdjl 666cb5caa98Sdjl static void 667cb5caa98Sdjl _nscd_cfg_free_vlen_data_int( 668cb5caa98Sdjl void *data) 669cb5caa98Sdjl { 670cb5caa98Sdjl nscd_cfg_vlen_data_t *v = NULL; 671cb5caa98Sdjl void *p; 672cb5caa98Sdjl 673cb5caa98Sdjl if (data == NULL) 674cb5caa98Sdjl return; 675cb5caa98Sdjl 676cb5caa98Sdjl p = (char *)data - sizeof (nscd_cfg_vlen_data_t); 677cb5caa98Sdjl v = (nscd_cfg_vlen_data_t *)p; 678cb5caa98Sdjl if (v->ptr == data) 679cb5caa98Sdjl free(v); 680cb5caa98Sdjl } 681cb5caa98Sdjl 682cb5caa98Sdjl static nscd_rc_t 683cb5caa98Sdjl _nscd_cfg_set_vlen_data_int( 684cb5caa98Sdjl void *src, 685cb5caa98Sdjl void *dest, 686cb5caa98Sdjl nscd_bool_t global) 687cb5caa98Sdjl { 688cb5caa98Sdjl int i, offset, dlen = 0; 689cb5caa98Sdjl void *s, *d, *new; 690cb5caa98Sdjl void *cptr; 691cb5caa98Sdjl nscd_rc_t rc; 692cb5caa98Sdjl nscd_cfg_param_desc_t *desc; 693cb5caa98Sdjl 694cb5caa98Sdjl desc = &_nscd_cfg_param_desc[0]; 695cb5caa98Sdjl for (i = 0; i < _nscd_cfg_num_param; i++, desc++) { 696cb5caa98Sdjl 697cb5caa98Sdjl if (global == nscd_true && 698cb5caa98Sdjl _nscd_cfg_flag_is_not_set(desc->pflag, 699cb5caa98Sdjl NSCD_CFG_PFLAG_GLOBAL)) 700cb5caa98Sdjl continue; 701cb5caa98Sdjl else if (global != nscd_true && 702cb5caa98Sdjl _nscd_cfg_flag_is_set(desc->pflag, 703cb5caa98Sdjl NSCD_CFG_PFLAG_GLOBAL)) 704cb5caa98Sdjl continue; 705cb5caa98Sdjl 706cb5caa98Sdjl if (_nscd_cfg_flag_is_set(desc->pflag, 707cb5caa98Sdjl NSCD_CFG_PFLAG_VLEN_DATA)) { 708cb5caa98Sdjl 709cb5caa98Sdjl offset = desc->g_offset + desc->p_offset; 710cb5caa98Sdjl 711cb5caa98Sdjl s = (char *)src + offset; 712cb5caa98Sdjl cptr = *(char **)s; 713cb5caa98Sdjl 714cb5caa98Sdjl rc = _nscd_cfg_copy_vlen_data(cptr, &new, 715cb5caa98Sdjl desc, &dlen, nscd_true); 716cb5caa98Sdjl if (rc != NSCD_SUCCESS) 717cb5caa98Sdjl return (rc); 718cb5caa98Sdjl 719cb5caa98Sdjl d = (char *)dest + offset; 720cb5caa98Sdjl /* free the old vlen data */ 721cb5caa98Sdjl if (*(char **)d == NULL) 722cb5caa98Sdjl _nscd_cfg_free_vlen_data_int(*(char **)d); 723cb5caa98Sdjl 724cb5caa98Sdjl *(char **)d = new; 725cb5caa98Sdjl } 726cb5caa98Sdjl } 727cb5caa98Sdjl 728cb5caa98Sdjl return (NSCD_SUCCESS); 729cb5caa98Sdjl } 730cb5caa98Sdjl 731cb5caa98Sdjl static void * 732cb5caa98Sdjl _nscd_cfg_locate_vlen_data( 733cb5caa98Sdjl void *cfg_data, 734cb5caa98Sdjl int *len) 735cb5caa98Sdjl { 736cb5caa98Sdjl void *ptr, *ret; 737cb5caa98Sdjl 738cb5caa98Sdjl ptr = *(char **)cfg_data; 739cb5caa98Sdjl ret = ptr; 740cb5caa98Sdjl if (ret == NULL) { 741cb5caa98Sdjl *len = 0; 742cb5caa98Sdjl return (NULL); 743cb5caa98Sdjl } 744cb5caa98Sdjl ptr = (char *)ptr - sizeof (nscd_cfg_vlen_data_t); 745cb5caa98Sdjl *len = ((nscd_cfg_vlen_data_t *)ptr)->len; 746cb5caa98Sdjl 747cb5caa98Sdjl return (ret); 748cb5caa98Sdjl } 749cb5caa98Sdjl 750cb5caa98Sdjl static void 751cb5caa98Sdjl _nscd_cfg_lock( 752cb5caa98Sdjl nscd_bool_t is_read, 753cb5caa98Sdjl nscd_cfg_lock_t *cfglock) 754cb5caa98Sdjl { 755cb5caa98Sdjl 756cb5caa98Sdjl int (*lockfunc)(rwlock_t *); 757cb5caa98Sdjl 758cb5caa98Sdjl if (cfglock == NULL) 759cb5caa98Sdjl return; 760cb5caa98Sdjl 761cb5caa98Sdjl if (is_read == nscd_true) 762cb5caa98Sdjl lockfunc = rw_rdlock; 763cb5caa98Sdjl else 764cb5caa98Sdjl lockfunc = rw_wrlock; 765cb5caa98Sdjl 766cb5caa98Sdjl if (cfglock->global != NULL) { 767cb5caa98Sdjl 768cb5caa98Sdjl (lockfunc)(cfglock->global); 769cb5caa98Sdjl return; 770cb5caa98Sdjl } 771cb5caa98Sdjl 772cb5caa98Sdjl if (cfglock->alldb != NULL) 773cb5caa98Sdjl (lockfunc)(cfglock->alldb); 774cb5caa98Sdjl 775cb5caa98Sdjl if (cfglock->nswdb != NULL) 776cb5caa98Sdjl (lockfunc)(cfglock->nswdb); 777cb5caa98Sdjl } 778cb5caa98Sdjl 779cb5caa98Sdjl static void 780cb5caa98Sdjl _nscd_cfg_unlock( 781cb5caa98Sdjl nscd_cfg_lock_t *cfglock) 782cb5caa98Sdjl { 783cb5caa98Sdjl if (cfglock == NULL) 784cb5caa98Sdjl return; 785cb5caa98Sdjl 786cb5caa98Sdjl if (cfglock->global != NULL) { 787cb5caa98Sdjl 788cb5caa98Sdjl (void) rw_unlock(cfglock->global); 789cb5caa98Sdjl free(cfglock); 790cb5caa98Sdjl return; 791cb5caa98Sdjl } 792cb5caa98Sdjl 793cb5caa98Sdjl if (cfglock->nswdb != NULL) 794cb5caa98Sdjl (void) rw_unlock(cfglock->nswdb); 795cb5caa98Sdjl 796cb5caa98Sdjl if (cfglock->alldb != NULL) 797cb5caa98Sdjl (void) rw_unlock(cfglock->alldb); 798cb5caa98Sdjl 799cb5caa98Sdjl free(cfglock); 800cb5caa98Sdjl } 801cb5caa98Sdjl 802cb5caa98Sdjl /* 803cb5caa98Sdjl * If vlen_data_addr is given, it will be set to the 804cb5caa98Sdjl * address of the pointer pointing to the vlen data. 805cb5caa98Sdjl * 'cfglock' will be set to point to the reader/writer 806cb5caa98Sdjl * lock(s) protecting the (group) configuration data. 807cb5caa98Sdjl */ 808cb5caa98Sdjl static nscd_rc_t 809cb5caa98Sdjl _nscd_cfg_locate_cfg_data( 810cb5caa98Sdjl void **cfg_data, 811cb5caa98Sdjl nscd_bool_t is_read, 812cb5caa98Sdjl nscd_cfg_param_desc_t *desc, 813cb5caa98Sdjl nscd_cfg_id_t *nswdb, 814cb5caa98Sdjl nscd_bool_t get_group, 815cb5caa98Sdjl void **vlen_data_addr, 816cb5caa98Sdjl int *len, 817cb5caa98Sdjl nscd_cfg_lock_t **cfglock) 818cb5caa98Sdjl { 819cb5caa98Sdjl int offset; 820cb5caa98Sdjl 821cb5caa98Sdjl *cfg_data = NULL; 822cb5caa98Sdjl if (len != NULL) 823cb5caa98Sdjl *len = 0; 824cb5caa98Sdjl if (vlen_data_addr != NULL) 825cb5caa98Sdjl *vlen_data_addr = NULL; 826cb5caa98Sdjl 827cb5caa98Sdjl if (cfglock != NULL) { 828cb5caa98Sdjl *cfglock = calloc(1, sizeof (nscd_cfg_lock_t)); 829cb5caa98Sdjl if (*cfglock == NULL) 830cb5caa98Sdjl return (NSCD_NO_MEMORY); 831cb5caa98Sdjl } 832cb5caa98Sdjl 833cb5caa98Sdjl /* assume if nswdb is NULL, the param is a global one */ 834cb5caa98Sdjl if (nswdb == NULL) { 835cb5caa98Sdjl 836cb5caa98Sdjl offset = desc->g_offset; 837cb5caa98Sdjl if (get_group != nscd_true) 838cb5caa98Sdjl offset += desc->p_offset; 839cb5caa98Sdjl *cfg_data = (char *)nscd_cfg_global_current + offset; 840cb5caa98Sdjl 841cb5caa98Sdjl if (cfglock != NULL) 842cb5caa98Sdjl (*cfglock)->global = nscd_cfg_global_rwlock; 843cb5caa98Sdjl 844cb5caa98Sdjl } else if (nswdb->index == NSCD_CFG_NSW_ALLDB_INDEX) { 845cb5caa98Sdjl 846cb5caa98Sdjl offset = desc->g_offset; 847cb5caa98Sdjl if (get_group != nscd_true) 848cb5caa98Sdjl offset += desc->p_offset; 849cb5caa98Sdjl *cfg_data = (char *)nscd_cfg_nsw_alldb_current + 850cb5caa98Sdjl offset; 851cb5caa98Sdjl 852cb5caa98Sdjl if (cfglock != NULL) 853cb5caa98Sdjl (*cfglock)->alldb = nscd_cfg_nsw_alldb_rwlock; 854cb5caa98Sdjl 855cb5caa98Sdjl } else { 856cb5caa98Sdjl 857cb5caa98Sdjl offset = nswdb->index * 858cb5caa98Sdjl (sizeof (nscd_cfg_nsw_db_data_t)) + desc->g_offset; 859cb5caa98Sdjl if (get_group != nscd_true) 860cb5caa98Sdjl offset += desc->p_offset; 861cb5caa98Sdjl *cfg_data = (char *)nscd_cfg_nsw_db_data_current + 862cb5caa98Sdjl offset; 863cb5caa98Sdjl 864cb5caa98Sdjl if (cfglock != NULL) { 865cb5caa98Sdjl (*cfglock)->nswdb = 866cb5caa98Sdjl &nscd_cfg_nsw_db_data_rwlock[nswdb->index]; 867cb5caa98Sdjl 868cb5caa98Sdjl (*cfglock)->alldb = nscd_cfg_nsw_alldb_rwlock; 869cb5caa98Sdjl } 870cb5caa98Sdjl } 871cb5caa98Sdjl 872cb5caa98Sdjl /* lock the config data */ 873cb5caa98Sdjl if (cfglock != NULL) 874cb5caa98Sdjl _nscd_cfg_lock(is_read, *cfglock); 875cb5caa98Sdjl 876cb5caa98Sdjl if (get_group != nscd_true && 877cb5caa98Sdjl _nscd_cfg_flag_is_not_set(desc->pflag, 878cb5caa98Sdjl NSCD_CFG_PFLAG_GROUP) && 879cb5caa98Sdjl (_nscd_cfg_flag_is_set(desc->pflag, 880cb5caa98Sdjl NSCD_CFG_PFLAG_VLEN_DATA))) { 881cb5caa98Sdjl if (vlen_data_addr != NULL) 882cb5caa98Sdjl *vlen_data_addr = *cfg_data; 883cb5caa98Sdjl *cfg_data = _nscd_cfg_locate_vlen_data(*cfg_data, len); 884cb5caa98Sdjl return (NSCD_SUCCESS); 885cb5caa98Sdjl } 886cb5caa98Sdjl 887cb5caa98Sdjl if (len != NULL) { 888cb5caa98Sdjl if (get_group == nscd_true) 889cb5caa98Sdjl *len = desc->g_size; 890cb5caa98Sdjl else 891cb5caa98Sdjl *len = desc->p_size; 892cb5caa98Sdjl } 893cb5caa98Sdjl 894cb5caa98Sdjl return (NSCD_SUCCESS); 895cb5caa98Sdjl } 896cb5caa98Sdjl 897cb5caa98Sdjl /* 898cb5caa98Sdjl * perform the preliminary (range) check on 'data' based on the 899cb5caa98Sdjl * datatype (desc->datatype) of the config parameter 900cb5caa98Sdjl */ 901cb5caa98Sdjl nscd_rc_t 902cb5caa98Sdjl _nscd_cfg_prelim_check( 903cb5caa98Sdjl nscd_cfg_param_desc_t *desc, 904cb5caa98Sdjl void *data, 905cb5caa98Sdjl nscd_cfg_error_t **errorp) 906cb5caa98Sdjl { 907cb5caa98Sdjl 908cb5caa98Sdjl char *me = "_nscd_cfg_prelim_check"; 909cb5caa98Sdjl char msg[NSCD_CFG_MAX_ERR_MSG_LEN]; 910cb5caa98Sdjl nscd_cfg_str_check_t *sc; 911cb5caa98Sdjl nscd_cfg_int_check_t *ic; 912cb5caa98Sdjl nscd_cfg_bitmap_check_t *bmc; 913cb5caa98Sdjl nscd_rc_t rc = NSCD_CFG_PRELIM_CHECK_FAILED; 914cb5caa98Sdjl 915cb5caa98Sdjl if ((nscd_cfg_str_check_t *)desc->p_check == NULL) 916cb5caa98Sdjl return (NSCD_SUCCESS); 917cb5caa98Sdjl 918cb5caa98Sdjl switch (desc->type) { 919cb5caa98Sdjl 920cb5caa98Sdjl case NSCD_CFG_DATA_STRING: 921cb5caa98Sdjl 922cb5caa98Sdjl sc = (nscd_cfg_str_check_t *)desc->p_check; 923cb5caa98Sdjl if (sc->must_not_null == nscd_true && data == NULL) { 924cb5caa98Sdjl 925cb5caa98Sdjl if (errorp == NULL) 926cb5caa98Sdjl break; 927cb5caa98Sdjl 928cb5caa98Sdjl (void) snprintf(msg, sizeof (msg), 929cb5caa98Sdjl gettext("data must be specified for %s"), 930cb5caa98Sdjl desc->id.name); 931cb5caa98Sdjl 932cb5caa98Sdjl break; 933cb5caa98Sdjl } 934cb5caa98Sdjl 935cb5caa98Sdjl if (data == NULL) { 936cb5caa98Sdjl rc = NSCD_SUCCESS; 937cb5caa98Sdjl break; 938cb5caa98Sdjl } 939cb5caa98Sdjl 940cb5caa98Sdjl if (sc->maxlen != 0 && 941cb5caa98Sdjl strlen((char *)data) > sc->maxlen) { 942cb5caa98Sdjl 943cb5caa98Sdjl if (errorp == NULL) 944cb5caa98Sdjl break; 945cb5caa98Sdjl 946cb5caa98Sdjl (void) snprintf(msg, sizeof (msg), 9478ea0afb9SMichen Chang gettext("length of data (%s) for %s larger " 9488ea0afb9SMichen Chang "than %d"), 949cb5caa98Sdjl (char *)data, desc->id.name, sc->maxlen); 950cb5caa98Sdjl break; 951cb5caa98Sdjl } 952cb5caa98Sdjl 953cb5caa98Sdjl rc = NSCD_SUCCESS; 954cb5caa98Sdjl 955cb5caa98Sdjl break; 956cb5caa98Sdjl 957cb5caa98Sdjl case NSCD_CFG_DATA_INTEGER: 958cb5caa98Sdjl 959cb5caa98Sdjl ic = (nscd_cfg_int_check_t *)desc->p_check; 960cb5caa98Sdjl if (*(int *)data > ic->max || 961cb5caa98Sdjl *(int *)data < ic->min) { 962cb5caa98Sdjl 963cb5caa98Sdjl if (errorp == NULL) 964cb5caa98Sdjl break; 965cb5caa98Sdjl 966cb5caa98Sdjl (void) snprintf(msg, sizeof (msg), 9678ea0afb9SMichen Chang gettext("data (%d) for %s out of range " 9688ea0afb9SMichen Chang "(%d - %d)"), 969cb5caa98Sdjl *(int *)data, desc->id.name, 970cb5caa98Sdjl ic->min, ic->max); 971cb5caa98Sdjl 972cb5caa98Sdjl break; 973cb5caa98Sdjl } 974cb5caa98Sdjl 975cb5caa98Sdjl rc = NSCD_SUCCESS; 976cb5caa98Sdjl 977cb5caa98Sdjl break; 978cb5caa98Sdjl 979cb5caa98Sdjl case NSCD_CFG_DATA_BITMAP: 980cb5caa98Sdjl 981cb5caa98Sdjl bmc = (nscd_cfg_bitmap_check_t *)desc->p_check; 982cb5caa98Sdjl if (_nscd_cfg_bitmap_value(*(nscd_cfg_bitmap_t *)data) & 983cb5caa98Sdjl ~(bmc->valid_bits)) { 984cb5caa98Sdjl 985cb5caa98Sdjl if (errorp == NULL) 986cb5caa98Sdjl break; 987cb5caa98Sdjl 988cb5caa98Sdjl (void) snprintf(msg, sizeof (msg), 9898ea0afb9SMichen Chang gettext("data (%#6.4x) for %s contain bit " 9908ea0afb9SMichen Chang "not in 0x%x"), 991cb5caa98Sdjl _nscd_cfg_bitmap_value( 992cb5caa98Sdjl *(nscd_cfg_bitmap_t *)data), 993cb5caa98Sdjl desc->id.name, 994cb5caa98Sdjl _nscd_cfg_bitmap_value(bmc->valid_bits)); 995cb5caa98Sdjl break; 996cb5caa98Sdjl } 997cb5caa98Sdjl 998cb5caa98Sdjl rc = NSCD_SUCCESS; 999cb5caa98Sdjl 1000cb5caa98Sdjl break; 1001cb5caa98Sdjl } 1002cb5caa98Sdjl 1003cb5caa98Sdjl if (rc != NSCD_SUCCESS && errorp != NULL) { 1004cb5caa98Sdjl *errorp = _nscd_cfg_make_error(rc, msg); 1005cb5caa98Sdjl 1006cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 1007cb5caa98Sdjl (me, "invalid argument: %s\n", (*errorp)->msg); 1008cb5caa98Sdjl } 1009cb5caa98Sdjl 1010cb5caa98Sdjl return (rc); 1011cb5caa98Sdjl } 1012cb5caa98Sdjl 1013cb5caa98Sdjl static nscd_rc_t 1014cb5caa98Sdjl _nscd_cfg_notify_i( 1015cb5caa98Sdjl nscd_cfg_param_desc_t *desc, 1016cb5caa98Sdjl nscd_cfg_id_t *nswdb, 1017cb5caa98Sdjl int *skip, 1018cb5caa98Sdjl nscd_cfg_error_t **errorp) 1019cb5caa98Sdjl { 1020cb5caa98Sdjl 1021cb5caa98Sdjl char *me = "_nscd_cfg_notify_i"; 1022cb5caa98Sdjl int i, num, skip_bk; 1023cb5caa98Sdjl void *cfg_data, *cdata; 1024cb5caa98Sdjl void *cookie = NULL; 1025cb5caa98Sdjl nscd_rc_t rc; 1026cb5caa98Sdjl nscd_cfg_flag_t dflag, dflag1; 1027cb5caa98Sdjl nscd_cfg_bitmap_t bitmap_c, bitmap_s, *bitmap_addr; 1028cb5caa98Sdjl nscd_cfg_group_info_t *gi; 1029cb5caa98Sdjl 1030cb5caa98Sdjl if (errorp != NULL) 1031cb5caa98Sdjl *errorp = NULL; 1032cb5caa98Sdjl 1033cb5caa98Sdjl if (skip == NULL) 1034cb5caa98Sdjl skip = &skip_bk; 1035cb5caa98Sdjl 1036cb5caa98Sdjl *skip = 0; 1037cb5caa98Sdjl 1038cb5caa98Sdjl if (_nscd_cfg_flag_is_not_set(desc->pflag, 1039cb5caa98Sdjl NSCD_CFG_PFLAG_GROUP)) { 1040cb5caa98Sdjl 1041cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 1042cb5caa98Sdjl (me, "ERROR: expect parameter description for group, " 1043cb5caa98Sdjl "but receive parameter description is for %s\n", 1044cb5caa98Sdjl desc->id.name); 1045cb5caa98Sdjl 1046cb5caa98Sdjl return (NSCD_CFG_PARAM_DESC_ERROR); 1047cb5caa98Sdjl } 1048cb5caa98Sdjl 1049cb5caa98Sdjl /* 1050cb5caa98Sdjl * Set data flag going with data to be sent to the 1051cb5caa98Sdjl * verify/notify routines. Allowing the config flag 1052cb5caa98Sdjl * be exipandable, set the bits one by one. 1053cb5caa98Sdjl */ 1054cb5caa98Sdjl dflag = NSCD_CFG_FLAG_ZERO; 1055cb5caa98Sdjl dflag = _nscd_cfg_flag_set(dflag, NSCD_CFG_DFLAG_STATIC_DATA); 1056cb5caa98Sdjl dflag = _nscd_cfg_flag_set(dflag, NSCD_CFG_DFLAG_INIT); 1057cb5caa98Sdjl dflag = _nscd_cfg_flag_set(dflag, NSCD_CFG_DFLAG_GROUP); 1058cb5caa98Sdjl if (_nscd_cfg_flag_is_set(desc->pflag, 1059cb5caa98Sdjl NSCD_CFG_PFLAG_INIT_SET_ALL_DB)) 1060cb5caa98Sdjl dflag = _nscd_cfg_flag_set(dflag, 1061cb5caa98Sdjl NSCD_CFG_DFLAG_SET_ALL_DB); 1062cb5caa98Sdjl 1063cb5caa98Sdjl /* get to the group data in the config store */ 1064cb5caa98Sdjl rc = _nscd_cfg_locate_cfg_data(&cfg_data, nscd_true, 1065cb5caa98Sdjl desc, nswdb, nscd_true, NULL, NULL, NULL); 1066cb5caa98Sdjl if (rc != NSCD_SUCCESS) 1067cb5caa98Sdjl goto error; 1068cb5caa98Sdjl 1069cb5caa98Sdjl /* 1070cb5caa98Sdjl * the static bitmap associated with the group 1071cb5caa98Sdjl * may be replaced before sending to the components, 1072cb5caa98Sdjl * so save the bitmap for later use 1073cb5caa98Sdjl */ 1074cb5caa98Sdjl gi = _nscd_cfg_get_gi(cfg_data); 1075cb5caa98Sdjl bitmap_c = gi->bitmap; 1076cb5caa98Sdjl bitmap_addr = &(gi->bitmap); 1077cb5caa98Sdjl 1078cb5caa98Sdjl /* 1079cb5caa98Sdjl * the elements in this group will all be handled 1080cb5caa98Sdjl * so the caller can skip them 1081cb5caa98Sdjl */ 1082cb5caa98Sdjl *skip = desc->p_fn; 1083cb5caa98Sdjl 1084cb5caa98Sdjl if (_nscd_cfg_flag_is_set(desc->pflag, 1085cb5caa98Sdjl NSCD_CFG_PFLAG_INIT_SEND_WHOLE_GROUP)) 1086cb5caa98Sdjl /* send the entire group just once */ 1087cb5caa98Sdjl num = 1; 1088cb5caa98Sdjl 1089cb5caa98Sdjl else { /* send individual members one by one */ 1090cb5caa98Sdjl 1091cb5caa98Sdjl num = desc->p_fn; 1092cb5caa98Sdjl 1093cb5caa98Sdjl /* 1094cb5caa98Sdjl * skip the first desc which is for the group 1095cb5caa98Sdjl * and get to the desc for the first member 1096cb5caa98Sdjl */ 1097cb5caa98Sdjl desc++; 1098cb5caa98Sdjl 1099cb5caa98Sdjl dflag = _nscd_cfg_flag_unset(dflag, 1100cb5caa98Sdjl NSCD_CFG_DFLAG_GROUP); 1101cb5caa98Sdjl } 1102cb5caa98Sdjl 1103cb5caa98Sdjl dflag1 = dflag; 1104cb5caa98Sdjl for (i = 0; i < num; i++, desc++) { 1105cb5caa98Sdjl 1106cb5caa98Sdjl dflag = dflag1; 1107cb5caa98Sdjl 1108cb5caa98Sdjl if (_nscd_cfg_flag_is_set(desc->pflag, 1109cb5caa98Sdjl NSCD_CFG_PFLAG_SEND_BIT_SELECTED)) { 1110cb5caa98Sdjl 1111cb5caa98Sdjl /* set the bitmap to select just this member */ 1112cb5caa98Sdjl bitmap_s = NSCD_CFG_BITMAP_ZERO; 1113cb5caa98Sdjl _nscd_cfg_bitmap_set_nth(bitmap_s, i); 1114cb5caa98Sdjl /* replace the bitmap in the cfg data */ 1115cb5caa98Sdjl _nscd_cfg_bitmap_set(bitmap_addr, bitmap_s); 1116cb5caa98Sdjl 1117cb5caa98Sdjl /* 1118cb5caa98Sdjl * send the whole group but with only one 1119cb5caa98Sdjl * member selected 1120cb5caa98Sdjl */ 1121cb5caa98Sdjl cdata = cfg_data; 1122cb5caa98Sdjl 1123cb5caa98Sdjl dflag = _nscd_cfg_flag_set(dflag, 1124cb5caa98Sdjl NSCD_CFG_DFLAG_GROUP); 1125cb5caa98Sdjl dflag = _nscd_cfg_flag_set(dflag, 1126cb5caa98Sdjl NSCD_CFG_DFLAG_BIT_SELECTED); 1127cb5caa98Sdjl } else { 1128cb5caa98Sdjl /* 1129cb5caa98Sdjl * send param data or group data: 1130cb5caa98Sdjl * param data - non-xero desc->p_offset 1131cb5caa98Sdjl * group data - zero desc->p_offset 1132cb5caa98Sdjl */ 1133cb5caa98Sdjl cdata = (char *)cfg_data + desc->p_offset; 1134cb5caa98Sdjl 1135cb5caa98Sdjl /* 1136cb5caa98Sdjl * if variable length data, need to send pointer 1137cb5caa98Sdjl * to the data (not the address of the pointer) 1138cb5caa98Sdjl */ 1139cb5caa98Sdjl if (_nscd_cfg_flag_is_set(desc->pflag, 1140cb5caa98Sdjl NSCD_CFG_PFLAG_VLEN_DATA)) 1141cb5caa98Sdjl cdata = *(char **)cdata; 1142cb5caa98Sdjl } 1143cb5caa98Sdjl 1144cb5caa98Sdjl if (desc->verify != NULL) { 1145cb5caa98Sdjl dflag = _nscd_cfg_flag_set(dflag, 1146cb5caa98Sdjl NSCD_CFG_DFLAG_VERIFY); 1147cb5caa98Sdjl rc = desc->verify(cdata, desc, nswdb, 1148cb5caa98Sdjl dflag, errorp, &cookie); 1149cb5caa98Sdjl if (rc != NSCD_SUCCESS) 1150cb5caa98Sdjl goto error; 1151cb5caa98Sdjl } 1152cb5caa98Sdjl 1153cb5caa98Sdjl if (desc->notify != NULL) { 1154cb5caa98Sdjl dflag = _nscd_cfg_flag_set(dflag, 1155cb5caa98Sdjl NSCD_CFG_DFLAG_NOTIFY); 1156cb5caa98Sdjl 1157cb5caa98Sdjl rc = desc->notify(cfg_data, desc, nswdb, 1158cb5caa98Sdjl dflag, errorp, cookie); 1159cb5caa98Sdjl if (rc != NSCD_SUCCESS) 1160cb5caa98Sdjl goto error; 1161cb5caa98Sdjl } 1162cb5caa98Sdjl } 1163cb5caa98Sdjl 1164cb5caa98Sdjl rc = NSCD_SUCCESS; 1165cb5caa98Sdjl 1166cb5caa98Sdjl /* restore the bitmap in the cfg data */ 1167cb5caa98Sdjl _nscd_cfg_bitmap_set(bitmap_addr, bitmap_c); 1168cb5caa98Sdjl 1169cb5caa98Sdjl error: 1170cb5caa98Sdjl 1171cb5caa98Sdjl return (rc); 1172cb5caa98Sdjl 1173cb5caa98Sdjl } 1174cb5caa98Sdjl 1175cb5caa98Sdjl static nscd_rc_t 1176cb5caa98Sdjl _nscd_cfg_notify_init( 1177cb5caa98Sdjl nscd_cfg_error_t **errorp) 1178cb5caa98Sdjl { 1179cb5caa98Sdjl int i, j, skip; 1180cb5caa98Sdjl nscd_rc_t rc; 1181cb5caa98Sdjl nscd_cfg_id_t *nswdb = NULL; 1182cb5caa98Sdjl nscd_cfg_param_desc_t *desc; 1183cb5caa98Sdjl 1184cb5caa98Sdjl if (errorp != NULL) 1185cb5caa98Sdjl *errorp = NULL; 1186cb5caa98Sdjl 1187cb5caa98Sdjl for (i = 0; i < _nscd_cfg_num_param; i++) { 1188cb5caa98Sdjl 1189cb5caa98Sdjl desc = &_nscd_cfg_param_desc[i]; 1190cb5caa98Sdjl 1191cb5caa98Sdjl if (_nscd_cfg_flag_is_set(desc->pflag, 1192cb5caa98Sdjl NSCD_CFG_PFLAG_GLOBAL)) { /* global cfg data */ 1193cb5caa98Sdjl 1194cb5caa98Sdjl rc = _nscd_cfg_notify_i(desc, NULL, &skip, errorp); 1195cb5caa98Sdjl } else { 1196cb5caa98Sdjl 1197cb5caa98Sdjl /* 1198cb5caa98Sdjl * if use defaults for all nsswitch database, 1199cb5caa98Sdjl * send the config data to verify/notify once 1200cb5caa98Sdjl */ 1201cb5caa98Sdjl if (_nscd_cfg_flag_is_set(desc->pflag, 1202cb5caa98Sdjl NSCD_CFG_PFLAG_INIT_SET_ALL_DB)) { 1203cb5caa98Sdjl 1204cb5caa98Sdjl nswdb = &_nscd_cfg_nsw_alldb; 1205cb5caa98Sdjl 1206cb5caa98Sdjl rc = _nscd_cfg_notify_i(desc, nswdb, 1207cb5caa98Sdjl &skip, errorp); 1208cb5caa98Sdjl } else { /* send data once for each nsw db */ 1209cb5caa98Sdjl 1210e37190e5Smichen for (j = 0; j < _nscd_cfg_num_nsw_db; j++) { 1211cb5caa98Sdjl 1212cb5caa98Sdjl nswdb = &_nscd_cfg_nsw_db[j]; 1213cb5caa98Sdjl 1214cb5caa98Sdjl rc = _nscd_cfg_notify_i(desc, 1215cb5caa98Sdjl nswdb, &skip, errorp); 1216e37190e5Smichen 1217e37190e5Smichen if (rc != NSCD_SUCCESS) 1218e37190e5Smichen break; 1219cb5caa98Sdjl } 1220cb5caa98Sdjl } 1221cb5caa98Sdjl } 1222cb5caa98Sdjl 1223cb5caa98Sdjl if (rc != NSCD_SUCCESS) 1224cb5caa98Sdjl return (rc); 1225cb5caa98Sdjl 1226cb5caa98Sdjl i += skip; 1227cb5caa98Sdjl } 1228cb5caa98Sdjl 1229cb5caa98Sdjl return (NSCD_SUCCESS); 1230cb5caa98Sdjl } 1231cb5caa98Sdjl 1232cb5caa98Sdjl nscd_rc_t 1233cb5caa98Sdjl _nscd_cfg_init( 1234cb5caa98Sdjl nscd_cfg_error_t **errorp) 1235cb5caa98Sdjl { 1236cb5caa98Sdjl 1237cb5caa98Sdjl int i, j, datalen; 1238cb5caa98Sdjl int dbi = 0, dbj = 0; 1239cb5caa98Sdjl char *dest, *src; 1240cb5caa98Sdjl char *dbni = NULL, *dbnj = NULL; 1241cb5caa98Sdjl nscd_rc_t rc; 1242cb5caa98Sdjl nscd_cfg_nsw_spc_default_t *spc; 1243cb5caa98Sdjl 1244cb5caa98Sdjl if (errorp != NULL) 1245cb5caa98Sdjl *errorp = NULL; 1246cb5caa98Sdjl 1247cb5caa98Sdjl rc = _nscd_cfg_init_param(); 1248cb5caa98Sdjl if (rc != NSCD_SUCCESS) 1249cb5caa98Sdjl return (rc); 1250cb5caa98Sdjl 1251cb5caa98Sdjl rc = _nscd_cfg_init_stat(); 1252cb5caa98Sdjl if (rc != NSCD_SUCCESS) 1253cb5caa98Sdjl return (rc); 1254cb5caa98Sdjl 1255cb5caa98Sdjl nscd_cfg_global_current = calloc(1, 1256cb5caa98Sdjl sizeof (nscd_cfg_global_data_t)); 1257cb5caa98Sdjl if (nscd_cfg_global_current == NULL) 1258cb5caa98Sdjl return (NSCD_NO_MEMORY); 1259cb5caa98Sdjl 1260cb5caa98Sdjl nscd_cfg_nsw_alldb_current = calloc(1, 1261cb5caa98Sdjl sizeof (nscd_cfg_nsw_db_data_t)); 1262cb5caa98Sdjl if (nscd_cfg_nsw_alldb_current == NULL) 1263cb5caa98Sdjl return (NSCD_NO_MEMORY); 1264cb5caa98Sdjl 1265cb5caa98Sdjl nscd_cfg_nsw_db_data_current = calloc(_nscd_cfg_num_nsw_db, 1266cb5caa98Sdjl sizeof (nscd_cfg_nsw_db_data_t)); 1267cb5caa98Sdjl if (nscd_cfg_nsw_db_data_current == NULL) 1268cb5caa98Sdjl return (NSCD_NO_MEMORY); 1269cb5caa98Sdjl 1270cb5caa98Sdjl nscd_cfg_global_rwlock = calloc(1, sizeof (rwlock_t)); 1271cb5caa98Sdjl if (nscd_cfg_global_rwlock == NULL) 1272cb5caa98Sdjl return (NSCD_NO_MEMORY); 1273cb5caa98Sdjl (void) rwlock_init(nscd_cfg_global_rwlock, NULL, NULL); 1274cb5caa98Sdjl 1275cb5caa98Sdjl *nscd_cfg_global_current = nscd_cfg_global_default; 1276cb5caa98Sdjl 1277cb5caa98Sdjl rc = _nscd_cfg_set_vlen_data_int(&nscd_cfg_global_default, 1278cb5caa98Sdjl nscd_cfg_global_current, nscd_true); 1279cb5caa98Sdjl if (rc != NSCD_SUCCESS) 1280cb5caa98Sdjl return (rc); 1281cb5caa98Sdjl 1282cb5caa98Sdjl nscd_cfg_nsw_db_data_rwlock = calloc(_nscd_cfg_num_nsw_db, 1283cb5caa98Sdjl sizeof (rwlock_t)); 1284cb5caa98Sdjl if (nscd_cfg_nsw_db_data_rwlock == NULL) 1285cb5caa98Sdjl return (NSCD_NO_MEMORY); 1286cb5caa98Sdjl 1287cb5caa98Sdjl /* set per switch db config to the default for all db's */ 1288cb5caa98Sdjl for (i = 0; i < _nscd_cfg_num_nsw_db; i++) { 1289cb5caa98Sdjl 1290cb5caa98Sdjl nscd_cfg_nsw_db_data_current[i] = 1291cb5caa98Sdjl nscd_cfg_nsw_db_data_default; 1292cb5caa98Sdjl 1293cb5caa98Sdjl (void) rwlock_init(&nscd_cfg_nsw_db_data_rwlock[i], 1294cb5caa98Sdjl NULL, NULL); 1295cb5caa98Sdjl } 1296cb5caa98Sdjl 1297cb5caa98Sdjl /* add db specific defaults */ 1298cb5caa98Sdjl for (i = 0; i < _nscd_cfg_num_nsw_default; i++) { 1299cb5caa98Sdjl 1300cb5caa98Sdjl if (_nscd_cfg_nsw_spc_default[i].data == NULL) 1301cb5caa98Sdjl continue; 1302cb5caa98Sdjl 1303cb5caa98Sdjl if (_nscd_cfg_nsw_spc_default[i].db != dbni) { 1304cb5caa98Sdjl for (j = 0; j < _nscd_cfg_num_nsw_db; j++) { 1305cb5caa98Sdjl 1306cb5caa98Sdjl if (strcmp(_nscd_cfg_nsw_db[j].name, 1307cb5caa98Sdjl _nscd_cfg_nsw_spc_default[i].db) != 0) 1308cb5caa98Sdjl continue; 1309cb5caa98Sdjl 1310cb5caa98Sdjl dbi = _nscd_cfg_nsw_db[j].index; 1311cb5caa98Sdjl dbni = _nscd_cfg_nsw_db[j].name; 1312cb5caa98Sdjl break; 1313cb5caa98Sdjl } 1314cb5caa98Sdjl } 1315cb5caa98Sdjl 1316cb5caa98Sdjl dest = (char *)&nscd_cfg_nsw_db_data_current[dbi] + 1317cb5caa98Sdjl _nscd_cfg_nsw_spc_default[i].group_off + 1318cb5caa98Sdjl _nscd_cfg_nsw_spc_default[i].param_off; 1319cb5caa98Sdjl 1320cb5caa98Sdjl src = _nscd_cfg_nsw_spc_default[i].data; 1321cb5caa98Sdjl datalen = _nscd_cfg_nsw_spc_default[i].data_len; 1322cb5caa98Sdjl 1323cb5caa98Sdjl (void) memcpy(dest, src, datalen); 1324cb5caa98Sdjl } 1325cb5caa98Sdjl 1326cb5caa98Sdjl /* add db specific defaults via links */ 1327cb5caa98Sdjl for (i = 0; i < _nscd_cfg_num_link_default; i++) { 1328cb5caa98Sdjl 1329cb5caa98Sdjl if (_nscd_cfg_nsw_link_default[i].data == NULL) 1330cb5caa98Sdjl continue; 1331cb5caa98Sdjl 1332cb5caa98Sdjl spc = _nscd_cfg_nsw_link_default[i].data; 1333cb5caa98Sdjl 1334cb5caa98Sdjl if (_nscd_cfg_nsw_link_default[i].db != dbni) { 1335cb5caa98Sdjl for (j = 0; j < _nscd_cfg_num_nsw_db; j++) { 1336cb5caa98Sdjl 1337cb5caa98Sdjl if (strcmp(_nscd_cfg_nsw_db[j].name, 1338cb5caa98Sdjl _nscd_cfg_nsw_link_default[i].db) != 0) 1339cb5caa98Sdjl continue; 1340cb5caa98Sdjl 1341cb5caa98Sdjl dbi = _nscd_cfg_nsw_db[j].index; 1342cb5caa98Sdjl dbni = _nscd_cfg_nsw_db[j].name; 1343cb5caa98Sdjl break; 1344cb5caa98Sdjl } 1345cb5caa98Sdjl } 1346cb5caa98Sdjl 1347cb5caa98Sdjl dest = (char *)&nscd_cfg_nsw_db_data_current[dbi] + 1348cb5caa98Sdjl _nscd_cfg_nsw_link_default[i].group_off + 1349cb5caa98Sdjl _nscd_cfg_nsw_link_default[i].param_off; 1350cb5caa98Sdjl 1351cb5caa98Sdjl if (_nscd_cfg_nsw_db[j].name != dbnj) { 1352cb5caa98Sdjl for (j = 0; j < _nscd_cfg_num_nsw_db; j++) { 1353cb5caa98Sdjl 1354cb5caa98Sdjl if (strcmp(spc->db, 1355cb5caa98Sdjl _nscd_cfg_nsw_db[j].name) != 0) 1356cb5caa98Sdjl continue; 1357cb5caa98Sdjl 1358cb5caa98Sdjl dbnj = _nscd_cfg_nsw_db[j].name; 1359cb5caa98Sdjl dbj = _nscd_cfg_nsw_db[j].index; 1360cb5caa98Sdjl break; 1361cb5caa98Sdjl } 1362cb5caa98Sdjl } 1363cb5caa98Sdjl 1364cb5caa98Sdjl src = (char *)&nscd_cfg_nsw_db_data_current[dbj] + 1365cb5caa98Sdjl spc->group_off + spc->param_off; 1366cb5caa98Sdjl datalen = spc->data_len; 1367cb5caa98Sdjl 1368cb5caa98Sdjl (void) memcpy(dest, src, datalen); 1369cb5caa98Sdjl } 1370cb5caa98Sdjl 1371cb5caa98Sdjl /* fix up variable length fields */ 1372cb5caa98Sdjl for (i = 0; i < _nscd_cfg_num_nsw_db; i++) { 1373cb5caa98Sdjl 1374cb5caa98Sdjl rc = _nscd_cfg_set_vlen_data_int( 1375cb5caa98Sdjl &nscd_cfg_nsw_db_data_current[i], 1376cb5caa98Sdjl &nscd_cfg_nsw_db_data_current[i], nscd_false); 1377cb5caa98Sdjl if (rc != NSCD_SUCCESS) 1378cb5caa98Sdjl return (rc); 1379cb5caa98Sdjl } 1380cb5caa98Sdjl 1381cb5caa98Sdjl nscd_cfg_nsw_alldb_rwlock = calloc(1, sizeof (rwlock_t)); 1382cb5caa98Sdjl if (nscd_cfg_nsw_alldb_rwlock == NULL) 1383cb5caa98Sdjl return (NSCD_NO_MEMORY); 1384cb5caa98Sdjl 1385cb5caa98Sdjl (void) rwlock_init(nscd_cfg_nsw_alldb_rwlock, NULL, NULL); 1386cb5caa98Sdjl 1387cb5caa98Sdjl rc = _nscd_cfg_set_vlen_data_int( 1388cb5caa98Sdjl &nscd_cfg_nsw_db_data_default, 1389e37190e5Smichen nscd_cfg_nsw_alldb_current, nscd_false); 1390cb5caa98Sdjl if (rc != NSCD_SUCCESS) 1391cb5caa98Sdjl return (rc); 1392cb5caa98Sdjl 1393cb5caa98Sdjl /* 1394cb5caa98Sdjl * notify and send the configuration data to 1395cb5caa98Sdjl * the nscd components 1396cb5caa98Sdjl */ 1397cb5caa98Sdjl rc = _nscd_cfg_notify_init(errorp); 1398cb5caa98Sdjl if (rc != NSCD_SUCCESS) 1399cb5caa98Sdjl return (rc); 1400cb5caa98Sdjl 1401cb5caa98Sdjl return (NSCD_SUCCESS); 1402cb5caa98Sdjl } 1403cb5caa98Sdjl 1404cb5caa98Sdjl static nscd_rc_t 1405cb5caa98Sdjl _nscd_cfg_get_handle_common( 1406cb5caa98Sdjl nscd_cfg_list_type_t type, 1407cb5caa98Sdjl char *name, 1408cb5caa98Sdjl char *nswdb_name, 1409cb5caa98Sdjl nscd_cfg_handle_t **handle, 1410cb5caa98Sdjl nscd_cfg_error_t **errorp) 1411cb5caa98Sdjl { 1412cb5caa98Sdjl 1413cb5caa98Sdjl int i, is_global; 1414cb5caa98Sdjl char *desc_str; 1415cb5caa98Sdjl nscd_cfg_handle_t *h; 1416cb5caa98Sdjl nscd_cfg_param_desc_t *pdesc; 1417cb5caa98Sdjl nscd_cfg_stat_desc_t *sdesc; 1418cb5caa98Sdjl char *me = "_nscd_cfg_get_handle_common"; 1419cb5caa98Sdjl char msg[NSCD_CFG_MAX_ERR_MSG_LEN]; 1420cb5caa98Sdjl nscd_rc_t rc = NSCD_INVALID_ARGUMENT; 1421cb5caa98Sdjl 1422cb5caa98Sdjl if (handle == NULL) { 1423cb5caa98Sdjl 1424cb5caa98Sdjl (void) snprintf(msg, sizeof (msg), 1425cb5caa98Sdjl gettext("address of handle not specified")); 1426cb5caa98Sdjl if (errorp) 1427cb5caa98Sdjl *errorp = _nscd_cfg_make_error(rc, msg); 1428cb5caa98Sdjl 1429cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 1430cb5caa98Sdjl (me, "invalid argument: %s\n", msg); 1431cb5caa98Sdjl 1432cb5caa98Sdjl return (rc); 1433cb5caa98Sdjl } 1434cb5caa98Sdjl 1435cb5caa98Sdjl *handle = NULL; 1436cb5caa98Sdjl 1437cb5caa98Sdjl if (name == NULL) { 1438cb5caa98Sdjl 1439cb5caa98Sdjl (void) snprintf(msg, sizeof (msg), 1440cb5caa98Sdjl gettext("name not specified")); 1441cb5caa98Sdjl if (errorp) 1442cb5caa98Sdjl *errorp = _nscd_cfg_make_error(rc, msg); 1443cb5caa98Sdjl 1444cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 1445cb5caa98Sdjl (me, "invalid argument: %s\n"); 1446cb5caa98Sdjl 1447cb5caa98Sdjl return (rc); 1448cb5caa98Sdjl } 1449cb5caa98Sdjl 1450cb5caa98Sdjl h = calloc(1, sizeof (nscd_cfg_handle_t)); 1451cb5caa98Sdjl if (h == NULL) 1452cb5caa98Sdjl return (NSCD_NO_MEMORY); 1453cb5caa98Sdjl h->type = type; 1454cb5caa98Sdjl 1455cb5caa98Sdjl if (type == NSCD_CFG_LIST_PARAM) 1456cb5caa98Sdjl desc_str = gettext("configuration parameter"); 1457cb5caa98Sdjl else 1458cb5caa98Sdjl desc_str = gettext("statistics"); 1459cb5caa98Sdjl 1460cb5caa98Sdjl /* get param or stat descriptor */ 1461cb5caa98Sdjl i = _nscd_cfg_get_index(name, type); 1462cb5caa98Sdjl if (i != -1) { 1463cb5caa98Sdjl 1464cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 1465cb5caa98Sdjl (me, "%s: index of %s is %d\n", desc_str, name, i); 1466cb5caa98Sdjl 1467cb5caa98Sdjl if (type == NSCD_CFG_LIST_PARAM) { 1468cb5caa98Sdjl pdesc = &_nscd_cfg_param_desc[i]; 1469cb5caa98Sdjl (void) memcpy(&h->desc, &pdesc, sizeof (pdesc)); 1470cb5caa98Sdjl is_global = _nscd_cfg_flag_is_set( 1471cb5caa98Sdjl pdesc->pflag, NSCD_CFG_PFLAG_GLOBAL); 1472cb5caa98Sdjl 1473cb5caa98Sdjl /* hidden params are not exposed */ 1474cb5caa98Sdjl if (_nscd_cfg_flag_is_set( 1475cb5caa98Sdjl pdesc->pflag, NSCD_CFG_PFLAG_HIDDEN)) 1476cb5caa98Sdjl i = -1; 1477cb5caa98Sdjl 1478cb5caa98Sdjl if (_nscd_cfg_flag_is_set(pdesc->pflag, 1479cb5caa98Sdjl NSCD_CFG_PFLAG_OBSOLETE)) { 1480cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, 1481cb5caa98Sdjl NSCD_LOG_LEVEL_WARNING) 14828ea0afb9SMichen Chang (me, gettext("%s: %s is obsolete and " 14838ea0afb9SMichen Chang "will be ignored\n"), 1484cb5caa98Sdjl desc_str, name); 1485cb5caa98Sdjl } 1486cb5caa98Sdjl } else { 1487cb5caa98Sdjl sdesc = &_nscd_cfg_stat_desc[i]; 1488cb5caa98Sdjl (void) memcpy(&h->desc, &sdesc, sizeof (sdesc)); 1489cb5caa98Sdjl is_global = _nscd_cfg_flag_is_set( 1490cb5caa98Sdjl sdesc->sflag, NSCD_CFG_SFLAG_GLOBAL); 1491cb5caa98Sdjl } 1492cb5caa98Sdjl } 1493cb5caa98Sdjl 1494cb5caa98Sdjl if (i == -1) { 1495cb5caa98Sdjl 1496cb5caa98Sdjl (void) snprintf(msg, sizeof (msg), 1497cb5caa98Sdjl gettext("%s: unknown name \"%s\""), desc_str, name); 1498cb5caa98Sdjl if (errorp) 1499cb5caa98Sdjl *errorp = _nscd_cfg_make_error(rc, msg); 1500cb5caa98Sdjl 1501cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 1502cb5caa98Sdjl (me, "%s\n", msg); 1503cb5caa98Sdjl 1504cb5caa98Sdjl free(h); 1505cb5caa98Sdjl return (rc); 1506cb5caa98Sdjl } 1507cb5caa98Sdjl 1508cb5caa98Sdjl /* 1509cb5caa98Sdjl * if the param/stat is not a global one, we need to 1510cb5caa98Sdjl * know which nsswitch database we are dealing with 1511cb5caa98Sdjl */ 1512cb5caa98Sdjl if (is_global == 0) { 1513cb5caa98Sdjl if (nswdb_name == NULL) { 1514cb5caa98Sdjl 1515cb5caa98Sdjl (void) snprintf(msg, sizeof (msg), 1516cb5caa98Sdjl gettext("%s: switch database name not specified"), 1517cb5caa98Sdjl desc_str); 1518cb5caa98Sdjl if (errorp) 1519cb5caa98Sdjl *errorp = _nscd_cfg_make_error(rc, msg); 1520cb5caa98Sdjl 1521cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 1522cb5caa98Sdjl (me, "%s for non-global param or stat %s\n", 1523cb5caa98Sdjl msg, name); 1524cb5caa98Sdjl 1525cb5caa98Sdjl free(h); 1526cb5caa98Sdjl return (rc); 1527cb5caa98Sdjl } 1528cb5caa98Sdjl } else { 1529cb5caa98Sdjl 1530cb5caa98Sdjl if (nswdb_name != NULL) { 1531cb5caa98Sdjl 1532cb5caa98Sdjl (void) snprintf(msg, sizeof (msg), 15338ea0afb9SMichen Chang gettext("%s: switch database specified for " 15348ea0afb9SMichen Chang "global data"), desc_str); 1535cb5caa98Sdjl if (errorp) 1536cb5caa98Sdjl *errorp = _nscd_cfg_make_error(rc, msg); 1537cb5caa98Sdjl 1538cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 1539cb5caa98Sdjl (me, "%s %s\n", msg, name); 1540cb5caa98Sdjl 1541cb5caa98Sdjl free(h); 1542cb5caa98Sdjl return (rc); 1543cb5caa98Sdjl } 1544cb5caa98Sdjl 1545cb5caa98Sdjl *handle = h; 1546cb5caa98Sdjl return (NSCD_SUCCESS); 1547cb5caa98Sdjl } 1548cb5caa98Sdjl 1549cb5caa98Sdjl /* get nsw DB id */ 1550cb5caa98Sdjl i = _nscd_cfg_get_index(nswdb_name, NSCD_CFG_LIST_NSW_DB); 1551cb5caa98Sdjl if (i != -1) { 1552cb5caa98Sdjl 1553cb5caa98Sdjl if (i == NSCD_CFG_NSW_ALLDB_INDEX) 1554cb5caa98Sdjl h->nswdb = &_nscd_cfg_nsw_alldb; 1555cb5caa98Sdjl else 1556cb5caa98Sdjl h->nswdb = &_nscd_cfg_nsw_db[i]; 1557cb5caa98Sdjl 1558cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 1559cb5caa98Sdjl (me, "%s: index of %s is %d\n", 1560cb5caa98Sdjl desc_str, nswdb_name, i); 1561cb5caa98Sdjl } else { 1562cb5caa98Sdjl 1563cb5caa98Sdjl (void) snprintf(msg, sizeof (msg), 1564cb5caa98Sdjl gettext("%s: unknown switch database name \"%s\""), 1565cb5caa98Sdjl desc_str, nswdb_name); 1566cb5caa98Sdjl if (errorp) 1567cb5caa98Sdjl *errorp = _nscd_cfg_make_error(rc, msg); 1568cb5caa98Sdjl 1569cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 1570cb5caa98Sdjl (me, "%s\n", msg); 1571cb5caa98Sdjl 1572cb5caa98Sdjl free(h); 1573cb5caa98Sdjl return (NSCD_CFG_UNSUPPORTED_SWITCH_DB); 1574cb5caa98Sdjl } 1575cb5caa98Sdjl 1576cb5caa98Sdjl *handle = h; 1577cb5caa98Sdjl 1578cb5caa98Sdjl return (NSCD_SUCCESS); 1579cb5caa98Sdjl } 1580cb5caa98Sdjl 1581cb5caa98Sdjl nscd_rc_t 1582cb5caa98Sdjl _nscd_cfg_get_handle( 1583cb5caa98Sdjl char *param_name, 1584cb5caa98Sdjl char *nswdb_name, 1585cb5caa98Sdjl nscd_cfg_handle_t **handle, 1586cb5caa98Sdjl nscd_cfg_error_t **errorp) 1587cb5caa98Sdjl { 1588cb5caa98Sdjl 1589cb5caa98Sdjl return (_nscd_cfg_get_handle_common(NSCD_CFG_LIST_PARAM, 1590cb5caa98Sdjl param_name, nswdb_name, handle, errorp)); 1591cb5caa98Sdjl } 1592cb5caa98Sdjl 1593cb5caa98Sdjl nscd_rc_t 1594cb5caa98Sdjl _nscd_cfg_get_stat_handle( 1595cb5caa98Sdjl char *stat_name, 1596cb5caa98Sdjl char *nswdb_name, 1597cb5caa98Sdjl nscd_cfg_handle_t **handle, 1598cb5caa98Sdjl nscd_cfg_error_t **errorp) 1599cb5caa98Sdjl { 1600cb5caa98Sdjl 1601cb5caa98Sdjl return (_nscd_cfg_get_handle_common(NSCD_CFG_LIST_STAT, 1602cb5caa98Sdjl stat_name, nswdb_name, handle, errorp)); 1603cb5caa98Sdjl } 1604cb5caa98Sdjl 1605cb5caa98Sdjl void 1606cb5caa98Sdjl _nscd_cfg_free_handle( 1607cb5caa98Sdjl nscd_cfg_handle_t *handle) 1608cb5caa98Sdjl { 1609cb5caa98Sdjl 1610cb5caa98Sdjl free(handle); 1611cb5caa98Sdjl 1612cb5caa98Sdjl } 1613cb5caa98Sdjl 1614cb5caa98Sdjl static void 1615cb5caa98Sdjl _nscd_cfg_free_vlen_data_group( 1616cb5caa98Sdjl nscd_cfg_param_desc_t *gdesc, 1617cb5caa98Sdjl void *group_data, 1618cb5caa98Sdjl nscd_bool_t in) 1619cb5caa98Sdjl { 1620cb5caa98Sdjl int num; 1621cb5caa98Sdjl void *dest, *ptr; 1622cb5caa98Sdjl nscd_cfg_param_desc_t *desc; 1623cb5caa98Sdjl 1624cb5caa98Sdjl desc = gdesc; 1625cb5caa98Sdjl 1626cb5caa98Sdjl num = ((nscd_cfg_group_info_t *)group_data)->num_param; 1627cb5caa98Sdjl 1628cb5caa98Sdjl while (num-- > 0) { 1629cb5caa98Sdjl 1630cb5caa98Sdjl desc++; 1631cb5caa98Sdjl 1632cb5caa98Sdjl /* skip fixed length data */ 1633cb5caa98Sdjl if (_nscd_cfg_flag_is_not_set(desc->pflag, 1634cb5caa98Sdjl NSCD_CFG_PFLAG_VLEN_DATA)) 1635cb5caa98Sdjl continue; 1636cb5caa98Sdjl 1637cb5caa98Sdjl dest = (char *)group_data + desc->p_offset; 1638cb5caa98Sdjl ptr = *(char **)dest; 1639cb5caa98Sdjl if (ptr == NULL) 1640cb5caa98Sdjl continue; 1641cb5caa98Sdjl if (in == nscd_true) 1642cb5caa98Sdjl _nscd_cfg_free_vlen_data_int(ptr); 1643cb5caa98Sdjl else 1644cb5caa98Sdjl free(ptr); 1645cb5caa98Sdjl } 1646cb5caa98Sdjl } 1647cb5caa98Sdjl 1648cb5caa98Sdjl void 1649cb5caa98Sdjl _nscd_cfg_free_param_data( 1650cb5caa98Sdjl void *data) 1651cb5caa98Sdjl { 1652cb5caa98Sdjl 1653cb5caa98Sdjl if (data == NULL) 1654cb5caa98Sdjl return; 1655cb5caa98Sdjl 1656cb5caa98Sdjl free(data); 1657cb5caa98Sdjl } 1658cb5caa98Sdjl 1659cb5caa98Sdjl void 1660cb5caa98Sdjl _nscd_cfg_free_group_data( 1661cb5caa98Sdjl nscd_cfg_handle_t *handle, 1662cb5caa98Sdjl void *data) 1663cb5caa98Sdjl { 1664cb5caa98Sdjl 1665cb5caa98Sdjl nscd_cfg_param_desc_t *desc; 1666cb5caa98Sdjl nscd_cfg_group_info_t *gi; 1667cb5caa98Sdjl 1668cb5caa98Sdjl if (handle == NULL || data == NULL) 1669cb5caa98Sdjl return; 1670cb5caa98Sdjl 1671cb5caa98Sdjl desc = _nscd_cfg_get_desc(handle); 1672cb5caa98Sdjl gi = (nscd_cfg_group_info_t *)data; 1673cb5caa98Sdjl if (desc->p_fn != gi->num_param) 1674cb5caa98Sdjl return; 1675cb5caa98Sdjl 1676cb5caa98Sdjl _nscd_cfg_free_vlen_data_group(desc, data, nscd_false); 1677cb5caa98Sdjl 1678cb5caa98Sdjl free(data); 1679cb5caa98Sdjl } 1680cb5caa98Sdjl 1681cb5caa98Sdjl void 1682cb5caa98Sdjl _nscd_cfg_free_error( 1683cb5caa98Sdjl nscd_cfg_error_t *error) 1684cb5caa98Sdjl { 1685cb5caa98Sdjl 1686cb5caa98Sdjl if (error == NULL) 1687cb5caa98Sdjl return; 1688cb5caa98Sdjl 1689cb5caa98Sdjl free(error); 1690cb5caa98Sdjl } 1691cb5caa98Sdjl 1692cb5caa98Sdjl static nscd_rc_t 1693cb5caa98Sdjl _nscd_cfg_copy_param_data( 1694cb5caa98Sdjl nscd_cfg_param_desc_t *desc, 1695cb5caa98Sdjl void *dest, 1696cb5caa98Sdjl void *pdata, 1697cb5caa98Sdjl nscd_bool_t in, 1698cb5caa98Sdjl nscd_bool_t set_addr) 1699cb5caa98Sdjl { 1700cb5caa98Sdjl 1701cb5caa98Sdjl char *me = "_nscd_cfg_copy_param_data"; 1702cb5caa98Sdjl void *tmp; 1703cb5caa98Sdjl int dlen; 1704cb5caa98Sdjl nscd_rc_t rc = NSCD_SUCCESS; 1705cb5caa98Sdjl 1706cb5caa98Sdjl if (desc == NULL || dest == NULL) { 1707cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 1708cb5caa98Sdjl (me, "input desc == %p, dest == %p\n", desc, dest); 1709cb5caa98Sdjl return (NSCD_INVALID_ARGUMENT); 1710cb5caa98Sdjl } 1711cb5caa98Sdjl 1712cb5caa98Sdjl /* fixed length data */ 1713cb5caa98Sdjl if (_nscd_cfg_flag_is_not_set(desc->pflag, 1714cb5caa98Sdjl NSCD_CFG_PFLAG_VLEN_DATA)) { 1715cb5caa98Sdjl (void) memcpy(dest, pdata, desc->p_size); 1716cb5caa98Sdjl goto done; 1717cb5caa98Sdjl } 1718cb5caa98Sdjl 1719cb5caa98Sdjl 1720cb5caa98Sdjl /* variable length data from this point on */ 1721cb5caa98Sdjl 1722cb5caa98Sdjl /* make a copy of the variable length data */ 1723cb5caa98Sdjl rc = _nscd_cfg_copy_vlen_data(pdata, &tmp, desc, &dlen, in); 1724cb5caa98Sdjl if (rc != NSCD_SUCCESS) 1725cb5caa98Sdjl goto done; 1726cb5caa98Sdjl 1727cb5caa98Sdjl if (in == nscd_true) { /* data to internal */ 1728cb5caa98Sdjl 1729cb5caa98Sdjl /* free the variable length data in the config store */ 1730cb5caa98Sdjl if (*(char **)dest != NULL) 1731cb5caa98Sdjl _nscd_cfg_free_vlen_data_int(*(char **)dest); 1732cb5caa98Sdjl } 1733cb5caa98Sdjl 1734cb5caa98Sdjl if (set_addr == nscd_true) { 1735cb5caa98Sdjl /* 1736cb5caa98Sdjl * set the addr of the vlen data 1737cb5caa98Sdjl */ 1738cb5caa98Sdjl *(char **)dest = tmp; 1739cb5caa98Sdjl } else { 1740cb5caa98Sdjl /* 1741cb5caa98Sdjl * copy the data content (not address) 1742cb5caa98Sdjl */ 1743cb5caa98Sdjl (void) memcpy(dest, tmp, dlen); 1744cb5caa98Sdjl } 1745cb5caa98Sdjl 1746cb5caa98Sdjl done: 1747cb5caa98Sdjl 1748cb5caa98Sdjl return (rc); 1749cb5caa98Sdjl } 1750cb5caa98Sdjl 1751cb5caa98Sdjl static nscd_rc_t 1752cb5caa98Sdjl _nscd_cfg_copy_group_data_in( 1753cb5caa98Sdjl nscd_cfg_param_desc_t *gdesc, 1754cb5caa98Sdjl nscd_cfg_group_info_t *gi, 1755cb5caa98Sdjl void *group_dest, 1756cb5caa98Sdjl void *group_src) 1757cb5caa98Sdjl { 1758cb5caa98Sdjl int i, num; 1759cb5caa98Sdjl nscd_cfg_param_desc_t *desc; 1760cb5caa98Sdjl void *src, *dest; 1761cb5caa98Sdjl 1762cb5caa98Sdjl i = 0; 1763cb5caa98Sdjl num = gi->num_param; 1764cb5caa98Sdjl desc = gdesc; 1765cb5caa98Sdjl 1766cb5caa98Sdjl while (num-- > 0) { 1767cb5caa98Sdjl 1768cb5caa98Sdjl desc++; 1769cb5caa98Sdjl 1770cb5caa98Sdjl /* if member not selected by bitmap, skip */ 1771cb5caa98Sdjl if (_nscd_cfg_bitmap_is_not_set(gi->bitmap, i++)) 1772cb5caa98Sdjl continue; 1773cb5caa98Sdjl 1774cb5caa98Sdjl src = (char *)group_src + desc->p_offset; 1775cb5caa98Sdjl dest = (char *)group_dest + desc->p_offset; 1776cb5caa98Sdjl 1777cb5caa98Sdjl /* 1778cb5caa98Sdjl * if variable length data, free and replace the old 1779cb5caa98Sdjl * with the new 1780cb5caa98Sdjl */ 1781cb5caa98Sdjl if (_nscd_cfg_flag_is_set(desc->pflag, 1782cb5caa98Sdjl NSCD_CFG_PFLAG_VLEN_DATA)) { 1783cb5caa98Sdjl _nscd_cfg_free_vlen_data_int(*(char **)dest); 1784cb5caa98Sdjl *(char **)dest = *(char **)src; 1785cb5caa98Sdjl *(char **)src = NULL; 1786cb5caa98Sdjl } else { 1787cb5caa98Sdjl /* 1788cb5caa98Sdjl * fixed length data, just copy it 1789cb5caa98Sdjl */ 1790cb5caa98Sdjl (void) memcpy(dest, src, desc->p_size); 1791cb5caa98Sdjl } 1792cb5caa98Sdjl } 1793cb5caa98Sdjl 1794cb5caa98Sdjl return (NSCD_SUCCESS); 1795cb5caa98Sdjl } 1796cb5caa98Sdjl 1797cb5caa98Sdjl static nscd_rc_t 1798cb5caa98Sdjl _nscd_cfg_copy_group_data_out( 1799cb5caa98Sdjl nscd_cfg_param_desc_t *gdesc, 1800cb5caa98Sdjl void *group_dest, 1801cb5caa98Sdjl void *group_src) 1802cb5caa98Sdjl { 1803cb5caa98Sdjl 1804cb5caa98Sdjl char *me = "_nscd_cfg_copy_group_data_out"; 1805cb5caa98Sdjl void *src, *dest; 1806cb5caa98Sdjl int dlen; 1807cb5caa98Sdjl int num; 1808cb5caa98Sdjl nscd_cfg_group_info_t *gi; 1809cb5caa98Sdjl nscd_rc_t rc = NSCD_SUCCESS; 1810cb5caa98Sdjl nscd_cfg_param_desc_t *desc; 1811cb5caa98Sdjl 1812cb5caa98Sdjl if (group_dest == NULL) { 1813cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 1814cb5caa98Sdjl (me, "input group_dest = NULL\n"); 1815cb5caa98Sdjl return (NSCD_INVALID_ARGUMENT); 1816cb5caa98Sdjl } 1817cb5caa98Sdjl 1818cb5caa98Sdjl gi = _nscd_cfg_get_gi(group_src); 1819cb5caa98Sdjl num = gi->num_param; 1820cb5caa98Sdjl desc = gdesc; 1821cb5caa98Sdjl 1822cb5caa98Sdjl while (num-- > 0) { 1823cb5caa98Sdjl 1824cb5caa98Sdjl desc++; 1825cb5caa98Sdjl 1826cb5caa98Sdjl dest = (char *)group_dest + desc->p_offset; 1827cb5caa98Sdjl src = (char *)group_src + desc->p_offset; 1828cb5caa98Sdjl 1829cb5caa98Sdjl /* 1830cb5caa98Sdjl * if variable length data, get the real 1831cb5caa98Sdjl * address and length of the data 1832cb5caa98Sdjl */ 1833cb5caa98Sdjl if (_nscd_cfg_flag_is_set(desc->pflag, 1834cb5caa98Sdjl NSCD_CFG_PFLAG_VLEN_DATA)) { 1835cb5caa98Sdjl src = _nscd_cfg_locate_vlen_data(src, &dlen); 1836cb5caa98Sdjl if (dlen == NULL) 1837cb5caa98Sdjl continue; 1838cb5caa98Sdjl } 1839cb5caa98Sdjl 1840cb5caa98Sdjl /* 1841cb5caa98Sdjl * The nscd_true asks _nscd_cfg_copy_param_data 1842cb5caa98Sdjl * to set addr of the vlen data in 'dest' rather 1843cb5caa98Sdjl * than copying the data content 1844cb5caa98Sdjl */ 1845cb5caa98Sdjl rc = _nscd_cfg_copy_param_data(desc, dest, src, 1846cb5caa98Sdjl nscd_false, nscd_true); 1847cb5caa98Sdjl if (rc != NSCD_SUCCESS) { 1848cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 1849cb5caa98Sdjl (me, "unable to copy param data for %s\n", 1850cb5caa98Sdjl desc->id.name); 1851cb5caa98Sdjl 1852cb5caa98Sdjl _nscd_cfg_free_vlen_data_group(gdesc, 1853cb5caa98Sdjl group_dest, nscd_false); 1854cb5caa98Sdjl 1855cb5caa98Sdjl free(group_dest); 1856cb5caa98Sdjl 1857cb5caa98Sdjl return (rc); 1858cb5caa98Sdjl } 1859cb5caa98Sdjl } 1860cb5caa98Sdjl 1861cb5caa98Sdjl /* 1862cb5caa98Sdjl * set group bitmap 1863cb5caa98Sdjl */ 1864cb5caa98Sdjl (void) memcpy(group_dest, group_src, 1865cb5caa98Sdjl sizeof (nscd_cfg_group_info_t)); 1866cb5caa98Sdjl 1867cb5caa98Sdjl return (rc); 1868cb5caa98Sdjl } 1869cb5caa98Sdjl 1870cb5caa98Sdjl 1871cb5caa98Sdjl /* 1872cb5caa98Sdjl * group_cfg is needed always; group_src may be NULL if 1873cb5caa98Sdjl * param_index not zero and pdata not NULL; group_cfg and 1874cb5caa98Sdjl * pdata should not be both non-NULL 1875cb5caa98Sdjl */ 1876cb5caa98Sdjl static nscd_rc_t 1877cb5caa98Sdjl _nscd_cfg_copy_group_data_merge( 1878cb5caa98Sdjl nscd_cfg_param_desc_t *gdesc, 1879cb5caa98Sdjl void **group_dest, 1880cb5caa98Sdjl void *group_src, 1881cb5caa98Sdjl void *group_cfg, 1882cb5caa98Sdjl int param_index, 1883cb5caa98Sdjl void *pdata) 1884cb5caa98Sdjl { 1885cb5caa98Sdjl 1886cb5caa98Sdjl char *me = "_nscd_cfg_copy_group_data_merge"; 1887cb5caa98Sdjl void *src, *dest, *tmp_dest = NULL; 1888cb5caa98Sdjl int num, i = 0; 1889cb5caa98Sdjl nscd_cfg_group_info_t *gi; 1890cb5caa98Sdjl nscd_rc_t rc = NSCD_SUCCESS; 1891cb5caa98Sdjl nscd_cfg_param_desc_t *desc; 1892cb5caa98Sdjl nscd_cfg_bitmap_t bitmap; 1893cb5caa98Sdjl 1894cb5caa98Sdjl if (group_dest == NULL) { 1895cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 1896cb5caa98Sdjl (me, "input **group_dest == NULL\n"); 1897cb5caa98Sdjl return (NSCD_INVALID_ARGUMENT); 1898cb5caa98Sdjl } 1899cb5caa98Sdjl 1900cb5caa98Sdjl if (group_cfg == NULL) { 1901cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 1902cb5caa98Sdjl (me, "input **group_cfg == NULL\n"); 1903cb5caa98Sdjl return (NSCD_INVALID_ARGUMENT); 1904cb5caa98Sdjl } 1905cb5caa98Sdjl 1906cb5caa98Sdjl if (param_index != NULL && pdata == NULL) { 1907cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 1908cb5caa98Sdjl (me, "param_index != NULL but pdata == %p\n", pdata); 1909cb5caa98Sdjl return (NSCD_INVALID_ARGUMENT); 1910cb5caa98Sdjl } 1911cb5caa98Sdjl 1912cb5caa98Sdjl tmp_dest = calloc(1, gdesc->g_size); 1913cb5caa98Sdjl if (tmp_dest == NULL) 1914cb5caa98Sdjl return (NSCD_NO_MEMORY); 1915cb5caa98Sdjl 1916cb5caa98Sdjl if (group_src != NULL) 1917cb5caa98Sdjl gi = _nscd_cfg_get_gi(group_src); 1918cb5caa98Sdjl else { 1919cb5caa98Sdjl gi = _nscd_cfg_get_gi(group_cfg); 1920cb5caa98Sdjl bitmap = NSCD_CFG_BITMAP_ZERO; 1921cb5caa98Sdjl } 1922cb5caa98Sdjl 1923cb5caa98Sdjl num = gi->num_param; 1924cb5caa98Sdjl desc = gdesc; 1925cb5caa98Sdjl 1926cb5caa98Sdjl while (num-- > 0) { 1927cb5caa98Sdjl 1928cb5caa98Sdjl desc++; 1929cb5caa98Sdjl 1930cb5caa98Sdjl dest = (char *)tmp_dest + desc->p_offset; 1931cb5caa98Sdjl 1932cb5caa98Sdjl /* 1933cb5caa98Sdjl * if member not selected by bitmap in group_src, 1934cb5caa98Sdjl * get the member data in group_cfg 1935cb5caa98Sdjl */ 1936cb5caa98Sdjl if (_nscd_cfg_bitmap_is_not_set(gi->bitmap, i++) || 1937cb5caa98Sdjl group_src == NULL) { 1938cb5caa98Sdjl src = (char *)group_cfg + desc->p_offset; 1939cb5caa98Sdjl } else 1940cb5caa98Sdjl src = (char *)group_src + desc->p_offset; 1941cb5caa98Sdjl 1942cb5caa98Sdjl if (desc->id.index == param_index) { 1943cb5caa98Sdjl 1944cb5caa98Sdjl /* use the param data in pdata if provided */ 1945cb5caa98Sdjl src = pdata; 1946cb5caa98Sdjl _nscd_cfg_bitmap_set_nth(bitmap, i); 1947cb5caa98Sdjl } 1948cb5caa98Sdjl 1949cb5caa98Sdjl /* 1950cb5caa98Sdjl * if variable length data, get to the data 1951cb5caa98Sdjl * instead of pointer to the data 1952cb5caa98Sdjl */ 1953cb5caa98Sdjl if (_nscd_cfg_flag_is_set(desc->pflag, 1954cb5caa98Sdjl NSCD_CFG_PFLAG_VLEN_DATA)) 1955cb5caa98Sdjl src = *(char **)src; 1956cb5caa98Sdjl 1957cb5caa98Sdjl /* 1958cb5caa98Sdjl * nscd_true asks _nscd_cfg_copy_param_data to 1959cb5caa98Sdjl * set addr of the vlen data in 'dest' rather 1960cb5caa98Sdjl * than copying the data content 1961cb5caa98Sdjl */ 1962cb5caa98Sdjl rc = _nscd_cfg_copy_param_data(desc, dest, src, 1963cb5caa98Sdjl nscd_true, nscd_true); 1964cb5caa98Sdjl if (rc != NSCD_SUCCESS) { 1965cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 1966cb5caa98Sdjl (me, "unable to copy param data for %s\n", 1967cb5caa98Sdjl desc->id.name); 1968cb5caa98Sdjl 1969cb5caa98Sdjl _nscd_cfg_free_vlen_data_group(gdesc, 1970cb5caa98Sdjl tmp_dest, nscd_true); 1971cb5caa98Sdjl 1972cb5caa98Sdjl free(tmp_dest); 1973cb5caa98Sdjl 1974cb5caa98Sdjl return (rc); 1975cb5caa98Sdjl } 1976cb5caa98Sdjl } 1977cb5caa98Sdjl 1978cb5caa98Sdjl *group_dest = tmp_dest; 1979cb5caa98Sdjl 1980cb5caa98Sdjl /* 1981cb5caa98Sdjl * set bitmap: if input is group data, use the one 1982cb5caa98Sdjl * given; if input is param data, use the one computed 1983cb5caa98Sdjl * above 1984cb5caa98Sdjl */ 1985cb5caa98Sdjl if (group_src != NULL) 1986cb5caa98Sdjl (void) memcpy(*group_dest, group_src, 1987cb5caa98Sdjl sizeof (nscd_cfg_group_info_t)); 1988cb5caa98Sdjl else { 1989cb5caa98Sdjl gi = _nscd_cfg_get_gi(*group_dest); 1990cb5caa98Sdjl _nscd_cfg_bitmap_set(&gi->bitmap, bitmap); 1991cb5caa98Sdjl } 1992cb5caa98Sdjl 1993cb5caa98Sdjl return (rc); 1994cb5caa98Sdjl } 1995cb5caa98Sdjl 1996cb5caa98Sdjl /* ARGSUSED */ 1997cb5caa98Sdjl nscd_rc_t 1998cb5caa98Sdjl _nscd_cfg_get( 1999cb5caa98Sdjl nscd_cfg_handle_t *handle, 2000cb5caa98Sdjl void **data, 2001cb5caa98Sdjl int *data_len, 2002cb5caa98Sdjl nscd_cfg_error_t **errorp) 2003cb5caa98Sdjl { 2004cb5caa98Sdjl char *me = "_nscd_cfg_get"; 2005cb5caa98Sdjl int dlen; 2006cb5caa98Sdjl nscd_rc_t rc = NSCD_SUCCESS; 2007cb5caa98Sdjl nscd_cfg_id_t *nswdb; 2008cb5caa98Sdjl nscd_cfg_param_desc_t *desc; 2009cb5caa98Sdjl void *cfg_data, *ptr = NULL; 2010cb5caa98Sdjl nscd_bool_t get_group = nscd_false; 2011cb5caa98Sdjl nscd_bool_t out = nscd_false; 2012cb5caa98Sdjl nscd_cfg_lock_t *lock = NULL; 2013cb5caa98Sdjl 2014cb5caa98Sdjl if (data_len != NULL) 2015cb5caa98Sdjl *data_len = 0; 2016cb5caa98Sdjl 2017cb5caa98Sdjl if (data == NULL) { 2018cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2019cb5caa98Sdjl (me, "input data = %p\n", data); 2020cb5caa98Sdjl return (NSCD_INVALID_ARGUMENT); 2021cb5caa98Sdjl } 2022cb5caa98Sdjl 2023cb5caa98Sdjl *data = NULL; 2024cb5caa98Sdjl 2025cb5caa98Sdjl if (handle == NULL) { 2026cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2027cb5caa98Sdjl (me, "handle is NULL\n"); 2028cb5caa98Sdjl return (NSCD_INVALID_ARGUMENT); 2029cb5caa98Sdjl } 2030cb5caa98Sdjl 2031cb5caa98Sdjl nswdb = handle->nswdb; 2032cb5caa98Sdjl desc = (nscd_cfg_param_desc_t *)handle->desc; 2033cb5caa98Sdjl 2034cb5caa98Sdjl if (_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP)) 2035cb5caa98Sdjl get_group = nscd_true; 2036cb5caa98Sdjl 2037cb5caa98Sdjl /* 2038cb5caa98Sdjl * locate the current value of the param or group 2039cb5caa98Sdjl * and lock the config data for reading 2040cb5caa98Sdjl */ 2041cb5caa98Sdjl rc = _nscd_cfg_locate_cfg_data(&cfg_data, nscd_true, desc, 2042cb5caa98Sdjl nswdb, get_group, NULL, &dlen, &lock); 2043cb5caa98Sdjl if (rc != NSCD_SUCCESS) { 2044cb5caa98Sdjl 2045cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2046cb5caa98Sdjl (me, "unable to locate config data\n"); 2047cb5caa98Sdjl return (rc); 2048cb5caa98Sdjl 2049cb5caa98Sdjl } else if (cfg_data == NULL) /* NULL vlen data */ 2050cb5caa98Sdjl goto done; 2051cb5caa98Sdjl 2052cb5caa98Sdjl ptr = calloc(1, dlen); 2053cb5caa98Sdjl if (ptr == NULL) { 2054cb5caa98Sdjl rc = NSCD_NO_MEMORY; 2055cb5caa98Sdjl goto error_exit; 2056cb5caa98Sdjl } 2057cb5caa98Sdjl 2058cb5caa98Sdjl if (get_group == nscd_true) { 2059cb5caa98Sdjl 2060cb5caa98Sdjl rc = _nscd_cfg_copy_group_data_out(desc, ptr, cfg_data); 2061cb5caa98Sdjl if (rc != NSCD_SUCCESS) { 2062cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2063cb5caa98Sdjl (me, "unable to copy group data %p: " 2064cb5caa98Sdjl "error = %d\n", cfg_data, rc); 2065cb5caa98Sdjl 2066cb5caa98Sdjl goto error_exit; 2067cb5caa98Sdjl } 2068cb5caa98Sdjl } else { 2069cb5caa98Sdjl /* 2070cb5caa98Sdjl * nscd_false asks _nscd_cfg_copy_param_data to 2071cb5caa98Sdjl * copy the data content rather than just setting 2072cb5caa98Sdjl * the addr of the vlen data in 'ptr' 2073cb5caa98Sdjl */ 2074cb5caa98Sdjl rc = _nscd_cfg_copy_param_data(desc, ptr, cfg_data, 2075cb5caa98Sdjl out, nscd_false); 2076cb5caa98Sdjl 2077cb5caa98Sdjl if (rc != NSCD_SUCCESS) { 2078cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2079cb5caa98Sdjl (me, "unable to copy param data %p: " 2080cb5caa98Sdjl "error = %d\n", cfg_data, rc); 2081cb5caa98Sdjl 2082cb5caa98Sdjl goto error_exit; 2083cb5caa98Sdjl } 2084cb5caa98Sdjl } 2085cb5caa98Sdjl 2086cb5caa98Sdjl *data = ptr; 2087cb5caa98Sdjl 2088cb5caa98Sdjl done: 2089cb5caa98Sdjl 2090cb5caa98Sdjl if (data_len != NULL) 2091cb5caa98Sdjl *data_len = dlen; 2092cb5caa98Sdjl 2093cb5caa98Sdjl _nscd_cfg_unlock(lock); 2094cb5caa98Sdjl 2095cb5caa98Sdjl return (NSCD_SUCCESS); 2096cb5caa98Sdjl 2097cb5caa98Sdjl error_exit: 2098cb5caa98Sdjl 2099cb5caa98Sdjl _nscd_cfg_unlock(lock); 2100cb5caa98Sdjl if (ptr != NULL) 2101cb5caa98Sdjl free(ptr); 2102cb5caa98Sdjl 2103cb5caa98Sdjl return (rc); 2104cb5caa98Sdjl } 2105cb5caa98Sdjl 2106cb5caa98Sdjl /* 2107cb5caa98Sdjl * three type of data: 2108cb5caa98Sdjl * 1 - single param 2109cb5caa98Sdjl * desc is that of the param 2110cb5caa98Sdjl * 2 - single param to be sent in a group 2111cb5caa98Sdjl * a single bit is set in the bitmap, 2112cb5caa98Sdjl * desc is that of the group 2113cb5caa98Sdjl * 3 - group data 2114cb5caa98Sdjl * one of more bits are set in the bitmap, 2115cb5caa98Sdjl * desc is that of the group 2116cb5caa98Sdjl */ 2117cb5caa98Sdjl static nscd_rc_t 2118cb5caa98Sdjl _nscd_cfg_notify_s( 2119cb5caa98Sdjl nscd_cfg_param_desc_t *desc, 2120cb5caa98Sdjl nscd_cfg_id_t *nswdb, 2121cb5caa98Sdjl void *data, 2122cb5caa98Sdjl nscd_cfg_error_t **errorp) 2123cb5caa98Sdjl { 2124cb5caa98Sdjl int i, num, is_group = 0; 2125cb5caa98Sdjl void *cookie = NULL; 2126cb5caa98Sdjl void *cdata; 2127cb5caa98Sdjl nscd_rc_t rc; 2128cb5caa98Sdjl nscd_cfg_flag_t dflag, dflag1; 2129cb5caa98Sdjl nscd_cfg_bitmap_t bitmap_s, bitmap_in, *bitmap_addr = NULL; 2130cb5caa98Sdjl nscd_cfg_group_info_t *gi; 2131cb5caa98Sdjl 2132cb5caa98Sdjl if (errorp != NULL) 2133cb5caa98Sdjl *errorp = NULL; 2134cb5caa98Sdjl 2135cb5caa98Sdjl /* 2136cb5caa98Sdjl * Set data flag going with data to be sent to the 2137cb5caa98Sdjl * verify/notify routines. To allow the config flag 2138cb5caa98Sdjl * be exipandable, set the bits one by one. 2139cb5caa98Sdjl */ 2140cb5caa98Sdjl dflag = NSCD_CFG_FLAG_ZERO; 2141cb5caa98Sdjl dflag = _nscd_cfg_flag_set(dflag, NSCD_CFG_DFLAG_STATIC_DATA); 2142cb5caa98Sdjl if (_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP)) { 2143cb5caa98Sdjl dflag = _nscd_cfg_flag_set(dflag, NSCD_CFG_DFLAG_GROUP); 2144cb5caa98Sdjl is_group = 1; 2145cb5caa98Sdjl } 2146cb5caa98Sdjl if (nswdb != NULL && 2147cb5caa98Sdjl strcmp(NSCD_CFG_NSW_ALLDB, nswdb->name) == 0) 2148cb5caa98Sdjl dflag = _nscd_cfg_flag_set(dflag, 2149cb5caa98Sdjl NSCD_CFG_DFLAG_SET_ALL_DB); 2150cb5caa98Sdjl 2151cb5caa98Sdjl /* 2152cb5caa98Sdjl * the bitmap in the input data may be replaced before 2153cb5caa98Sdjl * sending to the components, so save the bitmap for 2154cb5caa98Sdjl * later use 2155cb5caa98Sdjl */ 2156cb5caa98Sdjl if (is_group == 1) { 2157cb5caa98Sdjl gi = _nscd_cfg_get_gi(data); 2158cb5caa98Sdjl bitmap_in = gi->bitmap; 2159cb5caa98Sdjl bitmap_addr = &(gi->bitmap); 2160cb5caa98Sdjl 2161cb5caa98Sdjl if (_nscd_cfg_flag_is_set(desc->pflag, 2162cb5caa98Sdjl NSCD_CFG_PFLAG_INIT_SEND_WHOLE_GROUP)) 2163cb5caa98Sdjl /* send the entire group just once */ 2164cb5caa98Sdjl num = 1; 2165cb5caa98Sdjl 2166cb5caa98Sdjl else { /* send individual members one by one */ 2167cb5caa98Sdjl 2168cb5caa98Sdjl num = desc->p_fn; 2169cb5caa98Sdjl 2170cb5caa98Sdjl /* 2171cb5caa98Sdjl * skip the first desc which is for the group 2172cb5caa98Sdjl * and get to the desc for the first member 2173cb5caa98Sdjl */ 2174cb5caa98Sdjl desc++; 2175cb5caa98Sdjl 2176cb5caa98Sdjl dflag = _nscd_cfg_flag_unset(dflag, 2177cb5caa98Sdjl NSCD_CFG_DFLAG_GROUP); 2178cb5caa98Sdjl } 2179cb5caa98Sdjl } else { 2180cb5caa98Sdjl /* not group data, send the member once */ 2181cb5caa98Sdjl num = 1; 2182cb5caa98Sdjl } 2183cb5caa98Sdjl 2184cb5caa98Sdjl dflag1 = dflag; 2185cb5caa98Sdjl for (i = 0; i < num; i++, desc++) { 2186cb5caa98Sdjl 2187cb5caa98Sdjl dflag = dflag1; 2188cb5caa98Sdjl 2189cb5caa98Sdjl if (is_group == 0) { 2190cb5caa98Sdjl cdata = data; 2191cb5caa98Sdjl goto verify_data; 2192cb5caa98Sdjl } 2193cb5caa98Sdjl 2194cb5caa98Sdjl if (_nscd_cfg_flag_is_set(desc->pflag, 2195cb5caa98Sdjl NSCD_CFG_PFLAG_SEND_BIT_SELECTED)) { 2196cb5caa98Sdjl 2197cb5caa98Sdjl /* set the bitmap to select just this member */ 2198cb5caa98Sdjl bitmap_s = NSCD_CFG_BITMAP_ZERO; 2199cb5caa98Sdjl _nscd_cfg_bitmap_set_nth(bitmap_s, i); 2200cb5caa98Sdjl /* replace the bitmap in the input data */ 2201cb5caa98Sdjl _nscd_cfg_bitmap_set(bitmap_addr, bitmap_s); 2202cb5caa98Sdjl 2203cb5caa98Sdjl /* 2204cb5caa98Sdjl * send the whole group but with only one 2205cb5caa98Sdjl * member selected 2206cb5caa98Sdjl */ 2207cb5caa98Sdjl cdata = data; 2208cb5caa98Sdjl 2209cb5caa98Sdjl dflag = _nscd_cfg_flag_set(dflag, 2210cb5caa98Sdjl NSCD_CFG_DFLAG_GROUP); 2211cb5caa98Sdjl dflag = _nscd_cfg_flag_set(dflag, 2212cb5caa98Sdjl NSCD_CFG_DFLAG_BIT_SELECTED); 2213cb5caa98Sdjl } else { 2214cb5caa98Sdjl /* 2215cb5caa98Sdjl * send param data or group data: 2216cb5caa98Sdjl * param data - non-xero desc->p_offset 2217cb5caa98Sdjl * group data - zero desc->p_offset 2218cb5caa98Sdjl */ 2219cb5caa98Sdjl cdata = (char *)data + desc->p_offset; 2220cb5caa98Sdjl 2221cb5caa98Sdjl /* 2222cb5caa98Sdjl * if variable length data, need to send pointer 2223cb5caa98Sdjl * to the data (not the address of the pointer) 2224cb5caa98Sdjl */ 2225cb5caa98Sdjl if (_nscd_cfg_flag_is_set(desc->pflag, 2226cb5caa98Sdjl NSCD_CFG_PFLAG_VLEN_DATA)) 2227cb5caa98Sdjl cdata = *(char **)cdata; 2228cb5caa98Sdjl } 2229cb5caa98Sdjl 2230cb5caa98Sdjl verify_data: 2231cb5caa98Sdjl 2232cb5caa98Sdjl if (desc->verify != NULL) { 2233cb5caa98Sdjl dflag = _nscd_cfg_flag_set(dflag, 2234cb5caa98Sdjl NSCD_CFG_DFLAG_VERIFY); 2235cb5caa98Sdjl rc = desc->verify(cdata, desc, nswdb, 2236cb5caa98Sdjl dflag, errorp, &cookie); 2237cb5caa98Sdjl if (rc != NSCD_SUCCESS) 2238cb5caa98Sdjl goto error_exit; 2239cb5caa98Sdjl } 2240cb5caa98Sdjl 2241cb5caa98Sdjl if (desc->notify != NULL) { 2242cb5caa98Sdjl dflag = _nscd_cfg_flag_set(dflag, 2243cb5caa98Sdjl NSCD_CFG_DFLAG_NOTIFY); 2244cb5caa98Sdjl 2245cb5caa98Sdjl rc = desc->notify(data, desc, nswdb, 2246cb5caa98Sdjl dflag, errorp, cookie); 2247cb5caa98Sdjl if (rc != NSCD_SUCCESS) 2248cb5caa98Sdjl goto error_exit; 2249cb5caa98Sdjl } 2250cb5caa98Sdjl } 2251cb5caa98Sdjl 2252cb5caa98Sdjl rc = NSCD_SUCCESS; 2253cb5caa98Sdjl 2254cb5caa98Sdjl error_exit: 2255cb5caa98Sdjl 2256cb5caa98Sdjl /* restore the bitmap in the input data */ 2257cb5caa98Sdjl if (bitmap_addr != NULL) 2258cb5caa98Sdjl _nscd_cfg_bitmap_set(bitmap_addr, bitmap_in); 2259cb5caa98Sdjl 2260cb5caa98Sdjl return (rc); 2261cb5caa98Sdjl } 2262cb5caa98Sdjl 2263cb5caa98Sdjl /* 2264cb5caa98Sdjl * Convert string 'str' to data based on the data type in 'desc'. 2265cb5caa98Sdjl * 'data' points to the buffer in which the converted data 2266cb5caa98Sdjl * is placed. '*data_p' points to the buffer, or in the case 2267cb5caa98Sdjl * of a string data type, points to the untoched string (i.e., 2268cb5caa98Sdjl * 'str'). 2269cb5caa98Sdjl */ 2270cb5caa98Sdjl nscd_rc_t 2271cb5caa98Sdjl _nscd_cfg_str_to_data( 2272cb5caa98Sdjl nscd_cfg_param_desc_t *desc, 2273cb5caa98Sdjl char *str, 2274cb5caa98Sdjl void *data, 2275cb5caa98Sdjl void **data_p, 2276cb5caa98Sdjl nscd_cfg_error_t **errorp) 2277cb5caa98Sdjl { 2278cb5caa98Sdjl 2279cb5caa98Sdjl char *me = "_nscd_cfg_str_to_data"; 2280cb5caa98Sdjl char *c; 2281cb5caa98Sdjl nscd_cfg_bitmap_t bitmap; 2282cb5caa98Sdjl char msg[NSCD_CFG_MAX_ERR_MSG_LEN]; 2283cb5caa98Sdjl nscd_rc_t rc = NSCD_CFG_DATA_CONVERSION_FAILED; 2284cb5caa98Sdjl 2285cb5caa98Sdjl if (desc == NULL || str == NULL || data == NULL) { 2286cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2287cb5caa98Sdjl (me, "ERROR: one of the following is NULL " 2288cb5caa98Sdjl "desc = %p, str = %p, data = %p, data_p = %p\n", 2289cb5caa98Sdjl desc, str, data, data_p); 2290cb5caa98Sdjl 2291cb5caa98Sdjl return (NSCD_INVALID_ARGUMENT); 2292cb5caa98Sdjl } 2293cb5caa98Sdjl *data_p = data; 2294cb5caa98Sdjl 2295cb5caa98Sdjl /* if description is that of a group, return error */ 2296cb5caa98Sdjl if (_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP)) { 2297cb5caa98Sdjl 2298cb5caa98Sdjl (void) snprintf(msg, sizeof (msg), 2299cb5caa98Sdjl gettext("single data specified for group %s"), desc->id.name); 2300cb5caa98Sdjl 2301cb5caa98Sdjl if (errorp != NULL) 2302cb5caa98Sdjl *errorp = _nscd_cfg_make_error(NSCD_INVALID_ARGUMENT, 2303cb5caa98Sdjl msg); 2304cb5caa98Sdjl 2305cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2306cb5caa98Sdjl (me, "ERROR: %s)\n", msg); 2307cb5caa98Sdjl 2308cb5caa98Sdjl return (NSCD_INVALID_ARGUMENT); 2309cb5caa98Sdjl 2310cb5caa98Sdjl } 2311cb5caa98Sdjl 2312cb5caa98Sdjl if (desc->type == NSCD_CFG_DATA_STRING) { 2313cb5caa98Sdjl if (strcmp(str, NSCD_NULL) == 0) 2314cb5caa98Sdjl *(char **)data_p = NULL; 2315cb5caa98Sdjl else { 2316cb5caa98Sdjl /* remove the " char if quoted string */ 2317cb5caa98Sdjl if (str[0] == '"') { 2318cb5caa98Sdjl c = str + strlen(str) - 1; 2319cb5caa98Sdjl if (*c == '"') 2320cb5caa98Sdjl *c = '\0'; 2321cb5caa98Sdjl *(char **)data_p = str + 1; 2322cb5caa98Sdjl } else 2323cb5caa98Sdjl *(char **)data_p = str; 2324cb5caa98Sdjl 2325cb5caa98Sdjl } 2326cb5caa98Sdjl return (NSCD_SUCCESS); 2327cb5caa98Sdjl } 2328cb5caa98Sdjl 2329cb5caa98Sdjl if (str == NULL) { 2330cb5caa98Sdjl 2331cb5caa98Sdjl (void) snprintf(msg, sizeof (msg), 2332cb5caa98Sdjl gettext("data must be specified for %s"), desc->id.name); 2333cb5caa98Sdjl 2334cb5caa98Sdjl if (errorp != NULL) 2335cb5caa98Sdjl *errorp = _nscd_cfg_make_error(NSCD_INVALID_ARGUMENT, 2336cb5caa98Sdjl msg); 2337cb5caa98Sdjl 2338cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2339cb5caa98Sdjl (me, "ERROR: %s\n", msg); 2340cb5caa98Sdjl 2341cb5caa98Sdjl return (NSCD_INVALID_ARGUMENT); 2342cb5caa98Sdjl 2343cb5caa98Sdjl } 2344cb5caa98Sdjl 2345cb5caa98Sdjl switch (desc->type) { 2346cb5caa98Sdjl 2347cb5caa98Sdjl case NSCD_CFG_DATA_BOOLEAN: 2348cb5caa98Sdjl 2349cb5caa98Sdjl if (strcasecmp(str, "yes") == 0) 2350cb5caa98Sdjl *(nscd_bool_t *)data = nscd_true; 2351cb5caa98Sdjl else if (strcasecmp(str, "no") == 0) 2352cb5caa98Sdjl *(nscd_bool_t *)data = nscd_false; 2353cb5caa98Sdjl else { 2354cb5caa98Sdjl 2355cb5caa98Sdjl (void) snprintf(msg, sizeof (msg), 2356cb5caa98Sdjl gettext("data (%s) must be 'yes' or 'no' for %s"), 2357cb5caa98Sdjl str, desc->id.name); 2358cb5caa98Sdjl 2359cb5caa98Sdjl if (errorp != NULL) 2360cb5caa98Sdjl *errorp = _nscd_cfg_make_error(NSCD_INVALID_ARGUMENT, 2361cb5caa98Sdjl msg); 2362cb5caa98Sdjl 2363cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2364cb5caa98Sdjl (me, "ERROR: %s\n", msg); 2365cb5caa98Sdjl 2366cb5caa98Sdjl return (NSCD_INVALID_ARGUMENT); 2367cb5caa98Sdjl } 2368cb5caa98Sdjl 2369cb5caa98Sdjl break; 2370cb5caa98Sdjl 2371cb5caa98Sdjl case NSCD_CFG_DATA_INTEGER: 2372cb5caa98Sdjl 2373cb5caa98Sdjl errno = 0; 2374cb5caa98Sdjl *(int *)data = (int)strtol(str, (char **)NULL, 10); 2375cb5caa98Sdjl if (errno != NULL) { 2376cb5caa98Sdjl 2377cb5caa98Sdjl (void) snprintf(msg, sizeof (msg), 2378cb5caa98Sdjl gettext("unable to convert data (%s) for %s"), 2379cb5caa98Sdjl str, desc->id.name); 2380cb5caa98Sdjl 2381cb5caa98Sdjl if (errorp != NULL) 2382cb5caa98Sdjl *errorp = _nscd_cfg_make_error(rc, msg); 2383cb5caa98Sdjl 2384cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2385cb5caa98Sdjl (me, "ERROR: %s\n", msg); 2386cb5caa98Sdjl 2387cb5caa98Sdjl return (rc); 2388cb5caa98Sdjl } 2389cb5caa98Sdjl 2390cb5caa98Sdjl break; 2391cb5caa98Sdjl 2392cb5caa98Sdjl case NSCD_CFG_DATA_BITMAP: 2393cb5caa98Sdjl 2394cb5caa98Sdjl errno = 0; 2395cb5caa98Sdjl bitmap = (nscd_cfg_bitmap_t)strtol(str, (char **)NULL, 10); 2396cb5caa98Sdjl if (errno != NULL) { 2397cb5caa98Sdjl 2398cb5caa98Sdjl (void) snprintf(msg, sizeof (msg), 2399cb5caa98Sdjl gettext("unable to convert data (%s) for %s"), 2400cb5caa98Sdjl str, desc->id.name); 2401cb5caa98Sdjl 2402cb5caa98Sdjl if (errorp != NULL) 2403cb5caa98Sdjl *errorp = _nscd_cfg_make_error(rc, msg); 2404cb5caa98Sdjl 2405cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2406cb5caa98Sdjl (me, "ERROR: %s\n", msg); 2407cb5caa98Sdjl 2408cb5caa98Sdjl return (rc); 2409cb5caa98Sdjl } 2410cb5caa98Sdjl 2411cb5caa98Sdjl _nscd_cfg_bitmap_set(data, bitmap); 2412cb5caa98Sdjl 2413cb5caa98Sdjl break; 2414cb5caa98Sdjl 2415cb5caa98Sdjl } 2416cb5caa98Sdjl 2417cb5caa98Sdjl return (NSCD_SUCCESS); 2418cb5caa98Sdjl } 2419cb5caa98Sdjl 2420cb5caa98Sdjl 2421cb5caa98Sdjl nscd_rc_t 2422cb5caa98Sdjl _nscd_cfg_set( 2423cb5caa98Sdjl nscd_cfg_handle_t *handle, 2424cb5caa98Sdjl void *data, 2425cb5caa98Sdjl nscd_cfg_error_t **errorp) 2426cb5caa98Sdjl { 2427cb5caa98Sdjl char *me = "_nscd_cfg_set"; 2428cb5caa98Sdjl int dlen; 2429cb5caa98Sdjl nscd_cfg_id_t *nswdb; 2430cb5caa98Sdjl nscd_cfg_param_desc_t *desc, *gdesc; 2431cb5caa98Sdjl nscd_cfg_group_info_t *gi; 2432cb5caa98Sdjl char *nswdb_name, *param_name; 2433cb5caa98Sdjl void *pdata = NULL; 2434cb5caa98Sdjl void *cfg_data, *vdata_addr = NULL; 2435cb5caa98Sdjl nscd_bool_t get_group = 0; 2436cb5caa98Sdjl nscd_bool_t in = nscd_true; 2437cb5caa98Sdjl nscd_cfg_lock_t *lock = NULL; 2438cb5caa98Sdjl nscd_rc_t rc = NSCD_SUCCESS; 2439cb5caa98Sdjl 2440cb5caa98Sdjl if (handle == NULL) { 2441cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2442cb5caa98Sdjl (me, "handle is NULL\n"); 2443cb5caa98Sdjl return (NSCD_INVALID_ARGUMENT); 2444cb5caa98Sdjl } 2445cb5caa98Sdjl 2446cb5caa98Sdjl nswdb = handle->nswdb; 2447cb5caa98Sdjl desc = (nscd_cfg_param_desc_t *)handle->desc; 2448cb5caa98Sdjl if (nswdb == NULL) 2449cb5caa98Sdjl nswdb_name = "global"; 2450cb5caa98Sdjl else 2451cb5caa98Sdjl nswdb_name = nswdb->name; 2452cb5caa98Sdjl param_name = desc->id.name; 2453cb5caa98Sdjl 2454cb5caa98Sdjl if (data == NULL && _nscd_cfg_flag_is_not_set(desc->pflag, 2455cb5caa98Sdjl NSCD_CFG_PFLAG_VLEN_DATA)) { 2456cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2457cb5caa98Sdjl (me, "data == NULL\n"); 2458cb5caa98Sdjl return (NSCD_INVALID_ARGUMENT); 2459cb5caa98Sdjl } 2460cb5caa98Sdjl 2461cb5caa98Sdjl if (_nscd_cfg_flag_is_set(desc->pflag, 2462cb5caa98Sdjl NSCD_CFG_PFLAG_UPDATE_SEND_WHOLE_GROUP) || 2463cb5caa98Sdjl _nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP)) 2464cb5caa98Sdjl get_group = nscd_true; 2465cb5caa98Sdjl 2466cb5caa98Sdjl /* 2467cb5caa98Sdjl * locate the current value of the param or group 2468cb5caa98Sdjl * and lock the config data for writing 2469cb5caa98Sdjl */ 2470cb5caa98Sdjl rc = _nscd_cfg_locate_cfg_data(&cfg_data, nscd_false, desc, 2471cb5caa98Sdjl nswdb, get_group, &vdata_addr, &dlen, &lock); 2472cb5caa98Sdjl if (rc != NSCD_SUCCESS) { 2473cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2474cb5caa98Sdjl (me, "unable to locate config data (rc = %d)\n", rc); 2475cb5caa98Sdjl return (rc); 2476cb5caa98Sdjl } 2477cb5caa98Sdjl 2478cb5caa98Sdjl if (_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP) && 2479cb5caa98Sdjl ((nscd_cfg_group_info_t *)cfg_data)->num_param != 2480cb5caa98Sdjl ((nscd_cfg_group_info_t *)data)->num_param) { 2481cb5caa98Sdjl 2482cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2483cb5caa98Sdjl (me, "number of parameters in group <%s : %s> not equal: " 2484cb5caa98Sdjl "%d in input data, should be %d\n", 2485cb5caa98Sdjl NSCD_STR_OR_GLOBAL(nswdb_name), 2486cb5caa98Sdjl NSCD_STR_OR_NULL(param_name), 2487cb5caa98Sdjl ((nscd_cfg_group_info_t *)data)->num_param, 2488cb5caa98Sdjl ((nscd_cfg_group_info_t *)cfg_data)->num_param); 2489cb5caa98Sdjl 2490cb5caa98Sdjl rc = NSCD_INVALID_ARGUMENT; 2491cb5caa98Sdjl goto error_exit; 2492cb5caa98Sdjl } 2493cb5caa98Sdjl 2494cb5caa98Sdjl /* 2495cb5caa98Sdjl * if variable length data, we want the address 2496cb5caa98Sdjl * of the pointer pointing to the data 2497cb5caa98Sdjl */ 2498cb5caa98Sdjl if (vdata_addr != NULL) 2499cb5caa98Sdjl cfg_data = vdata_addr; 2500cb5caa98Sdjl 2501cb5caa98Sdjl /* 2502cb5caa98Sdjl * just copy in the specified data, if no need 2503cb5caa98Sdjl * to verify the data or notify the associated 2504cb5caa98Sdjl * component 2505cb5caa98Sdjl */ 2506cb5caa98Sdjl if (get_group == nscd_true) { 2507cb5caa98Sdjl 2508cb5caa98Sdjl gdesc = &_nscd_cfg_param_desc[desc->g_index]; 2509cb5caa98Sdjl 2510cb5caa98Sdjl rc = _nscd_cfg_copy_group_data_merge( 2511cb5caa98Sdjl gdesc, &pdata, data, cfg_data, 2512cb5caa98Sdjl desc->id.index, data); 2513cb5caa98Sdjl 2514cb5caa98Sdjl if (rc != NSCD_SUCCESS) { 2515cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2516cb5caa98Sdjl (me, "unable to copy group data <%s : %s>\n", 2517cb5caa98Sdjl NSCD_STR_OR_GLOBAL(nswdb_name), 2518cb5caa98Sdjl NSCD_STR_OR_NULL(param_name)); 2519cb5caa98Sdjl 2520cb5caa98Sdjl goto error_exit; 2521cb5caa98Sdjl } 2522cb5caa98Sdjl 2523cb5caa98Sdjl rc = _nscd_cfg_notify_s(gdesc, nswdb, 2524cb5caa98Sdjl pdata, errorp); 2525cb5caa98Sdjl 2526cb5caa98Sdjl } else 2527cb5caa98Sdjl rc = _nscd_cfg_notify_s(desc, nswdb, data, 2528cb5caa98Sdjl errorp); 2529cb5caa98Sdjl 2530cb5caa98Sdjl if (rc != NSCD_SUCCESS) { 2531cb5caa98Sdjl 2532cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2533cb5caa98Sdjl (me, "verifying/notifying of new configuration " 2534cb5caa98Sdjl "parameter <%s : %s> failed. %s\n", 2535cb5caa98Sdjl NSCD_STR_OR_GLOBAL(nswdb_name), 2536cb5caa98Sdjl param_name, (*errorp && (*errorp)->msg) ? 2537cb5caa98Sdjl (*errorp)->msg : ""); 2538cb5caa98Sdjl 2539cb5caa98Sdjl goto error_exit; 2540cb5caa98Sdjl } 2541cb5caa98Sdjl 2542cb5caa98Sdjl /* 2543cb5caa98Sdjl * Move the new config into the config store 2544cb5caa98Sdjl */ 2545cb5caa98Sdjl rc = NSCD_CFG_SET_PARAM_FAILED; 2546cb5caa98Sdjl if (_nscd_cfg_flag_is_set(desc->pflag, 2547cb5caa98Sdjl NSCD_CFG_PFLAG_GROUP)) { 2548cb5caa98Sdjl gi = _nscd_cfg_get_gi(pdata); 2549cb5caa98Sdjl rc = _nscd_cfg_copy_group_data_in(gdesc, gi, 2550cb5caa98Sdjl cfg_data, pdata); 2551cb5caa98Sdjl } else { 2552cb5caa98Sdjl /* 2553cb5caa98Sdjl * nscd_true asks _nscd_cfg_copy_param_data to 2554cb5caa98Sdjl * set addr of the vlen data in 'cfg_data' rather 2555cb5caa98Sdjl * than copying the data content 2556cb5caa98Sdjl */ 2557cb5caa98Sdjl if (pdata != NULL) 2558cb5caa98Sdjl _nscd_cfg_free_vlen_data_group(gdesc, 2559cb5caa98Sdjl pdata, in); 2560cb5caa98Sdjl 2561cb5caa98Sdjl rc = _nscd_cfg_copy_param_data(desc, 2562cb5caa98Sdjl cfg_data, data, in, nscd_true); 2563cb5caa98Sdjl } 2564cb5caa98Sdjl 2565cb5caa98Sdjl if (rc != NSCD_SUCCESS) { 2566cb5caa98Sdjl 2567cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2568cb5caa98Sdjl (me, "unable to make new param data <%s : %s> current\n", 2569cb5caa98Sdjl NSCD_STR_OR_GLOBAL(nswdb_name), 2570cb5caa98Sdjl NSCD_STR_OR_NULL(param_name)); 2571cb5caa98Sdjl } 2572cb5caa98Sdjl 2573cb5caa98Sdjl error_exit: 2574cb5caa98Sdjl 2575cb5caa98Sdjl _nscd_cfg_unlock(lock); 2576cb5caa98Sdjl 2577cb5caa98Sdjl return (rc); 2578cb5caa98Sdjl } 2579cb5caa98Sdjl 2580cb5caa98Sdjl nscd_rc_t 2581cb5caa98Sdjl _nscd_cfg_set_linked( 2582cb5caa98Sdjl nscd_cfg_handle_t *handle, 2583cb5caa98Sdjl void *data, 2584cb5caa98Sdjl nscd_cfg_error_t **errorp) 2585cb5caa98Sdjl { 2586cb5caa98Sdjl char *me = "_nscd_cfg_set_linked"; 2587cb5caa98Sdjl nscd_cfg_id_t *nswdb; 2588cb5caa98Sdjl nscd_cfg_handle_t *hl; 2589cb5caa98Sdjl nscd_cfg_param_desc_t *desc; 2590cb5caa98Sdjl char *nswdb_name, *param_name, *dbl; 2591cb5caa98Sdjl nscd_rc_t rc = NSCD_SUCCESS; 2592cb5caa98Sdjl nscd_cfg_nsw_spc_default_t *spc; 2593cb5caa98Sdjl int i; 2594cb5caa98Sdjl char msg[NSCD_CFG_MAX_ERR_MSG_LEN]; 2595cb5caa98Sdjl 2596cb5caa98Sdjl if (handle == NULL) { 2597cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2598cb5caa98Sdjl (me, "handle is NULL\n"); 2599cb5caa98Sdjl return (NSCD_INVALID_ARGUMENT); 2600cb5caa98Sdjl } 2601cb5caa98Sdjl 2602cb5caa98Sdjl nswdb = handle->nswdb; 2603cb5caa98Sdjl desc = (nscd_cfg_param_desc_t *)handle->desc; 2604cb5caa98Sdjl 2605cb5caa98Sdjl /* 2606cb5caa98Sdjl * no need to do the special linking thing, 2607cb5caa98Sdjl * if a global param, or a group, or not a linked param 2608cb5caa98Sdjl */ 2609cb5caa98Sdjl if (nswdb == NULL || _nscd_cfg_flag_is_set(desc->pflag, 2610cb5caa98Sdjl NSCD_CFG_PFLAG_GROUP) || 2611cb5caa98Sdjl _nscd_cfg_flag_is_not_set(desc->pflag, 2612cb5caa98Sdjl NSCD_CFG_PFLAG_LINKED)) 2613cb5caa98Sdjl return (_nscd_cfg_set(handle, data, errorp)); 2614cb5caa98Sdjl else 2615cb5caa98Sdjl nswdb_name = nswdb->name; 2616cb5caa98Sdjl param_name = desc->id.name; 2617cb5caa98Sdjl 2618cb5caa98Sdjl /* 2619cb5caa98Sdjl * if a param is linked to another, it can not be 2620cb5caa98Sdjl * changed directly 2621cb5caa98Sdjl */ 2622cb5caa98Sdjl for (i = 0; i < _nscd_cfg_num_link_default; i++) { 2623cb5caa98Sdjl 2624cb5caa98Sdjl if (_nscd_cfg_nsw_link_default[i].data == NULL) 2625cb5caa98Sdjl continue; 2626cb5caa98Sdjl 2627cb5caa98Sdjl if (strcmp(_nscd_cfg_nsw_link_default[i].db, 2628cb5caa98Sdjl nswdb_name) == 0 && 2629cb5caa98Sdjl _nscd_cfg_nsw_link_default[i].group_off == 2630cb5caa98Sdjl desc->g_offset && 2631cb5caa98Sdjl _nscd_cfg_nsw_link_default[i].param_off == 2632cb5caa98Sdjl desc->p_offset) { 2633cb5caa98Sdjl 2634cb5caa98Sdjl rc = NSCD_CFG_READ_ONLY; 2635cb5caa98Sdjl 2636cb5caa98Sdjl (void) snprintf(msg, sizeof (msg), 26378ea0afb9SMichen Chang gettext("value of \'%s\' not changeable, " 26388ea0afb9SMichen Chang "change that of \'%s\' instead"), 2639cb5caa98Sdjl nswdb->name, "passwd"); 2640cb5caa98Sdjl 2641cb5caa98Sdjl if (errorp != NULL) 2642cb5caa98Sdjl *errorp = _nscd_cfg_make_error(rc, msg); 2643cb5caa98Sdjl 2644cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2645cb5caa98Sdjl (me, "ERROR: %s\n", msg); 2646cb5caa98Sdjl 2647cb5caa98Sdjl return (rc); 2648cb5caa98Sdjl } 2649cb5caa98Sdjl } 2650cb5caa98Sdjl 2651cb5caa98Sdjl /* 2652cb5caa98Sdjl * if a param is linked from another, it should be verify 2653cb5caa98Sdjl * and changed first 2654cb5caa98Sdjl */ 2655cb5caa98Sdjl for (i = 0; i < _nscd_cfg_num_link_default; i++) { 2656cb5caa98Sdjl 2657cb5caa98Sdjl if (_nscd_cfg_nsw_link_default[i].data == NULL) 2658cb5caa98Sdjl continue; 2659cb5caa98Sdjl 2660cb5caa98Sdjl spc = _nscd_cfg_nsw_link_default[i].data; 2661cb5caa98Sdjl 2662cb5caa98Sdjl if (strcmp(spc->db, nswdb_name) == 0 && 2663cb5caa98Sdjl spc->group_off == desc->g_offset && 2664cb5caa98Sdjl spc->param_off == desc->p_offset) { 2665cb5caa98Sdjl 2666cb5caa98Sdjl rc = _nscd_cfg_set(handle, data, errorp); 2667cb5caa98Sdjl if (rc != NSCD_SUCCESS) 2668cb5caa98Sdjl return (rc); 2669cb5caa98Sdjl break; 2670cb5caa98Sdjl } 2671cb5caa98Sdjl } 2672cb5caa98Sdjl 2673cb5caa98Sdjl /* 2674cb5caa98Sdjl * then change all those linked to the one that has been changed 2675cb5caa98Sdjl */ 2676cb5caa98Sdjl for (i = 0; i < _nscd_cfg_num_link_default; i++) { 2677cb5caa98Sdjl 2678cb5caa98Sdjl if (_nscd_cfg_nsw_link_default[i].data == NULL) 2679cb5caa98Sdjl continue; 2680cb5caa98Sdjl 2681cb5caa98Sdjl spc = _nscd_cfg_nsw_link_default[i].data; 2682cb5caa98Sdjl 2683cb5caa98Sdjl if (strcmp(spc->db, nswdb_name) == 0 && 2684cb5caa98Sdjl spc->group_off == desc->g_offset && 2685cb5caa98Sdjl spc->param_off == desc->p_offset && 2686cb5caa98Sdjl _nscd_cfg_nsw_link_default[i].group_off == 2687cb5caa98Sdjl desc->g_offset && 2688cb5caa98Sdjl _nscd_cfg_nsw_link_default[i].param_off == 2689cb5caa98Sdjl desc->p_offset) { 2690cb5caa98Sdjl 2691cb5caa98Sdjl dbl = _nscd_cfg_nsw_link_default[i].db; 2692cb5caa98Sdjl 2693cb5caa98Sdjl rc = _nscd_cfg_get_handle(param_name, dbl, 2694cb5caa98Sdjl &hl, errorp); 2695e37190e5Smichen if (rc != NSCD_SUCCESS) 2696e37190e5Smichen return (rc); 2697cb5caa98Sdjl rc = _nscd_cfg_set(hl, data, errorp); 2698cb5caa98Sdjl _nscd_cfg_free_handle(hl); 2699cb5caa98Sdjl if (rc != NSCD_SUCCESS) 2700cb5caa98Sdjl return (rc); 2701cb5caa98Sdjl } 2702cb5caa98Sdjl } 2703cb5caa98Sdjl 2704cb5caa98Sdjl return (_nscd_cfg_set(handle, data, errorp)); 2705cb5caa98Sdjl } 2706cb5caa98Sdjl 2707cb5caa98Sdjl /* 27088ea0afb9SMichen Chang * Return a list of comma-separated database names that 27098ea0afb9SMichen Chang * have at least one of the input sources (the srcs array) 27108ea0afb9SMichen Chang * appears in their configured nsswitch policy string. 27118ea0afb9SMichen Chang * That is, if srcs contains "ldap" and "passwd: files ldap" 27128ea0afb9SMichen Chang * "group: files ldap" are in /etc/nsswitch.conf, then 27138ea0afb9SMichen Chang * "passwd,group" will be returned. The return string 27148ea0afb9SMichen Chang * should be freed by the caller. 2715cb5caa98Sdjl * 27168ea0afb9SMichen Chang * For compat nsswitch configuration, "group" and/or 27178ea0afb9SMichen Chang * "passwd,user_attr,shadow,audit_user" (not "group_compat" 27188ea0afb9SMichen Chang * or "passwd_compat") will be returned. Note that the 27198ea0afb9SMichen Chang * user_attr, shadow, and audit_user databases share the 27208ea0afb9SMichen Chang * same policy with the passwd database. 27218ea0afb9SMichen Chang * 27228ea0afb9SMichen Chang * For example, if srcs has "ldap" and in /etc/nsswitch.conf, 27238ea0afb9SMichen Chang * there are: 27248ea0afb9SMichen Chang * passwd: compat 27258ea0afb9SMichen Chang * passwd_compat: ldap 27268ea0afb9SMichen Chang * group: compat 27278ea0afb9SMichen Chang * group_compat: ldap 27288ea0afb9SMichen Chang * netgroup: ldap 27298ea0afb9SMichen Chang * then "netgroup,passwd,group,user_attr,shadow,audit_user" 27308ea0afb9SMichen Chang * will be returned. 2731cb5caa98Sdjl */ 2732cb5caa98Sdjl char * 2733cb5caa98Sdjl _nscd_srcs_in_db_nsw_policy( 2734cb5caa98Sdjl int num_src, 2735cb5caa98Sdjl char **srcs) 2736cb5caa98Sdjl { 2737cb5caa98Sdjl uint8_t i, j, n = 0, nc = 0; 2738cb5caa98Sdjl uint8_t compat_grp = 0, compat_pwd = 0; 2739cb5caa98Sdjl uint8_t *db; 2740cb5caa98Sdjl uint8_t *db_compat; 2741cb5caa98Sdjl int dlen = 0; 2742cb5caa98Sdjl nscd_cfg_nsw_db_data_t *dbcfg; 2743cb5caa98Sdjl nscd_cfg_switch_t *sw; 2744cb5caa98Sdjl char *outstr = NULL; 2745cb5caa98Sdjl char *dbname; 2746cb5caa98Sdjl 2747cb5caa98Sdjl db = (uint8_t *)calloc(_nscd_cfg_num_nsw_db, sizeof (uint8_t)); 2748cb5caa98Sdjl if (db == NULL) 2749cb5caa98Sdjl return (NULL); 2750cb5caa98Sdjl 2751cb5caa98Sdjl db_compat = (uint8_t *)calloc(_nscd_cfg_num_nsw_db, 2752cb5caa98Sdjl sizeof (uint8_t)); 2753cb5caa98Sdjl if (db_compat == NULL) { 2754cb5caa98Sdjl free(db); 2755cb5caa98Sdjl return (NULL); 2756cb5caa98Sdjl } 2757cb5caa98Sdjl 2758cb5caa98Sdjl for (i = 0; i < _nscd_cfg_num_nsw_db; i++) { 2759cb5caa98Sdjl 2760cb5caa98Sdjl (void) rw_rdlock(&nscd_cfg_nsw_db_data_rwlock[i]); 2761cb5caa98Sdjl 2762cb5caa98Sdjl dbcfg = &nscd_cfg_nsw_db_data_current[i]; 2763cb5caa98Sdjl sw = &dbcfg->sw; 27648ea0afb9SMichen Chang if (sw->nsw_config_string == NULL) { 27658ea0afb9SMichen Chang (void) rw_unlock(&nscd_cfg_nsw_db_data_rwlock[i]); 2766cb5caa98Sdjl continue; 27678ea0afb9SMichen Chang } 2768cb5caa98Sdjl 2769cb5caa98Sdjl dbname = _nscd_cfg_nsw_db[i].name; 2770cb5caa98Sdjl for (j = 0; j < num_src; j++) { 2771cb5caa98Sdjl if (strstr(sw->nsw_config_string, srcs[j]) != 2772cb5caa98Sdjl NULL) { 2773cb5caa98Sdjl db[n++] = i; 2774cb5caa98Sdjl dlen += strlen(dbname) + 1; 2775cb5caa98Sdjl } else if (strcmp(sw->nsw_config_string, 2776cb5caa98Sdjl "compat") == 0) { 2777cb5caa98Sdjl if (strcmp(dbname, "passwd") == 0) { 2778cb5caa98Sdjl compat_pwd = 1; 2779cb5caa98Sdjl dlen += 7; 2780cb5caa98Sdjl } else if (strcmp(dbname, "group") == 0) { 2781cb5caa98Sdjl compat_grp = 1; 2782cb5caa98Sdjl dlen += 6; 2783cb5caa98Sdjl } else { 2784cb5caa98Sdjl db_compat[nc++] = i; 2785cb5caa98Sdjl dlen += strlen(dbname) + 1; 2786cb5caa98Sdjl 2787cb5caa98Sdjl } 2788cb5caa98Sdjl } 2789cb5caa98Sdjl } 2790cb5caa98Sdjl (void) rw_unlock(&nscd_cfg_nsw_db_data_rwlock[i]); 2791cb5caa98Sdjl } 2792cb5caa98Sdjl 27938ea0afb9SMichen Chang if (dlen != 0) 2794cb5caa98Sdjl outstr = (char *)calloc(1, dlen); 2795cb5caa98Sdjl if (outstr == NULL) { 2796cb5caa98Sdjl free(db_compat); 2797cb5caa98Sdjl free(db); 2798cb5caa98Sdjl return (NULL); 2799cb5caa98Sdjl } 2800cb5caa98Sdjl 2801cb5caa98Sdjl for (j = 0; j < n; j++) { 2802cb5caa98Sdjl dbname = _nscd_cfg_nsw_db[db[j]].name; 2803cb5caa98Sdjl if (strstr(dbname, "group_compat") != NULL) { 2804cb5caa98Sdjl if (compat_grp == 1) 2805cb5caa98Sdjl dbname = "group"; 2806cb5caa98Sdjl else 2807cb5caa98Sdjl continue; 2808cb5caa98Sdjl } else if (strstr(dbname, "passwd_compat") != NULL) { 2809cb5caa98Sdjl if (compat_pwd == 1) 2810cb5caa98Sdjl dbname = "passwd"; 2811cb5caa98Sdjl else 2812cb5caa98Sdjl continue; 2813cb5caa98Sdjl } 2814cb5caa98Sdjl 2815cb5caa98Sdjl (void) strlcat(outstr, dbname, dlen); 2816cb5caa98Sdjl (void) strlcat(outstr, ",", dlen); 2817cb5caa98Sdjl } 2818cb5caa98Sdjl 2819cb5caa98Sdjl for (j = 0; j < nc; j++) { 2820cb5caa98Sdjl dbname = _nscd_cfg_nsw_db[db_compat[j]].name; 2821cb5caa98Sdjl if (compat_pwd == 1) { 2822cb5caa98Sdjl (void) strlcat(outstr, dbname, dlen); 28238ea0afb9SMichen Chang (void) strlcat(outstr, ",", dlen); 2824cb5caa98Sdjl } 2825cb5caa98Sdjl } 2826cb5caa98Sdjl 28278ea0afb9SMichen Chang /* remove the last comma */ 28288ea0afb9SMichen Chang i = strlen(outstr) - 1; 28298ea0afb9SMichen Chang if (outstr[i] == ',') 28308ea0afb9SMichen Chang outstr[i] = '\0'; 28318ea0afb9SMichen Chang 2832cb5caa98Sdjl free(db); 2833cb5caa98Sdjl free(db_compat); 2834cb5caa98Sdjl return (outstr); 2835cb5caa98Sdjl 2836cb5caa98Sdjl } 2837