nsdispatch.c (111618) | nsdispatch.c (113595) |
---|---|
1/* $NetBSD: nsdispatch.c,v 1.9 1999/01/25 00:16:17 lukem Exp $ */ 2 3/*- 4 * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Luke Mewburn. --- 21 unchanged lines hidden (view full) --- 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ | 1/* $NetBSD: nsdispatch.c,v 1.9 1999/01/25 00:16:17 lukem Exp $ */ 2 3/*- 4 * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Luke Mewburn. --- 21 unchanged lines hidden (view full) --- 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ |
38 | 38/*- 39 * Copyright (c) 2003 Networks Associates Technology, Inc. 40 * All rights reserved. 41 * 42 * Portions of this software were developed for the FreeBSD Project by 43 * Jacques A. Vidrine, Safeport Network Services, and Network 44 * Associates Laboratories, the Security Research Division of Network 45 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 46 * ("CBOSS"), as part of the DARPA CHATS research program. 47 * 48 * Redistribution and use in source and binary forms, with or without 49 * modification, are permitted provided that the following conditions 50 * are met: 51 * 1. Redistributions of source code must retain the above copyright 52 * notice, this list of conditions and the following disclaimer. 53 * 2. Redistributions in binary form must reproduce the above copyright 54 * notice, this list of conditions and the following disclaimer in the 55 * documentation and/or other materials provided with the distribution. 56 * 57 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 58 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 59 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 60 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 61 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 62 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 63 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 64 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 65 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 67 * SUCH DAMAGE. 68 * 69 */ |
39#include <sys/cdefs.h> | 70#include <sys/cdefs.h> |
40__FBSDID("$FreeBSD: head/lib/libc/net/nsdispatch.c 111618 2003-02-27 13:40:01Z nectar $"); | 71__FBSDID("$FreeBSD: head/lib/libc/net/nsdispatch.c 113595 2003-04-17 14:14:22Z nectar $"); |
41 | 72 |
42#include <sys/types.h> | 73#include "namespace.h" |
43#include <sys/param.h> 44#include <sys/stat.h> 45 | 74#include <sys/param.h> 75#include <sys/stat.h> 76 |
46#include "namespace.h" 47#include | 77#include <dlfcn.h> 78#include <errno.h> |
48#include <fcntl.h> 49#define _NS_PRIVATE 50#include <nsswitch.h> | 79#include <fcntl.h> 80#define _NS_PRIVATE 81#include <nsswitch.h> |
82#include <pthread.h> |
|
51#include <stdio.h> 52#include <stdlib.h> 53#include <string.h> | 83#include <stdio.h> 84#include <stdlib.h> 85#include <string.h> |
86#include <syslog.h> |
|
54#include <unistd.h> 55#include "un-namespace.h" 56 | 87#include <unistd.h> 88#include "un-namespace.h" 89 |
90enum _nss_constants { 91 /* Number of elements allocated when we grow a vector */ 92 ELEMSPERCHUNK = 8 93}; 94 |
|
57/* | 95/* |
96 * Global NSS data structures are mostly read-only, but we update 97 * them when we read or re-read the nsswitch.conf. 98 */ 99static pthread_rwlock_t nss_lock = PTHREAD_RWLOCK_INITIALIZER; 100 101/* 102 * Runtime determination of whether we are dynamically linked or not. 103 */ 104extern int _DYNAMIC __attribute__ ((weak)); 105#define is_dynamic() (&_DYNAMIC != NULL) 106 107/* |
|
58 * default sourcelist: `files' 59 */ 60const ns_src __nsdefaultsrc[] = { 61 { NSSRC_FILES, NS_SUCCESS }, 62 { 0 }, 63}; 64 | 108 * default sourcelist: `files' 109 */ 110const ns_src __nsdefaultsrc[] = { 111 { NSSRC_FILES, NS_SUCCESS }, 112 { 0 }, 113}; 114 |
65 66static int _nsmapsize = 0; | 115/* Database, source mappings. */ 116static unsigned int _nsmapsize; |
67static ns_dbt *_nsmap = NULL; 68 | 117static ns_dbt *_nsmap = NULL; 118 |
119/* NSS modules. */ 120static unsigned int _nsmodsize; 121static ns_mod *_nsmod; 122 123/* Placeholder for builtin modules' dlopen `handle'. */ 124static int __nss_builtin_handle; 125static void *nss_builtin_handle = &__nss_builtin_handle; 126 |
|
69/* | 127/* |
70 * size of dynamic array chunk for _nsmap and _nsmap[x].srclist | 128 * Attempt to spew relatively uniform messages to syslog. |
71 */ | 129 */ |
72#define NSELEMSPERCHUNK 8 | 130#define nss_log(level, fmt, ...) \ 131 syslog((level), "NSSWITCH(%s): " fmt, __func__, __VA_ARGS__) 132#define nss_log_simple(level, s) \ 133 syslog((level), "NSSWITCH(%s): " s, __func__) |
73 | 134 |
135/* 136 * Dynamically growable arrays are used for lists of databases, sources, 137 * and modules. The following `vector' interface is used to isolate the 138 * common operations. 139 */ 140typedef int (*vector_comparison)(const void *, const void *); 141typedef void (*vector_free_elem)(void *); 142static void vector_sort(void *, unsigned int, size_t, 143 vector_comparison); 144static void vector_free(void **, unsigned int *, size_t, 145 vector_free_elem); 146static void *vector_ref(unsigned int, void *, unsigned int, size_t); 147static void *vector_search(const void *, void *, unsigned int, size_t, 148 vector_comparison); 149static int vector_append(const void *, void **, unsigned int *, size_t); |
|
74 | 150 |
75int _nscmp(const void *, const void *); | |
76 | 151 |
152/* 153 * Internal interfaces. 154 */ 155static int string_compare(const void *, const void *); 156static int mtab_compare(const void *, const void *); 157static int nss_configure(void); 158static void ns_dbt_free(ns_dbt *); 159static void ns_mod_free(ns_mod *); 160static void ns_src_free(ns_src **, int); 161static void nss_load_builtin_modules(void); 162static void nss_load_module(const char *, nss_module_register_fn); 163static void nss_atexit(void); 164/* nsparser */ 165extern FILE *_nsyyin; |
|
77 | 166 |
78int 79_nscmp(a, b) 80 const void *a; 81 const void *b; | 167 168/* 169 * The vector operations 170 */ 171static void 172vector_sort(void *vec, unsigned int count, size_t esize, 173 vector_comparison comparison) |
82{ | 174{ |
83 return (strcasecmp(((const ns_dbt *)a)->name, 84 ((const ns_dbt *)b)->name)); | 175 qsort(vec, count, esize, comparison); |
85} 86 87 | 176} 177 178 |
88void 89_nsdbtaddsrc(dbt, src) 90 ns_dbt *dbt; 91 const ns_src *src; | 179static void * 180vector_search(const void *key, void *vec, unsigned int count, size_t esize, 181 vector_comparison comparison) |
92{ | 182{ |
93 if ((dbt->srclistsize % NSELEMSPERCHUNK) == 0) { 94 dbt->srclist = (ns_src *)realloc(dbt->srclist, 95 (dbt->srclistsize + NSELEMSPERCHUNK) * sizeof(ns_src)); 96 if (dbt->srclist == NULL) 97 _err(1, "nsdispatch: memory allocation failure"); | 183 return (bsearch(key, vec, count, esize, comparison)); 184} 185 186 187static int 188vector_append(const void *elem, void **vec, unsigned int *count, size_t esize) 189{ 190 void *p; 191 192 if ((*count % ELEMSPERCHUNK) == 0) { 193 p = realloc(*vec, (*count + ELEMSPERCHUNK) * esize); 194 if (p == NULL) { 195 nss_log_simple(LOG_ERR, "memory allocation failure"); 196 return (0); 197 } else 198 *vec = p; |
98 } | 199 } |
99 memmove(&dbt->srclist[dbt->srclistsize++], src, sizeof(ns_src)); | 200 memmove((void *)(((uintptr_t)*vec) + (*count * esize)), 201 elem, esize); 202 (*count)++; 203 return (1); |
100} 101 102 | 204} 205 206 |
207static void * 208vector_ref(unsigned int i, void *vec, unsigned int count, size_t esize) 209{ 210 if (i < count) 211 return (void *)((uintptr_t)vec + (i * esize)); 212 else 213 return (NULL); 214} 215 216 217static void 218vector_free(void **vec, unsigned int *count, size_t esize, 219 vector_free_elem free_elem) 220{ 221 unsigned int i; 222 void *elem; 223 224 for (i = 0; i < *count; i++) { 225 elem = vector_ref(i, *vec, *count, esize); 226 if (elem != NULL) 227 free_elem(elem); 228 } 229 free(*vec); 230 *vec = NULL; 231 *count = 0; 232} 233 234 235 236/* 237 * Comparison functions for vector_search. 238 */ 239static int 240string_compare(const void *a, const void *b) 241{ 242 return (strcasecmp(*(const char * const *)a, *(const char * const *)b)); 243} 244 245 246static int 247mtab_compare(const void *a, const void *b) 248{ 249 int cmp; 250 251 cmp = strcmp(((const ns_mtab *)a)->name, ((const ns_mtab *)b)->name); 252 if (cmp != 0) 253 return (cmp); 254 else 255 return (strcmp(((const ns_mtab *)a)->database, 256 ((const ns_mtab *)b)->database)); 257} 258 259 260 261/* 262 * NSS nsmap management. 263 */ |
|
103void | 264void |
104_nsdbtdump(dbt) 105 const ns_dbt *dbt; | 265_nsdbtaddsrc(ns_dbt *dbt, const ns_src *src) |
106{ | 266{ |
267 const ns_mod *modp; 268 269 vector_append(src, (void **)&dbt->srclist, &dbt->srclistsize, 270 sizeof(*src)); 271 modp = vector_search(&src->name, _nsmod, _nsmodsize, sizeof(*_nsmod), 272 string_compare); 273 if (modp == NULL) 274 nss_load_module(src->name, NULL); 275} 276 277 278#ifdef _NSS_DEBUG 279void 280_nsdbtdump(const ns_dbt *dbt) 281{ |
|
107 int i; 108 109 printf("%s (%d source%s):", dbt->name, dbt->srclistsize, 110 dbt->srclistsize == 1 ? "" : "s"); | 282 int i; 283 284 printf("%s (%d source%s):", dbt->name, dbt->srclistsize, 285 dbt->srclistsize == 1 ? "" : "s"); |
111 for (i = 0; i < dbt->srclistsize; i++) { | 286 for (i = 0; i < (int)dbt->srclistsize; i++) { |
112 printf(" %s", dbt->srclist[i].name); 113 if (!(dbt->srclist[i].flags & 114 (NS_UNAVAIL|NS_NOTFOUND|NS_TRYAGAIN)) && 115 (dbt->srclist[i].flags & NS_SUCCESS)) 116 continue; 117 printf(" ["); 118 if (!(dbt->srclist[i].flags & NS_SUCCESS)) 119 printf(" SUCCESS=continue"); 120 if (dbt->srclist[i].flags & NS_UNAVAIL) 121 printf(" UNAVAIL=return"); 122 if (dbt->srclist[i].flags & NS_NOTFOUND) 123 printf(" NOTFOUND=return"); 124 if (dbt->srclist[i].flags & NS_TRYAGAIN) 125 printf(" TRYAGAIN=return"); 126 printf(" ]"); 127 } 128 printf("\n"); 129} | 287 printf(" %s", dbt->srclist[i].name); 288 if (!(dbt->srclist[i].flags & 289 (NS_UNAVAIL|NS_NOTFOUND|NS_TRYAGAIN)) && 290 (dbt->srclist[i].flags & NS_SUCCESS)) 291 continue; 292 printf(" ["); 293 if (!(dbt->srclist[i].flags & NS_SUCCESS)) 294 printf(" SUCCESS=continue"); 295 if (dbt->srclist[i].flags & NS_UNAVAIL) 296 printf(" UNAVAIL=return"); 297 if (dbt->srclist[i].flags & NS_NOTFOUND) 298 printf(" NOTFOUND=return"); 299 if (dbt->srclist[i].flags & NS_TRYAGAIN) 300 printf(" TRYAGAIN=return"); 301 printf(" ]"); 302 } 303 printf("\n"); 304} |
305#endif |
|
130 131 | 306 307 |
132const ns_dbt * 133_nsdbtget(name) 134 const char *name; | 308/* 309 * The first time nsdispatch is called (during a process's lifetime, 310 * or after nsswitch.conf has been updated), nss_configure will 311 * prepare global data needed by NSS. 312 */ 313static int 314nss_configure(void) |
135{ | 315{ |
136 static time_t confmod; 137 | 316 static pthread_mutex_t conf_lock = PTHREAD_MUTEX_INITIALIZER; 317 static time_t confmod; |
138 struct stat statbuf; | 318 struct stat statbuf; |
139 ns_dbt dbt; | 319 int result; 320 const char *path; |
140 | 321 |
141 extern FILE *_nsyyin; 142 extern int _nsyyparse(void); | 322#if defined(_NSS_DEBUG) && defined(_NSS_SHOOT_FOOT) 323 /* NOTE WELL: THIS IS A SECURITY HOLE. This must only be built 324 * for debugging purposes and MUST NEVER be used in production. 325 */ 326 path = getenv("NSSWITCH_CONF"); 327 if (path == NULL) 328#endif 329 path = _PATH_NS_CONF; 330 if (stat(path, &statbuf) != 0) 331 return (0); 332 if (statbuf.st_mtime <= confmod) 333 return (0); 334 result = _pthread_mutex_trylock(&conf_lock); 335 if (result != 0) 336 return (0); 337 (void)_pthread_rwlock_unlock(&nss_lock); 338 result = _pthread_rwlock_wrlock(&nss_lock); 339 if (result != 0) 340 goto fin2; 341 _nsyyin = fopen(path, "r"); 342 if (_nsyyin == NULL) 343 goto fin; 344 vector_free((void **)&_nsmap, &_nsmapsize, sizeof(*_nsmap), 345 (vector_free_elem)ns_dbt_free); 346 vector_free((void **)&_nsmod, &_nsmodsize, sizeof(*_nsmod), 347 (vector_free_elem)ns_mod_free); 348 nss_load_builtin_modules(); 349 _nsyyparse(); 350 (void)fclose(_nsyyin); 351 vector_sort(_nsmap, _nsmapsize, sizeof(*_nsmap), string_compare); 352 if (confmod == 0) 353 (void)atexit(nss_atexit); 354 confmod = statbuf.st_mtime; 355fin: 356 (void)_pthread_rwlock_unlock(&nss_lock); 357 result = _pthread_rwlock_rdlock(&nss_lock); 358fin2: 359 (void)_pthread_mutex_unlock(&conf_lock); 360 return (result); 361} |
143 | 362 |
144 dbt.name = name; | |
145 | 363 |
146 if (confmod) { 147 if (stat(_PATH_NS_CONF, &statbuf) == -1) 148 return (NULL); 149 if (confmod < statbuf.st_mtime) { 150 int i, j; | 364void 365_nsdbtput(const ns_dbt *dbt) 366{ 367 unsigned int i; 368 ns_dbt *p; |
151 | 369 |
152 for (i = 0; i < _nsmapsize; i++) { 153 for (j = 0; j < _nsmap[i].srclistsize; j++) { 154 if (_nsmap[i].srclist[j].name != NULL) { 155 /*LINTED const cast*/ 156 free((void *) 157 _nsmap[i].srclist[j].name); 158 } 159 } 160 if (_nsmap[i].srclist) 161 free(_nsmap[i].srclist); 162 if (_nsmap[i].name) { 163 /*LINTED const cast*/ 164 free((void *)_nsmap[i].name); 165 } 166 } 167 if (_nsmap) 168 free(_nsmap); 169 _nsmap = NULL; 170 _nsmapsize = 0; 171 confmod = 0; | 370 for (i = 0; i < _nsmapsize; i++) { 371 p = vector_ref(i, _nsmap, _nsmapsize, sizeof(*_nsmap)); 372 if (string_compare(&dbt->name, &p->name) == 0) { 373 /* overwrite existing entry */ 374 if (p->srclist != NULL) 375 ns_src_free(&p->srclist, p->srclistsize); 376 memmove(p, dbt, sizeof(*dbt)); 377 return; |
172 } 173 } | 378 } 379 } |
174 if (!confmod) { 175 if (stat(_PATH_NS_CONF, &statbuf) == -1) 176 return (NULL); 177 _nsyyin = fopen(_PATH_NS_CONF, "r"); 178 if (_nsyyin == NULL) 179 return (NULL); 180 _nsyyparse(); 181 (void)fclose(_nsyyin); 182 qsort(_nsmap, (size_t)_nsmapsize, sizeof(ns_dbt), _nscmp); 183 confmod = statbuf.st_mtime; 184 } 185 return (bsearch(&dbt, _nsmap, (size_t)_nsmapsize, sizeof(ns_dbt), 186 _nscmp)); | 380 vector_append(dbt, (void **)&_nsmap, &_nsmapsize, sizeof(*_nsmap)); |
187} 188 189 | 381} 382 383 |
190void 191_nsdbtput(dbt) 192 const ns_dbt *dbt; | 384static void 385ns_dbt_free(ns_dbt *dbt) |
193{ | 386{ |
387 ns_src_free(&dbt->srclist, dbt->srclistsize); 388} 389 390 391static void 392ns_src_free(ns_src **src, int srclistsize) 393{ |
|
194 int i; 195 | 394 int i; 395 |
196 for (i = 0; i < _nsmapsize; i++) { 197 if (_nscmp(dbt, &_nsmap[i]) == 0) { 198 /* overwrite existing entry */ 199 if (_nsmap[i].srclist != NULL) 200 free(_nsmap[i].srclist); 201 memmove(&_nsmap[i], dbt, sizeof(ns_dbt)); 202 return; | 396 for (i = 0; i < srclistsize; i++) 397 if ((*src)[i].name != NULL) 398 /* This one was allocated by nslexer. You'll just 399 * have to trust me. 400 */ 401 free((void *)((*src)[i].name)); 402 free(*src); 403 *src = NULL; 404} 405 406 407 408/* 409 * NSS module management. 410 */ 411/* The built-in NSS modules are all loaded at once. */ 412#define NSS_BACKEND(name, reg) \ 413ns_mtab *reg(unsigned int *, nss_module_unregister_fn *); 414#include "nss_backends.h" 415#undef NSS_BACKEND 416 417static void 418nss_load_builtin_modules(void) 419{ 420#define NSS_BACKEND(name, reg) nss_load_module(#name, reg); 421#include "nss_backends.h" 422#undef NSS_BACKEND 423} 424 425 426/* Load a built-in or dynamically linked module. If the `reg_fn' 427 * argument is non-NULL, assume a built-in module and use reg_fn to 428 * register it. Otherwise, search for a dynamic NSS module. 429 */ 430static void 431nss_load_module(const char *source, nss_module_register_fn reg_fn) 432{ 433 char buf[PATH_MAX]; 434 ns_mod mod; 435 nss_module_register_fn fn; 436 437 memset(&mod, 0, sizeof(mod)); 438 mod.name = strdup(source); 439 if (mod.name == NULL) { 440 nss_log_simple(LOG_ERR, "memory allocation failure"); 441 return; 442 } 443 if (reg_fn != NULL) { 444 /* The placeholder is required, as a NULL handle 445 * represents an invalid module. 446 */ 447 mod.handle = nss_builtin_handle; 448 fn = reg_fn; 449 } else if (!is_dynamic()) 450 goto fin; 451 else { 452 if (snprintf(buf, sizeof(buf), "nss_%s.so.%d", mod.name, 453 NSS_MODULE_INTERFACE_VERSION) >= (int)sizeof(buf)) 454 goto fin; 455 mod.handle = dlopen(buf, RTLD_LOCAL|RTLD_LAZY); 456 if (mod.handle == NULL) { 457#ifdef _NSS_DEBUG 458 /* This gets pretty annoying since the built-in 459 * sources aren't modules yet. 460 */ 461 nss_log(LOG_DEBUG, "%s, %s", mod.name, dlerror()); 462#endif 463 goto fin; |
203 } | 464 } |
465 fn = (nss_module_register_fn)dlfunc(mod.handle, 466 "nss_module_register"); 467 if (fn == NULL) { 468 (void)dlclose(mod.handle); 469 mod.handle = NULL; 470 nss_log(LOG_ERR, "%s, %s", mod.name, dlerror()); 471 goto fin; 472 } |
|
204 } | 473 } |
474 mod.mtab = fn(mod.name, &mod.mtabsize, &mod.unregister); 475 if (mod.mtab == NULL || mod.mtabsize == 0) { 476 if (mod.handle != nss_builtin_handle) 477 (void)dlclose(mod.handle); 478 mod.handle = NULL; 479 nss_log(LOG_ERR, "%s, registration failed", mod.name); 480 goto fin; 481 } 482 if (mod.mtabsize > 1) 483 qsort(mod.mtab, mod.mtabsize, sizeof(mod.mtab[0]), 484 mtab_compare); 485fin: 486 vector_append(&mod, (void **)&_nsmod, &_nsmodsize, sizeof(*_nsmod)); 487 vector_sort(_nsmod, _nsmodsize, sizeof(*_nsmod), string_compare); 488} |
|
205 | 489 |
206 if ((_nsmapsize % NSELEMSPERCHUNK) == 0) { 207 _nsmap = (ns_dbt *)realloc(_nsmap, 208 (_nsmapsize + NSELEMSPERCHUNK) * sizeof(ns_dbt)); 209 if (_nsmap == NULL) 210 _err(1, "nsdispatch: memory allocation failure"); | 490 491 492static void 493ns_mod_free(ns_mod *mod) 494{ 495 496 free(mod->name); 497 if (mod->handle == NULL) 498 return; 499 if (mod->unregister != NULL) 500 mod->unregister(mod->mtab, mod->mtabsize); 501 if (mod->handle != nss_builtin_handle) 502 (void)dlclose(mod->handle); 503} 504 505 506 507/* 508 * Cleanup 509 */ 510static void 511nss_atexit(void) 512{ 513 (void)_pthread_rwlock_wrlock(&nss_lock); 514 vector_free((void **)&_nsmap, &_nsmapsize, sizeof(*_nsmap), 515 (vector_free_elem)ns_dbt_free); 516 vector_free((void **)&_nsmod, &_nsmodsize, sizeof(*_nsmod), 517 (vector_free_elem)ns_mod_free); 518 (void)_pthread_rwlock_unlock(&nss_lock); 519} 520 521 522 523/* 524 * Finally, the actual implementation. 525 */ 526static nss_method 527nss_method_lookup(const char *source, const char *database, 528 const char *method, const ns_dtab disp_tab[], void **mdata) 529{ 530 ns_mod *mod; 531 ns_mtab *match, key; 532 int i; 533 534 if (disp_tab != NULL) 535 for (i = 0; disp_tab[i].src != NULL; i++) 536 if (strcasecmp(source, disp_tab[i].src) == 0) { 537 *mdata = disp_tab[i].mdata; 538 return (disp_tab[i].method); 539 } 540 mod = vector_search(&source, _nsmod, _nsmodsize, sizeof(*_nsmod), 541 string_compare); 542 if (mod != NULL && mod->handle != NULL) { 543 key.database = database; 544 key.name = method; 545 match = bsearch(&key, mod->mtab, mod->mtabsize, 546 sizeof(mod->mtab[0]), mtab_compare); 547 if (match != NULL) { 548 *mdata = match->mdata; 549 return (match->method); 550 } |
211 } | 551 } |
212 memmove(&_nsmap[_nsmapsize++], dbt, sizeof(ns_dbt)); | 552 nss_log(LOG_DEBUG, "%s, %s, %s, not found", source, database, method); 553 *mdata = NULL; 554 return (NULL); |
213} 214 215 | 555} 556 557 |
558__weak_reference(_nsdispatch, nsdispatch); 559 |
|
216int | 560int |
217nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database, 218 const char *method, const ns_src defaults[], ...) | 561_nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database, 562 const char *method_name, const ns_src defaults[], ...) |
219{ 220 va_list ap; | 563{ 564 va_list ap; |
221 int i, curdisp, result; | |
222 const ns_dbt *dbt; 223 const ns_src *srclist; | 565 const ns_dbt *dbt; 566 const ns_src *srclist; |
224 int srclistsize; | 567 nss_method method; 568 void *mdata; 569 int serrno, i, result, srclistsize; |
225 | 570 |
226 dbt = _nsdbtget(database); | 571 serrno = errno; 572 result = _pthread_rwlock_rdlock(&nss_lock); 573 if (result != 0) { 574 result = NS_UNAVAIL; 575 goto fin; 576 } 577 result = nss_configure(); 578 if (result != 0) { 579 result = NS_UNAVAIL; 580 goto fin; 581 } 582 dbt = vector_search(&database, _nsmap, _nsmapsize, sizeof(*_nsmap), 583 string_compare); |
227 if (dbt != NULL) { 228 srclist = dbt->srclist; 229 srclistsize = dbt->srclistsize; 230 } else { 231 srclist = defaults; 232 srclistsize = 0; 233 while (srclist[srclistsize].name != NULL) 234 srclistsize++; 235 } | 584 if (dbt != NULL) { 585 srclist = dbt->srclist; 586 srclistsize = dbt->srclistsize; 587 } else { 588 srclist = defaults; 589 srclistsize = 0; 590 while (srclist[srclistsize].name != NULL) 591 srclistsize++; 592 } |
236 result = 0; 237 | |
238 for (i = 0; i < srclistsize; i++) { | 593 for (i = 0; i < srclistsize; i++) { |
239 for (curdisp = 0; disp_tab[curdisp].src != NULL; curdisp++) 240 if (strcasecmp(disp_tab[curdisp].src, 241 srclist[i].name) == 0) 242 break; 243 result = 0; 244 if (disp_tab[curdisp].callback) { | 594 result = NS_NOTFOUND; 595 method = nss_method_lookup(srclist[i].name, database, 596 method_name, disp_tab, &mdata); 597 if (method != NULL) { |
245 va_start(ap, defaults); | 598 va_start(ap, defaults); |
246 result = disp_tab[curdisp].callback(retval, 247 disp_tab[curdisp].cb_data, ap); | 599 result = method(retval, mdata, ap); |
248 va_end(ap); | 600 va_end(ap); |
249 if (result & srclist[i].flags) { | 601 if (result & (srclist[i].flags)) |
250 break; | 602 break; |
251 } | |
252 } 253 } | 603 } 604 } |
254 return (result ? result : NS_NOTFOUND); | 605 (void)_pthread_rwlock_unlock(&nss_lock); 606fin: 607 errno = serrno; 608 return (result); |
255} | 609} |