[PATCHES] nss-wrapper 1.1.2 in samba -- and fixes for samba

Michael Adam obnox at samba.org
Sat Dec 19 12:16:18 UTC 2015


Hi,

Andreas and I recently brought quite an extensive set of
patches (by Andreas, Robin Hack and me) to the nss_wrapper
repository, culimnating in version 1.1.2.

Among other things, 1.1.2 enhances and corrects various
aspects of our implementation of getaddrinfo.

Now the attempt to bring this version 1.1.2 to samba's copy
of nss-wrapper has uncovered a few bugs in the torture
tests, where dns host names were handed in to getaddrinfo
calls with the AI_NUMERICHOST flag set.

Attached find

1) The patchset that fixes the test cases.

   This also includes an addition to tsocket:
   tsocket_address_inet_from_strings_resolve()
   is a variant of
   tsocket_address_inet_from_strings()
   that does not set the AI_NUMERICHOST flag and
   hence allows for dns resolution of the handed
   in addr/name string.

2) The patchset that adds the nss-wrap patches
   leading to version 1.1.2.


All patches do carry sufficient review, but since
one patch touches tsocket, we would like to get
additional review to that one at least (Metze?)

Thanks - Michael
-------------- next part --------------
From 76ffa76ca46ce07d226668d7e67eeb753bfbab88 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 17 Dec 2015 12:49:18 +0100
Subject: [PATCH 1/6] tsocket: add tsocket_address_inet_from_strings_resolve()

Variant of tsocket_address_inet_from_strings() that allows
dns and service names to be handed in and will let getaddrinfo
do name resolution.

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/tsocket/tsocket.h     | 43 +++++++++++++++++++++++++++++++++++++++++++
 lib/tsocket/tsocket_bsd.c | 47 ++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 83 insertions(+), 7 deletions(-)

diff --git a/lib/tsocket/tsocket.h b/lib/tsocket/tsocket.h
index f52b746..5dcaf07 100644
--- a/lib/tsocket/tsocket.h
+++ b/lib/tsocket/tsocket.h
@@ -539,6 +539,49 @@ int _tsocket_address_inet_from_strings(TALLOC_CTX *mem_ctx,
 					   __location__)
 #endif
 
+#if DOXYGEN
+/**
+ * @brief Create a tsocket_address for ipv4 and ipv6 endpoint addresses.
+ *
+ * This is a variant of the tsocket_address_inet_from_strings()
+ * function that allows for resolving of the handed in node
+ * string from name to address.
+ *
+ * @param[in]  mem_ctx  The talloc memory context to use.
+ *
+ * @param[in]  fam      The family can be can be "ipv4", "ipv6" or "ip". With
+ *                      "ip" is autodetects "ipv4" or "ipv6" based on the
+ *                      addr.
+ *
+ * @param[in]  addr     A valid ip address string based on the selected family.
+ *                      dns names are allowed. It's valid to pass NULL,
+ *                      which gets mapped to "0.0.0.0" or "::".
+ *
+ * @param[in]  port     A valid port number or service name.
+ *
+ * @param[out] _addr    A tsocket_address pointer to store the information.
+ *
+ * @return              0 on success, -1 on error with errno set.
+ */
+int tsocket_address_inet_from_strings_resolve(TALLOC_CTX *mem_ctx,
+					      const char *fam,
+					      const char *addr,
+					      uint16_t port,
+					      struct tsocket_address **_addr);
+#else
+int _tsocket_address_inet_from_strings_resolve(TALLOC_CTX *mem_ctx,
+					       const char *fam,
+					       const char *addr,
+					       uint16_t port,
+					       struct tsocket_address **_addr,
+					       const char *location);
+
+#define tsocket_address_inet_from_strings_resolve(mem_ctx, fam, addr, port, \
+						  _addr) \
+	_tsocket_address_inet_from_strings_resolve(mem_ctx, fam, addr, port, \
+						   _addr, __location__)
+#endif
+
 /**
  * @brief Get the address of an 'inet' tsocket_address as a string.
  *
diff --git a/lib/tsocket/tsocket_bsd.c b/lib/tsocket/tsocket_bsd.c
index ac0617d..d3aad77 100644
--- a/lib/tsocket/tsocket_bsd.c
+++ b/lib/tsocket/tsocket_bsd.c
@@ -322,12 +322,13 @@ bool tsocket_address_is_inet(const struct tsocket_address *addr, const char *fam
 	return false;
 }
 
-int _tsocket_address_inet_from_strings(TALLOC_CTX *mem_ctx,
-				       const char *fam,
-				       const char *addr,
-				       uint16_t port,
-				       struct tsocket_address **_addr,
-				       const char *location)
+static int _tsocket_address_inet_from_strings_ext(TALLOC_CTX *mem_ctx,
+						const char *fam,
+						const char *addr,
+						uint16_t port,
+						int ai_flags,
+						struct tsocket_address **_addr,
+						const char *location)
 {
 	struct addrinfo hints;
 	struct addrinfo *result = NULL;
@@ -340,7 +341,7 @@ int _tsocket_address_inet_from_strings(TALLOC_CTX *mem_ctx,
 	 * back from getaddrinfo().
 	 */
 	hints.ai_socktype = SOCK_STREAM;
-	hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
+	hints.ai_flags = ai_flags;
 
 	if (strcasecmp(fam, "ip") == 0) {
 		hints.ai_family = AF_UNSPEC;
@@ -400,6 +401,38 @@ done:
 	return ret;
 }
 
+int _tsocket_address_inet_from_strings(TALLOC_CTX *mem_ctx,
+				       const char *fam,
+				       const char *addr,
+				       uint16_t port,
+				       struct tsocket_address **_addr,
+				       const char *location)
+{
+	int ret;
+	int ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
+
+	ret = _tsocket_address_inet_from_strings_ext(mem_ctx, fam, addr, port,
+						ai_flags, _addr, location);
+
+	return ret;
+}
+
+int _tsocket_address_inet_from_strings_resolve(TALLOC_CTX *mem_ctx,
+					       const char *fam,
+					       const char *addr,
+					       uint16_t port,
+					       struct tsocket_address **_addr,
+					       const char *location)
+{
+	int ret;
+	int ai_flags = 0;
+
+	ret = _tsocket_address_inet_from_strings_ext(mem_ctx, fam, addr, port,
+						ai_flags, _addr, location);
+
+	return ret;
+}
+
 char *tsocket_address_inet_addr_string(const struct tsocket_address *addr,
 				       TALLOC_CTX *mem_ctx)
 {
-- 
2.5.0


From c99a9c95b286cf5b2443e6870a66603846aac853 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 17 Dec 2015 13:56:16 +0100
Subject: [PATCH 2/6] torture: use tsocket_address_inet_from_strings_resolve()
 in the ldap:cldpa test

This is so a host*NAME* handed in will get properly resolved.
Bug uncovered by the new nss_wrapper code (1.1.2).

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 source4/torture/ldap/cldap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source4/torture/ldap/cldap.c b/source4/torture/ldap/cldap.c
index 6a925cf..ea66111 100644
--- a/source4/torture/ldap/cldap.c
+++ b/source4/torture/ldap/cldap.c
@@ -89,7 +89,7 @@ static bool test_cldap_generic(struct torture_context *tctx, const char *dest)
 	struct tsocket_address *dest_addr;
 	int ret;
 
-	ret = tsocket_address_inet_from_strings(tctx, "ip",
+	ret = tsocket_address_inet_from_strings_resolve(tctx, "ip",
 						dest,
 						lpcfg_cldap_port(tctx->lp_ctx),
 						&dest_addr);
-- 
2.5.0


From 0a97e60bae53b293b97a39c303052ea0c4b47532 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 17 Dec 2015 13:58:12 +0100
Subject: [PATCH 3/6] torture: use tsocket_address_inet_from_strings_resolve()
 in the ldap:netlogon test

This is so a host*NAME* handed in will get properly resolved.
Bug uncovered by the new nss_wrapper code (1.1.2).

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 source4/torture/ldap/netlogon.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/source4/torture/ldap/netlogon.c b/source4/torture/ldap/netlogon.c
index d632aaf..cd87962 100644
--- a/source4/torture/ldap/netlogon.c
+++ b/source4/torture/ldap/netlogon.c
@@ -585,10 +585,10 @@ bool torture_netlogon_udp(struct torture_context *tctx)
 	NTSTATUS status;
 	struct tsocket_address *dest_addr;
 
-	r = tsocket_address_inet_from_strings(tctx, "ip",
-					      host,
-					      lpcfg_cldap_port(tctx->lp_ctx),
-					      &dest_addr);
+	r = tsocket_address_inet_from_strings_resolve(tctx, "ip",
+						host,
+						lpcfg_cldap_port(tctx->lp_ctx),
+						&dest_addr);
 	CHECK_VAL(r, 0);
 
 	/* cldap_socket_init should now know about the dest. address */
-- 
2.5.0


From bc39ca1fa5392a3f2966a4dfdda5af9e1b8f05c8 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 17 Dec 2015 13:59:40 +0100
Subject: [PATCH 4/6] torture: use tsocket_address_inet_from_strings_resolve()
 in the rpc:lsa test

This is so a host*NAME* handed in will get properly resolved.
Bug uncovered by the new nss_wrapper code (1.1.2).

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 source4/torture/rpc/lsa.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c
index 4ba246f..93c9503 100644
--- a/source4/torture/rpc/lsa.c
+++ b/source4/torture/rpc/lsa.c
@@ -4182,10 +4182,10 @@ static bool check_dom_trust_pw(struct dcerpc_pipe *p,
 	cli_credentials_set_workstation(incoming_creds, workstation, CRED_SPECIFIED);
 	cli_credentials_set_secure_channel_type(incoming_creds, secure_channel_type);
 
-	rc = tsocket_address_inet_from_strings(tctx, "ip",
-					       host,
-					       lpcfg_cldap_port(tctx->lp_ctx),
-					       &dest_addr);
+	rc = tsocket_address_inet_from_strings_resolve(tctx, "ip",
+						host,
+						lpcfg_cldap_port(tctx->lp_ctx),
+						&dest_addr);
 	torture_assert_int_equal(tctx, rc, 0,
 				 talloc_asprintf(tctx,
 						 "tsocket_address_inet_from_strings failed parsing %s:%d",
-- 
2.5.0


From bd36ba58332458875ef126f60efd96b98020d81e Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 17 Dec 2015 13:59:58 +0100
Subject: [PATCH 5/6] torture: don't use AI_NUMERICHOST for getaddrinfo in
 rpc:lsa test

This is so a host*NAME* handed in will get properly resolved.
Bug uncovered by the new nss_wrapper code (1.1.2).

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 source4/torture/rpc/lsa.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c
index 93c9503..c53bd12 100644
--- a/source4/torture/rpc/lsa.c
+++ b/source4/torture/rpc/lsa.c
@@ -3216,7 +3216,7 @@ static bool check_pw_with_krb5(struct torture_context *tctx,
 	k5ret = smb_krb5_init_context(ctx, tctx->lp_ctx, &ctx->smb_krb5_context);
 	torture_assert_int_equal(tctx, k5ret, 0, "smb_krb5_init_context failed");
 
-	ok = interpret_string_addr_internal(&ctx->server, host, AI_NUMERICHOST);
+	ok = interpret_string_addr_internal(&ctx->server, host, 0);
 	torture_assert(tctx, ok, "Failed to parse target server");
 	talloc_set_destructor(ctx, check_pw_with_krb5_ctx_destructor);
 
-- 
2.5.0


From 7e1760cc36b19fe7973b5b27140b31c8402c713c Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Fri, 18 Dec 2015 19:11:43 +0100
Subject: [PATCH 6/6] torture: Fix winbind.wbclient.ResolveWinsByIp test

The test gets handed a name, so we first need
to resolve the name to an IP before we can
pass that on to ResolveWinsByIp.

Bug uncovered by the new nss_wrapper code (1.1.2).

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 nsswitch/libwbclient/tests/wbclient.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/nsswitch/libwbclient/tests/wbclient.c b/nsswitch/libwbclient/tests/wbclient.c
index 5bce0ae..3776e19 100644
--- a/nsswitch/libwbclient/tests/wbclient.c
+++ b/nsswitch/libwbclient/tests/wbclient.c
@@ -22,6 +22,7 @@
 #include "libcli/util/werror.h"
 #include "lib/util/data_blob.h"
 #include "lib/util/time.h"
+#include "libcli/resolve/resolve.h"
 #include "nsswitch/libwbclient/wbclient.h"
 #include "torture/smbtorture.h"
 #include "torture/winbind/proto.h"
@@ -418,10 +419,24 @@ static bool test_wbc_resolve_winsbyname(struct torture_context *tctx)
 static bool test_wbc_resolve_winsbyip(struct torture_context *tctx)
 {
 	const char *ip;
+	const char *host;
+	struct nbt_name nbt_name;
 	char *name;
 	wbcErr ret;
+	NTSTATUS status;
 
-	ip = torture_setting_string(tctx, "host", NULL);
+	host = torture_setting_string(tctx, "host", NULL);
+
+	make_nbt_name_server(&nbt_name, host);
+
+	/* do an initial name resolution to find its IP */
+	status = resolve_name_ex(lpcfg_resolve_context(tctx->lp_ctx),
+				 0, 0, &nbt_name, tctx, &ip, tctx->ev);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("Failed to resolve %s - %s\n",
+		       nbt_name.name, nt_errstr(status));
+		return false;
+	}
 
 	ret = wbcResolveWinsByIP(ip, &name);
 
-- 
2.5.0

-------------- next part --------------
From 3214247f1f9a83c14ea57d7dedc6fe191c271300 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Wed, 1 Oct 2014 17:15:35 +0200
Subject: [PATCH 01/91] nwrap: Fix the handle loops for older gcc versions.

Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index a41de9e..28c23d8 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -575,11 +575,14 @@ static void *nwrap_load_lib_handle(enum nwrap_lib lib)
 #ifdef HAVE_LIBNSL
 		handle = nwrap_main_global->libc->nsl_handle;
 		if (handle == NULL) {
-			for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
+			for (i = 10; i >= 0; i--) {
 				char soname[256] = {0};
 
 				snprintf(soname, sizeof(soname), "libnsl.so.%d", i);
 				handle = dlopen(soname, flags);
+				if (handle != NULL) {
+					break;
+				}
 			}
 
 			nwrap_main_global->libc->nsl_handle = handle;
@@ -591,11 +594,14 @@ static void *nwrap_load_lib_handle(enum nwrap_lib lib)
 #ifdef HAVE_LIBSOCKET
 		handle = nwrap_main_global->libc->sock_handle;
 		if (handle == NULL) {
-			for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
+			for (i = 10; i >= 0; i--) {
 				char soname[256] = {0};
 
 				snprintf(soname, sizeof(soname), "libsocket.so.%d", i);
 				handle = dlopen(soname, flags);
+				if (handle != NULL) {
+					break;
+				}
 			}
 
 			nwrap_main_global->libc->sock_handle = handle;
@@ -606,11 +612,14 @@ static void *nwrap_load_lib_handle(enum nwrap_lib lib)
 	case NWRAP_LIBC:
 		handle = nwrap_main_global->libc->handle;
 		if (handle == NULL) {
-			for (handle = NULL, i = 10; handle == NULL && i >= 0; i--) {
+			for (i = 10; i >= 0; i--) {
 				char soname[256] = {0};
 
 				snprintf(soname, sizeof(soname), "libc.so.%d", i);
 				handle = dlopen(soname, flags);
+				if (handle != NULL) {
+					break;
+				}
 			}
 
 			nwrap_main_global->libc->handle = handle;
-- 
2.5.0


From 9277babab6cffe822c1b3a717b784e89459fd52a Mon Sep 17 00:00:00 2001
From: Robin Hack <hack.robin at gmail.com>
Date: Sat, 29 Nov 2014 13:22:46 +0100
Subject: [PATCH 02/91] nwrap: Replace free() calls by SAFE_FREE macro where
 possible.

Signed-off-by: Robin Hack <hack.robin at gmail.com>
Reviewed-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 38 +++++++++++++-------------------------
 1 file changed, 13 insertions(+), 25 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 28c23d8..8171064 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -140,6 +140,10 @@ typedef nss_status_t NSS_STATUS;
 
 #define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } while(0)
 
+#ifndef SAFE_FREE
+#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
+#endif
+
 enum nwrap_dbglvl_e {
 	NWRAP_LOG_ERROR = 0,
 	NWRAP_LOG_WARN,
@@ -1078,8 +1082,7 @@ static void *nwrap_load_module_fn(struct nwrap_backend *b,
 			  "Cannot find function %s in %s",
 			  s, b->so_path);
 	}
-	free(s);
-	s = NULL;
+	SAFE_FREE(s);
 	return res;
 }
 
@@ -1380,7 +1383,7 @@ done:
 	return true;
 
 failed:
-	if (buf) free(buf);
+	SAFE_FREE(buf);
 	return false;
 }
 
@@ -1388,9 +1391,7 @@ static void nwrap_files_cache_unload(struct nwrap_cache *nwrap)
 {
 	nwrap->unload(nwrap);
 
-	if (nwrap->buf) free(nwrap->buf);
-
-	nwrap->buf = NULL;
+	SAFE_FREE(nwrap->buf);
 }
 
 static void nwrap_files_cache_reload(struct nwrap_cache *nwrap)
@@ -1626,9 +1627,7 @@ static void nwrap_pw_unload(struct nwrap_cache *nwrap)
 	struct nwrap_pw *nwrap_pw;
 	nwrap_pw = (struct nwrap_pw *)nwrap->private_data;
 
-	if (nwrap_pw->list) free(nwrap_pw->list);
-
-	nwrap_pw->list = NULL;
+	SAFE_FREE(nwrap_pw->list);
 	nwrap_pw->num = 0;
 	nwrap_pw->idx = 0;
 }
@@ -1813,14 +1812,11 @@ static void nwrap_gr_unload(struct nwrap_cache *nwrap)
 
 	if (nwrap_gr->list) {
 		for (i=0; i < nwrap_gr->num; i++) {
-			if (nwrap_gr->list[i].gr_mem) {
-				free(nwrap_gr->list[i].gr_mem);
-			}
+			SAFE_FREE(nwrap_gr->list[i].gr_mem);
 		}
-		free(nwrap_gr->list);
+		SAFE_FREE(nwrap_gr->list);
 	}
 
-	nwrap_gr->list = NULL;
 	nwrap_gr->num = 0;
 	nwrap_gr->idx = 0;
 }
@@ -2044,17 +2040,12 @@ static void nwrap_he_unload(struct nwrap_cache *nwrap)
 
 	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);
-			}
+			SAFE_FREE(nwrap_he->list[i].ht.h_aliases);
+			SAFE_FREE(nwrap_he->list[i].addr);
 		}
-		free(nwrap_he->list);
+		SAFE_FREE(nwrap_he->list);
 	}
 
-	nwrap_he->list = NULL;
 	nwrap_he->num = 0;
 	nwrap_he->idx = 0;
 }
@@ -2550,9 +2541,6 @@ static void nwrap_files_endhostent(void)
  * module backend
  */
 
-#ifndef SAFE_FREE
-#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
-#endif
 
 static struct passwd *nwrap_module_getpwnam(struct nwrap_backend *b,
 					    const char *name)
-- 
2.5.0


From 9416de2fe0ae7d363b8ca7bb074a27d2d6798140 Mon Sep 17 00:00:00 2001
From: Robin Hack <hack.robin at gmail.com>
Date: Wed, 25 Mar 2015 09:36:10 +0100
Subject: [PATCH 03/91] nwrap: Prevent compilation failure on machine without
 IPv4

Signed-off-by: Robin Hack <hack.robin at gmail.com>
Reviewed-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 8171064..d9363bc 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -144,6 +144,12 @@ typedef nss_status_t NSS_STATUS;
 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
 #endif
 
+#ifdef HAVE_IPV6
+#define NWRAP_INET_ADDRSTRLEN INET6_ADDRSTRLEN
+#else
+#define NWRAP_INET_ADDRSTRLEN INET_ADDRSTRLEN
+#endif
+
 enum nwrap_dbglvl_e {
 	NWRAP_LOG_ERROR = 0,
 	NWRAP_LOG_WARN,
@@ -2439,7 +2445,7 @@ static struct hostent *nwrap_files_gethostbyaddr(const void *addr,
 						 socklen_t len, int type)
 {
 	struct hostent *he;
-	char ip[INET6_ADDRSTRLEN] = {0};
+	char ip[NWRAP_INET_ADDRSTRLEN] = {0};
 	const char *a;
 	int i;
 
-- 
2.5.0


From b41f5edb0481e672bc697ae3ce69ec4ac319bb1f Mon Sep 17 00:00:00 2001
From: Robin Hack <hack.robin at gmail.com>
Date: Wed, 15 Jul 2015 15:00:02 +0200
Subject: [PATCH 04/91] nwrap: Use ssize_t for aliases_count

Signed-off-by: Robin Hack <hack.robin at gmail.com>
Reviewed-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index d9363bc..2abbc24 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -1886,7 +1886,7 @@ static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line)
 	struct nwrap_entdata *ed;
 	size_t list_size;
 	bool do_aliases = true;
-	int aliases_count = 0;
+	ssize_t aliases_count = 0;
 	char *p;
 	char *i;
 	char *n;
-- 
2.5.0


From ef8055c68a1358be9134e6cd80b9c759ff013c50 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Mon, 14 Sep 2015 14:52:51 +0200
Subject: [PATCH 05/91] nwrap: Avoid a string comparsion in getgrouplist()

Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 2abbc24..2527356 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -3552,7 +3552,6 @@ static int nwrap_getgrouplist(const char *user, gid_t group,
 	struct group *grp;
 	gid_t *groups_tmp;
 	int count = 1;
-	const char *name_of_group = "";
 
 	NWRAP_LOG(NWRAP_LOG_DEBUG, "getgrouplist called for %s", user);
 
@@ -3565,11 +3564,6 @@ static int nwrap_getgrouplist(const char *user, gid_t group,
 
 	memcpy(groups_tmp, &group, sizeof(gid_t));
 
-	grp = nwrap_getgrgid(group);
-	if (grp) {
-		name_of_group = grp->gr_name;
-	}
-
 	nwrap_setgrent();
 	while ((grp = nwrap_getgrent()) != NULL) {
 		int i = 0;
@@ -3580,8 +3574,8 @@ static int nwrap_getgrouplist(const char *user, gid_t group,
 
 		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)) {
+			if (group != grp->gr_gid &&
+			    (strcmp(user, grp->gr_mem[i]) == 0)) {
 
 				NWRAP_LOG(NWRAP_LOG_DEBUG,
 					  "%s is member of %s",
-- 
2.5.0


From ff07bc2f3689e0a164246350a3b5ba354a9d7735 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Mon, 14 Sep 2015 14:57:40 +0200
Subject: [PATCH 06/91] nwrap: Remove unneeded memcpy in getgrouplist()

Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 2527356..3e8545c 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -3561,8 +3561,7 @@ static int nwrap_getgrouplist(const char *user, gid_t group,
 		errno = ENOMEM;
 		return -1;
 	}
-
-	memcpy(groups_tmp, &group, sizeof(gid_t));
+	groups_tmp[0] = group;
 
 	nwrap_setgrent();
 	while ((grp = nwrap_getgrent()) != NULL) {
@@ -3589,8 +3588,8 @@ static int nwrap_getgrouplist(const char *user, gid_t group,
 					errno = ENOMEM;
 					return -1;
 				}
+				groups_tmp[count] = grp->gr_gid;
 
-				memcpy(&groups_tmp[count], &grp->gr_gid, sizeof(gid_t));
 				count++;
 			}
 		}
-- 
2.5.0


From ad06481f54e72607dd4aaf11262a3cc7adb91ba9 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Fri, 11 Sep 2015 13:37:57 +0200
Subject: [PATCH 07/91] nwrap: Implement nwrap_files_initgroups()

Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 63 ++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 57 insertions(+), 6 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 3e8545c..b2b715e 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2204,14 +2204,65 @@ static void nwrap_files_endpwent(struct nwrap_backend *b)
 
 /* misc functions */
 static int nwrap_files_initgroups(struct nwrap_backend *b,
-				  const char *user, gid_t group)
+				  const char *user,
+				  gid_t group)
 {
-	(void) b; /* unused */
-	(void) user; /* unused */
-	(void) group; /* used */
+	struct group *grp;
+	gid_t *groups;
+	int size = 1;
+	int rc;
+
+	groups = (gid_t *)malloc(size * sizeof(gid_t));
+	if (groups == NULL) {
+		NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
+		errno = ENOMEM;
+		return -1;
+	}
+	groups[0] = group;
+
+	nwrap_files_setgrent(b);
+	while ((grp = nwrap_files_getgrent(b)) != NULL) {
+		int i = 0;
+
+		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 (group != grp->gr_gid &&
+			    (strcmp(user, grp->gr_mem[i]) == 0)) {
+				NWRAP_LOG(NWRAP_LOG_DEBUG,
+					  "%s is member of %s",
+					  user,
+					  grp->gr_name);
+
+				groups = (gid_t *)realloc(groups,
+							  (size + 1) * sizeof(gid_t));
+				if (groups == NULL) {
+					NWRAP_LOG(NWRAP_LOG_ERROR,
+						  "Out of memory");
+					errno = ENOMEM;
+					return -1;
+				}
+
+				groups[size] = grp->gr_gid;
+				size++;
+			}
+		}
+	}
+
+	nwrap_files_endgrent(b);
+
+	NWRAP_LOG(NWRAP_LOG_DEBUG,
+		  "%s is member of %d groups",
+		  user, size);
+
+	/* This really only works if uid_wrapper is loaded */
+	rc = setgroups(size, groups);
+
+	free(groups);
 
-	/* TODO: maybe we should also fake this... */
-	return EPERM;
+	return rc;
 }
 
 /* group functions */
-- 
2.5.0


From e8e33ad374c168064d8089f27cc97a8f0d4db824 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Thu, 17 Sep 2015 10:32:46 +0200
Subject: [PATCH 08/91] nwrap: Remove unused struct member in nwrap_main

Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index b2b715e..6f10071 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -465,7 +465,6 @@ struct nwrap_libc {
 };
 
 struct nwrap_main {
-	const char *nwrap_switch;
 	int num_backends;
 	struct nwrap_backend *backends;
 	struct nwrap_libc *libc;
-- 
2.5.0


From 6e5b8098f3dfd6a5a89d93f016336beb3207b10e Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Thu, 17 Sep 2015 10:33:58 +0200
Subject: [PATCH 09/91] nwrap: Add shadow file parser

Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 322 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 322 insertions(+)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 6f10071..9c015dd 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -61,6 +61,7 @@
 
 #include <pwd.h>
 #include <grp.h>
+#include <shadow.h>
 
 #include <netdb.h>
 #include <arpa/inet.h>
@@ -483,6 +484,7 @@ struct nwrap_cache {
 	void (*unload)(struct nwrap_cache *);
 };
 
+/* passwd */
 struct nwrap_pw {
 	struct nwrap_cache *cache;
 
@@ -497,6 +499,22 @@ struct nwrap_pw nwrap_pw_global;
 static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line);
 static void nwrap_pw_unload(struct nwrap_cache *nwrap);
 
+/* shadow */
+struct nwrap_sp {
+	struct nwrap_cache *cache;
+
+	struct spwd *list;
+	int num;
+	int idx;
+};
+
+struct nwrap_cache __nwrap_cache_sp;
+struct nwrap_sp nwrap_sp_global;
+
+static bool nwrap_sp_parse_line(struct nwrap_cache *nwrap, char *line);
+static void nwrap_sp_unload(struct nwrap_cache *nwrap);
+
+/* group */
 struct nwrap_gr {
 	struct nwrap_cache *cache;
 
@@ -508,6 +526,7 @@ struct nwrap_gr {
 struct nwrap_cache __nwrap_cache_gr;
 struct nwrap_gr nwrap_gr_global;
 
+/* hosts */
 static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line);
 static void nwrap_he_unload(struct nwrap_cache *nwrap);
 
@@ -1249,6 +1268,7 @@ static void nwrap_init(void)
 
 	nwrap_backend_init(nwrap_main_global);
 
+	/* passwd */
 	nwrap_pw_global.cache = &__nwrap_cache_pw;
 
 	nwrap_pw_global.cache->path = getenv("NSS_WRAPPER_PASSWD");
@@ -1257,6 +1277,16 @@ static void nwrap_init(void)
 	nwrap_pw_global.cache->parse_line = nwrap_pw_parse_line;
 	nwrap_pw_global.cache->unload = nwrap_pw_unload;
 
+	/* shadow */
+	nwrap_sp_global.cache = &__nwrap_cache_sp;
+
+	nwrap_sp_global.cache->path = getenv("NSS_WRAPPER_SHADOW");
+	nwrap_sp_global.cache->fd = -1;
+	nwrap_sp_global.cache->private_data = &nwrap_sp_global;
+	nwrap_sp_global.cache->parse_line = nwrap_sp_parse_line;
+	nwrap_sp_global.cache->unload = nwrap_sp_unload;
+
+	/* group */
 	nwrap_gr_global.cache = &__nwrap_cache_gr;
 
 	nwrap_gr_global.cache->path = getenv("NSS_WRAPPER_GROUP");
@@ -1265,6 +1295,7 @@ static void nwrap_init(void)
 	nwrap_gr_global.cache->parse_line = nwrap_gr_parse_line;
 	nwrap_gr_global.cache->unload = nwrap_gr_unload;
 
+	/* hosts */
 	nwrap_he_global.cache = &__nwrap_cache_he;
 
 	nwrap_he_global.cache->path = getenv("NSS_WRAPPER_HOSTS");
@@ -1677,6 +1708,297 @@ static int nwrap_pw_copy_r(const struct passwd *src, struct passwd *dst,
 	return 0;
 }
 
+static bool nwrap_sp_parse_line(struct nwrap_cache *nwrap, char *line)
+{
+	struct nwrap_sp *nwrap_sp;
+	struct spwd *sp;
+	size_t list_size;
+	char *c;
+	char *e;
+	char *p;
+
+	nwrap_sp = (struct nwrap_sp *)nwrap->private_data;
+
+	list_size = sizeof(*nwrap_sp->list) * (nwrap_sp->num+1);
+	sp = (struct spwd *)realloc(nwrap_sp->list, list_size);
+	if (sp == NULL) {
+		NWRAP_LOG(NWRAP_LOG_ERROR,
+			  "realloc(%u) failed",
+			  (unsigned)list_size);
+		return false;
+	}
+	nwrap_sp->list = sp;
+
+	sp = &nwrap_sp->list[nwrap_sp->num];
+
+	c = line;
+
+	/* name */
+	p = strchr(c, ':');
+	if (p == NULL) {
+		NWRAP_LOG(NWRAP_LOG_ERROR,
+			  "name -- Invalid line[%s]: '%s'",
+			  line,
+			  c);
+		return false;
+	}
+	*p = '\0';
+	p++;
+	sp->sp_namp = c;
+	c = p;
+
+	NWRAP_LOG(NWRAP_LOG_TRACE, "name[%s]\n", sp->sp_namp);
+
+	/* pwd */
+	p = strchr(c, ':');
+	if (p == NULL) {
+		NWRAP_LOG(NWRAP_LOG_ERROR,
+			  "pwd -- Invalid line[%s]: '%s'",
+			  line,
+			  c);
+		return false;
+	}
+	*p = '\0';
+	p++;
+	sp->sp_pwdp = c;
+	c = p;
+
+	/* lstchg (long) */
+	if (c[0] == ':') {
+		sp->sp_lstchg = -1;
+		p++;
+	} else {
+		p = strchr(c, ':');
+		if (p == NULL) {
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "lstchg -- Invalid line[%s]: '%s'",
+				  line,
+				  c);
+			return false;
+		}
+		*p = '\0';
+		p++;
+		sp->sp_lstchg = strtol(c, &e, 10);
+		if (c == e) {
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "lstchg -- Invalid line[%s]: '%s' - %s",
+				  line, c, strerror(errno));
+			return false;
+		}
+		if (e == NULL) {
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "lstchg -- Invalid line[%s]: '%s' - %s",
+				  line, c, strerror(errno));
+			return false;
+		}
+		if (e[0] != '\0') {
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "lstchg -- Invalid line[%s]: '%s' - %s",
+				  line, c, strerror(errno));
+			return false;
+		}
+	}
+	c = p;
+
+	/* min (long) */
+	if (c[0] == ':') {
+		sp->sp_min = -1;
+		p++;
+	} else {
+		p = strchr(c, ':');
+		if (p == NULL) {
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "min -- Invalid line[%s]: '%s'",
+				  line,
+				  c);
+			return false;
+		}
+		*p = '\0';
+		p++;
+		sp->sp_min = strtol(c, &e, 10);
+		if (c == e) {
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "min -- Invalid line[%s]: '%s' - %s",
+				  line, c, strerror(errno));
+			return false;
+		}
+		if (e == NULL) {
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "min -- Invalid line[%s]: '%s' - %s",
+				  line, c, strerror(errno));
+			return false;
+		}
+		if (e[0] != '\0') {
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "min -- Invalid line[%s]: '%s' - %s",
+				  line, c, strerror(errno));
+			return false;
+		}
+	}
+	c = p;
+
+	/* max (long) */
+	if (c[0] == ':') {
+		sp->sp_max = -1;
+		p++;
+	} else {
+		p = strchr(c, ':');
+		if (p == NULL) {
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "max -- Invalid line[%s]: '%s'",
+				  line,
+				  c);
+			return false;
+		}
+		*p = '\0';
+		p++;
+		sp->sp_max = strtol(c, &e, 10);
+		if (c == e) {
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "max -- Invalid line[%s]: '%s' - %s",
+				  line, c, strerror(errno));
+			return false;
+		}
+		if (e == NULL) {
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "max -- Invalid line[%s]: '%s' - %s",
+				  line, c, strerror(errno));
+			return false;
+		}
+		if (e[0] != '\0') {
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "max -- Invalid line[%s]: '%s' - %s",
+				  line, c, strerror(errno));
+			return false;
+		}
+	}
+	c = p;
+
+	/* warn (long) */
+	if (c[0] == ':') {
+		sp->sp_warn = -1;
+		p++;
+	} else {
+		p = strchr(c, ':');
+		if (p == NULL) {
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "warn -- Invalid line[%s]: '%s'",
+				  line,
+				  c);
+			return false;
+		}
+		*p = '\0';
+		p++;
+		sp->sp_warn = strtol(c, &e, 10);
+		if (c == e) {
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "warn -- Invalid line[%s]: '%s' - %s",
+				  line, c, strerror(errno));
+			return false;
+		}
+		if (e == NULL) {
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "warn -- Invalid line[%s]: '%s' - %s",
+				  line, c, strerror(errno));
+			return false;
+		}
+		if (e[0] != '\0') {
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "warn -- Invalid line[%s]: '%s' - %s",
+				  line, c, strerror(errno));
+			return false;
+		}
+	}
+	c = p;
+
+	/* inact (long) */
+	if (c[0] == ':') {
+		sp->sp_inact = -1;
+		p++;
+	} else {
+		p = strchr(c, ':');
+		if (p == NULL) {
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "inact -- Invalid line[%s]: '%s'",
+				  line,
+				  c);
+			return false;
+		}
+		*p = '\0';
+		p++;
+		sp->sp_inact = strtol(c, &e, 10);
+		if (c == e) {
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "inact -- Invalid line[%s]: '%s' - %s",
+				  line, c, strerror(errno));
+			return false;
+		}
+		if (e == NULL) {
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "inact -- Invalid line[%s]: '%s' - %s",
+				  line, c, strerror(errno));
+			return false;
+		}
+		if (e[0] != '\0') {
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "inact -- Invalid line[%s]: '%s' - %s",
+				  line, c, strerror(errno));
+			return false;
+		}
+	}
+	c = p;
+
+	/* expire (long) */
+	if (c[0] == ':') {
+		sp->sp_expire = -1;
+		p++;
+	} else {
+		p = strchr(c, ':');
+		if (p == NULL) {
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "expire -- Invalid line[%s]: '%s'",
+				  line,
+				  c);
+			return false;
+		}
+		*p = '\0';
+		p++;
+		sp->sp_expire = strtol(c, &e, 10);
+		if (c == e) {
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "expire -- Invalid line[%s]: '%s' - %s",
+				  line, c, strerror(errno));
+			return false;
+		}
+		if (e == NULL) {
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "expire -- Invalid line[%s]: '%s' - %s",
+				  line, c, strerror(errno));
+			return false;
+		}
+		if (e[0] != '\0') {
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "expire -- Invalid line[%s]: '%s' - %s",
+				  line, c, strerror(errno));
+			return false;
+		}
+	}
+	c = p;
+
+	nwrap_sp->num++;
+	return true;
+}
+
+static void nwrap_sp_unload(struct nwrap_cache *nwrap)
+{
+	struct nwrap_sp *nwrap_sp;
+	nwrap_sp = (struct nwrap_sp *)nwrap->private_data;
+
+	SAFE_FREE(nwrap_sp->list);
+	nwrap_sp->num = 0;
+	nwrap_sp->idx = 0;
+}
+
 /*
  * the caller has to call nwrap_unload() on failure
  */
