[SCM] Resolv Wrapper Repository - branch master updated

Andreas Schneider asn at samba.org
Fri Mar 20 12:45:39 UTC 2020


The branch, master has been updated
       via  f34b454 rwrap: make use of res_{get,set}servers() for FreeBSD
       via  4eb4e25 rwrap: split out a rwrap_set_nameservers() function
       via  93702c8 rwrap: split out rwrap_{get,log}_nameservers() functions
       via  be1a294 rwrap: split out a rwrap_reset_nameservers() function
       via  e47b20d rwrap: let configure use define HAVE_RES_STATE_U_EXT_NSADDRS
       via  2cc5920 rwrap: fix resolv wrapper with ipv6 addresses and old glibc versions
       via  396e83a tests/test_res_init.c: avoid using public ipv6 addresses from google in tests
      from  3ab29a2 rwrap: improve logging messages by including getprogname()

https://git.samba.org/?p=resolv_wrapper.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit f34b4540fd1b860ecff38f9caaa6f4c48197a18a
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Mar 10 13:11:40 2020 +0100

    rwrap: make use of res_{get,set}servers() for FreeBSD
    
    This way don't depend on the opaque structure on FreeBSD
    and have support for ipv6 nameservers.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit 4eb4e25b89bcd5a10b9f0e3e42c4181b65518adf
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Mar 10 13:07:25 2020 +0100

    rwrap: split out a rwrap_set_nameservers() function
    
    This will make it easier to add support for ipv6 nameservers
    on FreeBSD in the next step.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit 93702c87726ac9f29df41e192c105e2f030d1d80
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Mar 10 13:07:25 2020 +0100

    rwrap: split out rwrap_{get,log}_nameservers() functions
    
    This will make it easier to add support for ipv6 nameservers
    on FreeBSD in the next step.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit be1a2940aff74edc7b6063b1772558f63eb82544
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Mar 10 13:07:25 2020 +0100

    rwrap: split out a rwrap_reset_nameservers() function
    
    This will make it easier to add support for ipv6 nameservers
    on FreeBSD in the following commits.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit e47b20d78b1d5ba9b66cb054659ed338d43f469e
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Mar 18 17:01:48 2020 +0100

    rwrap: let configure use define HAVE_RES_STATE_U_EXT_NSADDRS
    
    The configure check should describe what it checked for.
    Let the code logic decide if that means we expect
    HAVE_RESOLV_IPV6_NSADDRS to be defined.
    
    We'll get another condition that sets HAVE_RESOLV_IPV6_NSADDRS
    in the following commits.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit 2cc59200e35fe6251871d60a53f8a0886ec82fb5
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Feb 14 15:46:22 2019 +0100

    rwrap: fix resolv wrapper with ipv6 addresses and old glibc versions
    
    The handling of __res_state._u._ext was different before
    this glibc commit (e.g. glibc-2.19):
    
      commit 2212c1420c92a33b0e0bd9a34938c9814a56c0f7
      Author:     Andreas Schwab <schwab at suse.de>
      AuthorDate: Thu Feb 19 15:52:08 2015 +0100
      Commit:     Andreas Schwab <schwab at suse.de>
      CommitDate: Thu May 21 15:16:37 2015 +0200
    
          Simplify handling of nameserver configuration in resolver
    
          Remove use of ext.nsmap member of struct __res_state and always use
          an identity mapping betwen the nsaddr_list array and the ext.nsaddrs
          array.  The fact that a nameserver has an IPv6 address is signalled by
          setting nsaddr_list[].sin_family to zero.
    
    As a result of fixing this, it's now possible to run 'test_res_init'
    even without using resolv_wrapper.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

commit 396e83a1537a6f5df1cbe8aa152180c36cd18764
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Feb 15 17:24:57 2019 +0100

    tests/test_res_init.c: avoid using public ipv6 addresses from google in tests
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andreas Schneider <asn at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 ConfigureChecks.cmake |  10 +-
 config.h.cmake        |   4 +-
 src/resolv_wrapper.c  | 370 +++++++++++++++++++++++++++++++++++++-------------
 tests/test_res_init.c |  84 ++++++++----
 4 files changed, 347 insertions(+), 121 deletions(-)


Changeset truncated at 500 lines:

diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake
index ae9437b..8444232 100644
--- a/ConfigureChecks.cmake
+++ b/ConfigureChecks.cmake
@@ -173,7 +173,15 @@ int main(void) {
     return 0;
 }" HAVE_IPV6)
 
