aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2019-02-14 15:46:22 +0100
committerAndreas Schneider <asn@samba.org>2020-03-20 13:20:57 +0100
commit2cc59200e35fe6251871d60a53f8a0886ec82fb5 (patch)
treea4d7da7d190b7e276f36f5574fb76cd09c403333
parent396e83a1537a6f5df1cbe8aa152180c36cd18764 (diff)
downloadresolv_wrapper-2cc59200e35fe6251871d60a53f8a0886ec82fb5.tar.gz
resolv_wrapper-2cc59200e35fe6251871d60a53f8a0886ec82fb5.tar.xz
resolv_wrapper-2cc59200e35fe6251871d60a53f8a0886ec82fb5.zip
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@suse.de> AuthorDate: Thu Feb 19 15:52:08 2015 +0100 Commit: Andreas Schwab <schwab@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@samba.org> Reviewed-by: Andreas Schneider <asn@samba.org>
-rw-r--r--src/resolv_wrapper.c53
-rw-r--r--tests/test_res_init.c26
2 files changed, 43 insertions, 36 deletions
diff --git a/src/resolv_wrapper.c b/src/resolv_wrapper.c
index cbca248..20ba2d1 100644
--- a/src/resolv_wrapper.c
+++ b/src/resolv_wrapper.c
@@ -1645,14 +1645,13 @@ 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) {
+ state->nsaddr_list[nserv] = (struct sockaddr_in) {
.sin_family = AF_INET,
.sin_addr = a,
.sin_port = htons(53),
.sin_zero = { 0 },
};
- state->nscount++;
nserv++;
} else {
#ifdef HAVE_RESOLV_IPV6_NSADDRS
@@ -1673,11 +1672,11 @@ static int rwrap_parse_resolv_conf(struct __res_state *state,
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.nsaddrs[nserv] = sa6;
+ state->_u._ext.nssocks[nserv] = -1;
+ state->_u._ext.nsmap[nserv] = MAXNS + 1;
- state->_u._ext.nscount++;
+ state->_u._ext.nscount6++;
nserv++;
} else {
RWRAP_LOG(RWRAP_LOG_ERROR,
@@ -1700,6 +1699,13 @@ static int rwrap_parse_resolv_conf(struct __res_state *state,
} /* TODO: match other keywords */
}
+ /*
+ * 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 = nserv;
+
if (ferror(fp)) {
RWRAP_LOG(RWRAP_LOG_ERROR,
"Reading from %s failed",
@@ -1725,21 +1731,36 @@ static int rwrap_res_ninit(struct __res_state *state)
const char *resolv_conf = getenv("RESOLV_WRAPPER_CONF");
if (resolv_conf != NULL) {
+ /* Delete name servers */
+#ifdef HAVE_RESOLV_IPV6_NSADDRS
uint16_t i;
- (void)i; /* maybe unused */
+ for (i = 0; i < 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]);
+ }
+#endif
- /* Delete name servers */
state->nscount = 0;
memset(state->nsaddr_list, 0, sizeof(state->nsaddr_list));
#ifdef HAVE_RESOLV_IPV6_NSADDRS
+ state->ipv6_unavail = false;
+ state->_u._ext.nsinit = 0;
state->_u._ext.nscount = 0;
- for (i = 0; i < state->_u._ext.nscount; i++) {
- SAFE_FREE(state->_u._ext.nsaddrs[i]);
+ state->_u._ext.nscount6 = 0;
+ for (i = 0; i < MAXNS; i++) {
+ state->_u._ext.nsaddrs[i] = NULL;
+ state->_u._ext.nssocks[i] = -1;
+ state->_u._ext.nsmap[i] = MAXNS;
}
#endif
+ /* And parse the new name servers */
rc = rwrap_parse_resolv_conf(state, resolv_conf);
}
}
@@ -1786,19 +1807,7 @@ int __res_init(void)
static void rwrap_res_nclose(struct __res_state *state)
{
-#ifdef HAVE_RESOLV_IPV6_NSADDRS
- int i;
-#endif
-
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)
diff --git a/tests/test_res_init.c b/tests/test_res_init.c
index 7f73378..f0cd2ee 100644
--- a/tests/test_res_init.c
+++ b/tests/test_res_init.c
@@ -121,26 +121,17 @@ static void test_res_ninit(void **state)
/*
* Validate the number of parsed name servers.
- */
-
- assert_int_equal(dnsstate.nscount + dnsstate._u._ext.nscount, MAXNS);
-
-#ifndef HAVE_RESOLV_IPV6_NSADDRS
- /*
+ *
* On platforms that don't support IPv6, the v6 address is skipped
* and we end up reading three v4 addresses.
- */
- assert_int_equal(dnsstate.nscount, MAXNS);
-#else
- /*
+ *
* test we have two v4 and one v6 server
*
* Note: This test assumes MAXNS == 3, which is the
* case on all systems encountered so far.
*/
- assert_int_equal(dnsstate.nscount, 2);
- assert_int_equal(dnsstate._u._ext.nscount, 1);
-#endif /* HAVE_RESOLV_IPV6_NSADDRS */
+ assert_int_equal(MAXNS, 3);
+ assert_int_equal(dnsstate.nscount, MAXNS);
/* Validate the servers. */
@@ -150,12 +141,18 @@ static void test_res_ninit(void **state)
inet_ntop(AF_INET, &(dnsstate.nsaddr_list[0].sin_addr),
straddr, INET6_ADDRSTRLEN);
assert_string_equal(nameservers[0], straddr);
+#ifdef HAVE_RESOLV_IPV6_NSADDRS
+ assert_null(dnsstate._u._ext.nsaddrs[0]);
+#endif
assert_int_equal(dnsstate.nsaddr_list[1].sin_family, AF_INET);
assert_int_equal(dnsstate.nsaddr_list[1].sin_port, htons(53));
inet_ntop(AF_INET, &(dnsstate.nsaddr_list[1].sin_addr),
straddr, INET6_ADDRSTRLEN);
assert_string_equal(nameservers[1], straddr);
+#ifdef HAVE_RESOLV_IPV6_NSADDRS
+ assert_null(dnsstate._u._ext.nsaddrs[1]);
+#endif
#ifndef HAVE_RESOLV_IPV6_NSADDRS
/*
@@ -169,7 +166,8 @@ static void test_res_ninit(void **state)
assert_string_equal(nameservers[3], straddr);
#else
/* IPv6 */
- sa6 = dnsstate._u._ext.nsaddrs[0];
+ assert_non_null(dnsstate._u._ext.nsaddrs[2]);
+ sa6 = dnsstate._u._ext.nsaddrs[2];
assert_int_equal(sa6->sin6_family, AF_INET6);
assert_int_equal(sa6->sin6_port, htons(53));
inet_ntop(AF_INET6, &(sa6->sin6_addr), straddr, INET6_ADDRSTRLEN);