Commit c33aee16 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

treaded-resolver: better error messages

Now use gai_strerror() to get proper error messages when getaddrinfo()
has failed. Detect the function in configure.

Code based on work and suggestions by Jeff Pohlmeyer and Guenter Knauf
parent 3b1b2657
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2517,6 +2517,7 @@ CURL_CHECK_FUNC_FREEIFADDRS
CURL_CHECK_FUNC_FSETXATTR
CURL_CHECK_FUNC_FTRUNCATE
CURL_CHECK_FUNC_GETADDRINFO
CURL_CHECK_FUNC_GAI_STRERROR
CURL_CHECK_FUNC_GETHOSTBYADDR
CURL_CHECK_FUNC_GETHOSTBYADDR_R
CURL_CHECK_FUNC_GETHOSTBYNAME
+31 −10
Original line number Diff line number Diff line
@@ -64,6 +64,12 @@
#define in_addr_t unsigned long
#endif

#ifdef HAVE_GETADDRINFO
#  define RESOLVER_ENOMEM  EAI_MEMORY
#else
#  define RESOLVER_ENOMEM  ENOMEM
#endif

#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
@@ -281,9 +287,9 @@ static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg)
  rc = Curl_getaddrinfo_ex(tsd->hostname, service, &tsd->hints, &tsd->res);

  if(rc != 0) {
    tsd->sock_error = SOCKERRNO;
    tsd->sock_error = SOCKERRNO?SOCKERRNO:rc;
    if(tsd->sock_error == 0)
      tsd->sock_error = ENOMEM;
      tsd->sock_error = RESOLVER_ENOMEM;
  }

  Curl_mutex_acquire(tsd->mtx);
@@ -307,7 +313,7 @@ static unsigned int CURL_STDCALL gethostbyname_thread (void *arg)
  if(!tsd->res) {
    tsd->sock_error = SOCKERRNO;
    if(tsd->sock_error == 0)
      tsd->sock_error = ENOMEM;
      tsd->sock_error = RESOLVER_ENOMEM;
  }

  Curl_mutex_acquire(tsd->mtx);
@@ -355,7 +361,7 @@ static bool init_resolve_thread (struct connectdata *conn,
                                 const struct addrinfo *hints)
{
  struct thread_data *td = calloc(1, sizeof(struct thread_data));
  int err = ENOMEM;
  int err = RESOLVER_ENOMEM;

  conn->async.os_specific = (void*) td;
  if(!td)
@@ -409,6 +415,24 @@ static bool init_resolve_thread (struct connectdata *conn,
  return FALSE;
}

/*
 * resolver_error() calls failf() with the appropriate message after a resolve
 * error
 */

static void resolver_error(struct connectdata *conn, const char *host_or_proxy)
{
  failf(conn->data, "Could not resolve %s: %s; %s", host_or_proxy,
        conn->async.hostname,
#ifdef HAVE_GAI_STRERROR
        /* NetWare doesn't have gai_strerror and on Windows it isn't deemed
           thread-safe */
        gai_strerror(conn->async.status)
#else
        Curl_strerror(conn, conn->async.status);
#endif
    );
}

/*
 * Curl_resolver_wait_resolv()
@@ -443,13 +467,11 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
  if(!conn->async.dns) {
    /* a name was not resolved */
    if(conn->bits.httpproxy) {
      failf(data, "Could not resolve proxy: %s; %s",
            conn->async.hostname, Curl_strerror(conn, conn->async.status));
      resolver_error(conn, "proxy");
      rc = CURLE_COULDNT_RESOLVE_PROXY;
    }
    else {
      failf(data, "Could not resolve host: %s; %s",
            conn->async.hostname, Curl_strerror(conn, conn->async.status));
      resolver_error(conn, "host");
      rc = CURLE_COULDNT_RESOLVE_HOST;
    }
  }
