curl / Mailing Lists / curl-library / Single Mail
Buy commercial curl support from WolfSSL. We help you work out your issues, debug your libcurl applications, use the API, port to new platforms, add new features and more. With a team lead by the curl founder himself.

Happy Eyeballs mechanism may start from IPv4 family if c-ares resolver reply for IPv6 comes first.

From: Dmitry Karpov via curl-library <>
Date: Thu, 3 Jun 2021 20:11:29 +0000


Trying dual-stack on some embedded platform, I noticed that quite frequently (20%) libCurl starts from IPv4 regardless the Happy Eyeballs timeout value.
After debugging this issue, I noticed that this happens if c-ares resolver response for IPv6 family comes before IPv4 (which was randomly happening in my tests).

In such cases, because libCurl puts the last resolver response on top of the address list, when IPv4 resolver response comes after IPv6 one - the IPv4 family starts the connection phase instead of IPv6 family.

A potential solution for this issue can be always putting IPv6 addresses on top of the address list, regardless the order of resolver responses.

Here is the proposed fix for c-ares resolver that helped to mitigate the problem:

Changing the compound_results() function in lib\asyn-ares.c to the following:

/* Connects results to the list */
static void compound_results(struct ResolverResults *res,
                             Curl_addrinfo *ai)

  /* Add the new results to the list of old results. */
  if (res->temp_ai && res->temp_ai->ai_family == PF_INET6) {
      /* We have some results already and we need to make sure that IPv6 entries
         always go to the head of the list. */
      Curl_addrinfo* temp_ai_tail = res->temp_ai;

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

      temp_ai_tail->ai_next = ai;
#endif /* CURLRES_IPV6 */
      Curl_addrinfo* ai_tail = ai;

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

      ai_tail->ai_next = res->temp_ai;
      res->temp_ai = ai;

This change makes sure that IPv6 addresses are always put on top of the address list.

Unfortunately, I didn't have time to check the other resolvers - we use only c-ares, but they should be probably checked as well.

Dmitry Karpov

Received on 2021-06-03