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 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2012 Milan Jurik. All rights reserved.
25 */
26
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"
38
39 typedef struct {
40 rwlock_t *global;
41 rwlock_t *alldb;
42 rwlock_t *nswdb;
43 } nscd_cfg_lock_t;
44
45 static rwlock_t cfg_paramDB_rwlock = DEFAULTRWLOCK;
46 static nscd_db_t *cfg_paramDB = NULL;
47
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;
54
55 extern int _nscd_cfg_num_nsw_src_all;
56 extern nscd_cfg_id_t *_nscd_cfg_nsw_src_all;
57
58 nscd_cfg_error_t *
_nscd_cfg_make_error(nscd_rc_t rc,char * msg)59 _nscd_cfg_make_error(
60 nscd_rc_t rc,
61 char *msg)
62 {
63
64 nscd_cfg_error_t *ret;
65 int size, msglen;
66
67 msglen = (msg != NULL ? strlen(msg) + 1 : 0);
68
69 size = sizeof (nscd_cfg_error_t) + msglen;
70
71 ret = calloc(1, size);
72 if (ret == NULL)
73 return (NULL);
74
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);
80 }
81
82 return (ret);
83 }
84
85 static nscd_rc_t
_nscd_cfg_get_list(nscd_cfg_list_t ** list,nscd_cfg_list_type_t type)86 _nscd_cfg_get_list(
87 nscd_cfg_list_t **list,
88 nscd_cfg_list_type_t type)
89 {
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;
97
98 if (list == NULL) {
99 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
100 (me, "invalid argument: list = %p\n", list);
101
102 return (NSCD_INVALID_ARGUMENT);
103 }
104 *list = NULL;
105
106 switch (type) {
107 case NSCD_CFG_LIST_NSW_DB:
108
109 num = _nscd_cfg_num_nsw_db;
110 l = &_nscd_cfg_nsw_db[0];
111 break;
112
113 case NSCD_CFG_LIST_NSW_SRC:
114
115 num = _nscd_cfg_num_nsw_src_all;
116 l = _nscd_cfg_nsw_src_all;
117 break;
118
119 case NSCD_CFG_LIST_PARAM:
120
121 num = _nscd_cfg_num_param;
122 pl = &_nscd_cfg_param_desc[0];
123 break;
124
125 case NSCD_CFG_LIST_STAT:
126
127 num = _nscd_cfg_num_stat;
128 sl = &_nscd_cfg_stat_desc[0];
129 break;
130
131 default:
132 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
133 (me, "invalid argument: type (%d)\n", type);
134
135 return (NSCD_INVALID_ARGUMENT);
136 }
137
138 size = sizeof (nscd_cfg_list_t) + sizeof (nscd_cfg_id_t *) * (num + 1);
139
140 ret = calloc(1, size);
141 if (ret == NULL)
142 return (NSCD_NO_MEMORY);
143
144 ret->num = num;
145 p = (char *)ret + sizeof (nscd_cfg_list_t);
146 ret->list = (nscd_cfg_id_t **)p;
147
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];
157 }
158
159 *list = ret;
160
161 return (NSCD_SUCCESS);
162 }
163
164 nscd_rc_t
_nscd_cfg_get_param_desc_list(nscd_cfg_param_desc_list_t ** list)165 _nscd_cfg_get_param_desc_list(
166 nscd_cfg_param_desc_list_t **list)
167 {
168 return (_nscd_cfg_get_list((nscd_cfg_list_t **)list,
169 NSCD_CFG_LIST_PARAM));
170 }
171
172 /*
173 * FUNCTION: _nscd_cfg_create_paramDB
174 *
175 * Create the internal config parameter database
176 */
177 static nscd_db_t *
_nscd_cfg_create_paramDB()178 _nscd_cfg_create_paramDB()
179 {
180
181 nscd_db_t *ret;
182
183 (void) rw_wrlock(&cfg_paramDB_rwlock);
184
185 ret = _nscd_alloc_db(NSCD_DB_SIZE_MEDIUM);
186
187 if (ret != NULL)
188 cfg_paramDB = ret;
189
190 (void) rw_unlock(&cfg_paramDB_rwlock);
191
192 return (ret);
193 }
194
195 /*
196 * FUNCTION: _nscd_cfg_add_index_entry
197 *
198 * Add a config index entry (a name to index mapping)
199 * to the internal configuration database.
200 */
201 static nscd_rc_t
_nscd_cfg_add_index_entry(char * name,int index,nscd_cfg_list_type_t type)202 _nscd_cfg_add_index_entry(
203 char *name,
204 int index,
205 nscd_cfg_list_type_t type)
206 {
207 int *idx;
208 int size;
209 int dbe_type;
210 nscd_db_entry_t *db_entry;
211
212 if (name == NULL)
213 return (NSCD_INVALID_ARGUMENT);
214
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;
223
224 size = sizeof (int);
225
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);
230
231 idx = (int *)*(db_entry->data_array);
232 *idx = index;
233
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);
238
239 return (NSCD_SUCCESS);
240 }
241
242 /*
243 * FUNCTION: _nscd_cfg_get_index
244 *
245 * Get the index of a config data item by searching the internal config
246 * database. Do not free the returned data.
247 */
248 static int
_nscd_cfg_get_index(char * name,nscd_cfg_list_type_t type)249 _nscd_cfg_get_index(
250 char *name,
251 nscd_cfg_list_type_t type)
252 {
253 int index = -1, dbe_type;
254 const nscd_db_entry_t *db_entry;
255
256 if (name == NULL)
257 return (-1);
258
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);
269
270 db_entry = _nscd_get_db_entry(cfg_paramDB, dbe_type,
271 (const char *)name, NSCD_GET_FIRST_DB_ENTRY, 0);
272
273 if (db_entry != NULL)
274 index = *(int *)*(db_entry->data_array);
275
276 return (index);
277 }
278
279 static nscd_rc_t
_nscd_cfg_verify_group_info(nscd_cfg_group_info_t * g_info,nscd_cfg_param_desc_t * gdesc)280 _nscd_cfg_verify_group_info(
281 nscd_cfg_group_info_t *g_info,
282 nscd_cfg_param_desc_t *gdesc)
283 {
284
285 char *me = "_nscd_cfg_verify_group_info";
286 void *vp;
287 nscd_cfg_group_info_t *gi;
288
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;
297
298 }
299
300 if (g_info->num_param == gi->num_param &&
301 _nscd_cfg_bitmap_is_equal(g_info->bitmap, gi->bitmap))
302 return (NSCD_SUCCESS);
303
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));
310
311 return (NSCD_CFG_PARAM_DESC_ERROR);
312
313 }
314
315
316 static nscd_rc_t
_nscd_cfg_init_nsw()317 _nscd_cfg_init_nsw()
318 {
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 };
324
325 nscd_cfg_id_t *list[2] = { _nscd_cfg_nsw_db, NULL};
326
327 list[1] = _nscd_cfg_nsw_src_all;
328
329 for (j = 0; j < 2; j++) {
330
331 if (j == 0)
332 num = _nscd_cfg_num_nsw_db + 1;
333 else
334 num = _nscd_cfg_num_nsw_src_all;
335
336 for (i = 0; i < num; i++) {
337
338 /*
339 * _nscd_cfg_nsw_alldb is the id for the
340 * special ALLDB (defaults for all db)
341 */
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;
348 }
349
350 if (id->name == NULL)
351 continue;
352
353 if ((rc = _nscd_cfg_add_index_entry(id->name,
354 idx, type[j])) != NSCD_SUCCESS) {
355
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);
360
361 _nscd_free_db(cfg_paramDB);
362 return (rc);
363 }
364 }
365 }
366
367 return (NSCD_SUCCESS);
368 }
369
370 static nscd_rc_t
_nscd_cfg_init_param()371 _nscd_cfg_init_param()
372 {
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;
381
382 if (_nscd_cfg_create_paramDB() == NULL)
383 return (NSCD_NO_MEMORY);
384
385 desc = &_nscd_cfg_param_desc[0];
386
387 /*
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
393 */
394 for (i = 0; i < _nscd_cfg_num_param + 1; i++, desc++) {
395
396 id = (nscd_cfg_id_t *)desc;
397
398 if (_nscd_cfg_flag_is_set(desc->pflag,
399 NSCD_CFG_PFLAG_GROUP)) {
400
401 if (gdesc != NULL) {
402 g_info.num_param = fn;
403 gdesc->p_fn = fn;
404
405 if ((rc = _nscd_cfg_verify_group_info(
406 &g_info, gdesc)) != NSCD_SUCCESS)
407 return (rc);
408 }
409
410 gi = i;
411 fn = 0;
412 gdesc = desc;
413 g_info.bitmap = NSCD_CFG_BITMAP_ZERO;
414
415 /*
416 * set the notify/verify functions
417 */
418 nfunc = (void *)gdesc->notify;
419 vfunc = (void *)gdesc->verify;
420 } else {
421 if (i == 0) {
422
423 _NSCD_LOG(NSCD_LOG_CONFIG,
424 NSCD_LOG_LEVEL_ERROR)
425 (me, "ERROR: first parameter "
426 "description is not for a group\n");
427
428 return (NSCD_CFG_PARAM_DESC_ERROR);
429 }
430
431 /*
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
436 */
437 _nscd_cfg_bitmap_set_nth(g_info.bitmap, fn);
438
439 desc->p_fn = fn++;
440
441 /*
442 * set the notify/verify functions
443 */
444 if (desc->notify == NSCD_CFG_FUNC_NOTIFY_AS_GROUP) {
445 (void) memcpy(&desc->notify, &nfunc,
446 sizeof (void *));
447 }
448 if (desc->verify == NSCD_CFG_FUNC_VERIFY_AS_GROUP) {
449 (void) memcpy(&desc->verify, &vfunc,
450 sizeof (void *));
451 }
452 }
453
454 /* if end of list reached, we are done */
455 if (i == _nscd_cfg_num_param)
456 break;
457
458 desc->g_index = gi;
459
460 id->index = i;
461
462 if ((rc = _nscd_cfg_add_index_entry(id->name,
463 i, type)) != NSCD_SUCCESS) {
464
465 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
466 (me, "unable to add index entry for parameter "
467 "%s\n", id->name);
468
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);
475 }
476 }
477
478 return (_nscd_cfg_init_nsw());
479 }
480
481 static nscd_rc_t
_nscd_cfg_init_stat()482 _nscd_cfg_init_stat()
483 {
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;
492
493 desc = &_nscd_cfg_stat_desc[0];
494
495 /*
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
501 */
502 for (i = 0; i < _nscd_cfg_num_stat + 1; i++, desc++) {
503
504 id = (nscd_cfg_id_t *)desc;
505
506 if (_nscd_cfg_flag_is_set(desc->sflag,
507 NSCD_CFG_SFLAG_GROUP)) {
508
509 if (gdesc != NULL) {
510 g_info.num_param = fn;
511 gdesc->s_fn = fn;
512
513 if (g_info.num_param !=
514 gdesc->gi.num_param ||
515 !_nscd_cfg_bitmap_is_equal(
516 g_info.bitmap, gdesc->gi.bitmap)) {
517
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));
531
532 exit(1);
533 return (NSCD_CFG_STAT_DESC_ERROR);
534 }
535 }
536
537 gi = i;
538 fn = 0;
539 gdesc = desc;
540 g_info.bitmap = NSCD_CFG_BITMAP_ZERO;
541
542 /*
543 * set the get_stat function
544 */
545 gsfunc = (void *)gdesc->get_stat;
546 } else {
547 if (i == 0) {
548
549 _NSCD_LOG(NSCD_LOG_CONFIG,
550 NSCD_LOG_LEVEL_ERROR)
551 (me, "ERROR: first stat "
552 "description is not for a group\n");
553
554 return (NSCD_CFG_STAT_DESC_ERROR);
555 }
556
557 /*
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
562 */
563 _nscd_cfg_bitmap_set_nth(g_info.bitmap, fn);
564
565 desc->s_fn = fn++;
566
567 /*
568 * set the get_stat function
569 */
570 if (desc->get_stat == NSCD_CFG_FUNC_GET_STAT_AS_GROUP) {
571 (void) memcpy(&desc->get_stat, &gsfunc,
572 sizeof (void *));
573 }
574 }
575
576 /* if end of list reached, we are done */
577 if (i == _nscd_cfg_num_stat)
578 break;
579
580 desc->g_index = gi;
581
582 id->index = i;
583
584 if ((rc = _nscd_cfg_add_index_entry(id->name,
585 i, type)) != NSCD_SUCCESS) {
586
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);
590
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);
597 }
598 }
599
600 return (NSCD_SUCCESS);
601 }
602
603 static nscd_rc_t
_nscd_cfg_copy_vlen_data(void * data,void ** new_data_p,nscd_cfg_param_desc_t * desc,int * data_len,nscd_bool_t in)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)
610 {
611 int len, dlen;
612 nscd_cfg_vlen_data_t *v = NULL;
613
614 *new_data_p = NULL;
615 *data_len = 0;
616
617 /* it is OK if there is nothing to copy */
618 if (data == NULL)
619 return (NSCD_SUCCESS);
620
621 /*
622 * if copy to the config store we need to allocate space
623 * for the extra vlen header
624 */
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 {
630 /*
631 * should not be here, since for now
632 * only string variable length data
633 * is supported
634 */
635 *new_data_p = NULL;
636 return (NSCD_CFG_PARAM_DESC_ERROR);
637 }
638
639 v = calloc(1, len);
640 if (v == NULL) {
641 *new_data_p = NULL;
642 return (NSCD_NO_MEMORY);
643 }
644
645 /*
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.
651 */
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;
660 }
661 *data_len = dlen;
662
663 return (NSCD_SUCCESS);
664 }
665
666 static void
_nscd_cfg_free_vlen_data_int(void * data)667 _nscd_cfg_free_vlen_data_int(
668 void *data)
669 {
670 nscd_cfg_vlen_data_t *v = NULL;
671 void *p;
672
673 if (data == NULL)
674 return;
675
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);
680 }
681
682 static nscd_rc_t
_nscd_cfg_set_vlen_data_int(void * src,void * dest,nscd_bool_t global)683 _nscd_cfg_set_vlen_data_int(
684 void *src,
685 void *dest,
686 nscd_bool_t global)
687 {
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;
693
694 desc = &_nscd_cfg_param_desc[0];
695 for (i = 0; i < _nscd_cfg_num_param; i++, desc++) {
696
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;
705
706 if (_nscd_cfg_flag_is_set(desc->pflag,
707 NSCD_CFG_PFLAG_VLEN_DATA)) {
708
709 offset = desc->g_offset + desc->p_offset;
710
711 s = (char *)src + offset;
712 cptr = *(char **)s;
713
714 rc = _nscd_cfg_copy_vlen_data(cptr, &new,
715 desc, &dlen, nscd_true);
716 if (rc != NSCD_SUCCESS)
717 return (rc);
718
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);
723
724 *(char **)d = new;
725 }
726 }
727
728 return (NSCD_SUCCESS);
729 }
730
731 static void *
_nscd_cfg_locate_vlen_data(void * cfg_data,int * len)732 _nscd_cfg_locate_vlen_data(
733 void *cfg_data,
734 int *len)
735 {
736 void *ptr, *ret;
737
738 ptr = *(char **)cfg_data;
739 ret = ptr;
740 if (ret == NULL) {
741 *len = 0;
742 return (NULL);
743 }
744 ptr = (char *)ptr - sizeof (nscd_cfg_vlen_data_t);
745 *len = ((nscd_cfg_vlen_data_t *)ptr)->len;
746
747 return (ret);
748 }
749
750 static void
_nscd_cfg_lock(nscd_bool_t is_read,nscd_cfg_lock_t * cfglock)751 _nscd_cfg_lock(
752 nscd_bool_t is_read,
753 nscd_cfg_lock_t *cfglock)
754 {
755
756 int (*lockfunc)(rwlock_t *);
757
758 if (cfglock == NULL)
759 return;
760
761 if (is_read == nscd_true)
762 lockfunc = rw_rdlock;
763 else
764 lockfunc = rw_wrlock;
765
766 if (cfglock->global != NULL) {
767
768 (lockfunc)(cfglock->global);
769 return;
770 }
771
772 if (cfglock->alldb != NULL)
773 (lockfunc)(cfglock->alldb);
774
775 if (cfglock->nswdb != NULL)
776 (lockfunc)(cfglock->nswdb);
777 }
778
779 static void
_nscd_cfg_unlock(nscd_cfg_lock_t * cfglock)780 _nscd_cfg_unlock(
781 nscd_cfg_lock_t *cfglock)
782 {
783 if (cfglock == NULL)
784 return;
785
786 if (cfglock->global != NULL) {
787
788 (void) rw_unlock(cfglock->global);
789 free(cfglock);
790 return;
791 }
792
793 if (cfglock->nswdb != NULL)
794 (void) rw_unlock(cfglock->nswdb);
795
796 if (cfglock->alldb != NULL)
797 (void) rw_unlock(cfglock->alldb);
798
799 free(cfglock);
800 }
801
802 /*
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.
807 */
808 static nscd_rc_t
_nscd_cfg_locate_cfg_data(void ** cfg_data,nscd_bool_t is_read,nscd_cfg_param_desc_t * desc,nscd_cfg_id_t * nswdb,nscd_bool_t get_group,void ** vlen_data_addr,int * len,nscd_cfg_lock_t ** cfglock)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)
818 {
819 int offset;
820
821 *cfg_data = NULL;
822 if (len != NULL)
823 *len = 0;
824 if (vlen_data_addr != NULL)
825 *vlen_data_addr = NULL;
826
827 if (cfglock != NULL) {
828 *cfglock = calloc(1, sizeof (nscd_cfg_lock_t));
829 if (*cfglock == NULL)
830 return (NSCD_NO_MEMORY);
831 }
832
833 /* assume if nswdb is NULL, the param is a global one */
834 if (nswdb == NULL) {
835
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;
840
841 if (cfglock != NULL)
842 (*cfglock)->global = nscd_cfg_global_rwlock;
843
844 } else if (nswdb->index == NSCD_CFG_NSW_ALLDB_INDEX) {
845
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;
851
852 if (cfglock != NULL)
853 (*cfglock)->alldb = nscd_cfg_nsw_alldb_rwlock;
854
855 } else {
856
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;
863
864 if (cfglock != NULL) {
865 (*cfglock)->nswdb =
866 &nscd_cfg_nsw_db_data_rwlock[nswdb->index];
867
868 (*cfglock)->alldb = nscd_cfg_nsw_alldb_rwlock;
869 }
870 }
871
872 /* lock the config data */
873 if (cfglock != NULL)
874 _nscd_cfg_lock(is_read, *cfglock);
875
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);
885 }
886
887 if (len != NULL) {
888 if (get_group == nscd_true)
889 *len = desc->g_size;
890 else
891 *len = desc->p_size;
892 }
893
894 return (NSCD_SUCCESS);
895 }
896
897 /*
898 * perform the preliminary (range) check on 'data' based on the
899 * datatype (desc->datatype) of the config parameter
900 */
901 nscd_rc_t
_nscd_cfg_prelim_check(nscd_cfg_param_desc_t * desc,void * data,nscd_cfg_error_t ** errorp)902 _nscd_cfg_prelim_check(
903 nscd_cfg_param_desc_t *desc,
904 void *data,
905 nscd_cfg_error_t **errorp)
906 {
907
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;
914
915 if ((nscd_cfg_str_check_t *)desc->p_check == NULL)
916 return (NSCD_SUCCESS);
917
918 switch (desc->type) {
919
920 case NSCD_CFG_DATA_STRING:
921
922 sc = (nscd_cfg_str_check_t *)desc->p_check;
923 if (sc->must_not_null == nscd_true && data == NULL) {
924
925 if (errorp == NULL)
926 break;
927
928 (void) snprintf(msg, sizeof (msg),
929 gettext("data must be specified for %s"),
930 desc->id.name);
931
932 break;
933 }
934
935 if (data == NULL) {
936 rc = NSCD_SUCCESS;
937 break;
938 }
939
940 if (sc->maxlen != 0 &&
941 strlen((char *)data) > sc->maxlen) {
942
943 if (errorp == NULL)
944 break;
945
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;
951 }
952
953 rc = NSCD_SUCCESS;
954
955 break;
956
957 case NSCD_CFG_DATA_INTEGER:
958
959 ic = (nscd_cfg_int_check_t *)desc->p_check;
960 if (*(int *)data > ic->max ||
961 *(int *)data < ic->min) {
962
963 if (errorp == NULL)
964 break;
965
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);
971
972 break;
973 }
974
975 rc = NSCD_SUCCESS;
976
977 break;
978
979 case NSCD_CFG_DATA_BITMAP:
980
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)) {
984
985 if (errorp == NULL)
986 break;
987
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;
996 }
997
998 rc = NSCD_SUCCESS;
999
1000 break;
1001 }
1002
1003 if (rc != NSCD_SUCCESS && errorp != NULL) {
1004 *errorp = _nscd_cfg_make_error(rc, msg);
1005
1006 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
1007 (me, "invalid argument: %s\n", (*errorp)->msg);
1008 }
1009
1010 return (rc);
1011 }
1012
1013 static nscd_rc_t
_nscd_cfg_notify_i(nscd_cfg_param_desc_t * desc,nscd_cfg_id_t * nswdb,int * skip,nscd_cfg_error_t ** errorp)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)
1019 {
1020
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;
1029
1030 if (errorp != NULL)
1031 *errorp = NULL;
1032
1033 if (skip == NULL)
1034 skip = &skip_bk;
1035
1036 *skip = 0;
1037
1038 if (_nscd_cfg_flag_is_not_set(desc->pflag,
1039 NSCD_CFG_PFLAG_GROUP)) {
1040
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);
1045
1046 return (NSCD_CFG_PARAM_DESC_ERROR);
1047 }
1048
1049 /*
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.
1053 */
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);
1062
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;
1068
1069 /*
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
1073 */
1074 gi = _nscd_cfg_get_gi(cfg_data);
1075 bitmap_c = gi->bitmap;
1076 bitmap_addr = &(gi->bitmap);
1077
1078 /*
1079 * the elements in this group will all be handled
1080 * so the caller can skip them
1081 */
1082 *skip = desc->p_fn;
1083
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;
1088
1089 else { /* send individual members one by one */
1090
1091 num = desc->p_fn;
1092
1093 /*
1094 * skip the first desc which is for the group
1095 * and get to the desc for the first member
1096 */
1097 desc++;
1098
1099 dflag = _nscd_cfg_flag_unset(dflag,
1100 NSCD_CFG_DFLAG_GROUP);
1101 }
1102
1103 dflag1 = dflag;
1104 for (i = 0; i < num; i++, desc++) {
1105
1106 dflag = dflag1;
1107
1108 if (_nscd_cfg_flag_is_set(desc->pflag,
1109 NSCD_CFG_PFLAG_SEND_BIT_SELECTED)) {
1110
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);
1116
1117 /*
1118 * send the whole group but with only one
1119 * member selected
1120 */
1121 cdata = cfg_data;
1122
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 {
1128 /*
1129 * send param data or group data:
1130 * param data - non-xero desc->p_offset
1131 * group data - zero desc->p_offset
1132 */
1133 cdata = (char *)cfg_data + desc->p_offset;
1134
1135 /*
1136 * if variable length data, need to send pointer
1137 * to the data (not the address of the pointer)
1138 */
1139 if (_nscd_cfg_flag_is_set(desc->pflag,
1140 NSCD_CFG_PFLAG_VLEN_DATA))
1141 cdata = *(char **)cdata;
1142 }
1143
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;
1151 }
1152
1153 if (desc->notify != NULL) {
1154 dflag = _nscd_cfg_flag_set(dflag,
1155 NSCD_CFG_DFLAG_NOTIFY);
1156
1157 rc = desc->notify(cfg_data, desc, nswdb,
1158 dflag, errorp, cookie);
1159 if (rc != NSCD_SUCCESS)
1160 goto error;
1161 }
1162 }
1163
1164 rc = NSCD_SUCCESS;
1165
1166 /* restore the bitmap in the cfg data */
1167 _nscd_cfg_bitmap_set(bitmap_addr, bitmap_c);
1168
1169 error:
1170
1171 return (rc);
1172
1173 }
1174
1175 static nscd_rc_t
_nscd_cfg_notify_init(nscd_cfg_error_t ** errorp)1176 _nscd_cfg_notify_init(
1177 nscd_cfg_error_t **errorp)
1178 {
1179 int i, j, skip;
1180 nscd_rc_t rc;
1181 nscd_cfg_id_t *nswdb = NULL;
1182 nscd_cfg_param_desc_t *desc;
1183
1184 if (errorp != NULL)
1185 *errorp = NULL;
1186
1187 for (i = 0; i < _nscd_cfg_num_param; i++) {
1188
1189 desc = &_nscd_cfg_param_desc[i];
1190
1191 if (_nscd_cfg_flag_is_set(desc->pflag,
1192 NSCD_CFG_PFLAG_GLOBAL)) { /* global cfg data */
1193
1194 rc = _nscd_cfg_notify_i(desc, NULL, &skip, errorp);
1195 } else {
1196
1197 /*
1198 * if use defaults for all nsswitch database,
1199 * send the config data to verify/notify once
1200 */
1201 if (_nscd_cfg_flag_is_set(desc->pflag,
1202 NSCD_CFG_PFLAG_INIT_SET_ALL_DB)) {
1203
1204 nswdb = &_nscd_cfg_nsw_alldb;
1205
1206 rc = _nscd_cfg_notify_i(desc, nswdb,
1207 &skip, errorp);
1208 } else { /* send data once for each nsw db */
1209
1210 for (j = 0; j < _nscd_cfg_num_nsw_db; j++) {
1211
1212 nswdb = &_nscd_cfg_nsw_db[j];
1213
1214 rc = _nscd_cfg_notify_i(desc,
1215 nswdb, &skip, errorp);
1216
1217 if (rc != NSCD_SUCCESS)
1218 break;
1219 }
1220 }
1221 }
1222
1223 if (rc != NSCD_SUCCESS)
1224 return (rc);
1225
1226 i += skip;
1227 }
1228
1229 return (NSCD_SUCCESS);
1230 }
1231
1232 nscd_rc_t
_nscd_cfg_init(nscd_cfg_error_t ** errorp)1233 _nscd_cfg_init(
1234 nscd_cfg_error_t **errorp)
1235 {
1236
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;
1243
1244 if (errorp != NULL)
1245 *errorp = NULL;
1246
1247 rc = _nscd_cfg_init_param();
1248 if (rc != NSCD_SUCCESS)
1249 return (rc);
1250
1251 rc = _nscd_cfg_init_stat();
1252 if (rc != NSCD_SUCCESS)
1253 return (rc);
1254
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);
1259
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);
1264
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);
1269
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, USYNC_THREAD, NULL);
1274
1275 *nscd_cfg_global_current = nscd_cfg_global_default;
1276
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);
1281
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);
1286
1287 /* set per switch db config to the default for all db's */
1288 for (i = 0; i < _nscd_cfg_num_nsw_db; i++) {
1289
1290 nscd_cfg_nsw_db_data_current[i] =
1291 nscd_cfg_nsw_db_data_default;
1292
1293 (void) rwlock_init(&nscd_cfg_nsw_db_data_rwlock[i],
1294 0, NULL);
1295 }
1296
1297 /* add db specific defaults */
1298 for (i = 0; i < _nscd_cfg_num_nsw_default; i++) {
1299
1300 if (_nscd_cfg_nsw_spc_default[i].data == NULL)
1301 continue;
1302
1303 if (_nscd_cfg_nsw_spc_default[i].db != dbni) {
1304 for (j = 0; j < _nscd_cfg_num_nsw_db; j++) {
1305
1306 if (strcmp(_nscd_cfg_nsw_db[j].name,
1307 _nscd_cfg_nsw_spc_default[i].db) != 0)
1308 continue;
1309
1310 dbi = _nscd_cfg_nsw_db[j].index;
1311 dbni = _nscd_cfg_nsw_db[j].name;
1312 break;
1313 }
1314 }
1315
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;
1319
1320 src = _nscd_cfg_nsw_spc_default[i].data;
1321 datalen = _nscd_cfg_nsw_spc_default[i].data_len;
1322
1323 (void) memcpy(dest, src, datalen);
1324 }
1325
1326 /* add db specific defaults via links */
1327 for (i = 0; i < _nscd_cfg_num_link_default; i++) {
1328
1329 if (_nscd_cfg_nsw_link_default[i].data == NULL)
1330 continue;
1331
1332 spc = _nscd_cfg_nsw_link_default[i].data;
1333
1334 if (_nscd_cfg_nsw_link_default[i].db != dbni) {
1335 for (j = 0; j < _nscd_cfg_num_nsw_db; j++) {
1336
1337 if (strcmp(_nscd_cfg_nsw_db[j].name,
1338 _nscd_cfg_nsw_link_default[i].db) != 0)
1339 continue;
1340
1341 dbi = _nscd_cfg_nsw_db[j].index;
1342 dbni = _nscd_cfg_nsw_db[j].name;
1343 break;
1344 }
1345 }
1346
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;
1350
1351 if (_nscd_cfg_nsw_db[j].name != dbnj) {
1352 for (j = 0; j < _nscd_cfg_num_nsw_db; j++) {
1353
1354 if (strcmp(spc->db,
1355 _nscd_cfg_nsw_db[j].name) != 0)
1356 continue;
1357
1358 dbnj = _nscd_cfg_nsw_db[j].name;
1359 dbj = _nscd_cfg_nsw_db[j].index;
1360 break;
1361 }
1362 }
1363
1364 src = (char *)&nscd_cfg_nsw_db_data_current[dbj] +
1365 spc->group_off + spc->param_off;
1366 datalen = spc->data_len;
1367
1368 (void) memcpy(dest, src, datalen);
1369 }
1370
1371 /* fix up variable length fields */
1372 for (i = 0; i < _nscd_cfg_num_nsw_db; i++) {
1373
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);
1379 }
1380
1381 nscd_cfg_nsw_alldb_rwlock = calloc(1, sizeof (rwlock_t));
1382 if (nscd_cfg_nsw_alldb_rwlock == NULL)
1383 return (NSCD_NO_MEMORY);
1384
1385 (void) rwlock_init(nscd_cfg_nsw_alldb_rwlock, 0, NULL);
1386
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);
1392
1393 /*
1394 * notify and send the configuration data to
1395 * the nscd components
1396 */
1397 rc = _nscd_cfg_notify_init(errorp);
1398 if (rc != NSCD_SUCCESS)
1399 return (rc);
1400
1401 return (NSCD_SUCCESS);
1402 }
1403
1404 static nscd_rc_t
_nscd_cfg_get_handle_common(nscd_cfg_list_type_t type,char * name,char * nswdb_name,nscd_cfg_handle_t ** handle,nscd_cfg_error_t ** errorp)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)
1411 {
1412
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;
1421
1422 if (handle == NULL) {
1423
1424 (void) snprintf(msg, sizeof (msg),
1425 gettext("address of handle not specified"));
1426 if (errorp)
1427 *errorp = _nscd_cfg_make_error(rc, msg);
1428
1429 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
1430 (me, "invalid argument: %s\n", msg);
1431
1432 return (rc);
1433 }
1434
1435 *handle = NULL;
1436
1437 if (name == NULL) {
1438
1439 (void) snprintf(msg, sizeof (msg),
1440 gettext("name not specified"));
1441 if (errorp)
1442 *errorp = _nscd_cfg_make_error(rc, msg);
1443
1444 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
1445 (me, "invalid argument: %s\n");
1446
1447 return (rc);
1448 }
1449
1450 h = calloc(1, sizeof (nscd_cfg_handle_t));
1451 if (h == NULL)
1452 return (NSCD_NO_MEMORY);
1453 h->type = type;
1454
1455 if (type == NSCD_CFG_LIST_PARAM)
1456 desc_str = gettext("configuration parameter");
1457 else
1458 desc_str = gettext("statistics");
1459
1460 /* get param or stat descriptor */
1461 i = _nscd_cfg_get_index(name, type);
1462 if (i != -1) {
1463
1464 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
1465 (me, "%s: index of %s is %d\n", desc_str, name, i);
1466
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);
1472
1473 /* hidden params are not exposed */
1474 if (_nscd_cfg_flag_is_set(
1475 pdesc->pflag, NSCD_CFG_PFLAG_HIDDEN))
1476 i = -1;
1477
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);
1485 }
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);
1491 }
1492 }
1493
1494 if (i == -1) {
1495
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);
1500
1501 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1502 (me, "%s\n", msg);
1503
1504 free(h);
1505 return (rc);
1506 }
1507
1508 /*
1509 * if the param/stat is not a global one, we need to
1510 * know which nsswitch database we are dealing with
1511 */
1512 if (is_global == 0) {
1513 if (nswdb_name == NULL) {
1514
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);
1520
1521 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1522 (me, "%s for non-global param or stat %s\n",
1523 msg, name);
1524
1525 free(h);
1526 return (rc);
1527 }
1528 } else {
1529
1530 if (nswdb_name != NULL) {
1531
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);
1537
1538 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1539 (me, "%s %s\n", msg, name);
1540
1541 free(h);
1542 return (rc);
1543 }
1544
1545 *handle = h;
1546 return (NSCD_SUCCESS);
1547 }
1548
1549 /* get nsw DB id */
1550 i = _nscd_cfg_get_index(nswdb_name, NSCD_CFG_LIST_NSW_DB);
1551 if (i != -1) {
1552
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];
1557
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 {
1562
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);
1568
1569 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1570 (me, "%s\n", msg);
1571
1572 free(h);
1573 return (NSCD_CFG_UNSUPPORTED_SWITCH_DB);
1574 }
1575
1576 *handle = h;
1577
1578 return (NSCD_SUCCESS);
1579 }
1580
1581 nscd_rc_t
_nscd_cfg_get_handle(char * param_name,char * nswdb_name,nscd_cfg_handle_t ** handle,nscd_cfg_error_t ** errorp)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)
1587 {
1588
1589 return (_nscd_cfg_get_handle_common(NSCD_CFG_LIST_PARAM,
1590 param_name, nswdb_name, handle, errorp));
1591 }
1592
1593 nscd_rc_t
_nscd_cfg_get_stat_handle(char * stat_name,char * nswdb_name,nscd_cfg_handle_t ** handle,nscd_cfg_error_t ** errorp)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)
1599 {
1600
1601 return (_nscd_cfg_get_handle_common(NSCD_CFG_LIST_STAT,
1602 stat_name, nswdb_name, handle, errorp));
1603 }
1604
1605 void
_nscd_cfg_free_handle(nscd_cfg_handle_t * handle)1606 _nscd_cfg_free_handle(
1607 nscd_cfg_handle_t *handle)
1608 {
1609
1610 free(handle);
1611
1612 }
1613
1614 static void
_nscd_cfg_free_vlen_data_group(nscd_cfg_param_desc_t * gdesc,void * group_data,nscd_bool_t in)1615 _nscd_cfg_free_vlen_data_group(
1616 nscd_cfg_param_desc_t *gdesc,
1617 void *group_data,
1618 nscd_bool_t in)
1619 {
1620 int num;
1621 void *dest, *ptr;
1622 nscd_cfg_param_desc_t *desc;
1623
1624 desc = gdesc;
1625
1626 num = ((nscd_cfg_group_info_t *)group_data)->num_param;
1627
1628 while (num-- > 0) {
1629
1630 desc++;
1631
1632 /* skip fixed length data */
1633 if (_nscd_cfg_flag_is_not_set(desc->pflag,
1634 NSCD_CFG_PFLAG_VLEN_DATA))
1635 continue;
1636
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);
1645 }
1646 }
1647
1648 void
_nscd_cfg_free_param_data(void * data)1649 _nscd_cfg_free_param_data(
1650 void *data)
1651 {
1652
1653 if (data == NULL)
1654 return;
1655
1656 free(data);
1657 }
1658
1659 void
_nscd_cfg_free_group_data(nscd_cfg_handle_t * handle,void * data)1660 _nscd_cfg_free_group_data(
1661 nscd_cfg_handle_t *handle,
1662 void *data)
1663 {
1664
1665 nscd_cfg_param_desc_t *desc;
1666 nscd_cfg_group_info_t *gi;
1667
1668 if (handle == NULL || data == NULL)
1669 return;
1670
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;
1675
1676 _nscd_cfg_free_vlen_data_group(desc, data, nscd_false);
1677
1678 free(data);
1679 }
1680
1681 void
_nscd_cfg_free_error(nscd_cfg_error_t * error)1682 _nscd_cfg_free_error(
1683 nscd_cfg_error_t *error)
1684 {
1685
1686 if (error == NULL)
1687 return;
1688
1689 free(error);
1690 }
1691
1692 static nscd_rc_t
_nscd_cfg_copy_param_data(nscd_cfg_param_desc_t * desc,void * dest,void * pdata,nscd_bool_t in,nscd_bool_t set_addr)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)
1699 {
1700
1701 char *me = "_nscd_cfg_copy_param_data";
1702 void *tmp;
1703 int dlen;
1704 nscd_rc_t rc = NSCD_SUCCESS;
1705
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);
1710 }
1711
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;
1717 }
1718
1719
1720 /* variable length data from this point on */
1721
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;
1726
1727 if (in == nscd_true) { /* data to internal */
1728
1729 /* free the variable length data in the config store */
1730 if (*(char **)dest != NULL)
1731 _nscd_cfg_free_vlen_data_int(*(char **)dest);
1732 }
1733
1734 if (set_addr == nscd_true) {
1735 /*
1736 * set the addr of the vlen data
1737 */
1738 *(char **)dest = tmp;
1739 } else {
1740 /*
1741 * copy the data content (not address)
1742 */
1743 (void) memcpy(dest, tmp, dlen);
1744 }
1745
1746 done:
1747
1748 return (rc);
1749 }
1750
1751 static nscd_rc_t
_nscd_cfg_copy_group_data_in(nscd_cfg_param_desc_t * gdesc,nscd_cfg_group_info_t * gi,void * group_dest,void * group_src)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)
1757 {
1758 int i, num;
1759 nscd_cfg_param_desc_t *desc;
1760 void *src, *dest;
1761
1762 i = 0;
1763 num = gi->num_param;
1764 desc = gdesc;
1765
1766 while (num-- > 0) {
1767
1768 desc++;
1769
1770 /* if member not selected by bitmap, skip */
1771 if (_nscd_cfg_bitmap_is_not_set(gi->bitmap, i++))
1772 continue;
1773
1774 src = (char *)group_src + desc->p_offset;
1775 dest = (char *)group_dest + desc->p_offset;
1776
1777 /*
1778 * if variable length data, free and replace the old
1779 * with the new
1780 */
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 {
1787 /*
1788 * fixed length data, just copy it
1789 */
1790 (void) memcpy(dest, src, desc->p_size);
1791 }
1792 }
1793
1794 return (NSCD_SUCCESS);
1795 }
1796
1797 static nscd_rc_t
_nscd_cfg_copy_group_data_out(nscd_cfg_param_desc_t * gdesc,void * group_dest,void * group_src)1798 _nscd_cfg_copy_group_data_out(
1799 nscd_cfg_param_desc_t *gdesc,
1800 void *group_dest,
1801 void *group_src)
1802 {
1803
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;
1811
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);
1816 }
1817
1818 gi = _nscd_cfg_get_gi(group_src);
1819 num = gi->num_param;
1820 desc = gdesc;
1821
1822 while (num-- > 0) {
1823
1824 desc++;
1825
1826 dest = (char *)group_dest + desc->p_offset;
1827 src = (char *)group_src + desc->p_offset;
1828
1829 /*
1830 * if variable length data, get the real
1831 * address and length of the data
1832 */
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 == 0)
1837 continue;
1838 }
1839
1840 /*
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
1844 */
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);
1851
1852 _nscd_cfg_free_vlen_data_group(gdesc,
1853 group_dest, nscd_false);
1854
1855 free(group_dest);
1856
1857 return (rc);
1858 }
1859 }
1860
1861 /*
1862 * set group bitmap
1863 */
1864 (void) memcpy(group_dest, group_src,
1865 sizeof (nscd_cfg_group_info_t));
1866
1867 return (rc);
1868 }
1869
1870
1871 /*
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
1875 */
1876 static nscd_rc_t
_nscd_cfg_copy_group_data_merge(nscd_cfg_param_desc_t * gdesc,void ** group_dest,void * group_src,void * group_cfg,int param_index,void * pdata)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)
1884 {
1885
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;
1893
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);
1898 }
1899
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);
1904 }
1905
1906 if (param_index != 0 && 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);
1910 }
1911
1912 tmp_dest = calloc(1, gdesc->g_size);
1913 if (tmp_dest == NULL)
1914 return (NSCD_NO_MEMORY);
1915
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;
1921 }
1922
1923 num = gi->num_param;
1924 desc = gdesc;
1925
1926 while (num-- > 0) {
1927
1928 desc++;
1929
1930 dest = (char *)tmp_dest + desc->p_offset;
1931
1932 /*
1933 * if member not selected by bitmap in group_src,
1934 * get the member data in group_cfg
1935 */
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;
1941
1942 if (desc->id.index == param_index) {
1943
1944 /* use the param data in pdata if provided */
1945 src = pdata;
1946 _nscd_cfg_bitmap_set_nth(bitmap, i);
1947 }
1948
1949 /*
1950 * if variable length data, get to the data
1951 * instead of pointer to the data
1952 */
1953 if (_nscd_cfg_flag_is_set(desc->pflag,
1954 NSCD_CFG_PFLAG_VLEN_DATA))
1955 src = *(char **)src;
1956
1957 /*
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
1961 */
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);
1968
1969 _nscd_cfg_free_vlen_data_group(gdesc,
1970 tmp_dest, nscd_true);
1971
1972 free(tmp_dest);
1973
1974 return (rc);
1975 }
1976 }
1977
1978 *group_dest = tmp_dest;
1979
1980 /*
1981 * set bitmap: if input is group data, use the one
1982 * given; if input is param data, use the one computed
1983 * above
1984 */
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);
1991 }
1992
1993 return (rc);
1994 }
1995
1996 /* ARGSUSED */
1997 nscd_rc_t
_nscd_cfg_get(nscd_cfg_handle_t * handle,void ** data,int * data_len,nscd_cfg_error_t ** errorp)1998 _nscd_cfg_get(
1999 nscd_cfg_handle_t *handle,
2000 void **data,
2001 int *data_len,
2002 nscd_cfg_error_t **errorp)
2003 {
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;
2013
2014 if (data_len != NULL)
2015 *data_len = 0;
2016
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);
2021 }
2022
2023 *data = NULL;
2024
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);
2029 }
2030
2031 nswdb = handle->nswdb;
2032 desc = (nscd_cfg_param_desc_t *)handle->desc;
2033
2034 if (_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP))
2035 get_group = nscd_true;
2036
2037 /*
2038 * locate the current value of the param or group
2039 * and lock the config data for reading
2040 */
2041 rc = _nscd_cfg_locate_cfg_data(&cfg_data, nscd_true, desc,
2042 nswdb, get_group, NULL, &dlen, &lock);
2043 if (rc != NSCD_SUCCESS) {
2044
2045 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2046 (me, "unable to locate config data\n");
2047 return (rc);
2048
2049 } else if (cfg_data == NULL) /* NULL vlen data */
2050 goto done;
2051
2052 ptr = calloc(1, dlen);
2053 if (ptr == NULL) {
2054 rc = NSCD_NO_MEMORY;
2055 goto error_exit;
2056 }
2057
2058 if (get_group == nscd_true) {
2059
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);
2065
2066 goto error_exit;
2067 }
2068 } else {
2069 /*
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'
2073 */
2074 rc = _nscd_cfg_copy_param_data(desc, ptr, cfg_data,
2075 out, nscd_false);
2076
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);
2081
2082 goto error_exit;
2083 }
2084 }
2085
2086 *data = ptr;
2087
2088 done:
2089
2090 if (data_len != NULL)
2091 *data_len = dlen;
2092
2093 _nscd_cfg_unlock(lock);
2094
2095 return (NSCD_SUCCESS);
2096
2097 error_exit:
2098
2099 _nscd_cfg_unlock(lock);
2100 if (ptr != NULL)
2101 free(ptr);
2102
2103 return (rc);
2104 }
2105
2106 /*
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
2116 */
2117 static nscd_rc_t
_nscd_cfg_notify_s(nscd_cfg_param_desc_t * desc,nscd_cfg_id_t * nswdb,void * data,nscd_cfg_error_t ** errorp)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)
2123 {
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;
2131
2132 if (errorp != NULL)
2133 *errorp = NULL;
2134
2135 /*
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.
2139 */
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;
2145 }
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);
2150
2151 /*
2152 * the bitmap in the input data may be replaced before
2153 * sending to the components, so save the bitmap for
2154 * later use
2155 */
2156 if (is_group == 1) {
2157 gi = _nscd_cfg_get_gi(data);
2158 bitmap_in = gi->bitmap;
2159 bitmap_addr = &(gi->bitmap);
2160
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;
2165
2166 else { /* send individual members one by one */
2167
2168 num = desc->p_fn;
2169
2170 /*
2171 * skip the first desc which is for the group
2172 * and get to the desc for the first member
2173 */
2174 desc++;
2175
2176 dflag = _nscd_cfg_flag_unset(dflag,
2177 NSCD_CFG_DFLAG_GROUP);
2178 }
2179 } else {
2180 /* not group data, send the member once */
2181 num = 1;
2182 }
2183
2184 dflag1 = dflag;
2185 for (i = 0; i < num; i++, desc++) {
2186
2187 dflag = dflag1;
2188
2189 if (is_group == 0) {
2190 cdata = data;
2191 goto verify_data;
2192 }
2193
2194 if (_nscd_cfg_flag_is_set(desc->pflag,
2195 NSCD_CFG_PFLAG_SEND_BIT_SELECTED)) {
2196
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);
2202
2203 /*
2204 * send the whole group but with only one
2205 * member selected
2206 */
2207 cdata = data;
2208
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 {
2214 /*
2215 * send param data or group data:
2216 * param data - non-xero desc->p_offset
2217 * group data - zero desc->p_offset
2218 */
2219 cdata = (char *)data + desc->p_offset;
2220
2221 /*
2222 * if variable length data, need to send pointer
2223 * to the data (not the address of the pointer)
2224 */
2225 if (_nscd_cfg_flag_is_set(desc->pflag,
2226 NSCD_CFG_PFLAG_VLEN_DATA))
2227 cdata = *(char **)cdata;
2228 }
2229
2230 verify_data:
2231
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;
2239 }
2240
2241 if (desc->notify != NULL) {
2242 dflag = _nscd_cfg_flag_set(dflag,
2243 NSCD_CFG_DFLAG_NOTIFY);
2244
2245 rc = desc->notify(data, desc, nswdb,
2246 dflag, errorp, cookie);
2247 if (rc != NSCD_SUCCESS)
2248 goto error_exit;
2249 }
2250 }
2251
2252 rc = NSCD_SUCCESS;
2253
2254 error_exit:
2255
2256 /* restore the bitmap in the input data */
2257 if (bitmap_addr != NULL)
2258 _nscd_cfg_bitmap_set(bitmap_addr, bitmap_in);
2259
2260 return (rc);
2261 }
2262
2263 /*
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').
2269 */
2270 nscd_rc_t
_nscd_cfg_str_to_data(nscd_cfg_param_desc_t * desc,char * str,void * data,void ** data_p,nscd_cfg_error_t ** errorp)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)
2277 {
2278
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;
2284
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);
2290
2291 return (NSCD_INVALID_ARGUMENT);
2292 }
2293 *data_p = data;
2294
2295 /* if description is that of a group, return error */
2296 if (_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP)) {
2297
2298 (void) snprintf(msg, sizeof (msg),
2299 gettext("single data specified for group %s"), desc->id.name);
2300
2301 if (errorp != NULL)
2302 *errorp = _nscd_cfg_make_error(NSCD_INVALID_ARGUMENT,
2303 msg);
2304
2305 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2306 (me, "ERROR: %s)\n", msg);
2307
2308 return (NSCD_INVALID_ARGUMENT);
2309
2310 }
2311
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;
2324
2325 }
2326 return (NSCD_SUCCESS);
2327 }
2328
2329 if (str == NULL) {
2330
2331 (void) snprintf(msg, sizeof (msg),
2332 gettext("data must be specified for %s"), desc->id.name);
2333
2334 if (errorp != NULL)
2335 *errorp = _nscd_cfg_make_error(NSCD_INVALID_ARGUMENT,
2336 msg);
2337
2338 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2339 (me, "ERROR: %s\n", msg);
2340
2341 return (NSCD_INVALID_ARGUMENT);
2342
2343 }
2344
2345 switch (desc->type) {
2346
2347 case NSCD_CFG_DATA_BOOLEAN:
2348
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 {
2354 (void) snprintf(msg, sizeof (msg),
2355 gettext("data (%s) must be 'yes' or 'no' for %s"),
2356 str, desc->id.name);
2357
2358 if (errorp != NULL)
2359 *errorp = _nscd_cfg_make_error(
2360 NSCD_INVALID_ARGUMENT, msg);
2361
2362 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2363 (me, "ERROR: %s\n", msg);
2364
2365 return (NSCD_INVALID_ARGUMENT);
2366 }
2367
2368 break;
2369
2370 case NSCD_CFG_DATA_INTEGER:
2371
2372 errno = 0;
2373 *(int *)data = (int)strtol(str, NULL, 10);
2374 if (errno != 0) {
2375
2376 (void) snprintf(msg, sizeof (msg),
2377 gettext("unable to convert data (%s) for %s"),
2378 str, desc->id.name);
2379
2380 if (errorp != NULL)
2381 *errorp = _nscd_cfg_make_error(rc, msg);
2382
2383 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2384 (me, "ERROR: %s\n", msg);
2385
2386 return (rc);
2387 }
2388
2389 break;
2390
2391 case NSCD_CFG_DATA_BITMAP:
2392
2393 errno = 0;
2394 bitmap = (nscd_cfg_bitmap_t)strtol(str, NULL, 10);
2395 if (errno != 0) {
2396
2397 (void) snprintf(msg, sizeof (msg),
2398 gettext("unable to convert data (%s) for %s"),
2399 str, desc->id.name);
2400
2401 if (errorp != NULL)
2402 *errorp = _nscd_cfg_make_error(rc, msg);
2403
2404 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2405 (me, "ERROR: %s\n", msg);
2406
2407 return (rc);
2408 }
2409
2410 _nscd_cfg_bitmap_set(data, bitmap);
2411
2412 break;
2413
2414 }
2415
2416 return (NSCD_SUCCESS);
2417 }
2418
2419
2420 nscd_rc_t
_nscd_cfg_set(nscd_cfg_handle_t * handle,void * data,nscd_cfg_error_t ** errorp)2421 _nscd_cfg_set(
2422 nscd_cfg_handle_t *handle,
2423 void *data,
2424 nscd_cfg_error_t **errorp)
2425 {
2426 char *me = "_nscd_cfg_set";
2427 int dlen;
2428 nscd_cfg_id_t *nswdb;
2429 nscd_cfg_param_desc_t *desc, *gdesc;
2430 nscd_cfg_group_info_t *gi;
2431 char *nswdb_name, *param_name;
2432 void *pdata = NULL;
2433 void *cfg_data, *vdata_addr = NULL;
2434 nscd_bool_t get_group = 0;
2435 nscd_bool_t in = nscd_true;
2436 nscd_cfg_lock_t *lock = NULL;
2437 nscd_rc_t rc = NSCD_SUCCESS;
2438
2439 if (handle == NULL) {
2440 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2441 (me, "handle is NULL\n");
2442 return (NSCD_INVALID_ARGUMENT);
2443 }
2444
2445 nswdb = handle->nswdb;
2446 desc = (nscd_cfg_param_desc_t *)handle->desc;
2447 if (nswdb == NULL)
2448 nswdb_name = "global";
2449 else
2450 nswdb_name = nswdb->name;
2451 param_name = desc->id.name;
2452
2453 if (data == NULL && _nscd_cfg_flag_is_not_set(desc->pflag,
2454 NSCD_CFG_PFLAG_VLEN_DATA)) {
2455 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2456 (me, "data == NULL\n");
2457 return (NSCD_INVALID_ARGUMENT);
2458 }
2459
2460 if (_nscd_cfg_flag_is_set(desc->pflag,
2461 NSCD_CFG_PFLAG_UPDATE_SEND_WHOLE_GROUP) ||
2462 _nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP))
2463 get_group = nscd_true;
2464
2465 /*
2466 * locate the current value of the param or group
2467 * and lock the config data for writing
2468 */
2469 rc = _nscd_cfg_locate_cfg_data(&cfg_data, nscd_false, desc,
2470 nswdb, get_group, &vdata_addr, &dlen, &lock);
2471 if (rc != NSCD_SUCCESS) {
2472 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2473 (me, "unable to locate config data (rc = %d)\n", rc);
2474 return (rc);
2475 }
2476
2477 if (_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP) &&
2478 ((nscd_cfg_group_info_t *)cfg_data)->num_param !=
2479 ((nscd_cfg_group_info_t *)data)->num_param) {
2480
2481 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2482 (me, "number of parameters in group <%s : %s> not equal: "
2483 "%d in input data, should be %d\n",
2484 NSCD_STR_OR_GLOBAL(nswdb_name),
2485 NSCD_STR_OR_NULL(param_name),
2486 ((nscd_cfg_group_info_t *)data)->num_param,
2487 ((nscd_cfg_group_info_t *)cfg_data)->num_param);
2488
2489 rc = NSCD_INVALID_ARGUMENT;
2490 goto error_exit;
2491 }
2492
2493 /*
2494 * if variable length data, we want the address
2495 * of the pointer pointing to the data
2496 */
2497 if (vdata_addr != NULL)
2498 cfg_data = vdata_addr;
2499
2500 /*
2501 * just copy in the specified data, if no need
2502 * to verify the data or notify the associated
2503 * component
2504 */
2505 if (get_group == nscd_true) {
2506
2507 gdesc = &_nscd_cfg_param_desc[desc->g_index];
2508
2509 rc = _nscd_cfg_copy_group_data_merge(
2510 gdesc, &pdata, data, cfg_data,
2511 desc->id.index, data);
2512
2513 if (rc != NSCD_SUCCESS) {
2514 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2515 (me, "unable to copy group data <%s : %s>\n",
2516 NSCD_STR_OR_GLOBAL(nswdb_name),
2517 NSCD_STR_OR_NULL(param_name));
2518
2519 goto error_exit;
2520 }
2521
2522 rc = _nscd_cfg_notify_s(gdesc, nswdb,
2523 pdata, errorp);
2524
2525 } else
2526 rc = _nscd_cfg_notify_s(desc, nswdb, data,
2527 errorp);
2528
2529 if (rc != NSCD_SUCCESS) {
2530
2531 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2532 (me, "verifying/notifying of new configuration "
2533 "parameter <%s : %s> failed. %s\n",
2534 NSCD_STR_OR_GLOBAL(nswdb_name),
2535 param_name, (*errorp && (*errorp)->msg) ?
2536 (*errorp)->msg : "");
2537
2538 goto error_exit;
2539 }
2540
2541 /*
2542 * Move the new config into the config store
2543 */
2544 rc = NSCD_CFG_SET_PARAM_FAILED;
2545 if (_nscd_cfg_flag_is_set(desc->pflag,
2546 NSCD_CFG_PFLAG_GROUP)) {
2547 gi = _nscd_cfg_get_gi(pdata);
2548 rc = _nscd_cfg_copy_group_data_in(gdesc, gi,
2549 cfg_data, pdata);
2550 } else {
2551 /*
2552 * nscd_true asks _nscd_cfg_copy_param_data to
2553 * set addr of the vlen data in 'cfg_data' rather
2554 * than copying the data content
2555 */
2556 if (pdata != NULL)
2557 _nscd_cfg_free_vlen_data_group(gdesc,
2558 pdata, in);
2559
2560 rc = _nscd_cfg_copy_param_data(desc,
2561 cfg_data, data, in, nscd_true);
2562 }
2563
2564 if (rc != NSCD_SUCCESS) {
2565
2566 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2567 (me, "unable to make new param data <%s : %s> current\n",
2568 NSCD_STR_OR_GLOBAL(nswdb_name),
2569 NSCD_STR_OR_NULL(param_name));
2570 }
2571
2572 error_exit:
2573
2574 _nscd_cfg_unlock(lock);
2575
2576 return (rc);
2577 }
2578
2579 nscd_rc_t
_nscd_cfg_set_linked(nscd_cfg_handle_t * handle,void * data,nscd_cfg_error_t ** errorp)2580 _nscd_cfg_set_linked(
2581 nscd_cfg_handle_t *handle,
2582 void *data,
2583 nscd_cfg_error_t **errorp)
2584 {
2585 char *me = "_nscd_cfg_set_linked";
2586 nscd_cfg_id_t *nswdb;
2587 nscd_cfg_handle_t *hl;
2588 nscd_cfg_param_desc_t *desc;
2589 char *nswdb_name, *param_name, *dbl;
2590 nscd_rc_t rc = NSCD_SUCCESS;
2591 nscd_cfg_nsw_spc_default_t *spc;
2592 int i;
2593 char msg[NSCD_CFG_MAX_ERR_MSG_LEN];
2594
2595 if (handle == NULL) {
2596 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2597 (me, "handle is NULL\n");
2598 return (NSCD_INVALID_ARGUMENT);
2599 }
2600
2601 nswdb = handle->nswdb;
2602 desc = (nscd_cfg_param_desc_t *)handle->desc;
2603
2604 /*
2605 * no need to do the special linking thing,
2606 * if a global param, or a group, or not a linked param
2607 */
2608 if (nswdb == NULL || _nscd_cfg_flag_is_set(desc->pflag,
2609 NSCD_CFG_PFLAG_GROUP) ||
2610 _nscd_cfg_flag_is_not_set(desc->pflag,
2611 NSCD_CFG_PFLAG_LINKED))
2612 return (_nscd_cfg_set(handle, data, errorp));
2613 else
2614 nswdb_name = nswdb->name;
2615 param_name = desc->id.name;
2616
2617 /*
2618 * if a param is linked to another, it can not be
2619 * changed directly
2620 */
2621 for (i = 0; i < _nscd_cfg_num_link_default; i++) {
2622
2623 if (_nscd_cfg_nsw_link_default[i].data == NULL)
2624 continue;
2625
2626 if (strcmp(_nscd_cfg_nsw_link_default[i].db,
2627 nswdb_name) == 0 &&
2628 _nscd_cfg_nsw_link_default[i].group_off ==
2629 desc->g_offset &&
2630 _nscd_cfg_nsw_link_default[i].param_off ==
2631 desc->p_offset) {
2632
2633 rc = NSCD_CFG_READ_ONLY;
2634
2635 (void) snprintf(msg, sizeof (msg),
2636 gettext("value of \'%s\' not changeable, "
2637 "change that of \'%s\' instead"),
2638 nswdb->name, "passwd");
2639
2640 if (errorp != NULL)
2641 *errorp = _nscd_cfg_make_error(rc, msg);
2642
2643 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2644 (me, "ERROR: %s\n", msg);
2645
2646 return (rc);
2647 }
2648 }
2649
2650 /*
2651 * if a param is linked from another, it should be verify
2652 * and changed first
2653 */
2654 for (i = 0; i < _nscd_cfg_num_link_default; i++) {
2655
2656 if (_nscd_cfg_nsw_link_default[i].data == NULL)
2657 continue;
2658
2659 spc = _nscd_cfg_nsw_link_default[i].data;
2660
2661 if (strcmp(spc->db, nswdb_name) == 0 &&
2662 spc->group_off == desc->g_offset &&
2663 spc->param_off == desc->p_offset) {
2664
2665 rc = _nscd_cfg_set(handle, data, errorp);
2666 if (rc != NSCD_SUCCESS)
2667 return (rc);
2668 break;
2669 }
2670 }
2671
2672 /*
2673 * then change all those linked to the one that has been changed
2674 */
2675 for (i = 0; i < _nscd_cfg_num_link_default; i++) {
2676
2677 if (_nscd_cfg_nsw_link_default[i].data == NULL)
2678 continue;
2679
2680 spc = _nscd_cfg_nsw_link_default[i].data;
2681
2682 if (strcmp(spc->db, nswdb_name) == 0 &&
2683 spc->group_off == desc->g_offset &&
2684 spc->param_off == desc->p_offset &&
2685 _nscd_cfg_nsw_link_default[i].group_off ==
2686 desc->g_offset &&
2687 _nscd_cfg_nsw_link_default[i].param_off ==
2688 desc->p_offset) {
2689
2690 dbl = _nscd_cfg_nsw_link_default[i].db;
2691
2692 rc = _nscd_cfg_get_handle(param_name, dbl,
2693 &hl, errorp);
2694 if (rc != NSCD_SUCCESS)
2695 return (rc);
2696 rc = _nscd_cfg_set(hl, data, errorp);
2697 _nscd_cfg_free_handle(hl);
2698 if (rc != NSCD_SUCCESS)
2699 return (rc);
2700 }
2701 }
2702
2703 return (_nscd_cfg_set(handle, data, errorp));
2704 }
2705
2706 /*
2707 * Return a list of comma-separated database names that
2708 * have at least one of the input sources (the srcs array)
2709 * appears in their configured nsswitch policy string.
2710 * That is, if srcs contains "ldap" and "passwd: files ldap"
2711 * "group: files ldap" are in /etc/nsswitch.conf, then
2712 * "passwd,group" will be returned. The return string
2713 * should be freed by the caller.
2714 *
2715 * For compat nsswitch configuration, "group" and/or
2716 * "passwd,user_attr,shadow,audit_user" (not "group_compat"
2717 * or "passwd_compat") will be returned. Note that the
2718 * user_attr, shadow, and audit_user databases share the
2719 * same policy with the passwd database.
2720 *
2721 * For example, if srcs has "ldap" and in /etc/nsswitch.conf,
2722 * there are:
2723 * passwd: compat
2724 * passwd_compat: ldap
2725 * group: compat
2726 * group_compat: ldap
2727 * netgroup: ldap
2728 * then "netgroup,passwd,group,user_attr,shadow,audit_user"
2729 * will be returned.
2730 */
2731 char *
_nscd_srcs_in_db_nsw_policy(int num_src,char ** srcs)2732 _nscd_srcs_in_db_nsw_policy(
2733 int num_src,
2734 char **srcs)
2735 {
2736 uint8_t i, j, n = 0, nc = 0;
2737 uint8_t compat_grp = 0, compat_pwd = 0;
2738 uint8_t *db;
2739 uint8_t *db_compat;
2740 int dlen = 0;
2741 nscd_cfg_nsw_db_data_t *dbcfg;
2742 nscd_cfg_switch_t *sw;
2743 char *outstr = NULL;
2744 char *dbname;
2745
2746 db = (uint8_t *)calloc(_nscd_cfg_num_nsw_db, sizeof (uint8_t));
2747 if (db == NULL)
2748 return (NULL);
2749
2750 db_compat = (uint8_t *)calloc(_nscd_cfg_num_nsw_db,
2751 sizeof (uint8_t));
2752 if (db_compat == NULL) {
2753 free(db);
2754 return (NULL);
2755 }
2756
2757 for (i = 0; i < _nscd_cfg_num_nsw_db; i++) {
2758
2759 (void) rw_rdlock(&nscd_cfg_nsw_db_data_rwlock[i]);
2760
2761 dbcfg = &nscd_cfg_nsw_db_data_current[i];
2762 sw = &dbcfg->sw;
2763 if (sw->nsw_config_string == NULL) {
2764 (void) rw_unlock(&nscd_cfg_nsw_db_data_rwlock[i]);
2765 continue;
2766 }
2767
2768 dbname = _nscd_cfg_nsw_db[i].name;
2769 for (j = 0; j < num_src; j++) {
2770 if (strstr(sw->nsw_config_string, srcs[j]) !=
2771 NULL) {
2772 db[n++] = i;
2773 dlen += strlen(dbname) + 1;
2774 } else if (strcmp(sw->nsw_config_string,
2775 "compat") == 0) {
2776 if (strcmp(dbname, "passwd") == 0) {
2777 compat_pwd = 1;
2778 dlen += 7;
2779 } else if (strcmp(dbname, "group") == 0) {
2780 compat_grp = 1;
2781 dlen += 6;
2782 } else {
2783 db_compat[nc++] = i;
2784 dlen += strlen(dbname) + 1;
2785
2786 }
2787 }
2788 }
2789 (void) rw_unlock(&nscd_cfg_nsw_db_data_rwlock[i]);
2790 }
2791
2792 if (dlen != 0)
2793 outstr = (char *)calloc(1, dlen);
2794 if (outstr == NULL) {
2795 free(db_compat);
2796 free(db);
2797 return (NULL);
2798 }
2799
2800 for (j = 0; j < n; j++) {
2801 dbname = _nscd_cfg_nsw_db[db[j]].name;
2802 if (strstr(dbname, "group_compat") != NULL) {
2803 if (compat_grp == 1)
2804 dbname = "group";
2805 else
2806 continue;
2807 } else if (strstr(dbname, "passwd_compat") != NULL) {
2808 if (compat_pwd == 1)
2809 dbname = "passwd";
2810 else
2811 continue;
2812 }
2813
2814 (void) strlcat(outstr, dbname, dlen);
2815 (void) strlcat(outstr, ",", dlen);
2816 }
2817
2818 for (j = 0; j < nc; j++) {
2819 dbname = _nscd_cfg_nsw_db[db_compat[j]].name;
2820 if (compat_pwd == 1) {
2821 (void) strlcat(outstr, dbname, dlen);
2822 (void) strlcat(outstr, ",", dlen);
2823 }
2824 }
2825
2826 /* remove the last comma */
2827 i = strlen(outstr) - 1;
2828 if (outstr[i] == ',')
2829 outstr[i] = '\0';
2830
2831 free(db);
2832 free(db_compat);
2833 return (outstr);
2834
2835 }
2836