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 != NULL) 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 != NULL) 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 != NULL) 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 != NULL) 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 != NULL) 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 != NULL) 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; 1324 j++) { 1325 1326 nswdb = &_nscd_cfg_nsw_db[j]; 1327 1328 rc = _nscd_cfg_notify_i(desc, 1329 nswdb, &skip, errorp); 1330 } 1331 } 1332 } 1333 1334 if (rc != NSCD_SUCCESS) 1335 return (rc); 1336 1337 i += skip; 1338 } 1339 1340 return (NSCD_SUCCESS); 1341 } 1342 1343 nscd_rc_t 1344 _nscd_cfg_init( 1345 nscd_cfg_error_t **errorp) 1346 { 1347 1348 int i, j, datalen; 1349 int dbi = 0, dbj = 0; 1350 char *dest, *src; 1351 char *dbni = NULL, *dbnj = NULL; 1352 nscd_rc_t rc; 1353 nscd_cfg_nsw_spc_default_t *spc; 1354 1355 if (errorp != NULL) 1356 *errorp = NULL; 1357 1358 rc = _nscd_cfg_init_param(); 1359 if (rc != NSCD_SUCCESS) 1360 return (rc); 1361 1362 rc = _nscd_cfg_init_stat(); 1363 if (rc != NSCD_SUCCESS) 1364 return (rc); 1365 1366 nscd_cfg_global_current = calloc(1, 1367 sizeof (nscd_cfg_global_data_t)); 1368 if (nscd_cfg_global_current == NULL) 1369 return (NSCD_NO_MEMORY); 1370 1371 nscd_cfg_nsw_alldb_current = calloc(1, 1372 sizeof (nscd_cfg_nsw_db_data_t)); 1373 if (nscd_cfg_nsw_alldb_current == NULL) 1374 return (NSCD_NO_MEMORY); 1375 1376 nscd_cfg_nsw_db_data_current = calloc(_nscd_cfg_num_nsw_db, 1377 sizeof (nscd_cfg_nsw_db_data_t)); 1378 if (nscd_cfg_nsw_db_data_current == NULL) 1379 return (NSCD_NO_MEMORY); 1380 1381 nscd_cfg_global_rwlock = calloc(1, sizeof (rwlock_t)); 1382 if (nscd_cfg_global_rwlock == NULL) 1383 return (NSCD_NO_MEMORY); 1384 (void) rwlock_init(nscd_cfg_global_rwlock, NULL, NULL); 1385 1386 *nscd_cfg_global_current = nscd_cfg_global_default; 1387 1388 rc = _nscd_cfg_set_vlen_data_int(&nscd_cfg_global_default, 1389 nscd_cfg_global_current, nscd_true); 1390 if (rc != NSCD_SUCCESS) 1391 return (rc); 1392 1393 nscd_cfg_nsw_db_data_rwlock = calloc(_nscd_cfg_num_nsw_db, 1394 sizeof (rwlock_t)); 1395 if (nscd_cfg_nsw_db_data_rwlock == NULL) 1396 return (NSCD_NO_MEMORY); 1397 1398 /* set per switch db config to the default for all db's */ 1399 for (i = 0; i < _nscd_cfg_num_nsw_db; i++) { 1400 1401 nscd_cfg_nsw_db_data_current[i] = 1402 nscd_cfg_nsw_db_data_default; 1403 1404 (void) rwlock_init(&nscd_cfg_nsw_db_data_rwlock[i], 1405 NULL, NULL); 1406 } 1407 1408 /* add db specific defaults */ 1409 for (i = 0; i < _nscd_cfg_num_nsw_default; i++) { 1410 1411 if (_nscd_cfg_nsw_spc_default[i].data == NULL) 1412 continue; 1413 1414 if (_nscd_cfg_nsw_spc_default[i].db != dbni) { 1415 for (j = 0; j < _nscd_cfg_num_nsw_db; j++) { 1416 1417 if (strcmp(_nscd_cfg_nsw_db[j].name, 1418 _nscd_cfg_nsw_spc_default[i].db) != 0) 1419 continue; 1420 1421 dbi = _nscd_cfg_nsw_db[j].index; 1422 dbni = _nscd_cfg_nsw_db[j].name; 1423 break; 1424 } 1425 } 1426 1427 dest = (char *)&nscd_cfg_nsw_db_data_current[dbi] + 1428 _nscd_cfg_nsw_spc_default[i].group_off + 1429 _nscd_cfg_nsw_spc_default[i].param_off; 1430 1431 src = _nscd_cfg_nsw_spc_default[i].data; 1432 datalen = _nscd_cfg_nsw_spc_default[i].data_len; 1433 1434 (void) memcpy(dest, src, datalen); 1435 } 1436 1437 /* add db specific defaults via links */ 1438 for (i = 0; i < _nscd_cfg_num_link_default; i++) { 1439 1440 if (_nscd_cfg_nsw_link_default[i].data == NULL) 1441 continue; 1442 1443 spc = _nscd_cfg_nsw_link_default[i].data; 1444 1445 if (_nscd_cfg_nsw_link_default[i].db != dbni) { 1446 for (j = 0; j < _nscd_cfg_num_nsw_db; j++) { 1447 1448 if (strcmp(_nscd_cfg_nsw_db[j].name, 1449 _nscd_cfg_nsw_link_default[i].db) != 0) 1450 continue; 1451 1452 dbi = _nscd_cfg_nsw_db[j].index; 1453 dbni = _nscd_cfg_nsw_db[j].name; 1454 break; 1455 } 1456 } 1457 1458 dest = (char *)&nscd_cfg_nsw_db_data_current[dbi] + 1459 _nscd_cfg_nsw_link_default[i].group_off + 1460 _nscd_cfg_nsw_link_default[i].param_off; 1461 1462 if (_nscd_cfg_nsw_db[j].name != dbnj) { 1463 for (j = 0; j < _nscd_cfg_num_nsw_db; j++) { 1464 1465 if (strcmp(spc->db, 1466 _nscd_cfg_nsw_db[j].name) != 0) 1467 continue; 1468 1469 dbnj = _nscd_cfg_nsw_db[j].name; 1470 dbj = _nscd_cfg_nsw_db[j].index; 1471 break; 1472 } 1473 } 1474 1475 src = (char *)&nscd_cfg_nsw_db_data_current[dbj] + 1476 spc->group_off + spc->param_off; 1477 datalen = spc->data_len; 1478 1479 (void) memcpy(dest, src, datalen); 1480 } 1481 1482 /* fix up variable length fields */ 1483 for (i = 0; i < _nscd_cfg_num_nsw_db; i++) { 1484 1485 rc = _nscd_cfg_set_vlen_data_int( 1486 &nscd_cfg_nsw_db_data_current[i], 1487 &nscd_cfg_nsw_db_data_current[i], nscd_false); 1488 if (rc != NSCD_SUCCESS) 1489 return (rc); 1490 } 1491 1492 nscd_cfg_nsw_alldb_rwlock = calloc(1, sizeof (rwlock_t)); 1493 if (nscd_cfg_nsw_alldb_rwlock == NULL) 1494 return (NSCD_NO_MEMORY); 1495 1496 (void) rwlock_init(nscd_cfg_nsw_alldb_rwlock, NULL, NULL); 1497 1498 rc = _nscd_cfg_set_vlen_data_int( 1499 &nscd_cfg_nsw_db_data_default, 1500 &nscd_cfg_nsw_alldb_current, nscd_false); 1501 if (rc != NSCD_SUCCESS) 1502 return (rc); 1503 1504 /* 1505 * notify and send the configuration data to 1506 * the nscd components 1507 */ 1508 rc = _nscd_cfg_notify_init(errorp); 1509 if (rc != NSCD_SUCCESS) 1510 return (rc); 1511 1512 return (NSCD_SUCCESS); 1513 } 1514 1515 static nscd_rc_t 1516 _nscd_cfg_get_handle_common( 1517 nscd_cfg_list_type_t type, 1518 char *name, 1519 char *nswdb_name, 1520 nscd_cfg_handle_t **handle, 1521 nscd_cfg_error_t **errorp) 1522 { 1523 1524 int i, is_global; 1525 char *desc_str; 1526 nscd_cfg_handle_t *h; 1527 nscd_cfg_param_desc_t *pdesc; 1528 nscd_cfg_stat_desc_t *sdesc; 1529 char *me = "_nscd_cfg_get_handle_common"; 1530 char msg[NSCD_CFG_MAX_ERR_MSG_LEN]; 1531 nscd_rc_t rc = NSCD_INVALID_ARGUMENT; 1532 1533 if (handle == NULL) { 1534 1535 (void) snprintf(msg, sizeof (msg), 1536 gettext("address of handle not specified")); 1537 if (errorp) 1538 *errorp = _nscd_cfg_make_error(rc, msg); 1539 1540 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 1541 (me, "invalid argument: %s\n", msg); 1542 1543 return (rc); 1544 } 1545 1546 *handle = NULL; 1547 1548 if (name == NULL) { 1549 1550 (void) snprintf(msg, sizeof (msg), 1551 gettext("name not specified")); 1552 if (errorp) 1553 *errorp = _nscd_cfg_make_error(rc, msg); 1554 1555 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 1556 (me, "invalid argument: %s\n"); 1557 1558 return (rc); 1559 } 1560 1561 h = calloc(1, sizeof (nscd_cfg_handle_t)); 1562 if (h == NULL) 1563 return (NSCD_NO_MEMORY); 1564 h->type = type; 1565 1566 if (type == NSCD_CFG_LIST_PARAM) 1567 desc_str = gettext("configuration parameter"); 1568 else 1569 desc_str = gettext("statistics"); 1570 1571 /* get param or stat descriptor */ 1572 i = _nscd_cfg_get_index(name, type); 1573 if (i != -1) { 1574 1575 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 1576 (me, "%s: index of %s is %d\n", desc_str, name, i); 1577 1578 if (type == NSCD_CFG_LIST_PARAM) { 1579 pdesc = &_nscd_cfg_param_desc[i]; 1580 (void) memcpy(&h->desc, &pdesc, sizeof (pdesc)); 1581 is_global = _nscd_cfg_flag_is_set( 1582 pdesc->pflag, NSCD_CFG_PFLAG_GLOBAL); 1583 1584 /* hidden params are not exposed */ 1585 if (_nscd_cfg_flag_is_set( 1586 pdesc->pflag, NSCD_CFG_PFLAG_HIDDEN)) 1587 i = -1; 1588 1589 if (_nscd_cfg_flag_is_set(pdesc->pflag, 1590 NSCD_CFG_PFLAG_OBSOLETE)) { 1591 _NSCD_LOG(NSCD_LOG_CONFIG, 1592 NSCD_LOG_LEVEL_WARNING) 1593 (me, 1594 gettext("%s: %s is obsolete and will be ignored\n"), 1595 desc_str, name); 1596 } 1597 } else { 1598 sdesc = &_nscd_cfg_stat_desc[i]; 1599 (void) memcpy(&h->desc, &sdesc, sizeof (sdesc)); 1600 is_global = _nscd_cfg_flag_is_set( 1601 sdesc->sflag, NSCD_CFG_SFLAG_GLOBAL); 1602 } 1603 } 1604 1605 if (i == -1) { 1606 1607 (void) snprintf(msg, sizeof (msg), 1608 gettext("%s: unknown name \"%s\""), desc_str, name); 1609 if (errorp) 1610 *errorp = _nscd_cfg_make_error(rc, msg); 1611 1612 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 1613 (me, "%s\n", msg); 1614 1615 free(h); 1616 return (rc); 1617 } 1618 1619 /* 1620 * if the param/stat is not a global one, we need to 1621 * know which nsswitch database we are dealing with 1622 */ 1623 if (is_global == 0) { 1624 if (nswdb_name == NULL) { 1625 1626 (void) snprintf(msg, sizeof (msg), 1627 gettext("%s: switch database name not specified"), 1628 desc_str); 1629 if (errorp) 1630 *errorp = _nscd_cfg_make_error(rc, msg); 1631 1632 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 1633 (me, "%s for non-global param or stat %s\n", 1634 msg, name); 1635 1636 free(h); 1637 return (rc); 1638 } 1639 } else { 1640 1641 if (nswdb_name != NULL) { 1642 1643 (void) snprintf(msg, sizeof (msg), 1644 gettext("%s: switch database specified for global data"), 1645 desc_str); 1646 if (errorp) 1647 *errorp = _nscd_cfg_make_error(rc, msg); 1648 1649 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 1650 (me, "%s %s\n", msg, name); 1651 1652 free(h); 1653 return (rc); 1654 } 1655 1656 *handle = h; 1657 return (NSCD_SUCCESS); 1658 } 1659 1660 /* get nsw DB id */ 1661 i = _nscd_cfg_get_index(nswdb_name, NSCD_CFG_LIST_NSW_DB); 1662 if (i != -1) { 1663 1664 if (i == NSCD_CFG_NSW_ALLDB_INDEX) 1665 h->nswdb = &_nscd_cfg_nsw_alldb; 1666 else 1667 h->nswdb = &_nscd_cfg_nsw_db[i]; 1668 1669 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 1670 (me, "%s: index of %s is %d\n", 1671 desc_str, nswdb_name, i); 1672 } else { 1673 1674 (void) snprintf(msg, sizeof (msg), 1675 gettext("%s: unknown switch database name \"%s\""), 1676 desc_str, nswdb_name); 1677 if (errorp) 1678 *errorp = _nscd_cfg_make_error(rc, msg); 1679 1680 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 1681 (me, "%s\n", msg); 1682 1683 free(h); 1684 return (NSCD_CFG_UNSUPPORTED_SWITCH_DB); 1685 } 1686 1687 *handle = h; 1688 1689 return (NSCD_SUCCESS); 1690 } 1691 1692 nscd_rc_t 1693 _nscd_cfg_get_handle( 1694 char *param_name, 1695 char *nswdb_name, 1696 nscd_cfg_handle_t **handle, 1697 nscd_cfg_error_t **errorp) 1698 { 1699 1700 return (_nscd_cfg_get_handle_common(NSCD_CFG_LIST_PARAM, 1701 param_name, nswdb_name, handle, errorp)); 1702 } 1703 1704 nscd_rc_t 1705 _nscd_cfg_get_stat_handle( 1706 char *stat_name, 1707 char *nswdb_name, 1708 nscd_cfg_handle_t **handle, 1709 nscd_cfg_error_t **errorp) 1710 { 1711 1712 return (_nscd_cfg_get_handle_common(NSCD_CFG_LIST_STAT, 1713 stat_name, nswdb_name, handle, errorp)); 1714 } 1715 1716 void 1717 _nscd_cfg_free_handle( 1718 nscd_cfg_handle_t *handle) 1719 { 1720 1721 free(handle); 1722 1723 } 1724 1725 static void 1726 _nscd_cfg_free_vlen_data_group( 1727 nscd_cfg_param_desc_t *gdesc, 1728 void *group_data, 1729 nscd_bool_t in) 1730 { 1731 int num; 1732 void *dest, *ptr; 1733 nscd_cfg_param_desc_t *desc; 1734 1735 desc = gdesc; 1736 1737 num = ((nscd_cfg_group_info_t *)group_data)->num_param; 1738 1739 while (num-- > 0) { 1740 1741 desc++; 1742 1743 /* skip fixed length data */ 1744 if (_nscd_cfg_flag_is_not_set(desc->pflag, 1745 NSCD_CFG_PFLAG_VLEN_DATA)) 1746 continue; 1747 1748 dest = (char *)group_data + desc->p_offset; 1749 ptr = *(char **)dest; 1750 if (ptr == NULL) 1751 continue; 1752 if (in == nscd_true) 1753 _nscd_cfg_free_vlen_data_int(ptr); 1754 else 1755 free(ptr); 1756 } 1757 } 1758 1759 void 1760 _nscd_cfg_free_param_data( 1761 void *data) 1762 { 1763 1764 if (data == NULL) 1765 return; 1766 1767 free(data); 1768 } 1769 1770 void 1771 _nscd_cfg_free_group_data( 1772 nscd_cfg_handle_t *handle, 1773 void *data) 1774 { 1775 1776 nscd_cfg_param_desc_t *desc; 1777 nscd_cfg_group_info_t *gi; 1778 1779 if (handle == NULL || data == NULL) 1780 return; 1781 1782 desc = _nscd_cfg_get_desc(handle); 1783 gi = (nscd_cfg_group_info_t *)data; 1784 if (desc->p_fn != gi->num_param) 1785 return; 1786 1787 _nscd_cfg_free_vlen_data_group(desc, data, nscd_false); 1788 1789 free(data); 1790 } 1791 1792 void 1793 _nscd_cfg_free_error( 1794 nscd_cfg_error_t *error) 1795 { 1796 1797 if (error == NULL) 1798 return; 1799 1800 free(error); 1801 } 1802 1803 static nscd_rc_t 1804 _nscd_cfg_copy_param_data( 1805 nscd_cfg_param_desc_t *desc, 1806 void *dest, 1807 void *pdata, 1808 nscd_bool_t in, 1809 nscd_bool_t set_addr) 1810 { 1811 1812 char *me = "_nscd_cfg_copy_param_data"; 1813 void *tmp; 1814 int dlen; 1815 nscd_rc_t rc = NSCD_SUCCESS; 1816 1817 if (desc == NULL || dest == NULL) { 1818 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 1819 (me, "input desc == %p, dest == %p\n", desc, dest); 1820 return (NSCD_INVALID_ARGUMENT); 1821 } 1822 1823 /* fixed length data */ 1824 if (_nscd_cfg_flag_is_not_set(desc->pflag, 1825 NSCD_CFG_PFLAG_VLEN_DATA)) { 1826 (void) memcpy(dest, pdata, desc->p_size); 1827 goto done; 1828 } 1829 1830 1831 /* variable length data from this point on */ 1832 1833 /* make a copy of the variable length data */ 1834 rc = _nscd_cfg_copy_vlen_data(pdata, &tmp, desc, &dlen, in); 1835 if (rc != NSCD_SUCCESS) 1836 goto done; 1837 1838 if (in == nscd_true) { /* data to internal */ 1839 1840 /* free the variable length data in the config store */ 1841 if (*(char **)dest != NULL) 1842 _nscd_cfg_free_vlen_data_int(*(char **)dest); 1843 } 1844 1845 if (set_addr == nscd_true) { 1846 /* 1847 * set the addr of the vlen data 1848 */ 1849 *(char **)dest = tmp; 1850 } else { 1851 /* 1852 * copy the data content (not address) 1853 */ 1854 (void) memcpy(dest, tmp, dlen); 1855 } 1856 1857 done: 1858 1859 return (rc); 1860 } 1861 1862 static nscd_rc_t 1863 _nscd_cfg_copy_group_data_in( 1864 nscd_cfg_param_desc_t *gdesc, 1865 nscd_cfg_group_info_t *gi, 1866 void *group_dest, 1867 void *group_src) 1868 { 1869 int i, num; 1870 nscd_cfg_param_desc_t *desc; 1871 void *src, *dest; 1872 1873 i = 0; 1874 num = gi->num_param; 1875 desc = gdesc; 1876 1877 while (num-- > 0) { 1878 1879 desc++; 1880 1881 /* if member not selected by bitmap, skip */ 1882 if (_nscd_cfg_bitmap_is_not_set(gi->bitmap, i++)) 1883 continue; 1884 1885 src = (char *)group_src + desc->p_offset; 1886 dest = (char *)group_dest + desc->p_offset; 1887 1888 /* 1889 * if variable length data, free and replace the old 1890 * with the new 1891 */ 1892 if (_nscd_cfg_flag_is_set(desc->pflag, 1893 NSCD_CFG_PFLAG_VLEN_DATA)) { 1894 _nscd_cfg_free_vlen_data_int(*(char **)dest); 1895 *(char **)dest = *(char **)src; 1896 *(char **)src = NULL; 1897 } else { 1898 /* 1899 * fixed length data, just copy it 1900 */ 1901 (void) memcpy(dest, src, desc->p_size); 1902 } 1903 } 1904 1905 return (NSCD_SUCCESS); 1906 } 1907 1908 static nscd_rc_t 1909 _nscd_cfg_copy_group_data_out( 1910 nscd_cfg_param_desc_t *gdesc, 1911 void *group_dest, 1912 void *group_src) 1913 { 1914 1915 char *me = "_nscd_cfg_copy_group_data_out"; 1916 void *src, *dest; 1917 int dlen; 1918 int num; 1919 nscd_cfg_group_info_t *gi; 1920 nscd_rc_t rc = NSCD_SUCCESS; 1921 nscd_cfg_param_desc_t *desc; 1922 1923 if (group_dest == NULL) { 1924 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 1925 (me, "input group_dest = NULL\n"); 1926 return (NSCD_INVALID_ARGUMENT); 1927 } 1928 1929 gi = _nscd_cfg_get_gi(group_src); 1930 num = gi->num_param; 1931 desc = gdesc; 1932 1933 while (num-- > 0) { 1934 1935 desc++; 1936 1937 dest = (char *)group_dest + desc->p_offset; 1938 src = (char *)group_src + desc->p_offset; 1939 1940 /* 1941 * if variable length data, get the real 1942 * address and length of the data 1943 */ 1944 if (_nscd_cfg_flag_is_set(desc->pflag, 1945 NSCD_CFG_PFLAG_VLEN_DATA)) { 1946 src = _nscd_cfg_locate_vlen_data(src, &dlen); 1947 if (dlen == NULL) 1948 continue; 1949 } 1950 1951 /* 1952 * The nscd_true asks _nscd_cfg_copy_param_data 1953 * to set addr of the vlen data in 'dest' rather 1954 * than copying the data content 1955 */ 1956 rc = _nscd_cfg_copy_param_data(desc, dest, src, 1957 nscd_false, nscd_true); 1958 if (rc != NSCD_SUCCESS) { 1959 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 1960 (me, "unable to copy param data for %s\n", 1961 desc->id.name); 1962 1963 _nscd_cfg_free_vlen_data_group(gdesc, 1964 group_dest, nscd_false); 1965 1966 free(group_dest); 1967 1968 return (rc); 1969 } 1970 } 1971 1972 /* 1973 * set group bitmap 1974 */ 1975 (void) memcpy(group_dest, group_src, 1976 sizeof (nscd_cfg_group_info_t)); 1977 1978 return (rc); 1979 } 1980 1981 1982 /* 1983 * group_cfg is needed always; group_src may be NULL if 1984 * param_index not zero and pdata not NULL; group_cfg and 1985 * pdata should not be both non-NULL 1986 */ 1987 static nscd_rc_t 1988 _nscd_cfg_copy_group_data_merge( 1989 nscd_cfg_param_desc_t *gdesc, 1990 void **group_dest, 1991 void *group_src, 1992 void *group_cfg, 1993 int param_index, 1994 void *pdata) 1995 { 1996 1997 char *me = "_nscd_cfg_copy_group_data_merge"; 1998 void *src, *dest, *tmp_dest = NULL; 1999 int num, i = 0; 2000 nscd_cfg_group_info_t *gi; 2001 nscd_rc_t rc = NSCD_SUCCESS; 2002 nscd_cfg_param_desc_t *desc; 2003 nscd_cfg_bitmap_t bitmap; 2004 2005 if (group_dest == NULL) { 2006 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2007 (me, "input **group_dest == NULL\n"); 2008 return (NSCD_INVALID_ARGUMENT); 2009 } 2010 2011 if (group_cfg == NULL) { 2012 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2013 (me, "input **group_cfg == NULL\n"); 2014 return (NSCD_INVALID_ARGUMENT); 2015 } 2016 2017 if (param_index != NULL && pdata == NULL) { 2018 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2019 (me, "param_index != NULL but pdata == %p\n", pdata); 2020 return (NSCD_INVALID_ARGUMENT); 2021 } 2022 2023 tmp_dest = calloc(1, gdesc->g_size); 2024 if (tmp_dest == NULL) 2025 return (NSCD_NO_MEMORY); 2026 2027 if (group_src != NULL) 2028 gi = _nscd_cfg_get_gi(group_src); 2029 else { 2030 gi = _nscd_cfg_get_gi(group_cfg); 2031 bitmap = NSCD_CFG_BITMAP_ZERO; 2032 } 2033 2034 num = gi->num_param; 2035 desc = gdesc; 2036 2037 while (num-- > 0) { 2038 2039 desc++; 2040 2041 dest = (char *)tmp_dest + desc->p_offset; 2042 2043 /* 2044 * if member not selected by bitmap in group_src, 2045 * get the member data in group_cfg 2046 */ 2047 if (_nscd_cfg_bitmap_is_not_set(gi->bitmap, i++) || 2048 group_src == NULL) { 2049 src = (char *)group_cfg + desc->p_offset; 2050 } else 2051 src = (char *)group_src + desc->p_offset; 2052 2053 if (desc->id.index == param_index) { 2054 2055 /* use the param data in pdata if provided */ 2056 src = pdata; 2057 _nscd_cfg_bitmap_set_nth(bitmap, i); 2058 } 2059 2060 /* 2061 * if variable length data, get to the data 2062 * instead of pointer to the data 2063 */ 2064 if (_nscd_cfg_flag_is_set(desc->pflag, 2065 NSCD_CFG_PFLAG_VLEN_DATA)) 2066 src = *(char **)src; 2067 2068 /* 2069 * nscd_true asks _nscd_cfg_copy_param_data to 2070 * set addr of the vlen data in 'dest' rather 2071 * than copying the data content 2072 */ 2073 rc = _nscd_cfg_copy_param_data(desc, dest, src, 2074 nscd_true, nscd_true); 2075 if (rc != NSCD_SUCCESS) { 2076 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2077 (me, "unable to copy param data for %s\n", 2078 desc->id.name); 2079 2080 _nscd_cfg_free_vlen_data_group(gdesc, 2081 tmp_dest, nscd_true); 2082 2083 free(tmp_dest); 2084 2085 return (rc); 2086 } 2087 } 2088 2089 *group_dest = tmp_dest; 2090 2091 /* 2092 * set bitmap: if input is group data, use the one 2093 * given; if input is param data, use the one computed 2094 * above 2095 */ 2096 if (group_src != NULL) 2097 (void) memcpy(*group_dest, group_src, 2098 sizeof (nscd_cfg_group_info_t)); 2099 else { 2100 gi = _nscd_cfg_get_gi(*group_dest); 2101 _nscd_cfg_bitmap_set(&gi->bitmap, bitmap); 2102 } 2103 2104 return (rc); 2105 } 2106 2107 /* ARGSUSED */ 2108 nscd_rc_t 2109 _nscd_cfg_get( 2110 nscd_cfg_handle_t *handle, 2111 void **data, 2112 int *data_len, 2113 nscd_cfg_error_t **errorp) 2114 { 2115 char *me = "_nscd_cfg_get"; 2116 int dlen; 2117 nscd_rc_t rc = NSCD_SUCCESS; 2118 nscd_cfg_id_t *nswdb; 2119 nscd_cfg_param_desc_t *desc; 2120 void *cfg_data, *ptr = NULL; 2121 nscd_bool_t get_group = nscd_false; 2122 nscd_bool_t out = nscd_false; 2123 nscd_cfg_lock_t *lock = NULL; 2124 2125 if (data_len != NULL) 2126 *data_len = 0; 2127 2128 if (data == NULL) { 2129 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2130 (me, "input data = %p\n", data); 2131 return (NSCD_INVALID_ARGUMENT); 2132 } 2133 2134 *data = NULL; 2135 2136 if (handle == NULL) { 2137 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2138 (me, "handle is NULL\n"); 2139 return (NSCD_INVALID_ARGUMENT); 2140 } 2141 2142 nswdb = handle->nswdb; 2143 desc = (nscd_cfg_param_desc_t *)handle->desc; 2144 2145 if (_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP)) 2146 get_group = nscd_true; 2147 2148 /* 2149 * locate the current value of the param or group 2150 * and lock the config data for reading 2151 */ 2152 rc = _nscd_cfg_locate_cfg_data(&cfg_data, nscd_true, desc, 2153 nswdb, get_group, NULL, &dlen, &lock); 2154 if (rc != NSCD_SUCCESS) { 2155 2156 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2157 (me, "unable to locate config data\n"); 2158 return (rc); 2159 2160 } else if (cfg_data == NULL) /* NULL vlen data */ 2161 goto done; 2162 2163 ptr = calloc(1, dlen); 2164 if (ptr == NULL) { 2165 rc = NSCD_NO_MEMORY; 2166 goto error_exit; 2167 } 2168 2169 if (get_group == nscd_true) { 2170 2171 rc = _nscd_cfg_copy_group_data_out(desc, ptr, cfg_data); 2172 if (rc != NSCD_SUCCESS) { 2173 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2174 (me, "unable to copy group data %p: " 2175 "error = %d\n", cfg_data, rc); 2176 2177 goto error_exit; 2178 } 2179 } else { 2180 /* 2181 * nscd_false asks _nscd_cfg_copy_param_data to 2182 * copy the data content rather than just setting 2183 * the addr of the vlen data in 'ptr' 2184 */ 2185 rc = _nscd_cfg_copy_param_data(desc, ptr, cfg_data, 2186 out, nscd_false); 2187 2188 if (rc != NSCD_SUCCESS) { 2189 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2190 (me, "unable to copy param data %p: " 2191 "error = %d\n", cfg_data, rc); 2192 2193 goto error_exit; 2194 } 2195 } 2196 2197 *data = ptr; 2198 2199 done: 2200 2201 if (data_len != NULL) 2202 *data_len = dlen; 2203 2204 _nscd_cfg_unlock(lock); 2205 2206 return (NSCD_SUCCESS); 2207 2208 error_exit: 2209 2210 _nscd_cfg_unlock(lock); 2211 if (ptr != NULL) 2212 free(ptr); 2213 2214 return (rc); 2215 } 2216 2217 /* 2218 * three type of data: 2219 * 1 - single param 2220 * desc is that of the param 2221 * 2 - single param to be sent in a group 2222 * a single bit is set in the bitmap, 2223 * desc is that of the group 2224 * 3 - group data 2225 * one of more bits are set in the bitmap, 2226 * desc is that of the group 2227 */ 2228 static nscd_rc_t 2229 _nscd_cfg_notify_s( 2230 nscd_cfg_param_desc_t *desc, 2231 nscd_cfg_id_t *nswdb, 2232 void *data, 2233 nscd_cfg_error_t **errorp) 2234 { 2235 int i, num, is_group = 0; 2236 void *cookie = NULL; 2237 void *cdata; 2238 nscd_rc_t rc; 2239 nscd_cfg_flag_t dflag, dflag1; 2240 nscd_cfg_bitmap_t bitmap_s, bitmap_in, *bitmap_addr = NULL; 2241 nscd_cfg_group_info_t *gi; 2242 2243 if (errorp != NULL) 2244 *errorp = NULL; 2245 2246 /* 2247 * Set data flag going with data to be sent to the 2248 * verify/notify routines. To allow the config flag 2249 * be exipandable, set the bits one by one. 2250 */ 2251 dflag = NSCD_CFG_FLAG_ZERO; 2252 dflag = _nscd_cfg_flag_set(dflag, NSCD_CFG_DFLAG_STATIC_DATA); 2253 if (_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP)) { 2254 dflag = _nscd_cfg_flag_set(dflag, NSCD_CFG_DFLAG_GROUP); 2255 is_group = 1; 2256 } 2257 if (nswdb != NULL && 2258 strcmp(NSCD_CFG_NSW_ALLDB, nswdb->name) == 0) 2259 dflag = _nscd_cfg_flag_set(dflag, 2260 NSCD_CFG_DFLAG_SET_ALL_DB); 2261 2262 /* 2263 * the bitmap in the input data may be replaced before 2264 * sending to the components, so save the bitmap for 2265 * later use 2266 */ 2267 if (is_group == 1) { 2268 gi = _nscd_cfg_get_gi(data); 2269 bitmap_in = gi->bitmap; 2270 bitmap_addr = &(gi->bitmap); 2271 2272 if (_nscd_cfg_flag_is_set(desc->pflag, 2273 NSCD_CFG_PFLAG_INIT_SEND_WHOLE_GROUP)) 2274 /* send the entire group just once */ 2275 num = 1; 2276 2277 else { /* send individual members one by one */ 2278 2279 num = desc->p_fn; 2280 2281 /* 2282 * skip the first desc which is for the group 2283 * and get to the desc for the first member 2284 */ 2285 desc++; 2286 2287 dflag = _nscd_cfg_flag_unset(dflag, 2288 NSCD_CFG_DFLAG_GROUP); 2289 } 2290 } else { 2291 /* not group data, send the member once */ 2292 num = 1; 2293 } 2294 2295 dflag1 = dflag; 2296 for (i = 0; i < num; i++, desc++) { 2297 2298 dflag = dflag1; 2299 2300 if (is_group == 0) { 2301 cdata = data; 2302 goto verify_data; 2303 } 2304 2305 if (_nscd_cfg_flag_is_set(desc->pflag, 2306 NSCD_CFG_PFLAG_SEND_BIT_SELECTED)) { 2307 2308 /* set the bitmap to select just this member */ 2309 bitmap_s = NSCD_CFG_BITMAP_ZERO; 2310 _nscd_cfg_bitmap_set_nth(bitmap_s, i); 2311 /* replace the bitmap in the input data */ 2312 _nscd_cfg_bitmap_set(bitmap_addr, bitmap_s); 2313 2314 /* 2315 * send the whole group but with only one 2316 * member selected 2317 */ 2318 cdata = data; 2319 2320 dflag = _nscd_cfg_flag_set(dflag, 2321 NSCD_CFG_DFLAG_GROUP); 2322 dflag = _nscd_cfg_flag_set(dflag, 2323 NSCD_CFG_DFLAG_BIT_SELECTED); 2324 } else { 2325 /* 2326 * send param data or group data: 2327 * param data - non-xero desc->p_offset 2328 * group data - zero desc->p_offset 2329 */ 2330 cdata = (char *)data + desc->p_offset; 2331 2332 /* 2333 * if variable length data, need to send pointer 2334 * to the data (not the address of the pointer) 2335 */ 2336 if (_nscd_cfg_flag_is_set(desc->pflag, 2337 NSCD_CFG_PFLAG_VLEN_DATA)) 2338 cdata = *(char **)cdata; 2339 } 2340 2341 verify_data: 2342 2343 if (desc->verify != NULL) { 2344 dflag = _nscd_cfg_flag_set(dflag, 2345 NSCD_CFG_DFLAG_VERIFY); 2346 rc = desc->verify(cdata, desc, nswdb, 2347 dflag, errorp, &cookie); 2348 if (rc != NSCD_SUCCESS) 2349 goto error_exit; 2350 } 2351 2352 if (desc->notify != NULL) { 2353 dflag = _nscd_cfg_flag_set(dflag, 2354 NSCD_CFG_DFLAG_NOTIFY); 2355 2356 rc = desc->notify(data, desc, nswdb, 2357 dflag, errorp, cookie); 2358 if (rc != NSCD_SUCCESS) 2359 goto error_exit; 2360 } 2361 } 2362 2363 rc = NSCD_SUCCESS; 2364 2365 error_exit: 2366 2367 /* restore the bitmap in the input data */ 2368 if (bitmap_addr != NULL) 2369 _nscd_cfg_bitmap_set(bitmap_addr, bitmap_in); 2370 2371 return (rc); 2372 } 2373 2374 /* 2375 * Convert string 'str' to data based on the data type in 'desc'. 2376 * 'data' points to the buffer in which the converted data 2377 * is placed. '*data_p' points to the buffer, or in the case 2378 * of a string data type, points to the untoched string (i.e., 2379 * 'str'). 2380 */ 2381 nscd_rc_t 2382 _nscd_cfg_str_to_data( 2383 nscd_cfg_param_desc_t *desc, 2384 char *str, 2385 void *data, 2386 void **data_p, 2387 nscd_cfg_error_t **errorp) 2388 { 2389 2390 char *me = "_nscd_cfg_str_to_data"; 2391 char *c; 2392 nscd_cfg_bitmap_t bitmap; 2393 char msg[NSCD_CFG_MAX_ERR_MSG_LEN]; 2394 nscd_rc_t rc = NSCD_CFG_DATA_CONVERSION_FAILED; 2395 2396 if (desc == NULL || str == NULL || data == NULL) { 2397 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2398 (me, "ERROR: one of the following is NULL " 2399 "desc = %p, str = %p, data = %p, data_p = %p\n", 2400 desc, str, data, data_p); 2401 2402 return (NSCD_INVALID_ARGUMENT); 2403 } 2404 *data_p = data; 2405 2406 /* if description is that of a group, return error */ 2407 if (_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP)) { 2408 2409 (void) snprintf(msg, sizeof (msg), 2410 gettext("single data specified for group %s"), desc->id.name); 2411 2412 if (errorp != NULL) 2413 *errorp = _nscd_cfg_make_error(NSCD_INVALID_ARGUMENT, 2414 msg); 2415 2416 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2417 (me, "ERROR: %s)\n", msg); 2418 2419 return (NSCD_INVALID_ARGUMENT); 2420 2421 } 2422 2423 if (desc->type == NSCD_CFG_DATA_STRING) { 2424 if (strcmp(str, NSCD_NULL) == 0) 2425 *(char **)data_p = NULL; 2426 else { 2427 /* remove the " char if quoted string */ 2428 if (str[0] == '"') { 2429 c = str + strlen(str) - 1; 2430 if (*c == '"') 2431 *c = '\0'; 2432 *(char **)data_p = str + 1; 2433 } else 2434 *(char **)data_p = str; 2435 2436 } 2437 return (NSCD_SUCCESS); 2438 } 2439 2440 if (str == NULL) { 2441 2442 (void) snprintf(msg, sizeof (msg), 2443 gettext("data must be specified for %s"), desc->id.name); 2444 2445 if (errorp != NULL) 2446 *errorp = _nscd_cfg_make_error(NSCD_INVALID_ARGUMENT, 2447 msg); 2448 2449 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2450 (me, "ERROR: %s\n", msg); 2451 2452 return (NSCD_INVALID_ARGUMENT); 2453 2454 } 2455 2456 switch (desc->type) { 2457 2458 case NSCD_CFG_DATA_BOOLEAN: 2459 2460 if (strcasecmp(str, "yes") == 0) 2461 *(nscd_bool_t *)data = nscd_true; 2462 else if (strcasecmp(str, "no") == 0) 2463 *(nscd_bool_t *)data = nscd_false; 2464 else { 2465 2466 (void) snprintf(msg, sizeof (msg), 2467 gettext("data (%s) must be 'yes' or 'no' for %s"), 2468 str, desc->id.name); 2469 2470 if (errorp != NULL) 2471 *errorp = _nscd_cfg_make_error(NSCD_INVALID_ARGUMENT, 2472 msg); 2473 2474 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2475 (me, "ERROR: %s\n", msg); 2476 2477 return (NSCD_INVALID_ARGUMENT); 2478 } 2479 2480 break; 2481 2482 case NSCD_CFG_DATA_INTEGER: 2483 2484 errno = 0; 2485 *(int *)data = (int)strtol(str, (char **)NULL, 10); 2486 if (errno != NULL) { 2487 2488 (void) snprintf(msg, sizeof (msg), 2489 gettext("unable to convert data (%s) for %s"), 2490 str, desc->id.name); 2491 2492 if (errorp != NULL) 2493 *errorp = _nscd_cfg_make_error(rc, msg); 2494 2495 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2496 (me, "ERROR: %s\n", msg); 2497 2498 return (rc); 2499 } 2500 2501 break; 2502 2503 case NSCD_CFG_DATA_BITMAP: 2504 2505 errno = 0; 2506 bitmap = (nscd_cfg_bitmap_t)strtol(str, (char **)NULL, 10); 2507 if (errno != NULL) { 2508 2509 (void) snprintf(msg, sizeof (msg), 2510 gettext("unable to convert data (%s) for %s"), 2511 str, desc->id.name); 2512 2513 if (errorp != NULL) 2514 *errorp = _nscd_cfg_make_error(rc, msg); 2515 2516 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2517 (me, "ERROR: %s\n", msg); 2518 2519 return (rc); 2520 } 2521 2522 _nscd_cfg_bitmap_set(data, bitmap); 2523 2524 break; 2525 2526 } 2527 2528 return (NSCD_SUCCESS); 2529 } 2530 2531 2532 nscd_rc_t 2533 _nscd_cfg_set( 2534 nscd_cfg_handle_t *handle, 2535 void *data, 2536 nscd_cfg_error_t **errorp) 2537 { 2538 char *me = "_nscd_cfg_set"; 2539 int dlen; 2540 nscd_cfg_id_t *nswdb; 2541 nscd_cfg_param_desc_t *desc, *gdesc; 2542 nscd_cfg_group_info_t *gi; 2543 char *nswdb_name, *param_name; 2544 void *pdata = NULL; 2545 void *cfg_data, *vdata_addr = NULL; 2546 nscd_bool_t get_group = 0; 2547 nscd_bool_t in = nscd_true; 2548 nscd_cfg_lock_t *lock = NULL; 2549 nscd_rc_t rc = NSCD_SUCCESS; 2550 2551 if (handle == NULL) { 2552 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2553 (me, "handle is NULL\n"); 2554 return (NSCD_INVALID_ARGUMENT); 2555 } 2556 2557 nswdb = handle->nswdb; 2558 desc = (nscd_cfg_param_desc_t *)handle->desc; 2559 if (nswdb == NULL) 2560 nswdb_name = "global"; 2561 else 2562 nswdb_name = nswdb->name; 2563 param_name = desc->id.name; 2564 2565 if (data == NULL && _nscd_cfg_flag_is_not_set(desc->pflag, 2566 NSCD_CFG_PFLAG_VLEN_DATA)) { 2567 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2568 (me, "data == NULL\n"); 2569 return (NSCD_INVALID_ARGUMENT); 2570 } 2571 2572 if (_nscd_cfg_flag_is_set(desc->pflag, 2573 NSCD_CFG_PFLAG_UPDATE_SEND_WHOLE_GROUP) || 2574 _nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP)) 2575 get_group = nscd_true; 2576 2577 /* 2578 * locate the current value of the param or group 2579 * and lock the config data for writing 2580 */ 2581 rc = _nscd_cfg_locate_cfg_data(&cfg_data, nscd_false, desc, 2582 nswdb, get_group, &vdata_addr, &dlen, &lock); 2583 if (rc != NSCD_SUCCESS) { 2584 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2585 (me, "unable to locate config data (rc = %d)\n", rc); 2586 return (rc); 2587 } 2588 2589 if (_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP) && 2590 ((nscd_cfg_group_info_t *)cfg_data)->num_param != 2591 ((nscd_cfg_group_info_t *)data)->num_param) { 2592 2593 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2594 (me, "number of parameters in group <%s : %s> not equal: " 2595 "%d in input data, should be %d\n", 2596 NSCD_STR_OR_GLOBAL(nswdb_name), 2597 NSCD_STR_OR_NULL(param_name), 2598 ((nscd_cfg_group_info_t *)data)->num_param, 2599 ((nscd_cfg_group_info_t *)cfg_data)->num_param); 2600 2601 rc = NSCD_INVALID_ARGUMENT; 2602 goto error_exit; 2603 } 2604 2605 /* 2606 * if variable length data, we want the address 2607 * of the pointer pointing to the data 2608 */ 2609 if (vdata_addr != NULL) 2610 cfg_data = vdata_addr; 2611 2612 /* 2613 * just copy in the specified data, if no need 2614 * to verify the data or notify the associated 2615 * component 2616 */ 2617 if (get_group == nscd_true) { 2618 2619 gdesc = &_nscd_cfg_param_desc[desc->g_index]; 2620 2621 rc = _nscd_cfg_copy_group_data_merge( 2622 gdesc, &pdata, data, cfg_data, 2623 desc->id.index, data); 2624 2625 if (rc != NSCD_SUCCESS) { 2626 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2627 (me, "unable to copy group data <%s : %s>\n", 2628 NSCD_STR_OR_GLOBAL(nswdb_name), 2629 NSCD_STR_OR_NULL(param_name)); 2630 2631 goto error_exit; 2632 } 2633 2634 rc = _nscd_cfg_notify_s(gdesc, nswdb, 2635 pdata, errorp); 2636 2637 } else 2638 rc = _nscd_cfg_notify_s(desc, nswdb, data, 2639 errorp); 2640 2641 if (rc != NSCD_SUCCESS) { 2642 2643 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2644 (me, "verifying/notifying of new configuration " 2645 "parameter <%s : %s> failed. %s\n", 2646 NSCD_STR_OR_GLOBAL(nswdb_name), 2647 param_name, (*errorp && (*errorp)->msg) ? 2648 (*errorp)->msg : ""); 2649 2650 goto error_exit; 2651 } 2652 2653 /* 2654 * Move the new config into the config store 2655 */ 2656 rc = NSCD_CFG_SET_PARAM_FAILED; 2657 if (_nscd_cfg_flag_is_set(desc->pflag, 2658 NSCD_CFG_PFLAG_GROUP)) { 2659 gi = _nscd_cfg_get_gi(pdata); 2660 rc = _nscd_cfg_copy_group_data_in(gdesc, gi, 2661 cfg_data, pdata); 2662 } else { 2663 /* 2664 * nscd_true asks _nscd_cfg_copy_param_data to 2665 * set addr of the vlen data in 'cfg_data' rather 2666 * than copying the data content 2667 */ 2668 if (pdata != NULL) 2669 _nscd_cfg_free_vlen_data_group(gdesc, 2670 pdata, in); 2671 2672 rc = _nscd_cfg_copy_param_data(desc, 2673 cfg_data, data, in, nscd_true); 2674 } 2675 2676 if (rc != NSCD_SUCCESS) { 2677 2678 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2679 (me, "unable to make new param data <%s : %s> current\n", 2680 NSCD_STR_OR_GLOBAL(nswdb_name), 2681 NSCD_STR_OR_NULL(param_name)); 2682 } 2683 2684 error_exit: 2685 2686 _nscd_cfg_unlock(lock); 2687 2688 return (rc); 2689 } 2690 2691 nscd_rc_t 2692 _nscd_cfg_set_linked( 2693 nscd_cfg_handle_t *handle, 2694 void *data, 2695 nscd_cfg_error_t **errorp) 2696 { 2697 char *me = "_nscd_cfg_set_linked"; 2698 nscd_cfg_id_t *nswdb; 2699 nscd_cfg_handle_t *hl; 2700 nscd_cfg_param_desc_t *desc; 2701 char *nswdb_name, *param_name, *dbl; 2702 nscd_rc_t rc = NSCD_SUCCESS; 2703 nscd_cfg_nsw_spc_default_t *spc; 2704 int i; 2705 char msg[NSCD_CFG_MAX_ERR_MSG_LEN]; 2706 2707 if (handle == NULL) { 2708 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2709 (me, "handle is NULL\n"); 2710 return (NSCD_INVALID_ARGUMENT); 2711 } 2712 2713 nswdb = handle->nswdb; 2714 desc = (nscd_cfg_param_desc_t *)handle->desc; 2715 2716 /* 2717 * no need to do the special linking thing, 2718 * if a global param, or a group, or not a linked param 2719 */ 2720 if (nswdb == NULL || _nscd_cfg_flag_is_set(desc->pflag, 2721 NSCD_CFG_PFLAG_GROUP) || 2722 _nscd_cfg_flag_is_not_set(desc->pflag, 2723 NSCD_CFG_PFLAG_LINKED)) 2724 return (_nscd_cfg_set(handle, data, errorp)); 2725 else 2726 nswdb_name = nswdb->name; 2727 param_name = desc->id.name; 2728 2729 /* 2730 * if a param is linked to another, it can not be 2731 * changed directly 2732 */ 2733 for (i = 0; i < _nscd_cfg_num_link_default; i++) { 2734 2735 if (_nscd_cfg_nsw_link_default[i].data == NULL) 2736 continue; 2737 2738 if (strcmp(_nscd_cfg_nsw_link_default[i].db, 2739 nswdb_name) == 0 && 2740 _nscd_cfg_nsw_link_default[i].group_off == 2741 desc->g_offset && 2742 _nscd_cfg_nsw_link_default[i].param_off == 2743 desc->p_offset) { 2744 2745 rc = NSCD_CFG_READ_ONLY; 2746 2747 (void) snprintf(msg, sizeof (msg), 2748 gettext("vaule of \'%s\' not changeable, change that of \'%s\' instead"), 2749 nswdb->name, "passwd"); 2750 2751 if (errorp != NULL) 2752 *errorp = _nscd_cfg_make_error(rc, msg); 2753 2754 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) 2755 (me, "ERROR: %s\n", msg); 2756 2757 return (rc); 2758 } 2759 } 2760 2761 /* 2762 * if a param is linked from another, it should be verify 2763 * and changed first 2764 */ 2765 for (i = 0; i < _nscd_cfg_num_link_default; i++) { 2766 2767 if (_nscd_cfg_nsw_link_default[i].data == NULL) 2768 continue; 2769 2770 spc = _nscd_cfg_nsw_link_default[i].data; 2771 2772 if (strcmp(spc->db, nswdb_name) == 0 && 2773 spc->group_off == desc->g_offset && 2774 spc->param_off == desc->p_offset) { 2775 2776 rc = _nscd_cfg_set(handle, data, errorp); 2777 if (rc != NSCD_SUCCESS) 2778 return (rc); 2779 break; 2780 } 2781 } 2782 2783 /* 2784 * then change all those linked to the one that has been changed 2785 */ 2786 for (i = 0; i < _nscd_cfg_num_link_default; i++) { 2787 2788 if (_nscd_cfg_nsw_link_default[i].data == NULL) 2789 continue; 2790 2791 spc = _nscd_cfg_nsw_link_default[i].data; 2792 2793 if (strcmp(spc->db, nswdb_name) == 0 && 2794 spc->group_off == desc->g_offset && 2795 spc->param_off == desc->p_offset && 2796 _nscd_cfg_nsw_link_default[i].group_off == 2797 desc->g_offset && 2798 _nscd_cfg_nsw_link_default[i].param_off == 2799 desc->p_offset) { 2800 2801 dbl = _nscd_cfg_nsw_link_default[i].db; 2802 2803 rc = _nscd_cfg_get_handle(param_name, dbl, 2804 &hl, errorp); 2805 rc = _nscd_cfg_set(hl, data, errorp); 2806 _nscd_cfg_free_handle(hl); 2807 if (rc != NSCD_SUCCESS) 2808 return (rc); 2809 } 2810 } 2811 2812 return (_nscd_cfg_set(handle, data, errorp)); 2813 } 2814 2815 /* 2816 * Return a list of space-separated database names that 2817 * have at least one of the input sources appeared in the 2818 * configured nsswitch policy string of the databases. 2819 * The return string should be freed by the caller. 2820 * 2821 * For compat sources (compat_group and compat_passwd), 2822 * "group" will be returned, if the policy string for 2823 * compat_group contains one of the input sources. Same 2824 * for compat_passwd and passwd. 2825 */ 2826 char * 2827 _nscd_srcs_in_db_nsw_policy( 2828 int num_src, 2829 char **srcs) 2830 { 2831 uint8_t i, j, n = 0, nc = 0; 2832 uint8_t compat_grp = 0, compat_pwd = 0; 2833 uint8_t *db; 2834 uint8_t *db_compat; 2835 int dlen = 0; 2836 nscd_cfg_nsw_db_data_t *dbcfg; 2837 nscd_cfg_switch_t *sw; 2838 char *outstr = NULL; 2839 char *dbname; 2840 2841 db = (uint8_t *)calloc(_nscd_cfg_num_nsw_db, sizeof (uint8_t)); 2842 if (db == NULL) 2843 return (NULL); 2844 2845 db_compat = (uint8_t *)calloc(_nscd_cfg_num_nsw_db, 2846 sizeof (uint8_t)); 2847 if (db_compat == NULL) { 2848 free(db); 2849 return (NULL); 2850 } 2851 2852 for (i = 0; i < _nscd_cfg_num_nsw_db; i++) { 2853 2854 (void) rw_rdlock(&nscd_cfg_nsw_db_data_rwlock[i]); 2855 2856 dbcfg = &nscd_cfg_nsw_db_data_current[i]; 2857 sw = &dbcfg->sw; 2858 if (sw->nsw_config_string == NULL) 2859 continue; 2860 2861 dbname = _nscd_cfg_nsw_db[i].name; 2862 for (j = 0; j < num_src; j++) { 2863 if (strstr(sw->nsw_config_string, srcs[j]) != 2864 NULL) { 2865 db[n++] = i; 2866 dlen += strlen(dbname) + 1; 2867 } else if (strcmp(sw->nsw_config_string, 2868 "compat") == 0) { 2869 if (strcmp(dbname, "passwd") == 0) { 2870 compat_pwd = 1; 2871 dlen += 7; 2872 } else if (strcmp(dbname, "group") == 0) { 2873 compat_grp = 1; 2874 dlen += 6; 2875 } else { 2876 db_compat[nc++] = i; 2877 dlen += strlen(dbname) + 1; 2878 2879 } 2880 } 2881 } 2882 (void) rw_unlock(&nscd_cfg_nsw_db_data_rwlock[i]); 2883 } 2884 2885 if (dlen != NULL) 2886 outstr = (char *)calloc(1, dlen); 2887 if (outstr == NULL) { 2888 free(db_compat); 2889 free(db); 2890 return (NULL); 2891 } 2892 2893 for (j = 0; j < n; j++) { 2894 dbname = _nscd_cfg_nsw_db[db[j]].name; 2895 if (strstr(dbname, "group_compat") != NULL) { 2896 if (compat_grp == 1) 2897 dbname = "group"; 2898 else 2899 continue; 2900 } else if (strstr(dbname, "passwd_compat") != NULL) { 2901 if (compat_pwd == 1) 2902 dbname = "passwd"; 2903 else 2904 continue; 2905 } 2906 2907 (void) strlcat(outstr, dbname, dlen); 2908 (void) strlcat(outstr, ",", dlen); 2909 } 2910 2911 for (j = 0; j < nc; j++) { 2912 dbname = _nscd_cfg_nsw_db[db_compat[j]].name; 2913 if (compat_pwd == 1) { 2914 (void) strlcat(outstr, dbname, dlen); 2915 (void) strlcat(outstr, " ", dlen); 2916 } 2917 } 2918 2919 free(db); 2920 free(db_compat); 2921 return (outstr); 2922 2923 } 2924