1248aee62SJacques Vidrine /* $NetBSD: nsdispatch.c,v 1.9 1999/01/25 00:16:17 lukem Exp $ */ 2248aee62SJacques Vidrine 3248aee62SJacques Vidrine /*- 4d915a14eSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-NetBSD 5d915a14eSPedro F. Giffuni * 6248aee62SJacques Vidrine * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc. 7248aee62SJacques Vidrine * All rights reserved. 8248aee62SJacques Vidrine * 9248aee62SJacques Vidrine * This code is derived from software contributed to The NetBSD Foundation 10248aee62SJacques Vidrine * by Luke Mewburn. 11248aee62SJacques Vidrine * 12248aee62SJacques Vidrine * Redistribution and use in source and binary forms, with or without 13248aee62SJacques Vidrine * modification, are permitted provided that the following conditions 14248aee62SJacques Vidrine * are met: 15248aee62SJacques Vidrine * 1. Redistributions of source code must retain the above copyright 16248aee62SJacques Vidrine * notice, this list of conditions and the following disclaimer. 17248aee62SJacques Vidrine * 2. Redistributions in binary form must reproduce the above copyright 18248aee62SJacques Vidrine * notice, this list of conditions and the following disclaimer in the 19248aee62SJacques Vidrine * documentation and/or other materials provided with the distribution. 20248aee62SJacques Vidrine * 21248aee62SJacques Vidrine * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 22248aee62SJacques Vidrine * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23248aee62SJacques Vidrine * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24248aee62SJacques Vidrine * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 25248aee62SJacques Vidrine * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26248aee62SJacques Vidrine * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27248aee62SJacques Vidrine * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28248aee62SJacques Vidrine * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29248aee62SJacques Vidrine * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30248aee62SJacques Vidrine * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31248aee62SJacques Vidrine * POSSIBILITY OF SUCH DAMAGE. 32248aee62SJacques Vidrine */ 3346d93063SJacques Vidrine /*- 3446d93063SJacques Vidrine * Copyright (c) 2003 Networks Associates Technology, Inc. 3546d93063SJacques Vidrine * All rights reserved. 3646d93063SJacques Vidrine * 3746d93063SJacques Vidrine * Portions of this software were developed for the FreeBSD Project by 3846d93063SJacques Vidrine * Jacques A. Vidrine, Safeport Network Services, and Network 3946d93063SJacques Vidrine * Associates Laboratories, the Security Research Division of Network 4046d93063SJacques Vidrine * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 4146d93063SJacques Vidrine * ("CBOSS"), as part of the DARPA CHATS research program. 4246d93063SJacques Vidrine * 4346d93063SJacques Vidrine * Redistribution and use in source and binary forms, with or without 4446d93063SJacques Vidrine * modification, are permitted provided that the following conditions 4546d93063SJacques Vidrine * are met: 4646d93063SJacques Vidrine * 1. Redistributions of source code must retain the above copyright 4746d93063SJacques Vidrine * notice, this list of conditions and the following disclaimer. 4846d93063SJacques Vidrine * 2. Redistributions in binary form must reproduce the above copyright 4946d93063SJacques Vidrine * notice, this list of conditions and the following disclaimer in the 5046d93063SJacques Vidrine * documentation and/or other materials provided with the distribution. 5146d93063SJacques Vidrine * 5246d93063SJacques Vidrine * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 5346d93063SJacques Vidrine * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 5446d93063SJacques Vidrine * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 5546d93063SJacques Vidrine * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 5646d93063SJacques Vidrine * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 5746d93063SJacques Vidrine * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 5846d93063SJacques Vidrine * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 5946d93063SJacques Vidrine * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 6046d93063SJacques Vidrine * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 6146d93063SJacques Vidrine * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 6246d93063SJacques Vidrine * SUCH DAMAGE. 6346d93063SJacques Vidrine * 6446d93063SJacques Vidrine */ 65248aee62SJacques Vidrine #include <sys/cdefs.h> 66333fc21eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 67248aee62SJacques Vidrine 6846d93063SJacques Vidrine #include "namespace.h" 69248aee62SJacques Vidrine #include <sys/param.h> 70248aee62SJacques Vidrine #include <sys/stat.h> 71248aee62SJacques Vidrine 7246d93063SJacques Vidrine #include <dlfcn.h> 7346d93063SJacques Vidrine #include <errno.h> 74248aee62SJacques Vidrine #include <fcntl.h> 75248aee62SJacques Vidrine #define _NS_PRIVATE 76248aee62SJacques Vidrine #include <nsswitch.h> 7746d93063SJacques Vidrine #include <pthread.h> 786d722173SZachary Loafman #include <pthread_np.h> 79248aee62SJacques Vidrine #include <stdio.h> 80248aee62SJacques Vidrine #include <stdlib.h> 81248aee62SJacques Vidrine #include <string.h> 8246d93063SJacques Vidrine #include <syslog.h> 83248aee62SJacques Vidrine #include <unistd.h> 842bbd7cf8SJacques Vidrine #include "un-namespace.h" 856d722173SZachary Loafman #include "nss_tls.h" 86ab930670SJohn Baldwin #include "libc_private.h" 8706a99fe3SHajimu UMEMOTO #ifdef NS_CACHING 8806a99fe3SHajimu UMEMOTO #include "nscache.h" 8906a99fe3SHajimu UMEMOTO #endif 90248aee62SJacques Vidrine 9146d93063SJacques Vidrine enum _nss_constants { 9246d93063SJacques Vidrine /* Number of elements allocated when we grow a vector */ 9346d93063SJacques Vidrine ELEMSPERCHUNK = 8 9446d93063SJacques Vidrine }; 9546d93063SJacques Vidrine 9646d93063SJacques Vidrine /* 9746d93063SJacques Vidrine * Global NSS data structures are mostly read-only, but we update 9846d93063SJacques Vidrine * them when we read or re-read the nsswitch.conf. 9946d93063SJacques Vidrine */ 10046d93063SJacques Vidrine static pthread_rwlock_t nss_lock = PTHREAD_RWLOCK_INITIALIZER; 10146d93063SJacques Vidrine 10246d93063SJacques Vidrine /* 10346d93063SJacques Vidrine * Runtime determination of whether we are dynamically linked or not. 10446d93063SJacques Vidrine */ 10546d93063SJacques Vidrine extern int _DYNAMIC __attribute__ ((weak)); 10646d93063SJacques Vidrine #define is_dynamic() (&_DYNAMIC != NULL) 10746d93063SJacques Vidrine 108248aee62SJacques Vidrine /* 109248aee62SJacques Vidrine * default sourcelist: `files' 110248aee62SJacques Vidrine */ 111248aee62SJacques Vidrine const ns_src __nsdefaultsrc[] = { 112248aee62SJacques Vidrine { NSSRC_FILES, NS_SUCCESS }, 113248aee62SJacques Vidrine { 0 }, 114248aee62SJacques Vidrine }; 115248aee62SJacques Vidrine 11646d93063SJacques Vidrine /* Database, source mappings. */ 117*738314e4SAlex Richardson static unsigned int _nsmapsize; 118*738314e4SAlex Richardson static ns_dbt *_nsmap = NULL; 119248aee62SJacques Vidrine 12046d93063SJacques Vidrine /* NSS modules. */ 121*738314e4SAlex Richardson static unsigned int _nsmodsize; 122*738314e4SAlex Richardson static ns_mod *_nsmod; 12346d93063SJacques Vidrine 12446d93063SJacques Vidrine /* Placeholder for builtin modules' dlopen `handle'. */ 12546d93063SJacques Vidrine static int __nss_builtin_handle; 12646d93063SJacques Vidrine static void *nss_builtin_handle = &__nss_builtin_handle; 12746d93063SJacques Vidrine 12806a99fe3SHajimu UMEMOTO #ifdef NS_CACHING 12906a99fe3SHajimu UMEMOTO /* 13006a99fe3SHajimu UMEMOTO * Cache lookup cycle prevention function - if !NULL then no cache lookups 13106a99fe3SHajimu UMEMOTO * will be made 13206a99fe3SHajimu UMEMOTO */ 13306a99fe3SHajimu UMEMOTO static void *nss_cache_cycle_prevention_func = NULL; 13406a99fe3SHajimu UMEMOTO #endif 13506a99fe3SHajimu UMEMOTO 136248aee62SJacques Vidrine /* 13783804ea0SDag-Erling Smørgrav * We keep track of nsdispatch() nesting depth in dispatch_depth. When a 13883804ea0SDag-Erling Smørgrav * fallback method is invoked from nsdispatch(), we temporarily set 13983804ea0SDag-Erling Smørgrav * fallback_depth to the current dispatch depth plus one. Subsequent 14083804ea0SDag-Erling Smørgrav * calls at that exact depth will run in fallback mode (restricted to the 14183804ea0SDag-Erling Smørgrav * same source as the call that was handled by the fallback method), while 14283804ea0SDag-Erling Smørgrav * calls below that depth will be handled normally, allowing fallback 14383804ea0SDag-Erling Smørgrav * methods to perform arbitrary lookups. 144a59d6a87SMichael Bushkov */ 1456d722173SZachary Loafman struct fb_state { 14683804ea0SDag-Erling Smørgrav int dispatch_depth; 14783804ea0SDag-Erling Smørgrav int fallback_depth; 1486d722173SZachary Loafman }; 1496d722173SZachary Loafman static void fb_endstate(void *); 1506d722173SZachary Loafman NSS_TLS_HANDLING(fb); 151a59d6a87SMichael Bushkov 152a59d6a87SMichael Bushkov /* 15346d93063SJacques Vidrine * Attempt to spew relatively uniform messages to syslog. 154248aee62SJacques Vidrine */ 15546d93063SJacques Vidrine #define nss_log(level, fmt, ...) \ 15646d93063SJacques Vidrine syslog((level), "NSSWITCH(%s): " fmt, __func__, __VA_ARGS__) 15746d93063SJacques Vidrine #define nss_log_simple(level, s) \ 15846d93063SJacques Vidrine syslog((level), "NSSWITCH(%s): " s, __func__) 15946d93063SJacques Vidrine 16046d93063SJacques Vidrine /* 16146d93063SJacques Vidrine * Dynamically growable arrays are used for lists of databases, sources, 16246d93063SJacques Vidrine * and modules. The following `vector' interface is used to isolate the 16346d93063SJacques Vidrine * common operations. 16446d93063SJacques Vidrine */ 16546d93063SJacques Vidrine typedef int (*vector_comparison)(const void *, const void *); 16646d93063SJacques Vidrine typedef void (*vector_free_elem)(void *); 16746d93063SJacques Vidrine static void vector_sort(void *, unsigned int, size_t, 16846d93063SJacques Vidrine vector_comparison); 169*738314e4SAlex Richardson static void vector_free(void *, unsigned int *, size_t, 170*738314e4SAlex Richardson vector_free_elem); 17146d93063SJacques Vidrine static void *vector_ref(unsigned int, void *, unsigned int, size_t); 17246d93063SJacques Vidrine static void *vector_search(const void *, void *, unsigned int, size_t, 17346d93063SJacques Vidrine vector_comparison); 1744705e3daSDag-Erling Smørgrav static void *vector_append(const void *, void *, unsigned int *, size_t); 175248aee62SJacques Vidrine 176248aee62SJacques Vidrine 17746d93063SJacques Vidrine /* 17846d93063SJacques Vidrine * Internal interfaces. 17946d93063SJacques Vidrine */ 18046d93063SJacques Vidrine static int string_compare(const void *, const void *); 18146d93063SJacques Vidrine static int mtab_compare(const void *, const void *); 18246d93063SJacques Vidrine static int nss_configure(void); 18346d93063SJacques Vidrine static void ns_dbt_free(ns_dbt *); 18446d93063SJacques Vidrine static void ns_mod_free(ns_mod *); 18546d93063SJacques Vidrine static void ns_src_free(ns_src **, int); 18646d93063SJacques Vidrine static void nss_load_builtin_modules(void); 18746d93063SJacques Vidrine static void nss_load_module(const char *, nss_module_register_fn); 18846d93063SJacques Vidrine static void nss_atexit(void); 18946d93063SJacques Vidrine /* nsparser */ 19046d93063SJacques Vidrine extern FILE *_nsyyin; 191248aee62SJacques Vidrine 192248aee62SJacques Vidrine 19346d93063SJacques Vidrine /* 19446d93063SJacques Vidrine * The vector operations 19546d93063SJacques Vidrine */ 19646d93063SJacques Vidrine static void 19746d93063SJacques Vidrine vector_sort(void *vec, unsigned int count, size_t esize, 19846d93063SJacques Vidrine vector_comparison comparison) 199248aee62SJacques Vidrine { 20046d93063SJacques Vidrine qsort(vec, count, esize, comparison); 201248aee62SJacques Vidrine } 202248aee62SJacques Vidrine 203248aee62SJacques Vidrine 20446d93063SJacques Vidrine static void * 20546d93063SJacques Vidrine vector_search(const void *key, void *vec, unsigned int count, size_t esize, 20646d93063SJacques Vidrine vector_comparison comparison) 207248aee62SJacques Vidrine { 20846d93063SJacques Vidrine return (bsearch(key, vec, count, esize, comparison)); 209248aee62SJacques Vidrine } 210248aee62SJacques Vidrine 211248aee62SJacques Vidrine 2124705e3daSDag-Erling Smørgrav static void * 2134705e3daSDag-Erling Smørgrav vector_append(const void *elem, void *vec, unsigned int *count, size_t esize) 21446d93063SJacques Vidrine { 21546d93063SJacques Vidrine void *p; 21646d93063SJacques Vidrine 21746d93063SJacques Vidrine if ((*count % ELEMSPERCHUNK) == 0) { 2189f36610fSPedro F. Giffuni p = reallocarray(vec, *count + ELEMSPERCHUNK, esize); 21946d93063SJacques Vidrine if (p == NULL) { 22046d93063SJacques Vidrine nss_log_simple(LOG_ERR, "memory allocation failure"); 2214705e3daSDag-Erling Smørgrav return (vec); 22246d93063SJacques Vidrine } 2234705e3daSDag-Erling Smørgrav vec = p; 2244705e3daSDag-Erling Smørgrav } 2254705e3daSDag-Erling Smørgrav memmove((void *)(((uintptr_t)vec) + (*count * esize)), elem, esize); 22646d93063SJacques Vidrine (*count)++; 2274705e3daSDag-Erling Smørgrav return (vec); 22846d93063SJacques Vidrine } 22946d93063SJacques Vidrine 23046d93063SJacques Vidrine 23146d93063SJacques Vidrine static void * 23246d93063SJacques Vidrine vector_ref(unsigned int i, void *vec, unsigned int count, size_t esize) 23346d93063SJacques Vidrine { 23446d93063SJacques Vidrine if (i < count) 23546d93063SJacques Vidrine return (void *)((uintptr_t)vec + (i * esize)); 23646d93063SJacques Vidrine else 23746d93063SJacques Vidrine return (NULL); 23846d93063SJacques Vidrine } 23946d93063SJacques Vidrine 24046d93063SJacques Vidrine 241*738314e4SAlex Richardson #define VECTOR_FREE(v, c, s, f) \ 242*738314e4SAlex Richardson do { vector_free(v, c, s, f); v = NULL; } while (0) 24346d93063SJacques Vidrine static void 244*738314e4SAlex Richardson vector_free(void *vec, unsigned int *count, size_t esize, 24546d93063SJacques Vidrine vector_free_elem free_elem) 24646d93063SJacques Vidrine { 24746d93063SJacques Vidrine unsigned int i; 24846d93063SJacques Vidrine void *elem; 24946d93063SJacques Vidrine 250*738314e4SAlex Richardson for (i = 0; i < *count; i++) { 251*738314e4SAlex Richardson elem = vector_ref(i, vec, *count, esize); 25246d93063SJacques Vidrine if (elem != NULL) 25346d93063SJacques Vidrine free_elem(elem); 25446d93063SJacques Vidrine } 2554705e3daSDag-Erling Smørgrav free(vec); 256*738314e4SAlex Richardson *count = 0; 25746d93063SJacques Vidrine } 25846d93063SJacques Vidrine 25946d93063SJacques Vidrine /* 26046d93063SJacques Vidrine * Comparison functions for vector_search. 26146d93063SJacques Vidrine */ 26246d93063SJacques Vidrine static int 26346d93063SJacques Vidrine string_compare(const void *a, const void *b) 26446d93063SJacques Vidrine { 26546d93063SJacques Vidrine return (strcasecmp(*(const char * const *)a, *(const char * const *)b)); 26646d93063SJacques Vidrine } 26746d93063SJacques Vidrine 26846d93063SJacques Vidrine 26946d93063SJacques Vidrine static int 27046d93063SJacques Vidrine mtab_compare(const void *a, const void *b) 27146d93063SJacques Vidrine { 27246d93063SJacques Vidrine int cmp; 27346d93063SJacques Vidrine 27446d93063SJacques Vidrine cmp = strcmp(((const ns_mtab *)a)->name, ((const ns_mtab *)b)->name); 27546d93063SJacques Vidrine if (cmp != 0) 27646d93063SJacques Vidrine return (cmp); 27746d93063SJacques Vidrine else 27846d93063SJacques Vidrine return (strcmp(((const ns_mtab *)a)->database, 27946d93063SJacques Vidrine ((const ns_mtab *)b)->database)); 28046d93063SJacques Vidrine } 28146d93063SJacques Vidrine 28246d93063SJacques Vidrine /* 28346d93063SJacques Vidrine * NSS nsmap management. 28446d93063SJacques Vidrine */ 285*738314e4SAlex Richardson void 28646d93063SJacques Vidrine _nsdbtaddsrc(ns_dbt *dbt, const ns_src *src) 28746d93063SJacques Vidrine { 28846d93063SJacques Vidrine const ns_mod *modp; 28946d93063SJacques Vidrine 290*738314e4SAlex Richardson dbt->srclist = vector_append(src, dbt->srclist, &dbt->srclistsize, 291*738314e4SAlex Richardson sizeof(*src)); 29246d93063SJacques Vidrine modp = vector_search(&src->name, _nsmod, _nsmodsize, sizeof(*_nsmod), 29346d93063SJacques Vidrine string_compare); 29446d93063SJacques Vidrine if (modp == NULL) 29546d93063SJacques Vidrine nss_load_module(src->name, NULL); 29646d93063SJacques Vidrine } 29746d93063SJacques Vidrine 29846d93063SJacques Vidrine 29946d93063SJacques Vidrine #ifdef _NSS_DEBUG 30046d93063SJacques Vidrine void 30146d93063SJacques Vidrine _nsdbtdump(const ns_dbt *dbt) 302248aee62SJacques Vidrine { 303248aee62SJacques Vidrine int i; 304248aee62SJacques Vidrine 305248aee62SJacques Vidrine printf("%s (%d source%s):", dbt->name, dbt->srclistsize, 306248aee62SJacques Vidrine dbt->srclistsize == 1 ? "" : "s"); 30746d93063SJacques Vidrine for (i = 0; i < (int)dbt->srclistsize; i++) { 308248aee62SJacques Vidrine printf(" %s", dbt->srclist[i].name); 309248aee62SJacques Vidrine if (!(dbt->srclist[i].flags & 310248aee62SJacques Vidrine (NS_UNAVAIL|NS_NOTFOUND|NS_TRYAGAIN)) && 311248aee62SJacques Vidrine (dbt->srclist[i].flags & NS_SUCCESS)) 312248aee62SJacques Vidrine continue; 313248aee62SJacques Vidrine printf(" ["); 314248aee62SJacques Vidrine if (!(dbt->srclist[i].flags & NS_SUCCESS)) 315248aee62SJacques Vidrine printf(" SUCCESS=continue"); 316248aee62SJacques Vidrine if (dbt->srclist[i].flags & NS_UNAVAIL) 317248aee62SJacques Vidrine printf(" UNAVAIL=return"); 318248aee62SJacques Vidrine if (dbt->srclist[i].flags & NS_NOTFOUND) 319248aee62SJacques Vidrine printf(" NOTFOUND=return"); 320248aee62SJacques Vidrine if (dbt->srclist[i].flags & NS_TRYAGAIN) 321248aee62SJacques Vidrine printf(" TRYAGAIN=return"); 322248aee62SJacques Vidrine printf(" ]"); 323248aee62SJacques Vidrine } 324248aee62SJacques Vidrine printf("\n"); 325248aee62SJacques Vidrine } 32646d93063SJacques Vidrine #endif 327248aee62SJacques Vidrine 328248aee62SJacques Vidrine 32946d93063SJacques Vidrine /* 33046d93063SJacques Vidrine * The first time nsdispatch is called (during a process's lifetime, 33146d93063SJacques Vidrine * or after nsswitch.conf has been updated), nss_configure will 33246d93063SJacques Vidrine * prepare global data needed by NSS. 33346d93063SJacques Vidrine */ 334*738314e4SAlex Richardson static int 335*738314e4SAlex Richardson nss_configure(void) 336248aee62SJacques Vidrine { 337*738314e4SAlex Richardson static time_t confmod; 338*738314e4SAlex Richardson static int already_initialized = 0; 339248aee62SJacques Vidrine struct stat statbuf; 340*738314e4SAlex Richardson int result, isthreaded; 34146d93063SJacques Vidrine const char *path; 34206a99fe3SHajimu UMEMOTO #ifdef NS_CACHING 34306a99fe3SHajimu UMEMOTO void *handle; 34406a99fe3SHajimu UMEMOTO #endif 345248aee62SJacques Vidrine 346a03fd3b6SJacques Vidrine result = 0; 347*738314e4SAlex Richardson isthreaded = __isthreaded; 34846d93063SJacques Vidrine #if defined(_NSS_DEBUG) && defined(_NSS_SHOOT_FOOT) 34946d93063SJacques Vidrine /* NOTE WELL: THIS IS A SECURITY HOLE. This must only be built 35046d93063SJacques Vidrine * for debugging purposes and MUST NEVER be used in production. 35146d93063SJacques Vidrine */ 35246d93063SJacques Vidrine path = getenv("NSSWITCH_CONF"); 35346d93063SJacques Vidrine if (path == NULL) 35446d93063SJacques Vidrine #endif 35546d93063SJacques Vidrine path = _PATH_NS_CONF; 3565245bf7bSAlex Richardson #ifndef NS_REREAD_CONF 3575245bf7bSAlex Richardson /* 358*738314e4SAlex Richardson * Define NS_REREAD_CONF to have nsswitch notice changes 359*738314e4SAlex Richardson * to nsswitch.conf(5) during runtime. This involves calling 360*738314e4SAlex Richardson * stat(2) every time, which can result in performance hit. 3615245bf7bSAlex Richardson */ 3625245bf7bSAlex Richardson if (already_initialized) 363*738314e4SAlex Richardson return (0); 364*738314e4SAlex Richardson already_initialized = 1; 3655245bf7bSAlex Richardson #endif /* NS_REREAD_CONF */ 366*738314e4SAlex Richardson if (stat(path, &statbuf) != 0) 367*738314e4SAlex Richardson return (0); 368*738314e4SAlex Richardson if (statbuf.st_mtime <= confmod) 369*738314e4SAlex Richardson return (0); 370*738314e4SAlex Richardson if (isthreaded) { 371*738314e4SAlex Richardson (void)_pthread_rwlock_unlock(&nss_lock); 372*738314e4SAlex Richardson result = _pthread_rwlock_wrlock(&nss_lock); 373*738314e4SAlex Richardson if (result != 0) 374*738314e4SAlex Richardson return (result); 375f53b0456SMark Johnston if (stat(path, &statbuf) != 0) 376f53b0456SMark Johnston goto fin; 377f53b0456SMark Johnston if (statbuf.st_mtime <= confmod) 378f53b0456SMark Johnston goto fin; 379*738314e4SAlex Richardson } 380a93705b0SJilles Tjoelker _nsyyin = fopen(path, "re"); 3818074e24dSJacques Vidrine if (_nsyyin == NULL) 38246d93063SJacques Vidrine goto fin; 383*738314e4SAlex Richardson VECTOR_FREE(_nsmap, &_nsmapsize, sizeof(*_nsmap), 38446d93063SJacques Vidrine (vector_free_elem)ns_dbt_free); 385*738314e4SAlex Richardson VECTOR_FREE(_nsmod, &_nsmodsize, sizeof(*_nsmod), 38646d93063SJacques Vidrine (vector_free_elem)ns_mod_free); 387888e46a9SMark Johnston if (confmod == 0) 388888e46a9SMark Johnston (void)atexit(nss_atexit); 38946d93063SJacques Vidrine nss_load_builtin_modules(); 390248aee62SJacques Vidrine _nsyyparse(); 391248aee62SJacques Vidrine (void)fclose(_nsyyin); 39246d93063SJacques Vidrine vector_sort(_nsmap, _nsmapsize, sizeof(*_nsmap), string_compare); 393248aee62SJacques Vidrine confmod = statbuf.st_mtime; 39406a99fe3SHajimu UMEMOTO 39506a99fe3SHajimu UMEMOTO #ifdef NS_CACHING 3963e65b9c6SColin Percival handle = libc_dlopen(NULL, RTLD_LAZY | RTLD_GLOBAL); 39706a99fe3SHajimu UMEMOTO if (handle != NULL) { 39806a99fe3SHajimu UMEMOTO nss_cache_cycle_prevention_func = dlsym(handle, 39906a99fe3SHajimu UMEMOTO "_nss_cache_cycle_prevention_function"); 40006a99fe3SHajimu UMEMOTO dlclose(handle); 40106a99fe3SHajimu UMEMOTO } 40206a99fe3SHajimu UMEMOTO #endif 40346d93063SJacques Vidrine fin: 404*738314e4SAlex Richardson if (isthreaded) { 405*738314e4SAlex Richardson (void)_pthread_rwlock_unlock(&nss_lock); 406a03fd3b6SJacques Vidrine if (result == 0) 40746d93063SJacques Vidrine result = _pthread_rwlock_rdlock(&nss_lock); 408a03fd3b6SJacques Vidrine } 40946d93063SJacques Vidrine return (result); 410248aee62SJacques Vidrine } 411248aee62SJacques Vidrine 412248aee62SJacques Vidrine 413*738314e4SAlex Richardson void 41446d93063SJacques Vidrine _nsdbtput(const ns_dbt *dbt) 415248aee62SJacques Vidrine { 41646d93063SJacques Vidrine unsigned int i; 41746d93063SJacques Vidrine ns_dbt *p; 418248aee62SJacques Vidrine 419248aee62SJacques Vidrine for (i = 0; i < _nsmapsize; i++) { 42046d93063SJacques Vidrine p = vector_ref(i, _nsmap, _nsmapsize, sizeof(*_nsmap)); 42146d93063SJacques Vidrine if (string_compare(&dbt->name, &p->name) == 0) { 422248aee62SJacques Vidrine /* overwrite existing entry */ 42346d93063SJacques Vidrine if (p->srclist != NULL) 42446d93063SJacques Vidrine ns_src_free(&p->srclist, p->srclistsize); 42546d93063SJacques Vidrine memmove(p, dbt, sizeof(*dbt)); 426248aee62SJacques Vidrine return; 427248aee62SJacques Vidrine } 428248aee62SJacques Vidrine } 4294705e3daSDag-Erling Smørgrav _nsmap = vector_append(dbt, _nsmap, &_nsmapsize, sizeof(*_nsmap)); 430248aee62SJacques Vidrine } 431248aee62SJacques Vidrine 432248aee62SJacques Vidrine 43346d93063SJacques Vidrine static void 43446d93063SJacques Vidrine ns_dbt_free(ns_dbt *dbt) 43546d93063SJacques Vidrine { 43646d93063SJacques Vidrine ns_src_free(&dbt->srclist, dbt->srclistsize); 4377a800a56SJonathan Chen if (dbt->name) 4387a800a56SJonathan Chen free((void *)dbt->name); 43946d93063SJacques Vidrine } 44046d93063SJacques Vidrine 44146d93063SJacques Vidrine 44246d93063SJacques Vidrine static void 44346d93063SJacques Vidrine ns_src_free(ns_src **src, int srclistsize) 44446d93063SJacques Vidrine { 44546d93063SJacques Vidrine int i; 44646d93063SJacques Vidrine 44746d93063SJacques Vidrine for (i = 0; i < srclistsize; i++) 44846d93063SJacques Vidrine if ((*src)[i].name != NULL) 44946d93063SJacques Vidrine /* This one was allocated by nslexer. You'll just 45046d93063SJacques Vidrine * have to trust me. 45146d93063SJacques Vidrine */ 45246d93063SJacques Vidrine free((void *)((*src)[i].name)); 45346d93063SJacques Vidrine free(*src); 45446d93063SJacques Vidrine *src = NULL; 45546d93063SJacques Vidrine } 45646d93063SJacques Vidrine 45746d93063SJacques Vidrine 45846d93063SJacques Vidrine 45946d93063SJacques Vidrine /* 46046d93063SJacques Vidrine * NSS module management. 46146d93063SJacques Vidrine */ 46246d93063SJacques Vidrine /* The built-in NSS modules are all loaded at once. */ 46346d93063SJacques Vidrine #define NSS_BACKEND(name, reg) \ 46446d93063SJacques Vidrine ns_mtab *reg(unsigned int *, nss_module_unregister_fn *); 46546d93063SJacques Vidrine #include "nss_backends.h" 46646d93063SJacques Vidrine #undef NSS_BACKEND 46746d93063SJacques Vidrine 46846d93063SJacques Vidrine static void 46946d93063SJacques Vidrine nss_load_builtin_modules(void) 47046d93063SJacques Vidrine { 47146d93063SJacques Vidrine #define NSS_BACKEND(name, reg) nss_load_module(#name, reg); 47246d93063SJacques Vidrine #include "nss_backends.h" 47346d93063SJacques Vidrine #undef NSS_BACKEND 47446d93063SJacques Vidrine } 47546d93063SJacques Vidrine 47646d93063SJacques Vidrine 47746d93063SJacques Vidrine /* Load a built-in or dynamically linked module. If the `reg_fn' 47846d93063SJacques Vidrine * argument is non-NULL, assume a built-in module and use reg_fn to 47946d93063SJacques Vidrine * register it. Otherwise, search for a dynamic NSS module. 48046d93063SJacques Vidrine */ 481*738314e4SAlex Richardson static void 48246d93063SJacques Vidrine nss_load_module(const char *source, nss_module_register_fn reg_fn) 48346d93063SJacques Vidrine { 48446d93063SJacques Vidrine char buf[PATH_MAX]; 48546d93063SJacques Vidrine ns_mod mod; 48646d93063SJacques Vidrine nss_module_register_fn fn; 48746d93063SJacques Vidrine 48846d93063SJacques Vidrine memset(&mod, 0, sizeof(mod)); 48946d93063SJacques Vidrine mod.name = strdup(source); 49046d93063SJacques Vidrine if (mod.name == NULL) { 49146d93063SJacques Vidrine nss_log_simple(LOG_ERR, "memory allocation failure"); 49246d93063SJacques Vidrine return; 49346d93063SJacques Vidrine } 49446d93063SJacques Vidrine if (reg_fn != NULL) { 49546d93063SJacques Vidrine /* The placeholder is required, as a NULL handle 49646d93063SJacques Vidrine * represents an invalid module. 49746d93063SJacques Vidrine */ 49846d93063SJacques Vidrine mod.handle = nss_builtin_handle; 49946d93063SJacques Vidrine fn = reg_fn; 5001d7da823SEdward Tomasz Napierala } else if (!is_dynamic()) { 50146d93063SJacques Vidrine goto fin; 5021d7da823SEdward Tomasz Napierala } else if (strcmp(source, NSSRC_CACHE) == 0 || 5031d7da823SEdward Tomasz Napierala strcmp(source, NSSRC_COMPAT) == 0 || 5041d7da823SEdward Tomasz Napierala strcmp(source, NSSRC_DB) == 0 || 5051d7da823SEdward Tomasz Napierala strcmp(source, NSSRC_DNS) == 0 || 5061d7da823SEdward Tomasz Napierala strcmp(source, NSSRC_FILES) == 0 || 5071d7da823SEdward Tomasz Napierala strcmp(source, NSSRC_NIS) == 0) { 5081d7da823SEdward Tomasz Napierala /* 5091d7da823SEdward Tomasz Napierala * Avoid calling dlopen(3) for built-in modules. 5101d7da823SEdward Tomasz Napierala */ 5111d7da823SEdward Tomasz Napierala goto fin; 5121d7da823SEdward Tomasz Napierala } else { 51346d93063SJacques Vidrine if (snprintf(buf, sizeof(buf), "nss_%s.so.%d", mod.name, 51446d93063SJacques Vidrine NSS_MODULE_INTERFACE_VERSION) >= (int)sizeof(buf)) 51546d93063SJacques Vidrine goto fin; 5163e65b9c6SColin Percival mod.handle = libc_dlopen(buf, RTLD_LOCAL|RTLD_LAZY); 51746d93063SJacques Vidrine if (mod.handle == NULL) { 51846d93063SJacques Vidrine #ifdef _NSS_DEBUG 51946d93063SJacques Vidrine /* This gets pretty annoying since the built-in 52046d93063SJacques Vidrine * sources aren't modules yet. 52146d93063SJacques Vidrine */ 52246d93063SJacques Vidrine nss_log(LOG_DEBUG, "%s, %s", mod.name, dlerror()); 52346d93063SJacques Vidrine #endif 52446d93063SJacques Vidrine goto fin; 52546d93063SJacques Vidrine } 52646d93063SJacques Vidrine fn = (nss_module_register_fn)dlfunc(mod.handle, 52746d93063SJacques Vidrine "nss_module_register"); 52846d93063SJacques Vidrine if (fn == NULL) { 52946d93063SJacques Vidrine (void)dlclose(mod.handle); 53046d93063SJacques Vidrine mod.handle = NULL; 53146d93063SJacques Vidrine nss_log(LOG_ERR, "%s, %s", mod.name, dlerror()); 53246d93063SJacques Vidrine goto fin; 53346d93063SJacques Vidrine } 53446d93063SJacques Vidrine } 53546d93063SJacques Vidrine mod.mtab = fn(mod.name, &mod.mtabsize, &mod.unregister); 53646d93063SJacques Vidrine if (mod.mtab == NULL || mod.mtabsize == 0) { 53746d93063SJacques Vidrine if (mod.handle != nss_builtin_handle) 53846d93063SJacques Vidrine (void)dlclose(mod.handle); 53946d93063SJacques Vidrine mod.handle = NULL; 54046d93063SJacques Vidrine nss_log(LOG_ERR, "%s, registration failed", mod.name); 54146d93063SJacques Vidrine goto fin; 54246d93063SJacques Vidrine } 54346d93063SJacques Vidrine if (mod.mtabsize > 1) 54446d93063SJacques Vidrine qsort(mod.mtab, mod.mtabsize, sizeof(mod.mtab[0]), 54546d93063SJacques Vidrine mtab_compare); 54646d93063SJacques Vidrine fin: 5474705e3daSDag-Erling Smørgrav _nsmod = vector_append(&mod, _nsmod, &_nsmodsize, sizeof(*_nsmod)); 54846d93063SJacques Vidrine vector_sort(_nsmod, _nsmodsize, sizeof(*_nsmod), string_compare); 54946d93063SJacques Vidrine } 55046d93063SJacques Vidrine 551*738314e4SAlex Richardson static int exiting = 0; 55246d93063SJacques Vidrine 553*738314e4SAlex Richardson static void 55446d93063SJacques Vidrine ns_mod_free(ns_mod *mod) 55546d93063SJacques Vidrine { 55646d93063SJacques Vidrine 55746d93063SJacques Vidrine free(mod->name); 55846d93063SJacques Vidrine if (mod->handle == NULL) 55946d93063SJacques Vidrine return; 56046d93063SJacques Vidrine if (mod->unregister != NULL) 56146d93063SJacques Vidrine mod->unregister(mod->mtab, mod->mtabsize); 5627f48d6a4SMark Johnston if (mod->handle != nss_builtin_handle && !exiting) 56346d93063SJacques Vidrine (void)dlclose(mod->handle); 56446d93063SJacques Vidrine } 56546d93063SJacques Vidrine 56646d93063SJacques Vidrine /* 56746d93063SJacques Vidrine * Cleanup 56846d93063SJacques Vidrine */ 56946d93063SJacques Vidrine static void 57046d93063SJacques Vidrine nss_atexit(void) 57146d93063SJacques Vidrine { 572*738314e4SAlex Richardson int isthreaded; 573*738314e4SAlex Richardson 5747f48d6a4SMark Johnston exiting = 1; 575*738314e4SAlex Richardson isthreaded = __isthreaded; 576*738314e4SAlex Richardson if (isthreaded) 577*738314e4SAlex Richardson (void)_pthread_rwlock_wrlock(&nss_lock); 578*738314e4SAlex Richardson VECTOR_FREE(_nsmap, &_nsmapsize, sizeof(*_nsmap), 57946d93063SJacques Vidrine (vector_free_elem)ns_dbt_free); 580*738314e4SAlex Richardson VECTOR_FREE(_nsmod, &_nsmodsize, sizeof(*_nsmod), 58146d93063SJacques Vidrine (vector_free_elem)ns_mod_free); 582*738314e4SAlex Richardson if (isthreaded) 583*738314e4SAlex Richardson (void)_pthread_rwlock_unlock(&nss_lock); 58446d93063SJacques Vidrine } 58546d93063SJacques Vidrine 58646d93063SJacques Vidrine /* 58746d93063SJacques Vidrine * Finally, the actual implementation. 58846d93063SJacques Vidrine */ 589*738314e4SAlex Richardson static nss_method 59046d93063SJacques Vidrine nss_method_lookup(const char *source, const char *database, 59146d93063SJacques Vidrine const char *method, const ns_dtab disp_tab[], void **mdata) 59246d93063SJacques Vidrine { 59346d93063SJacques Vidrine ns_mod *mod; 59446d93063SJacques Vidrine ns_mtab *match, key; 59546d93063SJacques Vidrine int i; 59646d93063SJacques Vidrine 59746d93063SJacques Vidrine if (disp_tab != NULL) 59846d93063SJacques Vidrine for (i = 0; disp_tab[i].src != NULL; i++) 59946d93063SJacques Vidrine if (strcasecmp(source, disp_tab[i].src) == 0) { 60046d93063SJacques Vidrine *mdata = disp_tab[i].mdata; 60146d93063SJacques Vidrine return (disp_tab[i].method); 60246d93063SJacques Vidrine } 60346d93063SJacques Vidrine mod = vector_search(&source, _nsmod, _nsmodsize, sizeof(*_nsmod), 60446d93063SJacques Vidrine string_compare); 60546d93063SJacques Vidrine if (mod != NULL && mod->handle != NULL) { 60646d93063SJacques Vidrine key.database = database; 60746d93063SJacques Vidrine key.name = method; 60846d93063SJacques Vidrine match = bsearch(&key, mod->mtab, mod->mtabsize, 60946d93063SJacques Vidrine sizeof(mod->mtab[0]), mtab_compare); 61046d93063SJacques Vidrine if (match != NULL) { 61146d93063SJacques Vidrine *mdata = match->mdata; 61246d93063SJacques Vidrine return (match->method); 61346d93063SJacques Vidrine } 61446d93063SJacques Vidrine } 61536736e35SMichael Bushkov 61646d93063SJacques Vidrine *mdata = NULL; 61746d93063SJacques Vidrine return (NULL); 61846d93063SJacques Vidrine } 61946d93063SJacques Vidrine 6206d722173SZachary Loafman static void 6216d722173SZachary Loafman fb_endstate(void *p) 6226d722173SZachary Loafman { 6236d722173SZachary Loafman free(p); 6246d722173SZachary Loafman } 62546d93063SJacques Vidrine 62646d93063SJacques Vidrine __weak_reference(_nsdispatch, nsdispatch); 62746d93063SJacques Vidrine 628*738314e4SAlex Richardson int 62946d93063SJacques Vidrine _nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database, 63046d93063SJacques Vidrine const char *method_name, const ns_src defaults[], ...) 631248aee62SJacques Vidrine { 632248aee62SJacques Vidrine va_list ap; 633248aee62SJacques Vidrine const ns_dbt *dbt; 634248aee62SJacques Vidrine const ns_src *srclist; 635a59d6a87SMichael Bushkov nss_method method, fb_method; 63646d93063SJacques Vidrine void *mdata; 637*738314e4SAlex Richardson int isthreaded, serrno, i, result, srclistsize; 6386d722173SZachary Loafman struct fb_state *st; 63983804ea0SDag-Erling Smørgrav int saved_depth; 640248aee62SJacques Vidrine 64106a99fe3SHajimu UMEMOTO #ifdef NS_CACHING 64206a99fe3SHajimu UMEMOTO nss_cache_data cache_data; 64306a99fe3SHajimu UMEMOTO nss_cache_data *cache_data_p; 64406a99fe3SHajimu UMEMOTO int cache_flag; 64506a99fe3SHajimu UMEMOTO #endif 64606a99fe3SHajimu UMEMOTO 647a59d6a87SMichael Bushkov dbt = NULL; 648a59d6a87SMichael Bushkov fb_method = NULL; 649a59d6a87SMichael Bushkov 650*738314e4SAlex Richardson isthreaded = __isthreaded; 65146d93063SJacques Vidrine serrno = errno; 652*738314e4SAlex Richardson if (isthreaded) { 653*738314e4SAlex Richardson result = _pthread_rwlock_rdlock(&nss_lock); 654*738314e4SAlex Richardson if (result != 0) { 655*738314e4SAlex Richardson result = NS_UNAVAIL; 656*738314e4SAlex Richardson goto fin; 657*738314e4SAlex Richardson } 658*738314e4SAlex Richardson } 6596d722173SZachary Loafman 6606d722173SZachary Loafman result = fb_getstate(&st); 6616d722173SZachary Loafman if (result != 0) { 6626d722173SZachary Loafman result = NS_UNAVAIL; 6636d722173SZachary Loafman goto fin; 6646d722173SZachary Loafman } 6656d722173SZachary Loafman 66646d93063SJacques Vidrine result = nss_configure(); 66746d93063SJacques Vidrine if (result != 0) { 66846d93063SJacques Vidrine result = NS_UNAVAIL; 66946d93063SJacques Vidrine goto fin; 67046d93063SJacques Vidrine } 67183804ea0SDag-Erling Smørgrav ++st->dispatch_depth; 67283804ea0SDag-Erling Smørgrav if (st->dispatch_depth > st->fallback_depth) { 67346d93063SJacques Vidrine dbt = vector_search(&database, _nsmap, _nsmapsize, sizeof(*_nsmap), 67446d93063SJacques Vidrine string_compare); 675a59d6a87SMichael Bushkov fb_method = nss_method_lookup(NSSRC_FALLBACK, database, 676a59d6a87SMichael Bushkov method_name, disp_tab, &mdata); 677a59d6a87SMichael Bushkov } 678a59d6a87SMichael Bushkov 679248aee62SJacques Vidrine if (dbt != NULL) { 680248aee62SJacques Vidrine srclist = dbt->srclist; 681248aee62SJacques Vidrine srclistsize = dbt->srclistsize; 682248aee62SJacques Vidrine } else { 683248aee62SJacques Vidrine srclist = defaults; 684248aee62SJacques Vidrine srclistsize = 0; 685248aee62SJacques Vidrine while (srclist[srclistsize].name != NULL) 686248aee62SJacques Vidrine srclistsize++; 687248aee62SJacques Vidrine } 68806a99fe3SHajimu UMEMOTO 68906a99fe3SHajimu UMEMOTO #ifdef NS_CACHING 69006a99fe3SHajimu UMEMOTO cache_data_p = NULL; 69106a99fe3SHajimu UMEMOTO cache_flag = 0; 69206a99fe3SHajimu UMEMOTO #endif 693248aee62SJacques Vidrine for (i = 0; i < srclistsize; i++) { 69446d93063SJacques Vidrine result = NS_NOTFOUND; 69546d93063SJacques Vidrine method = nss_method_lookup(srclist[i].name, database, 69646d93063SJacques Vidrine method_name, disp_tab, &mdata); 69706a99fe3SHajimu UMEMOTO 69846d93063SJacques Vidrine if (method != NULL) { 69906a99fe3SHajimu UMEMOTO #ifdef NS_CACHING 70006a99fe3SHajimu UMEMOTO if (strcmp(srclist[i].name, NSSRC_CACHE) == 0 && 70106a99fe3SHajimu UMEMOTO nss_cache_cycle_prevention_func == NULL) { 70206a99fe3SHajimu UMEMOTO #ifdef NS_STRICT_LIBC_EID_CHECKING 70306a99fe3SHajimu UMEMOTO if (issetugid() != 0) 70406a99fe3SHajimu UMEMOTO continue; 70506a99fe3SHajimu UMEMOTO #endif 70606a99fe3SHajimu UMEMOTO cache_flag = 1; 70706a99fe3SHajimu UMEMOTO 70806a99fe3SHajimu UMEMOTO memset(&cache_data, 0, sizeof(nss_cache_data)); 70906a99fe3SHajimu UMEMOTO cache_data.info = (nss_cache_info const *)mdata; 71006a99fe3SHajimu UMEMOTO cache_data_p = &cache_data; 71106a99fe3SHajimu UMEMOTO 71206a99fe3SHajimu UMEMOTO va_start(ap, defaults); 71306a99fe3SHajimu UMEMOTO if (cache_data.info->id_func != NULL) 71406a99fe3SHajimu UMEMOTO result = __nss_common_cache_read(retval, 71506a99fe3SHajimu UMEMOTO cache_data_p, ap); 71606a99fe3SHajimu UMEMOTO else if (cache_data.info->marshal_func != NULL) 71706a99fe3SHajimu UMEMOTO result = __nss_mp_cache_read(retval, 71806a99fe3SHajimu UMEMOTO cache_data_p, ap); 71906a99fe3SHajimu UMEMOTO else 72006a99fe3SHajimu UMEMOTO result = __nss_mp_cache_end(retval, 72106a99fe3SHajimu UMEMOTO cache_data_p, ap); 72206a99fe3SHajimu UMEMOTO va_end(ap); 72306a99fe3SHajimu UMEMOTO } else { 72406a99fe3SHajimu UMEMOTO cache_flag = 0; 725f700faa5SHajimu UMEMOTO errno = 0; 726248aee62SJacques Vidrine va_start(ap, defaults); 72746d93063SJacques Vidrine result = method(retval, mdata, ap); 728248aee62SJacques Vidrine va_end(ap); 72906a99fe3SHajimu UMEMOTO } 73006a99fe3SHajimu UMEMOTO #else /* NS_CACHING */ 731f700faa5SHajimu UMEMOTO errno = 0; 73206a99fe3SHajimu UMEMOTO va_start(ap, defaults); 73306a99fe3SHajimu UMEMOTO result = method(retval, mdata, ap); 73406a99fe3SHajimu UMEMOTO va_end(ap); 73506a99fe3SHajimu UMEMOTO #endif /* NS_CACHING */ 73606a99fe3SHajimu UMEMOTO 73746d93063SJacques Vidrine if (result & (srclist[i].flags)) 738248aee62SJacques Vidrine break; 73936736e35SMichael Bushkov } else { 74036736e35SMichael Bushkov if (fb_method != NULL) { 74183804ea0SDag-Erling Smørgrav saved_depth = st->fallback_depth; 74283804ea0SDag-Erling Smørgrav st->fallback_depth = st->dispatch_depth + 1; 743a59d6a87SMichael Bushkov va_start(ap, defaults); 74436736e35SMichael Bushkov result = fb_method(retval, 74536736e35SMichael Bushkov (void *)srclist[i].name, ap); 746a59d6a87SMichael Bushkov va_end(ap); 74783804ea0SDag-Erling Smørgrav st->fallback_depth = saved_depth; 74836736e35SMichael Bushkov } else 74936736e35SMichael Bushkov nss_log(LOG_DEBUG, "%s, %s, %s, not found, " 75036736e35SMichael Bushkov "and no fallback provided", 75136736e35SMichael Bushkov srclist[i].name, database, method_name); 752248aee62SJacques Vidrine } 753248aee62SJacques Vidrine } 75406a99fe3SHajimu UMEMOTO 75506a99fe3SHajimu UMEMOTO #ifdef NS_CACHING 75606a99fe3SHajimu UMEMOTO if (cache_data_p != NULL && 75706a99fe3SHajimu UMEMOTO (result & (NS_NOTFOUND | NS_SUCCESS)) && cache_flag == 0) { 75806a99fe3SHajimu UMEMOTO va_start(ap, defaults); 75906a99fe3SHajimu UMEMOTO if (result == NS_SUCCESS) { 76006a99fe3SHajimu UMEMOTO if (cache_data.info->id_func != NULL) 76106a99fe3SHajimu UMEMOTO __nss_common_cache_write(retval, cache_data_p, 76206a99fe3SHajimu UMEMOTO ap); 76306a99fe3SHajimu UMEMOTO else if (cache_data.info->marshal_func != NULL) 76406a99fe3SHajimu UMEMOTO __nss_mp_cache_write(retval, cache_data_p, ap); 76506a99fe3SHajimu UMEMOTO } else if (result == NS_NOTFOUND) { 76606a99fe3SHajimu UMEMOTO if (cache_data.info->id_func == NULL) { 76706a99fe3SHajimu UMEMOTO if (cache_data.info->marshal_func != NULL) 76806a99fe3SHajimu UMEMOTO __nss_mp_cache_write_submit(retval, 76906a99fe3SHajimu UMEMOTO cache_data_p, ap); 77006a99fe3SHajimu UMEMOTO } else 77106a99fe3SHajimu UMEMOTO __nss_common_cache_write_negative(cache_data_p); 77206a99fe3SHajimu UMEMOTO } 77306a99fe3SHajimu UMEMOTO va_end(ap); 77406a99fe3SHajimu UMEMOTO } 77506a99fe3SHajimu UMEMOTO #endif /* NS_CACHING */ 77606a99fe3SHajimu UMEMOTO 777*738314e4SAlex Richardson if (isthreaded) 778*738314e4SAlex Richardson (void)_pthread_rwlock_unlock(&nss_lock); 77983804ea0SDag-Erling Smørgrav --st->dispatch_depth; 78046d93063SJacques Vidrine fin: 78146d93063SJacques Vidrine errno = serrno; 78246d93063SJacques Vidrine return (result); 783248aee62SJacques Vidrine } 784