-- 
2.5.0


From 6321b7d86c5db7ebba92d685f4e98c3c5f9b6205 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Thu, 17 Sep 2015 10:37:50 +0200
Subject: [PATCH 10/91] nwrap: Add nss_wrapper_shadow_enabled() function

Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 9c015dd..45a5d60 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -341,6 +341,7 @@ struct nwrap_ops {
 /* Public prototypes */
 
 bool nss_wrapper_enabled(void);
+bool nss_wrapper_shadow_enabled(void);
 bool nss_wrapper_hosts_enabled(void);
 
 /* prototypes for files backend */
@@ -1321,6 +1322,18 @@ bool nss_wrapper_enabled(void)
 	return true;
 }
 
+bool nss_wrapper_shadow_enabled(void)
+{
+	nwrap_init();
+
+	if (nwrap_sp_global.cache->path == NULL ||
+	    nwrap_sp_global.cache->path[0] == '\0') {
+		return false;
+	}
+
+	return true;
+}
+
 bool nss_wrapper_hosts_enabled(void)
 {
 	nwrap_init();
-- 
2.5.0


From 53e4ec4e2728b2e65ada01f7c61ffff37e9b07ab Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Thu, 17 Sep 2015 10:38:49 +0200
Subject: [PATCH 11/91] nwrap: Add (set|get|end)spent functions

Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 79 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 45a5d60..f24045d 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2536,6 +2536,39 @@ static void nwrap_files_endpwent(struct nwrap_backend *b)
 	nwrap_pw_global.idx = 0;
 }
 
+/* shadow */
+static void nwrap_files_setspent(void)
+{
+	nwrap_sp_global.idx = 0;
+}
+
+static struct spwd *nwrap_files_getspent(void)
+{
+	struct spwd *sp;
+
+	if (nwrap_sp_global.idx == 0) {
+		nwrap_files_cache_reload(nwrap_sp_global.cache);
+	}
+
+	if (nwrap_sp_global.idx >= nwrap_sp_global.num) {
+		errno = ENOENT;
+		return NULL;
+	}
+
+	sp = &nwrap_sp_global.list[nwrap_sp_global.idx++];
+
+	NWRAP_LOG(NWRAP_LOG_DEBUG,
+		  "return user[%s]",
+		  sp->sp_namp);
+
+	return sp;
+}
+
+static void nwrap_files_endspent(void)
+{
+	nwrap_sp_global.idx = 0;
+}
+
 /* misc functions */
 static int nwrap_files_initgroups(struct nwrap_backend *b,
 				  const char *user,
@@ -4010,6 +4043,52 @@ int getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups)
 #endif
 
 /**********************************************************
+ * SHADOW
+ **********************************************************/
+
+static void nwrap_setspent(void)
+{
+	nwrap_files_setspent();
+}
+
+void setspent(void)
+{
+	if (!nss_wrapper_shadow_enabled()) {
+		return;
+	}
+
+	nwrap_setspent();
+}
+
+static struct spwd *nwrap_getspent(void)
+{
+	return nwrap_files_getspent();
+}
+
+struct spwd *getspent(void)
+{
+	if (!nss_wrapper_shadow_enabled()) {
+		return NULL;
+	}
+
+	return nwrap_getspent();
+}
+
+static void nwrap_endspent(void)
+{
+	nwrap_files_endspent();
+}
+
+void endspent(void)
+{
+	if (!nss_wrapper_shadow_enabled()) {
+		return;
+	}
+
+	nwrap_endspent();
+}
+
+/**********************************************************
  * NETDB
  **********************************************************/
 
-- 
2.5.0


From 96822207b03380a553508ed0a84ba5d33e972f37 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Thu, 17 Sep 2015 10:39:15 +0200
Subject: [PATCH 12/91] nwrap: Add support for getspnam()

Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index f24045d..ca57dfb 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2569,6 +2569,31 @@ static void nwrap_files_endspent(void)
 	nwrap_sp_global.idx = 0;
 }
 
+static struct spwd *nwrap_files_getspnam(const char *name)
+{
+	int i;
+
+	NWRAP_LOG(NWRAP_LOG_DEBUG, "Lookup user %s in files", name);
+
+	nwrap_files_cache_reload(nwrap_sp_global.cache);
+
+	for (i=0; i<nwrap_sp_global.num; i++) {
+		if (strcmp(nwrap_sp_global.list[i].sp_namp, name) == 0) {
+			NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] found", name);
+			return &nwrap_sp_global.list[i];
+		}
+		NWRAP_LOG(NWRAP_LOG_DEBUG,
+			  "user[%s] does not match [%s]",
+			  name,
+			  nwrap_sp_global.list[i].sp_namp);
+	}
+
+	NWRAP_LOG(NWRAP_LOG_DEBUG, "user[%s] not found\n", name);
+
+	errno = ENOENT;
+	return NULL;
+}
+
 /* misc functions */
 static int nwrap_files_initgroups(struct nwrap_backend *b,
 				  const char *user,
@@ -4088,6 +4113,20 @@ void endspent(void)
 	nwrap_endspent();
 }
 
+static struct spwd *nwrap_getspnam(const char *name)
+{
+	return nwrap_files_getspnam(name);
+}
+
+struct spwd *getspnam(const char *name)
+{
+	if (!nss_wrapper_shadow_enabled()) {
+		return NULL;
+	}
+
+	return nwrap_getspnam(name);
+}
+
 /**********************************************************
  * NETDB
  **********************************************************/
-- 
2.5.0


From 4229217ef355d8d0ca7e589e449589e005775cf2 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Tue, 6 Oct 2015 10:19:48 +0200
Subject: [PATCH 13/91] src: Add configure check for shadow.h

This is the first part to fix FreeBSD.

Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index ca57dfb..978c3071 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -61,7 +61,9 @@
 
 #include <pwd.h>
 #include <grp.h>
+#ifdef HAVE_SHADOW_H
 #include <shadow.h>
+#endif /* HAVE_SHADOW_H */
 
 #include <netdb.h>
 #include <arpa/inet.h>
-- 
2.5.0


From 0091daf716a4fc04f69d6219e81ec5f09ea02fcd Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Tue, 6 Oct 2015 10:34:20 +0200
Subject: [PATCH 14/91] nwrap: Check for setspent and getspnam functions

Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 978c3071..e985bb3 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -503,6 +503,7 @@ static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line);
 static void nwrap_pw_unload(struct nwrap_cache *nwrap);
 
 /* shadow */
+#if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
 struct nwrap_sp {
 	struct nwrap_cache *cache;
 
@@ -516,6 +517,7 @@ struct nwrap_sp nwrap_sp_global;
 
 static bool nwrap_sp_parse_line(struct nwrap_cache *nwrap, char *line);
 static void nwrap_sp_unload(struct nwrap_cache *nwrap);
+#endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
 
 /* group */
 struct nwrap_gr {
@@ -1281,6 +1283,7 @@ static void nwrap_init(void)
 	nwrap_pw_global.cache->unload = nwrap_pw_unload;
 
 	/* shadow */
+#if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
 	nwrap_sp_global.cache = &__nwrap_cache_sp;
 
 	nwrap_sp_global.cache->path = getenv("NSS_WRAPPER_SHADOW");
@@ -1288,6 +1291,7 @@ static void nwrap_init(void)
 	nwrap_sp_global.cache->private_data = &nwrap_sp_global;
 	nwrap_sp_global.cache->parse_line = nwrap_sp_parse_line;
 	nwrap_sp_global.cache->unload = nwrap_sp_unload;
+#endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
 
 	/* group */
 	nwrap_gr_global.cache = &__nwrap_cache_gr;
@@ -1324,6 +1328,7 @@ bool nss_wrapper_enabled(void)
 	return true;
 }
 
+#if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
 bool nss_wrapper_shadow_enabled(void)
 {
 	nwrap_init();
@@ -1335,6 +1340,7 @@ bool nss_wrapper_shadow_enabled(void)
 
 	return true;
 }
+#endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
 
 bool nss_wrapper_hosts_enabled(void)
 {
@@ -1723,6 +1729,7 @@ static int nwrap_pw_copy_r(const struct passwd *src, struct passwd *dst,
 	return 0;
 }
 
+#if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
 static bool nwrap_sp_parse_line(struct nwrap_cache *nwrap, char *line)
 {
 	struct nwrap_sp *nwrap_sp;
@@ -2013,6 +2020,7 @@ static void nwrap_sp_unload(struct nwrap_cache *nwrap)
 	nwrap_sp->num = 0;
 	nwrap_sp->idx = 0;
 }
+#endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
 
 /*
  * the caller has to call nwrap_unload() on failure
@@ -2539,6 +2547,10 @@ static void nwrap_files_endpwent(struct nwrap_backend *b)
 }
 
 /* shadow */
+
+#if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
+
+#ifdef HAVE_SETSPENT
 static void nwrap_files_setspent(void)
 {
 	nwrap_sp_global.idx = 0;
@@ -2570,6 +2582,7 @@ static void nwrap_files_endspent(void)
 {
 	nwrap_sp_global.idx = 0;
 }
+#endif /* HAVE_SETSPENT */
 
 static struct spwd *nwrap_files_getspnam(const char *name)
 {
@@ -2595,6 +2608,7 @@ static struct spwd *nwrap_files_getspnam(const char *name)
 	errno = ENOENT;
 	return NULL;
 }
+#endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
 
 /* misc functions */
 static int nwrap_files_initgroups(struct nwrap_backend *b,
@@ -4073,6 +4087,9 @@ int getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups)
  * SHADOW
  **********************************************************/
 
+#if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
+
+#ifdef HAVE_SETSPENT
 static void nwrap_setspent(void)
 {
 	nwrap_files_setspent();
@@ -4114,6 +4131,7 @@ void endspent(void)
 
 	nwrap_endspent();
 }
+#endif /* HAVE_SETSPENT */
 
 static struct spwd *nwrap_getspnam(const char *name)
 {
@@ -4129,6 +4147,8 @@ struct spwd *getspnam(const char *name)
 	return nwrap_getspnam(name);
 }
 
+#endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
+
 /**********************************************************
  * NETDB
  **********************************************************/
-- 
2.5.0


From e6c3bb9f201f95deffcb6c88c80610b4e07f6f66 Mon Sep 17 00:00:00 2001
From: Robin Hack <hack.robin at gmail.com>
Date: Mon, 23 Mar 2015 14:10:18 +0100
Subject: [PATCH 15/91] nwrap: Add nwrap vector memory management functions

Nwrap vectors  are just more inteligent arrays.
They can look like very simple version of
vectors from C++.

TESTS: Add nwrap_vector tests.

Signed-off-by: Robin Hack <hack.robin at gmail.com>
Reviewed-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 137 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 137 insertions(+)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index e985bb3..69949aa 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -50,6 +50,8 @@
 #include <unistd.h>
 #include <ctype.h>
 
+#include <assert.h>
+
 /*
  * 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
@@ -477,6 +479,141 @@ struct nwrap_main {
 struct nwrap_main *nwrap_main_global;
 struct nwrap_main __nwrap_main_global;
 
+/*
+ * VECTORS
+ */
+
+#define DEFAULT_VECTOR_CAPACITY 16
+
+struct nwrap_vector {
+	void **items;
+	size_t count;
+	size_t capacity;
+};
+
+/* Macro returns pointer to first element of vector->items array.
+ *
+ * nwrap_vector is used as a memory backend which take care of
+ * memory allocations and other stuff like memory growing.
+ * nwrap_vectors should not be considered as some abstract structures.
+ * On this level, vectors are more handy than direct realloc/malloc
+ * calls.
+ *
+ * nwrap_vector->items is array inside nwrap_vector which can be
+ * directly pointed by libc structure assembled by cwrap itself.
+ *
+ * EXAMPLE:
+ *
+ * 1) struct hostent contains char **h_addr_list element.
+ * 2) nwrap_vector holds array of pointers to addresses.
+ *    It's easier to use vector to store results of
+ *    file parsing etc.
+ *
+ * Now, pretend that cwrap assembled struct hostent and
+ * we need to set h_addr_list to point to nwrap_vector.
+ * Idea behind is to shield users from internal nwrap_vector
+ * implementation.
+ * (Yes, not fully - array terminated by NULL is needed because
+ * it's result expected by libc function caller.)
+ *
+ *
+ * CODE EXAMPLE:
+ *
+ * struct hostent he;
+ * struct nwrap_vector *vector = malloc(sizeof(struct nwrap_vector));
+ * ... don't care about failed allocation now ...
+ *
+ * ... fill nwrap vector ...
+ *
+ * struct hostent he;
+ * he.h_addr_list = nwrap_vector_head(vector);
+ *
+ */
+#define nwrap_vector_head(vect) ((void *)((vect)->items))
+
+#define nwrap_vector_foreach(item, vect, iter) \
+	for (iter = 0, (item) = (vect).items == NULL ? NULL : (vect).items[0]; \
+	     item != NULL; \
+	     (item) = (vect).items[++iter])
+
+static inline bool nwrap_vector_init(struct nwrap_vector *const vector)
+{
+	if (vector == NULL) {
+		return false;
+	}
+
+	/* count is initialized by ZERO_STRUCTP */
+	ZERO_STRUCTP(vector);
+	vector->items = malloc(sizeof(void *) * (DEFAULT_VECTOR_CAPACITY + 1));
+	if (vector->items == NULL) {
+		return false;
+	}
+	vector->capacity = DEFAULT_VECTOR_CAPACITY;
+	memset(vector->items, '\0', sizeof(void *) * (DEFAULT_VECTOR_CAPACITY + 1));
+
+	return true;
+}
+
+static bool nwrap_vector_add_item(struct nwrap_vector *cont, void *const item)
+{
+	assert (cont != NULL);
+
+	if (cont->items == NULL) {
+		nwrap_vector_init(cont);
+	}
+
+	if (cont->count == cont->capacity) {
+		/* Items array _MUST_ be NULL terminated because it's passed
+		 * as result to caller which expect NULL terminated array from libc.
+		 */
+		void **items = realloc(cont->items, sizeof(void *) * ((cont->capacity * 2) + 1));
+		if (items == NULL) {
+			return false;
+		}
+		cont->items = items;
+
+		/* Don't count ending NULL to capacity */
+		cont->capacity *= 2;
+	}
+
+	cont->items[cont->count] = item;
+
+	cont->count += 1;
+	cont->items[cont->count] = NULL;
+
+	return true;
+}
+
+static bool nwrap_vector_merge(struct nwrap_vector *dst,
+			       struct nwrap_vector *src)
+{
+	void **dst_items = NULL;
+	size_t count;
+
+	if (src->count == 0) {
+		return true;
+	}
+
+	count = dst->count + src->count;
+
+	/* We don't need reallocation if we have enough capacity. */
+	if (src->count > (dst->capacity - dst->count)) {
+		dst_items = (void **)realloc(dst->items, (count + 1) * sizeof(void *));
+		if (dst_items == NULL) {
+			return false;
+		}
+		dst->items = dst_items;
+		dst->capacity = count;
+	}
+
+	memcpy((void *)(((long *)dst->items) + dst->count),
+	       src->items,
+	       src->count * sizeof(void *));
+	dst->count = count;
+
+	return true;
+}
+
 struct nwrap_cache {
 	const char *path;
 	int fd;
-- 
2.5.0


From 5aece0c03d9971d870b7eaff458841d2bb3f09c4 Mon Sep 17 00:00:00 2001
From: Robin Hack <hack.robin at gmail.com>
Date: Mon, 23 Mar 2015 14:39:28 +0100
Subject: [PATCH 16/91] nwrap: Simplify file loading.

Lines are stored into vectors now.

Signed-off-by: Robin Hack <hack.robin at gmail.com>
Reviewed-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 139 ++++++++++++++++++++++++------------------
 1 file changed, 80 insertions(+), 59 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 69949aa..94cc4cf 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -617,9 +617,12 @@ static bool nwrap_vector_merge(struct nwrap_vector *dst,
 struct nwrap_cache {
 	const char *path;
 	int fd;
+	FILE *fp;
 	struct stat st;
-	uint8_t *buf;
 	void *private_data;
+
+	struct nwrap_vector lines;
+
 	bool (*parse_line)(struct nwrap_cache *, char *line);
 	void (*unload)(struct nwrap_cache *);
 };
@@ -843,6 +846,18 @@ static void *_nwrap_load_lib_function(enum nwrap_lib lib, const char *fn_name)
 			_nwrap_load_lib_function(lib, #fn_name); \
 	}
 
+/* INTERNAL HELPER FUNCTIONS */
+static void nwrap_lines_unload(struct nwrap_cache *const nwrap)
+{
+	size_t p;
+	for (p = 0; p < nwrap->lines.count; p++) {
+		/* Maybe some vectors were merged ... */
+		SAFE_FREE(nwrap->lines.items[p]);
+	}
+	SAFE_FREE(nwrap->lines.items);
+	nwrap->lines.count = 0;
+}
+
 /*
  * IMPORTANT
  *
@@ -1414,6 +1429,7 @@ static void nwrap_init(void)
 	nwrap_pw_global.cache = &__nwrap_cache_pw;
 
 	nwrap_pw_global.cache->path = getenv("NSS_WRAPPER_PASSWD");
+	nwrap_pw_global.cache->fp = NULL;
 	nwrap_pw_global.cache->fd = -1;
 	nwrap_pw_global.cache->private_data = &nwrap_pw_global;
 	nwrap_pw_global.cache->parse_line = nwrap_pw_parse_line;
@@ -1424,6 +1440,7 @@ static void nwrap_init(void)
 	nwrap_sp_global.cache = &__nwrap_cache_sp;
 
 	nwrap_sp_global.cache->path = getenv("NSS_WRAPPER_SHADOW");
+	nwrap_sp_global.cache->fp = NULL;
 	nwrap_sp_global.cache->fd = -1;
 	nwrap_sp_global.cache->private_data = &nwrap_sp_global;
 	nwrap_sp_global.cache->parse_line = nwrap_sp_parse_line;
@@ -1434,6 +1451,7 @@ static void nwrap_init(void)
 	nwrap_gr_global.cache = &__nwrap_cache_gr;
 
 	nwrap_gr_global.cache->path = getenv("NSS_WRAPPER_GROUP");
+	nwrap_gr_global.cache->fp = NULL;
 	nwrap_gr_global.cache->fd = -1;
 	nwrap_gr_global.cache->private_data = &nwrap_gr_global;
 	nwrap_gr_global.cache->parse_line = nwrap_gr_parse_line;
@@ -1443,6 +1461,7 @@ static void nwrap_init(void)
 	nwrap_he_global.cache = &__nwrap_cache_he;
 
 	nwrap_he_global.cache->path = getenv("NSS_WRAPPER_HOSTS");
+	nwrap_he_global.cache->fp = NULL;
 	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;
@@ -1504,88 +1523,78 @@ static bool nwrap_hostname_enabled(void)
 
 static bool nwrap_parse_file(struct nwrap_cache *nwrap)
 {
-	int ret;
-	uint8_t *buf = NULL;
-	char *nline;
+	char *line = NULL;
+	ssize_t n;
+	/* Unused but getline needs it */
+	size_t len;
+	bool ok;
 
 	if (nwrap->st.st_size == 0) {
 		NWRAP_LOG(NWRAP_LOG_DEBUG, "size == 0");
-		goto done;
+		return true;
 	}
 
+	/* Support for 32-bit system I guess */
 	if (nwrap->st.st_size > INT32_MAX) {
 		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_LOG(NWRAP_LOG_ERROR, "lseek - rc=%d\n", ret);
-		goto failed;
-	}
-
-	buf = (uint8_t *)malloc(nwrap->st.st_size + 1);
-	if (!buf) {
-		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_LOG(NWRAP_LOG_ERROR,
-			  "read(%u) rc=%d\n",
-			  (unsigned)nwrap->st.st_size, ret);
-		goto failed;
+		return false;
 	}
 
-	buf[nwrap->st.st_size] = '\0';
+	rewind(nwrap->fp);
 
-	nline = (char *)buf;
-	while (nline != NULL && nline[0] != '\0') {
-		char *line;
-		char *e;
-		bool ok;
+	do {
+		n = getline(&line, &len, nwrap->fp);
+		if (n < 0) {
+			if (feof(nwrap->fp)) {
+				break;
+			}
 
-		line = nline;
-		nline = NULL;
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "Unable to read line from file: %s",
+				  nwrap->path);
+			return false;
+		}
 
-		e = strchr(line, '\n');
-		if (e) {
-			e[0] = '\0';
-			e++;
-			if (e[0] == '\r') {
-				e[0] = '\0';
-				e++;
-			}
-			nline = e;
+		if (line[n - 1] == '\n') {
+			line[n - 1] = '\0';
 		}
 
-		if (strlen(line) == 0) {
+		if (line[0] == '\0') {
+			SAFE_FREE(line);
 			continue;
 		}
 
 		ok = nwrap->parse_line(nwrap, line);
 		if (!ok) {
-			goto failed;
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "Unable to parse line file: %s",
+				  line);
+			SAFE_FREE(line);
+			return false;
 		}
-	}
 
-done:
-	nwrap->buf = buf;
-	return true;
+		/* Line is parsed without issues so add it to list */
+		ok = nwrap_vector_add_item(&(nwrap->lines), (void *const) line);
+		if (!ok) {
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "Unable to add line to vector");
+			return false;
+		}
+
+		/* This forces getline to allocate new memory for line. */
+		line = NULL;
+	} while (!feof(nwrap->fp));
 
-failed:
-	SAFE_FREE(buf);
-	return false;
+	return true;
 }
 
 static void nwrap_files_cache_unload(struct nwrap_cache *nwrap)
 {
 	nwrap->unload(nwrap);
 
-	SAFE_FREE(nwrap->buf);
+	nwrap_lines_unload(nwrap);
 }
 
 static void nwrap_files_cache_reload(struct nwrap_cache *nwrap)
@@ -1595,16 +1604,21 @@ static void nwrap_files_cache_reload(struct nwrap_cache *nwrap)
 	bool ok;
 	bool retried = false;
 
+	assert(nwrap != NULL);
+
 reopen:
 	if (nwrap->fd < 0) {
-		nwrap->fd = open(nwrap->path, O_RDONLY);
-		if (nwrap->fd < 0) {
+		nwrap->fp = fopen(nwrap->path, "re");
+		if (nwrap->fp == NULL) {
+			nwrap->fd = -1;
 			NWRAP_LOG(NWRAP_LOG_ERROR,
 				  "Unable to open '%s' readonly %d:%s",
 				  nwrap->path, nwrap->fd,
 				  strerror(errno));
 			return;
+
 		}
+		nwrap->fd = fileno(nwrap->fp);
 		NWRAP_LOG(NWRAP_LOG_DEBUG, "Open '%s'", nwrap->path);
 	}
 
@@ -1615,6 +1629,9 @@ reopen:
 			  nwrap->path,
 			  ret,
 			  strerror(errno));
+		fclose(nwrap->fp);
+		nwrap->fp = NULL;
+		nwrap->fd = -1;
 		return;
 	}
 
@@ -1625,7 +1642,8 @@ reopen:
 			  nwrap->path);
 		retried = true;
 		memset(&nwrap->st, 0, sizeof(nwrap->st));
-		close(nwrap->fd);
+		fclose(nwrap->fp);
+		nwrap->fp = NULL;
 		nwrap->fd = -1;
 		goto reopen;
 	}
