source: rtems-libbsd/freebsd-userspace/lib/libc/net/nsdispatch.c @ c52d922

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since c52d922 was c52d922, checked in by Joel Sherrill <joel.sherrill@…>, on 09/12/12 at 22:09:48

nsdispatch.c: New file added along with required dependencies

This file uses dynamic loading and is using some magic for
statically linked modules included in it. These modules may
or may not show up magically in an RTEMS executable. This will
eventually have to be investigated and resolved.

  • Property mode set to 100644
File size: 19.9 KB
Line 
1#include "port_before.h"
2
3/*      $NetBSD: nsdispatch.c,v 1.9 1999/01/25 00:16:17 lukem Exp $     */
4
5/*-
6 * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc.
7 * All rights reserved.
8 *
9 * This code is derived from software contributed to The NetBSD Foundation
10 * by Luke Mewburn.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 *    notice, this list of conditions and the following disclaimer in the
19 *    documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 *    must display the following acknowledgement:
22 *        This product includes software developed by the NetBSD
23 *        Foundation, Inc. and its contributors.
24 * 4. Neither the name of The NetBSD Foundation nor the names of its
25 *    contributors may be used to endorse or promote products derived
26 *    from this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 */
40/*-
41 * Copyright (c) 2003 Networks Associates Technology, Inc.
42 * All rights reserved.
43 *
44 * Portions of this software were developed for the FreeBSD Project by
45 * Jacques A. Vidrine, Safeport Network Services, and Network
46 * Associates Laboratories, the Security Research Division of Network
47 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
48 * ("CBOSS"), as part of the DARPA CHATS research program.
49 *
50 * Redistribution and use in source and binary forms, with or without
51 * modification, are permitted provided that the following conditions
52 * are met:
53 * 1. Redistributions of source code must retain the above copyright
54 *    notice, this list of conditions and the following disclaimer.
55 * 2. Redistributions in binary form must reproduce the above copyright
56 *    notice, this list of conditions and the following disclaimer in the
57 *    documentation and/or other materials provided with the distribution.
58 *
59 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 * SUCH DAMAGE.
70 *
71 */
72#include <sys/cdefs.h>
73__FBSDID("$FreeBSD$");
74
75#include "namespace.h"
76#include <sys/param.h>
77#include <sys/stat.h>
78
79#ifndef __rtems__
80#include <dlfcn.h>
81#else
82#include <stdint.h>
83#endif
84#include <errno.h>
85#include <fcntl.h>
86#define _NS_PRIVATE
87#include <nsswitch.h>
88#include <pthread.h>
89#include <pthread_np.h>
90#include <stdio.h>
91#include <stdlib.h>
92#include <string.h>
93#include <syslog.h>
94#include <unistd.h>
95#include "un-namespace.h"
96#include "nss_tls.h"
97#include "libc_private.h"
98#ifdef NS_CACHING
99#include "nscache.h"
100#endif
101
102enum _nss_constants {
103        /* Number of elements allocated when we grow a vector */
104        ELEMSPERCHUNK = 8
105};
106
107/*
108 * Global NSS data structures are mostly read-only, but we update
109 * them when we read or re-read the nsswitch.conf.
110 */
111static  pthread_rwlock_t        nss_lock = PTHREAD_RWLOCK_INITIALIZER;
112
113/*
114 * Runtime determination of whether we are dynamically linked or not.
115 */
116extern  int             _DYNAMIC __attribute__ ((weak));
117#define is_dynamic()    (&_DYNAMIC != NULL)
118
119/*
120 * default sourcelist: `files'
121 */
122const ns_src __nsdefaultsrc[] = {
123        { NSSRC_FILES, NS_SUCCESS },
124        { 0 },
125};
126
127/* Database, source mappings. */
128static  unsigned int             _nsmapsize;
129static  ns_dbt                  *_nsmap = NULL;
130
131/* NSS modules. */
132static  unsigned int             _nsmodsize;
133static  ns_mod                  *_nsmod;
134
135/* Placeholder for builtin modules' dlopen `handle'. */
136static  int                      __nss_builtin_handle;
137static  void                    *nss_builtin_handle = &__nss_builtin_handle;
138
139#ifdef NS_CACHING
140/*
141 * Cache lookup cycle prevention function - if !NULL then no cache lookups
142 * will be made
143 */
144static  void                    *nss_cache_cycle_prevention_func = NULL;
145#endif
146
147/*
148 * When this is set to 1, nsdispatch won't use nsswitch.conf
149 * but will consult the 'defaults' source list only.
150 * NOTE: nested fallbacks (when nsdispatch calls fallback functions,
151 *     which in turn calls nsdispatch, which should call fallback
152 *     function) are not supported
153 */
154struct fb_state {
155        int     fb_dispatch;
156};
157static  void    fb_endstate(void *);
158NSS_TLS_HANDLING(fb);
159
160/*
161 * Attempt to spew relatively uniform messages to syslog.
162 */
163#define nss_log(level, fmt, ...) \
164        syslog((level), "NSSWITCH(%s): " fmt, __func__, __VA_ARGS__)
165#define nss_log_simple(level, s) \
166        syslog((level), "NSSWITCH(%s): " s, __func__)
167
168/*
169 * Dynamically growable arrays are used for lists of databases, sources,
170 * and modules.  The following `vector' interface is used to isolate the
171 * common operations.
172 */
173typedef int     (*vector_comparison)(const void *, const void *);
174typedef void    (*vector_free_elem)(void *);
175static  void      vector_sort(void *, unsigned int, size_t,
176                    vector_comparison);
177static  void      vector_free(void *, unsigned int *, size_t,
178                    vector_free_elem);
179static  void     *vector_ref(unsigned int, void *, unsigned int, size_t);
180static  void     *vector_search(const void *, void *, unsigned int, size_t,
181                    vector_comparison);
182static  void     *vector_append(const void *, void *, unsigned int *, size_t);
183
184
185/*
186 * Internal interfaces.
187 */
188static  int      string_compare(const void *, const void *);
189static  int      mtab_compare(const void *, const void *);
190static  int      nss_configure(void);
191static  void     ns_dbt_free(ns_dbt *);
192static  void     ns_mod_free(ns_mod *);
193static  void     ns_src_free(ns_src **, int);
194static  void     nss_load_builtin_modules(void);
195static  void     nss_load_module(const char *, nss_module_register_fn);
196static  void     nss_atexit(void);
197/* nsparser */
198extern  FILE    *_nsyyin;
199
200
201/*
202 * The vector operations
203 */
204static void
205vector_sort(void *vec, unsigned int count, size_t esize,
206    vector_comparison comparison)
207{
208        qsort(vec, count, esize, comparison);
209}
210
211
212static void *
213vector_search(const void *key, void *vec, unsigned int count, size_t esize,
214    vector_comparison comparison)
215{
216        return (bsearch(key, vec, count, esize, comparison));
217}
218
219
220static void *
221vector_append(const void *elem, void *vec, unsigned int *count, size_t esize)
222{
223        void    *p;
224
225        if ((*count % ELEMSPERCHUNK) == 0) {
226                p = realloc(vec, (*count + ELEMSPERCHUNK) * esize);
227                if (p == NULL) {
228                        nss_log_simple(LOG_ERR, "memory allocation failure");
229                        return (vec);
230                }
231                vec = p;
232        }
233        memmove((void *)(((uintptr_t)vec) + (*count * esize)), elem, esize);
234        (*count)++;
235        return (vec);
236}
237
238
239static void *
240vector_ref(unsigned int i, void *vec, unsigned int count, size_t esize)
241{
242        if (i < count)
243                return (void *)((uintptr_t)vec + (i * esize));
244        else
245                return (NULL);
246}
247
248
249#define VECTOR_FREE(v, c, s, f) \
250        do { vector_free(v, c, s, f); v = NULL; } while (0)
251static void
252vector_free(void *vec, unsigned int *count, size_t esize,
253    vector_free_elem free_elem)
254{
255        unsigned int     i;
256        void            *elem;
257
258        for (i = 0; i < *count; i++) {
259                elem = vector_ref(i, vec, *count, esize);
260                if (elem != NULL)
261                        free_elem(elem);
262        }
263        free(vec);
264        *count = 0;
265}
266
267/*
268 * Comparison functions for vector_search.
269 */
270static int
271string_compare(const void *a, const void *b)
272{
273      return (strcasecmp(*(const char * const *)a, *(const char * const *)b));
274}
275
276
277static int
278mtab_compare(const void *a, const void *b)
279{
280      int     cmp;
281
282      cmp = strcmp(((const ns_mtab *)a)->name, ((const ns_mtab *)b)->name);
283      if (cmp != 0)
284              return (cmp);
285      else
286              return (strcmp(((const ns_mtab *)a)->database,
287                  ((const ns_mtab *)b)->database));
288}
289
290/*
291 * NSS nsmap management.
292 */
293void
294_nsdbtaddsrc(ns_dbt *dbt, const ns_src *src)
295{
296        const ns_mod    *modp;
297
298        dbt->srclist = vector_append(src, dbt->srclist, &dbt->srclistsize,
299            sizeof(*src));
300        modp = vector_search(&src->name, _nsmod, _nsmodsize, sizeof(*_nsmod),
301            string_compare);
302        if (modp == NULL)
303                nss_load_module(src->name, NULL);
304}
305
306
307#ifdef _NSS_DEBUG
308void
309_nsdbtdump(const ns_dbt *dbt)
310{
311        int i;
312
313        printf("%s (%d source%s):", dbt->name, dbt->srclistsize,
314            dbt->srclistsize == 1 ? "" : "s");
315        for (i = 0; i < (int)dbt->srclistsize; i++) {
316                printf(" %s", dbt->srclist[i].name);
317                if (!(dbt->srclist[i].flags &
318                    (NS_UNAVAIL|NS_NOTFOUND|NS_TRYAGAIN)) &&
319                    (dbt->srclist[i].flags & NS_SUCCESS))
320                        continue;
321                printf(" [");
322                if (!(dbt->srclist[i].flags & NS_SUCCESS))
323                        printf(" SUCCESS=continue");
324                if (dbt->srclist[i].flags & NS_UNAVAIL)
325                        printf(" UNAVAIL=return");
326                if (dbt->srclist[i].flags & NS_NOTFOUND)
327                        printf(" NOTFOUND=return");
328                if (dbt->srclist[i].flags & NS_TRYAGAIN)
329                        printf(" TRYAGAIN=return");
330                printf(" ]");
331        }
332        printf("\n");
333}
334#endif
335
336
337/*
338 * The first time nsdispatch is called (during a process's lifetime,
339 * or after nsswitch.conf has been updated), nss_configure will
340 * prepare global data needed by NSS.
341 */
342static int
343nss_configure(void)
344{
345        static pthread_mutex_t conf_lock = PTHREAD_MUTEX_INITIALIZER;
346        static time_t    confmod;
347        struct stat      statbuf;
348        int              result, isthreaded;
349        const char      *path;
350#ifdef NS_CACHING
351        void            *handle;
352#endif
353
354        result = 0;
355        isthreaded = __isthreaded;
356#if defined(_NSS_DEBUG) && defined(_NSS_SHOOT_FOOT)
357        /* NOTE WELL:  THIS IS A SECURITY HOLE. This must only be built
358         * for debugging purposes and MUST NEVER be used in production.
359         */
360        path = getenv("NSSWITCH_CONF");
361        if (path == NULL)
362#endif
363        path = _PATH_NS_CONF;
364        if (stat(path, &statbuf) != 0)
365                return (0);
366        if (statbuf.st_mtime <= confmod)
367                return (0);
368        if (isthreaded) {
369            result = _pthread_mutex_trylock(&conf_lock);
370            if (result != 0)
371                    return (0);
372            (void)_pthread_rwlock_unlock(&nss_lock);
373            result = _pthread_rwlock_wrlock(&nss_lock);
374            if (result != 0)
375                    goto fin2;
376        }
377        _nsyyin = fopen(path, "r");
378        if (_nsyyin == NULL)
379                goto fin;
380        VECTOR_FREE(_nsmap, &_nsmapsize, sizeof(*_nsmap),
381            (vector_free_elem)ns_dbt_free);
382        VECTOR_FREE(_nsmod, &_nsmodsize, sizeof(*_nsmod),
383            (vector_free_elem)ns_mod_free);
384        nss_load_builtin_modules();
385        _nsyyparse();
386        (void)fclose(_nsyyin);
387        vector_sort(_nsmap, _nsmapsize, sizeof(*_nsmap), string_compare);
388        if (confmod == 0)
389                (void)atexit(nss_atexit);
390        confmod = statbuf.st_mtime;
391
392#ifdef NS_CACHING
393        handle = libc_dlopen(NULL, RTLD_LAZY | RTLD_GLOBAL);
394        if (handle != NULL) {
395                nss_cache_cycle_prevention_func = dlsym(handle,
396                        "_nss_cache_cycle_prevention_function");
397                dlclose(handle);
398        }
399#endif
400fin:
401        if (isthreaded) {
402            (void)_pthread_rwlock_unlock(&nss_lock);
403            if (result == 0)
404                    result = _pthread_rwlock_rdlock(&nss_lock);
405        }
406fin2:
407        if (isthreaded)
408                (void)_pthread_mutex_unlock(&conf_lock);
409        return (result);
410}
411
412
413void
414_nsdbtput(const ns_dbt *dbt)
415{
416        unsigned int     i;
417        ns_dbt          *p;
418
419        for (i = 0; i < _nsmapsize; i++) {
420                p = vector_ref(i, _nsmap, _nsmapsize, sizeof(*_nsmap));
421                if (string_compare(&dbt->name, &p->name) == 0) {
422                        /* overwrite existing entry */
423                        if (p->srclist != NULL)
424                                ns_src_free(&p->srclist, p->srclistsize);
425                        memmove(p, dbt, sizeof(*dbt));
426                        return;
427                }
428        }
429        _nsmap = vector_append(dbt, _nsmap, &_nsmapsize, sizeof(*_nsmap));
430}
431
432
433static void
434ns_dbt_free(ns_dbt *dbt)
435{
436        ns_src_free(&dbt->srclist, dbt->srclistsize);
437        if (dbt->name)
438                free((void *)dbt->name);
439}
440
441
442static void
443ns_src_free(ns_src **src, int srclistsize)
444{
445        int     i;
446
447        for (i = 0; i < srclistsize; i++)
448                if ((*src)[i].name != NULL)
449                        /* This one was allocated by nslexer. You'll just
450                         * have to trust me.
451                         */
452                        free((void *)((*src)[i].name));
453        free(*src);
454        *src = NULL;
455}
456
457
458
459/*
460 * NSS module management.
461 */
462/* The built-in NSS modules are all loaded at once. */
463#define NSS_BACKEND(name, reg) \
464ns_mtab *reg(unsigned int *, nss_module_unregister_fn *);
465#include "nss_backends.h"
466#undef NSS_BACKEND
467
468static void
469nss_load_builtin_modules(void)
470{
471#define NSS_BACKEND(name, reg) nss_load_module(#name, reg);
472#include "nss_backends.h"
473#undef NSS_BACKEND
474}
475
476
477/* Load a built-in or dynamically linked module.  If the `reg_fn'
478 * argument is non-NULL, assume a built-in module and use reg_fn to
479 * register it.  Otherwise, search for a dynamic NSS module.
480 */
481static void
482nss_load_module(const char *source, nss_module_register_fn reg_fn)
483{
484        char             buf[PATH_MAX];
485        ns_mod           mod;
486        nss_module_register_fn fn;
487
488        memset(&mod, 0, sizeof(mod));
489        mod.name = strdup(source);
490        if (mod.name == NULL) {
491                nss_log_simple(LOG_ERR, "memory allocation failure");
492                return;
493        }
494        if (reg_fn != NULL) {
495                /* The placeholder is required, as a NULL handle
496                 * represents an invalid module.
497                 */
498                mod.handle = nss_builtin_handle;
499                fn = reg_fn;
500        } else if (!is_dynamic())
501                goto fin;
502#ifndef __rtems__
503        else {
504                if (snprintf(buf, sizeof(buf), "nss_%s.so.%d", mod.name,
505                    NSS_MODULE_INTERFACE_VERSION) >= (int)sizeof(buf))
506                        goto fin;
507                mod.handle = libc_dlopen(buf, RTLD_LOCAL|RTLD_LAZY);
508                if (mod.handle == NULL) {
509#ifdef _NSS_DEBUG
510                        /* This gets pretty annoying since the built-in
511                         * sources aren't modules yet.
512                         */
513                        nss_log(LOG_DEBUG, "%s, %s", mod.name, dlerror());
514#endif
515                        goto fin;
516                }
517                fn = (nss_module_register_fn)dlfunc(mod.handle,
518                    "nss_module_register");
519                if (fn == NULL) {
520                        (void)dlclose(mod.handle);
521                        mod.handle = NULL;
522                        nss_log(LOG_ERR, "%s, %s", mod.name, dlerror());
523                        goto fin;
524                }
525        }
526#endif
527        mod.mtab = fn(mod.name, &mod.mtabsize, &mod.unregister);
528        if (mod.mtab == NULL || mod.mtabsize == 0) {
529#ifndef __rtems__
530                if (mod.handle != nss_builtin_handle)
531                        (void)dlclose(mod.handle);
532#endif
533                mod.handle = NULL;
534                nss_log(LOG_ERR, "%s, registration failed", mod.name);
535                goto fin;
536        }
537        if (mod.mtabsize > 1)
538                qsort(mod.mtab, mod.mtabsize, sizeof(mod.mtab[0]),
539                    mtab_compare);
540fin:
541        _nsmod = vector_append(&mod, _nsmod, &_nsmodsize, sizeof(*_nsmod));
542        vector_sort(_nsmod, _nsmodsize, sizeof(*_nsmod), string_compare);
543}
544
545
546
547static void
548ns_mod_free(ns_mod *mod)
549{
550
551        free(mod->name);
552        if (mod->handle == NULL)
553                return;
554        if (mod->unregister != NULL)
555                mod->unregister(mod->mtab, mod->mtabsize);
556#ifndef __rtems__
557        if (mod->handle != nss_builtin_handle)
558                (void)dlclose(mod->handle);
559#endif
560}
561
562
563
564/*
565 * Cleanup
566 */
567static void
568nss_atexit(void)
569{
570        int isthreaded;
571
572        isthreaded = __isthreaded;
573        if (isthreaded)
574                (void)_pthread_rwlock_wrlock(&nss_lock);
575        VECTOR_FREE(_nsmap, &_nsmapsize, sizeof(*_nsmap),
576            (vector_free_elem)ns_dbt_free);
577        VECTOR_FREE(_nsmod, &_nsmodsize, sizeof(*_nsmod),
578            (vector_free_elem)ns_mod_free);
579        if (isthreaded)
580                (void)_pthread_rwlock_unlock(&nss_lock);
581}
582
583
584
585/*
586 * Finally, the actual implementation.
587 */
588static nss_method
589nss_method_lookup(const char *source, const char *database,
590    const char *method, const ns_dtab disp_tab[], void **mdata)
591{
592        ns_mod  *mod;
593        ns_mtab *match, key;
594        int      i;
595
596        if (disp_tab != NULL)
597                for (i = 0; disp_tab[i].src != NULL; i++)
598                        if (strcasecmp(source, disp_tab[i].src) == 0) {
599                                *mdata = disp_tab[i].mdata;
600                                return (disp_tab[i].method);
601                        }
602        mod = vector_search(&source, _nsmod, _nsmodsize, sizeof(*_nsmod),
603            string_compare);
604        if (mod != NULL && mod->handle != NULL) {
605                key.database = database;
606                key.name = method;
607                match = bsearch(&key, mod->mtab, mod->mtabsize,
608                    sizeof(mod->mtab[0]), mtab_compare);
609                if (match != NULL) {
610                        *mdata = match->mdata;
611                        return (match->method);
612                }
613        }
614
615        *mdata = NULL;
616        return (NULL);
617}
618
619static void
620fb_endstate(void *p)
621{
622        free(p);
623}
624
625__weak_reference(_nsdispatch, nsdispatch);
626
627int
628_nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database,
629            const char *method_name, const ns_src defaults[], ...)
630{
631        va_list          ap;
632        const ns_dbt    *dbt;
633        const ns_src    *srclist;
634        nss_method       method, fb_method;
635        void            *mdata;
636        int              isthreaded, serrno, i, result, srclistsize;
637        struct fb_state *st;
638
639#ifdef NS_CACHING
640        nss_cache_data   cache_data;
641        nss_cache_data  *cache_data_p;
642        int              cache_flag;
643#endif
644       
645        dbt = NULL;
646        fb_method = NULL;
647
648        isthreaded = __isthreaded;
649        serrno = errno;
650        if (isthreaded) {
651                result = _pthread_rwlock_rdlock(&nss_lock);
652                if (result != 0) {
653                        result = NS_UNAVAIL;
654                        goto fin;
655                }
656        }
657
658        result = fb_getstate(&st);
659        if (result != 0) {
660                result = NS_UNAVAIL;
661                goto fin;
662        }
663
664        result = nss_configure();
665        if (result != 0) {
666                result = NS_UNAVAIL;
667                goto fin;
668        }
669        if (st->fb_dispatch == 0) {
670                dbt = vector_search(&database, _nsmap, _nsmapsize, sizeof(*_nsmap),
671                    string_compare);
672                fb_method = nss_method_lookup(NSSRC_FALLBACK, database,
673                    method_name, disp_tab, &mdata);
674        }
675
676        if (dbt != NULL) {
677                srclist = dbt->srclist;
678                srclistsize = dbt->srclistsize;
679        } else {
680                srclist = defaults;
681                srclistsize = 0;
682                while (srclist[srclistsize].name != NULL)
683                        srclistsize++;
684        }
685
686#ifdef NS_CACHING
687        cache_data_p = NULL;
688        cache_flag = 0;
689#endif
690        for (i = 0; i < srclistsize; i++) {
691                result = NS_NOTFOUND;
692                method = nss_method_lookup(srclist[i].name, database,
693                    method_name, disp_tab, &mdata);
694
695                if (method != NULL) {
696#ifdef NS_CACHING
697                        if (strcmp(srclist[i].name, NSSRC_CACHE) == 0 &&
698                            nss_cache_cycle_prevention_func == NULL) {
699#ifdef NS_STRICT_LIBC_EID_CHECKING
700                                if (issetugid() != 0)
701                                        continue;
702#endif
703                                cache_flag = 1;
704
705                                memset(&cache_data, 0, sizeof(nss_cache_data));
706                                cache_data.info = (nss_cache_info const *)mdata;
707                                cache_data_p = &cache_data;
708
709                                va_start(ap, defaults);
710                                if (cache_data.info->id_func != NULL)
711                                        result = __nss_common_cache_read(retval,
712                                            cache_data_p, ap);
713                                else if (cache_data.info->marshal_func != NULL)
714                                        result = __nss_mp_cache_read(retval,
715                                            cache_data_p, ap);
716                                else
717                                        result = __nss_mp_cache_end(retval,
718                                            cache_data_p, ap);
719                                va_end(ap);
720                        } else {
721                                cache_flag = 0;
722                                errno = 0;
723                                va_start(ap, defaults);
724                                result = method(retval, mdata, ap);
725                                va_end(ap);
726                        }
727#else /* NS_CACHING */
728                        errno = 0;
729                        va_start(ap, defaults);
730                        result = method(retval, mdata, ap);
731                        va_end(ap);
732#endif /* NS_CACHING */
733
734                        if (result & (srclist[i].flags))
735                                break;
736                } else {
737                        if (fb_method != NULL) {
738                                st->fb_dispatch = 1;
739                                va_start(ap, defaults);
740                                result = fb_method(retval,
741                                    (void *)srclist[i].name, ap);
742                                va_end(ap);
743                                st->fb_dispatch = 0;
744                        } else
745                                nss_log(LOG_DEBUG, "%s, %s, %s, not found, "
746                                    "and no fallback provided",
747                                    srclist[i].name, database, method_name);
748                }
749        }
750
751#ifdef NS_CACHING
752        if (cache_data_p != NULL &&
753            (result & (NS_NOTFOUND | NS_SUCCESS)) && cache_flag == 0) {
754                va_start(ap, defaults);
755                if (result == NS_SUCCESS) {
756                        if (cache_data.info->id_func != NULL)
757                                __nss_common_cache_write(retval, cache_data_p,
758                                    ap);
759                        else if (cache_data.info->marshal_func != NULL)
760                                __nss_mp_cache_write(retval, cache_data_p, ap);
761                } else if (result == NS_NOTFOUND) {
762                        if (cache_data.info->id_func == NULL) {
763                                if (cache_data.info->marshal_func != NULL)
764                                        __nss_mp_cache_write_submit(retval,
765                                            cache_data_p, ap);
766                        } else
767                                __nss_common_cache_write_negative(cache_data_p);
768                }
769                va_end(ap);
770        }
771#endif /* NS_CACHING */
772
773        if (isthreaded)
774                (void)_pthread_rwlock_unlock(&nss_lock);
775fin:
776        errno = serrno;
777        return (result);
778}
Note: See TracBrowser for help on using the repository browser.