Example #1
0
int
resolv_init(struct ev_loop *loop, char *nameservers, int ipv6first)
{
    int status;

    if (ipv6first)
        resolv_mode = MODE_IPV6_FIRST;
    else
        resolv_mode = MODE_IPV4_FIRST;

    default_loop = loop;

    if ((status = ares_library_init(ARES_LIB_INIT_ALL)) != ARES_SUCCESS) {
        LOGE("c-ares error: %s", ares_strerror(status));
        FATAL("failed to initialize c-ares");
    }

    memset(&default_ctx, 0, sizeof(struct resolv_ctx));

    default_ctx.options.sock_state_cb_data = &default_ctx;
    default_ctx.options.sock_state_cb      = resolv_sock_state_cb;
    default_ctx.options.timeout            = 3000;
    default_ctx.options.tries              = 2;

    status = ares_init_options(&default_ctx.channel, &default_ctx.options,
#if ARES_VERSION_MAJOR >= 1 && ARES_VERSION_MINOR >= 12
                               ARES_OPT_NOROTATE |
#endif
                               ARES_OPT_TIMEOUTMS | ARES_OPT_TRIES | ARES_OPT_SOCK_STATE_CB);

    if (status != ARES_SUCCESS) {
        FATAL("failed to initialize c-ares");
    }

    if (nameservers != NULL) {
#if ARES_VERSION_MAJOR >= 1 && ARES_VERSION_MINOR >= 11
        status = ares_set_servers_ports_csv(default_ctx.channel, nameservers);
#else
        status = ares_set_servers_csv(default_ctx.channel, nameservers);
#endif
    }

    if (status != ARES_SUCCESS) {
        FATAL("failed to set nameservers");
    }

    ev_init(&default_ctx.io, resolv_sock_cb);
    ev_timer_init(&default_ctx.tw, resolv_timeout_cb, 0.0, 0.0);

    return 0;
}
Example #2
0
/* ares_dup() duplicates a channel handle with all its options and returns a
   new channel handle */
int ares_dup(ares_channel *dest, ares_channel src)
{
  struct ares_options opts;
  struct ares_addr_node *servers;
  int ipv6_nservers = 0;
  int i, rc;
  int optmask;

  *dest = NULL; /* in case of failure return NULL explicitly */

  /* First get the options supported by the old ares_save_options() function,
     which is most of them */
  rc = ares_save_options(src, &opts, &optmask);
  if(rc)
    return rc;

  /* Then create the new channel with those options */
  rc = ares_init_options(dest, &opts, optmask);

  /* destroy the options copy to not leak any memory */
  ares_destroy_options(&opts);

  if(rc)
    return rc;

  /* Now clone the options that ares_save_options() doesn't support. */
  (*dest)->sock_create_cb      = src->sock_create_cb;
  (*dest)->sock_create_cb_data = src->sock_create_cb_data;

  /* Full name server cloning required when not all are IPv4 */
  for (i = 0; i < src->nservers; i++)
    {
      if (src->servers[i].addr.family != AF_INET) {
        ipv6_nservers++;
        break;
      }
    }
  if (ipv6_nservers) {
    rc = ares_get_servers(src, &servers);
    if (rc != ARES_SUCCESS)
      return rc;
    rc = ares_set_servers(*dest, servers);
    ares_free_data(servers);
    if (rc != ARES_SUCCESS)
      return rc;
  }

  return ARES_SUCCESS; /* everything went fine */
}
Example #3
0
int Resolver::init(int flags/*=0*/, int tries/*=0*/, int ndots/*=0*/, int udp_port/*=0*/, int tcp_port/*=0*/)
{
    //初始lib  void*
    g_ObjCAresLib.init_lib();

    struct ares_options options;
    memset(&options, 0, sizeof(options));
    int optmask = ARES_OPT_SOCK_STATE_CB;
    options.sock_state_cb = Resolver::sock_state_callback;
    options.sock_state_cb_data = this; 
    if(flags)
    {
        options.flags = flags;
        optmask |= ARES_OPT_FLAGS;
    }
    /*if(timeout_ms)
    {
        options.timeout = timeout_ms;
        optmask |= ARES_OPT_TIMEOUTMS;
    }*/
    if(tries)
    {
        options.tries = tries;
        optmask |= ARES_OPT_TRIES;
    }
    if(ndots)
    {
        options.ndots = ndots;
        optmask |= ARES_OPT_NDOTS;
    }
    if(udp_port)
    {
        options.udp_port = udp_port;
        optmask |= ARES_OPT_UDP_PORT;
    }
    if(tcp_port)
    {
        options.tcp_port = tcp_port;
        optmask |= ARES_OPT_TCP_PORT;
    }
    assert(channel_ == nullptr);
    int result = ares_init_options(&channel_, &options, optmask);
    if (result != ARES_SUCCESS)
    {
        TORNADO_LOG_WARN("ares_init_options: %s", ares_strerror(result));
        return -1;
    }
    return 0;
}
Example #4
0
void dns_lookup_init(void)
{
	struct ares_options options;
	int optmask, status;
	int dbres;

	optmask = ARES_OPT_TIMEOUTMS | ARES_OPT_TRIES | ARES_OPT_FLAGS;
	options.flags = ARES_FLAG_STAYOPEN;
	options.timeout = 2000;
	options.tries = 4;
	status = ares_init_options(&dns_lookupchannel, &options, optmask);
	if (status != ARES_SUCCESS) {
		errprintf("Cannot initialise DNS lookups: %s\n", ares_strerror(status));
		return;
	}
}
Example #5
0
struct hostent *nssrs_resolver_by_servers(char *name, char *nameserver) {
    ares_channel channel = NULL;
    int status, optmask = 0;
    struct ares_options options;
    struct hostent *results;

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