@@ -4864,7 +4882,8 @@ void nwrap_destructor(void)
 
 		nwrap_files_cache_unload(c);
 		if (c->fd >= 0) {
-			close(c->fd);
+			fclose(c->fp);
+			c->fd = -1;
 		}
 
 		SAFE_FREE(nwrap_pw_global.list);
@@ -4876,7 +4895,8 @@ void nwrap_destructor(void)
 
 		nwrap_files_cache_unload(c);
 		if (c->fd >= 0) {
-			close(c->fd);
+			fclose(c->fp);
+			c->fd = -1;
 		}
 
 		SAFE_FREE(nwrap_gr_global.list);
@@ -4888,7 +4908,8 @@ void nwrap_destructor(void)
 
 		nwrap_files_cache_unload(c);
 		if (c->fd >= 0) {
-			close(c->fd);
+			fclose(c->fp);
+			c->fd = -1;
 		}
 
 		SAFE_FREE(nwrap_he_global.list);
-- 
2.5.0


From 438d0caf43695bf57fbf268062aac78738dad64e Mon Sep 17 00:00:00 2001
From: Robin Hack <hack.robin at gmail.com>
Date: Wed, 15 Jul 2015 15:01:48 +0200
Subject: [PATCH 17/91] nwrap: Add a hash table to the nwrap structure

The hash table will hold hostnames and ips internally. The new
environment variable which is introduced is NSS_WRAPPER_MAX_HOSTENTS. It
sets the maximum count of hostent (hostnames and ips) structs which the
hash table can hold.

Signed-off-by: Robin Hack <hack.robin at gmail.com>
Reviewed-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 94cc4cf..ae57e18 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -50,6 +50,7 @@
 #include <unistd.h>
 #include <ctype.h>
 
+#include <search.h>
 #include <assert.h>
 
 /*
@@ -680,15 +681,25 @@ struct nwrap_addrdata {
 	char *h_addr_ptrs[2]; /* host_addr pointer + NULL */
 };
 
+static size_t max_hostents = 100;
+
 struct nwrap_entdata {
 	struct nwrap_addrdata *addr;
 	struct hostent ht;
+
+	struct nwrap_vector nwrap_addrdata;
+
+	ssize_t aliases_count;
+
+	struct nwrap_entdata *ed_next;
+	struct nwrap_entdata *ed_tail;
 };
 
 struct nwrap_he {
 	struct nwrap_cache *cache;
 
 	struct nwrap_entdata *list;
+	struct nwrap_vector entdata;
 	int num;
 	int idx;
 };
@@ -1415,10 +1426,36 @@ static void nwrap_backend_init(struct nwrap_main *r)
 static void nwrap_init(void)
 {
 	static bool initialized;
+	const char *env;
+	char *endptr;
+	size_t max_hostents_tmp;
 
 	if (initialized) return;
 	initialized = true;
 
+	env = getenv("NSS_WRAPPER_MAX_HOSTENTS");
+	if (env != NULL) {
+		max_hostents_tmp = (size_t)strtol(env, &endptr, 10);
+		if (((env != '\0') && (endptr == '\0')) ||
+		    (max_hostents_tmp == 0)) {
+			NWRAP_LOG(NWRAP_LOG_DEBUG,
+				  "Error parsing NSS_WRAPPER_MAX_HOSTENTS "
+				  "value or value is too small. "
+				  "Using default value: %lu.",
+				  max_hostents);
+		} else {
+			max_hostents = max_hostents_tmp;
+		}
+	}
+	/* Initialize hash table */
+	NWRAP_LOG(NWRAP_LOG_DEBUG,
+		  "Initializing hash table of size %lu items.", max_hostents);
+	if (hcreate(max_hostents) == 0) {
+		NWRAP_LOG(NWRAP_LOG_ERROR,
+			  "Failed to initialize hash table");
+		return;
+	}
+
 	nwrap_main_global = &__nwrap_main_global;
 
 	nwrap_libc_init(nwrap_main_global);
@@ -4915,4 +4952,6 @@ void nwrap_destructor(void)
 		SAFE_FREE(nwrap_he_global.list);
 		nwrap_he_global.num = 0;
 	}
+
+	hdestroy();
 }
-- 
2.5.0


From b51ff754b392c1cd528cbd299c27ff933a0d5bb4 Mon Sep 17 00:00:00 2001
From: Robin Hack <hack.robin at gmail.com>
Date: Wed, 15 Jul 2015 15:04:32 +0200
Subject: [PATCH 18/91] nwrap: Add function nwrap_add_ai

This adds an ip to the hash table.

Signed-off-by: Robin Hack <hack.robin at gmail.com>
Reviewed-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index ae57e18..44eac67 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2416,6 +2416,23 @@ static int nwrap_gr_copy_r(const struct group *src, struct group *dst,
 	return 0;
 }
 
+static bool nwrap_add_ai(char *const ip_addr, struct nwrap_entdata *const ed)
+{
+	ENTRY e = {
+		.key = ip_addr,
+		.data = (void *)ed,
+	};
+	ENTRY *p;
+
+	p = hsearch(e, ENTER);
+	if (p == NULL) {
+		NWRAP_LOG(NWRAP_LOG_DEBUG, "Hash table is full");
+		return false;
+	}
+
+	return true;
+}
+
 static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line)
 {
 	struct nwrap_he *nwrap_he = (struct nwrap_he *)nwrap->private_data;
-- 
2.5.0


From 547dc38ff1f1d3f9425ffea95383735986929bde Mon Sep 17 00:00:00 2001
From: Robin Hack <hack.robin at gmail.com>
Date: Wed, 15 Jul 2015 15:05:28 +0200
Subject: [PATCH 19/91] nwrap: Add nwrap_add_hname() and
 nwrap_add_hname_alias().

Functions adds a hostname or an alias to the hash table.

Signed-off-by: Robin Hack <hack.robin at gmail.com>
Reviewed-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 124 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 124 insertions(+)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 44eac67..74aa8c3 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2433,6 +2433,130 @@ static bool nwrap_add_ai(char *const ip_addr, struct nwrap_entdata *const ed)
 	return true;
 }
 
+
+static bool nwrap_add_hname_add_new(char *const h_name,
+				    struct nwrap_entdata *const ed)
+{
+	/* No element found.. inventarize new item */
+	ENTRY e;
+	ENTRY *p;
+
+	e.key = h_name;
+	e.data = (void *)ed;
+	ed->ed_tail = NULL;
+	ed->ed_next = NULL;
+
+	p = hsearch(e, ENTER);
+	if (p == NULL) {
+		NWRAP_LOG(NWRAP_LOG_DEBUG, "Hash table is full!");
+		return false;
+	}
+
+	return true;
+}
+
+static void nwrap_add_hname_add_to_existing(struct nwrap_entdata *const ed,
+					    struct nwrap_entdata *const ed_dst)
+{
+	if (ed_dst->ed_tail != NULL) {
+		ed_dst->ed_tail->ed_next = ed;
+		if (ed_dst->ed_tail != ed) {
+			ed_dst->ed_tail = ed;
+			ed->ed_next = NULL;
+		}
+	} else {
+		ed_dst->ed_tail = ed;
+	}
+}
+
+static bool nwrap_add_hname_alias(const char *const h_name_a,
+				  struct nwrap_entdata *const ed)
+{
+	/* One of argument 'h_hame_a' are "optional" */
+	char *const h_name = (char *const) ((h_name_a == NULL) ? ed->ht.h_name : h_name_a);
+	ENTRY e;
+	ENTRY *p;
+
+	/* Maybe it's little bit late ... */
+	assert(ed != NULL);
+	assert(h_name != NULL);
+
+	e.key = h_name;
+	e.data = NULL;
+	NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching name: %s", e.key);
+	p = hsearch(e, FIND);
+	if (p == NULL) {
+		NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found. Adding...", h_name);
+		/* Just add alias and don't mess with metadata */
+		nwrap_add_hname_add_new(h_name, ed);
+	} else {
+		/* Element found. Add them to end of list */
+		struct nwrap_entdata *ed_dst = (struct nwrap_entdata *)p->data;
+
+		assert(p->data != NULL);
+		NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s found. Add record to list.", h_name);
+		nwrap_add_hname_add_to_existing(ed, ed_dst);
+	}
+
+	return true;
+}
+
+static bool nwrap_add_hname(const char *const h_name_a,
+			    struct nwrap_entdata *const ed)
+{
+	/* One of argument 'h_hame_a' are "optional" */
+	char *const h_name = (char *const) ((h_name_a == NULL) ? ed->ht.h_name : h_name_a);
+	ENTRY e;
+	ENTRY *p;
+	char *h_name_alias;
+	unsigned i;
+
+	/* Maybe it's little bit late ... */
+	assert(ed != NULL);
+	assert(h_name != NULL);
+
+	e.key = h_name;
+	e.data = NULL;
+	NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching name: %s", e.key);
+	p = hsearch(e, FIND);
+	if (p == NULL) {
+		NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found. Adding...", h_name);
+		/* Just add alias and don't mess with metadata */
+		nwrap_add_hname_add_new(h_name, ed);
+
+		if (ed->ed_tail == NULL) {
+			ed->ed_tail = ed;
+		}
+	} else {
+		/* Element found. Add them to end of list */
+		struct nwrap_entdata *ed_dst = (struct nwrap_entdata *)p->data;
+
+		assert(p->data != NULL);
+		NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s found. Add record to list.", h_name);
+		nwrap_add_hname_add_to_existing(ed, ed_dst);
+	}
+
+	/* Return true when list of aliases is empty */
+	if (ed->ht.h_aliases == NULL) {
+		return true;
+	}
+
+	/* Itemize aliases */
+	for (i = 0; ed->ht.h_aliases[i] != NULL; ++i) {
+		h_name_alias = ed->ht.h_aliases[i];
+		assert(h_name_alias != NULL);
+
+		NWRAP_LOG(NWRAP_LOG_DEBUG, "Add alias: %s", h_name_alias);
+
+		if (!nwrap_add_hname_alias(h_name_alias, ed)) {
+			NWRAP_LOG(NWRAP_LOG_DEBUG,
+				  "Unable to add alias: %s", h_name_alias);
+		}
+	}
+
+	return true;
+}
+
 static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line)
 {
 	struct nwrap_he *nwrap_he = (struct nwrap_he *)nwrap->private_data;
-- 
2.5.0


From d8f72516f69234740f37868b503beebab2b13fa9 Mon Sep 17 00:00:00 2001
From: Robin Hack <hack.robin at gmail.com>
Date: Tue, 24 Mar 2015 15:14:35 +0100
Subject: [PATCH 20/91] nwrap: Add string manipulation functions.

Signed-off-by: Robin Hack <hack.robin at gmail.com>
Reviewed-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 74aa8c3..2c2cbd6 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -939,6 +939,37 @@ static int libc_getpwuid_r(uid_t uid,
 }
 #endif
 
+static inline void str_tolower(char *dst, char *src)
+{
+	register char *src_tmp = src;
+	register char *dst_tmp = dst;
+
+	while (*src_tmp != '\0') {
+		*dst_tmp = tolower(*src_tmp);
+		++src_tmp;
+		++dst_tmp;
+	}
+}
+
+static bool str_tolower_copy(char **dst_name, const char *const src_name)
+{
+	char *h_name_lower;
+
+	if ((dst_name == NULL) || (src_name == NULL)) {
+		return false;
+	}
+
+	h_name_lower = strdup(src_name);
+	if (h_name_lower == NULL) {
+		NWRAP_LOG(NWRAP_LOG_DEBUG, "Out of memory while strdup");
+		return false;
+	}
+
+	str_tolower(h_name_lower, h_name_lower);
+	*dst_name = h_name_lower;
+	return true;
+}
+
 static void libc_setpwent(void)
 {
 	nwrap_load_lib_function(NWRAP_LIBC, setpwent);
-- 
2.5.0


From 4ce2d14398b3e4673e821705e93c2e98f6e216fa Mon Sep 17 00:00:00 2001
From: Robin Hack <hack.robin at gmail.com>
Date: Thu, 16 Jul 2015 16:10:20 +0200
Subject: [PATCH 21/91] nwrap: Use nwrap vectors as memory backend for
 getaddrinfo() and gethostbyname()

Previous patches introduced nwrap vectors and hash functions.
This patch will join all together.

Main purpose of this patch is:
	- support more records per hostname.
	  For example: hostname now can have associated IPv4 and IPv6 address.
	- better handling of big number of hostname records

Signed-off-by: Robin Hack <hack.robin at gmail.com>
Reviewed-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 432 ++++++++++++++++++++++++++++++------------
 1 file changed, 308 insertions(+), 124 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 2c2cbd6..b133e01 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -477,8 +477,17 @@ struct nwrap_main {
 	struct nwrap_libc *libc;
 };
 
-struct nwrap_main *nwrap_main_global;
-struct nwrap_main __nwrap_main_global;
+static struct nwrap_main *nwrap_main_global;
+static struct nwrap_main __nwrap_main_global;
+
+/*
+ * PROTOTYPES
+ */
+static int nwrap_convert_he_ai(const struct hostent *he,
+			       unsigned short port,
+			       const struct addrinfo *hints,
+			       struct addrinfo **pai,
+			       bool skip_canonname);
 
 /*
  * VECTORS
@@ -678,13 +687,12 @@ 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 */
 };
 
 static size_t max_hostents = 100;
 
 struct nwrap_entdata {
-	struct nwrap_addrdata *addr;
+	struct nwrap_addrdata addr;
 	struct hostent ht;
 
 	struct nwrap_vector nwrap_addrdata;
@@ -700,12 +708,13 @@ struct nwrap_he {
 
 	struct nwrap_entdata *list;
 	struct nwrap_vector entdata;
+
 	int num;
 	int idx;
 };
 
-struct nwrap_cache __nwrap_cache_he;
-struct nwrap_he nwrap_he_global;
+static struct nwrap_cache __nwrap_cache_he;
+static struct nwrap_he nwrap_he_global;
 
 
 /*********************************************************
@@ -2591,31 +2600,22 @@ static bool nwrap_add_hname(const char *const h_name_a,
 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;
 	ssize_t aliases_count = 0;
 	char *p;
 	char *i;
 	char *n;
 
-	list_size = sizeof(struct nwrap_entdata) * (nwrap_he->num + 1);
+	char *ip;
 
-	ed = (struct nwrap_entdata *)realloc(nwrap_he->list, list_size);
+	struct nwrap_entdata *ed = (struct nwrap_entdata *)
+				   malloc(sizeof(struct nwrap_entdata));
 	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);
+		NWRAP_LOG(NWRAP_LOG_ERROR,
+			  "Unable to allocate memory for nwrap_entdata");
 		return false;
 	}
+	ZERO_STRUCTP(ed);
 
 	i = line;
 
@@ -2629,6 +2629,7 @@ static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line)
 			NWRAP_LOG(NWRAP_LOG_ERROR,
 				  "Invalid line[%s]: '%s'",
 				  line, i);
+			free(ed);
 			return false;
 		}
 	}
@@ -2638,17 +2639,18 @@ static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line)
 			NWRAP_LOG(NWRAP_LOG_ERROR,
 				  "Invalid line[%s]: '%s'",
 				  line, i);
+			free(ed);
 			return false;
 		}
 	}
 
 	*p = '\0';
 
-	if (inet_pton(AF_INET, i, ed->addr->host_addr)) {
+	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)) {
+	} else if (inet_pton(AF_INET6, i, ed->addr.host_addr)) {
 		ed->ht.h_addrtype = AF_INET6;
 		ed->ht.h_length = 16;
 #endif
@@ -2657,13 +2659,14 @@ static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line)
 			  "Invalid line[%s]: '%s'",
 			  line, i);
 
+		free(ed);
 		return false;
 	}
+	ip = i;
 
-	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;
+	nwrap_vector_add_item(&(ed->nwrap_addrdata),
+			      (void *const)ed->addr.host_addr);
+	ed->ht.h_addr_list = nwrap_vector_head(&ed->nwrap_addrdata);
 
 	p++;
 
@@ -2678,6 +2681,7 @@ static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line)
 				  "Invalid line[%s]: '%s'",
 				  line, n);
 
+			free(ed);
 			return false;
 		}
 	}
@@ -2691,11 +2695,14 @@ static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line)
 
 	*p = '\0';
 
+	/* Convert to lowercase. This operate on same memory region */
+	str_tolower(n, n);
 	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) {
+		free(ed);
 		return false;
 	}
 	ed->ht.h_aliases[0] = NULL;
@@ -2732,16 +2739,25 @@ static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line)
 
 		aliases = realloc(ed->ht.h_aliases, sizeof(char *) * (aliases_count + 2));
 		if (aliases == NULL) {
+			free(ed);
 			return false;
 		}
 		ed->ht.h_aliases = aliases;
 
+		str_tolower(a, a);
 		aliases[aliases_count] = a;
 		aliases[aliases_count + 1] = NULL;
 
-		aliases_count++;
+		aliases_count += 1;
 	}
 
+	nwrap_vector_add_item(&(nwrap_he->entdata), (void *const)ed);
+
+	ed->aliases_count = aliases_count;
+	/* Inventarize item */
+	nwrap_add_hname(NULL, ed);
+	nwrap_add_ai(ip, ed);
+
 	nwrap_he->num++;
 	return true;
 }