-check_struct_has_member("struct __res_state" _u._ext.nsaddrs resolv.h HAVE_RESOLV_IPV6_NSADDRS)
+check_struct_has_member("struct __res_state" _u._ext.nsaddrs
+                        "sys/socket.h;netinet/in.h;resolv.h"
+                        HAVE_RES_STATE_U_EXT_NSADDRS)
+check_struct_has_member("union res_sockaddr_union" sin
+                        "sys/socket.h;netinet/in.h;resolv.h"
+                        HAVE_RES_SOCKADDR_UNION_SIN)
+check_struct_has_member("union res_sockaddr_union" sin6
+                        "sys/socket.h;netinet/in.h;resolv.h"
+                        HAVE_RES_SOCKADDR_UNION_SIN6)
 
 check_c_source_compiles("
 void log_fn(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
diff --git a/config.h.cmake b/config.h.cmake
index 0c2fa35..8eba17b 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -55,7 +55,9 @@
 /**************************** OPTIONS ****************************/
 
 #cmakedefine HAVE_IPV6 1
-#cmakedefine HAVE_RESOLV_IPV6_NSADDRS 1
+#cmakedefine HAVE_RES_STATE_U_EXT_NSADDRS 1
+#cmakedefine HAVE_RES_SOCKADDR_UNION_SIN 1
+#cmakedefine HAVE_RES_SOCKADDR_UNION_SIN6 1
 
 #cmakedefine HAVE_ATTRIBUTE_PRINTF_FORMAT 1
 #cmakedefine HAVE_DESTRUCTOR_ATTRIBUTE 1
diff --git a/src/resolv_wrapper.c b/src/resolv_wrapper.c
index cbca248..0d3f34c 100644
--- a/src/resolv_wrapper.c
+++ b/src/resolv_wrapper.c
@@ -52,6 +52,10 @@
 
 #include <resolv.h>
 
+#if defined(HAVE_RES_STATE_U_EXT_NSADDRS) || defined(HAVE_RES_SOCKADDR_UNION_SIN6)
+#define HAVE_RESOLV_IPV6_NSADDRS 1
+#endif
+
 /* GCC has printf type attribute check. */
 #ifdef HAVE_ATTRIBUTE_PRINTF_FORMAT
 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
@@ -173,6 +177,12 @@ static void rwrap_log(enum rwrap_dbglvl_e dbglvl,
 
 #define RWRAP_MAX_RECURSION 64
 
+union rwrap_sockaddr {
+	struct sockaddr sa;
+	struct sockaddr_in in;
+	struct sockaddr_in6 in6;
+};
+
 /* Priority and weight can be omitted from the hosts file, but need to be part
  * of the output
  */
@@ -1602,12 +1612,235 @@ static int libc_res_nsearch(struct __res_state *state,
  *   RES_HELPER
  ***************************************************************************/
 
+static size_t rwrap_get_nameservers(struct __res_state *state,
+				    size_t nserv,
+				    union rwrap_sockaddr *nsaddrs)
+{
+#ifdef HAVE_RES_SOCKADDR_UNION_SIN
+	union res_sockaddr_union set[MAXNS];
+	size_t i;
+	int rc;
+
+	memset(set, 0, sizeof(set));
+	memset(nsaddrs, 0, sizeof(*nsaddrs) * nserv);
+
+	if (nserv > MAXNS) {
+		nserv = MAXNS;
+	}
+
+	rc = res_getservers(state, set, nserv);
+	if (rc <= 0) {
+		return 0;
+	}
+	if (rc < nserv) {
+		nserv = rc;
+	}
+
+	for (i = 0; i < nserv; i++) {
+		switch (set[i].sin.sin_family) {
+		case AF_INET:
+			nsaddrs[i] = (union rwrap_sockaddr) {
+				.in = set[i].sin,
+			};
+			break;
+#ifdef HAVE_RES_SOCKADDR_UNION_SIN6
+		case AF_INET6:
+			nsaddrs[i] = (union rwrap_sockaddr) {
+				.in6 = set[i].sin6,
+			};
+			break;
+#endif
+		}
+	}
+
+	return nserv;
+#else /* ! HAVE_RES_SOCKADDR_UNION_SIN */
+	size_t i;
+
+	memset(nsaddrs, 0, sizeof(*nsaddrs) * nserv);
+
+	if (nserv > (size_t)state->nscount) {
+		nserv = (size_t)state->nscount;
+	}
+
+	for (i = 0; i < nserv; i++) {
+#ifdef HAVE_RES_STATE_U_EXT_NSADDRS
+		if (state->_u._ext.nsaddrs[i] != NULL) {
+			nsaddrs[i] = (union rwrap_sockaddr) {
+				.in6 = *state->_u._ext.nsaddrs[i],
+			};
+		} else
+#endif /* HAVE_RES_STATE_U_EXT_NSADDRS */
+		{
+			nsaddrs[i] = (union rwrap_sockaddr) {
+				.in = state->nsaddr_list[i],
+			};
+		}
+	}
+
+	return nserv;
+#endif /* ! HAVE_RES_SOCKADDR_UNION_SIN */
+}
+
+static void rwrap_log_nameservers(enum rwrap_dbglvl_e dbglvl,
+				  const char *func,
+				  struct __res_state *state)
+{
+	union rwrap_sockaddr nsaddrs[MAXNS];
+	size_t nserv = MAXNS;
+	size_t i;
+
+	memset(nsaddrs, 0, sizeof(nsaddrs));
+	nserv = rwrap_get_nameservers(state, nserv, nsaddrs);
+	for (i = 0; i < nserv; i++) {
+		char ip[INET6_ADDRSTRLEN];
+
+		switch (nsaddrs[i].sa.sa_family) {
+		case AF_INET:
+			inet_ntop(AF_INET, &(nsaddrs[i].in.sin_addr),
+				  ip, sizeof(ip));
+			break;
+		case AF_INET6:
+			inet_ntop(AF_INET6, &(nsaddrs[i].in6.sin6_addr),
+				  ip, sizeof(ip));
+			break;
+		default:
+			snprintf(ip, sizeof(ip), "<unknown sa_family=%d",
+				 nsaddrs[i].sa.sa_family);
+			break;
+		}
+
+		rwrap_log(dbglvl, func,
+			  "        nameserver: %s",
+			  ip);
+	}
+}
+
+static void rwrap_reset_nameservers(struct __res_state *state)
+{
+#ifdef HAVE_RES_SOCKADDR_UNION_SIN
+	res_setservers(state, NULL, 0);
+#else /* ! HAVE_RES_SOCKADDR_UNION_SIN */
+#ifdef HAVE_RES_STATE_U_EXT_NSADDRS
+	size_t i;
+
+	for (i = 0; i < (size_t)state->nscount; i++) {
+		if (state->_u._ext.nssocks[i] != -1) {
+			close(state->_u._ext.nssocks[i]);
+			state->_u._ext.nssocks[i] = -1;
+		}
+		SAFE_FREE(state->_u._ext.nsaddrs[i]);
+	}
+	memset(&state->_u._ext, 0, sizeof(state->_u._ext));
+	for (i = 0; i < MAXNS; i++) {
+		state->_u._ext.nssocks[i] = -1;
+		state->_u._ext.nsmap[i] = MAXNS + 1;
+	}
+	state->ipv6_unavail = false;
+#endif
+	memset(state->nsaddr_list, 0, sizeof(state->nsaddr_list));
+	state->nscount = 0;
+#endif /* ! HAVE_RES_SOCKADDR_UNION_SIN */
+}
+
+static int rwrap_set_nameservers(struct __res_state *state,
+				 size_t nserv,
+				 const union rwrap_sockaddr *nsaddrs)
+{
+#ifdef HAVE_RES_SOCKADDR_UNION_SIN
+	union res_sockaddr_union set[MAXNS];
+	size_t i;
+
+	memset(set, 0, sizeof(set));
+
+	if (nserv > MAXNS) {
+		nserv = MAXNS;
+	}
+
+	rwrap_reset_nameservers(state);
+
+	for (i = 0; i < nserv; i++) {
+		switch (nsaddrs[i].sa.sa_family) {
+		case AF_INET:
+			set[i] = (union res_sockaddr_union) {
+				.sin = nsaddrs[i].in,
+			};
+			break;
+#ifdef HAVE_RES_SOCKADDR_UNION_SIN6
+		case AF_INET6:
+			set[i] = (union res_sockaddr_union) {
+				.sin6 = nsaddrs[i].in6,
+			};
+			break;
+#endif
+		default:
+			RWRAP_LOG(RWRAP_LOG_ERROR,
+				  "Internal error unhandled sa_family=%d",
+				  nsaddrs[i].sa.sa_family);
+			errno = ENOSYS;
+			return -1;
+		}
+	}
+
+	res_setservers(state, set, nserv);
+	return 0;
+#else /* ! HAVE_RES_SOCKADDR_UNION_SIN */
+	size_t i;
+
+	if (nserv > MAXNS) {
+		nserv = MAXNS;
+	}
+	rwrap_reset_nameservers(state);
+
+	for (i = 0; i < nserv; i++) {
+		switch (nsaddrs[i].sa.sa_family) {
+		case AF_INET:
+			state->nsaddr_list[i] = nsaddrs[i].in;
+			break;
+#ifdef HAVE_RES_STATE_U_EXT_NSADDRS
+		case AF_INET6:
+			state->_u._ext.nsaddrs[i] = malloc(sizeof(nsaddrs[i].in6));
+			if (state->_u._ext.nsaddrs[i] == NULL) {
+				rwrap_reset_nameservers(state);
+				errno = ENOMEM;
+				return -1;
+			}
+			*state->_u._ext.nsaddrs[i] = nsaddrs[i].in6;
+			state->_u._ext.nssocks[i] = -1;
+			state->_u._ext.nsmap[i] = MAXNS + 1;
+			state->_u._ext.nscount6++;
+			break;
+#endif
+		default:
+			RWRAP_LOG(RWRAP_LOG_ERROR,
+				  "Internal error unhandled sa_family=%d",
+				  nsaddrs[i].sa.sa_family);
+			rwrap_reset_nameservers(state);
+			errno = ENOSYS;
+			return -1;
+		}
+	}
+
+	/*
+	 * note that state->_u._ext.nscount is left as 0,
+	 * this matches glibc and allows resolv wrapper
+	 * to work with most (maybe all) glibc versions.
+	 */
+	state->nscount = i;
+
+	return 0;
+#endif /* ! HAVE_RES_SOCKADDR_UNION_SIN */
+}
+
 static int rwrap_parse_resolv_conf(struct __res_state *state,
 				   const char *resolv_conf)
 {
 	FILE *fp;
 	char buf[BUFSIZ];
-	int nserv = 0;
+	size_t nserv = 0;
+	union rwrap_sockaddr nsaddrs[MAXNS];
+
+	memset(nsaddrs, 0, sizeof(nsaddrs));
 
 	fp = fopen(resolv_conf, "r");
 	if (fp == NULL) {
@@ -1627,6 +1860,7 @@ static int rwrap_parse_resolv_conf(struct __res_state *state,
 
 		if (RESOLV_MATCH(buf, "nameserver") && nserv < MAXNS) {
 			struct in_addr a;
+			struct in6_addr a6;
 			char *q;
 			int ok;
 
@@ -1645,57 +1879,42 @@ static int rwrap_parse_resolv_conf(struct __res_state *state,
 
 			ok = inet_pton(AF_INET, p, &a);
 			if (ok) {
-				state->nsaddr_list[state->nscount] = (struct sockaddr_in) {
-					.sin_family = AF_INET,
-					.sin_addr = a,
-					.sin_port = htons(53),
-					.sin_zero = { 0 },
+				nsaddrs[nserv] = (union rwrap_sockaddr) {
+					.in = {
+						.sin_family = AF_INET,
+						.sin_addr = a,
+						.sin_port = htons(53),
+						.sin_zero = { 0 },
+					},
 				};
 
-				state->nscount++;
 				nserv++;
-			} else {
+				continue;
+			}
+
+			ok = inet_pton(AF_INET6, p, &a6);
+			if (ok) {
 #ifdef HAVE_RESOLV_IPV6_NSADDRS
-				/* IPv6 */
-				struct in6_addr a6;
-				ok = inet_pton(AF_INET6, p, &a6);
-				if (ok) {
-					struct sockaddr_in6 *sa6;
-
-					sa6 = malloc(sizeof(*sa6));
-					if (sa6 == NULL) {
-						fclose(fp);
-						return -1;
-					}
-
-					sa6->sin6_family = AF_INET6;
-					sa6->sin6_port = htons(53);
-					sa6->sin6_flowinfo = 0;
-					sa6->sin6_addr = a6;
-
-					state->_u._ext.nsaddrs[state->_u._ext.nscount] = sa6;
-					state->_u._ext.nssocks[state->_u._ext.nscount] = -1;
-					state->_u._ext.nsmap[state->_u._ext.nscount] = MAXNS + 1;
-
-					state->_u._ext.nscount++;
-					nserv++;
-				} else {
-					RWRAP_LOG(RWRAP_LOG_ERROR,
-						"Malformed DNS server");
-					continue;
-				}
+				nsaddrs[nserv] = (union rwrap_sockaddr) {
+					.in6 = {
+
+						.sin6_family = AF_INET6,
+						.sin6_port = htons(53),
+						.sin6_flowinfo = 0,
+						.sin6_addr = a6,
+					},
+				};
+				nserv++;
+				continue;
 #else /* !HAVE_RESOLV_IPV6_NSADDRS */
-				/*
-				 * BSD uses an opaque structure to store the
-				 * IPv6 addresses. So we can not simply store
-				 * these addresses the same way as above.
-				 */
 				RWRAP_LOG(RWRAP_LOG_WARN,
 					  "resolve_wrapper does not support "
 					  "IPv6 on this platform");
-					continue;
+				continue;
 #endif
 			}
+
+			RWRAP_LOG(RWRAP_LOG_ERROR, "Malformed DNS server[%s]", p);
 			continue;
 		} /* TODO: match other keywords */
 	}
@@ -1709,7 +1928,16 @@ static int rwrap_parse_resolv_conf(struct __res_state *state,
 	}
 
 	fclose(fp);
-	return 0;
+
+	if (nserv == 0) {
+		RWRAP_LOG(RWRAP_LOG_ERROR,
+			  "No usable nameservers found in %s",
+			  resolv_conf);
+		errno = ESRCH;
+		return -1;
+	}
+
+	return rwrap_set_nameservers(state, nserv, nsaddrs);
 }
 
 /****************************************************************************
@@ -1725,21 +1953,6 @@ static int rwrap_res_ninit(struct __res_state *state)
 		const char *resolv_conf = getenv("RESOLV_WRAPPER_CONF");
 
 		if (resolv_conf != NULL) {
-			uint16_t i;
-
-			(void)i; /* maybe unused */
-
-			/* Delete name servers */
-			state->nscount = 0;
-			memset(state->nsaddr_list, 0, sizeof(state->nsaddr_list));
-
-#ifdef HAVE_RESOLV_IPV6_NSADDRS
-			state->_u._ext.nscount = 0;
-			for (i = 0; i < state->_u._ext.nscount; i++) {
-				SAFE_FREE(state->_u._ext.nsaddrs[i]);
-			}
-#endif
-
 			rc = rwrap_parse_resolv_conf(state, resolv_conf);
 		}
 	}
@@ -1786,19 +1999,8 @@ int __res_init(void)
 
 static void rwrap_res_nclose(struct __res_state *state)
 {
-#ifdef HAVE_RESOLV_IPV6_NSADDRS
-	int i;
-#endif
-
+	rwrap_reset_nameservers(state);
 	libc_res_nclose(state);
-
-#ifdef HAVE_RESOLV_IPV6_NSADDRS
-	if (state != NULL) {
-		for (i = 0; i < state->_u._ext.nscount; i++) {
-			SAFE_FREE(state->_u._ext.nsaddrs[i]);
-		}
-	}
-#endif
 }
 
 #if !defined(res_nclose) && defined(HAVE_RES_NCLOSE)
@@ -1841,23 +2043,11 @@ static int rwrap_res_nquery(struct __res_state *state,
 {
 	int rc;
 	const char *fake_hosts;
-#ifndef NDEBUG
-	int i;
-#endif
 
 	RWRAP_LOG(RWRAP_LOG_TRACE,
 		  "Resolve the domain name [%s] - class=%d, type=%d",
 		  dname, class, type);
-#ifndef NDEBUG
-	for (i = 0; i < state->nscount; i++) {
-		char ip[INET6_ADDRSTRLEN];
-
-		inet_ntop(AF_INET, &state->nsaddr_list[i].sin_addr, ip, sizeof(ip));
-		RWRAP_LOG(RWRAP_LOG_TRACE,
-			  "        nameserver: %s",
-			  ip);
-	}
-#endif
+	rwrap_log_nameservers(RWRAP_LOG_TRACE, __func__, state);
 
 	fake_hosts = getenv("RESOLV_WRAPPER_HOSTS");
 	if (fake_hosts != NULL) {
@@ -1950,23 +2140,11 @@ static int rwrap_res_nsearch(struct __res_state *state,
 {
 	int rc;
 	const char *fake_hosts;
-#ifndef NDEBUG
-	int i;
-#endif
 
 	RWRAP_LOG(RWRAP_LOG_TRACE,
 		  "Resolve the domain name [%s] - class=%d, type=%d",
 		  dname, class, type);
-#ifndef NDEBUG
-	for (i = 0; i < state->nscount; i++) {
-		char ip[INET6_ADDRSTRLEN];
-
-		inet_ntop(AF_INET, &state->nsaddr_list[i].sin_addr, ip, sizeof(ip));
-		RWRAP_LOG(RWRAP_LOG_TRACE,
-			  "        nameserver: %s",
-			  ip);
-	}
-#endif


-- 
Resolv Wrapper Repository



More information about the samba-cvs mailing list