static void next_lookup(struct addr_query *aquery)
{
  const char *p;
  char name[128];
  int status;
  struct hostent *host;

  for (p = aquery->remaining_lookups; *p; p++)
    {
      switch (*p)
        {
        case 'b':
          ptr_rr_name(name, &aquery->addr);
          aquery->remaining_lookups = p + 1;
          ares_query(aquery->channel, name, C_IN, T_PTR, addr_callback,
                     aquery);
          return;
        case 'f':
          status = file_lookup(&aquery->addr, &host);

          /* this status check below previously checked for !ARES_ENOTFOUND,
             but we should not assume that this single error code is the one
             that can occur, as that is in fact no longer the case */
          if (status == ARES_SUCCESS)
            {
              end_aquery(aquery, status, host);
              return;
            }
          break;
        }
    }
  end_aquery(aquery, ARES_ENOTFOUND, NULL);
}
Exemplo n.º 2
0
static int
query(const char *domain, int type, int flags, 
      cell_db_entry *dbservers, int max_num, 
      int *ret_num, int *lowest_ttl)
{
    struct ko_dns_query q;

    q.domain = domain;
    q.flags = flags & (CELL_QUERY|HOST_QUERY);
    q.dbservers = dbservers;
    q.max_num = max_num;
    if (type & CELL_QUERY)
	q.dbnum = 0;
    else
	q.dbnum = max_num;
    if (lowest_ttl)
	q.lowest_ttl = *lowest_ttl;

    IOMGR_Cancel(ares_pid);
    
    ares_query(achannel, domain, C_IN, type, callback, &q);

    while((q.flags & QUERY_DONE) == 0)
	LWP_WaitProcess(&q);

    if (lowest_ttl)
	*lowest_ttl = q.lowest_ttl;
    if (ret_num)
	*ret_num = q.dbnum;
    return q.error;
}
Exemplo n.º 3
0
static PyObject *
DNSResolver_func_query_a(DNSResolver *self, PyObject *args)
{
    char *name;
    ares_cb_data_t *cb_data;
    PyObject *callback;

    if (!PyArg_ParseTuple(args, "sO:query_a", &name, &callback)) {
        return NULL;
    }

    if (!PyCallable_Check(callback)) {
        PyErr_SetString(PyExc_TypeError, "a callable is required");
        return NULL;
    }

    cb_data = (ares_cb_data_t*) PyMem_Malloc(sizeof *cb_data);
    if (!cb_data) {
        return PyErr_NoMemory();
    }

    Py_INCREF(callback);
    cb_data->resolver = self;
    cb_data->cb = callback;

    ares_query(self->channel, name, C_IN, T_A, &query_a_cb, (void *)cb_data);

    Py_RETURN_NONE;
}
Exemplo n.º 4
0
void makeDNSTask(struct DNSTask * dnstask) {
    int type;
    struct ares_options options;
    int optmask;


    switch (dnstask->role) {
        case DNS_TASK:
            gettimeofday(&dnstask->CheckDt, NULL);
            optmask = ARES_OPT_FLAGS;
            options.servers = getNulledMemory(sizeof (struct in_addr));
            options.nservers = 1;
            options.flags = ARES_FLAG_NOCHECKRESP;
            optmask |= ARES_OPT_SERVERS;
            memcpy(options.servers, &dnstask->task->resolv->NSIP, sizeof (struct in_addr));
            ares_init_options(&dnstask->channel, &options, optmask);
            MSToTimeval(dnstask->task->Record.TimeOut, tv);
            type = dnstask->taskType;
            break;
        default:
            return;
            break;
    }


    ares_query(dnstask->channel, getPTR(dnstask->task->Record.HostName), C_IN, type, DNSTaskResolvCallback, dnstask);
    ares_getsock(dnstask->channel, &dnstask->fd, 1);
    event_assign(&dnstask->ev, base, dnstask->fd, EV_READ | EV_TIMEOUT, OnEventDNSTask, dnstask);
    event_add(&dnstask->ev, &tv);
}
Exemplo n.º 5
0
 vector<TSrvRecord> GetRecords(const string& host) const {
     ares_channel channel;
     int status;
     status = ares_init(&channel);
     if(status != ARES_SUCCESS) {
         throw UException(std::string("Failed to init ares channel: ") + ares_strerror(status));
     }
     TCallbackInfo info;
     ares_query(channel, host.c_str(), ns_c_in, ns_t_srv, callback, &info);
     wait_ares(channel);
     ares_destroy(channel);
     if (info.Status != ARES_SUCCESS) {
         throw UException(std::string("Failed to make ares request: ") + ares_strerror(info.Status));
     }
     struct ares_srv_reply* reply;
     status = ares_parse_srv_reply((const unsigned char*)info.Data.data(), info.Data.length(), &reply);
     if (info.Status != ARES_SUCCESS) {
         throw UException(std::string("Failed to parse response: ") + ares_strerror(status));
     }
     vector<TSrvRecord> records;
     struct ares_srv_reply* next = reply;
     while (next != NULL) {
         TSrvRecord record;
         record.Host = next->host;
         record.Port = next->port;
         record.Priority = next->priority;
         record.Weight = next->weight;
         records.push_back(record);
         next = next->next;
     }
     ares_free_data(reply);
     return records;
 }
