Skip to content

Commit

Permalink
Use libresolv to initialize cares on iPhone targets
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
gjasny authored and Gregor Jasny committed Jan 16, 2016
1 parent cbb466e commit 19690c2
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 5 deletions.
73 changes: 68 additions & 5 deletions ares_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -1058,7 +1062,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;
Expand Down Expand Up @@ -1150,6 +1155,63 @@ 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;
}
}
}
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;
Expand Down Expand Up @@ -1470,7 +1532,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;
Expand Down Expand Up @@ -1583,7 +1645,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)
{
Expand Down Expand Up @@ -1764,7 +1827,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;
Expand Down
24 changes: 24 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -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) ])

Expand Down

0 comments on commit 19690c2

Please sign in to comment.