lib: Change nss_wrapper to preloadable version.
authorAndreas Schneider <asn@samba.org>
Fri, 31 Jan 2014 14:57:43 +0000 (15:57 +0100)
committerStefan Metzmacher <metze@samba.org>
Thu, 17 Apr 2014 12:56:06 +0000 (14:56 +0200)
This imports nss_wrapper version 1.0.2.

Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
configure.developer
lib/nss_wrapper/nss_wrapper.c
lib/nss_wrapper/nss_wrapper.h [deleted file]
lib/nss_wrapper/testsuite.c [deleted file]
lib/nss_wrapper/wscript
lib/nss_wrapper/wscript_build [deleted file]
wscript

index 5033670..b8cf6d6 100755 (executable)
@@ -2,5 +2,4 @@
 `dirname $0`/configure -C \
        --enable-developer \
        --enable-socket-wrapper \
-       --enable-nss-wrapper \
        "$@"
index 8767fbf..7c5a413 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) Stefan Metzmacher 2007 <metze@samba.org>
  * Copyright (C) Guenther Deschner 2009 <gd@samba.org>
+ * Copyright (C) Andreas Schneider 2013 <asn@samba.org>
  *
  * All rights reserved.
  *
  * SUCH DAMAGE.
  */
 
-#ifdef _SAMBA_BUILD_
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
 
-/* defining this gives us the posix getpwnam_r() calls on solaris
-   Thanks to heimdal for this */
+/*
+ * Defining _POSIX_PTHREAD_SEMANTICS before including pwd.h and grp.h  gives us
+ * the posix getpwnam_r(), getpwuid_r(), getgrnam_r and getgrgid_r calls on
+ * Solaris
+ */
 #ifndef _POSIX_PTHREAD_SEMANTICS
 #define _POSIX_PTHREAD_SEMANTICS
 #endif
 
-#define NSS_WRAPPER_NOT_REPLACE
-#include "../replace/replace.h"
-#include "system/passwd.h"
-#include "system/filesys.h"
-#include "../nsswitch/nsstest.h"
+#include <pwd.h>
+#include <grp.h>
+
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <dlfcn.h>
 
-#else /* _SAMBA_BUILD_ */
+#if defined(HAVE_NSS_H)
+/* Linux and BSD */
+#include <nss.h>
 
-#error nss_wrapper_only_supported_in_samba_yet
+typedef enum nss_status NSS_STATUS;
+#elif defined(HAVE_NSS_COMMON_H)
+/* Solaris */
+#include <nss_common.h>
+#include <nss_dbdefs.h>
+#include <nsswitch.h>
+
+typedef nss_status_t NSS_STATUS;
+
+# define NSS_STATUS_SUCCESS     NSS_SUCCESS
+# define NSS_STATUS_NOTFOUND    NSS_NOTFOUND
+# define NSS_STATUS_UNAVAIL     NSS_UNAVAIL
+# define NSS_STATUS_TRYAGAIN    NSS_TRYAGAIN
+#else
+# error "No nsswitch support detected"
+#endif
 
+#ifndef PTR_DIFF
+#define PTR_DIFF(p1, p2) ((ptrdiff_t)(((const char *)(p1)) - (const char *)(p2)))
 #endif
 
 #ifndef _PUBLIC_
 #define _PUBLIC_
 #endif
 
-/* not all systems have _r functions... */
-#ifndef HAVE_GETPWNAM_R
-#define getpwnam_r(name, pwdst, buf, buflen, pwdstp)   ENOSYS
+#ifndef EAI_NODATA
+#define EAI_NODATA EAI_NONAME
 #endif
-#ifndef HAVE_GETPWUID_R
-#define getpwuid_r(uid, pwdst, buf, buflen, pwdstp)    ENOSYS
-#endif
-#ifndef HAVE_GETPWENT_R
-#define getpwent_r(pwdst, buf, buflen, pwdstp)         ENOSYS
+
+#ifndef EAI_ADDRFAMILY
+#define EAI_ADDRFAMILY EAI_FAMILY
 #endif
-#ifndef HAVE_GETGRNAM_R
-#define getgrnam_r(name, grdst, buf, buflen, grdstp)   ENOSYS
+
+#ifndef __STRING
+#define __STRING(x)    #x
 #endif
-#ifndef HAVE_GETGRGID_R
-#define getgrgid_r(gid, grdst, buf, buflen, grdstp)    ENOSYS
+
+#ifndef __STRINGSTRING
+#define __STRINGSTRING(x) __STRING(x)
 #endif
-#ifndef HAVE_GETGRENT_R
-#define getgrent_r(grdst, buf, buflen, grdstp)         ENOSYS
+
+#ifndef __LINESTR__
+#define __LINESTR__ __STRINGSTRING(__LINE__)
 #endif
 
-/* not all systems have getgrouplist */
-#ifndef HAVE_GETGROUPLIST
-#define getgrouplist(user, group, groups, ngroups)     0
+#ifndef __location__
+#define __location__ __FILE__ ":" __LINESTR__
 #endif
 
-/* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
- * for now */
-#define REWRITE_CALLS
+/* GCC have printf type attribute check. */
+#ifdef HAVE_ATTRIBUTE_PRINTF_FORMAT
+#define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
+#else
+#define PRINTF_ATTRIBUTE(a,b)
+#endif /* HAVE_ATTRIBUTE_PRINTF_FORMAT */
 
-#ifdef REWRITE_CALLS
+#ifdef HAVE_DESTRUCTOR_ATTRIBUTE
+#define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
+#else
+#define DESTRUCTOR_ATTRIBUTE
+#endif /* HAVE_DESTRUCTOR_ATTRIBUTE */
 
-#define real_getpwnam          getpwnam
-#define real_getpwnam_r                getpwnam_r
-#define real_getpwuid          getpwuid
-#define real_getpwuid_r                getpwuid_r
+#define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } while(0)
 
-#define real_setpwent          setpwent
-#define real_getpwent          getpwent
-#define real_getpwent_r                getpwent_r
-#define real_endpwent          endpwent
+enum nwrap_dbglvl_e {
+       NWRAP_LOG_ERROR = 0,
+       NWRAP_LOG_WARN,
+       NWRAP_LOG_DEBUG,
+       NWRAP_LOG_TRACE
+};
 
-/*
-#define real_getgrlst          getgrlst
-#define real_getgrlst_r                getgrlst_r
-#define real_initgroups_dyn    initgroups_dyn
-*/
-#define real_initgroups                initgroups
-#define real_getgrouplist      getgrouplist
-
-#define real_getgrnam          getgrnam
-#define real_getgrnam_r                getgrnam_r
-#define real_getgrgid          getgrgid
-#define real_getgrgid_r                getgrgid_r
-
-#define real_setgrent          setgrent
-#define real_getgrent          getgrent
-#define real_getgrent_r                getgrent_r
-#define real_endgrent          endgrent
+#ifdef NDEBUG
+# define NWRAP_LOG(...)
+#else
 
-#endif
+static void nwrap_log(enum nwrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
+# define NWRAP_LOG(dbglvl, ...) nwrap_log((dbglvl), __func__, __VA_ARGS__)
 
-#if 0
-# ifdef DEBUG
-# define NWRAP_ERROR(args)     DEBUG(0, args)
-# else
-# define NWRAP_ERROR(args)     printf args
-# endif
+static void nwrap_log(enum nwrap_dbglvl_e dbglvl,
+                     const char *func,
+                     const char *format, ...)
+{
+       char buffer[1024];
+       va_list va;
+       const char *d;
+       unsigned int lvl = 0;
+       int pid = getpid();
+
+       d = getenv("NSS_WRAPPER_DEBUGLEVEL");
+       if (d != NULL) {
+               lvl = atoi(d);
+       }
+
+       va_start(va, format);
+       vsnprintf(buffer, sizeof(buffer), format, va);
+       va_end(va);
+
+       if (lvl >= dbglvl) {
+               switch (dbglvl) {
+                       case NWRAP_LOG_ERROR:
+                               fprintf(stderr,
+                                       "NWRAP_ERROR(%d) - %s: %s\n",
+                                       pid, func, buffer);
+                               break;
+                       case NWRAP_LOG_WARN:
+                               fprintf(stderr,
+                                       "NWRAP_WARN(%d) - %s: %s\n",
+                                       pid, func, buffer);
+                               break;
+                       case NWRAP_LOG_DEBUG:
+                               fprintf(stderr,
+                                       "NWRAP_DEBUG(%d) - %s: %s\n",
+                                       pid, func, buffer);
+                               break;
+                       case NWRAP_LOG_TRACE:
+                               fprintf(stderr,
+                                       "NWRAP_TRACE(%d) - %s: %s\n",
+                                       pid, func, buffer);
+                               break;
+               }
+       }
+}
+#endif /* NDEBUG NWRAP_LOG */
+
+struct nwrap_libc_fns {
+       struct passwd *(*_libc_getpwnam)(const char *name);
+       int (*_libc_getpwnam_r)(const char *name, struct passwd *pwd,
+                      char *buf, size_t buflen, struct passwd **result);
+       struct passwd *(*_libc_getpwuid)(uid_t uid);
+       int (*_libc_getpwuid_r)(uid_t uid, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result);
+       void (*_libc_setpwent)(void);
+       struct passwd *(*_libc_getpwent)(void);
+#ifdef HAVE_SOLARIS_GETPWENT_R
+       struct passwd *(*_libc_getpwent_r)(struct passwd *pwbuf, char *buf, size_t buflen);
 #else
-#define NWRAP_ERROR(args)
+       int (*_libc_getpwent_r)(struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp);
 #endif
-
-#if 0
-# ifdef DEBUG
-# define NWRAP_DEBUG(args)     DEBUG(0, args)
-# else
-# define NWRAP_DEBUG(args)     printf args
-# endif
+       void (*_libc_endpwent)(void);
+       int (*_libc_initgroups)(const char *user, gid_t gid);
+       struct group *(*_libc_getgrnam)(const char *name);
+       int (*_libc_getgrnam_r)(const char *name, struct group *grp, char *buf, size_t buflen, struct group **result);
+       struct group *(*_libc_getgrgid)(gid_t gid);
+       int (*_libc_getgrgid_r)(gid_t gid, struct group *grp, char *buf, size_t buflen, struct group **result);
+       void (*_libc_setgrent)(void);
+       struct group *(*_libc_getgrent)(void);
+#ifdef HAVE_SOLARIS_GETGRENT_R
+       struct group *(*_libc_getgrent_r)(struct group *group, char *buf, size_t buflen);
 #else
-#define NWRAP_DEBUG(args)
+       int (*_libc_getgrent_r)(struct group *group, char *buf, size_t buflen, struct group **result);
 #endif
+       void (*_libc_endgrent)(void);
+       int (*_libc_getgrouplist)(const char *user, gid_t group, gid_t *groups, int *ngroups);
 
-#if 0
-# ifdef DEBUG
-# define NWRAP_VERBOSE(args)   DEBUG(0, args)
-# else
-# define NWRAP_VERBOSE(args)   printf args
-# endif
-#else
-#define NWRAP_VERBOSE(args)
+       void (*_libc_sethostent)(int stayopen);
+       struct hostent *(*_libc_gethostent)(void);
+       void (*_libc_endhostent)(void);
+
+       struct hostent *(*_libc_gethostbyname)(const char *name);
+#ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */
+       struct hostent *(*_libc_gethostbyname2)(const char *name, int af);
+#endif
+       struct hostent *(*_libc_gethostbyaddr)(const void *addr, socklen_t len, int type);
+
+       int (*_libc_getaddrinfo)(const char *node, const char *service,
+                                const struct addrinfo *hints,
+                                struct addrinfo **res);
+       int (*_libc_getnameinfo)(const struct sockaddr *sa, socklen_t salen,
+                                char *host, size_t hostlen,
+                                char *serv, size_t servlen,
+                                int flags);
+       int (*_libc_gethostname)(char *name, size_t len);
+#ifdef HAVE_GETHOSTBYNAME_R
+       int (*_libc_gethostbyname_r)(const char *name,
+                                    struct hostent *ret,
+                                    char *buf, size_t buflen,
+                                    struct hostent **result, int *h_errnop);
+#endif
+#ifdef HAVE_GETHOSTBYADDR_R
+       int (*_libc_gethostbyaddr_r)(const void *addr, socklen_t len, int type,
+                                    struct hostent *ret,
+                                    char *buf, size_t buflen,
+                                    struct hostent **result, int *h_errnop);
 #endif
+};
 
 struct nwrap_module_nss_fns {
        NSS_STATUS (*_nss_getpwnam_r)(const char *name, struct passwd *result, char *buffer,
@@ -213,6 +323,11 @@ struct nwrap_ops {
        void            (*nw_endgrent)(struct nwrap_backend *b);
 };
 
+/* Public prototypes */
+
+bool nss_wrapper_enabled(void);
+bool nss_wrapper_hosts_enabled(void);
+
 /* prototypes for files backend */
 
 
@@ -328,10 +443,18 @@ struct nwrap_ops nwrap_module_ops = {
        .nw_endgrent    = nwrap_module_endgrent,
 };
 
+struct nwrap_libc {
+       void *handle;
+       void *nsl_handle;
+       void *sock_handle;
+       struct nwrap_libc_fns *fns;
+};
+
 struct nwrap_main {
        const char *nwrap_switch;
        int num_backends;
        struct nwrap_backend *backends;
+       struct nwrap_libc *libc;
 };
 
 struct nwrap_main *nwrap_main_global;
@@ -372,8 +495,550 @@ struct nwrap_gr {
 struct nwrap_cache __nwrap_cache_gr;
 struct nwrap_gr nwrap_gr_global;
 
+static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line);
+static void nwrap_he_unload(struct nwrap_cache *nwrap);
+
+struct nwrap_addrdata {
+       unsigned char host_addr[16]; /* IPv4 or IPv6 address */
+       char *h_addr_ptrs[2]; /* host_addr pointer + NULL */
+};
+
+struct nwrap_entdata {
+       struct nwrap_addrdata *addr;
+       struct hostent ht;
+};
+
+struct nwrap_he {
+       struct nwrap_cache *cache;
+
+       struct nwrap_entdata *list;
+       int num;
+       int idx;
+};
+
+struct nwrap_cache __nwrap_cache_he;
+struct nwrap_he nwrap_he_global;
+
+
+/*********************************************************
+ * NWRAP PROTOTYPES
+ *********************************************************/
+
+static void nwrap_init(void);
 static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line);
 static void nwrap_gr_unload(struct nwrap_cache *nwrap);
+void nwrap_destructor(void) DESTRUCTOR_ATTRIBUTE;
+
+/*********************************************************
+ * NWRAP LIBC LOADER FUNCTIONS
+ *********************************************************/
+
+enum nwrap_lib {
+    NWRAP_LIBC,
+    NWRAP_LIBNSL,
+    NWRAP_LIBSOCKET,
+};
+
+#ifndef NDEBUG
+static const char *nwrap_str_lib(enum nwrap_lib lib)
+{
+       switch (lib) {
+       case NWRAP_LIBC:
+               return "libc";
+       case NWRAP_LIBNSL:
+               return "libnsl";
+       case NWRAP_LIBSOCKET:
+               return "libsocket";
+       }
+
+       /* Compiler would warn us about unhandled enum value if we get here */
+       return "unknown";
+}
+#endif
+
+static void *nwrap_load_lib_handle(enum nwrap_lib lib)
+{
+       int flags = RTLD_LAZY;
+       void *handle = NULL;
+       int i;
+
+#ifdef HAVE_APPLE
+       return RTLD_NEXT;
+#endif
+
+#ifdef RTLD_DEEPBIND
+       flags |= RTLD_DEEPBIND;
+#endif
+
+       switch (lib) {
+       case NWRAP_LIBNSL:
+#ifdef HAVE_LIBNSL
+               handle = nwrap_main_global->libc->nsl_handle;
+               if (handle == NULL) {
+                       for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
+                               char soname[256] = {0};
+
+                               snprintf(soname, sizeof(soname), "libnsl.so.%d", i);
+                               handle = dlopen(soname, flags);
+                       }
+
+                       nwrap_main_global->libc->nsl_handle = handle;
+               }
+               break;
+#endif
+               /* FALL TROUGH */
+       case NWRAP_LIBSOCKET:
+#ifdef HAVE_LIBSOCKET
+               handle = nwrap_main_global->libc->sock_handle;
+               if (handle == NULL) {
+                       for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
+                               char soname[256] = {0};
+
+                               snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
+                               handle = dlopen(soname, flags);
+                       }
+
+                       nwrap_main_global->libc->sock_handle = handle;
+               }
+               break;
+#endif
+               /* FALL TROUGH */
+       case NWRAP_LIBC:
+               handle = nwrap_main_global->libc->handle;
+               if (handle == NULL) {
+                       for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
+                               char soname[256] = {0};
+
+                               snprintf(soname, sizeof(soname), "libc.so.%d", i);
+                               handle = dlopen(soname, flags);
+                       }
+
+                       nwrap_main_global->libc->handle = handle;
+               }
+               break;
+       }
+
+       if (handle == NULL) {
+               NWRAP_LOG(NWRAP_LOG_ERROR,
+                         "Failed to dlopen library: %s\n",
+                         dlerror());
+               exit(-1);
+       }
+
+       return handle;
+}
+
+static void *_nwrap_load_lib_function(enum nwrap_lib lib, const char *fn_name)
+{
+       void *handle;
+       void *func;
+
+       nwrap_init();
+
+       handle = nwrap_load_lib_handle(lib);
+
+       func = dlsym(handle, fn_name);
+       if (func == NULL) {
+               NWRAP_LOG(NWRAP_LOG_ERROR,
+                               "Failed to find %s: %s\n",
+                               fn_name, dlerror());
+               exit(-1);
+       }
+
+       NWRAP_LOG(NWRAP_LOG_TRACE,
+                       "Loaded %s from %s",
+                       fn_name, nwrap_str_lib(lib));
+       return func;
+}
+
+#define nwrap_load_lib_function(lib, fn_name) \
+       if (nwrap_main_global->libc->fns->_libc_##fn_name == NULL) { \
+               *(void **) (&nwrap_main_global->libc->fns->_libc_##fn_name) = \
+                       _nwrap_load_lib_function(lib, #fn_name); \
+       }
+
+/*
+ * IMPORTANT
+ *
+ * Functions expeciall from libc need to be loaded individually, you can't load
+ * all at once or gdb will segfault at startup. The same applies to valgrind and
+ * has probably something todo with with the linker.
+ * So we need load each function at the point it is called the first time.
+ */
+static struct passwd *libc_getpwnam(const char *name)
+{
+       nwrap_load_lib_function(NWRAP_LIBC, getpwnam);
+
+       return nwrap_main_global->libc->fns->_libc_getpwnam(name);
+}
+
+#ifdef HAVE_GETPWNAM_R
+static int libc_getpwnam_r(const char *name,
+                          struct passwd *pwd,
+                          char *buf,
+                          size_t buflen,
+                          struct passwd **result)
+{
+#ifdef HAVE___POSIX_GETPWNAM_R
+       if (nwrap_main_global->libc->fns->_libc_getpwnam_r == NULL) {
+               *(void **) (&nwrap_main_global->libc->fns->_libc_getpwnam_r) =
+                       _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getpwnam_r");
+       }
+#else
+       nwrap_load_lib_function(NWRAP_LIBC, getpwnam_r);
+#endif
+
+       return nwrap_main_global->libc->fns->_libc_getpwnam_r(name,
+                                                             pwd,
+                                                             buf,
+                                                             buflen,
+                                                             result);
+}
+#endif
+
+static struct passwd *libc_getpwuid(uid_t uid)
+{
+       nwrap_load_lib_function(NWRAP_LIBC, getpwuid);
+
+       return nwrap_main_global->libc->fns->_libc_getpwuid(uid);
+}
+
+#ifdef HAVE_GETPWUID_R
+static int libc_getpwuid_r(uid_t uid,
+                          struct passwd *pwd,
+                          char *buf,
+                          size_t buflen,
+                          struct passwd **result)
+{
+#ifdef HAVE___POSIX_GETPWUID_R
+       if (nwrap_main_global->libc->fns->_libc_getpwuid_r == NULL) {
+               *(void **) (&nwrap_main_global->libc->fns->_libc_getpwuid_r) =
+                       _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getpwuid_r");
+       }
+#else
+       nwrap_load_lib_function(NWRAP_LIBC, getpwuid_r);
+#endif
+
+       return nwrap_main_global->libc->fns->_libc_getpwuid_r(uid,
+                                                             pwd,
+                                                             buf,
+                                                             buflen,
+                                                             result);
+}
+#endif
+
+static void libc_setpwent(void)
+{
+       nwrap_load_lib_function(NWRAP_LIBC, setpwent);
+
+       nwrap_main_global->libc->fns->_libc_setpwent();
+}
+
+static struct passwd *libc_getpwent(void)
+{
+       nwrap_load_lib_function(NWRAP_LIBC, getpwent);
+
+       return nwrap_main_global->libc->fns->_libc_getpwent();
+}
+
+#ifdef HAVE_SOLARIS_GETPWENT_R
+static struct passwd *libc_getpwent_r(struct passwd *pwdst,
+                                     char *buf,
+                                     int buflen)
+{
+       nwrap_load_lib_function(NWRAP_LIBC, getpwent_r);
+
+       return nwrap_main_global->libc->fns->_libc_getpwent_r(pwdst,
+                                                             buf,
+                                                             buflen);
+}
+#else /* HAVE_SOLARIS_GETPWENT_R */
+static int libc_getpwent_r(struct passwd *pwdst,
+                          char *buf,
+                          size_t buflen,
+                          struct passwd **pwdstp)
+{
+       nwrap_load_lib_function(NWRAP_LIBC, getpwent_r);
+
+       return nwrap_main_global->libc->fns->_libc_getpwent_r(pwdst,
+                                                             buf,
+                                                             buflen,
+                                                             pwdstp);
+}
+#endif /* HAVE_SOLARIS_GETPWENT_R */
+
+static void libc_endpwent(void)
+{
+       nwrap_load_lib_function(NWRAP_LIBC, endpwent);
+
+       nwrap_main_global->libc->fns->_libc_endpwent();
+}
+
+static int libc_initgroups(const char *user, gid_t gid)
+{
+       nwrap_load_lib_function(NWRAP_LIBC, initgroups);
+
+       return nwrap_main_global->libc->fns->_libc_initgroups(user, gid);
+}
+
+static struct group *libc_getgrnam(const char *name)
+{
+       nwrap_load_lib_function(NWRAP_LIBC, getgrnam);
+
+       return nwrap_main_global->libc->fns->_libc_getgrnam(name);
+}
+
+#ifdef HAVE_GETGRNAM_R
+static int libc_getgrnam_r(const char *name,
+                          struct group *grp,
+                          char *buf,
+                          size_t buflen,
+                          struct group **result)
+{
+#ifdef HAVE___POSIX_GETGRNAM_R
+       if (nwrap_main_global->libc->fns->_libc_getgrnam_r == NULL) {
+               *(void **) (&nwrap_main_global->libc->fns->_libc_getgrnam_r) =
+                       _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getgrnam_r");
+       }
+#else
+       nwrap_load_lib_function(NWRAP_LIBC, getgrnam_r);
+#endif
+
+       return nwrap_main_global->libc->fns->_libc_getgrnam_r(name,
+                                                             grp,
+                                                             buf,
+                                                             buflen,
+                                                             result);
+}
+#endif
+
+static struct group *libc_getgrgid(gid_t gid)
+{
+       nwrap_load_lib_function(NWRAP_LIBC, getgrgid);
+
+       return nwrap_main_global->libc->fns->_libc_getgrgid(gid);
+}
+
+#ifdef HAVE_GETGRGID_R
+static int libc_getgrgid_r(gid_t gid,
+                          struct group *grp,
+                          char *buf,
+                          size_t buflen,
+                          struct group **result)
+{
+#ifdef HAVE___POSIX_GETGRGID_R
+       if (nwrap_main_global->libc->fns->_libc_getgrgid_r == NULL) {
+               *(void **) (&nwrap_main_global->libc->fns->_libc_getgrgid_r) =
+                       _nwrap_load_lib_function(NWRAP_LIBC, "__posix_getgrgid_r");
+       }
+#else
+       nwrap_load_lib_function(NWRAP_LIBC, getgrgid_r);
+#endif
+
+       return nwrap_main_global->libc->fns->_libc_getgrgid_r(gid,
+                                                             grp,
+                                                             buf,
+                                                             buflen,
+                                                             result);
+}
+#endif
+
+static void libc_setgrent(void)
+{
+       nwrap_load_lib_function(NWRAP_LIBC, setgrent);
+
+       nwrap_main_global->libc->fns->_libc_setgrent();
+}
+
+static struct group *libc_getgrent(void)
+{
+       nwrap_load_lib_function(NWRAP_LIBC, getgrent);
+
+       return nwrap_main_global->libc->fns->_libc_getgrent();
+}
+
+#ifdef HAVE_GETGRENT_R
+#ifdef HAVE_SOLARIS_GETGRENT_R
+static struct group *libc_getgrent_r(struct group *group,
+                                    char *buf,
+                                    size_t buflen)
+{
+       nwrap_load_lib_function(NWRAP_LIBC, getgrent_r);
+
+       return nwrap_main_global->libc->fns->_libc_getgrent_r(group,
+                                                             buf,
+                                                             buflen);
+}
+#else /* !HAVE_SOLARIS_GETGRENT_R */
+static int libc_getgrent_r(struct group *group,
+                          char *buf,
+                          size_t buflen,
+                          struct group **result)
+{
+       nwrap_load_lib_function(NWRAP_LIBC, getgrent_r);
+
+       return nwrap_main_global->libc->fns->_libc_getgrent_r(group,
+                                                             buf,
+                                                             buflen,
+                                                             result);
+}
+#endif /* HAVE_SOLARIS_GETGRENT_R */
+#endif /* HAVE_GETGRENT_R */
+
+static void libc_endgrent(void)
+{
+       nwrap_load_lib_function(NWRAP_LIBC, endgrent);
+
+       nwrap_main_global->libc->fns->_libc_endgrent();
+}
+
+#ifdef HAVE_GETGROUPLIST
+static int libc_getgrouplist(const char *user,
+                            gid_t group,
+                            gid_t *groups,
+                            int *ngroups)
+{
+       nwrap_load_lib_function(NWRAP_LIBC, getgrouplist);
+
+       return nwrap_main_global->libc->fns->_libc_getgrouplist(user,
+                                                               group,
+                                                               groups,
+                                                               ngroups);
+}
+#endif
+
+static void libc_sethostent(int stayopen)
+{
+       nwrap_load_lib_function(NWRAP_LIBNSL, sethostent);
+
+       nwrap_main_global->libc->fns->_libc_sethostent(stayopen);
+}
+
+static struct hostent *libc_gethostent(void)
+{
+       nwrap_load_lib_function(NWRAP_LIBNSL, gethostent);
+
+       return nwrap_main_global->libc->fns->_libc_gethostent();
+}
+
+static void libc_endhostent(void)
+{
+       nwrap_load_lib_function(NWRAP_LIBNSL, endhostent);
+
+       nwrap_main_global->libc->fns->_libc_endhostent();
+}
+
+static struct hostent *libc_gethostbyname(const char *name)
+{
+       nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyname);
+
+       return nwrap_main_global->libc->fns->_libc_gethostbyname(name);
+}
+
+#ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */
+static struct hostent *libc_gethostbyname2(const char *name, int af)
+{
+       nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyname2);
+
+       return nwrap_main_global->libc->fns->_libc_gethostbyname2(name, af);
+}
+#endif
+
+static struct hostent *libc_gethostbyaddr(const void *addr,
+                                         socklen_t len,
+                                         int type)
+{
+       nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyaddr);
+
+       return nwrap_main_global->libc->fns->_libc_gethostbyaddr(addr,
+                                                                len,
+                                                                type);
+}
+
+static int libc_gethostname(char *name, size_t len)
+{
+       nwrap_load_lib_function(NWRAP_LIBNSL, gethostname);
+
+       return nwrap_main_global->libc->fns->_libc_gethostname(name, len);
+}
+
+#ifdef HAVE_GETHOSTBYNAME_R
+static int libc_gethostbyname_r(const char *name,
+                               struct hostent *ret,
+                               char *buf,
+                               size_t buflen,
+                               struct hostent **result,
+                               int *h_errnop)
+{
+       nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyname_r);
+
+       return nwrap_main_global->libc->fns->_libc_gethostbyname_r(name,
+                                                                  ret,
+                                                                  buf,
+                                                                  buflen,
+                                                                  result,
+                                                                  h_errnop);
+}
+#endif
+
+#ifdef HAVE_GETHOSTBYADDR_R
+static int libc_gethostbyaddr_r(const void *addr,
+                               socklen_t len,
+                               int type,
+                               struct hostent *ret,
+                               char *buf,
+                               size_t buflen,
+                               struct hostent **result,
+                               int *h_errnop)
+{
+       nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyaddr_r);
+
+       return nwrap_main_global->libc->fns->_libc_gethostbyaddr_r(addr,
+                                                                  len,
+                                                                  type,
+                                                                  ret,
+                                                                  buf,
+                                                                  buflen,
+                                                                  result,
+                                                                  h_errnop);
+}
+#endif
+
+static int libc_getaddrinfo(const char *node,
+                           const char *service,
+                           const struct addrinfo *hints,
+                           struct addrinfo **res)
+{
+       nwrap_load_lib_function(NWRAP_LIBSOCKET, getaddrinfo);
+
+       return nwrap_main_global->libc->fns->_libc_getaddrinfo(node,
+                                                              service,
+                                                              hints,
+                                                              res);
+}
+
+static int libc_getnameinfo(const struct sockaddr *sa,
+                           socklen_t salen,
+                           char *host,
+                           size_t hostlen,
+                           char *serv,
+                           size_t servlen,
+                           int flags)
+{
+       nwrap_load_lib_function(NWRAP_LIBSOCKET, getnameinfo);
+
+       return nwrap_main_global->libc->fns->_libc_getnameinfo(sa,
+                                                              salen,
+                                                              host,
+                                                              hostlen,
+                                                              serv,
+                                                              servlen,
+                                                              flags);
+}
+
+/*********************************************************
+ * NWRAP NSS MODULE LOADER FUNCTIONS
+ *********************************************************/
 
 static void *nwrap_load_module_fn(struct nwrap_backend *b,
                                  const char *fn_name)
