summaryrefslogtreecommitdiffstats
path: root/freebsd/lib/libc/net/nsdispatch.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/lib/libc/net/nsdispatch.c')
-rw-r--r--freebsd/lib/libc/net/nsdispatch.c47
1 files changed, 22 insertions, 25 deletions
diff --git a/freebsd/lib/libc/net/nsdispatch.c b/freebsd/lib/libc/net/nsdispatch.c
index f1a88d8d..8d0e1493 100644
--- a/freebsd/lib/libc/net/nsdispatch.c
+++ b/freebsd/lib/libc/net/nsdispatch.c
@@ -17,13 +17,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -147,14 +140,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);
@@ -352,7 +348,6 @@ _nsdbtdump(const ns_dbt *dbt)
static int
nss_configure(void)
{
- static pthread_mutex_t conf_lock = PTHREAD_MUTEX_INITIALIZER;
static time_t confmod;
struct stat statbuf;
int result, isthreaded;
@@ -376,15 +371,16 @@ nss_configure(void)
if (statbuf.st_mtime <= confmod)
return (0);
if (isthreaded) {
- result = _pthread_mutex_trylock(&conf_lock);
- if (result != 0)
- return (0);
(void)_pthread_rwlock_unlock(&nss_lock);
result = _pthread_rwlock_wrlock(&nss_lock);
if (result != 0)
- goto fin2;
+ return (result);
+ if (stat(path, &statbuf) != 0)
+ goto fin;
+ if (statbuf.st_mtime <= confmod)
+ goto fin;
}
- _nsyyin = fopen(path, "r");
+ _nsyyin = fopen(path, "re");
if (_nsyyin == NULL)
goto fin;
VECTOR_FREE(_nsmap, &_nsmapsize, sizeof(*_nsmap),
@@ -417,9 +413,6 @@ fin:
if (result == 0)
result = _pthread_rwlock_rdlock(&nss_lock);
}
-fin2:
- if (isthreaded)
- (void)_pthread_mutex_unlock(&conf_lock);
return (result);
}
@@ -681,6 +674,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;
@@ -712,7 +706,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,
@@ -781,12 +776,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",
@@ -818,6 +814,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);