    optmask = ARES_OPT_SERVERS | ARES_OPT_UDP_PORT;
    options.servers  = NULL;
    options.nservers = 0;
    options.flags    = ARES_FLAG_NOCHECKRESP;

    status = ares_init_options(&channel, &options, optmask);
    if(status != ARES_SUCCESS) {
        debug("ares_init_options: %s\n", ares_strerror(status));
        return NULL;
    }

    status = ares_set_servers_csv(channel, nameserver);
    if (status != ARES_SUCCESS) {
      debug("ares_set_servers_csv: %s\n", ares_strerror(status));
      ares_destroy(channel);
      ares_library_cleanup();
      return NULL;
    }

    // Wait resolver
    results = malloc(sizeof(struct hostent));
    ares_gethostbyname(channel, name, AF_INET, &callback, results);
    wait_ares(channel);
    ares_destroy(channel);
    ares_library_cleanup();

    if (results->h_name != NULL) {
        return results;
    }

    free(results);
    return NULL;
}
Example #6
0
/*
 * Curl_resolver_init()
 *
 * Called from curl_easy_init() -> Curl_open() to initialize resolver
 * URL-state specific environment ('resolver' member of the UrlState
 * structure).  Fills the passed pointer by the initialized ares_channel.
 */
CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver)
{
  int status;
  struct ares_options options;
  int optmask = ARES_OPT_SOCK_STATE_CB;
  options.sock_state_cb = Curl_ares_sock_state_cb;
  options.sock_state_cb_data = easy;
  status = ares_init_options((ares_channel*)resolver, &options, optmask);
  if(status != ARES_SUCCESS) {
    if(status == ARES_ENOMEM)
      return CURLE_OUT_OF_MEMORY;
    else
      return CURLE_FAILED_INIT;
  }
  return CURLE_OK;
  /* make sure that all other returns from this function should destroy the
     ares channel before returning error! */
}
Example #7
0
// Bad synchronous gethostbyname demo
uint32_t tm__sync_gethostbyname (const char *domain)
{
    ares_channel channel;
    int status;
    struct ares_options options;
    int optmask = 0;

    ipaddr[0] = ipaddr[1] = ipaddr[2] = ipaddr[3] = 0;

    struct in_addr ns1;

    inet_aton("8.8.8.8",&ns1);
 
    status = ares_library_init(ARES_LIB_INIT_ALL);
    if (status != ARES_SUCCESS){
        printf("ares_library_init: %s\n", ares_strerror(status));
        return 1;
    }
    options.servers = &ns1;
    options.nservers = 1;
    optmask |= ARES_OPT_SERVERS;
    options.sock_state_cb = state_cb;
    // options.sock_state_cb_data;
    optmask |= ARES_OPT_SOCK_STATE_CB;
 
    status = ares_init_options(&channel, &options, optmask);
    if(status != ARES_SUCCESS) {
        printf("ares_init_options: %s\n", ares_strerror(status));
        return 1;
    }
 
    ares_gethostbyname(channel, domain, AF_INET, callback, NULL);
    wait_ares(channel);
    ares_destroy(channel);
    ares_library_cleanup();
    // printf("fin\n");
    // printf("result => %d.%d.%d.%d\n", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);

    return (ipaddr[0] << 24) | (ipaddr[1] << 16) | (ipaddr[2] << 8) | ipaddr[3];
}
Example #8
0
/* Finds the SRV records for the given host. It returns the target IP
 * address and fills the port and transport if a suitable SRV record
 * exists. Otherwise it returns 0. The function follows 3263: first
 * TLS, then TCP and finally UDP. */