@@ -2750,15 +2766,16 @@ static void nwrap_he_unload(struct nwrap_cache *nwrap)
 {
 	struct nwrap_he *nwrap_he =
 		(struct nwrap_he *)nwrap->private_data;
-	int i;
+	struct nwrap_entdata *ed;
+	size_t i;
 
-	if (nwrap_he->list != NULL) {
-		for (i = 0; i < nwrap_he->num; i++) {
-			SAFE_FREE(nwrap_he->list[i].ht.h_aliases);
-			SAFE_FREE(nwrap_he->list[i].addr);
-		}
-		SAFE_FREE(nwrap_he->list);
+	nwrap_vector_foreach (ed, nwrap_he->entdata, i)
+	{
+		SAFE_FREE(ed->ht.h_aliases);
+		SAFE_FREE(ed);
 	}
+	SAFE_FREE(nwrap_he->entdata.items);
+	nwrap_he->entdata.count = nwrap_he->entdata.capacity = 0;
 
 	nwrap_he->num = 0;
 	nwrap_he->idx = 0;
@@ -3181,12 +3198,19 @@ static void nwrap_files_endgrent(struct nwrap_backend *b)
 }
 
 /* hosts functions */
-static struct hostent *nwrap_files_gethostbyname(const char *name, int af)
+static int nwrap_files_gethostbyname(const char *name, int af,
+				     struct hostent *result,
+				     struct nwrap_vector *addr_list)
 {
+	struct nwrap_entdata *ed_head;
+	struct nwrap_entdata *ed_cur;
 	struct hostent *he;
+	char *h_name_lower;
+	ENTRY e;
+	ENTRY *e_p;
 	char canon_name[DNS_NAME_MAX] = { 0 };
 	size_t name_len;
-	int i;
+	bool he_found = false;
 
 	nwrap_files_cache_reload(nwrap_he_global.cache);
 
@@ -3196,37 +3220,69 @@ static struct hostent *nwrap_files_gethostbyname(const char *name, int af)
 		name = canon_name;
 	}
 
-	for (i = 0; i < nwrap_he_global.num; i++) {
-		int j;
+	if (!str_tolower_copy(&h_name_lower, name)) {
+		NWRAP_LOG(NWRAP_LOG_DEBUG,
+			  "Out of memory while converting to lower case");
+		goto no_ent;
+	}
+
+	/* Look at hash table for element */
+	NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching for name: %s", h_name_lower);
+	e.key = h_name_lower;
+	e.data = NULL;
+	e_p = hsearch(e, FIND);
+	if (e_p == NULL) {
+		NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found.", h_name_lower);
+		SAFE_FREE(h_name_lower);
+		goto no_ent;
+	}
+	SAFE_FREE(h_name_lower);
+
+	/* Always cleanup vector and results */
+	if (!nwrap_vector_init(addr_list)) {
+		NWRAP_LOG(NWRAP_LOG_DEBUG,
+			  "Unable to initialize memory for addr_list vector");
+		goto no_ent;
+	}
 
-		he = &nwrap_he_global.list[i].ht;
+	/* Iterate through results */
+	ed_head = (struct nwrap_entdata *)e_p->data;
+	for (ed_cur = ed_head; ed_cur != NULL; ed_cur = ed_cur->ed_next) {
+		he = &(ed_cur->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) {
+		/*
+		 * GLIBC HACK?
+		 * glibc doesn't return ipv6 addresses when AF_UNSPEC is used
+		 */
+		if (af == AF_UNSPEC && he->h_addrtype != AF_INET) {
 			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;
-			}
+		if (!he_found) {
+			memcpy(result, he, sizeof(struct hostent));
+			NWRAP_LOG(NWRAP_LOG_DEBUG,
+				  "Name found. Returning record for %s",
+				  he->h_name);
+			he_found = true;
 		}
+		nwrap_vector_merge(addr_list, &ed_cur->nwrap_addrdata);
+		result->h_addr_list = nwrap_vector_head(addr_list);
 	}
 
+	if (he_found) {
+		return 0;
+	}
+	NWRAP_LOG(NWRAP_LOG_DEBUG,
+		  "Name found in database. No records matches type.");
+
+no_ent:
 	errno = ENOENT;
-	return NULL;
+	return -1;
 }
 
 #ifdef HAVE_GETHOSTBYNAME_R
@@ -3235,15 +3291,32 @@ static int nwrap_gethostbyname_r(const char *name,
 				 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 {
+	struct nwrap_vector *addr_list = malloc(sizeof(struct nwrap_vector));
+	int rc;
+
+	if (addr_list == NULL) {
+		NWRAP_LOG(NWRAP_LOG_ERROR,
+			  "Unable to allocate memory for address list");
+		errno = ENOENT;
+		return -1;
+	}
+
+	ZERO_STRUCTP(addr_list);
+
+	rc = nwrap_files_gethostbyname(name, AF_UNSPEC, ret, addr_list);
+	if (rc == -1) {
 		*h_errnop = h_errno;
+		if (addr_list->items != NULL) {
+			free(addr_list->items);
+		}
+		SAFE_FREE(addr_list);
+		errno = ENOENT;
 		return -1;
 	}
+
+	memset(buf, '\0', buflen);
+	*result = ret;
+	return 0;
 }
 
 int gethostbyname_r(const char *name,
@@ -3264,13 +3337,98 @@ int gethostbyname_r(const char *name,
 }
 #endif
 
+static struct addrinfo *nwrap_files_getaddrinfo(const char *name,
+					        unsigned short port,
+					        const struct addrinfo *hints,
+					        struct addrinfo **ai_tail)
+{
+	struct nwrap_entdata *ed_head;
+	struct nwrap_entdata *ed_cur;
+	struct hostent *he;
+	struct addrinfo *ai = NULL;
+	struct addrinfo *ai_head = NULL;
+	struct addrinfo *ai_prev = NULL;
+	char *h_name_lower;
+	size_t name_len;
+	char canon_name[DNS_NAME_MAX] = { 0 };
+	bool skip_canonname = false;
+	ENTRY e;
+	ENTRY *e_p;
+
+	nwrap_files_cache_reload(nwrap_he_global.cache);
+
+	name_len = strlen(name);
+	if (name_len < DNS_NAME_MAX && name[name_len - 1] == '.') {
+		strncpy(canon_name, name, name_len - 1);
+		name = canon_name;
+	}
+
+	if (!str_tolower_copy(&h_name_lower, name)) {
+		NWRAP_LOG(NWRAP_LOG_DEBUG,
+			  "Out of memory while converting to lower case");
+		return NULL;
+	}
+
+	NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching for name: %s", h_name_lower);
+	e.key = h_name_lower;
+	e.data = NULL;
+	e_p = hsearch(e, FIND);
+	if (e_p == NULL) {
+		NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found.", h_name_lower);
+		SAFE_FREE(h_name_lower);
+		errno = ENOENT;
+		return NULL;
+	}
+	NWRAP_LOG(NWRAP_LOG_DEBUG, "Name: %s found.", h_name_lower);
+	SAFE_FREE(h_name_lower);
+
+	ed_head = (struct nwrap_entdata *)e_p->data;
+
+	for (ed_cur = ed_head; ed_cur != NULL; ed_cur = ed_cur->ed_next) {
+		int rc;
+
+		he = &(ed_cur->ht);
+
+		if (hints->ai_family != AF_UNSPEC &&
+		    he->h_addrtype != hints->ai_family) {
+			continue;
+		}
+
+		/* Function allocates memory and returns it in ai. */
+		rc = nwrap_convert_he_ai(he,
+					 port,
+					 hints,
+					 &ai,
+					 skip_canonname);
+		if (rc != 0) {
+			/* FIXME: Investigate if this is nice to do... */
+			NWRAP_LOG(NWRAP_LOG_ERROR,
+				  "Error in converting he to ai! Skipping.");
+			continue;
+		}
+		skip_canonname = true;
+
+		if (ai_head == NULL) {
+			ai_head = ai;
+		}
+		if (ai_prev != NULL) {
+			ai_prev->ai_next = ai;
+		}
+		ai_prev = ai;
+	}
+
+	*ai_tail = ai;
+	return ai_head;
+}
+
 static struct hostent *nwrap_files_gethostbyaddr(const void *addr,
 						 socklen_t len, int type)
 {
 	struct hostent *he;
 	char ip[NWRAP_INET_ADDRSTRLEN] = {0};
+	struct nwrap_entdata *ed;
 	const char *a;
-	int i;
+	size_t i;
 
 	(void) len; /* unused */
 
@@ -3282,9 +3440,9 @@ static struct hostent *nwrap_files_gethostbyaddr(const void *addr,
 		return NULL;
 	}
 
-	for (i = 0; i < nwrap_he_global.num; i++) {
-		he = &nwrap_he_global.list[i].ht;
-
+	nwrap_vector_foreach(ed, nwrap_he_global.entdata, i)
+	{
+		he = &(ed->ht);
 		if (he->h_addrtype != type) {
 			continue;
 		}
@@ -3354,7 +3512,7 @@ static struct hostent *nwrap_files_gethostent(void)
 		return NULL;
 	}
 
-	he = &nwrap_he_global.list[nwrap_he_global.idx++].ht;
+	he = &((struct nwrap_entdata *)nwrap_he_global.entdata.items[nwrap_he_global.idx++])->ht;
 
 	NWRAP_LOG(NWRAP_LOG_DEBUG, "return hosts[%s]", he->h_name);
 
@@ -4588,9 +4746,14 @@ void endhostent(void)
 }
 #endif /* HAVE_SOLARIS_ENDHOSTENT */
 
+static struct hostent user_he;
+static struct nwrap_vector user_addrlist;
 static struct hostent *nwrap_gethostbyname(const char *name)
 {
-	return nwrap_files_gethostbyname(name, AF_UNSPEC);
+	if (nwrap_files_gethostbyname(name, AF_UNSPEC, &user_he, &user_addrlist) == -1) {
+		return NULL;
+	}
+	return &user_he;
 }
 
 struct hostent *gethostbyname(const char *name)
@@ -4602,11 +4765,15 @@ struct hostent *gethostbyname(const char *name)
 	return nwrap_gethostbyname(name);
 }
 
-/* This is a GNU extension */
 #ifdef HAVE_GETHOSTBYNAME2
+static struct hostent user_he2;
+static struct nwrap_vector user_addrlist2;
 static struct hostent *nwrap_gethostbyname2(const char *name, int af)
 {
-	return nwrap_files_gethostbyname(name, af);
+	if (nwrap_files_gethostbyname(name, af, &user_he2, &user_addrlist2) == -1) {
+		return NULL;
+	}
+	return &user_he2;
 }
 
 struct hostent *gethostbyname2(const char *name, int af)
@@ -4650,11 +4817,16 @@ static const struct addrinfo default_hints =
 static int nwrap_convert_he_ai(const struct hostent *he,
 			       unsigned short port,
 			       const struct addrinfo *hints,
-			       struct addrinfo **pai)
+			       struct addrinfo **pai,
+			       bool skip_canonname)
 {
 	struct addrinfo *ai;
 	socklen_t socklen;
 
+	if (he == NULL) {
+		return EAI_MEMORY;
+	}
+
 	switch (he->h_addrtype) {
 		case AF_INET:
 			socklen = sizeof(struct sockaddr_in);
@@ -4677,6 +4849,7 @@ static int nwrap_convert_he_ai(const struct hostent *he,
 	ai->ai_family = he->h_addrtype;
 	ai->ai_socktype = hints->ai_socktype;
 	ai->ai_protocol = hints->ai_protocol;
+	ai->ai_canonname = NULL;
 
 	ai->ai_addrlen = socklen;
 	ai->ai_addr = (void *)(ai + 1);
@@ -4713,7 +4886,9 @@ static int nwrap_convert_he_ai(const struct hostent *he,
 			sin6p->sin6_port = htons(port);
 			sin6p->sin6_family = AF_INET6;
 
-			memcpy(&sin6p->sin6_addr, he->h_addr_list[0], he->h_length);
+			memcpy(&sin6p->sin6_addr,
+			       he->h_addr_list[0],
+			       he->h_length);
 		}
 		break;
 #endif
@@ -4721,7 +4896,7 @@ static int nwrap_convert_he_ai(const struct hostent *he,
 
 	ai->ai_next = NULL;
 
-	if (he->h_name) {
+	if (he->h_name && !skip_canonname) {
 		ai->ai_canonname = strdup(he->h_name);
 		if (ai->ai_canonname == NULL) {
 			freeaddrinfo(ai);
@@ -4740,8 +4915,8 @@ static int nwrap_getaddrinfo(const char *node,
 {
 	struct addrinfo *ai = NULL;
 	struct addrinfo *p = NULL;
+	struct addrinfo *ai_tail;
 	unsigned short port = 0;
-	struct hostent *he;
 	struct {
 		int family;
 		union {
@@ -4761,24 +4936,27 @@ static int nwrap_getaddrinfo(const char *node,
 		return EAI_NONAME;
 	}
 
+	if (hints == NULL) {
+		hints = &default_hints;
+	}
+
+        /* EAI_BADFLAGS
+              hints.ai_flags   contains   invalid  flags;  or,  hints.ai_flags
+              included AI_CANONNAME and name was NULL.
+	*/
+	if ((hints->ai_flags & AI_CANONNAME) && (node == NULL)) {
+		return EAI_BADFLAGS;
+	}
+
 	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);
@@ -4822,37 +5000,23 @@ static int nwrap_getaddrinfo(const char *node,
 #endif
 	}
 
+	rc = -1;
 	if (addr.family == AF_INET) {
-		he = nwrap_files_gethostbyaddr(&addr.in.v4,
-					       sizeof(struct in_addr),
-					       addr.family);
-		if (he != NULL) {
-			rc = nwrap_convert_he_ai(he, port, hints, &ai);
-		} else {
-			eai = EAI_NODATA;
-			rc = -1;
+		ai = nwrap_files_getaddrinfo(node, port, hints, &ai_tail);
+		if (ai != NULL) {
+			rc = 1;
 		}
 #ifdef HAVE_IPV6
 	} else if (addr.family == AF_INET6) {
-		he = nwrap_files_gethostbyaddr(&addr.in.v6,
-					       sizeof(struct in6_addr),
-					       addr.family);
-		if (he != NULL) {
-			rc = nwrap_convert_he_ai(he, port, hints, &ai);
-			eai = rc;
-		} else {
-			eai = EAI_NODATA;
-			rc = -1;
+		ai = nwrap_files_getaddrinfo(node, port, hints, &ai_tail);
+		if (ai != NULL) {
+			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;
+		ai = nwrap_files_getaddrinfo(node, port, hints, &ai_tail);
+		if (ai != NULL) {
+			rc = 1;
 		}
 	}
 
@@ -4878,25 +5042,46 @@ static int nwrap_getaddrinfo(const char *node,
 
 	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;
-		}
+		struct addrinfo *ai_head = ai;
+		struct addrinfo *ai_tmp;
+		struct addrinfo *ai_new_tail = ai_tail;
+
+		/* Add at least one more struct */
+		do {
+			/* CHECKS! */
+			ai_tmp = malloc(sizeof(struct addrinfo));
+			memcpy(ai_tmp, ai_head, sizeof(struct addrinfo));
+			ai_tmp->ai_next = NULL;
+
+			/* We need a deep copy or freeaddrinfo() will blow up */
+			if (ai_head->ai_canonname != NULL) {
+				ai_tmp->ai_canonname =
+					strdup(ai_head->ai_canonname);
+			}
+			ai_tmp->ai_addr = malloc(sizeof(struct sockaddr));
+			memcpy(ai_tmp->ai_addr, ai_head, sizeof(struct sockaddr));
 
-		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 */
-		}
+			if (ai_head->ai_flags == 0) {
+				ai_tmp->ai_flags = hints->ai_flags;
+			}
+			if (ai_head->ai_socktype == SOCK_DGRAM) {
+				ai_tmp->ai_socktype = SOCK_STREAM;
+			} else if (ai_head->ai_socktype == SOCK_STREAM) {
+				ai_tmp->ai_socktype = SOCK_DGRAM;
+			}
+			if (ai_head->ai_socktype == SOCK_DGRAM) {
+				ai_tmp->ai_protocol = 17; /* UDP */
+			} else if (ai_head->ai_socktype == SOCK_STREAM) {
+				ai_tmp->ai_protocol = 6; /* TCP */
+			}
+			ai_new_tail->ai_next = ai_tmp;
+			ai_new_tail = ai_tmp;
+
+			if (ai_head == ai_tail) {
+				break;
+			}
+			ai_head = ai_head->ai_next;
+		} while (1);
 	}
 
 	*res = ai;
@@ -5121,7 +5306,6 @@ void nwrap_destructor(void)
 			c->fd = -1;
 		}
 
-		SAFE_FREE(nwrap_he_global.list);
 		nwrap_he_global.num = 0;
 	}
 
-- 
2.5.0


From 80d46ef9dfd3b4e46c4068f06922293222467e35 Mon Sep 17 00:00:00 2001
From: Robin Hack <hack.robin at gmail.com>
Date: Fri, 27 Mar 2015 15:51:11 +0100
Subject: [PATCH 22/91] nwrap: Add BSD libc support for gethost*_r functios.

BSD libc stores data in thread local storage.

Signed-off-by: Robin Hack <hack.robin at gmail.com>
Reviewed-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index b133e01..f2c2d55 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -4746,8 +4746,14 @@ void endhostent(void)
 }
 #endif /* HAVE_SOLARIS_ENDHOSTENT */
 
+#ifdef BSD
+/* BSD implementation stores data in thread local storage but GLIBC does not */
+static __thread struct hostent user_he;
+static __thread struct nwrap_vector user_addrlist;
+#else
 static struct hostent user_he;
 static struct nwrap_vector user_addrlist;
+#endif /* BSD */
 static struct hostent *nwrap_gethostbyname(const char *name)
 {
 	if (nwrap_files_gethostbyname(name, AF_UNSPEC, &user_he, &user_addrlist) == -1) {
@@ -4765,9 +4771,16 @@ struct hostent *gethostbyname(const char *name)
 	return nwrap_gethostbyname(name);
 }
 
+/* This is a GNU extension - Also can be found on BSD systems */
 #ifdef HAVE_GETHOSTBYNAME2
+#ifdef BSD
+/* BSD implementation stores data in  thread local storage but GLIBC not */
+static __thread struct hostent user_he2;
+static __thread struct nwrap_vector user_addrlist2;
+#else
 static struct hostent user_he2;
 static struct nwrap_vector user_addrlist2;
+#endif /* BSD */
 static struct hostent *nwrap_gethostbyname2(const char *name, int af)
 {
 	if (nwrap_files_gethostbyname(name, af, &user_he2, &user_addrlist2) == -1) {
-- 
2.5.0


From 9edd8d1d9e3cee76c4c51e81b13a56273c319da3 Mon Sep 17 00:00:00 2001
From: Robin Hack <hack.robin at gmail.com>
Date: Tue, 24 Mar 2015 17:54:34 +0100
Subject: [PATCH 23/91] nwrap: Add basic locking for support multithreaded
 applications

Signed-off-by: Robin Hack <hack.robin at gmail.com>
Reviewed-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 91 +++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 87 insertions(+), 4 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index f2c2d55..bf51ec2 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -35,6 +35,8 @@
 
 #include "config.h"
 
+#include <pthread.h>
+
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/socket.h>
@@ -156,6 +158,62 @@ typedef nss_status_t NSS_STATUS;
 #define NWRAP_INET_ADDRSTRLEN INET_ADDRSTRLEN
 #endif
 
+#define NWRAP_LOCK(m) do { \
+	pthread_mutex_lock(&( m ## _mutex)); \
+} while(0)
+
+#define NWRAP_UNLOCK(m) do { \
+	pthread_mutex_unlock(&( m ## _mutex)); \
+} while(0)
+
+
+static bool nwrap_initialized = false;
+static pthread_mutex_t nwrap_initialized_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/* The mutex or accessing the id */
+static pthread_mutex_t nwrap_global_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t nwrap_gr_global_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t nwrap_he_global_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t nwrap_pw_global_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t nwrap_sp_global_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/* Add new global locks here please */
+/* Also don't forget to add locks to
+ * nwrap_init() function.
+ */
+# define NWRAP_LOCK_ALL do { \
+	NWRAP_LOCK(nwrap_initialized); \
+	NWRAP_LOCK(nwrap_global); \
+	NWRAP_LOCK(nwrap_gr_global); \
+	NWRAP_LOCK(nwrap_he_global); \
+	NWRAP_LOCK(nwrap_pw_global); \
+	NWRAP_LOCK(nwrap_sp_global); \
+} while (0);
+
+# define NWRAP_UNLOCK_ALL do {\
+	NWRAP_UNLOCK(nwrap_sp_global); \
+	NWRAP_UNLOCK(nwrap_pw_global); \
+	NWRAP_UNLOCK(nwrap_he_global); \
+	NWRAP_UNLOCK(nwrap_gr_global); \
+	NWRAP_UNLOCK(nwrap_global); \
+	NWRAP_UNLOCK(nwrap_initialized); \
+} while (0);
+
+static void nwrap_thread_prepare(void)
+{
+	NWRAP_LOCK_ALL;
+}
+
+static void nwrap_thread_parent(void)
+{
+	NWRAP_UNLOCK_ALL;
+}
+
+static void nwrap_thread_child(void)
+{
+	NWRAP_UNLOCK_ALL;
+}
+
 enum nwrap_dbglvl_e {
 	NWRAP_LOG_ERROR = 0,
 	NWRAP_LOG_WARN,
@@ -1465,13 +1523,32 @@ static void nwrap_backend_init(struct nwrap_main *r)
 
 static void nwrap_init(void)
 {
-	static bool initialized;
 	const char *env;
 	char *endptr;
 	size_t max_hostents_tmp;
 
-	if (initialized) return;
-	initialized = true;
+	NWRAP_LOCK(nwrap_initialized);
+	if (nwrap_initialized) {
+		NWRAP_UNLOCK(nwrap_initialized);
+		return;
+	}
+
+	/*
+	 * Still holding nwrap_initialized lock here.
+	 * We don't use NWRAP_(UN)LOCK_ALL macros here because we
+	 * want to avoid overhead when other threads do their job.
+	 */
+	NWRAP_LOCK(nwrap_global);
+	NWRAP_LOCK(nwrap_gr_global);
+	NWRAP_LOCK(nwrap_he_global);
+	NWRAP_LOCK(nwrap_pw_global);
+	NWRAP_LOCK(nwrap_sp_global);
+
+	nwrap_initialized = true;
+
+	/* Initialize pthread_atfork handlers */
+	pthread_atfork(&nwrap_thread_prepare, &nwrap_thread_parent,
+		       &nwrap_thread_child);
 
 	env = getenv("NSS_WRAPPER_MAX_HOSTENTS");
 	if (env != NULL) {
@@ -1493,7 +1570,7 @@ static void nwrap_init(void)
 	if (hcreate(max_hostents) == 0) {
 		NWRAP_LOG(NWRAP_LOG_ERROR,
 			  "Failed to initialize hash table");
-		return;
+		goto done;
 	}
 
 	nwrap_main_global = &__nwrap_main_global;
@@ -1543,6 +1620,10 @@ static void nwrap_init(void)
 	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;
+
+done:
+	/* We hold all locks here so we can use NWRAP_UNLOCK_ALL. */
+	NWRAP_UNLOCK_ALL;
 }
 
 bool nss_wrapper_enabled(void)
@@ -5256,6 +5337,7 @@ void nwrap_destructor(void)
 {
 	int i;
 
+	NWRAP_LOCK_ALL;
 	if (nwrap_main_global != NULL) {
 		struct nwrap_main *m = nwrap_main_global;
 
@@ -5323,4 +5405,5 @@ void nwrap_destructor(void)
 	}
 
 	hdestroy();
+	NWRAP_UNLOCK_ALL;
 }
-- 
2.5.0


From cc165a139bba1ed26f553e517be2d71fc3a47f02 Mon Sep 17 00:00:00 2001
From: Robin Hack <hack.robin at gmail.com>
Date: Thu, 8 Oct 2015 11:36:33 +0200
Subject: [PATCH 24/91] nwrap: Fix memory leak when getline() is used.

getline() allocates memory even if return code is < 0.

Signed-off-by: Robin Hack <hack.robin at gmail.com>
Reviewed-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index bf51ec2..2759cd7 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -1705,6 +1705,7 @@ static bool nwrap_parse_file(struct nwrap_cache *nwrap)
 	do {
 		n = getline(&line, &len, nwrap->fp);
 		if (n < 0) {
+			SAFE_FREE(line);
 			if (feof(nwrap->fp)) {
 				break;
 			}
-- 
2.5.0


From 83c180d37dd325d2abb7a8b3a78de269cf9f8291 Mon Sep 17 00:00:00 2001
From: Robin Hack <hack.robin at gmail.com>
Date: Thu, 8 Oct 2015 14:00:38 +0200
Subject: [PATCH 25/91] nwrap: Use nwrap_vector_foreach instead of for loop

Replace for loop by nwrap_vector_foreach in nwrap_lines_unload().

Signed-off-by: Robin Hack <hack.robin at gmail.com>
Reviewed-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 2759cd7..393fa6e 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -928,12 +928,13 @@ static void *_nwrap_load_lib_function(enum nwrap_lib lib, const char *fn_name)
 static void nwrap_lines_unload(struct nwrap_cache *const nwrap)
 {
 	size_t p;
-	for (p = 0; p < nwrap->lines.count; p++) {
+	void *item;
+	nwrap_vector_foreach(item, nwrap->lines, p) {
 		/* Maybe some vectors were merged ... */
-		SAFE_FREE(nwrap->lines.items[p]);
+		SAFE_FREE(item);
 	}
 	SAFE_FREE(nwrap->lines.items);
-	nwrap->lines.count = 0;
+	ZERO_STRUCTP(&nwrap->lines);
 }
 
 /*
-- 
2.5.0


From fe9c0a8f8d31ad4148acd545dc051c66809044d7 Mon Sep 17 00:00:00 2001
From: Robin Hack <hack.robin at gmail.com>
Date: Thu, 8 Oct 2015 14:02:56 +0200
Subject: [PATCH 26/91] nwrap: Fix memory leak inside nwrap_getaddrinfo()

Memory leak was introduced by deep copy code.
Item ai_tmp->ai_addr should not have deep copy.

Signed-off-by: Robin Hack <hack.robin at gmail.com>
Reviewed-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 393fa6e..77015a5 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -5154,8 +5154,8 @@ static int nwrap_getaddrinfo(const char *node,
 				ai_tmp->ai_canonname =
 					strdup(ai_head->ai_canonname);
 			}
-			ai_tmp->ai_addr = malloc(sizeof(struct sockaddr));
-			memcpy(ai_tmp->ai_addr, ai_head, sizeof(struct sockaddr));
+			/* ai_head should point inside hints. */
+			ai_tmp->ai_addr = ai_head->ai_addr;
 
 			if (ai_head->ai_flags == 0) {
 				ai_tmp->ai_flags = hints->ai_flags;
-- 
2.5.0


From b6bad8923d69db68006ccc0535eeeaccec6cf5a4 Mon Sep 17 00:00:00 2001
From: Robin Hack <hack.robin at gmail.com>
Date: Thu, 8 Oct 2015 14:09:11 +0200
Subject: [PATCH 27/91] nwrap: Rename cont to vector in nwrap_vector_add_item()

Signed-off-by: Robin Hack <hack.robin at gmail.com>
Reviewed-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 77015a5..6d83a98 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -622,32 +622,32 @@ static inline bool nwrap_vector_init(struct nwrap_vector *const vector)
 	return true;
 }
 
-static bool nwrap_vector_add_item(struct nwrap_vector *cont, void *const item)
+static bool nwrap_vector_add_item(struct nwrap_vector *vector, void *const item)
 {
-	assert (cont != NULL);
+	assert (vector != NULL);
 
-	if (cont->items == NULL) {
-		nwrap_vector_init(cont);
+	if (vector->items == NULL) {
+		nwrap_vector_init(vector);
 	}
 
-	if (cont->count == cont->capacity) {
+	if (vector->count == vector->capacity) {
 		/* Items array _MUST_ be NULL terminated because it's passed
 		 * as result to caller which expect NULL terminated array from libc.
 		 */
-		void **items = realloc(cont->items, sizeof(void *) * ((cont->capacity * 2) + 1));
+		void **items = realloc(vector->items, sizeof(void *) * ((vector->capacity * 2) + 1));
 		if (items == NULL) {
 			return false;
 		}
-		cont->items = items;
+		vector->items = items;
 
 		/* Don't count ending NULL to capacity */
-		cont->capacity *= 2;
+		vector->capacity *= 2;
 	}
 
-	cont->items[cont->count] = item;
+	vector->items[vector->count] = item;
 
-	cont->count += 1;
-	cont->items[cont->count] = NULL;
+	vector->count += 1;
+	vector->items[vector->count] = NULL;
 
 	return true;
 }
-- 
2.5.0


From acca6237bf637a59ac176c3d43b13abcc07733b3 Mon Sep 17 00:00:00 2001
From: Robin Hack <hack.robin at gmail.com>
Date: Thu, 8 Oct 2015 15:00:33 +0200
Subject: [PATCH 28/91] nwrap: Fix memory leak in nwrap_he_unload()

Signed-off-by: Robin Hack <hack.robin at gmail.com>
Reviewed-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 6d83a98..3496162 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2854,6 +2854,7 @@ static void nwrap_he_unload(struct nwrap_cache *nwrap)
 
 	nwrap_vector_foreach (ed, nwrap_he->entdata, i)
 	{
+		SAFE_FREE(ed->nwrap_addrdata.items);
 		SAFE_FREE(ed->ht.h_aliases);
 		SAFE_FREE(ed);
 	}
-- 
2.5.0


From c3e55ba69605d11568e2e798c557324051d573ac Mon Sep 17 00:00:00 2001
From: Robin Hack <hack.robin at gmail.com>
Date: Thu, 8 Oct 2015 15:27:47 +0200
Subject: [PATCH 29/91] nwrap: Fix memory leak in nwrap_files_gethostbyname()

Signed-off-by: Robin Hack <hack.robin at gmail.com>
Reviewed-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 3496162..970b5b0 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -604,6 +604,8 @@ struct nwrap_vector {
 	     item != NULL; \
 	     (item) = (vect).items[++iter])
 
+#define nwrap_vector_is_initialized(vector) ((vector)->items != NULL)
+
 static inline bool nwrap_vector_init(struct nwrap_vector *const vector)
 {
 	if (vector == NULL) {
@@ -3323,10 +3325,16 @@ static int nwrap_files_gethostbyname(const char *name, int af,
 	SAFE_FREE(h_name_lower);
 
 	/* Always cleanup vector and results */
-	if (!nwrap_vector_init(addr_list)) {
-		NWRAP_LOG(NWRAP_LOG_DEBUG,
-			  "Unable to initialize memory for addr_list vector");
-		goto no_ent;
+	if (!nwrap_vector_is_initialized(addr_list)) {
+		if (!nwrap_vector_init(addr_list)) {
+			NWRAP_LOG(NWRAP_LOG_DEBUG,
+				  "Unable to initialize memory for addr_list vector");
+			goto no_ent;
+		}
+	} else {
+		/* When vector is initialized data are valid no more.
+		 * Quick way how to free vector is: */
+		addr_list->count = 0;
 	}
 
 	/* Iterate through results */
-- 
2.5.0


From e884fd1501e654b6f2f561475b81765be16f6f68 Mon Sep 17 00:00:00 2001
From: Robin Hack <hack.robin at gmail.com>
Date: Mon, 12 Oct 2015 10:36:04 +0200
Subject: [PATCH 30/91] nwrap: Fix memory leak in nwrap_gethostbyname_r()

Fix reimplements how memory is used.
Results from vector are copied to user provided buf.

Signed-off-by: Robin Hack <hack.robin at gmail.com>
Reviewed-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 970b5b0..f85395e 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -3406,7 +3406,21 @@ static int nwrap_gethostbyname_r(const char *name,
 		return -1;
 	}
 
-	memset(buf, '\0', buflen);
+	if (buflen < (addr_list->count * sizeof(void *))) {
+		SAFE_FREE(addr_list->items);
+		SAFE_FREE(addr_list);
+		return ERANGE;
+	}
+
+	/* Copy all to user provided buffer and change
+	 * pointers in returned structure.
+	 * +1 is for ending NULL pointer. */
+	memcpy(buf, addr_list->items, (addr_list->count + 1) * sizeof(void *));
+
+	free(addr_list->items);
+	free(addr_list);
+
+	ret->h_addr_list = (char **)buf;
 	*result = ret;
 	return 0;
 }
-- 
2.5.0


From a2a0f2ea73bf673506dc0a7bbdebb4d97d3632dd Mon Sep 17 00:00:00 2001
From: Robin Hack <hack.robin at gmail.com>
Date: Tue, 13 Oct 2015 14:41:14 +0200
Subject: [PATCH 31/91] nwrap: Better check service string sanity.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=11501

Patch use strtol() instead of atoi() to convert strings to numbers.
This helps better check sanity of service input string.

Signed-off-by: Robin Hack <hack.robin at gmail.com>
Reviewed-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 47 ++++++++++++++++++++++++++-----------------
 1 file changed, 28 insertions(+), 19 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index f85395e..21fc108 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -5077,33 +5077,42 @@ static int nwrap_getaddrinfo(const char *node,
 	}
 
 	if (service != NULL && service[0] != '\0') {
-		if (isdigit((int)service[0])) {
-			port = (unsigned short)atoi(service);
-		} else {
-			const char *proto = NULL;
-			struct servent *s;
+		const char *proto = NULL;
+		struct servent *s;
+		char *end_ptr;
+		long sl;
 
-			if (hints->ai_protocol != 0) {
-				struct protoent *pent;
+		errno = 0;
+		sl = strtol(service, &end_ptr, 10);
 
-				pent = getprotobynumber(hints->ai_protocol);
-				if (pent != NULL) {
-					proto = pent->p_name;
-				}
+		if (*end_ptr == '\0' || end_ptr != service) {
+			port = sl;
+			goto valid_port;
+		} else if (hints->ai_flags & AI_NUMERICSERV) {
+			return EAI_SERVICE;
+		}
+
+		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;
+		s = getservbyname(service, proto);
+		if (s != NULL) {
+			port = ntohs(s->s_port);
+		} else {
+			if (p != NULL) {
+				freeaddrinfo(p);
 			}
+			return EAI_SERVICE;
 		}
 	}
 
+valid_port:
 	rc = 0;
 	if (hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET) {
 		rc = inet_pton(AF_INET, node, &addr.in.v4);
-- 
2.5.0


From 081b69d74623d45415dca85433526be9d66650b7 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Fri, 6 Nov 2015 10:22:10 +0100
Subject: [PATCH 32/91] nwrap: fix numeric port detection in nwrap_getaddrinfo

Only a string that can be converted to a number, is
allowed as a numeric port specification. Trailing
characters are not allowed.

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 21fc108..5fd3d7b 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -5085,7 +5085,7 @@ static int nwrap_getaddrinfo(const char *node,
 		errno = 0;
 		sl = strtol(service, &end_ptr, 10);
 
-		if (*end_ptr == '\0' || end_ptr != service) {
+		if (*end_ptr == '\0') {
 			port = sl;
 			goto valid_port;
 		} else if (hints->ai_flags & AI_NUMERICSERV) {
-- 
2.5.0


From 6b3dc3ba0f458832c505c7a8938cb37a75ff7a3d Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Fri, 6 Nov 2015 10:45:15 +0100
Subject: [PATCH 33/91] nwrap: fix return code of getaddrinfo for
 AI_NUMERICSERV in error case

If the AI_NUMERICSERV flag is specified, the the port number
has to specified as a string representing a decimal number
or left NULL.

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 5fd3d7b..9404d17 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -5089,7 +5089,7 @@ static int nwrap_getaddrinfo(const char *node,
 			port = sl;
 			goto valid_port;
 		} else if (hints->ai_flags & AI_NUMERICSERV) {
-			return EAI_SERVICE;
+			return EAI_NONAME;
 		}
 
 		if (hints->ai_protocol != 0) {
-- 
2.5.0


From 2dc9309da4682052d12a7b083bec38a8f3d996ac Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Fri, 6 Nov 2015 11:00:54 +0100
Subject: [PATCH 34/91] nwrap: fix return code for getaddrinfo in case service
 is not valid

If the specified service is not a valid service name (or port number),
EAI_NONAME should be returned.

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 9404d17..986b974 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -5108,7 +5108,7 @@ static int nwrap_getaddrinfo(const char *node,
 			if (p != NULL) {
 				freeaddrinfo(p);
 			}
-			return EAI_SERVICE;
+			return EAI_NONAME;
 		}
 	}
 
-- 
2.5.0


From 0aa346a9501b9ce27315483e94a6dcd90fecb6c6 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Fri, 6 Nov 2015 11:28:35 +0100
Subject: [PATCH 35/91] nwrap: remove code duplication in nwrap_getaddrinfo

The three formerly distinct cases now are all the same.

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 20 +++-----------------
 1 file changed, 3 insertions(+), 17 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 986b974..63d5325 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -5129,23 +5129,9 @@ valid_port:
 	}
 
 	rc = -1;
-	if (addr.family == AF_INET) {
-		ai = nwrap_files_getaddrinfo(node, port, hints, &ai_tail);
-		if (ai != NULL) {
-			rc = 1;
-		}
-#ifdef HAVE_IPV6
-	} else if (addr.family == AF_INET6) {
-		ai = nwrap_files_getaddrinfo(node, port, hints, &ai_tail);
-		if (ai != NULL) {
-			rc = 1;
-		}
-#endif
-	} else {
-		ai = nwrap_files_getaddrinfo(node, port, hints, &ai_tail);
-		if (ai != NULL) {
-			rc = 1;
-		}
+	ai = nwrap_files_getaddrinfo(node, port, hints, &ai_tail);
+	if (ai != NULL) {
+		rc = 1;
 	}
 
 	if (rc < 0) {
-- 
2.5.0


From 50a4870cba78f81585798712398ce92e3f4a5d3a Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Fri, 6 Nov 2015 11:31:09 +0100
Subject: [PATCH 36/91] nwrap: improve code readability in nwrap_getaddrinfo()

Untangle a (a ? b : c) statement and add an explanatory
comment, since the intention is not immediately obvious.

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 63d5325..3dce079 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -5135,7 +5135,15 @@ valid_port:
 	}
 
 	if (rc < 0) {
-		return ret == 0 ? 0 : eai;
+		if (ret == 0) {
+			/*
+			 * nwrap_files_getaddrinfo failed, but libc was
+			 * successful -- use the result from libc.
+			 */
+			return 0;
+		}
+
+		return eai;
 	}
 
 	if (ret == 0) {
-- 
2.5.0


From fd6754c61e57795c442e93f5c6bb18285523f28b Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Fri, 6 Nov 2015 11:48:40 +0100
Subject: [PATCH 37/91] nwrap: simplify logic in nwrap_getaddrinfo, calling
 nwrap_files_getaddrinfo

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 3dce079..2f4388b 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -5047,7 +5047,6 @@ static int nwrap_getaddrinfo(const char *node,
 	} addr = {
 		.family = AF_UNSPEC,
 	};
-	int eai = EAI_SYSTEM;
 	int ret;
 	int rc;
 
@@ -5128,13 +5127,8 @@ valid_port:
 #endif
 	}
 
-	rc = -1;
 	ai = nwrap_files_getaddrinfo(node, port, hints, &ai_tail);
-	if (ai != NULL) {
-		rc = 1;
-	}
-
-	if (rc < 0) {
+	if (ai == NULL) {
 		if (ret == 0) {
 			/*
 			 * nwrap_files_getaddrinfo failed, but libc was
@@ -5143,7 +5137,7 @@ valid_port:
 			return 0;
 		}
 
-		return eai;
+		return EAI_SYSTEM;
 	}
 
 	if (ret == 0) {
-- 
2.5.0


From 0447cdea5087b2b61ea4a370e7e7a33dcf9998cf Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Fri, 6 Nov 2015 11:52:08 +0100
Subject: [PATCH 38/91] nwrap: slightly simplify logic in nwrap_getaddrinfo()

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 2f4388b..e50e18f 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -5048,7 +5048,6 @@ static int nwrap_getaddrinfo(const char *node,
 		.family = AF_UNSPEC,
 	};
 	int ret;
-	int rc;
 
 	if (node == NULL && service == NULL) {
 		return EAI_NONAME;
@@ -5112,20 +5111,20 @@ static int nwrap_getaddrinfo(const char *node,
 	}
 
 valid_port:
-	rc = 0;
 	if (hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET) {
-		rc = inet_pton(AF_INET, node, &addr.in.v4);
+		int rc = inet_pton(AF_INET, node, &addr.in.v4);
+		if (rc == 1) {
+			addr.family = AF_INET;
+		}
 	}
-	if (rc == 1) {
-		addr.family = AF_INET;
 #ifdef HAVE_IPV6
-	} else {
-		rc = inet_pton(AF_INET6, node, &addr.in.v6);
+	if (addr.family == AF_UNSPEC) {
+		int rc = inet_pton(AF_INET6, node, &addr.in.v6);
 		if (rc == 1) {
 			addr.family = AF_INET6;
 		}
-#endif
 	}
+#endif
 
 	ai = nwrap_files_getaddrinfo(node, port, hints, &ai_tail);
 	if (ai == NULL) {
-- 
2.5.0


From aa91f854efb6bc311f0185aeedfa93400261230b Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Fri, 6 Nov 2015 11:43:04 +0100
Subject: [PATCH 39/91] nwrap: in nwrap_getaddrinfo, only call libc_getaddrinfo
 if we need it.

Instead of calling libc_getaddrinfo on spec and throwing
away the result when we are certain that we don't need it,
call libc only if we really need it.

This fixes another memleak for the libc result.

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 27 ++++++++++++++-------------
 1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index e50e18f..e1edd7e 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -5033,7 +5033,6 @@ static int nwrap_getaddrinfo(const char *node,
 			     struct addrinfo **res)
 {
 	struct addrinfo *ai = NULL;
-	struct addrinfo *p = NULL;
 	struct addrinfo *ai_tail;
 	unsigned short port = 0;
 	struct {
@@ -5047,7 +5046,6 @@ static int nwrap_getaddrinfo(const char *node,
 	} addr = {
 		.family = AF_UNSPEC,
 	};
-	int ret;
 
 	if (node == NULL && service == NULL) {
 		return EAI_NONAME;
@@ -5065,12 +5063,16 @@ static int nwrap_getaddrinfo(const char *node,
 		return EAI_BADFLAGS;
 	}
 
-	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) {
+		int ret;
+		struct addrinfo *p = NULL;
+
+		ret = libc_getaddrinfo(node, service, hints, &p);
+
+		if (ret == 0) {
+			*res = p;
+		}
 		return ret;
 	}
 
@@ -5103,9 +5105,6 @@ static int nwrap_getaddrinfo(const char *node,
 		if (s != NULL) {
 			port = ntohs(s->s_port);
 		} else {
-			if (p != NULL) {
-				freeaddrinfo(p);
-			}
 			return EAI_NONAME;
 		}
 	}
@@ -5128,21 +5127,23 @@ valid_port:
 
 	ai = nwrap_files_getaddrinfo(node, port, hints, &ai_tail);
 	if (ai == NULL) {
+		int ret;
+		struct addrinfo *p = NULL;
+
+		ret = libc_getaddrinfo(node, service, hints, &p);
+
 		if (ret == 0) {
 			/*
 			 * nwrap_files_getaddrinfo failed, but libc was
 			 * successful -- use the result from libc.
 			 */
+			*res = p;
 			return 0;
 		}
 
 		return EAI_SYSTEM;
 	}
 
-	if (ret == 0) {
-		freeaddrinfo(p);
-	}
-
 	if (ai->ai_flags == 0) {
 		ai->ai_flags = hints->ai_flags;
 	}
-- 
2.5.0


From b0cac54ba87e368b15b856b209a79267ca26ec96 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Mon, 9 Nov 2015 00:55:00 +0100
Subject: [PATCH 40/91] nwrap: slightly clean flow by removing an else branch
 in nwrap_getaddrinfo

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index e1edd7e..988eb1d 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -5102,11 +5102,10 @@ static int nwrap_getaddrinfo(const char *node,
 		}
 
 		s = getservbyname(service, proto);
-		if (s != NULL) {
-			port = ntohs(s->s_port);
-		} else {
+		if (s == NULL) {
 			return EAI_NONAME;
 		}
+		port = ntohs(s->s_port);
 	}
 
 valid_port:
-- 
2.5.0


From 2649729c72a4002950361a150cc04cf1d7c31e34 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Mon, 9 Nov 2015 17:35:29 +0100
Subject: [PATCH 41/91] nwrap: initialize some variables in
 nwrap_files_getaddrinfo

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 988eb1d..ccb219c 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -3458,8 +3458,8 @@ static struct addrinfo *nwrap_files_getaddrinfo(const char *name,
 	size_t name_len;
 	char canon_name[DNS_NAME_MAX] = { 0 };
 	bool skip_canonname = false;
-	ENTRY e;
-	ENTRY *e_p;
+	ENTRY e = { 0 };
+	ENTRY *e_p = NULL;
 
 	nwrap_files_cache_reload(nwrap_he_global.cache);
 
-- 
2.5.0


From a6dc62fd38ed0a6554719c569664a993d7f06606 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Mon, 9 Nov 2015 17:36:07 +0100
Subject: [PATCH 42/91] nwrap: simplify nwrap_add_hname_alias

This always uses the provided h_name_a alias name.
No need to fall back to the fqdn name from the entry.

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index ccb219c..821c50f 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2594,32 +2594,30 @@ static void nwrap_add_hname_add_to_existing(struct nwrap_entdata *const ed,
 	}
 }
 
-static bool nwrap_add_hname_alias(const char *const h_name_a,
+static bool nwrap_add_hname_alias(char *const h_name_a,
 				  struct nwrap_entdata *const ed)
 {
-	/* One of argument 'h_hame_a' are "optional" */
-	char *const h_name = (char *const) ((h_name_a == NULL) ? ed->ht.h_name : h_name_a);
 	ENTRY e;
 	ENTRY *p;
 
 	/* Maybe it's little bit late ... */
 	assert(ed != NULL);
-	assert(h_name != NULL);
+	assert(h_name_a != NULL);
 
-	e.key = h_name;
+	e.key = h_name_a;
 	e.data = NULL;
 	NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching name: %s", e.key);
 	p = hsearch(e, FIND);
 	if (p == NULL) {
-		NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found. Adding...", h_name);
+		NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found. Adding...", h_name_a);
 		/* Just add alias and don't mess with metadata */
-		nwrap_add_hname_add_new(h_name, ed);
+		nwrap_add_hname_add_new(h_name_a, ed);
 	} else {
 		/* Element found. Add them to end of list */
 		struct nwrap_entdata *ed_dst = (struct nwrap_entdata *)p->data;
 
 		assert(p->data != NULL);
-		NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s found. Add record to list.", h_name);
+		NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s found. Add record to list.", h_name_a);
 		nwrap_add_hname_add_to_existing(ed, ed_dst);
 	}
 
-- 
2.5.0


From 230633ef0d960c0b7abcf791e837b86dd2b783b8 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Mon, 9 Nov 2015 17:36:37 +0100
Subject: [PATCH 43/91] nwrap: simplify nwrap_add_hname

This is never given an alias name, so remove
the h_name_a argument.

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 821c50f..0837c7c 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2624,11 +2624,9 @@ static bool nwrap_add_hname_alias(char *const h_name_a,
 	return true;
 }
 
-static bool nwrap_add_hname(const char *const h_name_a,
-			    struct nwrap_entdata *const ed)
+static bool nwrap_add_hname(struct nwrap_entdata *const ed)
 {
-	/* One of argument 'h_hame_a' are "optional" */
-	char *const h_name = (char *const) ((h_name_a == NULL) ? ed->ht.h_name : h_name_a);
+	char *const h_name = (char *const)(ed->ht.h_name);
 	ENTRY e;
 	ENTRY *p;
 	char *h_name_alias;
@@ -2838,7 +2836,7 @@ static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line)
 
 	ed->aliases_count = aliases_count;
 	/* Inventarize item */
-	nwrap_add_hname(NULL, ed);
+	nwrap_add_hname(ed);
 	nwrap_add_ai(ip, ed);
 
 	nwrap_he->num++;
-- 
2.5.0


From 301aac0050fbf9f1fd6522b689524b82b809f377 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Mon, 9 Nov 2015 17:41:43 +0100
Subject: [PATCH 44/91] nwrap: move var into scope in nwrap_add_hname()

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 0837c7c..c114ea0 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2629,7 +2629,6 @@ static bool nwrap_add_hname(struct nwrap_entdata *const ed)
 	char *const h_name = (char *const)(ed->ht.h_name);
 	ENTRY e;
 	ENTRY *p;
-	char *h_name_alias;
 	unsigned i;
 
 	/* Maybe it's little bit late ... */
@@ -2664,6 +2663,8 @@ static bool nwrap_add_hname(struct nwrap_entdata *const ed)
 
 	/* Itemize aliases */
 	for (i = 0; ed->ht.h_aliases[i] != NULL; ++i) {
+		char *h_name_alias;
+
 		h_name_alias = ed->ht.h_aliases[i];
 		assert(h_name_alias != NULL);
 
-- 
2.5.0


From 430f94af1f1014d4ad953881d505307a20036bfe Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Tue, 10 Nov 2015 12:32:20 +0100
Subject: [PATCH 45/91] nwrap: remove a superfluous comment from
 nwrap_add_hname_add_new()

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index c114ea0..02d5f35 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2562,7 +2562,6 @@ static bool nwrap_add_ai(char *const ip_addr, struct nwrap_entdata *const ed)
 static bool nwrap_add_hname_add_new(char *const h_name,
 				    struct nwrap_entdata *const ed)
 {
-	/* No element found.. inventarize new item */
 	ENTRY e;
 	ENTRY *p;
 
-- 
2.5.0


From bec8b054807ce6c56a872aca129833915f6f4fbb Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 11 Nov 2015 10:21:10 +0100
Subject: [PATCH 46/91] nwrap: remove superfluous comments from
 nwrap_add_hname_alias()

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 02d5f35..4b93f2d 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2599,7 +2599,6 @@ static bool nwrap_add_hname_alias(char *const h_name_a,
 	ENTRY e;
 	ENTRY *p;
 
-	/* Maybe it's little bit late ... */
 	assert(ed != NULL);
 	assert(h_name_a != NULL);
 
@@ -2609,10 +2608,8 @@ static bool nwrap_add_hname_alias(char *const h_name_a,
 	p = hsearch(e, FIND);
 	if (p == NULL) {
 		NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found. Adding...", h_name_a);
-		/* Just add alias and don't mess with metadata */
 		nwrap_add_hname_add_new(h_name_a, ed);
 	} else {
-		/* Element found. Add them to end of list */
 		struct nwrap_entdata *ed_dst = (struct nwrap_entdata *)p->data;
 
 		assert(p->data != NULL);
-- 
2.5.0


From 4cec44e29953213477e160e470bf13d8d3fc51a3 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 11 Nov 2015 10:21:30 +0100
Subject: [PATCH 47/91] nwrap: remove superfluous comments from
 nwrap_add_hname()

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 4b93f2d..bca1012 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2627,7 +2627,6 @@ static bool nwrap_add_hname(struct nwrap_entdata *const ed)
 	ENTRY *p;
 	unsigned i;
 
-	/* Maybe it's little bit late ... */
 	assert(ed != NULL);
 	assert(h_name != NULL);
 
@@ -2637,14 +2636,12 @@ static bool nwrap_add_hname(struct nwrap_entdata *const ed)
 	p = hsearch(e, FIND);
 	if (p == NULL) {
 		NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found. Adding...", h_name);
-		/* Just add alias and don't mess with metadata */
 		nwrap_add_hname_add_new(h_name, ed);
 
 		if (ed->ed_tail == NULL) {
 			ed->ed_tail = ed;
 		}
 	} else {
-		/* Element found. Add them to end of list */
 		struct nwrap_entdata *ed_dst = (struct nwrap_entdata *)p->data;
 
 		assert(p->data != NULL);
@@ -2652,7 +2649,6 @@ static bool nwrap_add_hname(struct nwrap_entdata *const ed)
 		nwrap_add_hname_add_to_existing(ed, ed_dst);
 	}
 
-	/* Return true when list of aliases is empty */
 	if (ed->ht.h_aliases == NULL) {
 		return true;
 	}
-- 
2.5.0


From c6b5989532a0fbdc9b947e1487d951051f990694 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 11 Nov 2015 10:27:50 +0100
Subject: [PATCH 48/91] nwrap: rewrite linked-list datastructures to be
 properly separated.

The data structures were wrong:

- The nwrap_entdata structures reflects one line of the hosts
  file, with ip, fqdn and aliases.
  But they also had a linked list structure.

- Now the hash table was used to point each
  ip address, fqdn and alias name occurring in the hosts
  file to the list of lines (entdata structs) that contain
  this name/address.

The problem was that these list heads were pointing to the same
entdata structures, while the list should actually be individual
for each entity (ip, fqdn, alias). This lead to wrong assiciations
of lines to IP addresse and also endless loops in the list, when
one line was put into one list twice starting from two different
points.

This patch fixes this by lifting the linked list structure to
a layer nwrap_entlist above nwrap_entdata. The entlist
entries just contain pointers to the entdata, and hence
each line can be referenced independetly by several lists.

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 115 +++++++++++++++++++++++++++++-------------
 1 file changed, 79 insertions(+), 36 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index bca1012..6676b6a 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -758,9 +758,11 @@ struct nwrap_entdata {
 	struct nwrap_vector nwrap_addrdata;
 
 	ssize_t aliases_count;
+};
 
-	struct nwrap_entdata *ed_next;
-	struct nwrap_entdata *ed_tail;
+struct nwrap_entlist {
+	struct nwrap_entlist *next;
+	struct nwrap_entdata *ed;
 };
 
 struct nwrap_he {
@@ -2541,13 +2543,41 @@ static int nwrap_gr_copy_r(const struct group *src, struct group *dst,
 	return 0;
 }
 
+static struct nwrap_entlist *nwrap_entlist_init(struct nwrap_entdata *ed)
+{
+	struct nwrap_entlist *el;
+
+	if (ed == NULL) {
+		NWRAP_LOG(NWRAP_LOG_ERROR,
+			  "entry is NULL, can't create list item");
+		return NULL;
+	}
+
+	el = (struct nwrap_entlist *)malloc(sizeof(struct nwrap_entlist));
+	if (el == NULL) {
+		NWRAP_LOG(NWRAP_LOG_ERROR, "malloc failed");
+		return NULL;
+	}
+
+	el->next = NULL;
+	el->ed = ed;
+
+	return el;
+}
+
 static bool nwrap_add_ai(char *const ip_addr, struct nwrap_entdata *const ed)
 {
-	ENTRY e = {
-		.key = ip_addr,
-		.data = (void *)ed,
-	};
+	ENTRY e;
 	ENTRY *p;
+	struct nwrap_entlist *el;
+
+	el = nwrap_entlist_init(ed);
+	if (el == NULL) {
+		return false;
+	}
+
+	e.key = ip_addr;
+	e.data = el;
 
 	p = hsearch(e, ENTER);
 	if (p == NULL) {
@@ -2564,11 +2594,15 @@ static bool nwrap_add_hname_add_new(char *const h_name,
 {
 	ENTRY e;
 	ENTRY *p;
+	struct nwrap_entlist *el;
+
+	el = nwrap_entlist_init(ed);
+	if (el == NULL) {
+		return false;
+	}
 
 	e.key = h_name;
-	e.data = (void *)ed;
-	ed->ed_tail = NULL;
-	ed->ed_next = NULL;
+	e.data = (void *)el;
 
 	p = hsearch(e, ENTER);
 	if (p == NULL) {
@@ -2580,17 +2614,30 @@ static bool nwrap_add_hname_add_new(char *const h_name,
 }
 
 static void nwrap_add_hname_add_to_existing(struct nwrap_entdata *const ed,
-					    struct nwrap_entdata *const ed_dst)
+					    struct nwrap_entlist *const el)
 {
-	if (ed_dst->ed_tail != NULL) {
-		ed_dst->ed_tail->ed_next = ed;
-		if (ed_dst->ed_tail != ed) {
-			ed_dst->ed_tail = ed;
-			ed->ed_next = NULL;
+	struct nwrap_entlist *cursor;
+	struct nwrap_entlist *el_new;
+
+	el_new = nwrap_entlist_init(ed);
+	if (el_new == NULL) {
+		return;
+	}
+
+	for (cursor = el; cursor->next != NULL; cursor = cursor->next)
+	{
+		if (cursor->ed == ed) {
+			free(el_new);
+			return;
 		}
-	} else {
-		ed_dst->ed_tail = ed;
 	}
+
+	if (cursor->ed == ed) {
+		free(el_new);
+		return;
+	}
+
+	cursor->next = el_new;
 }
 
 static bool nwrap_add_hname_alias(char *const h_name_a,
@@ -2610,11 +2657,11 @@ static bool nwrap_add_hname_alias(char *const h_name_a,
 		NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found. Adding...", h_name_a);
 		nwrap_add_hname_add_new(h_name_a, ed);
 	} else {
-		struct nwrap_entdata *ed_dst = (struct nwrap_entdata *)p->data;
+		struct nwrap_entlist *el = (struct nwrap_entlist *)p->data;
 
 		assert(p->data != NULL);
 		NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s found. Add record to list.", h_name_a);
-		nwrap_add_hname_add_to_existing(ed, ed_dst);
+		nwrap_add_hname_add_to_existing(ed, el);
 	}
 
 	return true;
@@ -2637,16 +2684,12 @@ static bool nwrap_add_hname(struct nwrap_entdata *const ed)
 	if (p == NULL) {
 		NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found. Adding...", h_name);
 		nwrap_add_hname_add_new(h_name, ed);
-
-		if (ed->ed_tail == NULL) {
-			ed->ed_tail = ed;
-		}
 	} else {
-		struct nwrap_entdata *ed_dst = (struct nwrap_entdata *)p->data;
+		struct nwrap_entlist *el = (struct nwrap_entlist *)p->data;
 
 		assert(p->data != NULL);
 		NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s found. Add record to list.", h_name);
-		nwrap_add_hname_add_to_existing(ed, ed_dst);
+		nwrap_add_hname_add_to_existing(ed, el);
 	}
 
 	if (ed->ht.h_aliases == NULL) {
@@ -3277,8 +3320,8 @@ static int nwrap_files_gethostbyname(const char *name, int af,
 				     struct hostent *result,
 				     struct nwrap_vector *addr_list)
 {
-	struct nwrap_entdata *ed_head;
-	struct nwrap_entdata *ed_cur;
+	struct nwrap_entlist *el_head;
+	struct nwrap_entlist *el_cur;
 	struct hostent *he;
 	char *h_name_lower;
 	ENTRY e;
@@ -3327,9 +3370,9 @@ static int nwrap_files_gethostbyname(const char *name, int af,
 	}
 
 	/* Iterate through results */
-	ed_head = (struct nwrap_entdata *)e_p->data;
-	for (ed_cur = ed_head; ed_cur != NULL; ed_cur = ed_cur->ed_next) {
-		he = &(ed_cur->ht);
+	el_head = (struct nwrap_entlist *)e_p->data;
+	for (el_cur = el_head; el_cur != NULL; el_cur = el_cur->next) {
+		he = &(el_cur->ed->ht);
 
 		/* Filter by address familiy if provided */
 		if (af != AF_UNSPEC && he->h_addrtype != af) {
@@ -3351,7 +3394,7 @@ static int nwrap_files_gethostbyname(const char *name, int af,
 				  he->h_name);
 			he_found = true;
 		}
-		nwrap_vector_merge(addr_list, &ed_cur->nwrap_addrdata);
+		nwrap_vector_merge(addr_list, &el_cur->ed->nwrap_addrdata);
 		result->h_addr_list = nwrap_vector_head(addr_list);
 	}
 
@@ -3437,8 +3480,8 @@ static struct addrinfo *nwrap_files_getaddrinfo(const char *name,
 					        const struct addrinfo *hints,
 					        struct addrinfo **ai_tail)
 {
-	struct nwrap_entdata *ed_head;
-	struct nwrap_entdata *ed_cur;
+	struct nwrap_entlist *el_head;
+	struct nwrap_entlist *el_cur;
 	struct hostent *he;
 	struct addrinfo *ai = NULL;
 	struct addrinfo *ai_head = NULL;
@@ -3477,12 +3520,12 @@ static struct addrinfo *nwrap_files_getaddrinfo(const char *name,
 	NWRAP_LOG(NWRAP_LOG_DEBUG, "Name: %s found.", h_name_lower);
 	SAFE_FREE(h_name_lower);
 
-	ed_head = (struct nwrap_entdata *)e_p->data;
+	el_head = (struct nwrap_entlist *)e_p->data;
 
-	for (ed_cur = ed_head; ed_cur != NULL; ed_cur = ed_cur->ed_next) {
+	for (el_cur = el_head; el_cur != NULL; el_cur = el_cur->next) {
 		int rc;
 
-		he = &(ed_cur->ht);
+		he = &(el_cur->ed->ht);
 
 		if (hints->ai_family != AF_UNSPEC &&
 		    he->h_addrtype != hints->ai_family) {
-- 
2.5.0


From cf297e706d7d93732e8a95371e6652fddec511c0 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 11 Nov 2015 11:30:13 +0100
Subject: [PATCH 49/91] nwrap: log hash table full message at error level

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 6676b6a..4f9251e 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2581,7 +2581,7 @@ static bool nwrap_add_ai(char *const ip_addr, struct nwrap_entdata *const ed)
 
 	p = hsearch(e, ENTER);
 	if (p == NULL) {
-		NWRAP_LOG(NWRAP_LOG_DEBUG, "Hash table is full");
+		NWRAP_LOG(NWRAP_LOG_ERROR, "Hash table is full");
 		return false;
 	}
 
@@ -2606,7 +2606,7 @@ static bool nwrap_add_hname_add_new(char *const h_name,
 
 	p = hsearch(e, ENTER);
 	if (p == NULL) {
-		NWRAP_LOG(NWRAP_LOG_DEBUG, "Hash table is full!");
+		NWRAP_LOG(NWRAP_LOG_ERROR, "Hash table is full!");
 		return false;
 	}
 
-- 
2.5.0


From 86dbe7cd37e4b9b57424db052118cba506876d78 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 11 Nov 2015 10:36:07 +0100
Subject: [PATCH 50/91] nwrap: simplify nwrap_files_gethostbyname: remove a
 variable

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 4f9251e..653b8d7 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -3320,8 +3320,7 @@ static int nwrap_files_gethostbyname(const char *name, int af,
 				     struct hostent *result,
 				     struct nwrap_vector *addr_list)
 {
-	struct nwrap_entlist *el_head;
-	struct nwrap_entlist *el_cur;
+	struct nwrap_entlist *el;
 	struct hostent *he;
 	char *h_name_lower;
 	ENTRY e;
@@ -3370,9 +3369,9 @@ static int nwrap_files_gethostbyname(const char *name, int af,
 	}
 
 	/* Iterate through results */
-	el_head = (struct nwrap_entlist *)e_p->data;
-	for (el_cur = el_head; el_cur != NULL; el_cur = el_cur->next) {
-		he = &(el_cur->ed->ht);
+	for (el = (struct nwrap_entlist *)e_p->data; el != NULL; el = el->next)
+	{
+		he = &(el->ed->ht);
 
 		/* Filter by address familiy if provided */
 		if (af != AF_UNSPEC && he->h_addrtype != af) {
@@ -3394,7 +3393,7 @@ static int nwrap_files_gethostbyname(const char *name, int af,
 				  he->h_name);
 			he_found = true;
 		}
-		nwrap_vector_merge(addr_list, &el_cur->ed->nwrap_addrdata);
+		nwrap_vector_merge(addr_list, &el->ed->nwrap_addrdata);
 		result->h_addr_list = nwrap_vector_head(addr_list);
 	}
 
-- 
2.5.0


From be4e62670e15d2f0aa7ce23938256a5a4e635968 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 11 Nov 2015 10:38:31 +0100
Subject: [PATCH 51/91] nwrap: simplify nwrap_file_getaddrinfo: remove a
 variable

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 653b8d7..b55e24e 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -3479,8 +3479,7 @@ static struct addrinfo *nwrap_files_getaddrinfo(const char *name,
 					        const struct addrinfo *hints,
 					        struct addrinfo **ai_tail)
 {
-	struct nwrap_entlist *el_head;
-	struct nwrap_entlist *el_cur;
+	struct nwrap_entlist *el;
 	struct hostent *he;
 	struct addrinfo *ai = NULL;
 	struct addrinfo *ai_head = NULL;
@@ -3519,12 +3518,11 @@ static struct addrinfo *nwrap_files_getaddrinfo(const char *name,
 	NWRAP_LOG(NWRAP_LOG_DEBUG, "Name: %s found.", h_name_lower);
 	SAFE_FREE(h_name_lower);
 
-	el_head = (struct nwrap_entlist *)e_p->data;
-
-	for (el_cur = el_head; el_cur != NULL; el_cur = el_cur->next) {
+	for (el = (struct nwrap_entlist *)e_p->data; el != NULL; el = el->next)
+	{
 		int rc;
 
-		he = &(el_cur->ed->ht);
+		he = &(el->ed->ht);
 
 		if (hints->ai_family != AF_UNSPEC &&
 		    he->h_addrtype != hints->ai_family) {
-- 
2.5.0


From ac4558ae704551480dcf8edfa29fa057cf5c6c0c Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 11 Nov 2015 11:56:59 +0100
Subject: [PATCH 52/91] nwrap: turn nwrap_add_hname_add_to_existing() into bool

for better error propagation.

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index b55e24e..aee5ff7 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2613,7 +2613,7 @@ static bool nwrap_add_hname_add_new(char *const h_name,
 	return true;
 }
 
-static void nwrap_add_hname_add_to_existing(struct nwrap_entdata *const ed,
+static bool nwrap_add_hname_add_to_existing(struct nwrap_entdata *const ed,
 					    struct nwrap_entlist *const el)
 {
 	struct nwrap_entlist *cursor;
@@ -2621,23 +2621,24 @@ static void nwrap_add_hname_add_to_existing(struct nwrap_entdata *const ed,
 
 	el_new = nwrap_entlist_init(ed);
 	if (el_new == NULL) {
-		return;
+		return false;
 	}
 
 	for (cursor = el; cursor->next != NULL; cursor = cursor->next)
 	{
 		if (cursor->ed == ed) {
 			free(el_new);
-			return;
+			return false;
 		}
 	}
 
 	if (cursor->ed == ed) {
 		free(el_new);
-		return;
+		return false;
 	}
 
 	cursor->next = el_new;
+	return true;
 }
 
 static bool nwrap_add_hname_alias(char *const h_name_a,
-- 
2.5.0


From e17dcb97b46eadd9394d21f68fa7cff43543bf1d Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 11 Nov 2015 12:24:53 +0100
Subject: [PATCH 53/91] nwrap: catch NULL ip in nwrap_add_ai

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index aee5ff7..8b0103e 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2571,6 +2571,11 @@ static bool nwrap_add_ai(char *const ip_addr, struct nwrap_entdata *const ed)
 	ENTRY *p;
 	struct nwrap_entlist *el;
 
+	if (ip_addr == NULL) {
+		NWRAP_LOG(NWRAP_LOG_ERROR, "ip_addr NULL - can't add");
+		return false;
+	}
+
 	el = nwrap_entlist_init(ed);
 	if (el == NULL) {
 		return false;
-- 
2.5.0


From 284bc2db0e746673dea32b6e4a03afcb7eb16f06 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 11 Nov 2015 12:25:30 +0100
Subject: [PATCH 54/91] nwrap: catch null h_name in nwrap_add_hname_add_new

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 8b0103e..d31fca9 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2601,6 +2601,11 @@ static bool nwrap_add_hname_add_new(char *const h_name,
 	ENTRY *p;
 	struct nwrap_entlist *el;
 
+	if (h_name == NULL) {
+		NWRAP_LOG(NWRAP_LOG_ERROR, "h_name NULL - can't add");
+		return false;
+	}
+
 	el = nwrap_entlist_init(ed);
 	if (el == NULL) {
 		return false;
-- 
2.5.0


From 5523651437e1d7bedf19b1824577aeec1c97690f Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 11 Nov 2015 12:26:02 +0100
Subject: [PATCH 55/91] nwrap: catch NULL list in
 nwrap_add_hname_add_to_existing

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index d31fca9..064d3d7 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2629,6 +2629,11 @@ static bool nwrap_add_hname_add_to_existing(struct nwrap_entdata *const ed,
 	struct nwrap_entlist *cursor;
 	struct nwrap_entlist *el_new;
 
+	if (el == NULL) {
+		NWRAP_LOG(NWRAP_LOG_ERROR, "list is NULL, can not add");
+		return false;
+	}
+
 	el_new = nwrap_entlist_init(ed);
 	if (el_new == NULL) {
 		return false;
-- 
2.5.0


From a4d188390b38cf32fb49209fa7bf0f1d8cbe364c Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 11 Nov 2015 12:27:33 +0100
Subject: [PATCH 56/91] nwrap: better error propagation in
 nwrap_add_hname_alias

use return codes from the called function.
Remove asserts becaus the cases are caught
by the called functions.

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 064d3d7..343bff7 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2661,9 +2661,7 @@ static bool nwrap_add_hname_alias(char *const h_name_a,
 {
 	ENTRY e;
 	ENTRY *p;
-
-	assert(ed != NULL);
-	assert(h_name_a != NULL);
+	bool ok;
 
 	e.key = h_name_a;
 	e.data = NULL;
@@ -2671,16 +2669,15 @@ static bool nwrap_add_hname_alias(char *const h_name_a,
 	p = hsearch(e, FIND);
 	if (p == NULL) {
 		NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found. Adding...", h_name_a);
-		nwrap_add_hname_add_new(h_name_a, ed);
+		ok = nwrap_add_hname_add_new(h_name_a, ed);
 	} else {
 		struct nwrap_entlist *el = (struct nwrap_entlist *)p->data;
 
-		assert(p->data != NULL);
 		NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s found. Add record to list.", h_name_a);
-		nwrap_add_hname_add_to_existing(ed, el);
+		ok = nwrap_add_hname_add_to_existing(ed, el);
 	}
 
-	return true;
+	return ok;
 }
 
 static bool nwrap_add_hname(struct nwrap_entdata *const ed)
-- 
2.5.0


From 880fcb9c4d934c87a75f27a02157b39c65b2d58f Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 11 Nov 2015 12:28:58 +0100
Subject: [PATCH 57/91] nwrap: better error propagation in nwrap_add_hname()

Use return codes from called functions.
Remove now unneeded asserts.
Make failure to add an entry for an alias an error.

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 343bff7..9ed11f0 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2686,9 +2686,7 @@ static bool nwrap_add_hname(struct nwrap_entdata *const ed)
 	ENTRY e;
 	ENTRY *p;
 	unsigned i;
-
-	assert(ed != NULL);
-	assert(h_name != NULL);
+	bool ok;
 
 	e.key = h_name;
 	e.data = NULL;
@@ -2696,13 +2694,16 @@ static bool nwrap_add_hname(struct nwrap_entdata *const ed)
 	p = hsearch(e, FIND);
 	if (p == NULL) {
 		NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found. Adding...", h_name);
-		nwrap_add_hname_add_new(h_name, ed);
+		ok = nwrap_add_hname_add_new(h_name, ed);
 	} else {
 		struct nwrap_entlist *el = (struct nwrap_entlist *)p->data;
 
-		assert(p->data != NULL);
 		NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s found. Add record to list.", h_name);
-		nwrap_add_hname_add_to_existing(ed, el);
+		ok = nwrap_add_hname_add_to_existing(ed, el);
+	}
+
+	if (!ok) {
+		return false;
 	}
 
 	if (ed->ht.h_aliases == NULL) {
@@ -2714,13 +2715,13 @@ static bool nwrap_add_hname(struct nwrap_entdata *const ed)
 		char *h_name_alias;
 
 		h_name_alias = ed->ht.h_aliases[i];
-		assert(h_name_alias != NULL);
 
 		NWRAP_LOG(NWRAP_LOG_DEBUG, "Add alias: %s", h_name_alias);
 
 		if (!nwrap_add_hname_alias(h_name_alias, ed)) {
 			NWRAP_LOG(NWRAP_LOG_DEBUG,
 				  "Unable to add alias: %s", h_name_alias);
+			return false;
 		}
 	}
 
-- 
2.5.0


From e2b171df3797e75a6172301d988ad73f8dd21179 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 11 Nov 2015 12:29:55 +0100
Subject: [PATCH 58/91] nwrap: log NULL alias name at ERROR level in
 nwrap_add_hname()

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 9ed11f0..71f5980 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2719,7 +2719,7 @@ static bool nwrap_add_hname(struct nwrap_entdata *const ed)
 		NWRAP_LOG(NWRAP_LOG_DEBUG, "Add alias: %s", h_name_alias);
 
 		if (!nwrap_add_hname_alias(h_name_alias, ed)) {
-			NWRAP_LOG(NWRAP_LOG_DEBUG,
+			NWRAP_LOG(NWRAP_LOG_ERROR,
 				  "Unable to add alias: %s", h_name_alias);
 			return false;
 		}
-- 
2.5.0


From ca0bad125dbbe2919aefb1a1fe904743b4daaa30 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 11 Nov 2015 12:30:36 +0100
Subject: [PATCH 59/91] nwrap: better error propagation in
 nwrap_he_parse_line()

Use the return codes of nwrap_add_hname() and nwrap_add_ai().

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 71f5980..fd2a967 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2738,6 +2738,7 @@ static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line)
 	char *n;
 
 	char *ip;
+	bool ok;
 
 	struct nwrap_entdata *ed = (struct nwrap_entdata *)
 				   malloc(sizeof(struct nwrap_entdata));
@@ -2886,8 +2887,15 @@ static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line)
 
 	ed->aliases_count = aliases_count;
 	/* Inventarize item */
-	nwrap_add_hname(ed);
-	nwrap_add_ai(ip, ed);
+	ok = nwrap_add_hname(ed);
+	if (!ok) {
+		return false;
+	}
+
+	ok = nwrap_add_ai(ip, ed);
+	if (!ok) {
+		return false;
+	}
 
 	nwrap_he->num++;
 	return true;
-- 
2.5.0


From 7e8d3abc1271673c57cb506cd2b8432f52305eb6 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 11 Nov 2015 12:33:12 +0100
Subject: [PATCH 60/91] nwrap: turn nwrap_files_cache_reload() into a bool
 function

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index fd2a967..bcf92a4 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -1761,7 +1761,7 @@ static void nwrap_files_cache_unload(struct nwrap_cache *nwrap)
 	nwrap_lines_unload(nwrap);
 }
 
-static void nwrap_files_cache_reload(struct nwrap_cache *nwrap)
+static bool nwrap_files_cache_reload(struct nwrap_cache *nwrap)
 {
 	struct stat st;
 	int ret;
@@ -1779,7 +1779,7 @@ reopen:
 				  "Unable to open '%s' readonly %d:%s",
 				  nwrap->path, nwrap->fd,
 				  strerror(errno));
-			return;
+			return false;
 
 		}
 		nwrap->fd = fileno(nwrap->fp);
@@ -1796,7 +1796,7 @@ reopen:
 		fclose(nwrap->fp);
 		nwrap->fp = NULL;
 		nwrap->fd = -1;
-		return;
+		return false;
 	}
 
 	if (retried == false && st.st_nlink == 0) {
@@ -1816,7 +1816,7 @@ reopen:
 		NWRAP_LOG(NWRAP_LOG_TRACE,
 			  "st_mtime[%u] hasn't changed, skip reload",
 			  (unsigned)st.st_mtime);
-		return;
+		return true;
 	}
 
 	NWRAP_LOG(NWRAP_LOG_TRACE,
@@ -1832,9 +1832,11 @@ reopen:
 	if (!ok) {
 		NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to reload %s", nwrap->path);
 		nwrap_files_cache_unload(nwrap);
+		return false;
 	}
 
 	NWRAP_LOG(NWRAP_LOG_TRACE, "Reloaded %s", nwrap->path);
+	return true;
 }
 
 /*
-- 
2.5.0


From 97678ca5a46982c9a3223676d47d0a09427c5079 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 11 Nov 2015 12:47:15 +0100
Subject: [PATCH 61/91] nwrap: use the error code from
 nwrap_files_cache_reload() in callers

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 87 +++++++++++++++++++++++++++++++++++++------
 1 file changed, 75 insertions(+), 12 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index bcf92a4..9767a5e 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2929,12 +2929,17 @@ static struct passwd *nwrap_files_getpwnam(struct nwrap_backend *b,
 					   const char *name)
 {
 	int i;
+	bool ok;
 
 	(void) b; /* unused */
 
 	NWRAP_LOG(NWRAP_LOG_DEBUG, "Lookup user %s in files", name);
 
-	nwrap_files_cache_reload(nwrap_pw_global.cache);
+	ok = nwrap_files_cache_reload(nwrap_pw_global.cache);
+	if (!ok) {
+		NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading passwd file");
+		return NULL;
+	}
 
 	for (i=0; i<nwrap_pw_global.num; i++) {
 		if (strcmp(nwrap_pw_global.list[i].pw_name, name) == 0) {
@@ -2974,10 +2979,15 @@ static struct passwd *nwrap_files_getpwuid(struct nwrap_backend *b,
 					   uid_t uid)
 {
 	int i;
+	bool ok;
 
 	(void) b; /* unused */
 
-	nwrap_files_cache_reload(nwrap_pw_global.cache);
+	ok = nwrap_files_cache_reload(nwrap_pw_global.cache);
+	if (!ok) {
+		NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading passwd file");
+		return NULL;
+	}
 
 	for (i=0; i<nwrap_pw_global.num; i++) {
 		if (nwrap_pw_global.list[i].pw_uid == uid) {
@@ -3028,7 +3038,12 @@ static struct passwd *nwrap_files_getpwent(struct nwrap_backend *b)
 	(void) b; /* unused */
 
 	if (nwrap_pw_global.idx == 0) {
-		nwrap_files_cache_reload(nwrap_pw_global.cache);
+		bool ok;
+		ok = nwrap_files_cache_reload(nwrap_pw_global.cache);
+		if (!ok) {
+			NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading passwd file");
+			return NULL;
+		}
 	}
 
 	if (nwrap_pw_global.idx >= nwrap_pw_global.num) {
@@ -3084,7 +3099,13 @@ static struct spwd *nwrap_files_getspent(void)
 	struct spwd *sp;
 
 	if (nwrap_sp_global.idx == 0) {
-		nwrap_files_cache_reload(nwrap_sp_global.cache);
+		bool ok;
+
+		ok = nwrap_files_cache_reload(nwrap_sp_global.cache);
+		if (!ok) {
+			NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading shadow file");
+			return NULL;
+		}
 	}
 
 	if (nwrap_sp_global.idx >= nwrap_sp_global.num) {
@@ -3110,10 +3131,15 @@ static void nwrap_files_endspent(void)
 static struct spwd *nwrap_files_getspnam(const char *name)
 {
 	int i;
+	bool ok;
 
 	NWRAP_LOG(NWRAP_LOG_DEBUG, "Lookup user %s in files", name);
 
-	nwrap_files_cache_reload(nwrap_sp_global.cache);
+	ok = nwrap_files_cache_reload(nwrap_sp_global.cache);
+	if (!ok) {
+		NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading shadow file");
+		return NULL;
+	}
 
 	for (i=0; i<nwrap_sp_global.num; i++) {
 		if (strcmp(nwrap_sp_global.list[i].sp_namp, name) == 0) {
@@ -3201,10 +3227,15 @@ static struct group *nwrap_files_getgrnam(struct nwrap_backend *b,
 					  const char *name)
 {
 	int i;
+	bool ok;
 
 	(void) b; /* unused */
 
-	nwrap_files_cache_reload(nwrap_gr_global.cache);
+	ok = nwrap_files_cache_reload(nwrap_gr_global.cache);
+	if (!ok) {
+		NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading group file");
+		return NULL;
+	}
 
 	for (i=0; i<nwrap_gr_global.num; i++) {
 		if (strcmp(nwrap_gr_global.list[i].gr_name, name) == 0) {
@@ -3244,10 +3275,15 @@ static struct group *nwrap_files_getgrgid(struct nwrap_backend *b,
 					  gid_t gid)
 {
 	int i;
+	bool ok;
 
 	(void) b; /* unused */
 
-	nwrap_files_cache_reload(nwrap_gr_global.cache);
+	ok = nwrap_files_cache_reload(nwrap_gr_global.cache);
+	if (!ok) {
+		NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading group file");
+		return NULL;
+	}
 
 	for (i=0; i<nwrap_gr_global.num; i++) {
 		if (nwrap_gr_global.list[i].gr_gid == gid) {
@@ -3298,7 +3334,13 @@ static struct group *nwrap_files_getgrent(struct nwrap_backend *b)
 	(void) b; /* unused */
 
 	if (nwrap_gr_global.idx == 0) {
-		nwrap_files_cache_reload(nwrap_gr_global.cache);
+		bool ok;
+
+		ok = nwrap_files_cache_reload(nwrap_gr_global.cache);
+		if (!ok) {
+			NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading group file");
+			return NULL;
+		}
 	}
 
 	if (nwrap_gr_global.idx >= nwrap_gr_global.num) {
@@ -3352,8 +3394,13 @@ static int nwrap_files_gethostbyname(const char *name, int af,
 	char canon_name[DNS_NAME_MAX] = { 0 };
 	size_t name_len;
 	bool he_found = false;
+	bool ok;
 
-	nwrap_files_cache_reload(nwrap_he_global.cache);
+	ok = nwrap_files_cache_reload(nwrap_he_global.cache);
+	if (!ok) {
+		NWRAP_LOG(NWRAP_LOG_ERROR, "error loading hosts file");
+		goto no_ent;
+	}
 
 	name_len = strlen(name);
 	if (name_len < sizeof(canon_name) && name[name_len - 1] == '.') {
@@ -3514,8 +3561,13 @@ static struct addrinfo *nwrap_files_getaddrinfo(const char *name,
 	bool skip_canonname = false;
 	ENTRY e = { 0 };
 	ENTRY *e_p = NULL;
+	bool ok;
 
-	nwrap_files_cache_reload(nwrap_he_global.cache);
+	ok = nwrap_files_cache_reload(nwrap_he_global.cache);
+	if (!ok) {
+		NWRAP_LOG(NWRAP_LOG_ERROR, "error loading hosts file");
+		return NULL;
+	}
 
 	name_len = strlen(name);
 	if (name_len < DNS_NAME_MAX && name[name_len - 1] == '.') {
@@ -3588,10 +3640,15 @@ static struct hostent *nwrap_files_gethostbyaddr(const void *addr,
 	struct nwrap_entdata *ed;
 	const char *a;
 	size_t i;
+	bool ok;
 
 	(void) len; /* unused */
 
-	nwrap_files_cache_reload(nwrap_he_global.cache);
+	ok = nwrap_files_cache_reload(nwrap_he_global.cache);
+	if (!ok) {
+		NWRAP_LOG(NWRAP_LOG_ERROR, "error loading hosts file");
+		return NULL;
+	}
 
 	a = inet_ntop(type, addr, ip, sizeof(ip));
 	if (a == NULL) {
@@ -3663,7 +3720,13 @@ static struct hostent *nwrap_files_gethostent(void)
 	struct hostent *he;
 
 	if (nwrap_he_global.idx == 0) {
-		nwrap_files_cache_reload(nwrap_he_global.cache);
+		bool ok;
+
+		ok = nwrap_files_cache_reload(nwrap_he_global.cache);
+		if (!ok) {
+			NWRAP_LOG(NWRAP_LOG_ERROR, "Error loading hosts file");
+			return NULL;
+		}
 	}
 
 	if (nwrap_he_global.idx >= nwrap_he_global.num) {
-- 
2.5.0


From 6ef52d853f993287843b392ac9351dd6e99e626f Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 11 Nov 2015 13:02:59 +0100
Subject: [PATCH 62/91] nwrap: convert nwrap_files_getaddrinfo() to return EAI
 error codes

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 41 ++++++++++++++++++++++-------------------
 1 file changed, 22 insertions(+), 19 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 9767a5e..49bf9bb 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -3545,14 +3545,15 @@ int gethostbyname_r(const char *name,
 }
 #endif
 
-static struct addrinfo *nwrap_files_getaddrinfo(const char *name,
-					        unsigned short port,
-					        const struct addrinfo *hints,
-					        struct addrinfo **ai_tail)
+static int nwrap_files_getaddrinfo(const char *name,
+				   unsigned short port,
+				   const struct addrinfo *hints,
+				   struct addrinfo **ai,
+				   struct addrinfo **ai_tail)
 {
 	struct nwrap_entlist *el;
 	struct hostent *he;
-	struct addrinfo *ai = NULL;
+	struct addrinfo *_ai = NULL;
 	struct addrinfo *ai_head = NULL;
 	struct addrinfo *ai_prev = NULL;
 	char *h_name_lower;
@@ -3566,7 +3567,7 @@ static struct addrinfo *nwrap_files_getaddrinfo(const char *name,
 	ok = nwrap_files_cache_reload(nwrap_he_global.cache);
 	if (!ok) {
 		NWRAP_LOG(NWRAP_LOG_ERROR, "error loading hosts file");
-		return NULL;
+		return EAI_SYSTEM;
 	}
 
 	name_len = strlen(name);
@@ -3578,7 +3579,7 @@ static struct addrinfo *nwrap_files_getaddrinfo(const char *name,
 	if (!str_tolower_copy(&h_name_lower, name)) {
 		NWRAP_LOG(NWRAP_LOG_DEBUG,
 			  "Out of memory while converting to lower case");
-		return NULL;
+		return EAI_MEMORY;
 	}
 
 	NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching for name: %s", h_name_lower);
@@ -3589,7 +3590,7 @@ static struct addrinfo *nwrap_files_getaddrinfo(const char *name,
 		NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found.", h_name_lower);
 		SAFE_FREE(h_name_lower);
 		errno = ENOENT;
-		return NULL;
+		return EAI_NONAME;
 	}
 	NWRAP_LOG(NWRAP_LOG_DEBUG, "Name: %s found.", h_name_lower);
 	SAFE_FREE(h_name_lower);
@@ -3609,7 +3610,7 @@ static struct addrinfo *nwrap_files_getaddrinfo(const char *name,
 		rc = nwrap_convert_he_ai(he,
 					 port,
 					 hints,
-					 &ai,
+					 &_ai,
 					 skip_canonname);
 		if (rc != 0) {
 			/* FIXME: Investigate if this is nice to do... */
@@ -3620,16 +3621,17 @@ static struct addrinfo *nwrap_files_getaddrinfo(const char *name,
 		skip_canonname = true;
 
 		if (ai_head == NULL) {
-			ai_head = ai;
+			ai_head = _ai;
 		}
 		if (ai_prev != NULL) {
-			ai_prev->ai_next = ai;
+			ai_prev->ai_next = _ai;
 		}
-		ai_prev = ai;
+		ai_prev = _ai;
 	}
 
-	*ai_tail = ai;
-	return ai_head;
+	*ai = ai_head;
+	*ai_tail = _ai;
+	return 0;
 }
 
 static struct hostent *nwrap_files_gethostbyaddr(const void *addr,
@@ -5162,6 +5164,7 @@ static int nwrap_getaddrinfo(const char *node,
 	} addr = {
 		.family = AF_UNSPEC,
 	};
+	int rc;
 
 	if (node == NULL && service == NULL) {
 		return EAI_NONAME;
@@ -5226,22 +5229,22 @@ static int nwrap_getaddrinfo(const char *node,
 
 valid_port:
 	if (hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET) {
-		int rc = inet_pton(AF_INET, node, &addr.in.v4);
+		rc = inet_pton(AF_INET, node, &addr.in.v4);
 		if (rc == 1) {
 			addr.family = AF_INET;
 		}
 	}
 #ifdef HAVE_IPV6
 	if (addr.family == AF_UNSPEC) {
-		int rc = inet_pton(AF_INET6, node, &addr.in.v6);
+		rc = inet_pton(AF_INET6, node, &addr.in.v6);
 		if (rc == 1) {
 			addr.family = AF_INET6;
 		}
 	}
 #endif
 
-	ai = nwrap_files_getaddrinfo(node, port, hints, &ai_tail);
-	if (ai == NULL) {
+	rc = nwrap_files_getaddrinfo(node, port, hints, &ai, &ai_tail);
+	if (rc != 0) {
 		int ret;
 		struct addrinfo *p = NULL;
 
@@ -5256,7 +5259,7 @@ valid_port:
 			return 0;
 		}
 
-		return EAI_SYSTEM;
+		return rc;
 	}
 
 	if (ai->ai_flags == 0) {
-- 
2.5.0


From e373c2ea9ebf773e3f391236dbdeb9476e923dd6 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 11 Nov 2015 13:04:15 +0100
Subject: [PATCH 63/91] nwrap: in nwrap_files_getaddrinfo, treat failure of
 nwrap_convert_he_ai as error

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 49bf9bb..1554777 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -3613,10 +3613,9 @@ static int nwrap_files_getaddrinfo(const char *name,
 					 &_ai,
 					 skip_canonname);
 		if (rc != 0) {
-			/* FIXME: Investigate if this is nice to do... */
 			NWRAP_LOG(NWRAP_LOG_ERROR,
 				  "Error in converting he to ai! Skipping.");
-			continue;
+			return rc;
 		}
 		skip_canonname = true;
 
-- 
2.5.0


From 64c187dba4ca2ea61d9a9cd43c042d506aeb052f Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 12 Nov 2015 08:01:57 +0100
Subject: [PATCH 64/91] nwrap: correctly track EAI_ADDRINFO in
 nwrap_files_getaddrinfo

When looping through the entry list and remember the
EAI_ADDRINFO case, so that we can differentiate
the cases
- no entry found at all
- an entry found buy wrong address type

Adapt return codes accordingly.

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 27 +++++++++++++++++++--------
 1 file changed, 19 insertions(+), 8 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 1554777..eaac7ef 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -3562,6 +3562,7 @@ static int nwrap_files_getaddrinfo(const char *name,
 	bool skip_canonname = false;
 	ENTRY e = { 0 };
 	ENTRY *e_p = NULL;
+	int rc;
 	bool ok;
 
 	ok = nwrap_files_cache_reload(nwrap_he_global.cache);
@@ -3595,27 +3596,32 @@ static int nwrap_files_getaddrinfo(const char *name,
 	NWRAP_LOG(NWRAP_LOG_DEBUG, "Name: %s found.", h_name_lower);
 	SAFE_FREE(h_name_lower);
 
+	rc = EAI_NONAME;
 	for (el = (struct nwrap_entlist *)e_p->data; el != NULL; el = el->next)
 	{
-		int rc;
+		int rc2;
 
 		he = &(el->ed->ht);
 
 		if (hints->ai_family != AF_UNSPEC &&
-		    he->h_addrtype != hints->ai_family) {
+		    he->h_addrtype != hints->ai_family)
+		{
+			NWRAP_LOG(NWRAP_LOG_DEBUG,
+				  "Entry found but with wrong AF - "
+				  "remembering EAI_ADDRINFO.");
+			rc = EAI_ADDRFAMILY;
 			continue;
 		}
 
 		/* Function allocates memory and returns it in ai. */
-		rc = nwrap_convert_he_ai(he,
+		rc2 = nwrap_convert_he_ai(he,
 					 port,
 					 hints,
 					 &_ai,
 					 skip_canonname);
-		if (rc != 0) {
-			NWRAP_LOG(NWRAP_LOG_ERROR,
-				  "Error in converting he to ai! Skipping.");
-			return rc;
+		if (rc2 != 0) {
+			NWRAP_LOG(NWRAP_LOG_ERROR, "Error converting he to ai");
+			return rc2;
 		}
 		skip_canonname = true;
 
@@ -3628,9 +3634,14 @@ static int nwrap_files_getaddrinfo(const char *name,
 		ai_prev = _ai;
 	}
 
+	if (ai_head != NULL) {
+		rc = 0;
+	}
+
 	*ai = ai_head;
 	*ai_tail = _ai;
-	return 0;
+
+	return rc;
 }
 
 static struct hostent *nwrap_files_gethostbyaddr(const void *addr,
-- 
2.5.0


From 61b2f3f33c5cc440f582d5e12e9e80cfadb42905 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 12 Nov 2015 08:16:18 +0100
Subject: [PATCH 65/91] nwrap: fix treatment of EAI_ADDRINFO in
 nwrap_files_getaddrinfo

Checking whether the passed in name (node) is a valid IPv6 or IPv4
address, we can do the checking for these two error conditions
properly up front.

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index eaac7ef..770058c 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -5238,11 +5238,10 @@ static int nwrap_getaddrinfo(const char *node,
 	}
 
 valid_port:
-	if (hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET) {
-		rc = inet_pton(AF_INET, node, &addr.in.v4);
-		if (rc == 1) {
-			addr.family = AF_INET;
-		}
+
+	rc = inet_pton(AF_INET, node, &addr.in.v4);
+	if (rc == 1) {
+		addr.family = AF_INET;
 	}
 #ifdef HAVE_IPV6
 	if (addr.family == AF_UNSPEC) {
@@ -5253,6 +5252,13 @@ valid_port:
 	}
 #endif
 
+	if ((addr.family != AF_UNSPEC) &&
+	    (hints->ai_family != AF_UNSPEC) &&
+	    (hints->ai_family != addr.family))
+	{
+		return EAI_ADDRFAMILY;
+	}
+
 	rc = nwrap_files_getaddrinfo(node, port, hints, &ai, &ai_tail);
 	if (rc != 0) {
 		int ret;
-- 
2.5.0


From ac13b8b43efe3933ecf82cd34db273e3a0b42715 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Mon, 9 Nov 2015 00:29:23 +0100
Subject: [PATCH 66/91] nwrap: treat AI_NUMERICHOST correctly in getaddrinfo.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=11477

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 770058c..25085b4 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -5252,9 +5252,12 @@ valid_port:
 	}
 #endif
 
-	if ((addr.family != AF_UNSPEC) &&
-	    (hints->ai_family != AF_UNSPEC) &&
-	    (hints->ai_family != addr.family))
+	if (addr.family == AF_UNSPEC) {
+	       if (hints->ai_flags & AI_NUMERICHOST) {
+			return EAI_NONAME;
+		}
+	} else if ((hints->ai_family != AF_UNSPEC) &&
+		   (hints->ai_family != addr.family))
 	{
 		return EAI_ADDRFAMILY;
 	}
-- 
2.5.0


From c81c9d43f1d867faa54eff4eefd3c74ed6447c1b Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 12 Nov 2015 08:29:57 +0100
Subject: [PATCH 67/91] nwrap: refactor nwrap_add_hname_* into one
 nwrap_ed_inventarize.

This reduces code duplication and abstracts the logic out.
It was not special to hname or hname_alias.

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 43 +++++++++++++++----------------------------
 1 file changed, 15 insertions(+), 28 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 25085b4..ac38a48 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2596,8 +2596,8 @@ static bool nwrap_add_ai(char *const ip_addr, struct nwrap_entdata *const ed)
 }
 
 
-static bool nwrap_add_hname_add_new(char *const h_name,
-				    struct nwrap_entdata *const ed)
+static bool nwrap_ed_inventarize_add_new(char *const h_name,
+					 struct nwrap_entdata *const ed)
 {
 	ENTRY e;
 	ENTRY *p;
@@ -2625,8 +2625,8 @@ static bool nwrap_add_hname_add_new(char *const h_name,
 	return true;
 }
 
-static bool nwrap_add_hname_add_to_existing(struct nwrap_entdata *const ed,
-					    struct nwrap_entlist *const el)
+static bool nwrap_ed_inventarize_add_to_existing(struct nwrap_entdata *const ed,
+						 struct nwrap_entlist *const el)
 {
 	struct nwrap_entlist *cursor;
 	struct nwrap_entlist *el_new;
@@ -2658,25 +2658,27 @@ static bool nwrap_add_hname_add_to_existing(struct nwrap_entdata *const ed,
 	return true;
 }
 
-static bool nwrap_add_hname_alias(char *const h_name_a,
-				  struct nwrap_entdata *const ed)
+static bool nwrap_ed_inventarize(char *const name,
+				 struct nwrap_entdata *const ed)
 {
 	ENTRY e;
 	ENTRY *p;
 	bool ok;
 
-	e.key = h_name_a;
+	e.key = name;
 	e.data = NULL;
+
 	NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching name: %s", e.key);
+
 	p = hsearch(e, FIND);
 	if (p == NULL) {
-		NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found. Adding...", h_name_a);
-		ok = nwrap_add_hname_add_new(h_name_a, ed);
+		NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found. Adding...", name);
+		ok = nwrap_ed_inventarize_add_new(name, ed);
 	} else {
 		struct nwrap_entlist *el = (struct nwrap_entlist *)p->data;
 
-		NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s found. Add record to list.", h_name_a);
-		ok = nwrap_add_hname_add_to_existing(ed, el);
+		NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s found. Add record to list.", name);
+		ok = nwrap_ed_inventarize_add_to_existing(ed, el);
 	}
 
 	return ok;
@@ -2685,25 +2687,10 @@ static bool nwrap_add_hname_alias(char *const h_name_a,
 static bool nwrap_add_hname(struct nwrap_entdata *const ed)
 {
 	char *const h_name = (char *const)(ed->ht.h_name);
-	ENTRY e;
-	ENTRY *p;
 	unsigned i;
 	bool ok;
 
-	e.key = h_name;
-	e.data = NULL;
-	NWRAP_LOG(NWRAP_LOG_DEBUG, "Searching name: %s", e.key);
-	p = hsearch(e, FIND);
-	if (p == NULL) {
-		NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s not found. Adding...", h_name);
-		ok = nwrap_add_hname_add_new(h_name, ed);
-	} else {
-		struct nwrap_entlist *el = (struct nwrap_entlist *)p->data;
-
-		NWRAP_LOG(NWRAP_LOG_DEBUG, "Name %s found. Add record to list.", h_name);
-		ok = nwrap_add_hname_add_to_existing(ed, el);
-	}
-
+	ok = nwrap_ed_inventarize(h_name, ed);
 	if (!ok) {
 		return false;
 	}
@@ -2720,7 +2707,7 @@ static bool nwrap_add_hname(struct nwrap_entdata *const ed)
 
 		NWRAP_LOG(NWRAP_LOG_DEBUG, "Add alias: %s", h_name_alias);
 
-		if (!nwrap_add_hname_alias(h_name_alias, ed)) {
+		if (!nwrap_ed_inventarize(h_name_alias, ed)) {
 			NWRAP_LOG(NWRAP_LOG_ERROR,
 				  "Unable to add alias: %s", h_name_alias);
 			return false;
-- 
2.5.0


From 1951c5cff249ef21afbab474aac67d7ab665e2c4 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 12 Nov 2015 08:34:39 +0100
Subject: [PATCH 68/91] nwrap: Fix inventarization of IPs when loading hosts

Use nwrap_ed_inventarize() instead of nwrap_add_ai().

This not only removes code duplication, but also
more correctly adds more than one line for a given
IP address in a list behind this address.

The original code would only have inventarized
the first line for an IP found.

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 31 +------------------------------
 1 file changed, 1 insertion(+), 30 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index ac38a48..0b57cbc 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2567,35 +2567,6 @@ static struct nwrap_entlist *nwrap_entlist_init(struct nwrap_entdata *ed)
 	return el;
 }
 
-static bool nwrap_add_ai(char *const ip_addr, struct nwrap_entdata *const ed)
-{
-	ENTRY e;
-	ENTRY *p;
-	struct nwrap_entlist *el;
-
-	if (ip_addr == NULL) {
-		NWRAP_LOG(NWRAP_LOG_ERROR, "ip_addr NULL - can't add");
-		return false;
-	}
-
-	el = nwrap_entlist_init(ed);
-	if (el == NULL) {
-		return false;
-	}
-
-	e.key = ip_addr;
-	e.data = el;
-
-	p = hsearch(e, ENTER);
-	if (p == NULL) {
-		NWRAP_LOG(NWRAP_LOG_ERROR, "Hash table is full");
-		return false;
-	}
-
-	return true;
-}
-
-
 static bool nwrap_ed_inventarize_add_new(char *const h_name,
 					 struct nwrap_entdata *const ed)
 {
@@ -2881,7 +2852,7 @@ static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line)
 		return false;
 	}
 
-	ok = nwrap_add_ai(ip, ed);
+	ok = nwrap_ed_inventarize(ip, ed);
 	if (!ok) {
 		return false;
 	}
-- 
2.5.0


From 2f323454055220b60b3a9dc2498c89dacf6f9e4b Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 12 Nov 2015 09:45:50 +0100
Subject: [PATCH 69/91] nwrap: rename ai_prev -> ai_cur in
 nwrap_files_getaddrinfo()

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 0b57cbc..c8d3486 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -3513,7 +3513,7 @@ static int nwrap_files_getaddrinfo(const char *name,
 	struct hostent *he;
 	struct addrinfo *_ai = NULL;
 	struct addrinfo *ai_head = NULL;
-	struct addrinfo *ai_prev = NULL;
+	struct addrinfo *ai_cur = NULL;
 	char *h_name_lower;
 	size_t name_len;
 	char canon_name[DNS_NAME_MAX] = { 0 };
@@ -3586,10 +3586,10 @@ static int nwrap_files_getaddrinfo(const char *name,
 		if (ai_head == NULL) {
 			ai_head = _ai;
 		}
-		if (ai_prev != NULL) {
-			ai_prev->ai_next = _ai;
+		if (ai_cur != NULL) {
+			ai_cur->ai_next = _ai;
 		}
-		ai_prev = _ai;
+		ai_cur = _ai;
 	}
 
 	if (ai_head != NULL) {
-- 
2.5.0


From 3be11bc2717a34e2daeef22a03abef24ed9fdc5f Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 12 Nov 2015 09:46:29 +0100
Subject: [PATCH 70/91] nwrap: fix a memleak in nwrap_files_getaddrinfo()

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index c8d3486..72181b9 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -3579,6 +3579,9 @@ static int nwrap_files_getaddrinfo(const char *name,
 					 skip_canonname);
 		if (rc2 != 0) {
 			NWRAP_LOG(NWRAP_LOG_ERROR, "Error converting he to ai");
+			if (ai_head != NULL) {
+				freeaddrinfo(ai_head);
+			}
 			return rc2;
 		}
 		skip_canonname = true;
-- 
2.5.0


From 3bd9c2195645fa33075d7fadae62cafdf0ede9ed Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 12 Nov 2015 09:47:59 +0100
Subject: [PATCH 71/91] nwrap: rename _ai -> ai_new in
 nwrap_files_getaddrinfo()

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 72181b9..429102a 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -3511,7 +3511,7 @@ static int nwrap_files_getaddrinfo(const char *name,
 {
 	struct nwrap_entlist *el;
 	struct hostent *he;
-	struct addrinfo *_ai = NULL;
+	struct addrinfo *ai_new = NULL;
 	struct addrinfo *ai_head = NULL;
 	struct addrinfo *ai_cur = NULL;
 	char *h_name_lower;
@@ -3575,7 +3575,7 @@ static int nwrap_files_getaddrinfo(const char *name,
 		rc2 = nwrap_convert_he_ai(he,
 					 port,
 					 hints,
-					 &_ai,
+					 &ai_new,
 					 skip_canonname);
 		if (rc2 != 0) {
 			NWRAP_LOG(NWRAP_LOG_ERROR, "Error converting he to ai");
@@ -3587,12 +3587,12 @@ static int nwrap_files_getaddrinfo(const char *name,
 		skip_canonname = true;
 
 		if (ai_head == NULL) {
-			ai_head = _ai;
+			ai_head = ai_new;
 		}
 		if (ai_cur != NULL) {
-			ai_cur->ai_next = _ai;
+			ai_cur->ai_next = ai_new;
 		}
-		ai_cur = _ai;
+		ai_cur = ai_new;
 	}
 
 	if (ai_head != NULL) {
@@ -3600,7 +3600,7 @@ static int nwrap_files_getaddrinfo(const char *name,
 	}
 
 	*ai = ai_head;
-	*ai_tail = _ai;
+	*ai_tail = ai_new;
 
 	return rc;
 }
-- 
2.5.0


From c015572f68519444535492962d3bd0462e1c376c Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 12 Nov 2015 11:08:47 +0100
Subject: [PATCH 72/91] nwrap: use symbols IPPROTO_TCP and IPPROTO_UDP

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 429102a..38866f1 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -52,6 +52,8 @@
 #include <unistd.h>
 #include <ctype.h>
 
+#include <netinet/in.h>
+
 #include <search.h>
 #include <assert.h>
 
@@ -5249,9 +5251,9 @@ valid_port:
 		ai->ai_socktype = SOCK_DGRAM;
 	}
 	if (ai->ai_protocol == 0 && ai->ai_socktype == SOCK_DGRAM) {
-		ai->ai_protocol = 17; /* UDP */
+		ai->ai_protocol = IPPROTO_UDP;
 	} else if (ai->ai_protocol == 0 && ai->ai_socktype == SOCK_STREAM) {
-		ai->ai_protocol = 6; /* TCP */
+		ai->ai_protocol = IPPROTO_TCP;
 	}
 
 	if (hints->ai_socktype == 0) {
@@ -5284,10 +5286,11 @@ valid_port:
 				ai_tmp->ai_socktype = SOCK_DGRAM;
 			}
 			if (ai_head->ai_socktype == SOCK_DGRAM) {
-				ai_tmp->ai_protocol = 17; /* UDP */
+				ai_tmp->ai_protocol = IPPROTO_UDP;
 			} else if (ai_head->ai_socktype == SOCK_STREAM) {
-				ai_tmp->ai_protocol = 6; /* TCP */
+				ai_tmp->ai_protocol = IPPROTO_TCP;
 			}
+
 			ai_new_tail->ai_next = ai_tmp;
 			ai_new_tail = ai_tmp;
 
-- 
2.5.0


From e21a4f589dfbfd6920ed2f87acb2a49657037b2a Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 12 Nov 2015 11:15:03 +0100
Subject: [PATCH 73/91] nwrap: move setting of ai_{flags|socktype|protocol}
 into nwrap_convert_he_ai

This makes the code in nwrap_getaddrinfo() more readable
and also treats all ai stuctures in the linked list, not
just the first one!

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 25 ++++++++++++-------------
 1 file changed, 12 insertions(+), 13 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 38866f1..a97d198 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -5055,12 +5055,23 @@ static int nwrap_convert_he_ai(const struct hostent *he,
 		return EAI_MEMORY;
 	}
 
-	ai->ai_flags = 0;
+	ai->ai_flags = hints->ai_flags;
 	ai->ai_family = he->h_addrtype;
 	ai->ai_socktype = hints->ai_socktype;
 	ai->ai_protocol = hints->ai_protocol;
 	ai->ai_canonname = NULL;
 
+	if (ai->ai_socktype == 0) {
+		ai->ai_socktype = SOCK_DGRAM;
+	}
+	if (ai->ai_protocol == 0) {
+		if (ai->ai_socktype == SOCK_DGRAM) {
+			ai->ai_protocol = IPPROTO_UDP;
+		} else if (ai->ai_socktype == SOCK_STREAM) {
+			ai->ai_protocol = IPPROTO_TCP;
+		}
+	}
+
 	ai->ai_addrlen = socklen;
 	ai->ai_addr = (void *)(ai + 1);
 
@@ -5244,18 +5255,6 @@ valid_port:
 		return rc;
 	}
 
-	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 = IPPROTO_UDP;
-	} else if (ai->ai_protocol == 0 && ai->ai_socktype == SOCK_STREAM) {
-		ai->ai_protocol = IPPROTO_TCP;
-	}
-
 	if (hints->ai_socktype == 0) {
 		/* Add second ai */
 		struct addrinfo *ai_head = ai;
-- 
2.5.0


From 180a5a2f53af36668b1b801ac8d84130cfac2a04 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 12 Nov 2015 11:17:21 +0100
Subject: [PATCH 74/91] nwrap: add an explaining comment for the ai duplicating
 loop

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index a97d198..dabced1 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -5255,6 +5255,11 @@ valid_port:
 		return rc;
 	}
 
+	/*
+	 * If the socktype was not specified, duplicate
+	 * each ai returned, so that we have variants for
+	 * both UDP and TCP.
+	 */
 	if (hints->ai_socktype == 0) {
 		/* Add second ai */
 		struct addrinfo *ai_head = ai;
-- 
2.5.0


From 23b64e446d0c979fb57b9196a86fc140de2b680b Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 12 Nov 2015 11:35:07 +0100
Subject: [PATCH 75/91] nwrap: rewrite the loop for duplication ai entries if
 socktype not given

This loop reads much more naturally now. It inserts the
duplicated entry right after the entrie that is being
duplicated. It does not need a ai_tail any more.

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 69 ++++++++++++++++++++++---------------------
 1 file changed, 35 insertions(+), 34 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index dabced1..539eb2a 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -5261,48 +5261,49 @@ valid_port:
 	 * both UDP and TCP.
 	 */
 	if (hints->ai_socktype == 0) {
-		/* Add second ai */
-		struct addrinfo *ai_head = ai;
-		struct addrinfo *ai_tmp;
-		struct addrinfo *ai_new_tail = ai_tail;
-
-		/* Add at least one more struct */
-		do {
-			/* CHECKS! */
-			ai_tmp = malloc(sizeof(struct addrinfo));
-			memcpy(ai_tmp, ai_head, sizeof(struct addrinfo));
-			ai_tmp->ai_next = NULL;
+		struct addrinfo *ai_cur;
 
-			/* We need a deep copy or freeaddrinfo() will blow up */
-			if (ai_head->ai_canonname != NULL) {
-				ai_tmp->ai_canonname =
-					strdup(ai_head->ai_canonname);
+		/* freeaddrinfo() frees ai_canonname and ai so allocate them */
+		for (ai_cur = ai; ai_cur != NULL; ai_cur = ai_cur->ai_next) {
+			struct addrinfo *ai_new;
+
+			/* duplicate the current entry */
+
+			ai_new = malloc(sizeof(struct addrinfo));
+			if (ai_new == NULL) {
+				freeaddrinfo(ai);
+				return EAI_MEMORY;
 			}
-			/* ai_head should point inside hints. */
-			ai_tmp->ai_addr = ai_head->ai_addr;
 
-			if (ai_head->ai_flags == 0) {
-				ai_tmp->ai_flags = hints->ai_flags;
+			memcpy(ai_new, ai_cur, sizeof(struct addrinfo));
+			ai_new->ai_next = NULL;
+
+			/* We need a deep copy or freeaddrinfo() will blow up */
+			if (ai_cur->ai_canonname != NULL) {
+				ai_new->ai_canonname =
+					strdup(ai_cur->ai_canonname);
 			}
-			if (ai_head->ai_socktype == SOCK_DGRAM) {
-				ai_tmp->ai_socktype = SOCK_STREAM;
-			} else if (ai_head->ai_socktype == SOCK_STREAM) {
-				ai_tmp->ai_socktype = SOCK_DGRAM;
+
+			if (ai_cur->ai_socktype == SOCK_DGRAM) {
+				ai_new->ai_socktype = SOCK_STREAM;
+			} else if (ai_cur->ai_socktype == SOCK_STREAM) {
+				ai_new->ai_socktype = SOCK_DGRAM;
 			}
-			if (ai_head->ai_socktype == SOCK_DGRAM) {
-				ai_tmp->ai_protocol = IPPROTO_UDP;
-			} else if (ai_head->ai_socktype == SOCK_STREAM) {
-				ai_tmp->ai_protocol = IPPROTO_TCP;
+			if (ai_cur->ai_protocol == IPPROTO_TCP) {
+				ai_new->ai_protocol = IPPROTO_UDP;
+			} else if (ai_cur->ai_protocol == IPPROTO_UDP) {
+				ai_new->ai_protocol = IPPROTO_TCP;
 			}
 
-			ai_new_tail->ai_next = ai_tmp;
-			ai_new_tail = ai_tmp;
+			/* now insert the new entry */
 
-			if (ai_head == ai_tail) {
-				break;
-			}
-			ai_head = ai_head->ai_next;
-		} while (1);
+			ai_new->ai_next = ai_cur->ai_next;
+			ai_cur->ai_next = ai_new;
+
+			/* and move on (don't duplicate the new entry) */
+
+			ai_cur = ai_new;
+		}
 	}
 
 	*res = ai;
-- 
2.5.0


From 5594ce0c3214a6989f73f79c0cca17f76a81dad2 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 12 Nov 2015 10:20:37 +0100
Subject: [PATCH 76/91] nwrap: remove ai_tail argument from
 nwrap_files_getaddrinfo()

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 539eb2a..9a7fbf5 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -3508,12 +3508,10 @@ int gethostbyname_r(const char *name,
 static int nwrap_files_getaddrinfo(const char *name,
 				   unsigned short port,
 				   const struct addrinfo *hints,
-				   struct addrinfo **ai,
-				   struct addrinfo **ai_tail)
+				   struct addrinfo **ai)
 {
 	struct nwrap_entlist *el;
 	struct hostent *he;
-	struct addrinfo *ai_new = NULL;
 	struct addrinfo *ai_head = NULL;
 	struct addrinfo *ai_cur = NULL;
 	char *h_name_lower;
@@ -3560,6 +3558,7 @@ static int nwrap_files_getaddrinfo(const char *name,
 	for (el = (struct nwrap_entlist *)e_p->data; el != NULL; el = el->next)
 	{
 		int rc2;
+		struct addrinfo *ai_new = NULL;
 
 		he = &(el->ed->ht);
 
@@ -3602,7 +3601,6 @@ static int nwrap_files_getaddrinfo(const char *name,
 	}
 
 	*ai = ai_head;
-	*ai_tail = ai_new;
 
 	return rc;
 }
@@ -5135,7 +5133,6 @@ static int nwrap_getaddrinfo(const char *node,
 			     struct addrinfo **res)
 {
 	struct addrinfo *ai = NULL;
-	struct addrinfo *ai_tail;
 	unsigned short port = 0;
 	struct {
 		int family;
@@ -5236,7 +5233,7 @@ valid_port:
 		return EAI_ADDRFAMILY;
 	}
 
-	rc = nwrap_files_getaddrinfo(node, port, hints, &ai, &ai_tail);
+	rc = nwrap_files_getaddrinfo(node, port, hints, &ai);
 	if (rc != 0) {
 		int ret;
 		struct addrinfo *p = NULL;
-- 
2.5.0


From e7af5bdad6d25e52f957da5bc56d342daa1e05fb Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Mon, 16 Nov 2015 10:17:39 +0100
Subject: [PATCH 77/91] nwrap: Fix initialization of e entry

This fixes a compiler warning.

Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 9a7fbf5..feb807a 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -3518,7 +3518,9 @@ static int nwrap_files_getaddrinfo(const char *name,
 	size_t name_len;
 	char canon_name[DNS_NAME_MAX] = { 0 };
 	bool skip_canonname = false;
-	ENTRY e = { 0 };
+	ENTRY e = {
+		.key = NULL,
+	};
 	ENTRY *e_p = NULL;
 	int rc;
 	bool ok;
-- 
2.5.0


From a5832f3b17003f9898603123788b5958a2e890b8 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Mon, 16 Nov 2015 10:19:27 +0100
Subject: [PATCH 78/91] nwrap: Cast max_hostents to avoid warnings

Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index feb807a..a8cbc22 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -1566,14 +1566,15 @@ static void nwrap_init(void)
 				  "Error parsing NSS_WRAPPER_MAX_HOSTENTS "
 				  "value or value is too small. "
 				  "Using default value: %lu.",
-				  max_hostents);
+				  (unsigned long)max_hostents);
 		} else {
 			max_hostents = max_hostents_tmp;
 		}
 	}
 	/* Initialize hash table */
 	NWRAP_LOG(NWRAP_LOG_DEBUG,
-		  "Initializing hash table of size %lu items.", max_hostents);
+		  "Initializing hash table of size %lu items.",
+		  (unsigned long)max_hostents);
 	if (hcreate(max_hostents) == 0) {
 		NWRAP_LOG(NWRAP_LOG_ERROR,
 			  "Failed to initialize hash table");
-- 
2.5.0


From df2421d1cd77428b4b8fc5ba593aa003187ed121 Mon Sep 17 00:00:00 2001
From: Robin Hack <hack.robin at gmail.com>
Date: Mon, 16 Nov 2015 23:38:51 +0100
Subject: [PATCH 79/91] nwrap: Small code shift in
 nwrap_ed_inventarize_add_to_existing()

Allocate memory only when necessary.

Signed-off-by: Robin Hack <hack.robin at gmail.com>
Reviewed-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index a8cbc22..d204ea6 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2610,21 +2610,20 @@ static bool nwrap_ed_inventarize_add_to_existing(struct nwrap_entdata *const ed,
 		return false;
 	}
 
-	el_new = nwrap_entlist_init(ed);
-	if (el_new == NULL) {
-		return false;
-	}
 
 	for (cursor = el; cursor->next != NULL; cursor = cursor->next)
 	{
 		if (cursor->ed == ed) {
-			free(el_new);
 			return false;
 		}
 	}
 
 	if (cursor->ed == ed) {
-		free(el_new);
+		return false;
+	}
+
+	el_new = nwrap_entlist_init(ed);
+	if (el_new == NULL) {
 		return false;
 	}
 
-- 
2.5.0


From 2995f71c3c4d609c45f6114e5f9a2e76044ed418 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 19 Nov 2015 00:24:14 +0100
Subject: [PATCH 80/91] nwrap: remove unused member list from struct nwrap_he

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index d204ea6..32d869b 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -770,7 +770,6 @@ struct nwrap_entlist {
 struct nwrap_he {
 	struct nwrap_cache *cache;
 
-	struct nwrap_entdata *list;
 	struct nwrap_vector entdata;
 
 	int num;
-- 
2.5.0


From 15d5db83a42e61f386de2e65ac2df718da36a6d0 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 19 Nov 2015 00:30:17 +0100
Subject: [PATCH 81/91] nwrap: rename nwrap_he.entdata to nwrap_he.entries

That's what is is the list of entries. In the guise
nwrap_entdata structures but the code reads more
naturally this way.

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 32d869b..4bde91c 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -770,7 +770,7 @@ struct nwrap_entlist {
 struct nwrap_he {
 	struct nwrap_cache *cache;
 
-	struct nwrap_vector entdata;
+	struct nwrap_vector entries;
 
 	int num;
 	int idx;
@@ -2844,7 +2844,7 @@ static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line)
 		aliases_count += 1;
 	}
 
-	nwrap_vector_add_item(&(nwrap_he->entdata), (void *const)ed);
+	nwrap_vector_add_item(&(nwrap_he->entries), (void *const)ed);
 
 	ed->aliases_count = aliases_count;
 	/* Inventarize item */
@@ -2869,14 +2869,14 @@ static void nwrap_he_unload(struct nwrap_cache *nwrap)
 	struct nwrap_entdata *ed;
 	size_t i;
 
-	nwrap_vector_foreach (ed, nwrap_he->entdata, i)
+	nwrap_vector_foreach (ed, nwrap_he->entries, i)
 	{
 		SAFE_FREE(ed->nwrap_addrdata.items);
 		SAFE_FREE(ed->ht.h_aliases);
 		SAFE_FREE(ed);
 	}
-	SAFE_FREE(nwrap_he->entdata.items);
-	nwrap_he->entdata.count = nwrap_he->entdata.capacity = 0;
+	SAFE_FREE(nwrap_he->entries.items);
+	nwrap_he->entries.count = nwrap_he->entries.capacity = 0;
 
 	nwrap_he->num = 0;
 	nwrap_he->idx = 0;
@@ -3630,7 +3630,7 @@ static struct hostent *nwrap_files_gethostbyaddr(const void *addr,
 		return NULL;
 	}
 
-	nwrap_vector_foreach(ed, nwrap_he_global.entdata, i)
+	nwrap_vector_foreach(ed, nwrap_he_global.entries, i)
 	{
 		he = &(ed->ht);
 		if (he->h_addrtype != type) {
@@ -3708,7 +3708,7 @@ static struct hostent *nwrap_files_gethostent(void)
 		return NULL;
 	}
 
-	he = &((struct nwrap_entdata *)nwrap_he_global.entdata.items[nwrap_he_global.idx++])->ht;
+	he = &((struct nwrap_entdata *)nwrap_he_global.entries.items[nwrap_he_global.idx++])->ht;
 
 	NWRAP_LOG(NWRAP_LOG_DEBUG, "return hosts[%s]", he->h_name);
 
-- 
2.5.0


From 52d94f45bf0c5ea7b5aa745bc24728831dd06b04 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 19 Nov 2015 00:34:54 +0100
Subject: [PATCH 82/91] nwrap: catch error to add item to vector in
 nwrap_he_parse_line()

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 4bde91c..f7979de 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2757,8 +2757,13 @@ static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line)
 	}
 	ip = i;
 
-	nwrap_vector_add_item(&(ed->nwrap_addrdata),
-			      (void *const)ed->addr.host_addr);
+	ok = nwrap_vector_add_item(&(ed->nwrap_addrdata),
+				   (void *const)ed->addr.host_addr);
+	if (!ok) {
+		NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to add addrdata to vector");
+		free(ed);
+		return false;
+	}
 	ed->ht.h_addr_list = nwrap_vector_head(&ed->nwrap_addrdata);
 
 	p++;
@@ -2844,7 +2849,12 @@ static bool nwrap_he_parse_line(struct nwrap_cache *nwrap, char *line)
 		aliases_count += 1;
 	}
 
-	nwrap_vector_add_item(&(nwrap_he->entries), (void *const)ed);
+	ok = nwrap_vector_add_item(&(nwrap_he->entries), (void *const)ed);
+	if (!ok) {
+		NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to add entry to vector");
+		free(ed);
+		return false;
+	}
 
 	ed->aliases_count = aliases_count;
 	/* Inventarize item */
-- 
2.5.0


From c621f7159be2dc4c9c7225198c3c37431412b07d Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Thu, 19 Nov 2015 01:00:16 +0100
Subject: [PATCH 83/91] nwrap: fix leaking the entlists

Track the list heads in a vector in the newrap_he_global
struct and free the structures upon nwrap_he_unload.

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index f7979de..562efba 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -771,6 +771,7 @@ struct nwrap_he {
 	struct nwrap_cache *cache;
 
 	struct nwrap_vector entries;
+	struct nwrap_vector lists;
 
 	int num;
 	int idx;
@@ -2575,6 +2576,7 @@ static bool nwrap_ed_inventarize_add_new(char *const h_name,
 	ENTRY e;
 	ENTRY *p;
 	struct nwrap_entlist *el;
+	bool ok;
 
 	if (h_name == NULL) {
 		NWRAP_LOG(NWRAP_LOG_ERROR, "h_name NULL - can't add");
@@ -2595,6 +2597,13 @@ static bool nwrap_ed_inventarize_add_new(char *const h_name,
 		return false;
 	}
 
+	ok = nwrap_vector_add_item(&(nwrap_he_global.lists), (void *)el);
+	if (!ok) {
+		NWRAP_LOG(NWRAP_LOG_ERROR,
+			  "Failed to add list entry to vector.");
+		return false;
+	}
+
 	return true;
 }
 
@@ -2877,6 +2886,7 @@ static void nwrap_he_unload(struct nwrap_cache *nwrap)
 	struct nwrap_he *nwrap_he =
 		(struct nwrap_he *)nwrap->private_data;
 	struct nwrap_entdata *ed;
+	struct nwrap_entlist *el;
 	size_t i;
 
 	nwrap_vector_foreach (ed, nwrap_he->entries, i)
@@ -2888,6 +2898,19 @@ static void nwrap_he_unload(struct nwrap_cache *nwrap)
 	SAFE_FREE(nwrap_he->entries.items);
 	nwrap_he->entries.count = nwrap_he->entries.capacity = 0;
 
+	nwrap_vector_foreach(el, nwrap_he->lists, i)
+	{
+		while (el != NULL) {
+			struct nwrap_entlist *el_next;
+
+			el_next = el->next;
+			SAFE_FREE(el);
+			el = el_next;
+		}
+	}
+	SAFE_FREE(nwrap_he->lists.items);
+	nwrap_he->lists.count = nwrap_he->lists.capacity = 0;
+
 	nwrap_he->num = 0;
 	nwrap_he->idx = 0;
 }
-- 
2.5.0


From 021d1ab49c709788e3164e603fe09ebbed17d2e3 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Thu, 19 Nov 2015 09:02:46 +0100
Subject: [PATCH 84/91] nwrap: Cleanup shadow getspnam() memory

Signed-off-by: Andreas Schneider <asn at samba.org>
Signed-off-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 562efba..914cd26 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -5551,6 +5551,18 @@ void nwrap_destructor(void)
 		nwrap_pw_global.num = 0;
 	}
 
+	if (nwrap_sp_global.cache != NULL) {
+		struct nwrap_cache *c = nwrap_sp_global.cache;
+
+		nwrap_files_cache_unload(c);
+		if (c->fd >= 0) {
+			fclose(c->fp);
+			c->fd = -1;
+		}
+
+		nwrap_he_global.num = 0;
+	}
+
 	if (nwrap_he_global.cache != NULL) {
 		struct nwrap_cache *c = nwrap_he_global.cache;
 
-- 
2.5.0


From c21ff0b0f52553b6f4ff0e94c4b9f8e6c1349e02 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Fri, 20 Nov 2015 09:01:01 +0100
Subject: [PATCH 85/91] nwrap: fix a copy and paste error in the destructor.

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 914cd26..a6ca816 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -5560,7 +5560,7 @@ void nwrap_destructor(void)
 			c->fd = -1;
 		}
 
-		nwrap_he_global.num = 0;
+		nwrap_sp_global.num = 0;
 	}
 
 	if (nwrap_he_global.cache != NULL) {
-- 
2.5.0


From 365e898d1faa6a6095a4a666609433925f8dd961 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Fri, 20 Nov 2015 08:51:49 +0100
Subject: [PATCH 86/91] nwrap: Fix the build on FreeBSD

Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index a6ca816..a8c97e1 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -5551,6 +5551,7 @@ void nwrap_destructor(void)
 		nwrap_pw_global.num = 0;
 	}
 
+#if defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM)
 	if (nwrap_sp_global.cache != NULL) {
 		struct nwrap_cache *c = nwrap_sp_global.cache;
 
@@ -5562,6 +5563,7 @@ void nwrap_destructor(void)
 
 		nwrap_sp_global.num = 0;
 	}
+#endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
 
 	if (nwrap_he_global.cache != NULL) {
 		struct nwrap_cache *c = nwrap_he_global.cache;
-- 
2.5.0


From fcb96617c3265cd485e1cc85fe1f4f35b4010aa5 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Fri, 20 Nov 2015 09:38:16 +0100
Subject: [PATCH 87/91] nwrap: Don't leak memory from gethostbyname*()
 functions

Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index a8c97e1..be977df 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -5577,6 +5577,9 @@ void nwrap_destructor(void)
 		nwrap_he_global.num = 0;
 	}
 
+	free(user_addrlist.items);
+	free(user_addrlist2.items);
+
 	hdestroy();
 	NWRAP_UNLOCK_ALL;
 }
-- 
2.5.0


From 5b122311500fc2cb3a13a4ac2c312274997c8fb1 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Mon, 23 Nov 2015 08:33:02 +0100
Subject: [PATCH 88/91] nwrap: Fix the build on Solaris

Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index be977df..a080b80 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -5578,7 +5578,9 @@ void nwrap_destructor(void)
 	}
 
 	free(user_addrlist.items);
+#ifdef HAVE_GETHOSTBYNAME2
 	free(user_addrlist2.items);
+#endif
 
 	hdestroy();
 	NWRAP_UNLOCK_ALL;
-- 
2.5.0


From 33d0071492478f68ae03908b9c44c20229301b79 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Tue, 24 Nov 2015 17:32:47 +0100
Subject: [PATCH 89/91] nwrap: Don't fail if we want to add an existing entry

Pair-Programmed-With: Michael Adam <obnox at samba.org>
Signed-off-by: Andreas Schneider <asn at samba.org>
Signed-off-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index a080b80..f48b9cc 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2622,12 +2622,14 @@ static bool nwrap_ed_inventarize_add_to_existing(struct nwrap_entdata *const ed,
 	for (cursor = el; cursor->next != NULL; cursor = cursor->next)
 	{
 		if (cursor->ed == ed) {
-			return false;
+			/* The entry already exists in this list. */
+			return true;
 		}
 	}
 
 	if (cursor->ed == ed) {
-		return false;
+		/* The entry already exists in this list. */
+		return true;
 	}
 
 	el_new = nwrap_entlist_init(ed);
-- 
2.5.0


From b1908398ec8cdaab3b24390e4d542835cb991940 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn at samba.org>
Date: Thu, 17 Dec 2015 08:46:33 +0100
Subject: [PATCH 90/91] nwrap: Fix segfaults while reloading hosts file

Signed-off-by: Andreas Schneider <asn at samba.org>
Reviewed-by: Michael Adam <obnox at samba.org>
---
 lib/nss_wrapper/nss_wrapper.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index f48b9cc..c4f1b33 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -2890,6 +2890,7 @@ static void nwrap_he_unload(struct nwrap_cache *nwrap)
 	struct nwrap_entdata *ed;
 	struct nwrap_entlist *el;
 	size_t i;
+	int rc;
 
 	nwrap_vector_foreach (ed, nwrap_he->entries, i)
 	{
@@ -2915,6 +2916,18 @@ static void nwrap_he_unload(struct nwrap_cache *nwrap)
 
 	nwrap_he->num = 0;
 	nwrap_he->idx = 0;
+
+	/*
+	 * If we unload the file, the pointers in the hash table point to
+	 * invalid memory. So we need to destroy the hash table and recreate
+	 * it.
+	 */
+	hdestroy();
+	rc = hcreate(max_hostents);
+	if (rc == 0) {
+		NWRAP_LOG(NWRAP_LOG_ERROR, "Failed to initialize hash table");
+		exit(-1);
+	}
 }
 
 
-- 
2.5.0


From 7067496a011db3f2b4d9bedbf192d351d6d1df9e Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Wed, 16 Dec 2015 17:47:04 +0100
Subject: [PATCH 91/91] nss_wrapper: bump version to 1.1.2

Signed-off-by: Michael Adam <obnox at samba.org>
Reviewed-by: Andreas Schneider <asn at samba.org>
---
 lib/nss_wrapper/wscript | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/nss_wrapper/wscript b/lib/nss_wrapper/wscript
index 0796bdb..6c3d7f7 100644
--- a/lib/nss_wrapper/wscript
+++ b/lib/nss_wrapper/wscript
@@ -2,7 +2,7 @@
 
 import os
 
-VERSION="1.0.3"
+VERSION="1.1.2"
 
 def configure(conf):
     if conf.CHECK_BUNDLED_SYSTEM('nss_wrapper', minversion=VERSION, set_target=False):
-- 
2.5.0

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20151219/68aa5b5b/signature-0001.sig>


More information about the samba-technical mailing list