@@ -382,21 +1047,20 @@ static void *nwrap_load_module_fn(struct nwrap_backend *b,
        char *s;
 
        if (!b->so_handle) {
-               NWRAP_ERROR(("%s: no handle\n",
-                            __location__));
+               NWRAP_LOG(NWRAP_LOG_ERROR, "No handle");
                return NULL;
        }
 
        if (asprintf(&s, "_nss_%s_%s", b->name, fn_name) == -1) {
-               NWRAP_ERROR(("%s: out of memory\n",
-                            __location__));
+               NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
                return NULL;
        }
 
        res = dlsym(b->so_handle, s);
        if (!res) {
-               NWRAP_ERROR(("%s: cannot find function %s in %s\n",
-                            __location__, s, b->so_path));
+               NWRAP_LOG(NWRAP_LOG_ERROR,
+                         "Cannot find function %s in %s",
+                         s, b->so_path);
        }
        free(s);
        s = NULL;
@@ -416,28 +1080,28 @@ static struct nwrap_module_nss_fns *nwrap_load_module_fns(struct nwrap_backend *
                return NULL;
        }
 
-       fns->_nss_getpwnam_r    = (NSS_STATUS (*)(const char *, struct passwd *, char *, size_t, int *))
-                                 nwrap_load_module_fn(b, "getpwnam_r");
-       fns->_nss_getpwuid_r    = (NSS_STATUS (*)(uid_t, struct passwd *, char *, size_t, int *))
-                                 nwrap_load_module_fn(b, "getpwuid_r");
-       fns->_nss_setpwent      = (NSS_STATUS(*)(void))
-                                 nwrap_load_module_fn(b, "setpwent");
-       fns->_nss_getpwent_r    = (NSS_STATUS (*)(struct passwd *, char *, size_t, int *))
-                                 nwrap_load_module_fn(b, "getpwent_r");
-       fns->_nss_endpwent      = (NSS_STATUS(*)(void))
-                                 nwrap_load_module_fn(b, "endpwent");
-       fns->_nss_initgroups    = (NSS_STATUS (*)(const char *, gid_t, long int *, long int *, gid_t **, long int, int *))
-                                 nwrap_load_module_fn(b, "initgroups_dyn");
-       fns->_nss_getgrnam_r    = (NSS_STATUS (*)(const char *, struct group *, char *, size_t, int *))
-                                 nwrap_load_module_fn(b, "getgrnam_r");
-       fns->_nss_getgrgid_r    = (NSS_STATUS (*)(gid_t, struct group *, char *, size_t, int *))
-                                 nwrap_load_module_fn(b, "getgrgid_r");
-       fns->_nss_setgrent      = (NSS_STATUS(*)(void))
-                                 nwrap_load_module_fn(b, "setgrent");
-       fns->_nss_getgrent_r    = (NSS_STATUS (*)(struct group *, char *, size_t, int *))
-                                 nwrap_load_module_fn(b, "getgrent_r");
-       fns->_nss_endgrent      = (NSS_STATUS(*)(void))
-                                 nwrap_load_module_fn(b, "endgrent");
+       *(void **)(&fns->_nss_getpwnam_r) =
+               nwrap_load_module_fn(b, "getpwnam_r");
+       *(void **)(&fns->_nss_getpwuid_r) =
+               nwrap_load_module_fn(b, "getpwuid_r");
+       *(void **)(&fns->_nss_setpwent) =
+               nwrap_load_module_fn(b, "setpwent");
+       *(void **)(&fns->_nss_getpwent_r) =
+               nwrap_load_module_fn(b, "getpwent_r");
+       *(void **)(&fns->_nss_endpwent) =
+               nwrap_load_module_fn(b, "endpwent");
+       *(void **)(&fns->_nss_initgroups) =
+               nwrap_load_module_fn(b, "initgroups_dyn");
+       *(void **)(&fns->_nss_getgrnam_r) =
+               nwrap_load_module_fn(b, "getgrnam_r");
+       *(void **)(&fns->_nss_getgrgid_r)=
+               nwrap_load_module_fn(b, "getgrgid_r");
+       *(void **)(&fns->_nss_setgrent) =
+               nwrap_load_module_fn(b, "setgrent");
+       *(void **)(&fns->_nss_getgrent_r) =
+               nwrap_load_module_fn(b, "getgrent_r");
+       *(void **)(&fns->_nss_endgrent) =
+               nwrap_load_module_fn(b, "endgrent");
 
        return fns;
 }
@@ -452,8 +1116,9 @@ static void *nwrap_load_module(const char *so_path)
 
        h = dlopen(so_path, RTLD_LAZY);
        if (!h) {
-               NWRAP_ERROR(("%s: cannot open shared library %s\n",
-                            __location__, so_path));
+               NWRAP_LOG(NWRAP_LOG_ERROR,
+                         "Cannot open shared library %s",
+                         so_path);
                return NULL;
        }
 
@@ -471,8 +1136,7 @@ static bool nwrap_module_init(const char *name,
        *backends = (struct nwrap_backend *)realloc(*backends,
                sizeof(struct nwrap_backend) * ((*num_backends) + 1));
        if (!*backends) {
-               NWRAP_ERROR(("%s: out of memory\n",
-                            __location__));
+               NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
                return false;
        }
 
@@ -498,9 +1162,27 @@ static bool nwrap_module_init(const char *name,
        return true;
 }
 
+static void nwrap_libc_init(struct nwrap_main *r)
+{
+       r->libc = malloc(sizeof(struct nwrap_libc));
+       if (r->libc == NULL) {
+               printf("Failed to allocate memory for libc");
+               exit(-1);
+       }
+       ZERO_STRUCTP(r->libc);
+
+       r->libc->fns = malloc(sizeof(struct nwrap_libc_fns));
+       if (r->libc->fns == NULL) {
+               printf("Failed to allocate memory for libc functions");
+               exit(-1);
+       }
+       ZERO_STRUCTP(r->libc->fns);
+}
+
 static void nwrap_backend_init(struct nwrap_main *r)
 {
-       const char *winbind_so_path = getenv("NSS_WRAPPER_WINBIND_SO_PATH");
+       const char *module_so_path = getenv("NSS_WRAPPER_MODULE_SO_PATH");
+       const char *module_fn_name = getenv("NSS_WRAPPER_MODULE_FN_PREFIX");
 
        r->num_backends = 0;
        r->backends = NULL;
@@ -508,17 +1190,23 @@ static void nwrap_backend_init(struct nwrap_main *r)
        if (!nwrap_module_init("files", &nwrap_files_ops, NULL,
                               &r->num_backends,
                               &r->backends)) {
-               NWRAP_ERROR(("%s: failed to initialize 'files' backend\n",
-                            __location__));
+               NWRAP_LOG(NWRAP_LOG_ERROR,
+                         "Failed to initialize 'files' backend");
                return;
        }
 
-       if (winbind_so_path && strlen(winbind_so_path)) {
-               if (!nwrap_module_init("winbind", &nwrap_module_ops, winbind_so_path,
+       if (module_so_path != NULL &&
+           module_so_path[0] != '\0' &&
+           module_fn_name != NULL &&
+           module_fn_name[0] != '\0') {
+               if (!nwrap_module_init(module_fn_name,
+                                      &nwrap_module_ops,
+                                      module_so_path,
                                       &r->num_backends,
                                       &r->backends)) {
-                       NWRAP_ERROR(("%s: failed to initialize 'winbind' backend\n",
-                                    __location__));
+                       NWRAP_LOG(NWRAP_LOG_ERROR,
+                                 "Failed to initialize '%s' backend",
+                                 module_fn_name);
                        return;
                }
        }
@@ -533,6 +1221,8 @@ static void nwrap_init(void)
 
        nwrap_main_global = &__nwrap_main_global;
 
+       nwrap_libc_init(nwrap_main_global);
+
        nwrap_backend_init(nwrap_main_global);
 
        nwrap_pw_global.cache = &__nwrap_cache_pw;
@@ -550,69 +1240,97 @@ static void nwrap_init(void)
        nwrap_gr_global.cache->private_data = &nwrap_gr_global;
        nwrap_gr_global.cache->parse_line = nwrap_gr_parse_line;
        nwrap_gr_global.cache->unload = nwrap_gr_unload;
+
+       nwrap_he_global.cache = &__nwrap_cache_he;
+
+       nwrap_he_global.cache->path = getenv("NSS_WRAPPER_HOSTS");
+       nwrap_he_global.cache->fd = -1;
+       nwrap_he_global.cache->private_data = &nwrap_he_global;
+       nwrap_he_global.cache->parse_line = nwrap_he_parse_line;
+       nwrap_he_global.cache->unload = nwrap_he_unload;
 }
 
-static bool nwrap_enabled(void)
+bool nss_wrapper_enabled(void)
 {
        nwrap_init();
 
-       if (!nwrap_pw_global.cache->path) {
-               return false;
-       }
-       if (nwrap_pw_global.cache->path[0] == '\0') {
-               return false;
-       }
-       if (!nwrap_gr_global.cache->path) {
+       if (nwrap_pw_global.cache->path == NULL ||
+           nwrap_pw_global.cache->path[0] == '\0') {
                return false;
        }
-       if (nwrap_gr_global.cache->path[0] == '\0') {
+       if (nwrap_gr_global.cache->path == NULL ||
+           nwrap_gr_global.cache->path[0] == '\0') {
                return false;
        }
 
        return true;
 }
 
-static bool nwrap_parse_file(struct nwrap_cache *nwrap)
+bool nss_wrapper_hosts_enabled(void)
 {
-       int ret;
-       uint8_t *buf = NULL;
-       char *nline;
+       nwrap_init();
 
-       if (nwrap->st.st_size == 0) {
-               NWRAP_DEBUG(("%s: size == 0\n",
-                            __location__));
-               goto done;
+       if (nwrap_he_global.cache->path == NULL ||
+           nwrap_he_global.cache->path[0] == '\0') {
+               return false;
+       }
+
+       return true;
+}
+
+static bool nwrap_hostname_enabled(void)
+{
+       nwrap_init();
+
+       if (getenv("NSS_WRAPPER_HOSTNAME") == NULL) {
+               return false;
+       }
+
+       return true;
+}
+
+static bool nwrap_parse_file(struct nwrap_cache *nwrap)
+{
+       int ret;
+       uint8_t *buf = NULL;
+       char *nline;
+
+       if (nwrap->st.st_size == 0) {
+               NWRAP_LOG(NWRAP_LOG_DEBUG, "size == 0");
+               goto done;
        }
 
        if (nwrap->st.st_size > INT32_MAX) {
-               NWRAP_ERROR(("%s: size[%u] larger than INT32_MAX\n",
-                            __location__, (unsigned)nwrap->st.st_size));
+               NWRAP_LOG(NWRAP_LOG_ERROR,
+                         "Size[%u] larger than INT32_MAX",
+                         (unsigned)nwrap->st.st_size);
                goto failed;
        }
 
        ret = lseek(nwrap->fd, 0, SEEK_SET);
        if (ret != 0) {
-               NWRAP_ERROR(("%s: lseek - %d\n",__location__,ret));
+               NWRAP_LOG(NWRAP_LOG_ERROR, "lseek - rc=%d\n", ret);
                goto failed;
        }
 
        buf = (uint8_t *)malloc(nwrap->st.st_size + 1);
        if (!buf) {
-               NWRAP_ERROR(("%s: malloc failed\n",__location__));
+               NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
                goto failed;
        }
 
        ret = read(nwrap->fd, buf, nwrap->st.st_size);
        if (ret != nwrap->st.st_size) {
-               NWRAP_ERROR(("%s: read(%u) gave %d\n",
-                            __location__, (unsigned)nwrap->st.st_size, ret));
+               NWRAP_LOG(NWRAP_LOG_ERROR,
+                         "read(%u) rc=%d\n",
+                         (unsigned)nwrap->st.st_size, ret);
                goto failed;
        }
 
        buf[nwrap->st.st_size] = '\0';
 
        nline = (char *)buf;
-       while (nline && nline[0]) {
+       while (nline != NULL && nline[0] != '\0') {
                char *line;
                char *e;
                bool ok;
@@ -631,8 +1349,6 @@ static bool nwrap_parse_file(struct nwrap_cache *nwrap)
                        nline = e;
                }
 
-               NWRAP_VERBOSE(("%s:'%s'\n",__location__, line));
-
                if (strlen(line) == 0) {
                        continue;
                }
@@ -672,28 +1388,30 @@ reopen:
        if (nwrap->fd < 0) {
                nwrap->fd = open(nwrap->path, O_RDONLY);
                if (nwrap->fd < 0) {
-                       NWRAP_ERROR(("%s: unable to open '%s' readonly %d:%s\n",
-                                    __location__,
-                                    nwrap->path, nwrap->fd,
-                                    strerror(errno)));
+                       NWRAP_LOG(NWRAP_LOG_ERROR,
+                                 "Unable to open '%s' readonly %d:%s",
+                                 nwrap->path, nwrap->fd,
+                                 strerror(errno));
                        return;
                }
-               NWRAP_VERBOSE(("%s: open '%s'\n", __location__, nwrap->path));
+               NWRAP_LOG(NWRAP_LOG_DEBUG, "Open '%s'", nwrap->path);
        }
 
        ret = fstat(nwrap->fd, &st);
        if (ret != 0) {
-               NWRAP_ERROR(("%s: fstat(%s) - %d:%s\n",
-                            __location__,
-                            nwrap->path,
-                            ret, strerror(errno)));
+               NWRAP_LOG(NWRAP_LOG_ERROR,
+                         "fstat(%s) - %d:%s",
+                         nwrap->path,
+                         ret,
+                         strerror(errno));
                return;
        }
 
        if (retried == false && st.st_nlink == 0) {
                /* maybe someone has replaced the file... */
-               NWRAP_DEBUG(("%s: st_nlink == 0, reopen %s\n",
-                            __location__, nwrap->path));
+               NWRAP_LOG(NWRAP_LOG_TRACE,
+                         "st_nlink == 0, reopen %s",
+                         nwrap->path);
                retried = true;
                memset(&nwrap->st, 0, sizeof(nwrap->st));
                close(nwrap->fd);
@@ -702,13 +1420,16 @@ reopen:
        }
 
        if (st.st_mtime == nwrap->st.st_mtime) {
-               NWRAP_VERBOSE(("%s: st_mtime[%u] hasn't changed, skip reload\n",
-                              __location__, (unsigned)st.st_mtime));
+               NWRAP_LOG(NWRAP_LOG_TRACE,
+                         "st_mtime[%u] hasn't changed, skip reload",
+                         (unsigned)st.st_mtime);
                return;
        }
-       NWRAP_DEBUG(("%s: st_mtime has changed [%u] => [%u], start reload\n",
-                    __location__, (unsigned)st.st_mtime,
-                    (unsigned)nwrap->st.st_mtime));
+
+       NWRAP_LOG(NWRAP_LOG_TRACE,
+                 "st_mtime has changed [%u] => [%u], start reload",
+                 (unsigned)st.st_mtime,
+                 (unsigned)nwrap->st.st_mtime);
 
        nwrap->st = st;
 
@@ -716,12 +1437,11 @@ reopen:
 
        ok = nwrap_parse_file(nwrap);
        if (!ok) {
-               NWRAP_ERROR(("%s: failed to reload %s\n",
-                            __location__, nwrap->path));
+               NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to reload %s", nwrap->path);
                nwrap_files_cache_unload(nwrap);
        }
-       NWRAP_DEBUG(("%s: reloaded %s\n",
-                    __location__, nwrap->path));
+
+       NWRAP_LOG(NWRAP_LOG_TRACE, "Reloaded %s", nwrap->path);
 }
 
 /*
@@ -741,8 +1461,9 @@ static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line)
        list_size = sizeof(*nwrap_pw->list) * (nwrap_pw->num+1);
        pw = (struct passwd *)realloc(nwrap_pw->list, list_size);
        if (!pw) {
-               NWRAP_ERROR(("%s:realloc(%u) failed\n",
-                            __location__, list_size));
+               NWRAP_LOG(NWRAP_LOG_ERROR,
+                         "realloc(%u) failed",
+                         (unsigned)list_size);
                return false;
        }
        nwrap_pw->list = pw;
@@ -754,8 +1475,10 @@ static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line)
        /* name */
        p = strchr(c, ':');
        if (!p) {
-               NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
-                            __location__, line, c));
+               NWRAP_LOG(NWRAP_LOG_ERROR,
+                         "Invalid line[%s]: '%s'",
+                         line,
+                         c);
                return false;
        }
        *p = '\0';
@@ -763,13 +1486,12 @@ static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line)
        pw->pw_name = c;
        c = p;
 
-       NWRAP_VERBOSE(("name[%s]\n", pw->pw_name));
+       NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]\n", pw->pw_name);
 
        /* password */
        p = strchr(c, ':');
        if (!p) {
-               NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
-                            __location__, line, c));
+               NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
                return false;
        }
        *p = '\0';
@@ -777,13 +1499,12 @@ static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line)
        pw->pw_passwd = c;
        c = p;
 
-       NWRAP_VERBOSE(("password[%s]\n", pw->pw_passwd));
+       NWRAP_LOG(NWRAP_LOG_TRACE, "password[%s]\n", pw->pw_passwd);
 
        /* uid */
        p = strchr(c, ':');
        if (!p) {
-               NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
-                            __location__, line, c));
+               NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
                return false;
        }
        *p = '\0';
