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

- ares_gethostbyname() now accepts 'AF_UNSPEC' as a family for resolving

  either AF_INET6 or AF_INET. It works by accepting any of the looksups in the
  hosts file, and it resolves the AAAA field with a fallback to A.
parent 8b680557
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
  Changelog for the c-ares project

* January 31 2009 (Daniel Stenberg)
- ares_gethostbyname() now accepts 'AF_UNSPEC' as a family for resolving
  either AF_INET6 or AF_INET. It works by accepting any of the looksups in the
  hosts file, and it resolves the AAAA field with a fallback to A.

* January 14 2009 (Daniel Stenberg)
- ares.h no longer uses the HAVE_STRUCT_IN6_ADDR define check, but instead it
  now declares the private struct ares_in6_addr for all systems instead of
+4 −2
Original line number Diff line number Diff line
@@ -2,8 +2,10 @@ This is what's new and changed in the c-ares 1.6.1 release:

Changed:

 o in6_addr is not used in ares.h anymore, but a private ares_in6_addr is instead
   declared and used
 o in6_addr is not used in ares.h anymore, but a private ares_in6_addr is
   instead declared and used
 p ares_gethostbyname() now supports 'AF_UNSPEC' as a family for resolving
   either AF_INET6 or AF_INET

Fixed:

