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 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <nss_common.h>
27 #include <dlfcn.h>
28 #include <alloca.h>
29
30 #include <stdlib.h>
31 #include <libscf_priv.h>
32 #include <string.h>
33 #include <assert.h>
34 #include "nscd_switch.h"
35 #include "nscd_log.h"
36 #include "nscd_db.h"
37
38 /*
39 * _nscd_nss_finders is used to replace the nss_default_finders in libc
40 * to allow nscd to have more control over the dl handles when using
41 * dlsym to get the address of the nss backend instance constructors
42 */
43 static nss_backend_constr_t _nscd_per_src_lookup(void *,
44 const char *, const char *, void **);
45 static void _nscd_per_src_delete(void *, nss_backend_constr_t);
46
47 static nss_backend_finder_t _nscd_per_src = {
48 _nscd_per_src_lookup,
49 _nscd_per_src_delete,
50 0,
51 0 };
52
53 nss_backend_finder_t *_nscd_nss_finders = &_nscd_per_src;
54
55 /*
56 * nscd database for each source. It contains backend
57 * info (nscd_be_info_t) for each naming database.
58 * Protected by nscd_src_backend_db_lock.
59 */
60 nscd_db_t ***nscd_src_backend_db;
61 int *nscd_src_backend_db_loaded;
62 static rwlock_t nscd_src_backend_db_lock = DEFAULTRWLOCK;
63
64 /*
65 * nsswitch config monitored by nscd. Protected by
66 * readers/writer lock nscd_nsw_config_lock
67 */
68 nscd_nsw_config_t ***nscd_nsw_config;
69 static rwlock_t nscd_nsw_config_lock = DEFAULTRWLOCK;
70
71 /*
72 * nsswitch source index/name array
73 * (allow 32 foreign nsswitch sources/backends)
74 */
75 #define NSCD_NUM_SRC_FOREIGN 32
76 nscd_cfg_id_t *_nscd_cfg_nsw_src_all;
77 int _nscd_cfg_num_nsw_src_all;
78
79 static void
free_nscd_nsw_config(nscd_acc_data_t * data)80 free_nscd_nsw_config(
81 nscd_acc_data_t *data)
82 {
83
84 nscd_nsw_config_t *nsw_cfg = *(nscd_nsw_config_t **)data;
85 char *me = "free_nscd_nsw_config";
86
87 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
88 (me, "freeing nscd nsw config %p \n", nsw_cfg);
89 if (nsw_cfg == NULL)
90 return;
91
92 if (nsw_cfg->db_name != NULL)
93 free(nsw_cfg->db_name);
94 if (nsw_cfg->nsw_cfg_str != NULL)
95 free(nsw_cfg->nsw_cfg_str);
96 if (nsw_cfg->nsw_config != NULL)
97 (void) __nsw_freeconfig_v1(nsw_cfg->nsw_config);
98 if (nsw_cfg->src_idx != NULL)
99 free(nsw_cfg->src_idx);
100
101 free(nsw_cfg);
102 }
103
104
105 void
_nscd_free_nsw_config(nscd_nsw_config_t * nswcfg)106 _nscd_free_nsw_config(
107 nscd_nsw_config_t *nswcfg)
108 {
109 free_nscd_nsw_config((nscd_acc_data_t *)&nswcfg);
110 }
111
112 void
_nscd_free_all_nsw_config()113 _nscd_free_all_nsw_config()
114 {
115
116 nscd_nsw_config_t **nsw_cfg;
117 int i;
118 char *me = "_nscd_free_all_nsw_config";
119
120 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
121 (me, "freeing all nscd nsw config \n");
122
123 (void) rw_wrlock(&nscd_nsw_config_lock);
124 for (i = 0; i < NSCD_NUM_DB; i++) {
125
126 if ((nsw_cfg = nscd_nsw_config[i]) == NULL)
127 continue;
128
129 nscd_nsw_config[i] = (nscd_nsw_config_t **)_nscd_set(
130 (nscd_acc_data_t *)nsw_cfg, NULL);
131 }
132 (void) rw_unlock(&nscd_nsw_config_lock);
133 }
134
135
136 static void
free_nsw_backend_info_db(nscd_acc_data_t * data)137 free_nsw_backend_info_db(nscd_acc_data_t *data)
138 {
139
140 nscd_db_t *db = *(nscd_db_t **)data;
141 char *me = "free_nsw_backend_info_db";
142
143 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
144 (me, "freeing nsw backend info db %p\n", db);
145
146 if (db == NULL)
147 return;
148
149 _nscd_free_db(db);
150
151 }
152
153 void
_nscd_free_all_nsw_backend_info_db()154 _nscd_free_all_nsw_backend_info_db()
155 {
156
157 nscd_db_t **db;
158 int i;
159 char *me = " _nscd_free_all_nsw_backend_info_db";
160
161 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
162 (me, "freeing all nsw backend info db\n");
163
164 (void) rw_wrlock(&nscd_src_backend_db_lock);
165 for (i = 0; i < NSCD_NUM_SRC; i++) {
166
167 if ((db = nscd_src_backend_db[i]) == NULL)
168 continue;
169
170 nscd_src_backend_db[i] = (nscd_db_t **)_nscd_set(
171 (nscd_acc_data_t *)db, NULL);
172 nscd_src_backend_db_loaded[i] = 0;
173 }
174 (void) rw_unlock(&nscd_src_backend_db_lock);
175 }
176
177 /*
178 * Populate the backend info db for the 'NSCD_NSW_SRC_NAME(srci)'
179 * source. Create one entry for each source/database pair
180 * (e.g., ldap:passwd, nis:hosts, etc).
181 */
182 static nscd_rc_t
_nscd_populate_nsw_backend_info_db(int srci)183 _nscd_populate_nsw_backend_info_db(int srci)
184 {
185 nscd_be_info_t be_info, *bi;
186 nss_backend_finder_t *bf;
187 nscd_nsw_config_t *nsw_cfg;
188 int i, size;
189 nscd_db_entry_t *db_entry;
190 char *src = NSCD_NSW_SRC_NAME(srci);
191 const char *dbn;
192 char *me = "_nscd_populate_nsw_backend_info_db";
193 void *handle = NULL;
194 nss_backend_constr_t c;
195 void *be_version = &_nscd_be_version;
196
197 /* get the version number of the backend (if available) */
198 if (srci >= _nscd_cfg_num_nsw_src) { /* a foreign backend */
199 c = _nscd_per_src_lookup(handle, NULL, src, &handle);
200 if (c == NULL)
201 be_version = NULL;
202 else
203 be_version = (void *)c;
204
205 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
206 (me, "foreign backend: _nss_%s_version = %p ", src, be_version);
207 }
208
209 for (i = 0; i < NSCD_NUM_DB; i++) {
210
211 /* no nsswitch configuration, no backend info db population */
212 if (nscd_nsw_config[i] == NULL || *nscd_nsw_config[i] == NULL)
213 continue;
214
215 nsw_cfg = *nscd_nsw_config[i];
216 dbn = NSCD_NSW_DB_NAME(i);
217 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
218 (me, "adding backend info for <%s : %s>\n", src, dbn);
219
220 (void) memset(&be_info, 0, sizeof (be_info));
221
222 for (bf = nsw_cfg->fe_params.finders; bf != 0; bf = bf->next) {
223
224 c = (*bf->lookup)(handle, dbn, src, &handle);
225
226 if (c != 0) {
227 be_info.be_constr = c;
228 be_info.finder = bf;
229 be_info.finder_priv = handle;
230 be_info.be_version = be_version;
231 break;
232 }
233 }
234 if (be_info.be_constr == NULL) {
235 /*
236 * Couldn't find the backend anywhere.
237 * This is fine, some backend just don't
238 * support certain databases.
239 */
240 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
241 (me, "unable to find backend info "
242 "for <%s : %s>\n", src, dbn);
243 }
244
245 size = sizeof (nscd_be_info_t);
246
247 db_entry = _nscd_alloc_db_entry(NSCD_DATA_BACKEND_INFO,
248 dbn, size, 1, 1);
249
250 if (db_entry == NULL) {
251 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
252 (me, "unable to allocate db entry for "
253 "<%s : %s>\n", src, dbn);
254 return (NSCD_NO_MEMORY);
255 }
256
257 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
258 (me, "adding be db entry %p for <%s : %s> to db %p: "
259 "constr = %p\n", db_entry, src, dbn,
260 *nscd_src_backend_db[srci], be_info.be_constr);
261
262 bi = (nscd_be_info_t *)*(db_entry->data_array);
263 *bi = be_info;
264
265 (void) _nscd_wrlock((nscd_acc_data_t *)
266 nscd_src_backend_db[srci]);
267 nscd_src_backend_db_loaded[srci] = 1;
268 (void) _nscd_add_db_entry(*nscd_src_backend_db[srci],
269 dbn, db_entry, NSCD_ADD_DB_ENTRY_LAST);
270 (void) _nscd_rw_unlock((nscd_acc_data_t *)
271 nscd_src_backend_db[srci]);
272 }
273
274 return (NSCD_SUCCESS);
275 }
276
277 /*
278 * create data structures (used by the switch engine) based
279 * on the input switch policy configuration and database
280 * name and indexes
281 */
282 nscd_rc_t
_nscd_create_sw_struct(int dbi,int compat_basei,const char * dbn,const char * cfgstr,void * swcfgv1,nscd_nsw_params_t * params)283 _nscd_create_sw_struct(
284 int dbi,
285 int compat_basei,
286 const char *dbn,
287 const char *cfgstr,
288 void *swcfgv1,
289 nscd_nsw_params_t *params)
290 {
291 char *me = "_nscd_create_sw_struct";
292 nscd_rc_t rc = NSCD_SUCCESS;
293 nscd_nsw_config_t *nsw_cfg = NULL;
294 nscd_nsw_config_t **nsw_cfg_p = NULL;
295 struct __nsw_switchconfig_v1 *swcfg = NULL;
296 struct __nsw_lookup_v1 *lkp;
297 enum __nsw_parse_err err;
298 int maxsrc;
299 int *src_idx_a = NULL;
300 int j, k;
301
302 /*
303 * if the nsw config string has been parsed into
304 * a struct __nsw_switchconfig_v1, use it. If not,
305 * create the struct.
306 */
307 if (swcfgv1 != NULL)
308 swcfg = (struct __nsw_switchconfig_v1 *)swcfgv1;
309 else {
310 char *cstr;
311
312 cstr = strdup(cfgstr);
313 if (cstr == NULL)
314 return (NSCD_NO_MEMORY);
315
316 /*
317 * parse the nsw config string and create
318 * a struct __nsw_switchconfig_v1
319 */
320 swcfg = _nsw_getoneconfig_v1(dbn, cstr, &err);
321 free(cstr);
322 if (swcfg == NULL) {
323 rc = NSCD_CFG_SYNTAX_ERROR;
324 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
325 (me, "error: unable to process nsw config string\n");
326 goto error_exit;
327 }
328 }
329
330 /* allocate the space for a nscd_nsw_config_t */
331 nsw_cfg = calloc(1, sizeof (nscd_nsw_config_t));
332 if (nsw_cfg == NULL) {
333 rc = NSCD_NO_MEMORY;
334 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
335 (me, "error: unable to allocate an nscd_nsw_config_t\n");
336 goto error_exit;
337 }
338
339 /* need to know how many backends (sources) */
340 maxsrc = swcfg->num_lookups;
341 nsw_cfg->max_src = maxsrc;
342
343 /*
344 * allocate an array to store the index for each
345 * backend (source)
346 */
347 src_idx_a = calloc(1, maxsrc * sizeof (int));
348 if (src_idx_a == NULL) {
349 rc = NSCD_NO_MEMORY;
350 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
351 (me, "error: unable to allocate an array for source index\n");
352 goto error_exit;
353 }
354
355 /*
356 * set the index for each backend (source)
357 */
358 lkp = swcfg->lookups;
359 for (j = 0; j < maxsrc; j++) {
360 char *usrc;
361
362 for (k = 0; k < NSCD_NUM_SRC && NSCD_NSW_SRC_NAME(k) != NULL &&
363 strcmp(lkp->service_name, NSCD_NSW_SRC_NAME(k)) != 0;
364 k++) {
365 /* empty */
366 }
367
368 if (k < NSCD_NUM_SRC && nscd_src_backend_db_loaded[k] == 0) {
369 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
370 (me, "unknown nsw source name %s\n", lkp->service_name);
371 usrc = strdup(lkp->service_name);
372 if (usrc == NULL) {
373 rc = NSCD_NO_MEMORY;
374 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
375 (me, "unable to strdup() source name\n");
376 goto error_exit;
377 }
378 NSCD_NSW_SRC_NAME(k) = usrc;
379
380 rc = _nscd_populate_nsw_backend_info_db(k);
381 if (rc != NSCD_SUCCESS) {
382 free(usrc);
383 NSCD_NSW_SRC_NAME(k) = NULL;
384 goto error_exit;
385 }
386 } else if (NSCD_NSW_SRC_NAME(k) == NULL) {
387 /*
388 * number of user-defined source exceeded
389 */
390 rc = NSCD_CFG_SYNTAX_ERROR;
391 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
392 (me, "error: number of user_defined source exceeded\n");
393
394 goto error_exit;
395 }
396
397 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
398 (me, "setting source index array [%d] = %d (%s)\n",
399 j, k, lkp->service_name);
400
401 src_idx_a[j] = k;
402
403 lkp = lkp->next;
404 if (lkp == NULL) break;
405
406 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
407 (me, "number of nsw sources = %d\n", nsw_cfg->max_src);
408 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
409 (me, "next nsw source is %s\n", lkp->service_name);
410 }
411
412 /* set it up to reference count the switch policy config */
413 nsw_cfg_p = (nscd_nsw_config_t **)_nscd_alloc(NSCD_DATA_NSW_CONFIG,
414 sizeof (nscd_nsw_config_t **), free_nscd_nsw_config,
415 NSCD_ALLOC_RWLOCK);
416
417 if (nsw_cfg_p == NULL) {
418 rc = NSCD_NO_MEMORY;
419 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
420 (me, "unable to allocate a new nsw config DB\n");
421 goto error_exit;
422 }
423 *nsw_cfg_p = nsw_cfg;
424
425 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
426 (me, "new nsw config DB %p allocated\n", nsw_cfg_p);
427
428 /* save all the data in the new nscd_nsw_config_t */
429 nsw_cfg->db_name = strdup(dbn);
430 nsw_cfg->nsw_cfg_str = strdup(cfgstr);
431 if (nsw_cfg->db_name == NULL || nsw_cfg->nsw_cfg_str == NULL) {
432 rc = NSCD_NO_MEMORY;
433 goto error_exit;
434 }
435
436 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
437 (me, "switch policy \"%s\" for database is \"%s\"\n",
438 nsw_cfg->db_name, nsw_cfg->nsw_cfg_str);
439
440 nsw_cfg->nsw_config = swcfg;
441 nsw_cfg->src_idx = src_idx_a;
442
443 /*
444 * set default frontend params and if necessary call initf()
445 * to initialize or override
446 */
447 nsw_cfg->fe_params.max_active_per_src = 10;
448 nsw_cfg->fe_params.max_dormant_per_src = 1;
449 nsw_cfg->fe_params.finders = _nscd_nss_finders;
450 if (params != NULL) {
451 nsw_cfg->fe_params = params->p;
452
453 if (params->p.flags & NSS_USE_DEFAULT_CONFIG) {
454 params->nswcfg = nsw_cfg_p;
455 /*
456 * this nsw_cfg is not meant to last long, no need
457 * to set up the nsw state and getent bases, just
458 * exit with NSCD_SUCCESS
459 */
460 nsw_cfg->nobase = 1;
461 goto error_exit;
462 }
463 } else
464 (void) (nscd_nss_db_initf[dbi])(&nsw_cfg->fe_params);
465
466 /*
467 * also create a new nsw state base
468 */
469 if ((rc = _nscd_init_nsw_state_base(dbi, compat_basei, 1)) !=
470 NSCD_SUCCESS) {
471 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
472 (me, "unable to initialize a nsw state base(%d)\n", dbi);
473 goto error_exit;
474 }
475
476 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
477 (me, "new nsw state base(%d) %p created\n", dbi,
478 nscd_nsw_state_base[dbi]);
479
480 /*
481 * also create a new getent context base
482 */
483 if ((rc = _nscd_init_getent_ctx_base(dbi, 1)) != NSCD_SUCCESS) {
484 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
485 (me, "unable to initialize a getent context base(%d)\n", dbi);
486 goto error_exit;
487 }
488
489 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
490 (me, "new getent context base(%d) %p created\n", dbi,
491 nscd_getent_ctx_base[dbi]);
492
493 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
494 (me, "new nsw config created (database = %s, "
495 "config = %s)\n", dbn, cfgstr);
496
497 /*
498 * Activate the new nscd_nsw_config_t and make it the
499 * current nsswitch config. The old one pointed to by
500 * nscd_nsw_config[dbi] will either be destroyed
501 * immediately or left on the side line (and be
502 * destroyed eventually). __nscd_set() will set the
503 * associated flags to make it happen.
504 */
505 nscd_nsw_config[dbi] = (nscd_nsw_config_t **)_nscd_set(
506 (nscd_acc_data_t *)nscd_nsw_config[dbi],
507 (nscd_acc_data_t *)nsw_cfg_p);
508
509 error_exit:
510
511 if (rc != NSCD_SUCCESS) {
512
513 if (swcfgv1 == NULL && swcfg != NULL)
514 (void) __nsw_freeconfig_v1(swcfg);
515 if (src_idx_a != NULL)
516 free(src_idx_a);
517 if (nsw_cfg_p)
518 free(nsw_cfg_p);
519 if (nsw_cfg != NULL) {
520 if (nsw_cfg->db_name != NULL)
521 free(nsw_cfg->db_name);
522 if (nsw_cfg->nsw_cfg_str != NULL)
523 free(nsw_cfg->nsw_cfg_str);
524 free(nsw_cfg);
525 }
526
527 return (rc);
528 } else
529 return (NSCD_SUCCESS);
530 }
531
532 static nscd_rc_t
create_nsw_config(int dbi)533 create_nsw_config(int dbi)
534 {
535
536 nscd_nsw_config_t *nsw_cfg = NULL;
537 nscd_nsw_config_t **nsw_cfg_p = NULL;
538 char *me = "create_nsw_config";
539
540 /*
541 * Allocate a pointer space for saving a pointer to a
542 * nscd_nsw_config_t. _nscd_alloc() will also create
543 * a nscd_access_t header with a rwlock_t and mutex_t
544 * for controlling later access to the data pointed
545 * to by the pointer.
546 */
547 nsw_cfg_p = (nscd_nsw_config_t **)_nscd_alloc(NSCD_DATA_NSW_CONFIG,
548 sizeof (nscd_nsw_config_t **), free_nscd_nsw_config,
549 NSCD_ALLOC_RWLOCK | NSCD_ALLOC_MUTEX);
550
551 if (nsw_cfg_p == NULL) {
552 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
553 (me, "unable to allocate a space for a nsw config pointer\n");
554 return (NSCD_NO_MEMORY);
555 }
556 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
557 (me, "addr for saving nsw config pointer = %p\n", nsw_cfg_p);
558
559 /*
560 * If pseudo-databases (initf function not defined),
561 * no need to create a nscd_nsw_config_t yet,
562 * so put a NULL pointer in the pointer space.
563 */
564 if (nscd_nss_db_initf[dbi] == NULL) {
565 *nsw_cfg_p = NULL;
566 nscd_nsw_config[dbi] = (nscd_nsw_config_t **)_nscd_set(
567 (nscd_acc_data_t *)nscd_nsw_config[dbi],
568 (nscd_acc_data_t *)nsw_cfg_p);
569
570 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
571 (me, "pointer to nsw config has been set to NULL\n");
572
573 return (NSCD_SUCCESS);
574 }
575
576 /* allocate the space for a nscd_nsw_config_t */
577 nsw_cfg = calloc(1, sizeof (nscd_nsw_config_t));
578 if (nsw_cfg == NULL) {
579 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
580 (me, "unable to allocate a nsw config structure\n");
581 return (NSCD_NO_MEMORY);
582 }
583 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
584 (me, "nsw config structure %pallocated\n", nsw_cfg);
585
586 nsw_cfg->db_name = strdup(NSCD_NSW_DB_NAME(dbi));
587 if (nsw_cfg->db_name == NULL) {
588 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
589 (me, "unable to strdup the db name\n");
590 return (NSCD_NO_MEMORY);
591 }
592
593 /*
594 * set default frontend params and then call initf()
595 * to initialize or override
596 */
597 nsw_cfg->fe_params.max_active_per_src = 10;
598 nsw_cfg->fe_params.max_dormant_per_src = 1;
599 nsw_cfg->fe_params.finders = _nscd_nss_finders;
600 (void) (nscd_nss_db_initf[dbi])(&nsw_cfg->fe_params);
601
602 /*
603 * activate the new nscd_nsw_config_t
604 */
605 *nsw_cfg_p = nsw_cfg;
606 nscd_nsw_config[dbi] = (nscd_nsw_config_t **)_nscd_set(
607 (nscd_acc_data_t *)nscd_nsw_config[dbi],
608 (nscd_acc_data_t *)nsw_cfg_p);
609
610 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
611 (me, "nsw config %p activated\n", nsw_cfg);
612
613 return (NSCD_SUCCESS);
614 }
615
616 nscd_rc_t
_nscd_init_all_nsw_config(void)617 _nscd_init_all_nsw_config(void)
618 {
619 nscd_rc_t rc;
620 int i;
621 char *me = "_nscd_init_all_nsw_config";
622
623 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
624 (me, "initializing all nsw config\n");
625
626 for (i = 0; i < NSCD_NUM_DB; i++) {
627 if ((rc = create_nsw_config(i)) != NSCD_SUCCESS)
628 return (rc);
629 }
630
631 return (NSCD_SUCCESS);
632 }
633
634 static nscd_rc_t
init_nsw_be_info_db(int srci)635 init_nsw_be_info_db(int srci)
636 {
637 nscd_db_t *ret, **db_p;
638 char *me = "init_nsw_be_info_db";
639
640 ret = _nscd_alloc_db(NSCD_DB_SIZE_SMALL);
641
642 if (ret == NULL) {
643 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
644 (me, "unable to allocate a nsw be info database\n");
645 return (NSCD_NO_MEMORY);
646 }
647
648 /* set up to reference count the backend info db */
649 db_p = (nscd_db_t **)_nscd_alloc(NSCD_DATA_BACKEND_INFO_DB,
650 sizeof (nscd_db_t **), free_nsw_backend_info_db,
651 NSCD_ALLOC_RWLOCK);
652
653 if (db_p == NULL) {
654 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
655 (me, "unable to allocate the pointer to the nsw "
656 "be info database\n");
657 return (NSCD_NO_MEMORY);
658 }
659
660 *db_p = ret;
661 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
662 (me, "backend database (db_p = %p, db = %p)\n", db_p, *db_p);
663
664 nscd_src_backend_db[srci] = (nscd_db_t **)_nscd_set(
665 (nscd_acc_data_t *)nscd_src_backend_db[srci],
666 (nscd_acc_data_t *)db_p);
667
668 return (NSCD_SUCCESS);
669 }
670
671 nscd_rc_t
_nscd_init_all_nsw_be_info_db(void)672 _nscd_init_all_nsw_be_info_db(void)
673 {
674
675 int i;
676 nscd_rc_t rc;
677 char *me = "_nscd_init_all_nsw_be_info_db";
678
679 _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
680 (me, "initializing all nsw be info databases\n");
681
682 for (i = 0; i < NSCD_NUM_SRC; i++) {
683 if ((rc = init_nsw_be_info_db(i)) != NSCD_SUCCESS)
684 return (rc);
685 }
686
687 return (NSCD_SUCCESS);
688 }
689
690
691 nscd_rc_t
_nscd_alloc_nsw_config()692 _nscd_alloc_nsw_config()
693 {
694 nscd_nsw_config = calloc(NSCD_NUM_DB, sizeof (nscd_nsw_config_t **));
695 if (nscd_nsw_config == NULL)
696 return (NSCD_NO_MEMORY);
697
698 return (NSCD_SUCCESS);
699 }
700
701 nscd_rc_t
_nscd_alloc_nsw_be_info_db()702 _nscd_alloc_nsw_be_info_db()
703 {
704 int i;
705
706 _nscd_cfg_num_nsw_src_all = _nscd_cfg_num_nsw_src +
707 NSCD_NUM_SRC_FOREIGN;
708 nscd_src_backend_db = calloc(NSCD_NUM_SRC, sizeof (nscd_db_t **));
709 if (nscd_src_backend_db == NULL)
710 return (NSCD_NO_MEMORY);
711 nscd_src_backend_db_loaded = calloc(NSCD_NUM_SRC, sizeof (int));
712 if (nscd_src_backend_db_loaded == NULL) {
713 free(nscd_src_backend_db);
714 return (NSCD_NO_MEMORY);
715 }
716
717 /* also allocate/init the nsswitch source index/name array */
718 _nscd_cfg_nsw_src_all = (nscd_cfg_id_t *)calloc(
719 _nscd_cfg_num_nsw_src_all + 1, sizeof (nscd_cfg_id_t));
720 for (i = 0; i < _nscd_cfg_num_nsw_src_all + 1; i++)
721 (_nscd_cfg_nsw_src_all + i)->index = -1;
722
723 (void) memcpy(_nscd_cfg_nsw_src_all, _nscd_cfg_nsw_src,
724 _nscd_cfg_num_nsw_src * sizeof (nscd_cfg_id_t));
725 return (NSCD_SUCCESS);
726 }
727
728 nscd_rc_t
_nscd_populate_nsw_backend_info()729 _nscd_populate_nsw_backend_info()
730 {
731 int i;
732 nscd_rc_t rc;
733
734 for (i = 0; i < NSCD_NUM_SRC; i++) {
735 if (NSCD_NSW_SRC_NAME(i) == NULL)
736 continue;
737 rc = _nscd_populate_nsw_backend_info_db(i);
738 if (rc != NSCD_SUCCESS)
739 return (rc);
740 }
741
742 return (NSCD_SUCCESS);
743 }
744
745 /*
746 * The following defines nscd's own lookup and delete functions
747 * that are to be stored in nss_backend_finder_t which is used
748 * by _nscd_populate_nsw_backend_info_db() to initialize the
749 * various nss backend instances
750 */
751
752 static const int dlopen_version = 1;
753 #ifndef NSS_DLOPEN_FORMAT
754 #define NSS_DLOPEN_FORMAT "nss_%s.so.%d"
755 #endif
756 #ifndef NSS_DLSYM_FORMAT
757 #define NSS_DLSYM_FORMAT "_nss_%s_%s_constr"
758 #define NSS_DLSYM_FORMAT_V "_nss_%s_version"
759 #endif
760 static const char dlopen_format[] = NSS_DLOPEN_FORMAT;
761 static const char dlsym_format [] = NSS_DLSYM_FORMAT;
762 static const char dlsym_format_v [] = NSS_DLSYM_FORMAT_V;
763 static const size_t format_maxlen = sizeof (dlsym_format);
764
765 /*ARGSUSED*/
766 static nss_backend_constr_t
_nscd_per_src_lookup(void * handle,const char * db_name,const char * src_name,void ** delete_privp)767 _nscd_per_src_lookup(void *handle, const char *db_name, const char *src_name,
768 void **delete_privp)
769 {
770 char *name;
771 void *dlhandle;
772 void *sym;
773 size_t len;
774 nss_backend_constr_t res = NULL;
775
776 len = format_maxlen + strlen(src_name);
777 if (db_name != NULL)
778 len += strlen(db_name);
779 name = alloca(len);
780 dlhandle = handle;
781 if ((dlhandle = handle) == NULL) {
782 (void) sprintf(name, dlopen_format, src_name, dlopen_version);
783 dlhandle = dlopen(name, RTLD_LAZY);
784 }
785
786 if (dlhandle != NULL) {
787 if (db_name != NULL)
788 (void) sprintf(name, dlsym_format, src_name, db_name);
789 else
790 (void) sprintf(name, dlsym_format_v, src_name);
791 if ((sym = dlsym(dlhandle, name)) == 0) {
792 if (handle == NULL)
793 (void) dlclose(dlhandle);
794 } else {
795 *delete_privp = dlhandle;
796 res = (nss_backend_constr_t)sym;
797 }
798 }
799 return (res);
800 }
801
802 /*ARGSUSED*/
803 static void
_nscd_per_src_delete(void * delete_priv,nss_backend_constr_t dummy)804 _nscd_per_src_delete(void *delete_priv, nss_backend_constr_t dummy)
805 {
806 (void) dlclose(delete_priv);
807 }
808