int getsrvadr(char *host, struct addrinfo *res) {
	int ret = -1;

#ifdef HAVE_SVR

#ifdef HAVE_CARES_H
	int status;
	int optmask = ARES_OPT_FLAGS;
	struct ares_options options;

	options.flags = ARES_FLAG_NOCHECKRESP;
	options.servers = NULL;
	options.nservers = 0;

	status = ares_init_options(&channel, &options, optmask);
	if (status != ARES_SUCCESS) {
		printf("error: failed to initialize ares\n");
		exit_code(2, __PRETTY_FUNCTION__, "failed to init ares lib");
	}
#endif

#ifdef WITH_TLS_TRANSP
	printf("TLS transport not yet supported\n");
	exit_code(2);
#endif
	ret = getsrvaddress(host, service, SRV_SIP_TCP, SIP_TCP_TRANSPORT, res);
	if (ret >= 0) {
		if (verbose > 1)
			printf("using SRV record: %s.%s:%i\n", SRV_SIP_TLS, host, srvport);
	}
	else {
		ret = getsrvaddress(host, service, SRV_SIP_UDP, SIP_UDP_TRANSPORT, res);
		if (ret >= 0) {
			if (verbose > 1)
				printf("using SRV record: %s.%s:%s\n", SRV_SIP_UDP, host, service);
		}
	}
#ifdef WITH_TLS_TRANSP
	}