+14 −10
Original line number Diff line number Diff line
@@ -69,16 +69,20 @@ int ares__get_hostent(FILE *fp, int family, struct hostent **host)
      addr.s_addr = inet_addr(line);
      if (addr.s_addr == INADDR_NONE)
      {
          if (ares_inet_pton(AF_INET6, line, &addr6) > 0)
            {
              if (family != AF_INET6)
                continue;
        /* It wasn't an AF_INET dotted address, then AF_UNSPEC and AF_INET6
           families are subject for this further check */
        if ((family != AF_INET) &&
            (ares_inet_pton(AF_INET6, line, &addr6) > 0)) {
          addrlen = sizeof(struct in6_addr);
          family = AF_INET6;
        }
        else
          continue;
      }
      else if (family == AF_UNSPEC)
        family = AF_INET; /* now confirmed! */
      else if (family != AF_INET)
        /* unknown, keep moving */
        continue;

      /* Get the canonical hostname. */
+54 −41
Original line number Diff line number Diff line
@@ -61,7 +61,8 @@ struct host_query {
  char *name;
  ares_host_callback callback;
  void *arg;
  int family;
  int sent_family; /* this family is what was is being used */
  int want_family; /* this family is what is asked for in the API */
  const char *remaining_lookups;
  int timeouts;
};
@@ -71,26 +72,31 @@ static void host_callback(void *arg, int status, int timeouts,
                          unsigned char *abuf, int alen);
static void end_hquery(struct host_query *hquery, int status,
                       struct hostent *host);
static int fake_hostent(const char *name, int family, ares_host_callback callback,
                        void *arg);
static int fake_hostent(const char *name, int family,
                        ares_host_callback callback, void *arg);
static int file_lookup(const char *name, int family, struct hostent **host);
static void sort_addresses(struct hostent *host, const struct apattern *sortlist,
                           int nsort);
static void sort6_addresses(struct hostent *host, const struct apattern *sortlist,
                           int nsort);
static int get_address_index(const struct in_addr *addr, const struct apattern *sortlist,
                             int nsort);
static int get6_address_index(const struct in6_addr *addr, const struct apattern *sortlist,
                             int nsort);
static void sort_addresses(struct hostent *host,
                           const struct apattern *sortlist, int nsort);
static void sort6_addresses(struct hostent *host,
                            const struct apattern *sortlist, int nsort);
static int get_address_index(const struct in_addr *addr,
                             const struct apattern *sortlist, int nsort);
static int get6_address_index(const struct in6_addr *addr,
                              const struct apattern *sortlist, int nsort);

void ares_gethostbyname(ares_channel channel, const char *name, int family,
                        ares_host_callback callback, void *arg)
{
  struct host_query *hquery;

  /* Right now we only know how to look up Internet addresses. */
  if (family != AF_INET && family != AF_INET6)
    {
  /* Right now we only know how to look up Internet addresses - and unspec
     means try both basically. */
  switch (family) {
  case AF_INET:
  case AF_INET6:
  case AF_UNSPEC:
    break;
  default:
    callback(arg, ARES_ENOTIMP, 0, NULL);
    return;
  }
@@ -107,9 +113,9 @@ void ares_gethostbyname(ares_channel channel, const char *name, int family,
    }
  hquery->channel = channel;
  hquery->name = strdup(name);
  hquery->family = family;
  if (!hquery->name)
    {
  hquery->want_family = family;
  hquery->sent_family = -1; /* nothing is sent yet */
  if (!hquery->name) {
    free(hquery);
    callback(arg, ARES_ENOMEM, 0, NULL);
    return;
@@ -136,17 +142,23 @@ static void next_lookup(struct host_query *hquery, int status_code)
        case 'b':
          /* DNS lookup */
          hquery->remaining_lookups = p + 1;
          if (hquery->family == AF_INET6)
          if ((hquery->want_family == AF_INET6) ||
              (hquery->want_family == AF_UNSPEC)) {
            /* if inet6 or unspec, start out with AAAA */
            hquery->sent_family = AF_INET6;
            ares_search(hquery->channel, hquery->name, C_IN, T_AAAA,
                        host_callback, hquery);
          else
          }
          else {
            hquery->sent_family = AF_INET;
            ares_search(hquery->channel, hquery->name, C_IN, T_A, host_callback,
                        hquery);
          }
          return;

        case 'f':
          /* Host file lookup */
          status = file_lookup(hquery->name, hquery->family, &host);
          status = file_lookup(hquery->name, hquery->want_family, &host);

          /* this status check below previously checked for !ARES_ENOTFOUND,
             but we should not assume that this single error code is the one
@@ -173,22 +185,22 @@ static void host_callback(void *arg, int status, int timeouts,
  hquery->timeouts += timeouts;
  if (status == ARES_SUCCESS)
    {
      if (hquery->family == AF_INET)
      if (hquery->sent_family == AF_INET)
        {
          status = ares_parse_a_reply(abuf, alen, &host, NULL, NULL);
          if (host && channel->nsort)
            sort_addresses(host, channel->sortlist, channel->nsort);
        }
      else if (hquery->family == AF_INET6)
      else if (hquery->sent_family == AF_INET6)
        {
          status = ares_parse_aaaa_reply(abuf, alen, &host, NULL, NULL);
          if (status == ARES_ENODATA)
            {
          if (status == ARES_ENODATA) {
            /* The query returned something (e.g. CNAME) but there were no
                 AAAA records.  Try looking up A instead.  */
              hquery->family = AF_INET;
              ares_search(hquery->channel, hquery->name, C_IN, T_A, host_callback,
                          hquery);
               AAAA records.  Try looking up A instead.  We should possibly
               limit this attempt-next logic to AF_UNSPEC lookups only. */
            hquery->sent_family = AF_INET;
            ares_search(hquery->channel, hquery->name, C_IN, T_A,
                        host_callback, hquery);
            return;
          }
          if (host && channel->nsort)
@@ -196,10 +208,11 @@ static void host_callback(void *arg, int status, int timeouts,
        }
      end_hquery(hquery, status, host);
    }
  else if (status == ARES_ENODATA && hquery->family == AF_INET6)
  else if (status == ARES_ENODATA && hquery->sent_family == AF_INET6)
    {
      /* There was no AAAA. Now lookup an A */
      hquery->family = AF_INET;
      /* There was no AAAA. Now lookup an A.  We should possibly limit this
         attempt-next logic to AF_UNSPEC lookups only. */
      hquery->sent_family = AF_INET;
      ares_search(hquery->channel, hquery->name, C_IN, T_A, host_callback,
                  hquery);
    }