@@ -791,29 +1512,31 @@ static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line)
        e = NULL;
        pw->pw_uid = (uid_t)strtoul(c, &e, 10);
        if (c == e) {
-               NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
-                            __location__, line, c, strerror(errno)));
+               NWRAP_LOG(NWRAP_LOG_ERROR,
+                         "Invalid line[%s]: '%s' - %s",
+                         line, c, strerror(errno));
                return false;
        }
        if (e == NULL) {
-               NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
-                            __location__, line, c, strerror(errno)));
+               NWRAP_LOG(NWRAP_LOG_ERROR,
+                         "Invalid line[%s]: '%s' - %s",
+                         line, c, strerror(errno));
                return false;
        }
        if (e[0] != '\0') {
-               NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
-                            __location__, line, c, strerror(errno)));
+               NWRAP_LOG(NWRAP_LOG_ERROR,
+                         "Invalid line[%s]: '%s' - %s",
+                         line, c, strerror(errno));
                return false;
        }
        c = p;
 
-       NWRAP_VERBOSE(("uid[%u]\n", pw->pw_uid));
+       NWRAP_LOG(NWRAP_LOG_TRACE, "uid[%u]", pw->pw_uid);
 
        /* gid */
        p = strchr(c, ':');
        if (!p) {
-               NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
-                            __location__, line, c));
+               NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
                return false;
        }
        *p = '\0';
@@ -821,29 +1544,31 @@ static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line)
        e = NULL;
        pw->pw_gid = (gid_t)strtoul(c, &e, 10);
        if (c == e) {
-               NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
-                            __location__, line, c, strerror(errno)));
+               NWRAP_LOG(NWRAP_LOG_ERROR,
+                         "Invalid line[%s]: '%s' - %s",
+                         line, c, strerror(errno));
                return false;
        }
        if (e == NULL) {
-               NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
-                            __location__, line, c, strerror(errno)));
+               NWRAP_LOG(NWRAP_LOG_ERROR,
+                         "Invalid line[%s]: '%s' - %s",
+                         line, c, strerror(errno));
                return false;
        }
        if (e[0] != '\0') {
-               NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
-                            __location__, line, c, strerror(errno)));
+               NWRAP_LOG(NWRAP_LOG_ERROR,
+                         "Invalid line[%s]: '%s' - %s",
+                         line, c, strerror(errno));
                return false;
        }
        c = p;
 
-       NWRAP_VERBOSE(("gid[%u]\n", pw->pw_gid));
+       NWRAP_LOG(NWRAP_LOG_TRACE, "gid[%u]\n", pw->pw_gid);
 
        /* gecos */
        p = strchr(c, ':');
        if (!p) {
-               NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
-                            __location__, line, c));
+               NWRAP_LOG(NWRAP_LOG_ERROR, "invalid line[%s]: '%s'", line, c);
                return false;
        }
        *p = '\0';
@@ -851,12 +1576,12 @@ static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line)
        pw->pw_gecos = c;
        c = p;
 
-       NWRAP_VERBOSE(("gecos[%s]\n", pw->pw_gecos));
+       NWRAP_LOG(NWRAP_LOG_TRACE, "gecos[%s]", pw->pw_gecos);
 
        /* dir */
        p = strchr(c, ':');
        if (!p) {
-               NWRAP_ERROR(("%s:'%s'\n",__location__,c));
+               NWRAP_LOG(NWRAP_LOG_ERROR, "'%s'", c);
                return false;
        }
        *p = '\0';
@@ -864,16 +1589,17 @@ static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line)
        pw->pw_dir = c;
        c = p;
 
-       NWRAP_VERBOSE(("dir[%s]\n", pw->pw_dir));
+       NWRAP_LOG(NWRAP_LOG_TRACE, "dir[%s]", pw->pw_dir);
 
        /* shell */
        pw->pw_shell = c;
-       NWRAP_VERBOSE(("shell[%s]\n", pw->pw_shell));
+       NWRAP_LOG(NWRAP_LOG_TRACE, "shell[%s]", pw->pw_shell);
 
-       NWRAP_DEBUG(("add user[%s:%s:%u:%u:%s:%s:%s]\n",
-                    pw->pw_name, pw->pw_passwd,
-                    pw->pw_uid, pw->pw_gid,
-                    pw->pw_gecos, pw->pw_dir, pw->pw_shell));
+       NWRAP_LOG(NWRAP_LOG_DEBUG,
+                 "Added user[%s:%s:%u:%u:%s:%s:%s]",
+                 pw->pw_name, pw->pw_passwd,
+                 pw->pw_uid, pw->pw_gid,
+                 pw->pw_gecos, pw->pw_dir, pw->pw_shell);
 
        nwrap_pw->num++;
        return true;
@@ -905,7 +1631,7 @@ static int nwrap_pw_copy_r(const struct passwd *src, struct passwd *dst,
 
        ofs = PTR_DIFF(last + 1, first);
 
-       if (ofs > buflen) {
+       if (ofs > (off_t) buflen) {
                return ERANGE;
        }
 
@@ -949,7 +1675,7 @@ static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line)
        list_size = sizeof(*nwrap_gr->list) * (nwrap_gr->num+1);
        gr = (struct group *)realloc(nwrap_gr->list, list_size);
        if (!gr) {
-               NWRAP_ERROR(("%s:realloc failed\n",__location__));
+               NWRAP_LOG(NWRAP_LOG_ERROR, "realloc failed");
                return false;
        }
        nwrap_gr->list = gr;
@@ -961,8 +1687,7 @@ static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line)
        /* name */
        p = strchr(c, ':');
        if (!p) {
-               NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
-                            __location__, line, c));
+               NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
                return false;
        }
        *p = '\0';
@@ -970,13 +1695,12 @@ static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line)
        gr->gr_name = c;
        c = p;
 
-       NWRAP_VERBOSE(("name[%s]\n", gr->gr_name));
+       NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]", gr->gr_name);
 
        /* password */
        p = strchr(c, ':');
        if (!p) {
-               NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
-                            __location__, line, c));
+               NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
                return false;
        }
        *p = '\0';
@@ -984,13 +1708,12 @@ static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line)
        gr->gr_passwd = c;
        c = p;
 
-       NWRAP_VERBOSE(("password[%s]\n", gr->gr_passwd));
+       NWRAP_LOG(NWRAP_LOG_TRACE, "password[%s]", gr->gr_passwd);
 
        /* gid */
        p = strchr(c, ':');
        if (!p) {
-               NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
-                            __location__, line, c));
+               NWRAP_LOG(NWRAP_LOG_ERROR, "Invalid line[%s]: '%s'", line, c);
                return false;
        }
        *p = '\0';
@@ -998,28 +1721,31 @@ static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line)
        e = NULL;
        gr->gr_gid = (gid_t)strtoul(c, &e, 10);
        if (c == e) {
-               NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
-                            __location__, line, c, strerror(errno)));
+               NWRAP_LOG(NWRAP_LOG_ERROR,
+                         "Invalid line[%s]: '%s' - %s",
+                         line, c, strerror(errno));
                return false;
        }
        if (e == NULL) {
-               NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
-                            __location__, line, c, strerror(errno)));
+               NWRAP_LOG(NWRAP_LOG_ERROR,
+                         "Invalid line[%s]: '%s' - %s",
+                         line, c, strerror(errno));
                return false;
        }
        if (e[0] != '\0') {
-               NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
-                            __location__, line, c, strerror(errno)));
+               NWRAP_LOG(NWRAP_LOG_ERROR,
+                         "Invalid line[%s]: '%s' - %s",
+                         line, c, strerror(errno));
                return false;
        }
        c = p;
 
-       NWRAP_VERBOSE(("gid[%u]\n", gr->gr_gid));
+       NWRAP_LOG(NWRAP_LOG_TRACE, "gid[%u]", gr->gr_gid);
 
        /* members */
        gr->gr_mem = (char **)malloc(sizeof(char *));
        if (!gr->gr_mem) {
-               NWRAP_ERROR(("%s:calloc failed\n",__location__));
+               NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
                return false;
        }
        gr->gr_mem[0] = NULL;
@@ -1041,19 +1767,23 @@ static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line)
                m_size = sizeof(char *) * (nummem+2);
                m = (char **)realloc(gr->gr_mem, m_size);
                if (!m) {
-                       NWRAP_ERROR(("%s:realloc(%u) failed\n",
-                                     __location__, m_size));
+                       NWRAP_LOG(NWRAP_LOG_ERROR,
+                                 "realloc(%zd) failed",
+                                 m_size);
                        return false;
                }
                gr->gr_mem = m;
                gr->gr_mem[nummem] = c;
                gr->gr_mem[nummem+1] = NULL;
 
-               NWRAP_VERBOSE(("member[%u]: '%s'\n", nummem, gr->gr_mem[nummem]));
+               NWRAP_LOG(NWRAP_LOG_TRACE,
+                         "member[%u]: '%s'",
+                         nummem, gr->gr_mem[nummem]);
        }
 
-       NWRAP_DEBUG(("add group[%s:%s:%u:] with %u members\n",
-                    gr->gr_name, gr->gr_passwd, gr->gr_gid, nummem));
+       NWRAP_LOG(NWRAP_LOG_DEBUG,
+                 "Added group[%s:%s:%u:] with %u members",
+                 gr->gr_name, gr->gr_passwd, gr->gr_gid, nummem);
 
        nwrap_gr->num++;
        return true;
@@ -1106,7 +1836,7 @@ static int nwrap_gr_copy_r(const struct group *src, struct group *dst,
        ofsb = PTR_DIFF(last + 1, first);
        ofsm = PTR_DIFF(lastm + 1, src->gr_mem);
 
-       if ((ofsb + ofsm) > buflen) {
+       if ((ofsb + ofsm) > (off_t) buflen) {
                return ERANGE;
        }
 
@@ -1132,26 +1862,212 @@ static int nwrap_gr_copy_r(const struct group *src, struct group *dst,
        return 0;
 }
 
+static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line)
+{
+       struct nwrap_he *nwrap_he = (struct nwrap_he *)nwrap->private_data;
+       struct nwrap_entdata *ed;
+       size_t list_size;
+       bool do_aliases = true;
+       int aliases_count = 0;
+       char *p;
+       char *i;
+       char *n;
+
+       list_size = sizeof(struct nwrap_entdata) * (nwrap_he->num + 1);
+
+       ed = (struct nwrap_entdata *)realloc(nwrap_he->list, list_size);
+       if (ed == NULL) {
+               NWRAP_LOG(NWRAP_LOG_ERROR, "realloc[%zd] failed", list_size);
+               return false;
+       }
+       nwrap_he->list = ed;
+
+       /* set it to the last element */
+       ed = &(nwrap_he->list[nwrap_he->num]);
+
+       ed->addr = malloc(sizeof(struct nwrap_addrdata));
+       if (ed->addr == NULL) {
+               NWRAP_LOG(NWRAP_LOG_ERROR, "realloc[%zd] failed", list_size);
+               return false;
+       }
+
+       i = line;
+
+       /*
+        * IP
+        */
+
+       /* Walk to first char */
+       for (p = i; *p != '.' && *p != ':' && !isxdigit((int) *p); p++) {
+               if (*p == '\0') {
+                       NWRAP_LOG(NWRAP_LOG_ERROR,
+                                 "Invalid line[%s]: '%s'",
+                                 line, i);
+                       return false;
+               }
+       }
+
+       for (i = p; !isspace((int)*p); p++) {
+               if (*p == '\0') {
+                       NWRAP_LOG(NWRAP_LOG_ERROR,
+                                 "Invalid line[%s]: '%s'",
+                                 line, i);
+                       return false;
+               }
+       }
+
+       *p = '\0';
+
+       if (inet_pton(AF_INET, i, ed->addr->host_addr)) {
+               ed->ht.h_addrtype = AF_INET;
+               ed->ht.h_length = 4;
+#ifdef HAVE_IPV6
+       } else if (inet_pton(AF_INET6, i, ed->addr->host_addr)) {
+               ed->ht.h_addrtype = AF_INET6;
+               ed->ht.h_length = 16;
+#endif
+       } else {
+               NWRAP_LOG(NWRAP_LOG_ERROR,
+                         "Invalid line[%s]: '%s'",
+                         line, i);
+
+               return false;
+       }
+
+       ed->addr->h_addr_ptrs[0] = (char *)ed->addr->host_addr;
+       ed->addr->h_addr_ptrs[1] = NULL;
+
+       ed->ht.h_addr_list = ed->addr->h_addr_ptrs;
+
+       p++;
+
+       /*
+        * FQDN
+        */
+
+       /* Walk to first char */
+       for (n = p; *p != '_' && !isalnum((int) *p); p++) {
+               if (*p == '\0') {
+                       NWRAP_LOG(NWRAP_LOG_ERROR,
+                                 "Invalid line[%s]: '%s'",
+                                 line, n);
+
+                       return false;
+               }
+       }
+
+       for (n = p; !isspace((int)*p); p++) {
+               if (*p == '\0') {
+                       do_aliases = false;
+                       break;
+               }
+       }
+
+       *p = '\0';
+
+       ed->ht.h_name = n;
+
+       /* glib's getent always dereferences he->h_aliases */
+       ed->ht.h_aliases = malloc(sizeof(char *));
+       if (ed->ht.h_aliases == NULL) {
+               return false;
+       }
+       ed->ht.h_aliases[0] = NULL;
+
+       /*
+        * Aliases
+        */
+       while (do_aliases) {
+               char **aliases;
+               char *a;
+
+               p++;
+
+               /* Walk to first char */
+               for (a = p; *p != '_' && !isalnum((int) *p); p++) {
+                       if (*p == '\0') {
+                               do_aliases = false;
+                               break;
+                       }
+               }
+               /* Only trailing spaces are left */
+               if (!do_aliases) {
+                       break;
+               }
+
+               for (a = p; !isspace((int)*p); p++) {
+                       if (*p == '\0') {
+                               do_aliases = false;
+                               break;
+                       }
+               }
+
+               *p = '\0';
+
+               aliases = realloc(ed->ht.h_aliases, sizeof(char *) * (aliases_count + 2));
+               if (aliases == NULL) {
+                       return false;
+               }
+               ed->ht.h_aliases = aliases;
+
+               aliases[aliases_count] = a;
+               aliases[aliases_count + 1] = NULL;
+
+               aliases_count++;
+       }
+
+       nwrap_he->num++;
+       return true;
+}
+
+static void nwrap_he_unload(struct nwrap_cache *nwrap)
+{
+       struct nwrap_he *nwrap_he =
+               (struct nwrap_he *)nwrap->private_data;
+       int i;
+
+       if (nwrap_he->list != NULL) {
+               for (i = 0; i < nwrap_he->num; i++) {
+                       if (nwrap_he->list[i].ht.h_aliases != NULL) {
+                               free(nwrap_he->list[i].ht.h_aliases);
+                       }
+                       if (nwrap_he->list[i].addr != NULL) {
+                               free(nwrap_he->list[i].addr);
+                       }
+               }
+               free(nwrap_he->list);
+       }
+
+       nwrap_he->list = NULL;
+       nwrap_he->num = 0;
+       nwrap_he->idx = 0;
+}
+
+
 /* user functions */
 static struct passwd *nwrap_files_getpwnam(struct nwrap_backend *b,
                                           const char *name)
 {
        int i;
 
+       (void) b; /* unused */
+
+       NWRAP_LOG(NWRAP_LOG_DEBUG, "Lookup user %s in files", name);
+
        nwrap_files_cache_reload(nwrap_pw_global.cache);
 
        for (i=0; i<nwrap_pw_global.num; i++) {
                if (strcmp(nwrap_pw_global.list[i].pw_name, name) == 0) {
-                       NWRAP_DEBUG(("%s: user[%s] found\n",
-                                    __location__, name));
+                       NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] found", name);
                        return &nwrap_pw_global.list[i];
                }
-               NWRAP_VERBOSE(("%s: user[%s] does not match [%s]\n",
-                              __location__, name,
-                              nwrap_pw_global.list[i].pw_name));
+               NWRAP_LOG(NWRAP_LOG_DEBUG,
+                         "user[%s] does not match [%s]",
+                         name,
+                         nwrap_pw_global.list[i].pw_name);
        }
 
-       NWRAP_DEBUG(("%s: user[%s] not found\n", __location__, name));
+       NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] not found\n", name);
 
        errno = ENOENT;
        return NULL;
