Esempio n. 1
0
static void search_callback(void *arg, int status, unsigned char *abuf,
			    int alen)
{
  struct search_query *squery = (struct search_query *) arg;
  ares_channel channel = squery->channel;
  char *s;

  /* Stop searching unless we got a non-fatal error. */
  if (status != ARES_ENODATA && status != ARES_ESERVFAIL
      && status != ARES_ENOTFOUND)
    end_squery(squery, status, abuf, alen);
  else
    {
      /* Save the status if we were trying as-is. */
      if (squery->trying_as_is)
	squery->status_as_is = status;
      if (squery->next_domain < channel->ndomains)
	{
	  /* Try the next domain. */
	  status = cat_domain(squery->name,
			      channel->domains[squery->next_domain], &s);
	  if (status != ARES_SUCCESS)
	    end_squery(squery, status, NULL, 0);
	  else
	    {
	      squery->trying_as_is = 0;
	      squery->next_domain++;
	      ares_query(channel, s, squery->dnsclass, squery->type,
			 search_callback, squery);
	      free(s);
	    }
	}
      else if (squery->status_as_is == -1)
	{
	  /* Try the name as-is at the end. */
	  squery->trying_as_is = 1;
	  ares_query(channel, squery->name, squery->dnsclass, squery->type,
		     search_callback, squery);
	}
      else
	end_squery(squery, squery->status_as_is, NULL, 0);
    }
}
Esempio n. 2
0
void ares_search(ares_channel channel, const char *name, int dnsclass,
		 int type, ares_callback callback, void *arg)
{
  struct search_query *squery;
  char *s;
  const char *p;
  int status, ndots;

  /* If name only yields one domain to search, then we don't have
   * to keep extra state, so just do an ares_query().
   */
  status = single_domain(channel, name, &s);
  if (status != ARES_SUCCESS)
    {
      callback(arg, status, NULL, 0);
      return;
    }
  if (s)
    {
      ares_query(channel, s, dnsclass, type, callback, arg);
      free(s);
      return;
    }

  /* Allocate a search_query structure to hold the state necessary for
   * doing multiple lookups.
   */
  squery = malloc(sizeof(struct search_query));
  if (!squery)
    {
      callback(arg, ARES_ENOMEM, NULL, 0);
      return;
    }
  squery->channel = channel;
  squery->name = strdup(name);
  if (!squery->name)
    {
      free(squery);
      callback(arg, ARES_ENOMEM, NULL, 0);
      return;
    }
  squery->dnsclass = dnsclass;
  squery->type = type;
  squery->status_as_is = -1;
  squery->callback = callback;
  squery->arg = arg;

  /* Count the number of dots in name. */
  ndots = 0;
  for (p = name; *p; p++)
    {
      if (*p == '.')
	ndots++;
    }

  /* If ndots is at least the channel ndots threshold (usually 1),
   * then we try the name as-is first.  Otherwise, we try the name
   * as-is last.
   */
  if (ndots >= channel->ndots)
    {
      /* Try the name as-is first. */
      squery->next_domain = 0;
      squery->trying_as_is = 1;
      ares_query(channel, name, dnsclass, type, search_callback, squery);
    }
  else
    {
      /* Try the name as-is last; start with the first search domain. */
      squery->next_domain = 1;
      squery->trying_as_is = 0;
      status = cat_domain(name, channel->domains[0], &s);
      if (status == ARES_SUCCESS)
      {
	  ares_query(channel, s, dnsclass, type, search_callback, squery);
	  free(s);
      }
      else
      {
	free(squery->name);
        free(squery);
	callback(arg, status, NULL, 0);
      }
    }
}
Esempio n. 3
0
static void search_callback(void *arg, int status, int timeouts,
                            unsigned char *abuf, int alen)
{
  struct search_query *squery = (struct search_query *) arg;
  ares_channel channel = squery->channel;
  char *s;

  squery->timeouts += timeouts;

  /* Stop searching unless we got a non-fatal error. */
  if (status != ARES_ENODATA && status != ARES_ESERVFAIL
      && status != ARES_ENOTFOUND)
    end_squery(squery, status, abuf, alen);
  else
    {
      /* 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. */
          status = cat_domain(squery->name,
                              channel->domains[squery->next_domain], &s);
          if (status != ARES_SUCCESS)
            end_squery(squery, status, NULL, 0);
          else
            {
              squery->trying_as_is = 0;
              squery->next_domain++;
              ares_query(channel, s, squery->dnsclass, squery->type,
                         search_callback, squery);
              free(s);
            }
        }
      else if (squery->status_as_is == -1)
        {
          /* Try the name as-is at the end. */
          squery->trying_as_is = 1;
          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);
      }
    }
}