@@ -490,8 +512,7 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
    destroy_async_data(&conn->async);

    if(!conn->async.dns) {
      failf(data, "Could not resolve host: %s; %s",
            conn->host.name, Curl_strerror(conn, conn->async.status));
      resolver_error(conn, "host");
      return CURLE_COULDNT_RESOLVE_HOST;
    }
    *entry = conn->async.dns;
+94 −1
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@
#                            | (__| |_| |  _ <| |___
#                             \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
# Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -2314,6 +2314,99 @@ AC_DEFUN([CURL_CHECK_FUNC_GETHOSTBYADDR], [
  fi
])

dnl CURL_CHECK_FUNC_GAI_STRERROR
dnl -------------------------------------------------
dnl Verify if gai_strerror is available, prototyped,
dnl and can be compiled. If all of these are true,
dnl and usage has not been previously disallowed with
dnl shell variable curl_disallow_gai_strerror, then
dnl HAVE_GAI_STRERROR will be defined.

AC_DEFUN([CURL_CHECK_FUNC_GAI_STRERROR], [
  AC_REQUIRE([CURL_INCLUDES_WINSOCK2])dnl
  AC_REQUIRE([CURL_INCLUDES_NETDB])dnl
  #
  tst_links_gai_strerror="unknown"
  tst_proto_gai_strerror="unknown"
  tst_compi_gai_strerror="unknown"
  tst_allow_gai_strerror="unknown"
  #
  AC_MSG_CHECKING([if gai_strerror can be linked])
  AC_LINK_IFELSE([
    AC_LANG_PROGRAM([[
      $curl_includes_winsock2
      $curl_includes_netdb
    ]],[[
      if(0 != gai_strerror(0))
        return 1;
    ]])
  ],[
    AC_MSG_RESULT([yes])
    tst_links_gai_strerror="yes"
  ],[
    AC_MSG_RESULT([no])
    tst_links_gai_strerror="no"
  ])
  #
  if test "$tst_links_gai_strerror" = "yes"; then
    AC_MSG_CHECKING([if gai_strerror is prototyped])
    AC_EGREP_CPP([gai_strerror],[
      $curl_includes_winsock2
      $curl_includes_netdb
    ],[
      AC_MSG_RESULT([yes])
      tst_proto_gai_strerror="yes"
    ],[
      AC_MSG_RESULT([no])
      tst_proto_gai_strerror="no"
    ])
  fi
  #
  if test "$tst_proto_gai_strerror" = "yes"; then
    AC_MSG_CHECKING([if gai_strerror is compilable])
    AC_COMPILE_IFELSE([
      AC_LANG_PROGRAM([[
        $curl_includes_winsock2
        $curl_includes_netdb
      ]],[[
        if(0 != gai_strerror(0))
          return 1;
      ]])
    ],[
      AC_MSG_RESULT([yes])
      tst_compi_gai_strerror="yes"
    ],[
      AC_MSG_RESULT([no])
      tst_compi_gai_strerror="no"
    ])
  fi
  #
  if test "$tst_compi_gai_strerror" = "yes"; then
    AC_MSG_CHECKING([if gai_strerror usage allowed])
    if test "x$curl_disallow_gai_strerror" != "xyes"; then
      AC_MSG_RESULT([yes])
      tst_allow_gai_strerror="yes"
    else
      AC_MSG_RESULT([no])
      tst_allow_gai_strerror="no"
    fi
  fi
  #
  AC_MSG_CHECKING([if gai_strerror might be used])
  if test "$tst_links_gai_strerror" = "yes" &&
     test "$tst_proto_gai_strerror" = "yes" &&
     test "$tst_compi_gai_strerror" = "yes" &&
     test "$tst_allow_gai_strerror" = "yes"; then
    AC_MSG_RESULT([yes])
    AC_DEFINE_UNQUOTED(HAVE_GAI_STRERROR, 1,
      [Define to 1 if you have the gai_strerror function.])
    ac_cv_func_gai_strerror="yes"
  else
    AC_MSG_RESULT([no])
    ac_cv_func_gai_strerror="no"
  fi
])


dnl CURL_CHECK_FUNC_GETHOSTBYADDR_R
dnl -------------------------------------------------