Skip to content

Commit

Permalink
Remove usage of getaddrinfo_a() and gai_* functions
Browse files Browse the repository at this point in the history
The glibc async functions turned out to be unstable and
error-prone. They also use threads to implement timeouts.
If we need DNS timeouts and/or async DNS lookups, we should
have a look at external resolver libraries.
  • Loading branch information
rockdaboot committed Aug 4, 2018
1 parent a503e27 commit 8a8d1de
Show file tree
Hide file tree
Showing 2 changed files with 1 addition and 67 deletions.
4 changes: 1 addition & 3 deletions configure.ac
Expand Up @@ -677,8 +677,6 @@ AS_IF([test "x$with_libmicrohttpd" != xno], [
])
AM_CONDITIONAL([WITH_MICROHTTPD], [test "x$with_libmicrohttpd" = xyes])

AC_SEARCH_LIBS(getaddrinfo_a, anl)

# Check for plugin support
AC_CANONICAL_HOST
case "$host_os" in
Expand Down Expand Up @@ -733,7 +731,7 @@ AC_CHECK_HEADERS([\
AC_FUNC_FORK
AC_FUNC_MMAP
AC_CHECK_FUNCS([\
strlcpy getuid fmemopen getaddrinfo_a])
strlcpy getuid fmemopen])

AC_CONFIG_FILES([Makefile
lib/Makefile
Expand Down
64 changes: 0 additions & 64 deletions libwget/net.c
Expand Up @@ -230,69 +230,6 @@ static struct addrinfo *_wget_sort_preferred(struct addrinfo *addrinfo, int pref
}
}

#if defined HAVE_GETADDRINFO_A && ! defined FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
static int _wget_tcp_resolve(wget_tcp_t *tcp, const char *host, uint16_t port, struct addrinfo **out_addr)
{
int err;
char s_port[NI_MAXSERV];

if (port) {
wget_snprintf(s_port, sizeof(s_port), "%hu", port);
debug_printf("resolving %s:%s...\n", host ? host : "", s_port);
} else {
debug_printf("resolving %s...\n", host);
}

struct addrinfo hints = {
.ai_family = tcp->family,
.ai_socktype = SOCK_STREAM,
.ai_flags = AI_ADDRCONFIG | (port ? AI_NUMERICSERV : 0)
};

// shortcut if no timeout has been specified
if (tcp->dns_timeout == -1)
return getaddrinfo(host, port ? s_port : NULL, &hints, out_addr);

struct gaicb addr = {
.ar_name = host,
.ar_service = port ? s_port : NULL,
.ar_request = &hints,
};
struct gaicb *addrs = &addr;

if ((err = getaddrinfo_a(GAI_NOWAIT, &addrs, 1, NULL))) {
debug_printf("getaddrinfo_a() failed (%d): %s\n", err, gai_strerror(err));
return err;
}

struct timespec tmo = {
.tv_sec = tcp->dns_timeout / 1000,
.tv_nsec = (tcp->dns_timeout % 1000) * 1000000
};

if ((err = gai_suspend((const struct gaicb * const *) &addrs, 1, &tmo)) == EAI_AGAIN) {
// timeout occurred, do we need to cancel ?
int cancel_err = gai_cancel(&addr);
debug_printf("gai_cancel = %s\n", gai_strerror(cancel_err));
} else if (err == EAI_ALLDONE) {
debug_printf("gai_suspend(): %s, accept as OK\n", gai_strerror(err));
err = 0;
} else if (err)
debug_printf("gai_suspend() failed (%d): %s\n", err, gai_strerror(err));

gai_cancel(NULL); // seems to free some internal memory, but this is not even documented

if (err == 0) {
if (addr.ar_result) {
*out_addr = addr.ar_result;
addr.ar_result = NULL;
} else
err = EAI_NODATA; // as returned by getaddrinfo(): "No address associated with hostname"
}

return err;
}
#else
// we can't provide a portable way of respecting a DNS timeout
static int _wget_tcp_resolve(wget_tcp_t *tcp, const char *host, uint16_t port, struct addrinfo **out_addr)
{
Expand All @@ -313,7 +250,6 @@ static int _wget_tcp_resolve(wget_tcp_t *tcp, const char *host, uint16_t port, s
return getaddrinfo(host, NULL, &hints, out_addr);
}
}
#endif

/**
* \param[in] tcp A `wget_tcp_t` structure, obtained with a previous call to wget_tcp_init().
Expand Down

0 comments on commit 8a8d1de

Please sign in to comment.