Backed out changeset e05f5705283d (wrong name)
[unleashed.git] / usr / src / cmd / nscd / nscd_config.c
blob4668ca685f13c8490fb56cb16f9ad1ed1bffb9d3
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2012 Milan Jurik. All rights reserved.
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <locale.h> /* gettext */
30 #include <dlfcn.h>
31 #include <string.h>
32 #include <sys/varargs.h>
33 #include <errno.h>
34 #include "nscd_db.h"
35 #include "nscd_config.h"
36 #include "nscd_cfgdef.h"
37 #include "nscd_log.h"
39 typedef struct {
40 rwlock_t *global;
41 rwlock_t *alldb;
42 rwlock_t *nswdb;
43 } nscd_cfg_lock_t;
45 static rwlock_t cfg_paramDB_rwlock = DEFAULTRWLOCK;
46 static nscd_db_t *cfg_paramDB = NULL;
48 static nscd_cfg_global_data_t *nscd_cfg_global_current;
49 static nscd_cfg_nsw_db_data_t *nscd_cfg_nsw_db_data_current;
50 static nscd_cfg_nsw_db_data_t *nscd_cfg_nsw_alldb_current;
51 static rwlock_t *nscd_cfg_global_rwlock;
52 static rwlock_t *nscd_cfg_nsw_db_data_rwlock;
53 static rwlock_t *nscd_cfg_nsw_alldb_rwlock;
55 extern int _nscd_cfg_num_nsw_src_all;
56 extern nscd_cfg_id_t *_nscd_cfg_nsw_src_all;
58 nscd_cfg_error_t *
59 _nscd_cfg_make_error(
60 nscd_rc_t rc,
61 char *msg)
64 nscd_cfg_error_t *ret;
65 int size, msglen;
67 msglen = (msg != NULL ? strlen(msg) + 1 : 0);
69 size = sizeof (nscd_cfg_error_t) + msglen;
71 ret = calloc(1, size);
72 if (ret == NULL)
73 return (NULL);
75 ret->rc = rc;
76 if (msg != NULL) {
77 ret->msg = (char *)ret +
78 sizeof (nscd_cfg_error_t);
79 (void) memcpy(ret->msg, msg, msglen);
82 return (ret);
85 static nscd_rc_t
86 _nscd_cfg_get_list(
87 nscd_cfg_list_t **list,
88 nscd_cfg_list_type_t type)
90 char *me = "_nscd_cfg_get_list";
91 int i, num, size;
92 nscd_cfg_id_t *l;
93 nscd_cfg_list_t *ret;
94 nscd_cfg_param_desc_t *pl;
95 nscd_cfg_stat_desc_t *sl;
96 void *p;
98 if (list == NULL) {
99 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
100 (me, "invalid argument: list = %p\n", list);
102 return (NSCD_INVALID_ARGUMENT);
104 *list = NULL;
106 switch (type) {
107 case NSCD_CFG_LIST_NSW_DB:
109 num = _nscd_cfg_num_nsw_db;
110 l = &_nscd_cfg_nsw_db[0];
111 break;
113 case NSCD_CFG_LIST_NSW_SRC:
115 num = _nscd_cfg_num_nsw_src_all;
116 l = _nscd_cfg_nsw_src_all;
117 break;
119 case NSCD_CFG_LIST_PARAM:
121 num = _nscd_cfg_num_param;
122 pl = &_nscd_cfg_param_desc[0];
123 break;
125 case NSCD_CFG_LIST_STAT:
127 num = _nscd_cfg_num_stat;
128 sl = &_nscd_cfg_stat_desc[0];
129 break;
131 default:
132 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
133 (me, "invalid argument: type (%d)\n", type);
135 return (NSCD_INVALID_ARGUMENT);
138 size = sizeof (nscd_cfg_list_t) + sizeof (nscd_cfg_id_t *) * (num + 1);
140 ret = calloc(1, size);
141 if (ret == NULL)
142 return (NSCD_NO_MEMORY);
144 ret->num = num;
145 p = (char *)ret + sizeof (nscd_cfg_list_t);
146 ret->list = (nscd_cfg_id_t **)p;
148 if (type == NSCD_CFG_LIST_PARAM) {
149 for (i = 0; i <= num; i++)
150 ret->list[i] = (nscd_cfg_id_t *)&pl[i];
151 } else if (type == NSCD_CFG_LIST_STAT) {
152 for (i = 0; i <= num; i++)
153 ret->list[i] = (nscd_cfg_id_t *)&sl[i];
154 } else {
155 for (i = 0; i <= num; i++)
156 ret->list[i] = &l[i];
159 *list = ret;
161 return (NSCD_SUCCESS);
164 nscd_rc_t
165 _nscd_cfg_get_param_desc_list(
166 nscd_cfg_param_desc_list_t **list)
168 return (_nscd_cfg_get_list((nscd_cfg_list_t **)list,
169 NSCD_CFG_LIST_PARAM));
173 * FUNCTION: _nscd_cfg_create_paramDB
175 * Create the internal config parameter database
177 static nscd_db_t *
178 _nscd_cfg_create_paramDB()
181 nscd_db_t *ret;
183 (void) rw_wrlock(&cfg_paramDB_rwlock);
185 ret = _nscd_alloc_db(NSCD_DB_SIZE_MEDIUM);
187 if (ret != NULL)
188 cfg_paramDB = ret;
190 (void) rw_unlock(&cfg_paramDB_rwlock);
192 return (ret);
196 * FUNCTION: _nscd_cfg_add_index_entry
198 * Add a config index entry (a name to index mapping)
199 * to the internal configuration database.
201 static nscd_rc_t
202 _nscd_cfg_add_index_entry(
203 char *name,
204 int index,
205 nscd_cfg_list_type_t type)
207 int *idx;
208 int size;
209 int dbe_type;
210 nscd_db_entry_t *db_entry;
212 if (name == NULL)
213 return (NSCD_INVALID_ARGUMENT);
215 if (type == NSCD_CFG_LIST_NSW_DB)
216 dbe_type = NSCD_DATA_CFG_NSW_DB_INDEX;
217 else if (type == NSCD_CFG_LIST_NSW_SRC)
218 dbe_type = NSCD_DATA_CFG_NSW_SRC_INDEX;
219 else if (type == NSCD_CFG_LIST_PARAM)
220 dbe_type = NSCD_DATA_CFG_PARAM_INDEX;
221 else if (type == NSCD_CFG_LIST_STAT)
222 dbe_type = NSCD_DATA_CFG_STAT_INDEX;
224 size = sizeof (int);
226 db_entry = _nscd_alloc_db_entry(dbe_type, (const char *)name,
227 size, 1, 1);
228 if (db_entry == NULL)
229 return (NSCD_NO_MEMORY);
231 idx = (int *)*(db_entry->data_array);
232 *idx = index;
234 (void) rw_wrlock(&cfg_paramDB_rwlock);
235 (void) _nscd_add_db_entry(cfg_paramDB, name, db_entry,
236 NSCD_ADD_DB_ENTRY_FIRST);
237 (void) rw_unlock(&cfg_paramDB_rwlock);
239 return (NSCD_SUCCESS);
243 * FUNCTION: _nscd_cfg_get_index
245 * Get the index of a config data item by searching the internal config
246 * database. Do not free the returned data.
248 static int
249 _nscd_cfg_get_index(
250 char *name,
251 nscd_cfg_list_type_t type)
253 int index = -1, dbe_type;
254 const nscd_db_entry_t *db_entry;
256 if (name == NULL)
257 return (-1);
259 if (type == NSCD_CFG_LIST_NSW_DB)
260 dbe_type = NSCD_DATA_CFG_NSW_DB_INDEX;
261 else if (type == NSCD_CFG_LIST_NSW_SRC)
262 dbe_type = NSCD_DATA_CFG_NSW_SRC_INDEX;
263 else if (type == NSCD_CFG_LIST_PARAM)
264 dbe_type = NSCD_DATA_CFG_PARAM_INDEX;
265 else if (type == NSCD_CFG_LIST_STAT)
266 dbe_type = NSCD_DATA_CFG_STAT_INDEX;
267 else
268 return (-1);
270 db_entry = _nscd_get_db_entry(cfg_paramDB, dbe_type,
271 (const char *)name, NSCD_GET_FIRST_DB_ENTRY, 0);
273 if (db_entry != NULL)
274 index = *(int *)*(db_entry->data_array);
276 return (index);
279 static nscd_rc_t
280 _nscd_cfg_verify_group_info(
281 nscd_cfg_group_info_t *g_info,
282 nscd_cfg_param_desc_t *gdesc)
285 char *me = "_nscd_cfg_verify_group_info";
286 void *vp;
287 nscd_cfg_group_info_t *gi;
289 if (_nscd_cfg_flag_is_set(gdesc->pflag, NSCD_CFG_PFLAG_GLOBAL)) {
290 vp = (char *)&nscd_cfg_global_default +
291 gdesc->g_offset;
292 gi = (nscd_cfg_group_info_t *)vp;
293 } else {
294 vp = (char *)&nscd_cfg_nsw_db_data_default +
295 gdesc->g_offset;
296 gi = (nscd_cfg_group_info_t *)vp;
300 if (g_info->num_param == gi->num_param &&
301 _nscd_cfg_bitmap_is_equal(g_info->bitmap, gi->bitmap))
302 return (NSCD_SUCCESS);
304 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
305 (me, "ERROR: group (%s) info mismatched: group info "
306 "(%d, %#6.4x) not equal to that of default configuration data "
307 "(%d, %#6.4x)\n", gdesc->id.name, g_info->num_param,
308 _nscd_cfg_bitmap_value(g_info->bitmap), gi->num_param,
309 _nscd_cfg_bitmap_value(gi->bitmap));
311 return (NSCD_CFG_PARAM_DESC_ERROR);
316 static nscd_rc_t
317 _nscd_cfg_init_nsw()
319 char *me = "_nscd_cfg_init_nsw";
320 int i, j, idx, rc, num;
321 nscd_cfg_id_t *id;
322 nscd_cfg_list_type_t type[2] = { NSCD_CFG_LIST_NSW_DB,
323 NSCD_CFG_LIST_NSW_SRC };
325 nscd_cfg_id_t *list[2] = { _nscd_cfg_nsw_db, NULL};
327 list[1] = _nscd_cfg_nsw_src_all;
329 for (j = 0; j < 2; j++) {
331 if (j == 0)
332 num = _nscd_cfg_num_nsw_db + 1;
333 else
334 num = _nscd_cfg_num_nsw_src_all;
336 for (i = 0; i < num; i++) {
339 * _nscd_cfg_nsw_alldb is the id for the
340 * special ALLDB (defaults for all db)
342 if (j == 0 && i == _nscd_cfg_num_nsw_db) {
343 id = &_nscd_cfg_nsw_alldb;
344 idx = NSCD_CFG_NSW_ALLDB_INDEX;
345 } else {
346 id = &(list[j])[i];
347 id->index = idx = i;
350 if (id->name == NULL)
351 continue;
353 if ((rc = _nscd_cfg_add_index_entry(id->name,
354 idx, type[j])) != NSCD_SUCCESS) {
356 _NSCD_LOG(NSCD_LOG_CONFIG,
357 NSCD_LOG_LEVEL_ERROR)
358 (me, "unable to add index entry for "
359 "nsswitch entry %s\n", id->name);
361 _nscd_free_db(cfg_paramDB);
362 return (rc);
367 return (NSCD_SUCCESS);
370 static nscd_rc_t
371 _nscd_cfg_init_param()
373 char *me = "_nscd_cfg_init_param";
374 int i, gi, fn = 0;
375 nscd_cfg_id_t *id;
376 nscd_cfg_param_desc_t *desc, *gdesc = NULL;
377 nscd_cfg_group_info_t g_info;
378 nscd_cfg_list_type_t type = NSCD_CFG_LIST_PARAM;
379 nscd_rc_t rc;
380 void *nfunc, *vfunc;
382 if (_nscd_cfg_create_paramDB() == NULL)
383 return (NSCD_NO_MEMORY);
385 desc = &_nscd_cfg_param_desc[0];
388 * need to loop to the last (+1) param description
389 * which is a fake group and which marks the end
390 * of list. It is used to signal the end of the
391 * previous group so that the proper data will be
392 * set for that group
394 for (i = 0; i < _nscd_cfg_num_param + 1; i++, desc++) {
396 id = (nscd_cfg_id_t *)desc;
398 if (_nscd_cfg_flag_is_set(desc->pflag,
399 NSCD_CFG_PFLAG_GROUP)) {
401 if (gdesc != NULL) {
402 g_info.num_param = fn;
403 gdesc->p_fn = fn;
405 if ((rc = _nscd_cfg_verify_group_info(
406 &g_info, gdesc)) != NSCD_SUCCESS)
407 return (rc);
410 gi = i;
411 fn = 0;
412 gdesc = desc;
413 g_info.bitmap = NSCD_CFG_BITMAP_ZERO;
416 * set the notify/verify functions
418 nfunc = (void *)gdesc->notify;
419 vfunc = (void *)gdesc->verify;
420 } else {
421 if (i == 0) {
423 _NSCD_LOG(NSCD_LOG_CONFIG,
424 NSCD_LOG_LEVEL_ERROR)
425 (me, "ERROR: first parameter "
426 "description is not for a group\n");
428 return (NSCD_CFG_PARAM_DESC_ERROR);
432 * set bitmap: the rightmost bit represents
433 * the first member (index = 0) in the group,
434 * the next bit is for the second member
435 * (index = 1), and so on
437 _nscd_cfg_bitmap_set_nth(g_info.bitmap, fn);
439 desc->p_fn = fn++;
442 * set the notify/verify functions
444 if (desc->notify == NSCD_CFG_FUNC_NOTIFY_AS_GROUP) {
445 (void) memcpy(&desc->notify, &nfunc,
446 sizeof (void *));
448 if (desc->verify == NSCD_CFG_FUNC_VERIFY_AS_GROUP) {
449 (void) memcpy(&desc->verify, &vfunc,
450 sizeof (void *));
454 /* if end of list reached, we are done */
455 if (i == _nscd_cfg_num_param)
456 break;
458 desc->g_index = gi;
460 id->index = i;
462 if ((rc = _nscd_cfg_add_index_entry(id->name,
463 i, type)) != NSCD_SUCCESS) {
465 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
466 (me, "unable to add index entry for parameter "
467 "%s\n", id->name);
469 _nscd_free_db(cfg_paramDB);
470 return (rc);
471 } else {
472 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
473 (me, "index entry for parameter "
474 "%s added\n", id->name);
478 return (_nscd_cfg_init_nsw());
481 static nscd_rc_t
482 _nscd_cfg_init_stat()
484 char *me = "_nscd_cfg_init_stat";
485 int i, gi, fn = 0;
486 nscd_cfg_id_t *id;
487 nscd_cfg_stat_desc_t *desc, *gdesc = NULL;
488 nscd_cfg_group_info_t g_info;
489 nscd_cfg_list_type_t type = NSCD_CFG_LIST_STAT;
490 nscd_rc_t rc;
491 void *gsfunc;
493 desc = &_nscd_cfg_stat_desc[0];
496 * need to loop to the last (+1) stat description
497 * which is a fake group and which marks the end
498 * of list. It is used to signal the end of the
499 * previous group so that the proper data will be
500 * set for that group
502 for (i = 0; i < _nscd_cfg_num_stat + 1; i++, desc++) {
504 id = (nscd_cfg_id_t *)desc;
506 if (_nscd_cfg_flag_is_set(desc->sflag,
507 NSCD_CFG_SFLAG_GROUP)) {
509 if (gdesc != NULL) {
510 g_info.num_param = fn;
511 gdesc->s_fn = fn;
513 if (g_info.num_param !=
514 gdesc->gi.num_param ||
515 !_nscd_cfg_bitmap_is_equal(
516 g_info.bitmap, gdesc->gi.bitmap)) {
518 _NSCD_LOG(NSCD_LOG_CONFIG,
519 NSCD_LOG_LEVEL_ERROR)
520 (me, "ERROR: group (%s) "
521 "info mismatched: "
522 "group info (%d, %#6.4x) not "
523 "equal to the predefined one "
524 "(%d, %#6.4x)\n", gdesc->id.name,
525 g_info.num_param,
526 _nscd_cfg_bitmap_value(
527 g_info.bitmap),
528 gdesc->gi.num_param,
529 _nscd_cfg_bitmap_value(
530 gdesc->gi.bitmap));
532 exit(1);
533 return (NSCD_CFG_STAT_DESC_ERROR);
537 gi = i;
538 fn = 0;
539 gdesc = desc;
540 g_info.bitmap = NSCD_CFG_BITMAP_ZERO;
543 * set the get_stat function
545 gsfunc = (void *)gdesc->get_stat;
546 } else {
547 if (i == 0) {
549 _NSCD_LOG(NSCD_LOG_CONFIG,
550 NSCD_LOG_LEVEL_ERROR)
551 (me, "ERROR: first stat "
552 "description is not for a group\n");
554 return (NSCD_CFG_STAT_DESC_ERROR);
558 * set bitmap: the rightmost bit represents
559 * the first member (index = 0) in the group,
560 * the next bit is for the second member
561 * (index = 1), and so on
563 _nscd_cfg_bitmap_set_nth(g_info.bitmap, fn);
565 desc->s_fn = fn++;
568 * set the get_stat function
570 if (desc->get_stat == NSCD_CFG_FUNC_GET_STAT_AS_GROUP) {
571 (void) memcpy(&desc->get_stat, &gsfunc,
572 sizeof (void *));
576 /* if end of list reached, we are done */
577 if (i == _nscd_cfg_num_stat)
578 break;
580 desc->g_index = gi;
582 id->index = i;
584 if ((rc = _nscd_cfg_add_index_entry(id->name,
585 i, type)) != NSCD_SUCCESS) {
587 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
588 (me, "unable to add index entry for stat "
589 "description %s\n", id->name);
591 _nscd_free_db(cfg_paramDB);
592 return (rc);
593 } else {
594 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
595 (me, "index entry for stat description "
596 "%s added\n", id->name);
600 return (NSCD_SUCCESS);
603 static nscd_rc_t
604 _nscd_cfg_copy_vlen_data(
605 void *data,
606 void **new_data_p,
607 nscd_cfg_param_desc_t *desc,
608 int *data_len,
609 nscd_bool_t in)
611 int len, dlen;
612 nscd_cfg_vlen_data_t *v = NULL;
614 *new_data_p = NULL;
615 *data_len = 0;
617 /* it is OK if there is nothing to copy */
618 if (data == NULL)
619 return (NSCD_SUCCESS);
622 * if copy to the config store we need to allocate space
623 * for the extra vlen header
625 if (desc->type == NSCD_CFG_DATA_STRING) {
626 len = dlen = strlen((char *)data) + 1;
627 if (in == nscd_true)
628 len += sizeof (nscd_cfg_vlen_data_t);
629 } else {
631 * should not be here, since for now
632 * only string variable length data
633 * is supported
635 *new_data_p = NULL;
636 return (NSCD_CFG_PARAM_DESC_ERROR);
639 v = calloc(1, len);
640 if (v == NULL) {
641 *new_data_p = NULL;
642 return (NSCD_NO_MEMORY);
646 * if copy to the config store, set up
647 * the extra vlen header in which the
648 * pointer to, and length of, the real
649 * data are kept. The pointer to the real
650 * data, not the vlen header, is returned.
652 if (in == nscd_true) {
653 v->ptr = (char *)v + sizeof (nscd_cfg_vlen_data_t);
654 v->len = dlen;
655 (void) memcpy(v->ptr, data, dlen);
656 *new_data_p = v->ptr;
657 } else {
658 (void) memcpy(v, data, dlen);
659 *new_data_p = v;
661 *data_len = dlen;
663 return (NSCD_SUCCESS);
666 static void
667 _nscd_cfg_free_vlen_data_int(
668 void *data)
670 nscd_cfg_vlen_data_t *v = NULL;
671 void *p;
673 if (data == NULL)
674 return;
676 p = (char *)data - sizeof (nscd_cfg_vlen_data_t);
677 v = (nscd_cfg_vlen_data_t *)p;
678 if (v->ptr == data)
679 free(v);
682 static nscd_rc_t
683 _nscd_cfg_set_vlen_data_int(
684 void *src,
685 void *dest,
686 nscd_bool_t global)
688 int i, offset, dlen = 0;
689 void *s, *d, *new;
690 void *cptr;
691 nscd_rc_t rc;
692 nscd_cfg_param_desc_t *desc;
694 desc = &_nscd_cfg_param_desc[0];
695 for (i = 0; i < _nscd_cfg_num_param; i++, desc++) {
697 if (global == nscd_true &&
698 _nscd_cfg_flag_is_not_set(desc->pflag,
699 NSCD_CFG_PFLAG_GLOBAL))
700 continue;
701 else if (global != nscd_true &&
702 _nscd_cfg_flag_is_set(desc->pflag,
703 NSCD_CFG_PFLAG_GLOBAL))
704 continue;
706 if (_nscd_cfg_flag_is_set(desc->pflag,
707 NSCD_CFG_PFLAG_VLEN_DATA)) {
709 offset = desc->g_offset + desc->p_offset;
711 s = (char *)src + offset;
712 cptr = *(char **)s;
714 rc = _nscd_cfg_copy_vlen_data(cptr, &new,
715 desc, &dlen, nscd_true);
716 if (rc != NSCD_SUCCESS)
717 return (rc);
719 d = (char *)dest + offset;
720 /* free the old vlen data */
721 if (*(char **)d == NULL)
722 _nscd_cfg_free_vlen_data_int(*(char **)d);
724 *(char **)d = new;
728 return (NSCD_SUCCESS);
731 static void *
732 _nscd_cfg_locate_vlen_data(
733 void *cfg_data,
734 int *len)
736 void *ptr, *ret;
738 ptr = *(char **)cfg_data;
739 ret = ptr;
740 if (ret == NULL) {
741 *len = 0;
742 return (NULL);
744 ptr = (char *)ptr - sizeof (nscd_cfg_vlen_data_t);
745 *len = ((nscd_cfg_vlen_data_t *)ptr)->len;
747 return (ret);
750 static void
751 _nscd_cfg_lock(
752 nscd_bool_t is_read,
753 nscd_cfg_lock_t *cfglock)
756 int (*lockfunc)(rwlock_t *);
758 if (cfglock == NULL)
759 return;
761 if (is_read == nscd_true)
762 lockfunc = rw_rdlock;
763 else
764 lockfunc = rw_wrlock;
766 if (cfglock->global != NULL) {
768 (lockfunc)(cfglock->global);
769 return;
772 if (cfglock->alldb != NULL)
773 (lockfunc)(cfglock->alldb);
775 if (cfglock->nswdb != NULL)
776 (lockfunc)(cfglock->nswdb);
779 static void
780 _nscd_cfg_unlock(
781 nscd_cfg_lock_t *cfglock)
783 if (cfglock == NULL)
784 return;
786 if (cfglock->global != NULL) {
788 (void) rw_unlock(cfglock->global);
789 free(cfglock);
790 return;
793 if (cfglock->nswdb != NULL)
794 (void) rw_unlock(cfglock->nswdb);
796 if (cfglock->alldb != NULL)
797 (void) rw_unlock(cfglock->alldb);
799 free(cfglock);
803 * If vlen_data_addr is given, it will be set to the
804 * address of the pointer pointing to the vlen data.
805 * 'cfglock' will be set to point to the reader/writer
806 * lock(s) protecting the (group) configuration data.
808 static nscd_rc_t
809 _nscd_cfg_locate_cfg_data(
810 void **cfg_data,
811 nscd_bool_t is_read,
812 nscd_cfg_param_desc_t *desc,
813 nscd_cfg_id_t *nswdb,
814 nscd_bool_t get_group,
815 void **vlen_data_addr,
816 int *len,
817 nscd_cfg_lock_t **cfglock)
819 int offset;
821 *cfg_data = NULL;
822 if (len != NULL)
823 *len = 0;
824 if (vlen_data_addr != NULL)
825 *vlen_data_addr = NULL;
827 if (cfglock != NULL) {
828 *cfglock = calloc(1, sizeof (nscd_cfg_lock_t));
829 if (*cfglock == NULL)
830 return (NSCD_NO_MEMORY);
833 /* assume if nswdb is NULL, the param is a global one */
834 if (nswdb == NULL) {
836 offset = desc->g_offset;
837 if (get_group != nscd_true)
838 offset += desc->p_offset;
839 *cfg_data = (char *)nscd_cfg_global_current + offset;
841 if (cfglock != NULL)
842 (*cfglock)->global = nscd_cfg_global_rwlock;
844 } else if (nswdb->index == NSCD_CFG_NSW_ALLDB_INDEX) {
846 offset = desc->g_offset;
847 if (get_group != nscd_true)
848 offset += desc->p_offset;
849 *cfg_data = (char *)nscd_cfg_nsw_alldb_current +
850 offset;
852 if (cfglock != NULL)
853 (*cfglock)->alldb = nscd_cfg_nsw_alldb_rwlock;
855 } else {
857 offset = nswdb->index *
858 (sizeof (nscd_cfg_nsw_db_data_t)) + desc->g_offset;
859 if (get_group != nscd_true)
860 offset += desc->p_offset;
861 *cfg_data = (char *)nscd_cfg_nsw_db_data_current +
862 offset;
864 if (cfglock != NULL) {
865 (*cfglock)->nswdb =
866 &nscd_cfg_nsw_db_data_rwlock[nswdb->index];
868 (*cfglock)->alldb = nscd_cfg_nsw_alldb_rwlock;
872 /* lock the config data */
873 if (cfglock != NULL)
874 _nscd_cfg_lock(is_read, *cfglock);
876 if (get_group != nscd_true &&
877 _nscd_cfg_flag_is_not_set(desc->pflag,
878 NSCD_CFG_PFLAG_GROUP) &&
879 (_nscd_cfg_flag_is_set(desc->pflag,
880 NSCD_CFG_PFLAG_VLEN_DATA))) {
881 if (vlen_data_addr != NULL)
882 *vlen_data_addr = *cfg_data;
883 *cfg_data = _nscd_cfg_locate_vlen_data(*cfg_data, len);
884 return (NSCD_SUCCESS);
887 if (len != NULL) {
888 if (get_group == nscd_true)
889 *len = desc->g_size;
890 else
891 *len = desc->p_size;
894 return (NSCD_SUCCESS);
898 * perform the preliminary (range) check on 'data' based on the
899 * datatype (desc->datatype) of the config parameter
901 nscd_rc_t
902 _nscd_cfg_prelim_check(
903 nscd_cfg_param_desc_t *desc,
904 void *data,
905 nscd_cfg_error_t **errorp)
908 char *me = "_nscd_cfg_prelim_check";
909 char msg[NSCD_CFG_MAX_ERR_MSG_LEN];
910 nscd_cfg_str_check_t *sc;
911 nscd_cfg_int_check_t *ic;
912 nscd_cfg_bitmap_check_t *bmc;
913 nscd_rc_t rc = NSCD_CFG_PRELIM_CHECK_FAILED;
915 if ((nscd_cfg_str_check_t *)desc->p_check == NULL)
916 return (NSCD_SUCCESS);
918 switch (desc->type) {
920 case NSCD_CFG_DATA_STRING:
922 sc = (nscd_cfg_str_check_t *)desc->p_check;
923 if (sc->must_not_null == nscd_true && data == NULL) {
925 if (errorp == NULL)
926 break;
928 (void) snprintf(msg, sizeof (msg),
929 gettext("data must be specified for %s"),
930 desc->id.name);
932 break;
935 if (data == NULL) {
936 rc = NSCD_SUCCESS;
937 break;
940 if (sc->maxlen != 0 &&
941 strlen((char *)data) > sc->maxlen) {
943 if (errorp == NULL)
944 break;
946 (void) snprintf(msg, sizeof (msg),
947 gettext("length of data (%s) for %s larger "
948 "than %d"),
949 (char *)data, desc->id.name, sc->maxlen);
950 break;
953 rc = NSCD_SUCCESS;
955 break;
957 case NSCD_CFG_DATA_INTEGER:
959 ic = (nscd_cfg_int_check_t *)desc->p_check;
960 if (*(int *)data > ic->max ||
961 *(int *)data < ic->min) {
963 if (errorp == NULL)
964 break;
966 (void) snprintf(msg, sizeof (msg),
967 gettext("data (%d) for %s out of range "
968 "(%d - %d)"),
969 *(int *)data, desc->id.name,
970 ic->min, ic->max);
972 break;
975 rc = NSCD_SUCCESS;
977 break;
979 case NSCD_CFG_DATA_BITMAP:
981 bmc = (nscd_cfg_bitmap_check_t *)desc->p_check;
982 if (_nscd_cfg_bitmap_value(*(nscd_cfg_bitmap_t *)data) &
983 ~(bmc->valid_bits)) {
985 if (errorp == NULL)
986 break;
988 (void) snprintf(msg, sizeof (msg),
989 gettext("data (%#6.4x) for %s contain bit "
990 "not in 0x%x"),
991 _nscd_cfg_bitmap_value(
992 *(nscd_cfg_bitmap_t *)data),
993 desc->id.name,
994 _nscd_cfg_bitmap_value(bmc->valid_bits));
995 break;
998 rc = NSCD_SUCCESS;
1000 break;
1003 if (rc != NSCD_SUCCESS && errorp != NULL) {
1004 *errorp = _nscd_cfg_make_error(rc, msg);
1006 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
1007 (me, "invalid argument: %s\n", (*errorp)->msg);
1010 return (rc);
1013 static nscd_rc_t
1014 _nscd_cfg_notify_i(
1015 nscd_cfg_param_desc_t *desc,
1016 nscd_cfg_id_t *nswdb,
1017 int *skip,
1018 nscd_cfg_error_t **errorp)
1021 char *me = "_nscd_cfg_notify_i";
1022 int i, num, skip_bk;
1023 void *cfg_data, *cdata;
1024 void *cookie = NULL;
1025 nscd_rc_t rc;
1026 nscd_cfg_flag_t dflag, dflag1;
1027 nscd_cfg_bitmap_t bitmap_c, bitmap_s, *bitmap_addr;
1028 nscd_cfg_group_info_t *gi;
1030 if (errorp != NULL)
1031 *errorp = NULL;
1033 if (skip == NULL)
1034 skip = &skip_bk;
1036 *skip = 0;
1038 if (_nscd_cfg_flag_is_not_set(desc->pflag,
1039 NSCD_CFG_PFLAG_GROUP)) {
1041 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1042 (me, "ERROR: expect parameter description for group, "
1043 "but receive parameter description is for %s\n",
1044 desc->id.name);
1046 return (NSCD_CFG_PARAM_DESC_ERROR);
1050 * Set data flag going with data to be sent to the
1051 * verify/notify routines. Allowing the config flag
1052 * be exipandable, set the bits one by one.
1054 dflag = NSCD_CFG_FLAG_ZERO;
1055 dflag = _nscd_cfg_flag_set(dflag, NSCD_CFG_DFLAG_STATIC_DATA);
1056 dflag = _nscd_cfg_flag_set(dflag, NSCD_CFG_DFLAG_INIT);
1057 dflag = _nscd_cfg_flag_set(dflag, NSCD_CFG_DFLAG_GROUP);
1058 if (_nscd_cfg_flag_is_set(desc->pflag,
1059 NSCD_CFG_PFLAG_INIT_SET_ALL_DB))
1060 dflag = _nscd_cfg_flag_set(dflag,
1061 NSCD_CFG_DFLAG_SET_ALL_DB);
1063 /* get to the group data in the config store */
1064 rc = _nscd_cfg_locate_cfg_data(&cfg_data, nscd_true,
1065 desc, nswdb, nscd_true, NULL, NULL, NULL);
1066 if (rc != NSCD_SUCCESS)
1067 goto error;
1070 * the static bitmap associated with the group
1071 * may be replaced before sending to the components,
1072 * so save the bitmap for later use
1074 gi = _nscd_cfg_get_gi(cfg_data);
1075 bitmap_c = gi->bitmap;
1076 bitmap_addr = &(gi->bitmap);
1079 * the elements in this group will all be handled
1080 * so the caller can skip them
1082 *skip = desc->p_fn;
1084 if (_nscd_cfg_flag_is_set(desc->pflag,
1085 NSCD_CFG_PFLAG_INIT_SEND_WHOLE_GROUP))
1086 /* send the entire group just once */
1087 num = 1;
1089 else { /* send individual members one by one */
1091 num = desc->p_fn;
1094 * skip the first desc which is for the group
1095 * and get to the desc for the first member
1097 desc++;
1099 dflag = _nscd_cfg_flag_unset(dflag,
1100 NSCD_CFG_DFLAG_GROUP);
1103 dflag1 = dflag;
1104 for (i = 0; i < num; i++, desc++) {
1106 dflag = dflag1;
1108 if (_nscd_cfg_flag_is_set(desc->pflag,
1109 NSCD_CFG_PFLAG_SEND_BIT_SELECTED)) {
1111 /* set the bitmap to select just this member */
1112 bitmap_s = NSCD_CFG_BITMAP_ZERO;
1113 _nscd_cfg_bitmap_set_nth(bitmap_s, i);
1114 /* replace the bitmap in the cfg data */
1115 _nscd_cfg_bitmap_set(bitmap_addr, bitmap_s);
1118 * send the whole group but with only one
1119 * member selected
1121 cdata = cfg_data;
1123 dflag = _nscd_cfg_flag_set(dflag,
1124 NSCD_CFG_DFLAG_GROUP);
1125 dflag = _nscd_cfg_flag_set(dflag,
1126 NSCD_CFG_DFLAG_BIT_SELECTED);
1127 } else {
1129 * send param data or group data:
1130 * param data - non-xero desc->p_offset
1131 * group data - zero desc->p_offset
1133 cdata = (char *)cfg_data + desc->p_offset;
1136 * if variable length data, need to send pointer
1137 * to the data (not the address of the pointer)
1139 if (_nscd_cfg_flag_is_set(desc->pflag,
1140 NSCD_CFG_PFLAG_VLEN_DATA))
1141 cdata = *(char **)cdata;
1144 if (desc->verify != NULL) {
1145 dflag = _nscd_cfg_flag_set(dflag,
1146 NSCD_CFG_DFLAG_VERIFY);
1147 rc = desc->verify(cdata, desc, nswdb,
1148 dflag, errorp, &cookie);
1149 if (rc != NSCD_SUCCESS)
1150 goto error;
1153 if (desc->notify != NULL) {
1154 dflag = _nscd_cfg_flag_set(dflag,
1155 NSCD_CFG_DFLAG_NOTIFY);
1157 rc = desc->notify(cfg_data, desc, nswdb,
1158 dflag, errorp, cookie);
1159 if (rc != NSCD_SUCCESS)
1160 goto error;
1164 rc = NSCD_SUCCESS;
1166 /* restore the bitmap in the cfg data */
1167 _nscd_cfg_bitmap_set(bitmap_addr, bitmap_c);
1169 error:
1171 return (rc);
1175 static nscd_rc_t
1176 _nscd_cfg_notify_init(
1177 nscd_cfg_error_t **errorp)
1179 int i, j, skip;
1180 nscd_rc_t rc;
1181 nscd_cfg_id_t *nswdb = NULL;
1182 nscd_cfg_param_desc_t *desc;
1184 if (errorp != NULL)
1185 *errorp = NULL;
1187 for (i = 0; i < _nscd_cfg_num_param; i++) {
1189 desc = &_nscd_cfg_param_desc[i];
1191 if (_nscd_cfg_flag_is_set(desc->pflag,
1192 NSCD_CFG_PFLAG_GLOBAL)) { /* global cfg data */
1194 rc = _nscd_cfg_notify_i(desc, NULL, &skip, errorp);
1195 } else {
1198 * if use defaults for all nsswitch database,
1199 * send the config data to verify/notify once
1201 if (_nscd_cfg_flag_is_set(desc->pflag,
1202 NSCD_CFG_PFLAG_INIT_SET_ALL_DB)) {
1204 nswdb = &_nscd_cfg_nsw_alldb;
1206 rc = _nscd_cfg_notify_i(desc, nswdb,
1207 &skip, errorp);
1208 } else { /* send data once for each nsw db */
1210 for (j = 0; j < _nscd_cfg_num_nsw_db; j++) {
1212 nswdb = &_nscd_cfg_nsw_db[j];
1214 rc = _nscd_cfg_notify_i(desc,
1215 nswdb, &skip, errorp);
1217 if (rc != NSCD_SUCCESS)
1218 break;
1223 if (rc != NSCD_SUCCESS)
1224 return (rc);
1226 i += skip;
1229 return (NSCD_SUCCESS);
1232 nscd_rc_t
1233 _nscd_cfg_init(
1234 nscd_cfg_error_t **errorp)
1237 int i, j, datalen;
1238 int dbi = 0, dbj = 0;
1239 char *dest, *src;
1240 char *dbni = NULL, *dbnj = NULL;
1241 nscd_rc_t rc;
1242 nscd_cfg_nsw_spc_default_t *spc;
1244 if (errorp != NULL)
1245 *errorp = NULL;
1247 rc = _nscd_cfg_init_param();
1248 if (rc != NSCD_SUCCESS)
1249 return (rc);
1251 rc = _nscd_cfg_init_stat();
1252 if (rc != NSCD_SUCCESS)
1253 return (rc);
1255 nscd_cfg_global_current = calloc(1,
1256 sizeof (nscd_cfg_global_data_t));
1257 if (nscd_cfg_global_current == NULL)
1258 return (NSCD_NO_MEMORY);
1260 nscd_cfg_nsw_alldb_current = calloc(1,
1261 sizeof (nscd_cfg_nsw_db_data_t));
1262 if (nscd_cfg_nsw_alldb_current == NULL)
1263 return (NSCD_NO_MEMORY);
1265 nscd_cfg_nsw_db_data_current = calloc(_nscd_cfg_num_nsw_db,
1266 sizeof (nscd_cfg_nsw_db_data_t));
1267 if (nscd_cfg_nsw_db_data_current == NULL)
1268 return (NSCD_NO_MEMORY);
1270 nscd_cfg_global_rwlock = calloc(1, sizeof (rwlock_t));
1271 if (nscd_cfg_global_rwlock == NULL)
1272 return (NSCD_NO_MEMORY);
1273 (void) rwlock_init(nscd_cfg_global_rwlock, NULL, NULL);
1275 *nscd_cfg_global_current = nscd_cfg_global_default;
1277 rc = _nscd_cfg_set_vlen_data_int(&nscd_cfg_global_default,
1278 nscd_cfg_global_current, nscd_true);
1279 if (rc != NSCD_SUCCESS)
1280 return (rc);
1282 nscd_cfg_nsw_db_data_rwlock = calloc(_nscd_cfg_num_nsw_db,
1283 sizeof (rwlock_t));
1284 if (nscd_cfg_nsw_db_data_rwlock == NULL)
1285 return (NSCD_NO_MEMORY);
1287 /* set per switch db config to the default for all db's */
1288 for (i = 0; i < _nscd_cfg_num_nsw_db; i++) {
1290 nscd_cfg_nsw_db_data_current[i] =
1291 nscd_cfg_nsw_db_data_default;
1293 (void) rwlock_init(&nscd_cfg_nsw_db_data_rwlock[i],
1294 NULL, NULL);
1297 /* add db specific defaults */
1298 for (i = 0; i < _nscd_cfg_num_nsw_default; i++) {
1300 if (_nscd_cfg_nsw_spc_default[i].data == NULL)
1301 continue;
1303 if (_nscd_cfg_nsw_spc_default[i].db != dbni) {
1304 for (j = 0; j < _nscd_cfg_num_nsw_db; j++) {
1306 if (strcmp(_nscd_cfg_nsw_db[j].name,
1307 _nscd_cfg_nsw_spc_default[i].db) != 0)
1308 continue;
1310 dbi = _nscd_cfg_nsw_db[j].index;
1311 dbni = _nscd_cfg_nsw_db[j].name;
1312 break;
1316 dest = (char *)&nscd_cfg_nsw_db_data_current[dbi] +
1317 _nscd_cfg_nsw_spc_default[i].group_off +
1318 _nscd_cfg_nsw_spc_default[i].param_off;
1320 src = _nscd_cfg_nsw_spc_default[i].data;
1321 datalen = _nscd_cfg_nsw_spc_default[i].data_len;
1323 (void) memcpy(dest, src, datalen);
1326 /* add db specific defaults via links */
1327 for (i = 0; i < _nscd_cfg_num_link_default; i++) {
1329 if (_nscd_cfg_nsw_link_default[i].data == NULL)
1330 continue;
1332 spc = _nscd_cfg_nsw_link_default[i].data;
1334 if (_nscd_cfg_nsw_link_default[i].db != dbni) {
1335 for (j = 0; j < _nscd_cfg_num_nsw_db; j++) {
1337 if (strcmp(_nscd_cfg_nsw_db[j].name,
1338 _nscd_cfg_nsw_link_default[i].db) != 0)
1339 continue;
1341 dbi = _nscd_cfg_nsw_db[j].index;
1342 dbni = _nscd_cfg_nsw_db[j].name;
1343 break;
1347 dest = (char *)&nscd_cfg_nsw_db_data_current[dbi] +
1348 _nscd_cfg_nsw_link_default[i].group_off +
1349 _nscd_cfg_nsw_link_default[i].param_off;
1351 if (_nscd_cfg_nsw_db[j].name != dbnj) {
1352 for (j = 0; j < _nscd_cfg_num_nsw_db; j++) {
1354 if (strcmp(spc->db,
1355 _nscd_cfg_nsw_db[j].name) != 0)
1356 continue;
1358 dbnj = _nscd_cfg_nsw_db[j].name;
1359 dbj = _nscd_cfg_nsw_db[j].index;
1360 break;
1364 src = (char *)&nscd_cfg_nsw_db_data_current[dbj] +
1365 spc->group_off + spc->param_off;
1366 datalen = spc->data_len;
1368 (void) memcpy(dest, src, datalen);
1371 /* fix up variable length fields */
1372 for (i = 0; i < _nscd_cfg_num_nsw_db; i++) {
1374 rc = _nscd_cfg_set_vlen_data_int(
1375 &nscd_cfg_nsw_db_data_current[i],
1376 &nscd_cfg_nsw_db_data_current[i], nscd_false);
1377 if (rc != NSCD_SUCCESS)
1378 return (rc);
1381 nscd_cfg_nsw_alldb_rwlock = calloc(1, sizeof (rwlock_t));
1382 if (nscd_cfg_nsw_alldb_rwlock == NULL)
1383 return (NSCD_NO_MEMORY);
1385 (void) rwlock_init(nscd_cfg_nsw_alldb_rwlock, NULL, NULL);
1387 rc = _nscd_cfg_set_vlen_data_int(
1388 &nscd_cfg_nsw_db_data_default,
1389 nscd_cfg_nsw_alldb_current, nscd_false);
1390 if (rc != NSCD_SUCCESS)
1391 return (rc);
1394 * notify and send the configuration data to
1395 * the nscd components
1397 rc = _nscd_cfg_notify_init(errorp);
1398 if (rc != NSCD_SUCCESS)
1399 return (rc);
1401 return (NSCD_SUCCESS);
1404 static nscd_rc_t
1405 _nscd_cfg_get_handle_common(
1406 nscd_cfg_list_type_t type,
1407 char *name,
1408 char *nswdb_name,
1409 nscd_cfg_handle_t **handle,
1410 nscd_cfg_error_t **errorp)
1413 int i, is_global;
1414 char *desc_str;
1415 nscd_cfg_handle_t *h;
1416 nscd_cfg_param_desc_t *pdesc;
1417 nscd_cfg_stat_desc_t *sdesc;
1418 char *me = "_nscd_cfg_get_handle_common";
1419 char msg[NSCD_CFG_MAX_ERR_MSG_LEN];
1420 nscd_rc_t rc = NSCD_INVALID_ARGUMENT;
1422 if (handle == NULL) {
1424 (void) snprintf(msg, sizeof (msg),
1425 gettext("address of handle not specified"));
1426 if (errorp)
1427 *errorp = _nscd_cfg_make_error(rc, msg);
1429 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
1430 (me, "invalid argument: %s\n", msg);
1432 return (rc);
1435 *handle = NULL;
1437 if (name == NULL) {
1439 (void) snprintf(msg, sizeof (msg),
1440 gettext("name not specified"));
1441 if (errorp)
1442 *errorp = _nscd_cfg_make_error(rc, msg);
1444 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
1445 (me, "invalid argument: %s\n");
1447 return (rc);
1450 h = calloc(1, sizeof (nscd_cfg_handle_t));
1451 if (h == NULL)
1452 return (NSCD_NO_MEMORY);
1453 h->type = type;
1455 if (type == NSCD_CFG_LIST_PARAM)
1456 desc_str = gettext("configuration parameter");
1457 else
1458 desc_str = gettext("statistics");
1460 /* get param or stat descriptor */
1461 i = _nscd_cfg_get_index(name, type);
1462 if (i != -1) {
1464 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
1465 (me, "%s: index of %s is %d\n", desc_str, name, i);
1467 if (type == NSCD_CFG_LIST_PARAM) {
1468 pdesc = &_nscd_cfg_param_desc[i];
1469 (void) memcpy(&h->desc, &pdesc, sizeof (pdesc));
1470 is_global = _nscd_cfg_flag_is_set(
1471 pdesc->pflag, NSCD_CFG_PFLAG_GLOBAL);
1473 /* hidden params are not exposed */
1474 if (_nscd_cfg_flag_is_set(
1475 pdesc->pflag, NSCD_CFG_PFLAG_HIDDEN))
1476 i = -1;
1478 if (_nscd_cfg_flag_is_set(pdesc->pflag,
1479 NSCD_CFG_PFLAG_OBSOLETE)) {
1480 _NSCD_LOG(NSCD_LOG_CONFIG,
1481 NSCD_LOG_LEVEL_WARNING)
1482 (me, gettext("%s: %s is obsolete and "
1483 "will be ignored\n"),
1484 desc_str, name);
1486 } else {
1487 sdesc = &_nscd_cfg_stat_desc[i];
1488 (void) memcpy(&h->desc, &sdesc, sizeof (sdesc));
1489 is_global = _nscd_cfg_flag_is_set(
1490 sdesc->sflag, NSCD_CFG_SFLAG_GLOBAL);
1494 if (i == -1) {
1496 (void) snprintf(msg, sizeof (msg),
1497 gettext("%s: unknown name \"%s\""), desc_str, name);
1498 if (errorp)
1499 *errorp = _nscd_cfg_make_error(rc, msg);
1501 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1502 (me, "%s\n", msg);
1504 free(h);
1505 return (rc);
1509 * if the param/stat is not a global one, we need to
1510 * know which nsswitch database we are dealing with
1512 if (is_global == 0) {
1513 if (nswdb_name == NULL) {
1515 (void) snprintf(msg, sizeof (msg),
1516 gettext("%s: switch database name not specified"),
1517 desc_str);
1518 if (errorp)
1519 *errorp = _nscd_cfg_make_error(rc, msg);
1521 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1522 (me, "%s for non-global param or stat %s\n",
1523 msg, name);
1525 free(h);
1526 return (rc);
1528 } else {
1530 if (nswdb_name != NULL) {
1532 (void) snprintf(msg, sizeof (msg),
1533 gettext("%s: switch database specified for "
1534 "global data"), desc_str);
1535 if (errorp)
1536 *errorp = _nscd_cfg_make_error(rc, msg);
1538 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1539 (me, "%s %s\n", msg, name);
1541 free(h);
1542 return (rc);
1545 *handle = h;
1546 return (NSCD_SUCCESS);
1549 /* get nsw DB id */
1550 i = _nscd_cfg_get_index(nswdb_name, NSCD_CFG_LIST_NSW_DB);
1551 if (i != -1) {
1553 if (i == NSCD_CFG_NSW_ALLDB_INDEX)
1554 h->nswdb = &_nscd_cfg_nsw_alldb;
1555 else
1556 h->nswdb = &_nscd_cfg_nsw_db[i];
1558 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
1559 (me, "%s: index of %s is %d\n",
1560 desc_str, nswdb_name, i);
1561 } else {
1563 (void) snprintf(msg, sizeof (msg),
1564 gettext("%s: unknown switch database name \"%s\""),
1565 desc_str, nswdb_name);
1566 if (errorp)
1567 *errorp = _nscd_cfg_make_error(rc, msg);
1569 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1570 (me, "%s\n", msg);
1572 free(h);
1573 return (NSCD_CFG_UNSUPPORTED_SWITCH_DB);
1576 *handle = h;
1578 return (NSCD_SUCCESS);
1581 nscd_rc_t
1582 _nscd_cfg_get_handle(
1583 char *param_name,
1584 char *nswdb_name,
1585 nscd_cfg_handle_t **handle,
1586 nscd_cfg_error_t **errorp)
1589 return (_nscd_cfg_get_handle_common(NSCD_CFG_LIST_PARAM,
1590 param_name, nswdb_name, handle, errorp));
1593 nscd_rc_t
1594 _nscd_cfg_get_stat_handle(
1595 char *stat_name,
1596 char *nswdb_name,
1597 nscd_cfg_handle_t **handle,
1598 nscd_cfg_error_t **errorp)
1601 return (_nscd_cfg_get_handle_common(NSCD_CFG_LIST_STAT,
1602 stat_name, nswdb_name, handle, errorp));
1605 void
1606 _nscd_cfg_free_handle(
1607 nscd_cfg_handle_t *handle)
1610 free(handle);
1614 static void
1615 _nscd_cfg_free_vlen_data_group(
1616 nscd_cfg_param_desc_t *gdesc,
1617 void *group_data,
1618 nscd_bool_t in)
1620 int num;
1621 void *dest, *ptr;
1622 nscd_cfg_param_desc_t *desc;
1624 desc = gdesc;
1626 num = ((nscd_cfg_group_info_t *)group_data)->num_param;
1628 while (num-- > 0) {
1630 desc++;
1632 /* skip fixed length data */
1633 if (_nscd_cfg_flag_is_not_set(desc->pflag,
1634 NSCD_CFG_PFLAG_VLEN_DATA))
1635 continue;
1637 dest = (char *)group_data + desc->p_offset;
1638 ptr = *(char **)dest;
1639 if (ptr == NULL)
1640 continue;
1641 if (in == nscd_true)
1642 _nscd_cfg_free_vlen_data_int(ptr);
1643 else
1644 free(ptr);
1648 void
1649 _nscd_cfg_free_param_data(
1650 void *data)
1653 if (data == NULL)
1654 return;
1656 free(data);
1659 void
1660 _nscd_cfg_free_group_data(
1661 nscd_cfg_handle_t *handle,
1662 void *data)
1665 nscd_cfg_param_desc_t *desc;
1666 nscd_cfg_group_info_t *gi;
1668 if (handle == NULL || data == NULL)
1669 return;
1671 desc = _nscd_cfg_get_desc(handle);
1672 gi = (nscd_cfg_group_info_t *)data;
1673 if (desc->p_fn != gi->num_param)
1674 return;
1676 _nscd_cfg_free_vlen_data_group(desc, data, nscd_false);
1678 free(data);
1681 void
1682 _nscd_cfg_free_error(
1683 nscd_cfg_error_t *error)
1686 if (error == NULL)
1687 return;
1689 free(error);
1692 static nscd_rc_t
1693 _nscd_cfg_copy_param_data(
1694 nscd_cfg_param_desc_t *desc,
1695 void *dest,
1696 void *pdata,
1697 nscd_bool_t in,
1698 nscd_bool_t set_addr)
1701 char *me = "_nscd_cfg_copy_param_data";
1702 void *tmp;
1703 int dlen;
1704 nscd_rc_t rc = NSCD_SUCCESS;
1706 if (desc == NULL || dest == NULL) {
1707 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1708 (me, "input desc == %p, dest == %p\n", desc, dest);
1709 return (NSCD_INVALID_ARGUMENT);
1712 /* fixed length data */
1713 if (_nscd_cfg_flag_is_not_set(desc->pflag,
1714 NSCD_CFG_PFLAG_VLEN_DATA)) {
1715 (void) memcpy(dest, pdata, desc->p_size);
1716 goto done;
1720 /* variable length data from this point on */
1722 /* make a copy of the variable length data */
1723 rc = _nscd_cfg_copy_vlen_data(pdata, &tmp, desc, &dlen, in);
1724 if (rc != NSCD_SUCCESS)
1725 goto done;
1727 if (in == nscd_true) { /* data to internal */
1729 /* free the variable length data in the config store */
1730 if (*(char **)dest != NULL)
1731 _nscd_cfg_free_vlen_data_int(*(char **)dest);
1734 if (set_addr == nscd_true) {
1736 * set the addr of the vlen data
1738 *(char **)dest = tmp;
1739 } else {
1741 * copy the data content (not address)
1743 (void) memcpy(dest, tmp, dlen);
1746 done:
1748 return (rc);
1751 static nscd_rc_t
1752 _nscd_cfg_copy_group_data_in(
1753 nscd_cfg_param_desc_t *gdesc,
1754 nscd_cfg_group_info_t *gi,
1755 void *group_dest,
1756 void *group_src)
1758 int i, num;
1759 nscd_cfg_param_desc_t *desc;
1760 void *src, *dest;
1762 i = 0;
1763 num = gi->num_param;
1764 desc = gdesc;
1766 while (num-- > 0) {
1768 desc++;
1770 /* if member not selected by bitmap, skip */
1771 if (_nscd_cfg_bitmap_is_not_set(gi->bitmap, i++))
1772 continue;
1774 src = (char *)group_src + desc->p_offset;
1775 dest = (char *)group_dest + desc->p_offset;
1778 * if variable length data, free and replace the old
1779 * with the new
1781 if (_nscd_cfg_flag_is_set(desc->pflag,
1782 NSCD_CFG_PFLAG_VLEN_DATA)) {
1783 _nscd_cfg_free_vlen_data_int(*(char **)dest);
1784 *(char **)dest = *(char **)src;
1785 *(char **)src = NULL;
1786 } else {
1788 * fixed length data, just copy it
1790 (void) memcpy(dest, src, desc->p_size);
1794 return (NSCD_SUCCESS);
1797 static nscd_rc_t
1798 _nscd_cfg_copy_group_data_out(
1799 nscd_cfg_param_desc_t *gdesc,
1800 void *group_dest,
1801 void *group_src)
1804 char *me = "_nscd_cfg_copy_group_data_out";
1805 void *src, *dest;
1806 int dlen;
1807 int num;
1808 nscd_cfg_group_info_t *gi;
1809 nscd_rc_t rc = NSCD_SUCCESS;
1810 nscd_cfg_param_desc_t *desc;
1812 if (group_dest == NULL) {
1813 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1814 (me, "input group_dest = NULL\n");
1815 return (NSCD_INVALID_ARGUMENT);
1818 gi = _nscd_cfg_get_gi(group_src);
1819 num = gi->num_param;
1820 desc = gdesc;
1822 while (num-- > 0) {
1824 desc++;
1826 dest = (char *)group_dest + desc->p_offset;
1827 src = (char *)group_src + desc->p_offset;
1830 * if variable length data, get the real
1831 * address and length of the data
1833 if (_nscd_cfg_flag_is_set(desc->pflag,
1834 NSCD_CFG_PFLAG_VLEN_DATA)) {
1835 src = _nscd_cfg_locate_vlen_data(src, &dlen);
1836 if (dlen == NULL)
1837 continue;
1841 * The nscd_true asks _nscd_cfg_copy_param_data
1842 * to set addr of the vlen data in 'dest' rather
1843 * than copying the data content
1845 rc = _nscd_cfg_copy_param_data(desc, dest, src,
1846 nscd_false, nscd_true);
1847 if (rc != NSCD_SUCCESS) {
1848 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1849 (me, "unable to copy param data for %s\n",
1850 desc->id.name);
1852 _nscd_cfg_free_vlen_data_group(gdesc,
1853 group_dest, nscd_false);
1855 free(group_dest);
1857 return (rc);
1862 * set group bitmap
1864 (void) memcpy(group_dest, group_src,
1865 sizeof (nscd_cfg_group_info_t));
1867 return (rc);
1872 * group_cfg is needed always; group_src may be NULL if
1873 * param_index not zero and pdata not NULL; group_cfg and
1874 * pdata should not be both non-NULL
1876 static nscd_rc_t
1877 _nscd_cfg_copy_group_data_merge(
1878 nscd_cfg_param_desc_t *gdesc,
1879 void **group_dest,
1880 void *group_src,
1881 void *group_cfg,
1882 int param_index,
1883 void *pdata)
1886 char *me = "_nscd_cfg_copy_group_data_merge";
1887 void *src, *dest, *tmp_dest = NULL;
1888 int num, i = 0;
1889 nscd_cfg_group_info_t *gi;
1890 nscd_rc_t rc = NSCD_SUCCESS;
1891 nscd_cfg_param_desc_t *desc;
1892 nscd_cfg_bitmap_t bitmap;
1894 if (group_dest == NULL) {
1895 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1896 (me, "input **group_dest == NULL\n");
1897 return (NSCD_INVALID_ARGUMENT);
1900 if (group_cfg == NULL) {
1901 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1902 (me, "input **group_cfg == NULL\n");
1903 return (NSCD_INVALID_ARGUMENT);
1906 if (param_index != NULL && pdata == NULL) {
1907 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1908 (me, "param_index != NULL but pdata == %p\n", pdata);
1909 return (NSCD_INVALID_ARGUMENT);
1912 tmp_dest = calloc(1, gdesc->g_size);
1913 if (tmp_dest == NULL)
1914 return (NSCD_NO_MEMORY);
1916 if (group_src != NULL)
1917 gi = _nscd_cfg_get_gi(group_src);
1918 else {
1919 gi = _nscd_cfg_get_gi(group_cfg);
1920 bitmap = NSCD_CFG_BITMAP_ZERO;
1923 num = gi->num_param;
1924 desc = gdesc;
1926 while (num-- > 0) {
1928 desc++;
1930 dest = (char *)tmp_dest + desc->p_offset;
1933 * if member not selected by bitmap in group_src,
1934 * get the member data in group_cfg
1936 if (_nscd_cfg_bitmap_is_not_set(gi->bitmap, i++) ||
1937 group_src == NULL) {
1938 src = (char *)group_cfg + desc->p_offset;
1939 } else
1940 src = (char *)group_src + desc->p_offset;
1942 if (desc->id.index == param_index) {
1944 /* use the param data in pdata if provided */
1945 src = pdata;
1946 _nscd_cfg_bitmap_set_nth(bitmap, i);
1950 * if variable length data, get to the data
1951 * instead of pointer to the data
1953 if (_nscd_cfg_flag_is_set(desc->pflag,
1954 NSCD_CFG_PFLAG_VLEN_DATA))
1955 src = *(char **)src;
1958 * nscd_true asks _nscd_cfg_copy_param_data to
1959 * set addr of the vlen data in 'dest' rather
1960 * than copying the data content
1962 rc = _nscd_cfg_copy_param_data(desc, dest, src,
1963 nscd_true, nscd_true);
1964 if (rc != NSCD_SUCCESS) {
1965 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1966 (me, "unable to copy param data for %s\n",
1967 desc->id.name);
1969 _nscd_cfg_free_vlen_data_group(gdesc,
1970 tmp_dest, nscd_true);
1972 free(tmp_dest);
1974 return (rc);
1978 *group_dest = tmp_dest;
1981 * set bitmap: if input is group data, use the one
1982 * given; if input is param data, use the one computed
1983 * above
1985 if (group_src != NULL)
1986 (void) memcpy(*group_dest, group_src,
1987 sizeof (nscd_cfg_group_info_t));
1988 else {
1989 gi = _nscd_cfg_get_gi(*group_dest);
1990 _nscd_cfg_bitmap_set(&gi->bitmap, bitmap);
1993 return (rc);
1996 /* ARGSUSED */
1997 nscd_rc_t
1998 _nscd_cfg_get(
1999 nscd_cfg_handle_t *handle,
2000 void **data,
2001 int *data_len,
2002 nscd_cfg_error_t **errorp)
2004 char *me = "_nscd_cfg_get";
2005 int dlen;
2006 nscd_rc_t rc = NSCD_SUCCESS;
2007 nscd_cfg_id_t *nswdb;
2008 nscd_cfg_param_desc_t *desc;
2009 void *cfg_data, *ptr = NULL;
2010 nscd_bool_t get_group = nscd_false;
2011 nscd_bool_t out = nscd_false;
2012 nscd_cfg_lock_t *lock = NULL;
2014 if (data_len != NULL)
2015 *data_len = 0;
2017 if (data == NULL) {
2018 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2019 (me, "input data = %p\n", data);
2020 return (NSCD_INVALID_ARGUMENT);
2023 *data = NULL;
2025 if (handle == NULL) {
2026 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2027 (me, "handle is NULL\n");
2028 return (NSCD_INVALID_ARGUMENT);
2031 nswdb = handle->nswdb;
2032 desc = (nscd_cfg_param_desc_t *)handle->desc;
2034 if (_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP))
2035 get_group = nscd_true;
2038 * locate the current value of the param or group
2039 * and lock the config data for reading
2041 rc = _nscd_cfg_locate_cfg_data(&cfg_data, nscd_true, desc,
2042 nswdb, get_group, NULL, &dlen, &lock);
2043 if (rc != NSCD_SUCCESS) {
2045 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2046 (me, "unable to locate config data\n");
2047 return (rc);
2049 } else if (cfg_data == NULL) /* NULL vlen data */
2050 goto done;
2052 ptr = calloc(1, dlen);
2053 if (ptr == NULL) {
2054 rc = NSCD_NO_MEMORY;
2055 goto error_exit;
2058 if (get_group == nscd_true) {
2060 rc = _nscd_cfg_copy_group_data_out(desc, ptr, cfg_data);
2061 if (rc != NSCD_SUCCESS) {
2062 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2063 (me, "unable to copy group data %p: "
2064 "error = %d\n", cfg_data, rc);
2066 goto error_exit;
2068 } else {
2070 * nscd_false asks _nscd_cfg_copy_param_data to
2071 * copy the data content rather than just setting
2072 * the addr of the vlen data in 'ptr'
2074 rc = _nscd_cfg_copy_param_data(desc, ptr, cfg_data,
2075 out, nscd_false);
2077 if (rc != NSCD_SUCCESS) {
2078 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2079 (me, "unable to copy param data %p: "
2080 "error = %d\n", cfg_data, rc);
2082 goto error_exit;
2086 *data = ptr;
2088 done:
2090 if (data_len != NULL)
2091 *data_len = dlen;
2093 _nscd_cfg_unlock(lock);
2095 return (NSCD_SUCCESS);
2097 error_exit:
2099 _nscd_cfg_unlock(lock);
2100 if (ptr != NULL)
2101 free(ptr);
2103 return (rc);
2107 * three type of data:
2108 * 1 - single param
2109 * desc is that of the param
2110 * 2 - single param to be sent in a group
2111 * a single bit is set in the bitmap,
2112 * desc is that of the group
2113 * 3 - group data
2114 * one of more bits are set in the bitmap,
2115 * desc is that of the group
2117 static nscd_rc_t
2118 _nscd_cfg_notify_s(
2119 nscd_cfg_param_desc_t *desc,
2120 nscd_cfg_id_t *nswdb,
2121 void *data,
2122 nscd_cfg_error_t **errorp)
2124 int i, num, is_group = 0;
2125 void *cookie = NULL;
2126 void *cdata;
2127 nscd_rc_t rc;
2128 nscd_cfg_flag_t dflag, dflag1;
2129 nscd_cfg_bitmap_t bitmap_s, bitmap_in, *bitmap_addr = NULL;
2130 nscd_cfg_group_info_t *gi;
2132 if (errorp != NULL)
2133 *errorp = NULL;
2136 * Set data flag going with data to be sent to the
2137 * verify/notify routines. To allow the config flag
2138 * be exipandable, set the bits one by one.
2140 dflag = NSCD_CFG_FLAG_ZERO;
2141 dflag = _nscd_cfg_flag_set(dflag, NSCD_CFG_DFLAG_STATIC_DATA);
2142 if (_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP)) {
2143 dflag = _nscd_cfg_flag_set(dflag, NSCD_CFG_DFLAG_GROUP);
2144 is_group = 1;
2146 if (nswdb != NULL &&
2147 strcmp(NSCD_CFG_NSW_ALLDB, nswdb->name) == 0)
2148 dflag = _nscd_cfg_flag_set(dflag,
2149 NSCD_CFG_DFLAG_SET_ALL_DB);
2152 * the bitmap in the input data may be replaced before
2153 * sending to the components, so save the bitmap for
2154 * later use
2156 if (is_group == 1) {
2157 gi = _nscd_cfg_get_gi(data);
2158 bitmap_in = gi->bitmap;
2159 bitmap_addr = &(gi->bitmap);
2161 if (_nscd_cfg_flag_is_set(desc->pflag,
2162 NSCD_CFG_PFLAG_INIT_SEND_WHOLE_GROUP))
2163 /* send the entire group just once */
2164 num = 1;
2166 else { /* send individual members one by one */
2168 num = desc->p_fn;
2171 * skip the first desc which is for the group
2172 * and get to the desc for the first member
2174 desc++;
2176 dflag = _nscd_cfg_flag_unset(dflag,
2177 NSCD_CFG_DFLAG_GROUP);
2179 } else {
2180 /* not group data, send the member once */
2181 num = 1;
2184 dflag1 = dflag;
2185 for (i = 0; i < num; i++, desc++) {
2187 dflag = dflag1;
2189 if (is_group == 0) {
2190 cdata = data;
2191 goto verify_data;
2194 if (_nscd_cfg_flag_is_set(desc->pflag,
2195 NSCD_CFG_PFLAG_SEND_BIT_SELECTED)) {
2197 /* set the bitmap to select just this member */
2198 bitmap_s = NSCD_CFG_BITMAP_ZERO;
2199 _nscd_cfg_bitmap_set_nth(bitmap_s, i);
2200 /* replace the bitmap in the input data */
2201 _nscd_cfg_bitmap_set(bitmap_addr, bitmap_s);
2204 * send the whole group but with only one
2205 * member selected
2207 cdata = data;
2209 dflag = _nscd_cfg_flag_set(dflag,
2210 NSCD_CFG_DFLAG_GROUP);
2211 dflag = _nscd_cfg_flag_set(dflag,
2212 NSCD_CFG_DFLAG_BIT_SELECTED);
2213 } else {
2215 * send param data or group data:
2216 * param data - non-xero desc->p_offset
2217 * group data - zero desc->p_offset
2219 cdata = (char *)data + desc->p_offset;
2222 * if variable length data, need to send pointer
2223 * to the data (not the address of the pointer)
2225 if (_nscd_cfg_flag_is_set(desc->pflag,
2226 NSCD_CFG_PFLAG_VLEN_DATA))
2227 cdata = *(char **)cdata;
2230 verify_data:
2232 if (desc->verify != NULL) {
2233 dflag = _nscd_cfg_flag_set(dflag,
2234 NSCD_CFG_DFLAG_VERIFY);
2235 rc = desc->verify(cdata, desc, nswdb,
2236 dflag, errorp, &cookie);
2237 if (rc != NSCD_SUCCESS)
2238 goto error_exit;
2241 if (desc->notify != NULL) {
2242 dflag = _nscd_cfg_flag_set(dflag,
2243 NSCD_CFG_DFLAG_NOTIFY);
2245 rc = desc->notify(data, desc, nswdb,
2246 dflag, errorp, cookie);
2247 if (rc != NSCD_SUCCESS)
2248 goto error_exit;
2252 rc = NSCD_SUCCESS;
2254 error_exit:
2256 /* restore the bitmap in the input data */
2257 if (bitmap_addr != NULL)
2258 _nscd_cfg_bitmap_set(bitmap_addr, bitmap_in);
2260 return (rc);
2264 * Convert string 'str' to data based on the data type in 'desc'.
2265 * 'data' points to the buffer in which the converted data
2266 * is placed. '*data_p' points to the buffer, or in the case
2267 * of a string data type, points to the untoched string (i.e.,
2268 * 'str').
2270 nscd_rc_t
2271 _nscd_cfg_str_to_data(
2272 nscd_cfg_param_desc_t *desc,
2273 char *str,
2274 void *data,
2275 void **data_p,
2276 nscd_cfg_error_t **errorp)
2279 char *me = "_nscd_cfg_str_to_data";
2280 char *c;
2281 nscd_cfg_bitmap_t bitmap;
2282 char msg[NSCD_CFG_MAX_ERR_MSG_LEN];
2283 nscd_rc_t rc = NSCD_CFG_DATA_CONVERSION_FAILED;
2285 if (desc == NULL || str == NULL || data == NULL) {
2286 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2287 (me, "ERROR: one of the following is NULL "
2288 "desc = %p, str = %p, data = %p, data_p = %p\n",
2289 desc, str, data, data_p);
2291 return (NSCD_INVALID_ARGUMENT);
2293 *data_p = data;
2295 /* if description is that of a group, return error */
2296 if (_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP)) {
2298 (void) snprintf(msg, sizeof (msg),
2299 gettext("single data specified for group %s"), desc->id.name);
2301 if (errorp != NULL)
2302 *errorp = _nscd_cfg_make_error(NSCD_INVALID_ARGUMENT,
2303 msg);
2305 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2306 (me, "ERROR: %s)\n", msg);
2308 return (NSCD_INVALID_ARGUMENT);
2312 if (desc->type == NSCD_CFG_DATA_STRING) {
2313 if (strcmp(str, NSCD_NULL) == 0)
2314 *(char **)data_p = NULL;
2315 else {
2316 /* remove the " char if quoted string */
2317 if (str[0] == '"') {
2318 c = str + strlen(str) - 1;
2319 if (*c == '"')
2320 *c = '\0';
2321 *(char **)data_p = str + 1;
2322 } else
2323 *(char **)data_p = str;
2326 return (NSCD_SUCCESS);
2329 if (str == NULL) {
2331 (void) snprintf(msg, sizeof (msg),
2332 gettext("data must be specified for %s"), desc->id.name);
2334 if (errorp != NULL)
2335 *errorp = _nscd_cfg_make_error(NSCD_INVALID_ARGUMENT,
2336 msg);
2338 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2339 (me, "ERROR: %s\n", msg);
2341 return (NSCD_INVALID_ARGUMENT);
2345 switch (desc->type) {
2347 case NSCD_CFG_DATA_BOOLEAN:
2349 if (strcasecmp(str, "yes") == 0)
2350 *(nscd_bool_t *)data = nscd_true;
2351 else if (strcasecmp(str, "no") == 0)
2352 *(nscd_bool_t *)data = nscd_false;
2353 else {
2355 (void) snprintf(msg, sizeof (msg),
2356 gettext("data (%s) must be 'yes' or 'no' for %s"),
2357 str, desc->id.name);
2359 if (errorp != NULL)
2360 *errorp = _nscd_cfg_make_error(NSCD_INVALID_ARGUMENT,
2361 msg);
2363 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2364 (me, "ERROR: %s\n", msg);
2366 return (NSCD_INVALID_ARGUMENT);
2369 break;
2371 case NSCD_CFG_DATA_INTEGER:
2373 errno = 0;
2374 *(int *)data = (int)strtol(str, (char **)NULL, 10);
2375 if (errno != NULL) {
2377 (void) snprintf(msg, sizeof (msg),
2378 gettext("unable to convert data (%s) for %s"),
2379 str, desc->id.name);
2381 if (errorp != NULL)
2382 *errorp = _nscd_cfg_make_error(rc, msg);
2384 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2385 (me, "ERROR: %s\n", msg);
2387 return (rc);
2390 break;
2392 case NSCD_CFG_DATA_BITMAP:
2394 errno = 0;
2395 bitmap = (nscd_cfg_bitmap_t)strtol(str, (char **)NULL, 10);
2396 if (errno != NULL) {
2398 (void) snprintf(msg, sizeof (msg),
2399 gettext("unable to convert data (%s) for %s"),
2400 str, desc->id.name);
2402 if (errorp != NULL)
2403 *errorp = _nscd_cfg_make_error(rc, msg);
2405 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2406 (me, "ERROR: %s\n", msg);
2408 return (rc);
2411 _nscd_cfg_bitmap_set(data, bitmap);
2413 break;
2417 return (NSCD_SUCCESS);
2421 nscd_rc_t
2422 _nscd_cfg_set(
2423 nscd_cfg_handle_t *handle,
2424 void *data,
2425 nscd_cfg_error_t **errorp)
2427 char *me = "_nscd_cfg_set";
2428 int dlen;
2429 nscd_cfg_id_t *nswdb;
2430 nscd_cfg_param_desc_t *desc, *gdesc;
2431 nscd_cfg_group_info_t *gi;
2432 char *nswdb_name, *param_name;
2433 void *pdata = NULL;
2434 void *cfg_data, *vdata_addr = NULL;
2435 nscd_bool_t get_group = 0;
2436 nscd_bool_t in = nscd_true;
2437 nscd_cfg_lock_t *lock = NULL;
2438 nscd_rc_t rc = NSCD_SUCCESS;
2440 if (handle == NULL) {
2441 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2442 (me, "handle is NULL\n");
2443 return (NSCD_INVALID_ARGUMENT);
2446 nswdb = handle->nswdb;
2447 desc = (nscd_cfg_param_desc_t *)handle->desc;
2448 if (nswdb == NULL)
2449 nswdb_name = "global";
2450 else
2451 nswdb_name = nswdb->name;
2452 param_name = desc->id.name;
2454 if (data == NULL && _nscd_cfg_flag_is_not_set(desc->pflag,
2455 NSCD_CFG_PFLAG_VLEN_DATA)) {
2456 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2457 (me, "data == NULL\n");
2458 return (NSCD_INVALID_ARGUMENT);
2461 if (_nscd_cfg_flag_is_set(desc->pflag,
2462 NSCD_CFG_PFLAG_UPDATE_SEND_WHOLE_GROUP) ||
2463 _nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP))
2464 get_group = nscd_true;
2467 * locate the current value of the param or group
2468 * and lock the config data for writing
2470 rc = _nscd_cfg_locate_cfg_data(&cfg_data, nscd_false, desc,
2471 nswdb, get_group, &vdata_addr, &dlen, &lock);
2472 if (rc != NSCD_SUCCESS) {
2473 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2474 (me, "unable to locate config data (rc = %d)\n", rc);
2475 return (rc);
2478 if (_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP) &&
2479 ((nscd_cfg_group_info_t *)cfg_data)->num_param !=
2480 ((nscd_cfg_group_info_t *)data)->num_param) {
2482 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2483 (me, "number of parameters in group <%s : %s> not equal: "
2484 "%d in input data, should be %d\n",
2485 NSCD_STR_OR_GLOBAL(nswdb_name),
2486 NSCD_STR_OR_NULL(param_name),
2487 ((nscd_cfg_group_info_t *)data)->num_param,
2488 ((nscd_cfg_group_info_t *)cfg_data)->num_param);
2490 rc = NSCD_INVALID_ARGUMENT;
2491 goto error_exit;
2495 * if variable length data, we want the address
2496 * of the pointer pointing to the data
2498 if (vdata_addr != NULL)
2499 cfg_data = vdata_addr;
2502 * just copy in the specified data, if no need
2503 * to verify the data or notify the associated
2504 * component
2506 if (get_group == nscd_true) {
2508 gdesc = &_nscd_cfg_param_desc[desc->g_index];
2510 rc = _nscd_cfg_copy_group_data_merge(
2511 gdesc, &pdata, data, cfg_data,
2512 desc->id.index, data);
2514 if (rc != NSCD_SUCCESS) {
2515 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2516 (me, "unable to copy group data <%s : %s>\n",
2517 NSCD_STR_OR_GLOBAL(nswdb_name),
2518 NSCD_STR_OR_NULL(param_name));
2520 goto error_exit;
2523 rc = _nscd_cfg_notify_s(gdesc, nswdb,
2524 pdata, errorp);
2526 } else
2527 rc = _nscd_cfg_notify_s(desc, nswdb, data,
2528 errorp);
2530 if (rc != NSCD_SUCCESS) {
2532 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2533 (me, "verifying/notifying of new configuration "
2534 "parameter <%s : %s> failed. %s\n",
2535 NSCD_STR_OR_GLOBAL(nswdb_name),
2536 param_name, (*errorp && (*errorp)->msg) ?
2537 (*errorp)->msg : "");
2539 goto error_exit;
2543 * Move the new config into the config store
2545 rc = NSCD_CFG_SET_PARAM_FAILED;
2546 if (_nscd_cfg_flag_is_set(desc->pflag,
2547 NSCD_CFG_PFLAG_GROUP)) {
2548 gi = _nscd_cfg_get_gi(pdata);
2549 rc = _nscd_cfg_copy_group_data_in(gdesc, gi,
2550 cfg_data, pdata);
2551 } else {
2553 * nscd_true asks _nscd_cfg_copy_param_data to
2554 * set addr of the vlen data in 'cfg_data' rather
2555 * than copying the data content
2557 if (pdata != NULL)
2558 _nscd_cfg_free_vlen_data_group(gdesc,
2559 pdata, in);
2561 rc = _nscd_cfg_copy_param_data(desc,
2562 cfg_data, data, in, nscd_true);
2565 if (rc != NSCD_SUCCESS) {
2567 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2568 (me, "unable to make new param data <%s : %s> current\n",
2569 NSCD_STR_OR_GLOBAL(nswdb_name),
2570 NSCD_STR_OR_NULL(param_name));
2573 error_exit:
2575 _nscd_cfg_unlock(lock);
2577 return (rc);
2580 nscd_rc_t
2581 _nscd_cfg_set_linked(
2582 nscd_cfg_handle_t *handle,
2583 void *data,
2584 nscd_cfg_error_t **errorp)
2586 char *me = "_nscd_cfg_set_linked";
2587 nscd_cfg_id_t *nswdb;
2588 nscd_cfg_handle_t *hl;
2589 nscd_cfg_param_desc_t *desc;
2590 char *nswdb_name, *param_name, *dbl;
2591 nscd_rc_t rc = NSCD_SUCCESS;
2592 nscd_cfg_nsw_spc_default_t *spc;
2593 int i;
2594 char msg[NSCD_CFG_MAX_ERR_MSG_LEN];
2596 if (handle == NULL) {
2597 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2598 (me, "handle is NULL\n");
2599 return (NSCD_INVALID_ARGUMENT);
2602 nswdb = handle->nswdb;
2603 desc = (nscd_cfg_param_desc_t *)handle->desc;
2606 * no need to do the special linking thing,
2607 * if a global param, or a group, or not a linked param
2609 if (nswdb == NULL || _nscd_cfg_flag_is_set(desc->pflag,
2610 NSCD_CFG_PFLAG_GROUP) ||
2611 _nscd_cfg_flag_is_not_set(desc->pflag,
2612 NSCD_CFG_PFLAG_LINKED))
2613 return (_nscd_cfg_set(handle, data, errorp));
2614 else
2615 nswdb_name = nswdb->name;
2616 param_name = desc->id.name;
2619 * if a param is linked to another, it can not be
2620 * changed directly
2622 for (i = 0; i < _nscd_cfg_num_link_default; i++) {
2624 if (_nscd_cfg_nsw_link_default[i].data == NULL)
2625 continue;
2627 if (strcmp(_nscd_cfg_nsw_link_default[i].db,
2628 nswdb_name) == 0 &&
2629 _nscd_cfg_nsw_link_default[i].group_off ==
2630 desc->g_offset &&
2631 _nscd_cfg_nsw_link_default[i].param_off ==
2632 desc->p_offset) {
2634 rc = NSCD_CFG_READ_ONLY;
2636 (void) snprintf(msg, sizeof (msg),
2637 gettext("value of \'%s\' not changeable, "
2638 "change that of \'%s\' instead"),
2639 nswdb->name, "passwd");
2641 if (errorp != NULL)
2642 *errorp = _nscd_cfg_make_error(rc, msg);
2644 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2645 (me, "ERROR: %s\n", msg);
2647 return (rc);
2652 * if a param is linked from another, it should be verify
2653 * and changed first
2655 for (i = 0; i < _nscd_cfg_num_link_default; i++) {
2657 if (_nscd_cfg_nsw_link_default[i].data == NULL)
2658 continue;
2660 spc = _nscd_cfg_nsw_link_default[i].data;
2662 if (strcmp(spc->db, nswdb_name) == 0 &&
2663 spc->group_off == desc->g_offset &&
2664 spc->param_off == desc->p_offset) {
2666 rc = _nscd_cfg_set(handle, data, errorp);
2667 if (rc != NSCD_SUCCESS)
2668 return (rc);
2669 break;
2674 * then change all those linked to the one that has been changed
2676 for (i = 0; i < _nscd_cfg_num_link_default; i++) {
2678 if (_nscd_cfg_nsw_link_default[i].data == NULL)
2679 continue;
2681 spc = _nscd_cfg_nsw_link_default[i].data;
2683 if (strcmp(spc->db, nswdb_name) == 0 &&
2684 spc->group_off == desc->g_offset &&
2685 spc->param_off == desc->p_offset &&
2686 _nscd_cfg_nsw_link_default[i].group_off ==
2687 desc->g_offset &&
2688 _nscd_cfg_nsw_link_default[i].param_off ==
2689 desc->p_offset) {
2691 dbl = _nscd_cfg_nsw_link_default[i].db;
2693 rc = _nscd_cfg_get_handle(param_name, dbl,
2694 &hl, errorp);
2695 if (rc != NSCD_SUCCESS)
2696 return (rc);
2697 rc = _nscd_cfg_set(hl, data, errorp);
2698 _nscd_cfg_free_handle(hl);
2699 if (rc != NSCD_SUCCESS)
2700 return (rc);
2704 return (_nscd_cfg_set(handle, data, errorp));
2708 * Return a list of comma-separated database names that
2709 * have at least one of the input sources (the srcs array)
2710 * appears in their configured nsswitch policy string.
2711 * That is, if srcs contains "ldap" and "passwd: files ldap"
2712 * "group: files ldap" are in /etc/nsswitch.conf, then
2713 * "passwd,group" will be returned. The return string
2714 * should be freed by the caller.
2716 * For compat nsswitch configuration, "group" and/or
2717 * "passwd,user_attr,shadow,audit_user" (not "group_compat"
2718 * or "passwd_compat") will be returned. Note that the
2719 * user_attr, shadow, and audit_user databases share the
2720 * same policy with the passwd database.
2722 * For example, if srcs has "ldap" and in /etc/nsswitch.conf,
2723 * there are:
2724 * passwd: compat
2725 * passwd_compat: ldap
2726 * group: compat
2727 * group_compat: ldap
2728 * netgroup: ldap
2729 * then "netgroup,passwd,group,user_attr,shadow,audit_user"
2730 * will be returned.
2732 char *
2733 _nscd_srcs_in_db_nsw_policy(
2734 int num_src,
2735 char **srcs)
2737 uint8_t i, j, n = 0, nc = 0;
2738 uint8_t compat_grp = 0, compat_pwd = 0;
2739 uint8_t *db;
2740 uint8_t *db_compat;
2741 int dlen = 0;
2742 nscd_cfg_nsw_db_data_t *dbcfg;
2743 nscd_cfg_switch_t *sw;
2744 char *outstr = NULL;
2745 char *dbname;
2747 db = (uint8_t *)calloc(_nscd_cfg_num_nsw_db, sizeof (uint8_t));
2748 if (db == NULL)
2749 return (NULL);
2751 db_compat = (uint8_t *)calloc(_nscd_cfg_num_nsw_db,
2752 sizeof (uint8_t));
2753 if (db_compat == NULL) {
2754 free(db);
2755 return (NULL);
2758 for (i = 0; i < _nscd_cfg_num_nsw_db; i++) {
2760 (void) rw_rdlock(&nscd_cfg_nsw_db_data_rwlock[i]);
2762 dbcfg = &nscd_cfg_nsw_db_data_current[i];
2763 sw = &dbcfg->sw;
2764 if (sw->nsw_config_string == NULL) {
2765 (void) rw_unlock(&nscd_cfg_nsw_db_data_rwlock[i]);
2766 continue;
2769 dbname = _nscd_cfg_nsw_db[i].name;
2770 for (j = 0; j < num_src; j++) {
2771 if (strstr(sw->nsw_config_string, srcs[j]) !=
2772 NULL) {
2773 db[n++] = i;
2774 dlen += strlen(dbname) + 1;
2775 } else if (strcmp(sw->nsw_config_string,
2776 "compat") == 0) {
2777 if (strcmp(dbname, "passwd") == 0) {
2778 compat_pwd = 1;
2779 dlen += 7;
2780 } else if (strcmp(dbname, "group") == 0) {
2781 compat_grp = 1;
2782 dlen += 6;
2783 } else {
2784 db_compat[nc++] = i;
2785 dlen += strlen(dbname) + 1;
2790 (void) rw_unlock(&nscd_cfg_nsw_db_data_rwlock[i]);
2793 if (dlen != 0)
2794 outstr = (char *)calloc(1, dlen);
2795 if (outstr == NULL) {
2796 free(db_compat);
2797 free(db);
2798 return (NULL);
2801 for (j = 0; j < n; j++) {
2802 dbname = _nscd_cfg_nsw_db[db[j]].name;
2803 if (strstr(dbname, "group_compat") != NULL) {
2804 if (compat_grp == 1)
2805 dbname = "group";
2806 else
2807 continue;
2808 } else if (strstr(dbname, "passwd_compat") != NULL) {
2809 if (compat_pwd == 1)
2810 dbname = "passwd";
2811 else
2812 continue;
2815 (void) strlcat(outstr, dbname, dlen);
2816 (void) strlcat(outstr, ",", dlen);
2819 for (j = 0; j < nc; j++) {
2820 dbname = _nscd_cfg_nsw_db[db_compat[j]].name;
2821 if (compat_pwd == 1) {
2822 (void) strlcat(outstr, dbname, dlen);
2823 (void) strlcat(outstr, ",", dlen);
2827 /* remove the last comma */
2828 i = strlen(outstr) - 1;
2829 if (outstr[i] == ',')
2830 outstr[i] = '\0';
2832 free(db);
2833 free(db_compat);
2834 return (outstr);