@@ -1179,20 +2095,22 @@ static struct passwd *nwrap_files_getpwuid(struct nwrap_backend *b,
 {
        int i;
 
+       (void) b; /* unused */
+
        nwrap_files_cache_reload(nwrap_pw_global.cache);
 
        for (i=0; i<nwrap_pw_global.num; i++) {
                if (nwrap_pw_global.list[i].pw_uid == uid) {
-                       NWRAP_DEBUG(("%s: uid[%u] found\n",
-                                    __location__, uid));
+                       NWRAP_LOG(NWRAP_LOG_DEBUG, "uid[%u] found", uid);
                        return &nwrap_pw_global.list[i];
                }
-               NWRAP_VERBOSE(("%s: uid[%u] does not match [%u]\n",
-                              __location__, uid,
-                              nwrap_pw_global.list[i].pw_uid));
+               NWRAP_LOG(NWRAP_LOG_DEBUG,
+                         "uid[%u] does not match [%u]",
+                         uid,
+                         nwrap_pw_global.list[i].pw_uid);
        }
 
-       NWRAP_DEBUG(("%s: uid[%u] not found\n", __location__, uid));
+       NWRAP_LOG(NWRAP_LOG_DEBUG, "uid[%u] not found\n", uid);
 
        errno = ENOENT;
        return NULL;
@@ -1218,6 +2136,8 @@ static int nwrap_files_getpwuid_r(struct nwrap_backend *b,
 /* user enum functions */
 static void nwrap_files_setpwent(struct nwrap_backend *b)
 {
+       (void) b; /* unused */
+
        nwrap_pw_global.idx = 0;
 }
 
@@ -1225,6 +2145,8 @@ static struct passwd *nwrap_files_getpwent(struct nwrap_backend *b)
 {
        struct passwd *pw;
 
+       (void) b; /* unused */
+
        if (nwrap_pw_global.idx == 0) {
                nwrap_files_cache_reload(nwrap_pw_global.cache);
        }
@@ -1236,8 +2158,9 @@ static struct passwd *nwrap_files_getpwent(struct nwrap_backend *b)
 
        pw = &nwrap_pw_global.list[nwrap_pw_global.idx++];
 
-       NWRAP_VERBOSE(("%s: return user[%s] uid[%u]\n",
-                      __location__, pw->pw_name, pw->pw_uid));
+       NWRAP_LOG(NWRAP_LOG_DEBUG,
+                 "return user[%s] uid[%u]",
+                 pw->pw_name, pw->pw_uid);
 
        return pw;
 }
@@ -1261,6 +2184,8 @@ static int nwrap_files_getpwent_r(struct nwrap_backend *b,
 
 static void nwrap_files_endpwent(struct nwrap_backend *b)
 {
+       (void) b; /* unused */
+
        nwrap_pw_global.idx = 0;
 }
 
@@ -1268,6 +2193,10 @@ static void nwrap_files_endpwent(struct nwrap_backend *b)
 static int nwrap_files_initgroups(struct nwrap_backend *b,
                                  const char *user, gid_t group)
 {
+       (void) b; /* unused */
+       (void) user; /* unused */
+       (void) group; /* used */
+
        /* TODO: maybe we should also fake this... */
        return EPERM;
 }
@@ -1278,20 +2207,22 @@ static struct group *nwrap_files_getgrnam(struct nwrap_backend *b,
 {
        int i;
 
+       (void) b; /* unused */
+
        nwrap_files_cache_reload(nwrap_gr_global.cache);
 
        for (i=0; i<nwrap_gr_global.num; i++) {
                if (strcmp(nwrap_gr_global.list[i].gr_name, name) == 0) {
-                       NWRAP_DEBUG(("%s: group[%s] found\n",
-                                    __location__, name));
+                       NWRAP_LOG(NWRAP_LOG_DEBUG, "group[%s] found", name);
                        return &nwrap_gr_global.list[i];
                }
-               NWRAP_VERBOSE(("%s: group[%s] does not match [%s]\n",
-                              __location__, name,
-                              nwrap_gr_global.list[i].gr_name));
+               NWRAP_LOG(NWRAP_LOG_DEBUG,
+                         "group[%s] does not match [%s]",
+                         name,
+                         nwrap_gr_global.list[i].gr_name);
        }
 
-       NWRAP_DEBUG(("%s: group[%s] not found\n", __location__, name));
+       NWRAP_LOG(NWRAP_LOG_DEBUG, "group[%s] not found", name);
 
        errno = ENOENT;
        return NULL;
@@ -1319,20 +2250,22 @@ static struct group *nwrap_files_getgrgid(struct nwrap_backend *b,
 {
        int i;
 
+       (void) b; /* unused */
+
        nwrap_files_cache_reload(nwrap_gr_global.cache);
 
        for (i=0; i<nwrap_gr_global.num; i++) {
                if (nwrap_gr_global.list[i].gr_gid == gid) {
-                       NWRAP_DEBUG(("%s: gid[%u] found\n",
-                                    __location__, gid));
+                       NWRAP_LOG(NWRAP_LOG_DEBUG, "gid[%u] found", gid);
                        return &nwrap_gr_global.list[i];
                }
-               NWRAP_VERBOSE(("%s: gid[%u] does not match [%u]\n",
-                              __location__, gid,
-                              nwrap_gr_global.list[i].gr_gid));
+               NWRAP_LOG(NWRAP_LOG_DEBUG,
+                         "gid[%u] does not match [%u]",
+                         gid,
+                         nwrap_gr_global.list[i].gr_gid);
        }
 
-       NWRAP_DEBUG(("%s: gid[%u] not found\n", __location__, gid));
+       NWRAP_LOG(NWRAP_LOG_DEBUG, "gid[%u] not found", gid);
 
        errno = ENOENT;
        return NULL;
@@ -1358,6 +2291,8 @@ static int nwrap_files_getgrgid_r(struct nwrap_backend *b,
 /* group enum functions */
 static void nwrap_files_setgrent(struct nwrap_backend *b)
 {
+       (void) b; /* unused */
+
        nwrap_gr_global.idx = 0;
 }
 
@@ -1365,6 +2300,8 @@ static struct group *nwrap_files_getgrent(struct nwrap_backend *b)
 {
        struct group *gr;
 
+       (void) b; /* unused */
+
        if (nwrap_gr_global.idx == 0) {
                nwrap_files_cache_reload(nwrap_gr_global.cache);
        }
@@ -1376,8 +2313,9 @@ static struct group *nwrap_files_getgrent(struct nwrap_backend *b)
 
        gr = &nwrap_gr_global.list[nwrap_gr_global.idx++];
 
-       NWRAP_VERBOSE(("%s: return group[%s] gid[%u]\n",
-                      __location__, gr->gr_name, gr->gr_gid));
+       NWRAP_LOG(NWRAP_LOG_DEBUG,
+                 "return group[%s] gid[%u]",
+                 gr->gr_name, gr->gr_gid);
 
        return gr;
 }
@@ -1401,9 +2339,189 @@ static int nwrap_files_getgrent_r(struct nwrap_backend *b,
 
 static void nwrap_files_endgrent(struct nwrap_backend *b)
 {
+       (void) b; /* unused */
+
        nwrap_gr_global.idx = 0;
 }
 
+/* hosts functions */
+static struct hostent *nwrap_files_gethostbyname(const char *name, int af)
+{
+       struct hostent *he;
+       int i;
+
+       nwrap_files_cache_reload(nwrap_he_global.cache);
+
+       for (i = 0; i < nwrap_he_global.num; i++) {
+               int j;
+
+               he = &nwrap_he_global.list[i].ht;
+
+               /* Filter by address familiy if provided */
+               if (af != AF_UNSPEC && he->h_addrtype != af) {
+                       continue;
+               }
+
+               if (strcasecmp(he->h_name, name) == 0) {
+                       NWRAP_LOG(NWRAP_LOG_DEBUG, "name[%s] found", name);
+                       return he;
+               }
+
+               if (he->h_aliases == NULL) {
+                       continue;
+               }
+
+               for (j = 0; he->h_aliases[j] != NULL; j++) {
+                       if (strcasecmp(he->h_aliases[j], name) == 0) {
+                               NWRAP_LOG(NWRAP_LOG_DEBUG,
+                                         "name[%s] found",
+                                         name);
+                               return he;
+                       }
+               }
+       }
+
+       errno = ENOENT;
+       return NULL;
+}
+
+#ifdef HAVE_GETHOSTBYNAME_R
+static int nwrap_gethostbyname_r(const char *name,
+                                struct hostent *ret,
+                                char *buf, size_t buflen,
+                                struct hostent **result, int *h_errnop)
+{
+       *result = nwrap_files_gethostbyname(name, AF_UNSPEC);
+       if (*result != NULL) {
+               memset(buf, '\0', buflen);
+               *ret = **result;
+               return 0;
+       } else {
+               *h_errnop = h_errno;
+               return -1;
+       }
+}
+
+int gethostbyname_r(const char *name,
+                   struct hostent *ret,
+                   char *buf, size_t buflen,
+                   struct hostent **result, int *h_errnop)
+{
+       if (!nss_wrapper_hosts_enabled()) {
+               return libc_gethostbyname_r(name,
+                                           ret,
+                                           buf,
+                                           buflen,
+                                           result,
+                                           h_errnop);
+       }
+
+       return nwrap_gethostbyname_r(name, ret, buf, buflen, result, h_errnop);
+}
+#endif
+
+static struct hostent *nwrap_files_gethostbyaddr(const void *addr,
+                                                socklen_t len, int type)
+{
+       struct hostent *he;
+       char ip[INET6_ADDRSTRLEN] = {0};
+       const char *a;
+       int i;
+
+       (void) len; /* unused */
+
+       nwrap_files_cache_reload(nwrap_he_global.cache);
+
+       a = inet_ntop(type, addr, ip, sizeof(ip));
+       if (a == NULL) {
+               errno = EINVAL;
+               return NULL;
+       }
+
+       for (i = 0; i < nwrap_he_global.num; i++) {
+               he = &nwrap_he_global.list[i].ht;
+
+               if (he->h_addrtype != type) {
+                       continue;
+               }
+
+               if (memcmp(addr, he->h_addr_list[0], he->h_length) == 0) {
+                       return he;
+               }
+       }
+
+       errno = ENOENT;
+       return NULL;
+}
+
+#ifdef HAVE_GETHOSTBYADDR_R
+static int nwrap_gethostbyaddr_r(const void *addr, socklen_t len, int type,
+                                struct hostent *ret,
+                                char *buf, size_t buflen,
+                                struct hostent **result, int *h_errnop)
+{
+       *result = nwrap_files_gethostbyaddr(addr, len, type);
+       if (*result != NULL) {
+               memset(buf, '\0', buflen);
+               *ret = **result;
+               return 0;
+       } else {
+               *h_errnop = h_errno;
+               return -1;
+       }
+}
+
+int gethostbyaddr_r(const void *addr, socklen_t len, int type,
+                   struct hostent *ret,
+                   char *buf, size_t buflen,
+                   struct hostent **result, int *h_errnop)
+{
+       if (!nss_wrapper_hosts_enabled()) {
+               return libc_gethostbyaddr_r(addr,
+                                           len,
+                                           type,
+                                           ret,
+                                           buf,
+                                           buflen,
+                                           result,
+                                           h_errnop);
+       }
+
+       return nwrap_gethostbyaddr_r(addr, len, type, ret, buf, buflen, result, h_errnop);
+}
+#endif
+
+/* hosts enum functions */
+static void nwrap_files_sethostent(void)
+{
+       nwrap_he_global.idx = 0;
+}
+
+static struct hostent *nwrap_files_gethostent(void)
+{
+       struct hostent *he;
+
+       if (nwrap_he_global.idx == 0) {
+               nwrap_files_cache_reload(nwrap_he_global.cache);
+       }
+
+       if (nwrap_he_global.idx >= nwrap_he_global.num) {
+               errno = ENOENT;
+               return NULL;
+       }
+
+       he = &nwrap_he_global.list[nwrap_he_global.idx++].ht;
+
+       NWRAP_LOG(NWRAP_LOG_DEBUG, "return hosts[%s]", he->h_name);
+
+       return he;
+}
+
+static void nwrap_files_endhostent(void)
+{
+       nwrap_he_global.idx = 0;
+}
+
 /*
  * module backend
  */
@@ -1430,6 +2548,7 @@ static struct passwd *nwrap_module_getpwnam(struct nwrap_backend *b,
        if (status != NSS_STATUS_SUCCESS) {
                return NULL;
        }
+
        return &pwd;
 }
 
@@ -1439,6 +2558,10 @@ static int nwrap_module_getpwnam_r(struct nwrap_backend *b,
 {
        int ret;
 
+       (void) b; /* unused */
+       (void) pwdst; /* unused */
+       (void) pwdstp; /* unused */
+
        if (!b->fns->_nss_getpwnam_r) {
                return NSS_STATUS_NOTFOUND;
        }
@@ -1492,6 +2615,8 @@ static int nwrap_module_getpwuid_r(struct nwrap_backend *b,
 {
        int ret;
 
+       (void) pwdstp; /* unused */
+
        if (!b->fns->_nss_getpwuid_r) {
                return ENOENT;
        }
@@ -1553,6 +2678,8 @@ static int nwrap_module_getpwent_r(struct nwrap_backend *b,
 {
        int ret;
 
+       (void) pwdstp; /* unused */
+
        if (!b->fns->_nss_getpwent_r) {
                return ENOENT;
        }
@@ -1644,6 +2771,8 @@ static int nwrap_module_getgrnam_r(struct nwrap_backend *b,
 {
        int ret;
 
+       (void) grdstp; /* unused */
+
        if (!b->fns->_nss_getgrnam_r) {
                return ENOENT;
        }
@@ -1713,6 +2842,8 @@ static int nwrap_module_getgrgid_r(struct nwrap_backend *b,
 {
        int ret;
 
+       (void) grdstp; /* unused */
+
        if (!b->fns->_nss_getgrgid_r) {
                return ENOENT;
        }
@@ -1790,6 +2921,8 @@ static int nwrap_module_getgrent_r(struct nwrap_backend *b,
 {
        int ret;
 
+       (void) grdstp; /* unused */
+
        if (!b->fns->_nss_getgrent_r) {
                return ENOENT;
        }
@@ -1825,19 +2958,15 @@ static void nwrap_module_endgrent(struct nwrap_backend *b)
        b->fns->_nss_endgrent();
 }
 
-/*
- * PUBLIC interface
- */
+/****************************************************************************
+ *   GETPWNAM
+ ***************************************************************************/
 
-_PUBLIC_ struct passwd *nwrap_getpwnam(const char *name)
+static struct passwd *nwrap_getpwnam(const char *name)
 {
        int i;
        struct passwd *pwd;
 
-       if (!nwrap_enabled()) {
-               return real_getpwnam(name);
-       }
-
        for (i=0; i < nwrap_main_global->num_backends; i++) {
                struct nwrap_backend *b = &nwrap_main_global->backends[i];
                pwd = b->ops->nw_getpwnam(b, name);
@@ -1849,15 +2978,24 @@ _PUBLIC_ struct passwd *nwrap_getpwnam(const char *name)
        return NULL;
 }
 
-_PUBLIC_ int nwrap_getpwnam_r(const char *name, struct passwd *pwdst,
-                             char *buf, size_t buflen, struct passwd **pwdstp)
+struct passwd *getpwnam(const char *name)
 {
-       int i,ret;
-
-       if (!nwrap_enabled()) {
-               return real_getpwnam_r(name, pwdst, buf, buflen, pwdstp);
+       if (!nss_wrapper_enabled()) {
+               return libc_getpwnam(name);
        }
 
+       return nwrap_getpwnam(name);
+}
+
+/****************************************************************************
+ *   GETPWNAM_R
+ ***************************************************************************/
+
+static int nwrap_getpwnam_r(const char *name, struct passwd *pwdst,
+                           char *buf, size_t buflen, struct passwd **pwdstp)
+{
+       int i,ret;
+
        for (i=0; i < nwrap_main_global->num_backends; i++) {
                struct nwrap_backend *b = &nwrap_main_global->backends[i];
                ret = b->ops->nw_getpwnam_r(b, name, pwdst, buf, buflen, pwdstp);
@@ -1870,15 +3008,32 @@ _PUBLIC_ int nwrap_getpwnam_r(const char *name, struct passwd *pwdst,
        return ENOENT;
 }
 
-_PUBLIC_ struct passwd *nwrap_getpwuid(uid_t uid)
+#ifdef HAVE_GETPWNAM_R
+# ifdef HAVE_SOLARIS_GETPWNAM_R
+int getpwnam_r(const char *name, struct passwd *pwdst,
+              char *buf, int buflen, struct passwd **pwdstp)
+# else /* HAVE_SOLARIS_GETPWNAM_R */
+int getpwnam_r(const char *name, struct passwd *pwdst,
+              char *buf, size_t buflen, struct passwd **pwdstp)
+# endif /* HAVE_SOLARIS_GETPWNAM_R */
+{
+       if (!nss_wrapper_enabled()) {
+               return libc_getpwnam_r(name, pwdst, buf, buflen, pwdstp);
+       }
+
+       return nwrap_getpwnam_r(name, pwdst, buf, buflen, pwdstp);
+}
+#endif
+
+/****************************************************************************
+ *   GETPWUID
+ ***************************************************************************/
+
+static struct passwd *nwrap_getpwuid(uid_t uid)
 {
        int i;
        struct passwd *pwd;
 
-       if (!nwrap_enabled()) {
-               return real_getpwuid(uid);
-       }
-
        for (i=0; i < nwrap_main_global->num_backends; i++) {
                struct nwrap_backend *b = &nwrap_main_global->backends[i];
                pwd = b->ops->nw_getpwuid(b, uid);
@@ -1890,15 +3045,24 @@ _PUBLIC_ struct passwd *nwrap_getpwuid(uid_t uid)
        return NULL;
 }
 
-_PUBLIC_ int nwrap_getpwuid_r(uid_t uid, struct passwd *pwdst,
-                             char *buf, size_t buflen, struct passwd **pwdstp)
+struct passwd *getpwuid(uid_t uid)
 {
-       int i,ret;
-
-       if (!nwrap_enabled()) {
-               return real_getpwuid_r(uid, pwdst, buf, buflen, pwdstp);
+       if (!nss_wrapper_enabled()) {
+               return libc_getpwuid(uid);
        }
 
+       return nwrap_getpwuid(uid);
+}
+
+/****************************************************************************
+ *   GETPWUID_R
+ ***************************************************************************/
+
+static int nwrap_getpwuid_r(uid_t uid, struct passwd *pwdst,
+                           char *buf, size_t buflen, struct passwd **pwdstp)
+{
+       int i,ret;
+
        for (i=0; i < nwrap_main_global->num_backends; i++) {
                struct nwrap_backend *b = &nwrap_main_global->backends[i];
                ret = b->ops->nw_getpwuid_r(b, uid, pwdst, buf, buflen, pwdstp);
@@ -1911,30 +3075,54 @@ _PUBLIC_ int nwrap_getpwuid_r(uid_t uid, struct passwd *pwdst,
        return ENOENT;
 }
 
-_PUBLIC_ void nwrap_setpwent(void)
+#ifdef HAVE_SOLARIS_GETPWUID_R
+int getpwuid_r(uid_t uid, struct passwd *pwdst,
+              char *buf, int buflen, struct passwd **pwdstp)
+#else
+int getpwuid_r(uid_t uid, struct passwd *pwdst,
+              char *buf, size_t buflen, struct passwd **pwdstp)
+#endif
 {
-       int i;
-
-       if (!nwrap_enabled()) {
-               real_setpwent();
-               return;
+       if (!nss_wrapper_enabled()) {
+               return libc_getpwuid_r(uid, pwdst, buf, buflen, pwdstp);
        }
 
+       return nwrap_getpwuid_r(uid, pwdst, buf, buflen, pwdstp);
+}
+
+/****************************************************************************
+ *   SETPWENT
+ ***************************************************************************/
+
+static void nwrap_setpwent(void)
+{
+       int i;
+
        for (i=0; i < nwrap_main_global->num_backends; i++) {
                struct nwrap_backend *b = &nwrap_main_global->backends[i];
                b->ops->nw_setpwent(b);
        }
 }
 
-_PUBLIC_ struct passwd *nwrap_getpwent(void)
+void setpwent(void)
+{
+       if (!nss_wrapper_enabled()) {
+               libc_setpwent();
+               return;
+       }
+
+       nwrap_setpwent();
+}
+
+/****************************************************************************
+ *   GETPWENT
+ ***************************************************************************/
+
+static struct passwd *nwrap_getpwent(void)
 {
        int i;
        struct passwd *pwd;
 
-       if (!nwrap_enabled()) {
-               return real_getpwent();
-       }
-
        for (i=0; i < nwrap_main_global->num_backends; i++) {
                struct nwrap_backend *b = &nwrap_main_global->backends[i];
                pwd = b->ops->nw_getpwent(b);
@@ -1946,30 +3134,24 @@ _PUBLIC_ struct passwd *nwrap_getpwent(void)
        return NULL;
 }
 
-_PUBLIC_ int nwrap_getpwent_r(struct passwd *pwdst, char *buf,
-                             size_t buflen, struct passwd **pwdstp)
+struct passwd *getpwent(void)
 {
-       int i,ret;
-
-       if (!nwrap_enabled()) {
-#ifdef SOLARIS_GETPWENT_R
-               struct passwd *pw;
-               pw = real_getpwent_r(pwdst, buf, buflen);
-               if (!pw) {
-                       if (errno == 0) {
-                               return ENOENT;
-                       }
-                       return errno;
-               }
-               if (pwdstp) {
-                       *pwdstp = pw;
-               }
-               return 0;
-#else
-               return real_getpwent_r(pwdst, buf, buflen, pwdstp);
-#endif
+       if (!nss_wrapper_enabled()) {
+               return libc_getpwent();
        }
 
+       return nwrap_getpwent();
+}
+
+/****************************************************************************
+ *   GETPWENT_R
+ ***************************************************************************/
+
+static int nwrap_getpwent_r(struct passwd *pwdst, char *buf,
+                           size_t buflen, struct passwd **pwdstp)
+{
+       int i,ret;
+
        for (i=0; i < nwrap_main_global->num_backends; i++) {
                struct nwrap_backend *b = &nwrap_main_global->backends[i];
                ret = b->ops->nw_getpwent_r(b, pwdst, buf, buflen, pwdstp);
@@ -1982,47 +3164,98 @@ _PUBLIC_ int nwrap_getpwent_r(struct passwd *pwdst, char *buf,
        return ENOENT;
 }
 
-_PUBLIC_ void nwrap_endpwent(void)
+#ifdef HAVE_SOLARIS_GETPWENT_R
+struct passwd *getpwent_r(struct passwd *pwdst, char *buf, int buflen)
 {
-       int i;
+       struct passwd *pwdstp = NULL;
+       int rc;
 
-       if (!nwrap_enabled()) {
-               real_endpwent();
-               return;
+       if (!nss_wrapper_enabled()) {
+               return libc_getpwent_r(pwdst, buf, buflen);
+       }
+       rc = nwrap_getpwent_r(pwdst, buf, buflen, &pwdstp);
+       if (rc < 0) {
+               return NULL;
+       }
+
+       return pwdstp;
+}
+#else /* HAVE_SOLARIS_GETPWENT_R */
+int getpwent_r(struct passwd *pwdst, char *buf,
+              size_t buflen, struct passwd **pwdstp)
+{
+       if (!nss_wrapper_enabled()) {
+               return libc_getpwent_r(pwdst, buf, buflen, pwdstp);
        }
 
+       return nwrap_getpwent_r(pwdst, buf, buflen, pwdstp);
+}
+#endif /* HAVE_SOLARIS_GETPWENT_R */
+
+/****************************************************************************
+ *   ENDPWENT
+ ***************************************************************************/
+
+static void nwrap_endpwent(void)
+{
+       int i;
+
        for (i=0; i < nwrap_main_global->num_backends; i++) {
                struct nwrap_backend *b = &nwrap_main_global->backends[i];
                b->ops->nw_endpwent(b);
        }
 }
 
-_PUBLIC_ int nwrap_initgroups(const char *user, gid_t group)
+void endpwent(void)
 {
-       int i;
-
-       if (!nwrap_enabled()) {
-               return real_initgroups(user, group);
+       if (!nss_wrapper_enabled()) {
+               libc_endpwent();
+               return;
        }
 
+       nwrap_endpwent();
+}
+
+/****************************************************************************
+ *   INITGROUPS
+ ***************************************************************************/
+
+static int nwrap_initgroups(const char *user, gid_t group)
+{
+       int i;
+
        for (i=0; i < nwrap_main_global->num_backends; i++) {
                struct nwrap_backend *b = &nwrap_main_global->backends[i];
-               return b->ops->nw_initgroups(b, user, group);
+               int rc;
+
+               rc = b->ops->nw_initgroups(b, user, group);
+               if (rc == 0) {
+                       return 0;
+               }
        }
 
        errno = ENOENT;
        return -1;
 }
 
-_PUBLIC_ struct group *nwrap_getgrnam(const char *name)
+int initgroups(const char *user, gid_t group)
+{
+       if (!nss_wrapper_enabled()) {
+               return libc_initgroups(user, group);
+       }
+
+       return nwrap_initgroups(user, group);
+}
+
+/****************************************************************************
+ *   GETGRNAM
+ ***************************************************************************/
+
+static struct group *nwrap_getgrnam(const char *name)
 {
        int i;
        struct group *grp;
 
-       if (!nwrap_enabled()) {
-               return real_getgrnam(name);
-       }
-
        for (i=0; i < nwrap_main_global->num_backends; i++) {
                struct nwrap_backend *b = &nwrap_main_global->backends[i];
                grp = b->ops->nw_getgrnam(b, name);
@@ -2034,15 +3267,24 @@ _PUBLIC_ struct group *nwrap_getgrnam(const char *name)
        return NULL;
 }
 
-_PUBLIC_ int nwrap_getgrnam_r(const char *name, struct group *grdst,
-                             char *buf, size_t buflen, struct group **grdstp)
+struct group *getgrnam(const char *name)
 {
-       int i,ret;
-
-       if (!nwrap_enabled()) {
-               return real_getgrnam_r(name, grdst, buf, buflen, grdstp);
+       if (!nss_wrapper_enabled()) {
+               return libc_getgrnam(name);
        }
 
+       return nwrap_getgrnam(name);
+}
+
+/****************************************************************************
+ *   GETGRNAM_R
+ ***************************************************************************/
+
+static int nwrap_getgrnam_r(const char *name, struct group *grdst,
+                           char *buf, size_t buflen, struct group **grdstp)
+{
+       int i, ret;
+
        for (i=0; i < nwrap_main_global->num_backends; i++) {
                struct nwrap_backend *b = &nwrap_main_global->backends[i];
                ret = b->ops->nw_getgrnam_r(b, name, grdst, buf, buflen, grdstp);
@@ -2055,15 +3297,36 @@ _PUBLIC_ int nwrap_getgrnam_r(const char *name, struct group *grdst,
        return ENOENT;
 }
 
-_PUBLIC_ struct group *nwrap_getgrgid(gid_t gid)
+#ifdef HAVE_GETGRNAM_R
+# ifdef HAVE_SOLARIS_GETGRNAM_R
+int getgrnam_r(const char *name, struct group *grp,
+               char *buf, int buflen, struct group **pgrp)
+# else /* HAVE_SOLARIS_GETGRNAM_R */
+int getgrnam_r(const char *name, struct group *grp,
+              char *buf, size_t buflen, struct group **pgrp)
+# endif /* HAVE_SOLARIS_GETGRNAM_R */
+{
+       if (!nss_wrapper_enabled()) {
+               return libc_getgrnam_r(name,
+                                      grp,
+                                      buf,
+                                      buflen,
+                                      pgrp);
+       }
+
+       return nwrap_getgrnam_r(name, grp, buf, buflen, pgrp);
+}
+#endif /* HAVE_GETGRNAM_R */
+
+/****************************************************************************
+ *   GETGRGID
+ ***************************************************************************/
+
+static struct group *nwrap_getgrgid(gid_t gid)
 {
        int i;
        struct group *grp;
 
-       if (!nwrap_enabled()) {
-               return real_getgrgid(gid);
-       }
-
        for (i=0; i < nwrap_main_global->num_backends; i++) {
                struct nwrap_backend *b = &nwrap_main_global->backends[i];
                grp = b->ops->nw_getgrgid(b, gid);
@@ -2075,15 +3338,24 @@ _PUBLIC_ struct group *nwrap_getgrgid(gid_t gid)
        return NULL;
 }
 
-_PUBLIC_ int nwrap_getgrgid_r(gid_t gid, struct group *grdst,
-                             char *buf, size_t buflen, struct group **grdstp)
+struct group *getgrgid(gid_t gid)
 {
-       int i,ret;
-
-       if (!nwrap_enabled()) {
-               return real_getgrgid_r(gid, grdst, buf, buflen, grdstp);
+       if (!nss_wrapper_enabled()) {
+               return libc_getgrgid(gid);
        }
 
+       return nwrap_getgrgid(gid);
+}
+
+/****************************************************************************
+ *   GETGRGID_R
+ ***************************************************************************/
+
+static int nwrap_getgrgid_r(gid_t gid, struct group *grdst,
+                           char *buf, size_t buflen, struct group **grdstp)
+{
+       int i,ret;
+
        for (i=0; i < nwrap_main_global->num_backends; i++) {
                struct nwrap_backend *b = &nwrap_main_global->backends[i];
                ret = b->ops->nw_getgrgid_r(b, gid, grdst, buf, buflen, grdstp);
@@ -2096,30 +3368,67 @@ _PUBLIC_ int nwrap_getgrgid_r(gid_t gid, struct group *grdst,
        return ENOENT;
 }
 
-_PUBLIC_ void nwrap_setgrent(void)
+#ifdef HAVE_GETGRGID_R
+# ifdef HAVE_SOLARIS_GETGRGID_R
+int getgrgid_r(gid_t gid, struct group *grdst,
+              char *buf, int buflen, struct group **grdstp)
+# else /* HAVE_SOLARIS_GETGRGID_R */
+int getgrgid_r(gid_t gid, struct group *grdst,
+              char *buf, size_t buflen, struct group **grdstp)
+# endif /* HAVE_SOLARIS_GETGRGID_R */
 {
-       int i;
-
-       if (!nwrap_enabled()) {
-               real_setgrent();
-               return;
+       if (!nss_wrapper_enabled()) {
+               return libc_getgrgid_r(gid, grdst, buf, buflen, grdstp);
        }
 
+       return nwrap_getgrgid_r(gid, grdst, buf, buflen, grdstp);
+}
+#endif
+
+/****************************************************************************
+ *   SETGRENT
+ ***************************************************************************/
+
+static void nwrap_setgrent(void)
+{
+       int i;
+
        for (i=0; i < nwrap_main_global->num_backends; i++) {
                struct nwrap_backend *b = &nwrap_main_global->backends[i];
                b->ops->nw_setgrent(b);
        }
 }
 
-_PUBLIC_ struct group *nwrap_getgrent(void)
+#ifdef HAVE_BSD_SETGRENT
+int setgrent(void)
+#else
+void setgrent(void)
+#endif
+{
+       if (!nss_wrapper_enabled()) {
+               libc_setgrent();
+               goto out;
+       }
+
+       nwrap_setgrent();
+
+out:
+#ifdef HAVE_BSD_SETGRENT
+       return 0;
+#else
+       return;
+#endif
+}
+
+/****************************************************************************
+ *   GETGRENT
+ ***************************************************************************/
+
+static struct group *nwrap_getgrent(void)
 {
        int i;
        struct group *grp;
 
-       if (!nwrap_enabled()) {
-               return real_getgrent();
-       }
-
        for (i=0; i < nwrap_main_global->num_backends; i++) {
                struct nwrap_backend *b = &nwrap_main_global->backends[i];
                grp = b->ops->nw_getgrent(b);
@@ -2131,30 +3440,24 @@ _PUBLIC_ struct group *nwrap_getgrent(void)
        return NULL;
 }
 
-_PUBLIC_ int nwrap_getgrent_r(struct group *grdst, char *buf,
-                             size_t buflen, struct group **grdstp)
+struct group *getgrent(void)
 {
-       int i,ret;
-
-       if (!nwrap_enabled()) {
-#ifdef SOLARIS_GETGRENT_R
-               struct group *gr;
-               gr = real_getgrent_r(grdst, buf, buflen);
-               if (!gr) {
-                       if (errno == 0) {
-                               return ENOENT;
-                       }
-                       return errno;
-               }
-               if (grdstp) {
-                       *grdstp = gr;
-               }
-               return 0;
-#else
-               return real_getgrent_r(grdst, buf, buflen, grdstp);
-#endif
+       if (!nss_wrapper_enabled()) {
+               return libc_getgrent();
        }
 
+       return nwrap_getgrent();
+}
+
+/****************************************************************************
+ *   GETGRENT_R
+ ***************************************************************************/
+
+static int nwrap_getgrent_r(struct group *grdst, char *buf,
+                           size_t buflen, struct group **grdstp)
+{
+       int i,ret;
+
        for (i=0; i < nwrap_main_global->num_backends; i++) {
                struct nwrap_backend *b = &nwrap_main_global->backends[i];
                ret = b->ops->nw_getgrent_r(b, grdst, buf, buflen, grdstp);
@@ -2167,37 +3470,77 @@ _PUBLIC_ int nwrap_getgrent_r(struct group *grdst, char *buf,
        return ENOENT;
 }
 
-_PUBLIC_ void nwrap_endgrent(void)
+#ifdef HAVE_SOLARIS_GETGRENT_R
+struct group *getgrent_r(struct group *src, char *buf, int buflen)
 {
-       int i;
+       struct group *grdstp = NULL;
+       int rc;
 
-       if (!nwrap_enabled()) {
-               real_endgrent();
-               return;
+       if (!nss_wrapper_enabled()) {
+               return libc_getgrent_r(src, buf, buflen);
+       }
+
+       rc = nwrap_getgrent_r(src, buf, buflen, &grdstp);
+       if (rc < 0) {
+               return NULL;
        }
 
+       return grdstp;
+}
+#else /* HAVE_SOLARIS_GETGRENT_R */
+int getgrent_r(struct group *src, char *buf,
+              size_t buflen, struct group **grdstp)
+{
+       if (!nss_wrapper_enabled()) {
+               return libc_getgrent_r(src, buf, buflen, grdstp);
+       }
+
+       return nwrap_getgrent_r(src, buf, buflen, grdstp);
+}
+#endif /* HAVE_SOLARIS_GETGRENT_R */
+
+/****************************************************************************
+ *   ENDGRENT
+ ***************************************************************************/
+
+static void nwrap_endgrent(void)
+{
+       int i;
+
        for (i=0; i < nwrap_main_global->num_backends; i++) {
                struct nwrap_backend *b = &nwrap_main_global->backends[i];
                b->ops->nw_endgrent(b);
        }
 }
 
-_PUBLIC_ int nwrap_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups)
+void endgrent(void)
+{
+       if (!nss_wrapper_enabled()) {
+               libc_endgrent();
+               return;
+       }
+
+       nwrap_endgrent();
+}
+
+/****************************************************************************
+ *   GETGROUPLIST
+ ***************************************************************************/
+
+#ifdef HAVE_GETGROUPLIST
+static int nwrap_getgrouplist(const char *user, gid_t group,
+                             gid_t *groups, int *ngroups)
 {
        struct group *grp;
        gid_t *groups_tmp;
        int count = 1;
        const char *name_of_group = "";
 
-       if (!nwrap_enabled()) {
-               return real_getgrouplist(user, group, groups, ngroups);
-       }
-
-       NWRAP_DEBUG(("%s: getgrouplist called for %s\n", __location__, user));
+       NWRAP_LOG(NWRAP_LOG_DEBUG, "getgrouplist called for %s", user);
 
        groups_tmp = (gid_t *)malloc(count * sizeof(gid_t));
        if (!groups_tmp) {
-               NWRAP_ERROR(("%s:calloc failed\n",__location__));
+               NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
                errno = ENOMEM;
                return -1;
        }
@@ -2213,20 +3556,24 @@ _PUBLIC_ int nwrap_getgrouplist(const char *user, gid_t group, gid_t *groups, in
        while ((grp = nwrap_getgrent()) != NULL) {
                int i = 0;
 
-               NWRAP_VERBOSE(("%s: inspecting %s for group membership\n",
-                              __location__, grp->gr_name));
+               NWRAP_LOG(NWRAP_LOG_DEBUG,
+                         "Inspecting %s for group membership",
+                         grp->gr_name);
 
                for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) {
 
                        if ((strcmp(user, grp->gr_mem[i]) == 0) &&
                            (strcmp(name_of_group, grp->gr_name) != 0)) {
 
-                               NWRAP_DEBUG(("%s: %s is member of %s\n",
-                                       __location__, user, grp->gr_name));
+                               NWRAP_LOG(NWRAP_LOG_DEBUG,
+                                         "%s is member of %s",
+                                         user,
+                                         grp->gr_name);
 
                                groups_tmp = (gid_t *)realloc(groups_tmp, (count + 1) * sizeof(gid_t));
                                if (!groups_tmp) {
-                                       NWRAP_ERROR(("%s:calloc failed\n",__location__));
+                                       NWRAP_LOG(NWRAP_LOG_ERROR,
+                                                 "Out of memory");
                                        errno = ENOMEM;
                                        return -1;
                                }
@@ -2239,8 +3586,9 @@ _PUBLIC_ int nwrap_getgrouplist(const char *user, gid_t group, gid_t *groups, in
 
        nwrap_endgrent();
 
-       NWRAP_VERBOSE(("%s: %s is member of %d groups: %d\n",
-                      __location__, user, *ngroups));
+       NWRAP_LOG(NWRAP_LOG_DEBUG,
+                 "%s is member of %d groups",
+                 user, *ngroups);
 
        if (*ngroups < count) {
                *ngroups = count;
@@ -2254,3 +3602,631 @@ _PUBLIC_ int nwrap_getgrouplist(const char *user, gid_t group, gid_t *groups, in
 
        return count;
 }
+
+int getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups)
+{
+       if (!nss_wrapper_enabled()) {
+               return libc_getgrouplist(user, group, groups, ngroups);
+       }
+
+       return nwrap_getgrouplist(user, group, groups, ngroups);
+}
+#endif
+
+/**********************************************************
+ * NETDB
+ **********************************************************/
+
+static void nwrap_sethostent(int stayopen) {
+       (void) stayopen; /* ignored */
+
+       nwrap_files_sethostent();
+}
+
+#ifdef HAVE_SOLARIS_SETHOSTENT
+int sethostent(int stayopen)
+{
+       if (!nss_wrapper_hosts_enabled()) {
+               libc_sethostent(stayopen);
+               return 0;
+       }
+
+       nwrap_sethostent(stayopen);
+
+       return 0;
+}
+#else /* HAVE_SOLARIS_SETHOSTENT */
+void sethostent(int stayopen)
+{
+       if (!nss_wrapper_hosts_enabled()) {
+               libc_sethostent(stayopen);
+               return;
+       }
+
+       nwrap_sethostent(stayopen);
+}
+#endif /* HAVE_SOLARIS_SETHOSTENT */
+
+static struct hostent *nwrap_gethostent(void)
+{
+       return nwrap_files_gethostent();
+}
+
+struct hostent *gethostent(void) {
+       if (!nss_wrapper_hosts_enabled()) {
+               return libc_gethostent();
+       }
+
+       return nwrap_gethostent();
+}
+
+static void nwrap_endhostent(void) {
+       nwrap_files_endhostent();
+}
+
+#ifdef HAVE_SOLARIS_ENDHOSTENT
+int endhostent(void)
+{
+       if (!nss_wrapper_hosts_enabled()) {
+               libc_endhostent();
+               return 0;
+       }
+
+       nwrap_endhostent();
+
+       return 0;
+}
+#else /* HAVE_SOLARIS_ENDHOSTENT */
+void endhostent(void)
+{
+       if (!nss_wrapper_hosts_enabled()) {
+               libc_endhostent();
+               return;
+       }
+
+       nwrap_endhostent();
+}
+#endif /* HAVE_SOLARIS_ENDHOSTENT */
+
+static struct hostent *nwrap_gethostbyname(const char *name)
+{
+       return nwrap_files_gethostbyname(name, AF_UNSPEC);
+}
+
+struct hostent *gethostbyname(const char *name)
+{
+       if (!nss_wrapper_hosts_enabled()) {
+               return libc_gethostbyname(name);
+       }
+
+       return nwrap_gethostbyname(name);
+}
+
+/* This is a GNU extension */
+#ifdef HAVE_GETHOSTBYNAME2
+static struct hostent *nwrap_gethostbyname2(const char *name, int af)
+{
+       return nwrap_files_gethostbyname(name, af);
+}
+
+struct hostent *gethostbyname2(const char *name, int af)
+{
+       if (!nss_wrapper_hosts_enabled()) {
+               return libc_gethostbyname2(name, af);
+       }
+
+       return nwrap_gethostbyname2(name, af);
+}
+#endif
+
+static struct hostent *nwrap_gethostbyaddr(const void *addr,
+                                          socklen_t len, int type)
+{
+       return nwrap_files_gethostbyaddr(addr, len, type);
+}
+
+struct hostent *gethostbyaddr(const void *addr,
+                             socklen_t len, int type)
+{
+       if (!nss_wrapper_hosts_enabled()) {
+               return libc_gethostbyaddr(addr, len, type);
+       }
+
+       return nwrap_gethostbyaddr(addr, len, type);
+}
+
+static const struct addrinfo default_hints =
+{
+       .ai_flags = AI_ADDRCONFIG|AI_V4MAPPED,
+       .ai_family = AF_UNSPEC,
+       .ai_socktype = 0,
+       .ai_protocol = 0,
+       .ai_addrlen = 0,
+       .ai_addr = NULL,
+       .ai_canonname = NULL,
+       .ai_next = NULL
+};
+
+static int nwrap_convert_he_ai(const struct hostent *he,
+                              unsigned short port,
+                              const struct addrinfo *hints,
+                              struct addrinfo **pai)
+{
+       struct addrinfo *ai;
+       socklen_t socklen;
+
+       switch (he->h_addrtype) {
+               case AF_INET:
+                       socklen = sizeof(struct sockaddr_in);
+                       break;
+#ifdef HAVE_IPV6
+               case AF_INET6:
+                       socklen = sizeof(struct sockaddr_in6);
+                       break;
+#endif
+               default:
+                       return EAI_FAMILY;
+       }
+
+       ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + socklen);
+       if (ai == NULL) {
+               return EAI_MEMORY;
+       }
+
+       ai->ai_flags = 0;
+       ai->ai_family = he->h_addrtype;
+       ai->ai_socktype = hints->ai_socktype;
+       ai->ai_protocol = hints->ai_protocol;
+
+       ai->ai_addrlen = socklen;
+       ai->ai_addr = (void *)(ai + 1);
+
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+       ai->ai_addr->sa_len = socklen;
+#endif
+       ai->ai_addr->sa_family = he->h_addrtype;
+
+       switch (he->h_addrtype) {
+               case AF_INET:
+               {
+                       struct sockaddr_in *sinp =
+                               (struct sockaddr_in *) ai->ai_addr;
+
+                       memset(sinp, 0, sizeof(struct sockaddr_in));
+
+                       sinp->sin_port = htons(port);
+                       sinp->sin_family = AF_INET;
+
+                       memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
+                       memcpy(&sinp->sin_addr, he->h_addr_list[0], he->h_length);
+
+               }
+               break;
+#ifdef HAVE_IPV6
+               case AF_INET6:
+               {
+                       struct sockaddr_in6 *sin6p =
+                               (struct sockaddr_in6 *) ai->ai_addr;
+
+                       memset(sin6p, 0, sizeof(struct sockaddr_in6));
+
+                       sin6p->sin6_port = htons(port);
+                       sin6p->sin6_family = AF_INET6;
+
+                       memcpy(&sin6p->sin6_addr, he->h_addr_list[0], he->h_length);
+               }
+               break;
+#endif
+       }
+
+       ai->ai_next = NULL;
+
+       if (he->h_name) {
+               ai->ai_canonname = strdup(he->h_name);
+               if (ai->ai_canonname == NULL) {
+                       freeaddrinfo(ai);
+                       return EAI_MEMORY;
+               }
+       }
+
+       *pai = ai;
+       return 0;
+}
+
+static int nwrap_getaddrinfo(const char *node,
+                            const char *service,
+                            const struct addrinfo *hints,
+                            struct addrinfo **res)
+{
+       struct addrinfo *ai = NULL;
+       struct addrinfo *p = NULL;
+       unsigned short port = 0;
+       struct hostent *he;
+       struct in_addr in;
+       bool is_addr_ipv4 = false;
+       bool is_addr_ipv6 = false;
+       int eai = EAI_SYSTEM;
+       int ret;
+       int rc;
+       int af;
+
+       if (node == NULL && service == NULL) {
+               return EAI_NONAME;
+       }
+
+       ret = libc_getaddrinfo(node, service, hints, &p);
+       if (ret == 0) {
+               *res = p;
+       }
+
+       /* If no node has been specified, let glibc deal with it */
+       if (node == NULL) {
+               return ret;
+       }
+
+       if (hints == NULL) {
+               hints = &default_hints;
+       }
+
+       if ((hints->ai_flags & AI_CANONNAME) && node == NULL) {
+               return EAI_BADFLAGS;
+       }
+
+       if (service != NULL && service[0] != '\0') {
+               if (isdigit((int)service[0])) {
+                       port = (unsigned short)atoi(service);
+               } else {
+                       const char *proto = NULL;
+                       struct servent *s;
+
+                       if (hints->ai_protocol != 0) {
+                               struct protoent *pent;
+
+                               pent = getprotobynumber(hints->ai_protocol);
+                               if (pent != NULL) {
+                                       proto = pent->p_name;
+                               }
+                       }
+
+                       s = getservbyname(service, proto);
+                       if (s != NULL) {
+                               port = ntohs(s->s_port);
+                       } else {
+                               if (p != NULL) {
+                                       freeaddrinfo(p);
+                               }
+                               return EAI_SERVICE;
+                       }
+               }
+       }
+
+       af = hints->ai_family;
+       if (af == AF_UNSPEC) {
+               af = AF_INET;
+       }
+
+       rc = inet_pton(af, node, &in);
+       if (rc == 1) {
+               is_addr_ipv4 = true;
+               if (af == AF_UNSPEC) {
+                       af = AF_INET;
+               }
+#ifdef HAVE_IPV6
+       } else {
+               struct in6_addr in6;
+
+               af = AF_INET6;
+
+               rc = inet_pton(af, node, &in6);
+               if (rc == 1) {
+                       is_addr_ipv6 = true;
+               }
+#endif
+       }
+
+       if (is_addr_ipv4) {
+               he = nwrap_files_gethostbyaddr(&in, sizeof(struct in_addr), af);
+               if (he != NULL) {
+                       rc = nwrap_convert_he_ai(he, port, hints, &ai);
+               } else {
+                       eai = EAI_NODATA;
+                       rc = -1;
+               }
+#ifdef HAVE_IPV6
+       } else if (is_addr_ipv6) {
+               struct in6_addr in6;
+
+               rc =  inet_pton(af, node, &in6);
+               if (rc <= 0) {
+                       eai = EAI_ADDRFAMILY;
+                       return ret == 0 ? 0 : eai;
+               }
+
+               he = nwrap_files_gethostbyaddr(&in6,
+                                              sizeof(struct in6_addr),
+                                              af);
+               if (he != NULL) {
+                       rc = nwrap_convert_he_ai(he, port, hints, &ai);
+                       eai = rc;
+               } else {
+                       eai = EAI_NODATA;
+                       rc = -1;
+               }
+#endif
+       } else {
+               he = nwrap_files_gethostbyname(node, hints->ai_family);
+               if (he != NULL) {
+                       rc = nwrap_convert_he_ai(he, port, hints, &ai);
+                       eai = rc;
+               } else {
+                       eai = EAI_NODATA;
+                       rc = -1;
+               }
+       }
+
+       if (rc < 0) {
+               return ret == 0 ? 0 : eai;
+       }
+
+       if (ret == 0) {
+               freeaddrinfo(p);
+       }
+
+       if (ai->ai_flags == 0) {
+               ai->ai_flags = hints->ai_flags;
+       }
+       if (ai->ai_socktype == 0) {
+               ai->ai_socktype = SOCK_DGRAM;
+       }
+       if (ai->ai_protocol == 0 && ai->ai_socktype == SOCK_DGRAM) {
+               ai->ai_protocol = 17; /* UDP */
+       } else if (ai->ai_protocol == 0 && ai->ai_socktype == SOCK_STREAM) {
+               ai->ai_protocol = 6; /* TCP */
+       }
+
+       if (hints->ai_socktype == 0) {
+               /* Add second ai */
+               rc = nwrap_convert_he_ai(he, port, hints, &ai->ai_next);
+               if (rc < 0) {
+                       freeaddrinfo(ai);
+                       return rc;
+               }
+
+               if (ai->ai_next->ai_flags == 0) {
+                       ai->ai_next->ai_flags = hints->ai_flags;
+               }
+               if (ai->ai_socktype == SOCK_DGRAM) {
+                       ai->ai_next->ai_socktype = SOCK_STREAM;
+               } else if (ai->ai_socktype == SOCK_STREAM) {
+                       ai->ai_next->ai_socktype = SOCK_DGRAM;
+               }
+               if (ai->ai_next->ai_socktype == SOCK_DGRAM) {
+                       ai->ai_next->ai_protocol = 17; /* UDP */
+               } else if (ai->ai_next->ai_socktype == SOCK_STREAM) {
+                       ai->ai_next->ai_protocol = 6; /* TCP */
+               }
+       }
+
+       *res = ai;
+
+       return 0;
+}
+
+int getaddrinfo(const char *node, const char *service,
+               const struct addrinfo *hints,
+               struct addrinfo **res)
+{
+       if (!nss_wrapper_hosts_enabled()) {
+               return libc_getaddrinfo(node, service, hints, res);
+       }
+
+       return nwrap_getaddrinfo(node, service, hints, res);
+}
+
+static int nwrap_getnameinfo(const struct sockaddr *sa, socklen_t salen,
+                            char *host, size_t hostlen,
+                            char *serv, size_t servlen,
+                            int flags)
+{
+       struct hostent *he;
+       struct servent *service;
+       const char *proto;
+       const void *addr;
+       socklen_t addrlen;
+       uint16_t port;
+       sa_family_t type;
+
+       if (sa == NULL || salen < sizeof(sa_family_t)) {
+               return EAI_FAMILY;
+       }
+
+       if ((flags & NI_NAMEREQD) && host == NULL && serv == NULL) {
+               return EAI_NONAME;
+       }
+
+       type = sa->sa_family;
+       switch (type) {
+               case AF_INET:
+                       if (salen < sizeof(struct sockaddr_in))
+                               return EAI_FAMILY;
+                       addr = &((struct sockaddr_in *)sa)->sin_addr;
+                       addrlen = sizeof(((struct sockaddr_in *)sa)->sin_addr);
+                       port = ntohs(((struct sockaddr_in *)sa)->sin_port);
+                       break;
+#ifdef HAVE_IPV6
+               case AF_INET6:
+                       if (salen < sizeof(struct sockaddr_in6))
+                               return EAI_FAMILY;
+                       addr = &((struct sockaddr_in6 *)sa)->sin6_addr;
+                       addrlen = sizeof(((struct sockaddr_in6 *)sa)->sin6_addr);
+                       port = ntohs(((struct sockaddr_in6 *)sa)->sin6_port);
+                       break;
+#endif
+               default:
+                       return EAI_FAMILY;
+       }
+
+       if (host != NULL) {
+               he = NULL;
+               if ((flags & NI_NUMERICHOST) == 0) {
+                       he = nwrap_files_gethostbyaddr(addr, addrlen, type);
+                       if ((flags & NI_NAMEREQD) && (he == NULL || he->h_name == NULL))
+                               return EAI_NONAME;
+               }
+               if (he != NULL && he->h_name != NULL) {
+                       if (strlen(he->h_name) >= hostlen)
+                               return EAI_OVERFLOW;
+                       strcpy(host, he->h_name);
+                       if (flags & NI_NOFQDN)
+                               host[strcspn(host, ".")] = '\0';
+               } else {
+                       if (inet_ntop(type, addr, host, hostlen) == NULL)
+                               return (errno == ENOSPC) ? EAI_OVERFLOW : EAI_FAIL;
+               }
+       }
+
+       if (serv != NULL) {
+               service = NULL;
+               if ((flags & NI_NUMERICSERV) == 0) {
+                       proto = (flags & NI_DGRAM) ? "udp" : "tcp";
+                       service = getservbyport(htons(port), proto);
+               }
+               if (service != NULL) {
+                       if (strlen(service->s_name) >= servlen)
+                               return EAI_OVERFLOW;
+                       strcpy(serv, service->s_name);
+               } else {
+                       if (snprintf(serv, servlen, "%u", port) >= (int) servlen)
+                               return EAI_OVERFLOW;
+               }
+       }
+
+       return 0;
+}
+
+#ifdef HAVE_LINUX_GETNAMEINFO
+int getnameinfo(const struct sockaddr *sa, socklen_t salen,
+               char *host, socklen_t hostlen,
+               char *serv, socklen_t servlen,
+               int flags)
+#elif defined(HAVE_LINUX_GETNAMEINFO_UNSIGNED)
+int getnameinfo(const struct sockaddr *sa, socklen_t salen,
+               char *host, socklen_t hostlen,
+               char *serv, socklen_t servlen,
+               unsigned int flags)
+#else
+int getnameinfo(const struct sockaddr *sa, socklen_t salen,
+               char *host, size_t hostlen,
+               char *serv, size_t servlen,
+               int flags)
+#endif
+{
+       if (!nss_wrapper_hosts_enabled()) {
+               return libc_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
+       }
+
+       return nwrap_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
+}
+
+static int nwrap_gethostname(char *name, size_t len)
+{
+       const char *hostname = getenv("NSS_WRAPPER_HOSTNAME");
+
+       if (strlen(hostname) >= len) {
+               errno = ENAMETOOLONG;
+               return -1;
+       }
+       snprintf(name, len, "%s", hostname);
+
+       return 0;
+}
+
+#ifdef HAVE_SOLARIS_GETHOSTNAME
+int gethostname(char *name, int len)
+#else /* HAVE_SOLARIS_GETHOSTNAME */
+int gethostname(char *name, size_t len)
+#endif /* HAVE_SOLARIS_GETHOSTNAME */
+{
+       if (!nwrap_hostname_enabled()) {
+               return libc_gethostname(name, len);
+       }
+
+       return nwrap_gethostname(name, len);
+}
+
+/****************************
+ * DESTRUCTOR
+ ***************************/
+
+/*
+ * This function is called when the library is unloaded and makes sure that
+ * sockets get closed and the unix file for the socket are unlinked.
+ */
+void nwrap_destructor(void)
+{
+       int i;
+
+       if (nwrap_main_global != NULL) {
+               struct nwrap_main *m = nwrap_main_global;
+
+               /* libc */
+               SAFE_FREE(m->libc->fns);
+               if (m->libc->handle != NULL) {
+                       dlclose(m->libc->handle);
+               }
+               if (m->libc->nsl_handle != NULL) {
+                       dlclose(m->libc->nsl_handle);
+               }
+               if (m->libc->sock_handle != NULL) {
+                       dlclose(m->libc->sock_handle);
+               }
+               SAFE_FREE(m->libc);
+
+               /* backends */
+               for (i = 0; i < m->num_backends; i++) {
+                       struct nwrap_backend *b = &(m->backends[i]);
+
+                       if (b->so_handle != NULL) {
+                               dlclose(b->so_handle);
+                       }
+                       SAFE_FREE(b->fns);
+               }
+               SAFE_FREE(m->backends);
+       }
+
+       if (nwrap_pw_global.cache != NULL) {
+               struct nwrap_cache *c = nwrap_pw_global.cache;
+
+               nwrap_files_cache_unload(c);
+               if (c->fd >= 0) {
+                       close(c->fd);
+               }
+
+               SAFE_FREE(nwrap_pw_global.list);
+               nwrap_pw_global.num = 0;
+       }
+
+       if (nwrap_gr_global.cache != NULL) {
+               struct nwrap_cache *c = nwrap_gr_global.cache;
+
+               nwrap_files_cache_unload(c);
+               if (c->fd >= 0) {
+                       close(c->fd);
+               }
+
+               SAFE_FREE(nwrap_gr_global.list);
+               nwrap_pw_global.num = 0;
+       }
+
+       if (nwrap_he_global.cache != NULL) {
+               struct nwrap_cache *c = nwrap_he_global.cache;
+
+               nwrap_files_cache_unload(c);
+               if (c->fd >= 0) {
+                       close(c->fd);
+               }
+
+               SAFE_FREE(nwrap_he_global.list);
+               nwrap_he_global.num = 0;
+       }
+}
diff --git a/lib/nss_wrapper/nss_wrapper.h b/lib/nss_wrapper/nss_wrapper.h
deleted file mode 100644 (file)
index 5bcd42e..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) Stefan Metzmacher 2007 <metze@samba.org>
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 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. Neither the name of the author 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 AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef __NSS_WRAPPER_H__
-#define __NSS_WRAPPER_H__
-
-struct passwd *nwrap_getpwnam(const char *name);
-int nwrap_getpwnam_r(const char *name, struct passwd *pwbuf,
-                    char *buf, size_t buflen, struct passwd **pwbufp);
-struct passwd *nwrap_getpwuid(uid_t uid);
-int nwrap_getpwuid_r(uid_t uid, struct passwd *pwbuf,
-                    char *buf, size_t buflen, struct passwd **pwbufp);
-void nwrap_setpwent(void);
-struct passwd *nwrap_getpwent(void);
-int nwrap_getpwent_r(struct passwd *pwbuf, char *buf,
-                    size_t buflen, struct passwd **pwbufp);
-void nwrap_endpwent(void);
-int nwrap_initgroups(const char *user, gid_t group);
-int nwrap_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups);
-struct group *nwrap_getgrnam(const char *name);
-int nwrap_getgrnam_r(const char *name, struct group *gbuf,
-                    char *buf, size_t buflen, struct group **gbufp);
-struct group *nwrap_getgrgid(gid_t gid);
-int nwrap_getgrgid_r(gid_t gid, struct group *gbuf,
-                    char *buf, size_t buflen, struct group **gbufp);
-void nwrap_setgrent(void);
-struct group *nwrap_getgrent(void);
-int nwrap_getgrent_r(struct group *gbuf, char *buf,
-                    size_t buflen, struct group **gbufp);
-void nwrap_endgrent(void);
-
-#ifdef NSS_WRAPPER_REPLACE
-
-#ifdef getpwnam
-#undef getpwnam
-#endif
-#define getpwnam       nwrap_getpwnam
-
-#ifdef getpwnam_r
-#undef getpwnam_r
-#endif
-#define getpwnam_r     nwrap_getpwnam_r
-
-#ifdef getpwuid
-#undef getpwuid
-#endif
-#define getpwuid       nwrap_getpwuid
-
-#ifdef getpwuid_r
-#undef getpwuid_r
-#endif
-#define getpwuid_r     nwrap_getpwuid_r
-
-#ifdef setpwent
-#undef setpwent
-#endif
-#define setpwent       nwrap_setpwent
-
-#ifdef getpwent
-#undef getpwent
-#endif
-#define getpwent       nwrap_getpwent
-
-#ifdef getpwent_r
-#undef getpwent_r
-#endif
-#define getpwent_r     nwrap_getpwent_r
-
-#ifdef endpwent
-#undef endpwent
-#endif
-#define endpwent       nwrap_endpwent
-
-#ifdef getgrlst
-#undef getgrlst
-#endif
-#define getgrlst       __none_nwrap_getgrlst
-
-#ifdef getgrlst_r
-#undef getgrlst_r
-#endif
-#define getgrlst_r     __none_nwrap_getgrlst_r
-
-#ifdef initgroups_dyn
-#undef initgroups_dyn
-#endif
-#define initgroups_dyn __none_nwrap_initgroups_dyn
-
-#ifdef initgroups
-#undef initgroups
-#endif
-#define initgroups     nwrap_initgroups
-
-#ifdef getgrouplist
-#undef getgrouplist
-#endif
-#define getgrouplist   nwrap_getgrouplist
-
-#ifdef getgrnam
-#undef getgrnam
-#endif
-#define getgrnam       nwrap_getgrnam
-
-#ifdef getgrnam_r
-#undef getgrnam_r
-#endif
-#define getgrnam_r     nwrap_getgrnam_r
-
-#ifdef getgrgid
-#undef getgrgid
-#endif
-#define getgrgid       nwrap_getgrgid
-
-#ifdef getgrgid_r
-#undef getgrgid_r
-#endif
-#define getgrgid_r     nwrap_getgrgid_r
-
-#ifdef setgrent
-#undef setgrent
-#endif
-#define setgrent       nwrap_setgrent
-
-#ifdef getgrent
-#undef getgrent
-#endif
-#define getgrent       nwrap_getgrent
-
-#ifdef getgrent_r
-#undef getgrent_r
-#endif
-#define getgrent_r     nwrap_getgrent_r
-
-#ifdef endgrent
-#undef endgrent
-#endif
-#define endgrent       nwrap_endgrent
-
-#endif /* NSS_WRAPPER_REPLACE */
-
-#endif /* __NSS_WRAPPER_H__ */
diff --git a/lib/nss_wrapper/testsuite.c b/lib/nss_wrapper/testsuite.c
deleted file mode 100644 (file)
index 6fae124..0000000
+++ /dev/null
@@ -1,958 +0,0 @@
-/*
-   Unix SMB/CIFS implementation.
-
-   local testing of the nss wrapper
-
-   Copyright (C) Guenther Deschner 2009-2010
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-
-#ifndef NSS_WRAPPER
-#define NSS_WRAPPER
-#endif
-
-#include "torture/torture.h"
-#include "torture/local/proto.h"
-#include "lib/replace/system/passwd.h"
-
-static bool copy_passwd(struct torture_context *tctx,
-                       const struct passwd *pwd,
-                       struct passwd *p)
-{
-       p->pw_name      = talloc_strdup(tctx, pwd->pw_name);
-       p->pw_passwd    = talloc_strdup(tctx, pwd->pw_passwd);
-       p->pw_uid       = pwd->pw_uid;
-       p->pw_gid       = pwd->pw_gid;
-       p->pw_gecos     = talloc_strdup(tctx, pwd->pw_gecos);
-       p->pw_dir       = talloc_strdup(tctx, pwd->pw_dir);
-       p->pw_shell     = talloc_strdup(tctx, pwd->pw_shell);
-
-       return true;
-}
-
-static void print_passwd(struct passwd *pwd)
-{
-       printf("%s:%s:%lu:%lu:%s:%s:%s\n",
-              pwd->pw_name,
-              pwd->pw_passwd,
-              (unsigned long)pwd->pw_uid,
-              (unsigned long)pwd->pw_gid,
-              pwd->pw_gecos,
-              pwd->pw_dir,
-              pwd->pw_shell);
-}
-
-
-static bool test_nwrap_getpwnam(struct torture_context *tctx,
-                               const char *name,
-                               struct passwd *pwd_p)
-{
-       struct passwd *pwd;
-
-       torture_comment(tctx, "Testing getpwnam: %s\n", name);
-
-       pwd = getpwnam(name);
-       if (pwd) {
-               print_passwd(pwd);
-       }
-
-       if (pwd_p) {
-               copy_passwd(tctx, pwd, pwd_p);
-       }
-
-       return pwd ? true : false;
-}
-
-static bool test_nwrap_getpwnam_r(struct torture_context *tctx,
-                                 const char *name,
-                                 struct passwd *pwd_p)
-{
-       struct passwd pwd, *pwdp;
-       char buffer[4096];
-       int ret;
-
-       torture_comment(tctx, "Testing getpwnam_r: %s\n", name);
-
-       ret = getpwnam_r(name, &pwd, buffer, sizeof(buffer), &pwdp);
-       if (ret != 0) {
-               if (ret != ENOENT) {
-                       torture_comment(tctx, "got %d return code\n", ret);
-               }
-               return false;
-       }
-
-       print_passwd(&pwd);
-
-       if (pwd_p) {
-               copy_passwd(tctx, &pwd, pwd_p);
-       }
-
-       return true;
-}
-
-static bool test_nwrap_getpwuid(struct torture_context *tctx,
-                               uid_t uid,
-                               struct passwd *pwd_p)
-{
-       struct passwd *pwd;
-
-       torture_comment(tctx, "Testing getpwuid: %lu\n", (unsigned long)uid);
-
-       pwd = getpwuid(uid);
-       if (pwd) {
-               print_passwd(pwd);
-       }
-
-       if (pwd_p) {
-               copy_passwd(tctx, pwd, pwd_p);
-       }
-
-       return pwd ? true : false;
-}
-
-static bool test_nwrap_getpwuid_r(struct torture_context *tctx,
-                                 uid_t uid,
-                                 struct passwd *pwd_p)
-{
-       struct passwd pwd, *pwdp;
-       char buffer[4096];
-       int ret;
-
-       torture_comment(tctx, "Testing getpwuid_r: %lu\n", (unsigned long)uid);
-
-       ret = getpwuid_r(uid, &pwd, buffer, sizeof(buffer), &pwdp);
-       if (ret != 0) {
-               if (ret != ENOENT) {
-                       torture_comment(tctx, "got %d return code\n", ret);
-               }
-               return false;
-       }
-
-       print_passwd(&pwd);
-
-       if (pwd_p) {
-               copy_passwd(tctx, &pwd, pwd_p);
-       }
-
-       return true;
-}
-
-
-static bool copy_group(struct torture_context *tctx,
-                      const struct group *grp,
-                      struct group *g)
-{
-       int i;
-
-       g->gr_name      = talloc_strdup(tctx, grp->gr_name);
-       g->gr_passwd    = talloc_strdup(tctx, grp->gr_passwd);
-       g->gr_gid       = grp->gr_gid;
-       g->gr_mem       = NULL;
-
-       for (i=0; grp->gr_mem && grp->gr_mem[i]; i++) {
-               g->gr_mem = talloc_realloc(tctx, g->gr_mem, char *, i + 2);
-               g->gr_mem[i] = talloc_strdup(g->gr_mem, grp->gr_mem[i]);
-               g->gr_mem[i+1] = NULL;
-       }
-
-       return true;
-}
-
-static void print_group(struct group *grp)
-{
-       int i;
-       printf("%s:%s:%lu:",
-              grp->gr_name,
-              grp->gr_passwd,
-              (unsigned long)grp->gr_gid);
-
-       if ((grp->gr_mem == NULL) || !grp->gr_mem[0]) {
-               printf("\n");
-               return;
-       }
-
-       for (i=0; grp->gr_mem[i+1]; i++) {
-               printf("%s,", grp->gr_mem[i]);
-       }
-       printf("%s\n", grp->gr_mem[i]);
-}
-
-static bool test_nwrap_getgrnam(struct torture_context *tctx,
-                               const char *name,
-                               struct group *grp_p)
-{
-       struct group *grp;
-
-       torture_comment(tctx, "Testing getgrnam: %s\n", name);
-
-       grp = getgrnam(name);
-       if (grp) {
-               print_group(grp);
-       }
-
-       if (grp_p) {
-               copy_group(tctx, grp, grp_p);
-       }
-
-       return grp ? true : false;
-}
-
-static bool test_nwrap_getgrnam_r(struct torture_context *tctx,
-                                 const char *name,
-                                 struct group *grp_p)
-{
-       struct group grp, *grpp;
-       char buffer[4096];
-       int ret;
-
-       torture_comment(tctx, "Testing getgrnam_r: %s\n", name);
-
-       ret = getgrnam_r(name, &grp, buffer, sizeof(buffer), &grpp);
-       if (ret != 0) {
-               if (ret != ENOENT) {
-                       torture_comment(tctx, "got %d return code\n", ret);
-               }
-               return false;
-       }
-
-       print_group(&grp);
-
-       if (grp_p) {
-               copy_group(tctx, &grp, grp_p);
-       }
-
-       return true;
-}
-
-
-static bool test_nwrap_getgrgid(struct torture_context *tctx,
-                               gid_t gid,
-                               struct group *grp_p)
-{
-       struct group *grp;
-
-       torture_comment(tctx, "Testing getgrgid: %lu\n", (unsigned long)gid);
-
-       grp = getgrgid(gid);
-       if (grp) {
-               print_group(grp);
-       }
-
-       if (grp_p) {
-               copy_group(tctx, grp, grp_p);
-       }
-
-       return grp ? true : false;
-}
-
-static bool test_nwrap_getgrgid_r(struct torture_context *tctx,
-                                 gid_t gid,
-                                 struct group *grp_p)
-{
-       struct group grp, *grpp;
-       char buffer[4096];
-       int ret;
-
-       torture_comment(tctx, "Testing getgrgid_r: %lu\n", (unsigned long)gid);
-
-       ret = getgrgid_r(gid, &grp, buffer, sizeof(buffer), &grpp);
-       if (ret != 0) {
-               if (ret != ENOENT) {
-                       torture_comment(tctx, "got %d return code\n", ret);
-               }
-               return false;
-       }
-
-       print_group(&grp);
-
-       if (grp_p) {
-               copy_group(tctx, &grp, grp_p);
-       }
-
-       return true;
-}
-
-static bool test_nwrap_enum_passwd(struct torture_context *tctx,
-                                  struct passwd **pwd_array_p,
-                                  size_t *num_pwd_p)
-{
-       struct passwd *pwd;
-       struct passwd *pwd_array = NULL;
-       size_t num_pwd = 0;
-
-       torture_comment(tctx, "Testing setpwent\n");
-       setpwent();
-
-       while ((pwd = getpwent()) != NULL) {
-               torture_comment(tctx, "Testing getpwent\n");
-
-               print_passwd(pwd);
-               if (pwd_array_p && num_pwd_p) {
-                       pwd_array = talloc_realloc(tctx, pwd_array, struct passwd, num_pwd+1);
-                       torture_assert(tctx, pwd_array, "out of memory");
-                       copy_passwd(tctx, pwd, &pwd_array[num_pwd]);
-                       num_pwd++;
-               }
-       }
-
-       torture_comment(tctx, "Testing endpwent\n");
-       endpwent();
-
-       if (pwd_array_p) {
-               *pwd_array_p = pwd_array;
-       }
-       if (num_pwd_p) {
-               *num_pwd_p = num_pwd;
-       }
-
-       return true;
-}
-
-static bool test_nwrap_enum_r_passwd(struct torture_context *tctx,
-                                    struct passwd **pwd_array_p,
-                                    size_t *num_pwd_p)
-{
-       struct passwd pwd, *pwdp;
-       struct passwd *pwd_array = NULL;
-       size_t num_pwd = 0;
-       char buffer[4096];
-       int ret;
-
-       torture_comment(tctx, "Testing setpwent\n");
-       setpwent();
-
-       while (1) {
-               torture_comment(tctx, "Testing getpwent_r\n");
-
-               ret = getpwent_r(&pwd, buffer, sizeof(buffer), &pwdp);
-               if (ret != 0) {
-                       if (ret != ENOENT) {
-                               torture_comment(tctx, "got %d return code\n", ret);
-                       }
-                       break;
-               }
-               print_passwd(&pwd);
-               if (pwd_array_p && num_pwd_p) {
-                       pwd_array = talloc_realloc(tctx, pwd_array, struct passwd, num_pwd+1);
-                       torture_assert(tctx, pwd_array, "out of memory");
-                       copy_passwd(tctx, &pwd, &pwd_array[num_pwd]);
-                       num_pwd++;
-               }
-       }
-
-       torture_comment(tctx, "Testing endpwent\n");
-       endpwent();
-
-       if (pwd_array_p) {
-               *pwd_array_p = pwd_array;
-       }
-       if (num_pwd_p) {
-               *num_pwd_p = num_pwd;
-       }
-
-       return true;
-}
-
-static bool torture_assert_passwd_equal(struct torture_context *tctx,
-                                       const struct passwd *p1,
-                                       const struct passwd *p2,
-                                       const char *comment)
-{
-       torture_assert_str_equal(tctx, p1->pw_name, p2->pw_name, comment);
-       torture_assert_str_equal(tctx, p1->pw_passwd, p2->pw_passwd, comment);
-       torture_assert_int_equal(tctx, p1->pw_uid, p2->pw_uid, comment);
-       torture_assert_int_equal(tctx, p1->pw_gid, p2->pw_gid, comment);
-       torture_assert_str_equal(tctx, p1->pw_gecos, p2->pw_gecos, comment);
-       torture_assert_str_equal(tctx, p1->pw_dir, p2->pw_dir, comment);
-       torture_assert_str_equal(tctx, p1->pw_shell, p2->pw_shell, comment);
-
-       return true;
-}
-
-static bool test_nwrap_passwd(struct torture_context *tctx)
-{
-       int i;
-       struct passwd *pwd, pwd1, pwd2;
-       size_t num_pwd;
-
-       torture_assert(tctx, test_nwrap_enum_passwd(tctx, &pwd, &num_pwd),
-                                                   "failed to enumerate passwd");
-
-       for (i=0; i < num_pwd; i++) {
-               torture_assert(tctx, test_nwrap_getpwnam(tctx, pwd[i].pw_name, &pwd1),
-                       "failed to call getpwnam for enumerated user");
-               torture_assert_passwd_equal(tctx, &pwd[i], &pwd1,
-                       "getpwent and getpwnam gave different results");
-               torture_assert(tctx, test_nwrap_getpwuid(tctx, pwd[i].pw_uid, &pwd2),
-                       "failed to call getpwuid for enumerated user");
-               torture_assert_passwd_equal(tctx, &pwd[i], &pwd2,
-                       "getpwent and getpwuid gave different results");
-               torture_assert_passwd_equal(tctx, &pwd1, &pwd2,
-                       "getpwnam and getpwuid gave different results");
-       }
-
-       return true;
-}
-
-static bool test_nwrap_passwd_r(struct torture_context *tctx)
-{
-       int i;
-       struct passwd *pwd, pwd1, pwd2;
-       size_t num_pwd;
-
-       torture_assert(tctx, test_nwrap_enum_r_passwd(tctx, &pwd, &num_pwd),
-                                                     "failed to enumerate passwd");
-
-       for (i=0; i < num_pwd; i++) {
-               torture_assert(tctx, test_nwrap_getpwnam_r(tctx, pwd[i].pw_name, &pwd1),
-                       "failed to call getpwnam_r for enumerated user");
-               torture_assert_passwd_equal(tctx, &pwd[i], &pwd1,
-                       "getpwent_r and getpwnam_r gave different results");
-               torture_assert(tctx, test_nwrap_getpwuid_r(tctx, pwd[i].pw_uid, &pwd2),
-                       "failed to call getpwuid_r for enumerated user");
-               torture_assert_passwd_equal(tctx, &pwd[i], &pwd2,
-                       "getpwent_r and getpwuid_r gave different results");
-               torture_assert_passwd_equal(tctx, &pwd1, &pwd2,
-                       "getpwnam_r and getpwuid_r gave different results");
-       }
-
-       return true;
-}
-
-static bool test_nwrap_passwd_r_cross(struct torture_context *tctx)
-{
-       int i;
-       struct passwd *pwd, pwd1, pwd2, pwd3, pwd4;
-       size_t num_pwd;
-
-       torture_assert(tctx, test_nwrap_enum_r_passwd(tctx, &pwd, &num_pwd),
-                                                     "failed to enumerate passwd");
-
-       for (i=0; i < num_pwd; i++) {
-               torture_assert(tctx, test_nwrap_getpwnam_r(tctx, pwd[i].pw_name, &pwd1),
-                       "failed to call getpwnam_r for enumerated user");
-               torture_assert_passwd_equal(tctx, &pwd[i], &pwd1,
-                       "getpwent_r and getpwnam_r gave different results");
-               torture_assert(tctx, test_nwrap_getpwuid_r(tctx, pwd[i].pw_uid, &pwd2),
-                       "failed to call getpwuid_r for enumerated user");
-               torture_assert_passwd_equal(tctx, &pwd[i], &pwd2,
-                       "getpwent_r and getpwuid_r gave different results");
-               torture_assert_passwd_equal(tctx, &pwd1, &pwd2,
-                       "getpwnam_r and getpwuid_r gave different results");
-               torture_assert(tctx, test_nwrap_getpwnam(tctx, pwd[i].pw_name, &pwd3),
-                       "failed to call getpwnam for enumerated user");
-               torture_assert_passwd_equal(tctx, &pwd[i], &pwd3,
-                       "getpwent_r and getpwnam gave different results");
-               torture_assert(tctx, test_nwrap_getpwuid(tctx, pwd[i].pw_uid, &pwd4),
-                       "failed to call getpwuid for enumerated user");
-               torture_assert_passwd_equal(tctx, &pwd[i], &pwd4,
-                       "getpwent_r and getpwuid gave different results");
-               torture_assert_passwd_equal(tctx, &pwd3, &pwd4,
-                       "getpwnam and getpwuid gave different results");
-       }
-
-       return true;
-}
-
-static bool test_nwrap_enum_group(struct torture_context *tctx,
-                                 struct group **grp_array_p,
-                                 size_t *num_grp_p)
-{
-       struct group *grp;
-       struct group *grp_array = NULL;
-       size_t num_grp = 0;
-
-       torture_comment(tctx, "Testing setgrent\n");
-       setgrent();
-
-       while ((grp = getgrent()) != NULL) {
-               torture_comment(tctx, "Testing getgrent\n");
-
-               print_group(grp);
-               if (grp_array_p && num_grp_p) {
-                       grp_array = talloc_realloc(tctx, grp_array, struct group, num_grp+1);
-                       torture_assert(tctx, grp_array, "out of memory");
-                       copy_group(tctx, grp, &grp_array[num_grp]);
-                       num_grp++;
-               }
-       }
-
-       torture_comment(tctx, "Testing endgrent\n");
-       endgrent();
-
-       if (grp_array_p) {
-               *grp_array_p = grp_array;
-       }
-       if (num_grp_p) {
-               *num_grp_p = num_grp;
-       }
-
-       return true;
-}
-
-static bool test_nwrap_enum_r_group(struct torture_context *tctx,
-                                   struct group **grp_array_p,
-                                   size_t *num_grp_p)
-{
-       struct group grp, *grpp;
-       struct group *grp_array = NULL;
-       size_t num_grp = 0;
-       char buffer[4096];
-       int ret;
-
-       torture_comment(tctx, "Testing setgrent\n");
-       setgrent();
-
-       while (1) {
-               torture_comment(tctx, "Testing getgrent_r\n");
-
-               ret = getgrent_r(&grp, buffer, sizeof(buffer), &grpp);
-               if (ret != 0) {
-                       if (ret != ENOENT) {
-                               torture_comment(tctx, "got %d return code\n", ret);
-                       }
-                       break;
-               }
-               print_group(&grp);
-               if (grp_array_p && num_grp_p) {
-                       grp_array = talloc_realloc(tctx, grp_array, struct group, num_grp+1);
-                       torture_assert(tctx, grp_array, "out of memory");
-                       copy_group(tctx, &grp, &grp_array[num_grp]);
-                       num_grp++;
-               }
-       }
-
-       torture_comment(tctx, "Testing endgrent\n");
-       endgrent();
-
-       if (grp_array_p) {
-               *grp_array_p = grp_array;
-       }
-       if (num_grp_p) {
-               *num_grp_p = num_grp;
-       }
-
-       return true;
-}
-
-static bool torture_assert_group_equal(struct torture_context *tctx,
-                                      const struct group *g1,
-                                      const struct group *g2,
-                                      const char *comment)
-{
-       int i;
-       torture_assert_str_equal(tctx, g1->gr_name, g2->gr_name, comment);
-       torture_assert_str_equal(tctx, g1->gr_passwd, g2->gr_passwd, comment);
-       torture_assert_int_equal(tctx, g1->gr_gid, g2->gr_gid, comment);
-       if (g1->gr_mem && !g2->gr_mem) {
-               return false;
-       }
-       if (!g1->gr_mem && g2->gr_mem) {
-               return false;
-       }
-       if (!g1->gr_mem && !g2->gr_mem) {
-               return true;
-       }
-       for (i=0; g1->gr_mem[i] && g2->gr_mem[i]; i++) {
-               torture_assert_str_equal(tctx, g1->gr_mem[i], g2->gr_mem[i], comment);
-       }
-
-       return true;
-}
-
-static bool test_nwrap_group(struct torture_context *tctx)
-{
-       int i;
-       struct group *grp, grp1, grp2;
-       size_t num_grp;
-
-       torture_assert(tctx, test_nwrap_enum_group(tctx, &grp, &num_grp),
-                                                  "failed to enumerate group");
-
-       for (i=0; i < num_grp; i++) {
-               torture_assert(tctx, test_nwrap_getgrnam(tctx, grp[i].gr_name, &grp1),
-                       "failed to call getgrnam for enumerated user");
-               torture_assert_group_equal(tctx, &grp[i], &grp1,
-                       "getgrent and getgrnam gave different results");
-               torture_assert(tctx, test_nwrap_getgrgid(tctx, grp[i].gr_gid, &grp2),
-                       "failed to call getgrgid for enumerated user");
-               torture_assert_group_equal(tctx, &grp[i], &grp2,
-                       "getgrent and getgrgid gave different results");
-               torture_assert_group_equal(tctx, &grp1, &grp2,
-                       "getgrnam and getgrgid gave different results");
-       }
-
-       return true;
-}
-
-static bool test_nwrap_group_r(struct torture_context *tctx)
-{
-       int i;
-       struct group *grp, grp1, grp2;
-       size_t num_grp;
-
-       torture_assert(tctx, test_nwrap_enum_r_group(tctx, &grp, &num_grp),
-                                                    "failed to enumerate group");
-
-       for (i=0; i < num_grp; i++) {
-               torture_assert(tctx, test_nwrap_getgrnam_r(tctx, grp[i].gr_name, &grp1),
-                       "failed to call getgrnam_r for enumerated user");
-               torture_assert_group_equal(tctx, &grp[i], &grp1,
-                       "getgrent_r and getgrnam_r gave different results");
-               torture_assert(tctx, test_nwrap_getgrgid_r(tctx, grp[i].gr_gid, &grp2),
-                       "failed to call getgrgid_r for enumerated user");
-               torture_assert_group_equal(tctx, &grp[i], &grp2,
-                       "getgrent_r and getgrgid_r gave different results");
-               torture_assert_group_equal(tctx, &grp1, &grp2,
-                       "getgrnam_r and getgrgid_r gave different results");
-       }
-
-       return true;
-}
-
-static bool test_nwrap_group_r_cross(struct torture_context *tctx)
-{
-       int i;
-       struct group *grp, grp1, grp2, grp3, grp4;
-       size_t num_grp;
-
-       torture_assert(tctx, test_nwrap_enum_r_group(tctx, &grp, &num_grp),
-                                                    "failed to enumerate group");
-
-       for (i=0; i < num_grp; i++) {
-               torture_assert(tctx, test_nwrap_getgrnam_r(tctx, grp[i].gr_name, &grp1),
-                       "failed to call getgrnam_r for enumerated user");
-               torture_assert_group_equal(tctx, &grp[i], &grp1,
-                       "getgrent_r and getgrnam_r gave different results");
-               torture_assert(tctx, test_nwrap_getgrgid_r(tctx, grp[i].gr_gid, &grp2),
-                       "failed to call getgrgid_r for enumerated user");
-               torture_assert_group_equal(tctx, &grp[i], &grp2,
-                       "getgrent_r and getgrgid_r gave different results");
-               torture_assert_group_equal(tctx, &grp1, &grp2,
-                       "getgrnam_r and getgrgid_r gave different results");
-               torture_assert(tctx, test_nwrap_getgrnam(tctx, grp[i].gr_name, &grp3),
-                       "failed to call getgrnam for enumerated user");
-               torture_assert_group_equal(tctx, &grp[i], &grp3,
-                       "getgrent_r and getgrnam gave different results");
-               torture_assert(tctx, test_nwrap_getgrgid(tctx, grp[i].gr_gid, &grp4),
-                       "failed to call getgrgid for enumerated user");
-               torture_assert_group_equal(tctx, &grp[i], &grp4,
-                       "getgrent_r and getgrgid gave different results");
-               torture_assert_group_equal(tctx, &grp3, &grp4,
-                       "getgrnam and getgrgid gave different results");
-       }
-
-       return true;
-}
-
-static bool test_nwrap_getgrouplist(struct torture_context *tctx,
-                                   const char *user,
-                                   gid_t gid,
-                                   gid_t **gids_p,
-                                   int *num_gids_p)
-{
-       int ret;
-       int num_groups = 0;
-       gid_t *groups = NULL;
-
-       torture_comment(tctx, "Testing getgrouplist: %s\n", user);
-
-       ret = getgrouplist(user, gid, NULL, &num_groups);
-       if (ret == -1 || num_groups != 0) {
-
-               groups = talloc_array(tctx, gid_t, num_groups);
-               torture_assert(tctx, groups, "out of memory\n");
-
-               ret = getgrouplist(user, gid, groups, &num_groups);
-       }
-
-       torture_assert(tctx, (ret != -1), "failed to call getgrouplist");
-
-       torture_comment(tctx, "%s is member in %d groups\n", user, num_groups);
-
-       if (gids_p) {
-               *gids_p = groups;
-       }
-       if (num_gids_p) {
-               *num_gids_p = num_groups;
-       }
-
-       return true;
-}
-
-static bool test_nwrap_user_in_group(struct torture_context *tctx,
-                                    const struct passwd *pwd,
-                                    const struct group *grp)
-{
-       int i;
-
-       for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) {
-               if (strequal(grp->gr_mem[i], pwd->pw_name)) {
-                       return true;
-               }
-       }
-
-       return false;
-}
-
-static bool test_nwrap_membership_user(struct torture_context *tctx,
-                                      const struct passwd *pwd,
-                                      struct group *grp_array,
-                                      size_t num_grp)
-{
-       int num_user_groups = 0;
-       int num_user_groups_from_enum = 0;
-       gid_t *user_groups = NULL;
-       int g, i;
-       bool primary_group_had_user_member = false;
-
-       torture_assert(tctx, test_nwrap_getgrouplist(tctx,
-                                                    pwd->pw_name,
-                                                    pwd->pw_gid,
-                                                    &user_groups,
-                                                    &num_user_groups),
-                                                    "failed to test getgrouplist");
-
-       for (g=0; g < num_user_groups; g++) {
-               torture_assert(tctx, test_nwrap_getgrgid(tctx, user_groups[g], NULL),
-                       "failed to find the group the user is a member of");
-       }
-
-
-       for (i=0; i < num_grp; i++) {
-
-               struct group grp = grp_array[i];
-
-               if (test_nwrap_user_in_group(tctx, pwd, &grp)) {
-
-                       struct group current_grp;
-                       num_user_groups_from_enum++;
-
-                       torture_assert(tctx, test_nwrap_getgrnam(tctx, grp.gr_name, &current_grp),
-                                       "failed to find the group the user is a member of");
-
-                       if (current_grp.gr_gid == pwd->pw_gid) {
-                               torture_comment(tctx, "primary group %s of user %s lists user as member\n",
-                                               current_grp.gr_name,
-                                               pwd->pw_name);
-                               primary_group_had_user_member = true;
-                       }
-
-                       continue;
-               }
-       }
-
-       if (!primary_group_had_user_member) {
-               num_user_groups_from_enum++;
-       }
-
-       torture_assert_int_equal(tctx, num_user_groups, num_user_groups_from_enum,
-               "getgrouplist and real inspection of grouplist gave different results\n");
-
-       return true;
-}
-
-static bool test_nwrap_membership(struct torture_context *tctx)
-{
-       const char *old_pwd = getenv("NSS_WRAPPER_PASSWD");
-       const char *old_group = getenv("NSS_WRAPPER_GROUP");
-       struct passwd *pwd;
-       size_t num_pwd;
-       struct group *grp;
-       size_t num_grp;
-       int i;
-
-       if (!old_pwd || !old_group) {
-               torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n");
-               torture_skip(tctx, "nothing to test\n");
-       }
-
-       torture_assert(tctx, test_nwrap_enum_passwd(tctx, &pwd, &num_pwd),
-                                                   "failed to enumerate passwd");
-       torture_assert(tctx, test_nwrap_enum_group(tctx, &grp, &num_grp),
-                                                   "failed to enumerate group");
-
-       for (i=0; i < num_pwd; i++) {
-
-               torture_assert(tctx, test_nwrap_membership_user(tctx, &pwd[i], grp, num_grp),
-                       "failed to test membership for user");
-
-       }
-
-       return true;
-}
-
-static bool test_nwrap_enumeration(struct torture_context *tctx)
-{
-       const char *old_pwd = getenv("NSS_WRAPPER_PASSWD");
-       const char *old_group = getenv("NSS_WRAPPER_GROUP");
-
-       if (!old_pwd || !old_group) {
-               torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n");
-               torture_skip(tctx, "nothing to test\n");
-       }
-
-       torture_assert(tctx, test_nwrap_passwd(tctx),
-                       "failed to test users");
-       torture_assert(tctx, test_nwrap_group(tctx),
-                       "failed to test groups");
-
-       return true;
-}
-
-static bool test_nwrap_reentrant_enumeration(struct torture_context *tctx)
-{
-       const char *old_pwd = getenv("NSS_WRAPPER_PASSWD");
-       const char *old_group = getenv("NSS_WRAPPER_GROUP");
-
-       if (!old_pwd || !old_group) {
-               torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n");
-               torture_skip(tctx, "nothing to test\n");
-       }
-
-       torture_comment(tctx, "Testing re-entrant calls\n");
-
-       torture_assert(tctx, test_nwrap_passwd_r(tctx),
-                       "failed to test users");
-       torture_assert(tctx, test_nwrap_group_r(tctx),
-                       "failed to test groups");
-
-       return true;
-}
-
-static bool test_nwrap_reentrant_enumeration_crosschecks(struct torture_context *tctx)
-{
-       const char *old_pwd = getenv("NSS_WRAPPER_PASSWD");
-       const char *old_group = getenv("NSS_WRAPPER_GROUP");
-
-       if (!old_pwd || !old_group) {
-               torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n");
-               torture_skip(tctx, "nothing to test\n");
-       }
-
-       torture_comment(tctx, "Testing re-entrant calls with cross checks\n");
-
-       torture_assert(tctx, test_nwrap_passwd_r_cross(tctx),
-                       "failed to test users");
-       torture_assert(tctx, test_nwrap_group_r_cross(tctx),
-                       "failed to test groups");
-
-       return true;
-}
-
-static bool test_nwrap_passwd_duplicates(struct torture_context *tctx)
-{
-       int i, d;
-       struct passwd *pwd;
-       size_t num_pwd;
-       int duplicates = 0;
-
-       torture_assert(tctx, test_nwrap_enum_passwd(tctx, &pwd, &num_pwd),
-           "failed to enumerate passwd");
-
-       for (i=0; i < num_pwd; i++) {
-               const char *current_name = pwd[i].pw_name;
-               for (d=0; d < num_pwd; d++) {
-                       const char *dup_name = pwd[d].pw_name;
-                       if (d == i) {
-                               continue;
-                       }
-                       if (!strequal(current_name, dup_name)) {
-                               continue;
-                       }
-
-                       torture_warning(tctx, "found duplicate names:");
-                       print_passwd(&pwd[d]);
-                       print_passwd(&pwd[i]);
-                       duplicates++;
-               }
-       }
-
-       if (duplicates) {
-               torture_fail(tctx, talloc_asprintf(tctx, "found %d duplicate names", duplicates));
-       }
-
-       return true;
-}
-
-static bool test_nwrap_group_duplicates(struct torture_context *tctx)
-{
-       int i, d;
-       struct group *grp;
-       size_t num_grp;
-       int duplicates = 0;
-
-       torture_assert(tctx, test_nwrap_enum_group(tctx, &grp, &num_grp),
-               "failed to enumerate group");
-
-       for (i=0; i < num_grp; i++) {
-               const char *current_name = grp[i].gr_name;
-               for (d=0; d < num_grp; d++) {
-                       const char *dup_name = grp[d].gr_name;
-                       if (d == i) {
-                               continue;
-                       }
-                       if (!strequal(current_name, dup_name)) {
-                               continue;
-                       }
-
-                       torture_warning(tctx, "found duplicate names:");
-                       print_group(&grp[d]);
-                       print_group(&grp[i]);
-                       duplicates++;
-               }
-       }
-
-       if (duplicates) {
-               torture_fail(tctx, talloc_asprintf(tctx, "found %d duplicate names", duplicates));
-       }
-
-       return true;
-}
-
-
-static bool test_nwrap_duplicates(struct torture_context *tctx)
-{
-       const char *old_pwd = getenv("NSS_WRAPPER_PASSWD");
-       const char *old_group = getenv("NSS_WRAPPER_GROUP");
-
-       if (!old_pwd || !old_group) {
-               torture_comment(tctx, "ENV NSS_WRAPPER_PASSWD or NSS_WRAPPER_GROUP not set\n");
-               torture_skip(tctx, "nothing to test\n");
-       }
-
-       torture_assert(tctx, test_nwrap_passwd_duplicates(tctx),
-                       "failed to test users");
-       torture_assert(tctx, test_nwrap_group_duplicates(tctx),
-                       "failed to test groups");
-
-       return true;
-}
-
-
-struct torture_suite *torture_local_nss_wrapper(TALLOC_CTX *mem_ctx)
-{
-       struct torture_suite *suite = torture_suite_create(mem_ctx, "nss-wrapper");
-
-       torture_suite_add_simple_test(suite, "enumeration", test_nwrap_enumeration);
-       torture_suite_add_simple_test(suite, "reentrant enumeration", test_nwrap_reentrant_enumeration);
-       torture_suite_add_simple_test(suite, "reentrant enumeration crosschecks", test_nwrap_reentrant_enumeration_crosschecks);
-       torture_suite_add_simple_test(suite, "membership", test_nwrap_membership);
-       torture_suite_add_simple_test(suite, "duplicates", test_nwrap_duplicates);
-
-       return suite;
-}
index 5cfff1f..34026c0 100644 (file)
 #!/usr/bin/env python
 
-import Options
+import os
 
-def set_options(opt):
-    gr = opt.option_group('developer options')
-    gr.add_option('--enable-nss-wrapper',
-              help=("Turn on nss wrapper library (default=no)"),
-              action="store_true", dest='enable_nss_wrapper', default=False)
+VERSION="1.0.2"
 
 def configure(conf):
-    if (Options.options.enable_nss_wrapper or
-        Options.options.developer or
-        Options.options.enable_selftest):
-        conf.DEFINE('NSS_WRAPPER', 1)
-        conf.ADD_GLOBAL_DEPENDENCY('nss_wrapper')
+    if conf.CHECK_BUNDLED_SYSTEM('nss_wrapper', minversion=VERSION, set_target=False):
+        conf.DEFINE('USING_SYSTEM_NSS_WRAPPER', 1)
+        libnss_wrapper_so_path = 'libnss_wrapper.so'
+    else:
+        # check HAVE_GCC_THREAD_LOCAL_STORAGE
+        conf.CHECK_CODE('''
+            __thread int tls;
 
+            int main(void) {
+                return 0;
+            }
+            ''',
+            'HAVE_GCC_THREAD_LOCAL_STORAGE',
+            addmain=False,
+            msg='Checking for thread local storage')
+
+        # check HAVE_DESTRUCTOR_ATTRIBUTE
+        conf.CHECK_CODE('''
+            void test_destructor_attribute(void) __attribute__ ((destructor));
+
+            void test_destructor_attribute(void)
+            {
+                return;
+            }
+
+            int main(void) {
+                return 0;
+            }
+            ''',
+            'HAVE_DESTRUCTOR_ATTRIBUTE',
+            addmain=False,
+            msg='Checking for library destructor support')
+
+        conf.CHECK_FUNCS('gethostbyaddr_r gethostbyname_r')
+        # Solaris
+        conf.CHECK_FUNCS('__posix_getpwnam_r __posix_getpwuid_r')
+        conf.CHECK_FUNCS('__posix_getgrgid_r __posix_getgrnam_r')
+
+        conf.CHECK_FUNCS_IN('nsl',
+                            'gethostname',
+                            checklibc=True,
+                            headers='unistd.h')
+
+        # Prototype checks
+        conf.CHECK_C_PROTOTYPE('getpwent_r',
+                               'struct passwd *getpwent_r(struct passwd *src, char *buf, int buflen)',
+                               define='HAVE_SOLARIS_GETPWENT_R', headers='unistd.h pwd.h')
+        conf.CHECK_C_PROTOTYPE('getpwnam_r',
+                               'int getpwnam_r(const char *name, struct passwd *pwd, char *buf, int buflen, struct passwd **ppwd)',
+                               define='HAVE_SOLARIS_GETPWNAM_R', headers='unistd.h pwd.h')
+        conf.CHECK_C_PROTOTYPE('getpwuid_r',
+                               'int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, int buflen, struct passwd **ppwd)',
+                               define='HAVE_SOLARIS_GETPWUID_R', headers='unistd.h pwd.h')
+        conf.CHECK_C_PROTOTYPE('getgrent_r',
+                               'struct group *getgrent_r(struct group *src, char *buf, int buflen)',
+                               define='SOLARIS_GETGRENT_R', headers='unistd.h grp.h')
+        conf.CHECK_C_PROTOTYPE('getgrnam_r',
+                               'int getgrnam_r(const char *name, struct group *grp, char *buf, int buflen, struct group **pgrp)',
+                               define='HAVE_SOLARIS_GETGRNAM_R', headers='unistd.h grp.h')
+        conf.CHECK_C_PROTOTYPE('getgrgid_r',
+                               'int getgrgid_r(gid_t gid, struct group *grp, char *buf, int buflen, struct group **pgrp)',
+                               define='HAVE_SOLARIS_GETGRGID_R', headers='unistd.h grp.h')
+        conf.CHECK_C_PROTOTYPE('sethostent',
+                               'int sethostent(int stayopen)',
+                               define='HAVE_SOLARIS_SETHOSTENT', headers='unistd.h netdb.h')
+        conf.CHECK_C_PROTOTYPE('endhostent',
+                               'int endhostent(void)',
+                               define='HAVE_SOLARIS_ENDHOSTENT', headers='unistd.h netdb.h')
+        conf.CHECK_C_PROTOTYPE('gethostname',
+                               'int gethostname(char *name, int len)',
+                               define='HAVE_SOLARIS_GETHOSTNAME', headers='unistd.h netdb.h')
+        conf.CHECK_C_PROTOTYPE('setgrent',
+                               'int setgrent(void)',
+                               define='HAVE_BSD_SETGRENT', headers='unistd.h grp.h')
+        conf.CHECK_C_PROTOTYPE('getnameinfo',
+                               'int getnameinfo (const struct sockaddr *sa, socklen_t salen, char *host, socklen_t __hostlen, char *serv, socklen_t servlen, int flags)',
+                               define='HAVE_LINUX_GETNAMEINFO', headers='unistd.h netdb.h')
+        conf.CHECK_C_PROTOTYPE('getnameinfo',
+                               'int getnameinfo (const struct sockaddr *sa, socklen_t salen, char *host, socklen_t __hostlen, char *serv, socklen_t servlen, unsigned int flags)',
+                               define='HAVE_LINUX_GETNAMEINFO_UNSIGNED', headers='unistd.h netdb.h')
+
+        # Create full path to nss_wrapper
+        srcdir = os.path.realpath(conf.srcdir)
+        libnss_wrapper_so_path = srcdir + '/bin/default/lib/nss_wrapper/libnss-wrapper.so'
+
+    conf.DEFINE('LIBNSS_WRAPPER_SO_PATH', libnss_wrapper_so_path)
+    conf.DEFINE('NSS_WRAPPER', 1)
+
+def build(bld):
+    if not bld.CONFIG_SET("USING_SYSTEM_NSS_WRAPPER"):
+        # We need to do it this way or the library wont work.
+        # Using private_library=True will add symbol version which
+        # breaks preloading!
+        bld.SAMBA_LIBRARY('nss_wrapper',
+                          source='nss_wrapper.c',
+                          cflags='-DNDEBUG',
+                          deps='dl',
+                          install=False,
+                          realname='libnss-wrapper.so')
diff --git a/lib/nss_wrapper/wscript_build b/lib/nss_wrapper/wscript_build
deleted file mode 100644 (file)
index 5f9df3a..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/usr/bin/env python
-
-
-bld.SAMBA_LIBRARY('nss_wrapper',
-                  source='nss_wrapper.c',
-                  deps='replace',
-                  private_library=True,
-                  enabled=bld.CONFIG_SET("NSS_WRAPPER"),
-                  )
-
diff --git a/wscript b/wscript
index 49f0460..fe1e1d4 100644 (file)
--- a/wscript
+++ b/wscript
@@ -40,7 +40,6 @@ def set_options(opt):
     opt.RECURSE('lib/ntdb')
     opt.RECURSE('selftest')
     opt.RECURSE('source4/lib/tls')
-    opt.RECURSE('lib/nss_wrapper')
     opt.RECURSE('lib/socket_wrapper')
     opt.RECURSE('pidl')
     opt.RECURSE('source3')