Commit 92aaff00 authored by Steinar H. Gunderson's avatar Steinar H. Gunderson
Browse files

Fix a bug where fallback from AF_INET6 to AF_INET would not work properly...

Fix a bug where fallback from AF_INET6 to AF_INET would not work properly together with relative search; if you had a search path of .a.com and .b.com, and foo.a.com would return ARES_ENODATA and foo.b.com would return ARES_ENOTFOUND, the lookup would not properly retry with AF_INET as it forgot the first ARES_ENODATA.
parent 65ba6e33
Loading
Loading
Loading
Loading
+22 −4
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ struct search_query {
  int next_domain;              /* next search domain to try */
  int trying_as_is;             /* current query is for name as-is */
  int timeouts;                 /* number of timeouts we saw for this request */
  int ever_got_nodata;          /* did we ever get ARES_ENODATA along the way? */
};

static void search_callback(void *arg, int status, int timeouts,
@@ -98,6 +99,7 @@ void ares_search(ares_channel channel, const char *name, int dnsclass,
  squery->callback = callback;
  squery->arg = arg;
  squery->timeouts = 0;
  squery->ever_got_nodata = 0;

  /* Count the number of dots in name. */
  ndots = 0;
@@ -157,6 +159,17 @@ static void search_callback(void *arg, int status, int timeouts,
      /* Save the status if we were trying as-is. */
      if (squery->trying_as_is)
        squery->status_as_is = status;

      /* 
       * If we ever get ARES_ENODATA along the way, record that; if the search
       * should run to the very end and we got at least one ARES_ENODATA,
       * then callers like ares_gethostbyname() may want to try a T_A search
       * even if the last domain we queried for T_AAAA resource records
       * returned ARES_ENOTFOUND.
       */
      if (status == ARES_ENODATA)
        squery->ever_got_nodata = 1;

      if (squery->next_domain < channel->ndomains)
        {
          /* Try the next domain. */
@@ -180,10 +193,15 @@ static void search_callback(void *arg, int status, int timeouts,
          ares_query(channel, squery->name, squery->dnsclass, squery->type,
                     search_callback, squery);
        }
      else {
        if (squery->status_as_is == ARES_ENOTFOUND && squery->ever_got_nodata) {
          end_squery(squery, ARES_ENODATA, NULL, 0);
        }
        else
          end_squery(squery, squery->status_as_is, NULL, 0);
      }
    }
}

static void end_squery(struct search_query *squery, int status,
                       unsigned char *abuf, int alen)