Exemplo n.º 6
0
inline unsigned long srv_ares(char *host, int *port, char *srv) {
	int nfds, count, srvh_len;
	char *srvh;
	fd_set read_fds, write_fds;
	struct timeval *tvp, tv;

	caport = 0;
	caadr = 0;
	ca_tmpname = NULL;
#ifdef DEBUG
	printf("!!! ARES query !!!\n");
#endif

	srvh_len = strlen(host) + strlen(srv) + 2;
	srvh = malloc(srvh_len);
	if (srvh == NULL) {
		printf("error: failed to allocate memory (%i) for ares query\n", srvh_len);
		exit_code(2);
	}
	memset(srvh, 0, srvh_len);
	strncpy(srvh, srv, strlen(srv));
	memcpy(srvh + strlen(srv), ".", 1);
	strcpy(srvh + strlen(srv) + 1, host);
#ifdef DEBUG
	printf("hostname: '%s', len: %i\n", srvh, srvh_len);
#endif

	ares_query(channel, srvh, CARES_CLASS_C_IN, CARES_TYPE_SRV, cares_callback, (char *) NULL);
#ifdef DEBUG
	printf("after ares_query\n");
#endif
	/* wait for query to complete */
	while (1) {
		FD_ZERO(&read_fds);
		FD_ZERO(&write_fds);
		nfds = ares_fds(channel, &read_fds, &write_fds);
		if (nfds == 0)
			break;
		tvp = ares_timeout(channel, NULL, &tv);
		count = select(nfds, &read_fds, &write_fds, NULL, tvp);
		if (count < 0 && errno != EINVAL) {
			perror("ares select");
			exit_code(2);
		}
		ares_process(channel, &read_fds, &write_fds);
	}
#ifdef DEBUG
	printf("end of while\n");
#endif
	*port = caport;
	if (caadr == 0 && ca_tmpname != NULL) {
		caadr = getaddress(ca_tmpname);
	}
	if (ca_tmpname != NULL)
		free(ca_tmpname);
	free(srvh);
	return caadr;
}
Exemplo n.º 7
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);
    }
}
Exemplo n.º 8
0
int
cert_updater_start(ProxyContext * const proxy_context)
{
    CertUpdater *cert_updater = &proxy_context->cert_updater;

    DNSCRYPT_PROXY_CERTS_UPDATE_START();
    ares_query(cert_updater->ar_channel, proxy_context->provider_name,
               DNS_CLASS_IN, DNS_TYPE_TXT, cert_query_cb, proxy_context);
    return 0;
}
Exemplo n.º 9
0
void DnsCachedResolver::DnsTsx::execute()
{
  ares_query(_channel->channel,
             _domain.c_str(),
             ns_c_in,
             _dnstype,
             DnsTsx::ares_callback,
             this);
  ++_channel->pending_queries;
}
Exemplo n.º 10
0
static inline unsigned long srv_ares(char *host, int *port, char *srv) {
	int nfds, count, srvh_len;
	char *srvh;
	fd_set read_fds, write_fds;
	struct timeval *tvp, tv;

	caport = 0;
	caadr = 0;
	ca_tmpname = NULL;
	dbg("starting ARES query\n");

	srvh_len = strlen(host) + strlen(srv) + 2;
	srvh = malloc(srvh_len);
	if (srvh == NULL) {
		printf("error: failed to allocate memory (%i) for ares query\n", srvh_len);
		exit_code(2, __PRETTY_FUNCTION__, "memory allocation failure");
	}
	memset(srvh, 0, srvh_len);
	strncpy(srvh, srv, strlen(srv));
	memcpy(srvh + strlen(srv), ".", 1);
	strcpy(srvh + strlen(srv) + 1, host);
	dbg("hostname: '%s', len: %i\n", srvh, srvh_len);

	ares_query(channel, srvh, CARES_CLASS_C_IN, CARES_TYPE_SRV, cares_callback, (char *) NULL);
	dbg("ares_query finished, waiting for result...\n");
	/* wait for query to complete */
	while (1) {
		FD_ZERO(&read_fds);
		FD_ZERO(&write_fds);
		nfds = ares_fds(channel, &read_fds, &write_fds);
		if (nfds == 0)
			break;
		tvp = ares_timeout(channel, NULL, &tv);
		count = select(nfds, &read_fds, &write_fds, NULL, tvp);
		if (count < 0 && errno != EINVAL) {
			perror("ares select");
			exit_code(2, __PRETTY_FUNCTION__, "ares DNS resolution failure");
		}
		ares_process(channel, &read_fds, &write_fds);
	}
	dbg("ARES answer processed\n");
	*port = caport;
	if (caadr == 0 && ca_tmpname != NULL) {
		caadr = getaddress(ca_tmpname);
	}
	if (ca_tmpname != NULL)
		free(ca_tmpname);
	free(srvh);
	return caadr;
}
Exemplo n.º 11
0
static void printer_poll(void *arg)
{
  struct printer_poll_args *pargs = (struct printer_poll_args *) arg;
  struct serverstate *state = pargs->state;
  struct printer *printer = pargs->printer;
  char *hesname;

  /* Null out the timer, since it may have just gone off. */
  printer->timer = NULL;
  hesname = hesiod_to_bind(state->hescontext, printer->name, "pcap");
  if (hesname == NULL)
    {
      syslog(LOG_ERR, "printer_poll: can't convert printer name %s to "
	     "hesiod name: %m", printer->name);
      printer->timer = timer_set_rel(60, printer_poll, pargs);
      return;
    }

  syslog(LOG_DEBUG, "printer_poll: printer %s starting query for %s",
	 printer->name, hesname);
  ares_query(state->channel, hesname, C_IN, T_TXT, printer_hes_callback,
	     pargs);
  hesiod_free_string(state->hescontext, hesname);
}
Exemplo n.º 12
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);
      }
    }
}
Exemplo n.º 13
0
int main(int argc, char **argv)
{
  ares_channel channel;
  int c, i, optmask = ARES_OPT_FLAGS, dnsclass = C_IN, type = T_A;
  int status, nfds, count;
  struct ares_options options;
  struct hostent *hostent;
  fd_set read_fds, write_fds;
  struct timeval *tvp, tv;
  struct ares_addr_node *srvr, *servers = NULL;

#ifdef USE_WINSOCK
  WORD wVersionRequested = MAKEWORD(USE_WINSOCK,USE_WINSOCK);
  WSADATA wsaData;
  WSAStartup(wVersionRequested, &wsaData);
#endif

  status = ares_library_init(ARES_LIB_INIT_ALL);
  if (status != ARES_SUCCESS)
    {
      fprintf(stderr, "ares_library_init: %s\n", ares_strerror(status));
      return 1;
    }

  options.flags = ARES_FLAG_NOCHECKRESP;
  options.servers = NULL;
  options.nservers = 0;
  while ((c = ares_getopt(argc, argv, "df:s:c:t:T:U:")) != -1)
    {
      switch (c)
        {
        case 'd':
#ifdef WATT32
          dbug_init();
#endif
          break;

        case 'f':
          /* Add a flag. */
          for (i = 0; i < nflags; i++)
            {
              if (strcmp(flags[i].name, optarg) == 0)
                break;
            }
          if (i < nflags)
            options.flags |= flags[i].value;
          else
            usage();
          break;

        case 's':
          /* User-specified name servers override default ones. */
          srvr = malloc(sizeof(struct ares_addr_node));
          if (!srvr)
            {
              fprintf(stderr, "Out of memory!\n");
              destroy_addr_list(servers);
              return 1;
            }
          append_addr_list(&servers, srvr);
          if (ares_inet_pton(AF_INET, optarg, &srvr->addr.addr4) > 0)
            srvr->family = AF_INET;
          else if (ares_inet_pton(AF_INET6, optarg, &srvr->addr.addr6) > 0)
            srvr->family = AF_INET6;
          else
            {
              hostent = gethostbyname(optarg);
              if (!hostent)
                {
                  fprintf(stderr, "adig: server %s not found.\n", optarg);
                  destroy_addr_list(servers);
                  return 1;
                }
              switch (hostent->h_addrtype)
                {
                  case AF_INET:
                    srvr->family = AF_INET;
                    memcpy(&srvr->addr.addr4, hostent->h_addr,
                           sizeof(srvr->addr.addr4));
                    break;
                  case AF_INET6:
                    srvr->family = AF_INET6;
                    memcpy(&srvr->addr.addr6, hostent->h_addr,
                           sizeof(srvr->addr.addr6));
                    break;
                  default:
                    fprintf(stderr,
                      "adig: server %s unsupported address family.\n", optarg);
                    destroy_addr_list(servers);
                    return 1;
                }
            }
          /* Notice that calling ares_init_options() without servers in the
           * options struct and with ARES_OPT_SERVERS set simultaneously in
           * the options mask, results in an initialization with no servers.
           * When alternative name servers have been specified these are set
           * later calling ares_set_servers() overriding any existing server
           * configuration. To prevent initial configuration with default
           * servers that will be discarded later, ARES_OPT_SERVERS is set.
           * If this flag is not set here the result shall be the same but
           * ares_init_options() will do needless work. */
          optmask |= ARES_OPT_SERVERS;
          break;

        case 'c':
          /* Set the query class. */
          for (i = 0; i < nclasses; i++)
            {
              if (strcasecmp(classes[i].name, optarg) == 0)
                break;
            }
          if (i < nclasses)
            dnsclass = classes[i].value;
          else
            usage();
          break;

        case 't':
          /* Set the query type. */
          for (i = 0; i < ntypes; i++)
            {
              if (strcasecmp(types[i].name, optarg) == 0)
                break;
            }
          if (i < ntypes)
            type = types[i].value;
          else
            usage();
          break;

        case 'T':
          /* Set the TCP port number. */
          if (!ISDIGIT(*optarg))
            usage();
          options.tcp_port = (unsigned short)strtol(optarg, NULL, 0);
          optmask |= ARES_OPT_TCP_PORT;
          break;

        case 'U':
          /* Set the UDP port number. */
          if (!ISDIGIT(*optarg))
            usage();
          options.udp_port = (unsigned short)strtol(optarg, NULL, 0);
          optmask |= ARES_OPT_UDP_PORT;
          break;
        }
    }
  argc -= optind;
  argv += optind;
  if (argc == 0)
    usage();

  status = ares_init_options(&channel, &options, optmask);

  if (status != ARES_SUCCESS)
    {
      fprintf(stderr, "ares_init_options: %s\n",
              ares_strerror(status));
      return 1;
    }

  if(servers)
    {
      status = ares_set_servers(channel, servers);
      destroy_addr_list(servers);
      if (status != ARES_SUCCESS)
        {
          fprintf(stderr, "ares_init_options: %s\n",
                  ares_strerror(status));
          return 1;
        }
    }

  /* Initiate the queries, one per command-line argument.  If there is
   * only one query to do, supply NULL as the callback argument;
   * otherwise, supply the query name as an argument so we can
   * distinguish responses for the user when printing them out.
   */
  if (argc == 1)
    ares_query(channel, *argv, dnsclass, type, callback, (char *) NULL);
  else
    {
      for (; *argv; argv++)
        ares_query(channel, *argv, dnsclass, type, callback, *argv);
    }

  /* Wait for all queries to complete. */
  for (;;)
    {
      FD_ZERO(&read_fds);
      FD_ZERO(&write_fds);
      nfds = ares_fds(channel, &read_fds, &write_fds);
      if (nfds == 0)
        break;
      tvp = ares_timeout(channel, NULL, &tv);
      count = select(nfds, &read_fds, &write_fds, NULL, tvp);
      if (count < 0 && SOCKERRNO != EINVAL)
        {
          perror("select");
          return 1;
        }
      ares_process(channel, &read_fds, &write_fds);
    }

  ares_destroy(channel);

  ares_library_cleanup();

#ifdef USE_WINSOCK
  WSACleanup();
#endif

  return 0;
}
/*Scheduler input function*/
void auth_mgr_input(nkn_task_id_t id)
{
    nkn_task_set_state(id, TASK_STATE_EVENT_WAIT);
    struct nkn_task     *ntask = nkn_task_get_task(id);
    int dns_type;
    int ret=0;
    char domain_name[2048];
    char *p_domain_name;

    assert(ntask);
    auth_msg_t *data = (auth_msg_t*)nkn_task_get_data(id);
    /* If its DNS lookup, the scheduler thread will just fire this request
    and leave, so no need to put it into a queue like auth tasks*/
    if (data->authtype==DNSLOOKUP)
    {
        if (adnsd_enabled) {
            adns_daemon_input(id);
            return;
        }

        auth_dns_t* pdns=(auth_dns_t*)(data->authdata);
        pdns->auth_task_id=id;
        //Returns void
        pthread_mutex_lock(&cares_mutex);
        AO_fetch_and_add1(&glob_dns_task_called);
        /* Since we will support ttl provided by nameserver
         * we will not be using gethostbyname() anymore
         * Also, I should be using nameser.h and have ns_c_in
         * and ns_t_a for the below query, but lots of woes.
                 * ares_gethostbyname(channel,(char*)pdns->domain,AF_INET,
         *		cares_callback,data);
         */

        /* TODO: use nameser.h */
        if (pdns->ip[0].family == AF_INET) {
            dns_type = 1; // ns_t_a
        } else {
            dns_type = 28; // ns_t_aaaa
        }

        if (pdns->dns_query_len == 0) {
            p_domain_name = (char *)pdns->domain;
        } else {
            memcpy(domain_name, pdns->domain, pdns->domain_len);
            domain_name[pdns->domain_len] = '.';
            memcpy(domain_name + pdns->domain_len + 1, pdns->dns_query, pdns->dns_query_len);
            domain_name[pdns->domain_len + 1 + pdns->dns_query_len] = '\0';
            p_domain_name = domain_name;
        }
        ares_query(channel,
                   p_domain_name,
                   1, /*ns_c_in = 1 Class: Internet. */
                   dns_type,
                   cares_callback_req, data);
        /*
         * Wake up the select loop.
         */
        if (channel_ready == 0) {
            ares_destroy(channel);
            //re-init the channel to get a new port
            ret = ares_init_options(&channel, &options, optmask);
            if (ret != ARES_SUCCESS) {
                DBG_LOG(SEVERE, MOD_AUTHMGR,"ares_init: %d %s", ret, ares_strerror(ret));
                assert(0);
            }
            channel_ready = 1;
            AO_fetch_and_add1(&glob_dns_channel_reinit);
            pthread_mutex_unlock(&cares_mutex);
            return;
        }
        pthread_cond_signal(&cares_cond);
        pthread_mutex_unlock(&cares_mutex);
    }
    else {
        NKN_MUTEX_LOCK(&authreq_mutex);
        if (isam_task_arrFull()) {
            nkn_task_set_action_and_state(id, TASK_ACTION_OUTPUT,
                                          TASK_STATE_RUNNABLE);
            NKN_MUTEX_UNLOCK(&authreq_mutex);
            return;
        }
        auth_task_arr[auth_task_arr_tail] = id;
        if (auth_task_arr_tail == (MAX_AM_TASK_ARR - 1))
        {
            auth_task_arr_tail = 0;
        }
        else
        {
            auth_task_arr_tail++;
        }
        pthread_cond_signal(&authreq_cond);
        NKN_MUTEX_UNLOCK(&authreq_mutex);
    }

    return;
}
Exemplo n.º 15
0
int main(int argc, char **argv)
{
  ares_channel channel;
  int c, i, optmask = ARES_OPT_FLAGS, dnsclass = C_IN, type = T_A;
  int status, nfds, count;
  struct ares_options options;
  struct hostent *hostent;
  fd_set read_fds, write_fds;
  struct timeval *tvp, tv;

#ifdef USE_WINSOCK
  WORD wVersionRequested = MAKEWORD(USE_WINSOCK,USE_WINSOCK);
  WSADATA wsaData;
  WSAStartup(wVersionRequested, &wsaData);
#endif

  options.flags = ARES_FLAG_NOCHECKRESP;
  options.servers = NULL;
  options.nservers = 0;
  while ((c = ares_getopt(argc, argv, "df:s:c:t:T:U:")) != -1)
    {
      switch (c)
        {
        case 'd':
#ifdef WATT32
          dbug_init();
#endif
          break;

        case 'f':
          /* Add a flag. */
          for (i = 0; i < nflags; i++)
            {
              if (strcmp(flags[i].name, optarg) == 0)
                break;
            }
          if (i == nflags)
            usage();
          options.flags |= flags[i].value;
          break;

        case 's':
          /* Add a server, and specify servers in the option mask. */
          if (ares_inet_pton(AF_INET, optarg, &inaddr) <= 0)
            {
              hostent = gethostbyname(optarg);
              if (!hostent || hostent->h_addrtype != AF_INET)
                {
                  fprintf(stderr, "adig: server %s not found.\n", optarg);
                  return 1;
                }
              memcpy(&inaddr, hostent->h_addr, sizeof(struct in_addr));
            }
          options.servers = realloc(options.servers, (options.nservers + 1)
                                    * sizeof(struct in_addr));
          if (!options.servers)
            {
              fprintf(stderr, "Out of memory!\n");
              return 1;
            }
          memcpy(&options.servers[options.nservers], &inaddr,
                 sizeof(struct in_addr));
          options.nservers++;
          optmask |= ARES_OPT_SERVERS;
          break;

        case 'c':
          /* Set the query class. */
          for (i = 0; i < nclasses; i++)
            {
              if (strcasecmp(classes[i].name, optarg) == 0)
                break;
            }
          if (i == nclasses)
            usage();
          dnsclass = classes[i].value;
          break;

        case 't':
          /* Set the query type. */
          for (i = 0; i < ntypes; i++)
            {
              if (strcasecmp(types[i].name, optarg) == 0)
                break;
            }
          if (i == ntypes)
            usage();
          type = types[i].value;
          break;

        case 'T':
          /* Set the TCP port number. */
          if (!ISDIGIT(*optarg))
            usage();
          options.tcp_port = (unsigned short)strtol(optarg, NULL, 0);
          optmask |= ARES_OPT_TCP_PORT;
          break;

        case 'U':
          /* Set the UDP port number. */
          if (!ISDIGIT(*optarg))
            usage();
          options.udp_port = (unsigned short)strtol(optarg, NULL, 0);
          optmask |= ARES_OPT_UDP_PORT;
          break;
        }
    }
  argc -= optind;
  argv += optind;
  if (argc == 0)
    usage();

  status = ares_init_options(&channel, &options, optmask);

  if (status != ARES_SUCCESS)
    {
      fprintf(stderr, "ares_init_options: %s\n",
              ares_strerror(status));
      return 1;
    }

  /* Initiate the queries, one per command-line argument.  If there is
   * only one query to do, supply NULL as the callback argument;
   * otherwise, supply the query name as an argument so we can
   * distinguish responses for the user when printing them out.
   */
  if (argc == 1)
    ares_query(channel, *argv, dnsclass, type, callback, (char *) NULL);
  else
    {
      for (; *argv; argv++)
        ares_query(channel, *argv, dnsclass, type, callback, *argv);
    }

  /* Wait for all queries to complete. */
  while (1)
    {
      FD_ZERO(&read_fds);
      FD_ZERO(&write_fds);
      nfds = ares_fds(channel, &read_fds, &write_fds);
      if (nfds == 0)
        break;
      tvp = ares_timeout(channel, NULL, &tv);
      count = select(nfds, &read_fds, &write_fds, NULL, tvp);
      if (count < 0 && SOCKERRNO != EINVAL)
        {
          perror("select");
          return 1;
        }
      ares_process(channel, &read_fds, &write_fds);
    }

  ares_destroy(channel);

#ifdef USE_WINSOCK
  WSACleanup();
#endif

  return 0;
}
static PyObject *
Channel_func_query(Channel *self, PyObject *args)
{
    char *name;
    int query_type;
    PyObject *callback, *ret;

    CHECK_CHANNEL(self);

    if (!PyArg_ParseTuple(args, "etiO:query", "idna", &name, &query_type, &callback)) {
        return NULL;
    }

    if (!PyCallable_Check(callback)) {
        PyErr_SetString(PyExc_TypeError, "a callable is required");
        ret = NULL;
        goto finally;
    }

    Py_INCREF(callback);

    switch (query_type) {
        case T_A:
        {
            ares_query(self->channel, name, C_IN, T_A, &query_a_cb, (void *)callback);
            break;
        }

        case T_AAAA:
        {
            ares_query(self->channel, name, C_IN, T_AAAA, &query_aaaa_cb, (void *)callback);
            break;
        }

        case T_CNAME:
        {
            ares_query(self->channel, name, C_IN, T_CNAME, &query_cname_cb, (void *)callback);
            break;
        }

        case T_MX:
        {
            ares_query(self->channel, name, C_IN, T_MX, &query_mx_cb, (void *)callback);
            break;
        }

        case T_NAPTR:
        {
            ares_query(self->channel, name, C_IN, T_NAPTR, &query_naptr_cb, (void *)callback);
            break;
        }

        case T_NS:
        {
            ares_query(self->channel, name, C_IN, T_NS, &query_ns_cb, (void *)callback);
            break;
        }

        case T_PTR:
        {
            ares_query(self->channel, name, C_IN, T_PTR, &query_ptr_cb, (void *)callback);
            break;
        }

        case T_SOA:
        {
            ares_query(self->channel, name, C_IN, T_SOA, &query_soa_cb, (void *)callback);
            break;
        }

        case T_SRV:
        {
            ares_query(self->channel, name, C_IN, T_SRV, &query_srv_cb, (void *)callback);
            break;
        }

        case T_TXT:
        {
            ares_query(self->channel, name, C_IN, T_TXT, &query_txt_cb, (void *)callback);
            break;
        }

        default:
        {
            Py_DECREF(callback);
            PyErr_SetString(PyExc_AresError, "invalid query type specified");
            ret = NULL;
            goto finally;
        }
    }
    ret = Py_None;

finally:
    PyMem_Free(name);
    Py_XINCREF(ret);
    return ret;
}
Exemplo n.º 17
0
int dns_start_query(myconn_t *rec, char *targetserver)
{
	struct ares_addr_node *srvr, *servers = NULL;
	struct ares_options options;
	int status, optmask;
	char *tdup, *tst;

	/* See what IP family we must use to communicate with the target DNS server */
	srvr = malloc(sizeof(struct ares_addr_node));
	append_addr_list(&servers, srvr);
	srvr->family = -1;
#ifdef IPV4_SUPPORT
	if ((srvr->family == -1) && (inet_pton(AF_INET, targetserver, &srvr->addr.addr4) > 0))
		srvr->family = AF_INET;
#endif

#ifdef IPV6_SUPPORT
	if ((srvr->family == -1) && (inet_pton(AF_INET6, targetserver, &srvr->addr.addr6) > 0))
		srvr->family = AF_INET6;
#endif

	if (srvr->family == -1) {
		errprintf("Unsupported IP family for DNS target IP %s, test %s\n", targetserver, rec->testspec);
		return 0;
	}

	/* Create a new ARES request channel */
	rec->dnschannel = malloc(sizeof(ares_channel));

	/* 
	 * The C-ARES timeout handling is a bit complicated. The timeout setting
	 * here in the options only determines the timeout for the first query;
	 * subsequent queries (up to the "tries" count) use a progressively
	 * higher timeout setting.
	 * So we cannot easily determine what combination of timeout/tries will
	 * result in the full query timing out after the desired number of seconds.
	 * Therefore, use a fixed set of values - the 2000 ms / 4 tries combination
	 * results in a timeout after 23-24 seconds.
	 */
	optmask = ARES_OPT_FLAGS | ARES_OPT_SERVERS | ARES_OPT_TIMEOUTMS | ARES_OPT_TRIES;
	options.flags = ARES_FLAG_NOCHECKRESP;
	options.servers = NULL;
	options.nservers = 0;
	options.timeout = 2000;
	options.tries = 4;
	status = ares_init_options(rec->dnschannel, &options, optmask);
	if (status != ARES_SUCCESS) {
		errprintf("Cannot create ARES channel for DNS target %s, test %s\n", targetserver, rec->testspec);
		rec->dnsstatus = DNS_FINISHED;
		return 0;
	}

	/* Point the channel at the target server */
	status = ares_set_servers(*((ares_channel *)rec->dnschannel), servers);
	destroy_addr_list(servers);
	if (status != ARES_SUCCESS)
	{
		errprintf("Cannot select ARES target DNS server %s, test %s\n", targetserver, rec->testspec);
		rec->dnsstatus = DNS_QUERY_COMPLETED;	/* To reap the ARES channel later */
		return 0;
	}

	/* Post the queries we want to perform */
	tdup = strdup(rec->testspec);

	tst = strtok(tdup, ",");
	do {
		char *p, *tlookup;
		int atype = dns_atype;

		p = strchr(tst, ':');
		tlookup = (p ? p+1 : tst);
		if (p) { 
			*p = '\0'; 
			atype = dns_name_type(tst);
			*p = ':';
		}

		/* Use ares_query() here, since we dont want to get results from hosts file or other odd stuff. */
		ares_query(*((ares_channel *)rec->dnschannel), tlookup, dns_aclass, atype, dns_query_callback, rec);
		tst = strtok(NULL, ",");
	} while (tst);

	xfree(tdup);

	rec->textlog = newstrbuffer(0);
	getntimer(&rec->dnsstarttime);
	rec->dnsstatus = DNS_QUERY_ACTIVE;

	return 1;
}
Exemplo n.º 18
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);
      }
    }
}