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