Use libresolv to initialize cares on iPhone targets

On iPhone targets like iOS, watchOS or tvOS the file
/etc/resolv.conf cannot be used to configure cares.

Instead the resolver library is queried for configuration
values.

CC: Yury Kirpichev <ykirpichev@yandex-team.ru>
pull/32/merge
Gregor Jasny 9 years ago committed by David Drysdale
parent f945a0cfe3
commit affc63cba8
  1. 75
      ares_init.c
  2. 24
      configure.ac

@ -49,6 +49,10 @@
#define MAX_DNS_PROPERTIES 8
#endif
#if defined(CARES_USE_LIBRESOLV)
#include <resolv.h>
#endif
#include "ares.h"
#include "ares_inet_net_pton.h"
#include "ares_library_init.h"
@ -77,7 +81,7 @@ static const char *try_option(const char *p, const char *q, const char *opt);
static int init_id_key(rc4_key* key,int key_data_len);
#if !defined(WIN32) && !defined(WATT32) && \
!defined(ANDROID) && !defined(__ANDROID__)
!defined(ANDROID) && !defined(__ANDROID__) && !defined(CARES_USE_LIBRESOLV)
static int sortlist_alloc(struct apattern **sortlist, int *nsort,
struct apattern *pat);
static int ip_addr(const char *s, ssize_t len, struct in_addr *addr);
@ -1067,7 +1071,8 @@ static int get_DNS_Windows(char **outptr)
static int init_by_resolv_conf(ares_channel channel)
{
#if !defined(ANDROID) && !defined(__ANDROID__) && !defined(WATT32)
#if !defined(ANDROID) && !defined(__ANDROID__) && !defined(WATT32) && \
!defined(CARES_USE_LIBRESOLV)
char *line = NULL;
#endif
int status = -1, nservers = 0, nsort = 0;
@ -1159,6 +1164,65 @@ static int init_by_resolv_conf(ares_channel channel)
break;
status = ARES_EOF;
}
#elif defined(CARES_USE_LIBRESOLV)
struct __res_state res;
memset(&res, 0, sizeof(res));
int result = res_ninit(&res);
if (result == 0 && (res.options & RES_INIT)) {
status = ARES_EOF;
if (channel->nservers == -1) {
union res_sockaddr_union addr[MAXNS];
int nscount = res_getservers(&res, addr, MAXNS);
for (int i = 0; i < nscount; ++i) {
char str[INET6_ADDRSTRLEN];
int config_status;
sa_family_t family = addr[i].sin.sin_family;
if (family == AF_INET) {
ares_inet_ntop(family, &addr[i].sin.sin_addr, str, sizeof(str));
} else if (family == AF_INET6) {
ares_inet_ntop(family, &addr[i].sin6.sin6_addr, str, sizeof(str));
} else {
continue;
}
config_status = config_nameserver(&servers, &nservers, str);
if (config_status != ARES_SUCCESS) {
status = config_status;
break;
}
}
}
if (channel->ndomains == -1) {
int entries = 0;
while ((entries < MAXDNSRCH) && res.dnsrch[entries])
entries++;
channel->domains = malloc(entries * sizeof(char *));
if (!channel->domains) {
status = ARES_ENOMEM;
} else {
channel->ndomains = entries;
for (int i = 0; i < channel->ndomains; ++i) {
channel->domains[i] = strdup(res.dnsrch[i]);
if (!channel->domains[i]) {
status = ARES_ENOMEM;
break;
}
}
}
}
if (channel->ndots == -1)
channel->ndots = res.ndots;
if (channel->tries == -1)
channel->tries = res.retry;
if (channel->rotate == -1)
channel->rotate = res.options & RES_ROTATE;
if (channel->timeout == -1)
channel->timeout = res.retrans * 1000;
res_ndestroy(&res);
}
#else
{
char *p;
@ -1479,7 +1543,7 @@ static int init_by_defaults(ares_channel channel)
}
#if !defined(WIN32) && !defined(WATT32) && \
!defined(ANDROID) && !defined(__ANDROID__)
!defined(ANDROID) && !defined(__ANDROID__) && !defined(CARES_USE_LIBRESOLV)
static int config_domain(ares_channel channel, char *str)
{
char *q;
@ -1592,7 +1656,8 @@ static int config_nameserver(struct server_state **servers, int *nservers,
return ARES_SUCCESS;
}
#if !defined(WIN32) && !defined(ANDROID) && !defined(__ANDROID__)
#if !defined(WIN32) && !defined(ANDROID) && !defined(__ANDROID__) && \
!defined(CARES_USE_LIBRESOLV)
static int config_sortlist(struct apattern **sortlist, int *nsort,
const char *str)
{
@ -1773,7 +1838,7 @@ static const char *try_option(const char *p, const char *q, const char *opt)
}
#if !defined(WIN32) && !defined(WATT32) && \
!defined(ANDROID) && !defined(__ANDROID__)
!defined(ANDROID) && !defined(__ANDROID__) && !defined(CARES_USE_LIBRESOLV)
static char *try_config(char *s, const char *opt, char scc)
{
size_t len;

@ -346,6 +346,30 @@ if test "$HAVE_GETHOSTBYNAME" != "1"; then
AC_MSG_ERROR([couldn't find libraries for gethostbyname()])
fi
dnl resolv lib for iPhone
AS_IF([test "x$host_vendor" = "xapple"], [
AC_MSG_CHECKING([for iPhone target])
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
#include "TargetConditionals.h"
]], [[
#if TARGET_OS_IPHONE == 0
#error Not an iPhone target
#endif
return 0;
]])
],[
AC_MSG_RESULT([yes])
AC_SEARCH_LIBS([res_servicename], [resolv], [
AC_DEFINE([CARES_USE_LIBRESOLV], [1], [Use resolver library to configure cares])
], [
AC_MSG_ERROR([Unable to find libresolv which is required for iPhone targets])
])
],[
AC_MSG_RESULT([no])
])
])
dnl resolve lib?
AC_CHECK_FUNC(strcasecmp, , [ AC_CHECK_LIB(resolve, strcasecmp) ])

Loading…
Cancel
Save