diff options
author | Dag-Erling Smørgrav <des@FreeBSD.org> | 2014-11-25 09:47:15 +0000 |
---|---|---|
committer | Dag-Erling Smørgrav <des@FreeBSD.org> | 2014-11-25 09:47:15 +0000 |
commit | 83804ea07400d96725647571ae0b64a6a728f5bd (patch) | |
tree | 7af0b1c9ed178688ccdea34280f37bf58134427e | |
parent | 4ab8910605b5d9f4f934fae1181527a169f7f8f4 (diff) | |
download | src-test2-83804ea07400d96725647571ae0b64a6a728f5bd.tar.gz src-test2-83804ea07400d96725647571ae0b64a6a728f5bd.zip |
Notes
-rw-r--r-- | lib/libc/net/nsdispatch.c | 25 |
1 files changed, 16 insertions, 9 deletions
diff --git a/lib/libc/net/nsdispatch.c b/lib/libc/net/nsdispatch.c index c23315cbd108..4de1df3ffd16 100644 --- a/lib/libc/net/nsdispatch.c +++ b/lib/libc/net/nsdispatch.c @@ -132,14 +132,17 @@ static void *nss_cache_cycle_prevention_func = NULL; #endif /* - * When this is set to 1, nsdispatch won't use nsswitch.conf - * but will consult the 'defaults' source list only. - * NOTE: nested fallbacks (when nsdispatch calls fallback functions, - * which in turn calls nsdispatch, which should call fallback - * function) are not supported + * We keep track of nsdispatch() nesting depth in dispatch_depth. When a + * fallback method is invoked from nsdispatch(), we temporarily set + * fallback_depth to the current dispatch depth plus one. Subsequent + * calls at that exact depth will run in fallback mode (restricted to the + * same source as the call that was handled by the fallback method), while + * calls below that depth will be handled normally, allowing fallback + * methods to perform arbitrary lookups. */ struct fb_state { - int fb_dispatch; + int dispatch_depth; + int fallback_depth; }; static void fb_endstate(void *); NSS_TLS_HANDLING(fb); @@ -613,6 +616,7 @@ _nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database, void *mdata; int isthreaded, serrno, i, result, srclistsize; struct fb_state *st; + int saved_depth; #ifdef NS_CACHING nss_cache_data cache_data; @@ -644,7 +648,8 @@ _nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database, result = NS_UNAVAIL; goto fin; } - if (st->fb_dispatch == 0) { + ++st->dispatch_depth; + if (st->dispatch_depth > st->fallback_depth) { dbt = vector_search(&database, _nsmap, _nsmapsize, sizeof(*_nsmap), string_compare); fb_method = nss_method_lookup(NSSRC_FALLBACK, database, @@ -713,12 +718,13 @@ _nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database, break; } else { if (fb_method != NULL) { - st->fb_dispatch = 1; + saved_depth = st->fallback_depth; + st->fallback_depth = st->dispatch_depth + 1; va_start(ap, defaults); result = fb_method(retval, (void *)srclist[i].name, ap); va_end(ap); - st->fb_dispatch = 0; + st->fallback_depth = saved_depth; } else nss_log(LOG_DEBUG, "%s, %s, %s, not found, " "and no fallback provided", @@ -750,6 +756,7 @@ _nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database, if (isthreaded) (void)_pthread_rwlock_unlock(&nss_lock); + --st->dispatch_depth; fin: errno = serrno; return (result); |