aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2020-03-10 13:07:25 +0100
committerAndreas Schneider <asn@samba.org>2020-03-20 13:20:57 +0100
commit4eb4e25b89bcd5a10b9f0e3e42c4181b65518adf (patch)
treef5bbfc872fd006b8dbc4cba1ee4d5dfac502a1e1
parent93702c87726ac9f29df41e192c105e2f030d1d80 (diff)
downloadresolv_wrapper-4eb4e25b89bcd5a10b9f0e3e42c4181b65518adf.tar.gz
resolv_wrapper-4eb4e25b89bcd5a10b9f0e3e42c4181b65518adf.tar.xz
resolv_wrapper-4eb4e25b89bcd5a10b9f0e3e42c4181b65518adf.zip
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@samba.org> Reviewed-by: Andreas Schneider <asn@samba.org>
-rw-r--r--src/resolv_wrapper.c140
1 files changed, 90 insertions, 50 deletions
diff --git a/src/resolv_wrapper.c b/src/resolv_wrapper.c
index c97ad26..e1903c9 100644
--- a/src/resolv_wrapper.c
+++ b/src/resolv_wrapper.c
@@ -1699,14 +1699,65 @@ static void rwrap_reset_nameservers(struct __res_state *state)
state->nscount = 0;
}
+static int rwrap_set_nameservers(struct __res_state *state,
+ size_t nserv,
+ const union rwrap_sockaddr *nsaddrs)
+{
+ 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;
+}
+
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];
- rwrap_reset_nameservers(state);
+ memset(nsaddrs, 0, sizeof(nsaddrs));
fp = fopen(resolv_conf, "r");
if (fp == NULL) {
@@ -1726,6 +1777,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;
@@ -1744,67 +1796,46 @@ static int rwrap_parse_resolv_conf(struct __res_state *state,
ok = inet_pton(AF_INET, p, &a);
if (ok) {
- state->nsaddr_list[nserv] = (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 },
+ },
};
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[nserv] = sa6;
- state->_u._ext.nssocks[nserv] = -1;
- state->_u._ext.nsmap[nserv] = MAXNS + 1;
-
- state->_u._ext.nscount6++;
- 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 */
}
- /*
- * 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",
@@ -1814,7 +1845,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);
}
/****************************************************************************