Example #9
0
static ph_dns_channel_t *create_chan(void)
{
  ph_dns_channel_t *chan;
  struct ares_options opts;
  int res;
  pthread_mutexattr_t attr;

  chan = ph_mem_alloc(mt.chan);
  if (!chan) {
    return NULL;
  }

  pthread_mutexattr_init(&attr);
  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  pthread_mutex_init(&chan->chanlock, &attr);
  pthread_mutexattr_destroy(&attr);

  if (ph_ht_init(&chan->sock_map, 4, &sock_key, &ph_ht_ptr_val_def) != PH_OK) {
    ph_panic("failed to init sock map");
  }

  memset(&opts, 0, sizeof(opts));
  opts.sock_state_cb_data = chan;
  opts.sock_state_cb = sock_state_cb;
  opts.flags = ARES_FLAG_STAYOPEN;

  res = ares_init_options(&chan->chan, &opts,
      ARES_OPT_SOCK_STATE_CB|ARES_OPT_FLAGS);

  if (res != ARES_SUCCESS) {
    ph_panic("failed to ares_init_options: %s", ares_strerror(res));
  }

  ares_set_socket_callback(chan->chan, sock_create_cb, chan);

  return chan;
}
Example #10
0
int
ecore_con_info_init(void)
{
   struct ares_options opts;
   
   if (!info_init)
     {
        if (ares_library_init(ARES_LIB_INIT_ALL))
          return 0;

        opts.lookups = "fb"; /* hosts file then dns */
        opts.sock_state_cb = _ecore_con_info_cares_state_cb;

        if (ares_init_options(&info_channel, &opts,
            ARES_OPT_LOOKUPS | ARES_OPT_SOCK_STATE_CB) != ARES_SUCCESS)
          {
             ares_library_cleanup();
             return 0;
          }
     }

   info_init++;
   return info_init;
}
Example #11
0
int ares_init(ares_channel *channelptr)
{
  return ares_init_options(channelptr, NULL, 0);
}
static int
Channel_tp_init(Channel *self, PyObject *args, PyObject *kwargs)
{
    int r, flags, tries, ndots, tcp_port, udp_port, optmask, ndomains, socket_send_buffer_size, socket_receive_buffer_size;
    char *lookups;
    char **c_domains;
    double timeout;
    struct ares_options options;
    PyObject *servers, *domains, *sock_state_cb;

    static char *kwlist[] = {"flags", "timeout", "tries", "ndots", "tcp_port", "udp_port",
                             "servers", "domains", "lookups", "sock_state_cb", "socket_send_buffer_size", "socket_receive_buffer_size", NULL};

    optmask = 0;
    flags = tries = ndots = tcp_port = udp_port = socket_send_buffer_size = socket_receive_buffer_size = -1;
    timeout = -1.0;
    lookups = NULL;
    c_domains = NULL;
    servers = domains = sock_state_cb = NULL;

    if (self->channel) {
        PyErr_SetString(PyExc_AresError, "Object already initialized");
        return -1;
    }

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|idiiiiOOsOii:__init__", kwlist, &flags, &timeout, &tries, &ndots, &tcp_port, &udp_port, &servers,
                                                                                     &domains, &lookups, &sock_state_cb, &socket_send_buffer_size, &socket_receive_buffer_size)) {
        return -1;
    }

    if (sock_state_cb && !PyCallable_Check(sock_state_cb)) {
        PyErr_SetString(PyExc_TypeError, "sock_state_cb is not callable");
        return -1;
    }

    r = ares_library_init(ARES_LIB_INIT_ALL);
    if (r != ARES_SUCCESS) {
        RAISE_ARES_EXCEPTION(r);
        return -1;
    }
    self->lib_initialized = True;

    memset(&options, 0, sizeof(struct ares_options));

    if (flags != -1) {
        options.flags = flags;
        optmask |= ARES_OPT_FLAGS;
    }
    if (timeout != -1) {
        options.timeout = (int)timeout * 1000;
        optmask |= ARES_OPT_TIMEOUTMS;
    }
    if (tries != -1) {
        options.tries = tries;
        optmask |= ARES_OPT_TRIES;
    }
    if (ndots != -1) {
        options.ndots = ndots;
        optmask |= ARES_OPT_NDOTS;
    }
    if (tcp_port != -1) {
        options.tcp_port = tcp_port;
        optmask |= ARES_OPT_TCP_PORT;
    }
    if (udp_port != -1) {
        options.udp_port = udp_port;
        optmask |= ARES_OPT_UDP_PORT;
    }
    if (socket_send_buffer_size != -1) {
        options.socket_send_buffer_size = socket_send_buffer_size;
        optmask |= ARES_OPT_SOCK_SNDBUF;
    }
    if (socket_receive_buffer_size != -1) {
        options.socket_receive_buffer_size = socket_receive_buffer_size;
        optmask |= ARES_OPT_SOCK_RCVBUF;
    }
    if (sock_state_cb) {
        options.sock_state_cb = ares__sock_state_cb;
        options.sock_state_cb_data = (void *)self;
        optmask |= ARES_OPT_SOCK_STATE_CB;
        Py_INCREF(sock_state_cb);
        self->sock_state_cb = sock_state_cb;
    }
    if (lookups) {
        options.lookups = lookups;
        optmask |= ARES_OPT_LOOKUPS;
    }
    if (domains) {
        process_domains(domains, &c_domains, &ndomains);
        if (ndomains == -1) {
            goto error;
        }
        options.domains = c_domains;
        options.ndomains = ndomains;
        optmask |= ARES_OPT_DOMAINS;
    }

    r = ares_init_options(&self->channel, &options, optmask);
    if (r != ARES_SUCCESS) {
        RAISE_ARES_EXCEPTION(r);
        goto error;
    }

    free_domains(c_domains);

    if (servers) {
        return set_nameservers(self, servers);
    }

    return 0;

