Commit 8ab137b2 authored by Tommie Gannert's avatar Tommie Gannert Committed by Daniel Stenberg
Browse files

ares: ask for both IPv4 and IPv6 addresses

Make the c-ares resolver code ask for both IPv4 and IPv6 addresses when
IPv6 is enabled.

This is a workaround for the missing ares_getaddrinfo() and is a lot
easier to implement.

Note that as long as c-ares returns IPv4 addresses when IPv6 addresses
were requested but missing, this will cause a host's IPv4 addresses to
occur twice in the DNS cache.

URL: http://curl.haxx.se/mail/lib-2010-12/0041.html
parent bcfb9ea3
Loading
Loading
Loading
Loading
+23 −6
Original line number Diff line number Diff line
@@ -401,10 +401,27 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
    conn->async.done = FALSE;   /* not done */
    conn->async.status = 0;     /* clear */
    conn->async.dns = NULL;     /* clear */
    conn->async.temp_ai = NULL; /* clear */

#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
    if(family == PF_UNSPEC) {
      conn->async.num_pending = 2;

      /* areschannel is already setup in the Curl_open() function */
      ares_gethostbyname(data->state.areschannel, hostname, PF_INET,
                         ares_query_completed_cb, conn);
      ares_gethostbyname(data->state.areschannel, hostname, PF_INET6,
                         ares_query_completed_cb, conn);
    }
    else
#endif /* CURLRES_IPV6 */
    {
      conn->async.num_pending = 1;

      /* areschannel is already setup in the Curl_open() function */
      ares_gethostbyname(data->state.areschannel, hostname, family,
                       (ares_host_callback)ares_query_completed_cb, conn);
                         ares_query_completed_cb, conn);
    }

    *waitp = 1; /* expect asynchronous response */
  }
+55 −2
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
 * Copyright (C) 1998 - 2010, 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
@@ -95,6 +95,20 @@ CURLcode Curl_addrinfo_callback(struct connectdata * conn,
    if(ai) {
      struct SessionHandle *data = conn->data;

#if defined(ENABLE_IPV6) && defined(CURLRES_ARES) /* CURLRES_IPV6 */
      Curl_addrinfo *ai_tail = ai;

      while (ai_tail->ai_next)
        ai_tail = ai_tail->ai_next;

      /* Add the new results to the list of old results. */
      ai_tail->ai_next = conn->async.temp_ai;
      conn->async.temp_ai = ai;

      if(--conn->async.num_pending > 0)
        /* We are not done yet. Just return. */
        return CURLE_OK;
#endif
      if(data->share)
        Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);

@@ -110,10 +124,49 @@ CURLcode Curl_addrinfo_callback(struct connectdata * conn,
      if(data->share)
        Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
    }
    else {
#if defined(ENABLE_IPV6) && defined(CURLRES_ARES) /* CURLRES_IPV6 */
      if(--conn->async.num_pending > 0) {
        /* We are not done yet. Clean up and return.
	   This function will be called again. */
        if(conn->async.temp_ai)
          Curl_freeaddrinfo(conn->async.temp_ai);
        return CURLE_OUT_OF_MEMORY;
      }
#endif
      rc = CURLE_OUT_OF_MEMORY;
    }
  }
#if defined(ENABLE_IPV6) && defined(CURLRES_ARES) /* CURLRES_IPV6 */
  else
  {
      if(--conn->async.num_pending > 0)
        /* We are not done yet. Just return. */
        return CURLE_OK;

      if(conn->async.temp_ai) {
        /* We are done, and while this latest request
           failed, some previous results exist. */
        struct SessionHandle *data = conn->data;

        if(data->share)
          Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);

        dns = Curl_cache_addr(data, conn->async.temp_ai,
                              conn->async.hostname,
                              conn->async.port);
        if(!dns) {
          /* failed to store, cleanup and return error */
          Curl_freeaddrinfo(conn->async.temp_ai);
          rc = CURLE_OUT_OF_MEMORY;
        }

        if(data->share)
          Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
      }
  }
#endif

  conn->async.dns = dns;

 /* Set async.done TRUE last in this function since it may be used multi-
+2 −0
Original line number Diff line number Diff line
@@ -479,6 +479,8 @@ struct Curl_async {
  bool done;  /* set TRUE when the lookup is complete */
  int status; /* if done is TRUE, this is the status from the callback */
  void *os_specific;  /* 'struct thread_data' for Windows */
  int num_pending; /* number of ares_gethostbyname() requests */
  Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares parts */
};
#endif