[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