error:
    free_domains(c_domains);
    Py_XDECREF(sock_state_cb);
    return -1;
}
Example #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;
}
Example #14
0
int main(int argc, char **argv)
{
  struct ares_options options;
  int optmask = 0;
  ares_channel channel;
  int status, nfds, c, addr_family = AF_INET;
  fd_set read_fds, write_fds;
  struct timeval *tvp, tv;
  struct in_addr addr4;
  struct ares_in6_addr addr6;

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

  memset(&options, 0, sizeof(options));

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

  while ((c = ares_getopt(argc,argv,"dt:hs:")) != -1)
    {
      switch (c)
        {
        case 'd':
#ifdef WATT32
          dbug_init();
#endif
          break;
        case 's':
          optmask |= ARES_OPT_DOMAINS;
          options.ndomains++;
          options.domains = realloc(options.domains,
                                    options.ndomains * sizeof(char *));
          options.domains[options.ndomains - 1] = strdup(optarg);
          break;
        case 't':
          if (!strcasecmp(optarg,"a"))
            addr_family = AF_INET;
          else if (!strcasecmp(optarg,"aaaa"))
            addr_family = AF_INET6;
          else if (!strcasecmp(optarg,"u"))
            addr_family = AF_UNSPEC;
          else
            usage();
          break;
        case 'h':
        default:
          usage();
          break;
        }
    }

  argc -= optind;
  argv += optind;
  if (argc < 1)
    usage();

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

  /* Initiate the queries, one per command-line argument. */
  for ( ; *argv; argv++)
    {
      if (ares_inet_pton(AF_INET, *argv, &addr4) == 1)
        {
          ares_gethostbyaddr(channel, &addr4, sizeof(addr4), AF_INET, callback,
                             *argv);
        }
      else if (ares_inet_pton(AF_INET6, *argv, &addr6) == 1)
        {
          ares_gethostbyaddr(channel, &addr6, sizeof(addr6), AF_INET6, callback,
                             *argv);
        }
      else
        {
          ares_gethostbyname(channel, *argv, addr_family, callback, *argv);
        }
    }

  /* Wait for all queries to complete. */
  for (;;)
    {
      int res;
      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);
      res = select(nfds, &read_fds, &write_fds, NULL, tvp);
      if (-1 == res)
        break;
      ares_process(channel, &read_fds, &write_fds);
    }

  ares_destroy(channel);

  ares_library_cleanup();

#ifdef USE_WINSOCK
  WSACleanup();
