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)));
#cmakedefine HAVE_IPV6 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
#include <resolv.h>
-#ifdef HAVE_RES_STATE_U_EXT_NSADDRS
+#if defined(HAVE_RES_STATE_U_EXT_NSADDRS) || defined(HAVE_RES_SOCKADDR_UNION_SIN6)
#define HAVE_RESOLV_IPV6_NSADDRS 1
#endif
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);
}
return nserv;
+#endif /* ! HAVE_RES_SOCKADDR_UNION_SIN */
}
static void rwrap_log_nameservers(enum rwrap_dbglvl_e dbglvl,
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;
#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) {
state->nscount = i;
return 0;
+#endif /* ! HAVE_RES_SOCKADDR_UNION_SIN */
}
static int rwrap_parse_resolv_conf(struct __res_state *state,
int i;
int rv;
char straddr[INET6_ADDRSTRLEN] = { '\0' };
+#ifdef HAVE_RES_SOCKADDR_UNION_SIN
+ union res_sockaddr_union set[MAXNS*5];
+#endif
#ifdef HAVE_RES_STATE_U_EXT_NSADDRS
struct sockaddr_in6 *sa6;
#endif
* case on all systems encountered so far.
*/
assert_int_equal(MAXNS, 3);
+#ifdef HAVE_RES_SOCKADDR_UNION_SIN
+ memset(set, 0, sizeof(set));
+ rv = res_getservers(&dnsstate, set, MAXNS+5);
+ assert_int_equal(rv, MAXNS);
+
+ /* IPv4 */
+ assert_int_equal(set[0].sin.sin_family, AF_INET);
+ assert_int_equal(set[0].sin.sin_port, htons(53));
+ inet_ntop(AF_INET, &(set[0].sin.sin_addr),
+ straddr, INET6_ADDRSTRLEN);
+ assert_string_equal(nameservers[0], straddr);
+
+ assert_int_equal(set[1].sin.sin_family, AF_INET);
+ assert_int_equal(set[1].sin.sin_port, htons(53));
+ inet_ntop(AF_INET, &(set[1].sin.sin_addr), straddr, INET6_ADDRSTRLEN);
+ assert_string_equal(nameservers[1], straddr);
+
+#ifdef HAVE_RES_SOCKADDR_UNION_SIN6
+ /* IPv6 */
+ assert_int_equal(set[2].sin6.sin6_family, AF_INET6);
+ assert_int_equal(set[2].sin6.sin6_port, htons(53));
+ inet_ntop(AF_INET6, &(set[2].sin6.sin6_addr), straddr, INET6_ADDRSTRLEN);
+ assert_string_equal(nameservers[2], straddr);
+#else /* ! HAVE_RES_SOCKADDR_UNION_SIN6 */
+ /*
+ * On platforms that don't support IPv6, the v6 address is skipped
+ * and we end up reading three v4 addresses.
+ */
+ assert_int_equal(set[2].sin.sin_family, AF_INET);
+ assert_int_equal(set[2].sin.sin_port, htons(53));
+ inet_ntop(AF_INET, &(set[2].sin.sin_addr), straddr, INET6_ADDRSTRLEN);
+ assert_string_equal(nameservers[3], straddr);
+#endif /* ! HAVE_RES_SOCKADDR_UNION_SIN6 */
+
+#else /* ! HAVE_RES_SOCKADDR_UNION_SIN */
assert_int_equal(dnsstate.nscount, MAXNS);
/* Validate the servers. */
assert_string_equal(nameservers[3], straddr);
#endif
+#endif /* ! HAVE_RES_SOCKADDR_UNION_SIN */
+
res_nclose(&dnsstate);
}