#endif

  return 0;
}
Example #15
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;
}
/*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;
}
void *auth_mgr_adns_handler_epoll(void *arg)
{
    //struct timeval *tvp, tv, tv_copy;
    ares_socket_t dns_client_fds[16] = {0};
    struct epoll_event ev, events[DNS_MAX_EVENTS];
    int i,bitmask,nfds, epollfd, timeout, fd_count, ret;

    UNUSED_ARGUMENT(arg);
    memset(dns_client_fds, 0, sizeof(dns_client_fds));

    memset((char *)&ev, 0, sizeof(struct epoll_event));
    memset((char *)&events[0], 0, sizeof(events));

    epollfd = epoll_create(DNS_MAX_SERVERS);
    if (epollfd < 0) {
        DBG_LOG(SEVERE, MOD_AUTHMGR, "epoll_create() error");
        assert(0);
    }

    prctl(PR_SET_NAME, "nvsd-adns", 0, 0, 0);

    /*Infinite loop, to process all the dns responses. Each channel can handle
     16 name servers in RR fashion. Inside each channel there is one socket
    dedicated for one nameserver. So if there are 2 nameservers in /etc/resol.conf
    , then c-ares will assign 2 fds to the channel*/
    while(1)
    {
        nfds=0;
        bitmask=0;
        for (i =0; i < DNS_MAX_SERVERS ; i++) {
            if (dns_client_fds[i] > 0) {
                if (epoll_ctl(epollfd, EPOLL_CTL_DEL, dns_client_fds[i], NULL) < 0) {
                    //not a serious problem, strange that we should hit this case
                    continue;
                }
            }
        }
        memset(dns_client_fds, 0, sizeof(dns_client_fds));
        pthread_mutex_lock(&cares_mutex);
        bitmask = ares_getsock(channel, dns_client_fds, DNS_MAX_SERVERS);
        for (i =0; i < DNS_MAX_SERVERS ; i++) {
            if (dns_client_fds[i] > 0) {
                ev.events = 0;
                if (ARES_GETSOCK_READABLE(bitmask, i)) {
                    ev.events |= EPOLLIN;
                }
                if (ARES_GETSOCK_WRITABLE(bitmask, i)) {
                    ev.events |= EPOLLOUT;
                }
                ev.data.fd = dns_client_fds[i];
                if (epoll_ctl(epollfd, EPOLL_CTL_ADD, dns_client_fds[i], &ev) < 0) {
                    if(errno == EEXIST) {
                        nfds++;
                        continue;
                    }
                    DBG_LOG(SEVERE, MOD_AUTHMGR, "%d fd has trouble when adding to epoll:%s\n",
                            dns_client_fds[i], strerror(errno));
                    continue;
                }
                nfds++;
            }
        }
        if(nfds==0)
        {
            pthread_cond_wait(&cares_cond, &cares_mutex);
            pthread_mutex_unlock(&cares_mutex);
            continue;
        }
        //tvp = ares_timeout(channel, NULL, &tv);
        //memcpy(&tv_copy, tvp, sizeof(struct timeval));
        pthread_mutex_unlock(&cares_mutex);
        //timeout = (tv_copy.tv_sec)*1000;//millisecs
        timeout = 1000;//millisecs
        /*********************************************************
        The default timeout was 5 seconds with default retries
        as 4. The timeout algorith that c-ares adopts, has
        timeout increasing linearly for every retry, and can
        go upto 75secs(~5+~10+~20+~40). To avoid such a big
        block in our select, reduced the timeout to 3secs
        and retries to 2, so max blocking limited to 9 secs
        Changes in ares_init.
        ******************************************************/
        fd_count = epoll_wait(epollfd, events, DNS_MAX_EVENTS, timeout);
        if (fd_count < 0) {
            DBG_LOG(SEVERE, MOD_AUTHMGR, "epoll_wait failed:%s", strerror(errno));
            continue;
        }
        pthread_mutex_lock(&cares_mutex);
        if (fd_count > 0) {
            for (i = 0; i < fd_count; ++i) {
                ares_process_fd(channel,
                                ((events[i].events) & (EPOLLIN) ?
                                 events[i].data.fd:ARES_SOCKET_BAD),
                                ((events[i].events) & (EPOLLOUT)?
                                 events[i].data.fd:ARES_SOCKET_BAD));
            }
        } else {
            ares_process_fd(channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
        }
        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);
    }
}
Example #18
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;
}
/* Init function to start auth worker threads and adns thread.
It also initializes the c-ares library and c-ares channel*/
int auth_mgr_init(uint32_t init_flags)
{
    int ret,flags;
    NKN_MUTEX_INIT(&authreq_mutex, NULL, "authreq_mutex");
    /***********************************************************
     * We do not need this for now, but will eventually need
     * to handle the auth taks, key management etcc..
     ***********************************************************/
    if (init_flags & AUTH_MGR_INIT_START_WORKER_TH) {
        int32_t i;
        for (i=0; i<MAX_AM_THREADS; i++) {
            DBG_LOG(MSG, MOD_AUTHMGR,
                    "Thread %d created for Auth Manager",i);
            if(pthread_create(&auththr[i], NULL,
                              auth_mgr_input_handler_thread, (void *)&i) != 0) {
                DBG_LOG(SEVERE, MOD_AUTHMGR,
                        "Failed to create authmgr threads %d",i);
                DBG_ERR(SEVERE, "Failed to create authmgr threads %d",i);
                return -1;
            }
        }
    }
    auth_htbl_list_init();

    /*All the c-ares relates stuff goes in here*/

    if (adnsd_enabled) {
        return adns_client_init();
    }
    flags = ARES_LIB_INIT_ALL;
    ares_library_cleanup();
    ret = ares_library_init(flags);
    if (ret != ARES_SUCCESS) {
        DBG_LOG(SEVERE, MOD_AUTHMGR,"ares_library_init: %d %s", ret,
                ares_strerror(ret));
        return -1;
    }
    optmask = ARES_OPT_FLAGS|ARES_OPT_TIMEOUT|ARES_OPT_TRIES;

    options.flags = ARES_FLAG_STAYOPEN|ARES_FLAG_IGNTC|ARES_FLAG_NOCHECKRESP;
    options.timeout = DNS_MAX_TIMEOUT;
    options.tries = DNS_MAX_RETRIES;
    ret = ares_init_options(&channel, &options, optmask);
    if (ret != ARES_SUCCESS) {
        DBG_LOG(SEVERE, MOD_AUTHMGR,"ares_init: %d %s", ret,
                ares_strerror(ret) );
        return -1;
    }
    channel_ready = 1;

    /* Additionally one more thread needs to handle all
    the DNS queries, so starting it here*/
    if (pthread_create(&adnsthr, NULL, auth_mgr_adns_handler_epoll, NULL) != 0) {
        DBG_LOG(SEVERE, MOD_AUTHMGR,
                "Failed to create adns thread");
        DBG_ERR(SEVERE,"Failed to create adns thread");
        return -1;
    }


    return 0;

}