Beispiel #1
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;
 }
Beispiel #2
0
int main (int argc, char *argv[]) {
	struct ev_loop *loop = EV_DEFAULT;
	
	if (argc < 2) { fprintf(stderr, "Usage:\n\t%s domain\n",argv[0]); return 1; }
	char *hostname = argv[1];
	char *jabber = calloc(1,strlen(argv[1]) + strlen(JSRV) + 1); // will be freed on exit ;)
	strcat(jabber,JSRV);
	strcat(jabber,argv[1]);
	
	// Declare resolver struct;
	ev_ares resolver;
	
	printf("Resolving '%s'\n",hostname);
	
	// Initialize ares library.
	int status;
	if ((status = ares_library_init(ARES_LIB_INIT_ALL) )!= ARES_SUCCESS) {
		fprintf(stderr,"Ares error: %s\n",ares_strerror(status));
		return 1;
	}
	
	//Initialize resolver with timeout 1.3
	if (( status = ev_ares_init(&resolver, 1.3) ) != ARES_SUCCESS) {
		fprintf(stderr,"Ares error: %s\n",ares_strerror(status));
		return 1;
	}
	
	// hostname variable must not be freed until resolve callback, since it referenced as result->host
	
	ev_ares_soa(loop,&resolver,hostname,0,callback_soa);
	
	ev_ares_ns(loop,&resolver,hostname,0,callback_ns);
	
	ev_ares_a(loop,&resolver,hostname,0,callback_a);
	ev_ares_aaaa(loop,&resolver,hostname,0,callback_aaaa);
	
	ev_ares_mx(loop,&resolver,hostname,0,callback_mx);
	
	ev_ares_srv(loop,&resolver,jabber,0,callback_srv);
	ev_ares_txt(loop,&resolver,hostname,0,callback_txt);
	
	ev_ares_gethostbyaddr(loop,&resolver,"8.8.8.8", 0, callback_hba);
	ev_ares_gethostbyaddr(loop,&resolver,"2a00:1450:4010:c04::66", 0,callback_hba);
	
	// Raw PTR queries
	ev_ares_ptr(loop,&resolver,"8.8.8.8.in-addr.arpa", 0,callback_ptr);
	ev_ares_ptr(loop,&resolver,"a.8.0.0.0.0.0.0.0.0.0.0.0.0.0.0.4.0.c.0.0.1.0.4.0.5.4.1.0.0.a.2.ip6.arpa", 0,callback_ptr);
	
	//This is the only NAPTR example i found ;)
	ev_ares_naptr(loop,&resolver,"0.2.0.1.1.6.5.1.0.3.1.loligo.com.",0,callback_naptr);
	
	// Run loop
	ev_run (loop, 0);
	
	free(jabber);
	ev_ares_clean(&resolver);
	ares_library_cleanup();
}
Beispiel #3
0
 void init_lib()
 {
     if(init_)
     {
         return;
     }
     int result = ares_library_init(ARES_LIB_INIT_ALL);
     if (result != ARES_SUCCESS)
     {
         TORNADO_LOG_ERROR("ares_library_init: %s", ares_strerror(result));
         throw std::runtime_error( std::string("ares_library_init fail :") + ares_strerror(result) );
     }
     init_ = true;
 }
Beispiel #4
0
static void callback(void *arg, int status, int timeouts, struct hostent *host)
{
  char **p;

  (void)timeouts;

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

  for (p = host->h_addr_list; *p; p++)
    {
      char addr_buf[46] = "??";

      ares_inet_ntop(host->h_addrtype, *p, addr_buf, sizeof(addr_buf));
      printf("%-32s\t%s", host->h_name, addr_buf);
#if 0
      if (host->h_aliases[0])
        {
           int i;

           printf (", Aliases: ");
           for (i = 0; host->h_aliases[i]; i++)
               printf("%s ", host->h_aliases[i]);
        }
#endif
      puts("");
    }
}
/*
 * Curl_resolver_is_resolved() is called repeatedly to check if a previous
 * name resolve request has completed. It should also make sure to time-out if
 * the operation seems to take too long.
 *
 * Returns normal CURLcode errors.
 */
CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
                                   struct Curl_dns_entry **dns)
{
  struct SessionHandle *data = conn->data;
  struct ResolverResults *res = (struct ResolverResults *)
    conn->async.os_specific;

  *dns = NULL;

  waitperform(conn, 0);

  if(res && !res->num_pending) {
    (void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai);
    /* temp_ai ownership is moved to the connection, so we need not free-up
       them */
    res->temp_ai = NULL;
    destroy_async_data(&conn->async);
    if(!conn->async.dns) {
      failf(data, "Could not resolve %s: %s (%s)",
            conn->bits.proxy?"proxy":"host",
            conn->host.dispname,
            ares_strerror(conn->async.status));
      return conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
        CURLE_COULDNT_RESOLVE_HOST;
    }
    *dns = conn->async.dns;
  }

  return CURLE_OK;
}
Beispiel #6
0
/*
 * Curl_is_resolved() is called repeatedly to check if a previous name resolve
 * request has completed. It should also make sure to time-out if the
 * operation seems to take too long.
 *
 * Returns normal CURLcode errors.
 */
CURLcode Curl_is_resolved(struct connectdata *conn,
                          struct Curl_dns_entry **dns)
{
  fd_set read_fds, write_fds;
  struct timeval tv={0,0};
  struct SessionHandle *data = conn->data;
  int nfds;

  FD_ZERO(&read_fds);
  FD_ZERO(&write_fds);

  nfds = ares_fds(data->state.areschannel, &read_fds, &write_fds);

  (void)select(nfds, &read_fds, &write_fds, NULL,
               (struct timeval *)&tv);

  /* Call ares_process() unconditonally here, even if we simply timed out
     above, as otherwise the ares name resolve won't timeout! */
  ares_process(data->state.areschannel, &read_fds, &write_fds);

  *dns = NULL;

  if(conn->async.done) {
    /* we're done, kill the ares handle */
    if(!conn->async.dns) {
      failf(data, "Could not resolve host: %s (%s)", conn->host.dispname,
            ares_strerror(conn->async.status));
      return CURLE_COULDNT_RESOLVE_HOST;
    }
    *dns = conn->async.dns;
  }

  return CURLE_OK;
}
Beispiel #7
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;
}
Beispiel #8
0
/*
 * Curl_resolver_is_resolved() is called repeatedly to check if a previous
 * name resolve request has completed. It should also make sure to time-out if
 * the operation seems to take too long.
 *
 * Returns normal CURLcode errors.
 */
CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
                                   struct Curl_dns_entry **dns)
{
  struct Curl_easy *data = conn->data;
  struct ResolverResults *res = (struct ResolverResults *)
    conn->async.os_specific;
  CURLcode result = CURLE_OK;

  if(dns)
    *dns = NULL;

  waitperform(conn, 0);

  /* Now that we've checked for any last minute results above, see if there are
     any responses still pending when the EXPIRE_HAPPY_EYEBALLS_DNS timer
     expires. */
  if(res
     && res->num_pending
     /* This is only set to non-zero if the timer was started. */
     && (res->happy_eyeballs_dns_time.tv_sec
         || res->happy_eyeballs_dns_time.tv_usec)
     && (Curl_timediff(Curl_now(), res->happy_eyeballs_dns_time)
         >= HAPPY_EYEBALLS_DNS_TIMEOUT)) {
    /* Remember that the EXPIRE_HAPPY_EYEBALLS_DNS timer is no longer
       running. */
    memset(
      &res->happy_eyeballs_dns_time, 0, sizeof(res->happy_eyeballs_dns_time));

    /* Cancel the raw c-ares request, which will fire query_completed_cb() with
       ARES_ECANCELLED synchronously for all pending responses.  This will
       leave us with res->num_pending == 0, which is perfect for the next
       block. */
    ares_cancel((ares_channel)data->state.resolver);
    DEBUGASSERT(res->num_pending == 0);
  }

  if(res && !res->num_pending) {
    if(dns) {
      (void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai);
      /* temp_ai ownership is moved to the connection, so we need not free-up
         them */
      res->temp_ai = NULL;
    }
    if(!conn->async.dns) {
      failf(data, "Could not resolve: %s (%s)",
            conn->async.hostname, ares_strerror(conn->async.status));
      result = conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
        CURLE_COULDNT_RESOLVE_HOST;
    }
    else if(dns)
      *dns = conn->async.dns;

    destroy_async_data(&conn->async);
  }

  return result;
}
Beispiel #9
0
 TAres() {
 #if defined (_WIN32) && ! defined (__CYGWIN__)
   WSADATA p;
   WSAStartup ((2<<8) | 2, &p);
 #endif
     int status = ares_library_init(ARES_LIB_INIT_ALL);
     if (status != ARES_SUCCESS) {
         throw UException(std::string("Failed to init ares: ") + ares_strerror(status));
     }
 }
Beispiel #10
0
int main(int argc, char *argv[]) {

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

  int sock;
  int n;
  struct sockaddr_in serv_addr;

  if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
    perror("socket");
  }

  n = 1;
  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&n, sizeof(n)) < 0) {
    perror("setsockopt SO_REUSEADDR");
  }

  memset(&serv_addr, 0, sizeof(serv_addr));
  serv_addr.sin_family = AF_INET;
  serv_addr.sin_port = htons(8080);
  serv_addr.sin_addr.s_addr = inet_addr("0.0.0.0");

  if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
    perror("bind");
  }

  if (listen(sock, 10) < 0) {
    perror("listen");
  }

  st_netfd_t server_nfd = st_netfd_open_socket(sock);
  st_netfd_t client_nfd;
  struct sockaddr_in from;
  int fromlen = sizeof(from);

  for (;;) {
    client_nfd = st_accept(server_nfd,
      (struct sockaddr *)&from, &fromlen, ST_UTIME_NO_TIMEOUT);
    printf("accepted\n");
    if (st_thread_create(handle_connection,
      (void *)client_nfd, 0, 1024 * 1024) == NULL)
    {
      fprintf(stderr, "st_thread_create error\n");
    }
  }
  ares_library_cleanup();
  return EXIT_SUCCESS;
}
Beispiel #11
0
static void callback(void *arg, int status, int timeouts, struct hostent *from) {
    struct hostent *to = (struct hostent *)arg;

    if(!from || status != ARES_SUCCESS){
        debug("Failed to lookup: %s\n", ares_strerror(status));
        return;
    }

    // Save return
    nssrs_copy_hostent(from, to);
}
Beispiel #12
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];
}
Beispiel #13
0
/**
 * Initialize the DNS resolver for use. If this function fails the BNC will not be able to function
 * properly.
 */
int p_dns_init()
{
    int ret;

    if ((ret = ares_init(&resolver)) != ARES_SUCCESS)
    {
        p_log(LOG_ERROR, -1, "Failed to initialize ares resolver: %s", ares_strerror(ret));
        return 0;
    }

    p_log(LOG_INFO, -1, "Asynchronous resolver initialized: c-ares %s", ares_version(NULL));
    return 1;
}
Beispiel #14
0
static PyObject *
Errno_func_strerror(PyObject *obj, PyObject *args)
{
    int errorno;

    UNUSED_ARG(obj);

    if (!PyArg_ParseTuple(args, "i:strerror", &errorno)) {
        return NULL;
    }

    return Py_BuildValue("s", ares_strerror(errorno));
}
Beispiel #15
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;
}
Beispiel #16
0
void dns_library_init(void)
{
	int status;

	status = ares_library_init(ARES_LIB_INIT_ALL);
	if (status != ARES_SUCCESS) {
		errprintf("Cannot initialize ARES library: %s\n", ares_strerror(status));
		return;
	}
	
	dns_atype= dns_name_type("A");
	dns_aaaatype= dns_name_type("AAAA");
	dns_aclass = dns_name_class("IN");
}
Beispiel #17
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;
}
Beispiel #18
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;
	}
}
Beispiel #19
0
static void do_ares_init(void)
{
  int res = ares_library_init(ARES_LIB_INIT_ALL);

  atexit(do_ares_fini);

  if (res) {
    ph_panic("ares_library_init failed: %s", ares_strerror(res));
  }

  ph_memtype_register_block(sizeof(defs)/sizeof(defs[0]), defs, &mt.chan);

  // This must be the last thing we do in this function
  default_channel = create_chan();
  if (!default_channel) {
    ph_panic("failed to create default DNS channel");
  }
}
Beispiel #20
0
int main(int argc, char *argv[]) {
  int status;
  st_init();
  status = ares_library_init(ARES_LIB_INIT_ALL);
  if (status != ARES_SUCCESS)
  {
    fprintf(stderr, "ares_library_init: %s\n", ares_strerror(status));
    return 1;
  }

  st_thread_t t = st_thread_create(do_lookup, (void *)"A", 1, 1024 * 128);
  st_thread_t t2 = st_thread_create(do_lookup, (void *)"B", 1, 1024 * 128);
  st_thread_join(t, NULL);
  st_thread_join(t2, NULL);

  ares_library_cleanup();
  return 0;
}
Beispiel #21
0
void
_ko_resolve_init(void)
{
    char *errmem;
    int ret;

    IOMGR_Initialize();

    if (LWP_CreateProcess(ares_worker_thread, AFS_LWP_MINSTACKSIZE, 0, 0, 
			  "ares resolver daemon", &ares_pid))
	errx(1, "Couldn't initialize resolver, helper thread didn't start");

    /* XXX use ARES_FLAG_NOSEARCH */
    ret = ares_init(&achannel);
    if (ret != ARES_SUCCESS)
	errx(1, "Couldn't initialize resolver: %s", 
	     ares_strerror(ret, &errmem));
}
Beispiel #22
0
static void cares_callback(void *arg, int status, unsigned char *abuf, int alen) {
	int i;
	unsigned int ancount, nscount, arcount;
	const unsigned char *aptr;

#ifdef DEBUG
	printf("cares_callback: status=%i, alen=%i\n", status, alen);
#endif
	if (status != ARES_SUCCESS) {
		if (verbose > 1)
			printf("ares failed: %s\n", ares_strerror(status));
		return;
	}

	ancount = DNS_HEADER_ANCOUNT(abuf);
	nscount = DNS_HEADER_NSCOUNT(abuf);
	arcount = DNS_HEADER_ARCOUNT(abuf);
	
#ifdef DEBUG
	printf("ancount: %i, nscount: %i, arcount: %i\n", ancount, nscount, arcount);
#endif

	/* safety check */
	if (alen < NS_HFIXEDSZ)
		return;
	aptr = abuf + NS_HFIXEDSZ;

	aptr = skip_query(aptr, abuf, alen);

	for (i = 0; i < ancount && caadr == 0; i++) {
		if (ca_tmpname == NULL)
			aptr = parse_rr(aptr, abuf, alen);
		else
			aptr = skip_rr(aptr, abuf, alen);
	}
	if (caadr == 0) {
		for (i = 0; i < nscount; i++) {
			aptr = skip_rr(aptr, abuf, alen);
		}
		for (i = 0; i < arcount && caadr == 0; i++) {
			aptr = parse_rr(aptr, abuf, alen);
		}
	}
}
Beispiel #23
0
void Resolver::ares_host_callback(void *arg, int status, int timeouts, struct hostent* host)
{
    Resolver* ch = reinterpret_cast<Resolver*>(arg);
    if(!host || status != ARES_SUCCESS)
    {
        TORNADO_LOG_WARN("Failed to lookup %s\n", ares_strerror(status));
        ch->run_callback(-1, NULL);
        return;
    }
    TORNADO_LOG_DEBUG("Found address name %s", host->h_name);
    Hosts hosts;
    char ip[INET6_ADDRSTRLEN];
    for (int i = 0; host->h_addr_list[i]; ++i) 
    {
        inet_ntop(host->h_addrtype, host->h_addr_list[i], ip, sizeof(ip));
        std::string strIP(ip);
        hosts.push_back( std::move(strIP) );
    }
    ch->run_callback(0, &hosts);
}
Beispiel #24
0
/*
 * Curl_is_resolved() is called repeatedly to check if a previous name resolve
 * request has completed. It should also make sure to time-out if the
 * operation seems to take too long.
 *
 * Returns normal CURLcode errors.
 */
CURLcode Curl_is_resolved(struct connectdata *conn,
                          struct Curl_dns_entry **dns)
{
  struct SessionHandle *data = conn->data;

  *dns = NULL;

  ares_waitperform(conn, 0);

  if(conn->async.done) {
    /* we're done, kill the ares handle */
    if(!conn->async.dns) {
      failf(data, "Could not resolve host: %s (%s)", conn->host.dispname,
            ares_strerror(conn->async.status));
      return CURLE_COULDNT_RESOLVE_HOST;
    }
    *dns = conn->async.dns;
  }

  return CURLE_OK;
}
void cares_callback(void *argdata, int status, int timeouts, struct hostent *hostptr)
{
    UNUSED_ARGUMENT(timeouts);
    auth_dns_t* pdns=(auth_dns_t*)(((auth_msg_t*)(argdata))->authdata);
    int32_t ttl = DEFAULT_DNS_TTL;

    AO_fetch_and_add1(&glob_dns_task_completed);

    if(status!=ARES_SUCCESS)
    {
        pdns->ip[0]=INADDR_NONE;
        DBG_LOG(ERROR, MOD_AUTHMGR,
                "Dnslookup for domain:%s failed:%s",pdns->domain,ares_strerror(status));
        AO_fetch_and_add1(&glob_dns_task_failed);
    }
    else
    {
        memcpy((struct in_addr *)&pdns->ip, hostptr->h_addr, sizeof(struct in_addr));
        if(0x0100007F == pdns->ip[0]) {
            // change 0x0100007F to INADDR_NONE
            pdns->ip[0]=INADDR_NONE;
        }
    }
    pdns->num_ips=1;
    pdns->ttl[0] = ttl;
    //Negative hashing, forcing a failure in find_origin_server
    dns_hash_and_insert((char*)pdns->domain,&pdns->ip[0], &pdns->ttl[0], 0, pdns->num_ips);
    nkn_task_set_action_and_state((nkn_task_id_t)(pdns->auth_task_id),
                                  TASK_ACTION_OUTPUT, TASK_STATE_RUNNABLE);

    if (enable_reinit && (status == ARES_ESERVFAIL)) {
        /*
         * something is wrong here. BIND9 servers do not respond to this
         * channel after encountering this error, so reset everything
         */
        channel_ready = 0;
        AO_fetch_and_add1(&glob_dns_servfail);
    }
}
Beispiel #26
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;
}
Beispiel #27
0
static void
callback(void *arg, int status, int timeouts, struct hostent *host)
{
    (void) arg;
    (void) timeouts;

    if(!host || status != ARES_SUCCESS){
        printf("Failed to lookup %s\n", ares_strerror(status));
        return;
    }
 
    // printf("Found address name %s\n", host->h_name);
    int i = 0;
 
    for (i = 0; host->h_addr_list[i]; ++i) {
        const uint8_t *ap = (const uint8_t *)&(*(struct in_addr *) host->h_addr_list[i]).s_addr;
        // printf("%d.%d.%d.%d\n", ap[0], ap[1], ap[2], ap[3]);
        ipaddr[0] = ap[0];
        ipaddr[1] = ap[1];
        ipaddr[2] = ap[2];
        ipaddr[3] = ap[3];
        break;
    }
}
/*
 * Curl_resolver_wait_resolv()
 *
 * waits for a resolve to finish. This function should be avoided since using
 * this risk getting the multi interface to "hang".
 *
 * If 'entry' is non-NULL, make it point to the resolved dns entry
 *
 * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, and
 * CURLE_OPERATION_TIMEDOUT if a time-out occurred.
 */
CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
                                   struct Curl_dns_entry **entry)
{
  CURLcode rc=CURLE_OK;
  struct SessionHandle *data = conn->data;
  long timeout;
  struct timeval now = Curl_tvnow();
  struct Curl_dns_entry *temp_entry;

  timeout = Curl_timeleft(data, &now, TRUE);
  if(!timeout)
    timeout = CURL_TIMEOUT_RESOLVE * 1000; /* default name resolve timeout */

  /* Wait for the name resolve query to complete. */
  for(;;) {
    struct timeval *tvp, tv, store;
    long timediff;
    int itimeout;
    int timeout_ms;

    itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeout;

    store.tv_sec = itimeout/1000;
    store.tv_usec = (itimeout%1000)*1000;

    tvp = ares_timeout((ares_channel)data->state.resolver, &store, &tv);

    /* use the timeout period ares returned to us above if less than one
       second is left, otherwise just use 1000ms to make sure the progress
       callback gets called frequent enough */
    if(!tvp->tv_sec)
      timeout_ms = (int)(tvp->tv_usec/1000);
    else
      timeout_ms = 1000;

    waitperform(conn, timeout_ms);
    Curl_resolver_is_resolved(conn,&temp_entry);

    if(conn->async.done)
      break;

    if(Curl_pgrsUpdate(conn)) {
      rc = CURLE_ABORTED_BY_CALLBACK;
      timeout = -1; /* trigger the cancel below */
    }
    else {
      struct timeval now2 = Curl_tvnow();
      timediff = Curl_tvdiff(now2, now); /* spent time */
      timeout -= timediff?timediff:1; /* always deduct at least 1 */
      now = now2; /* for next loop */
    }
    if(timeout < 0) {
      /* our timeout, so we cancel the ares operation */
      ares_cancel((ares_channel)data->state.resolver);
      break;
    }
  }

  /* Operation complete, if the lookup was successful we now have the entry
     in the cache. */

  if(entry)
    *entry = conn->async.dns;

  if(!conn->async.dns) {
    /* a name was not resolved */
    if((timeout < 0) || (conn->async.status == ARES_ETIMEOUT)) {
      if(conn->bits.proxy) {
        failf(data, "Resolving proxy timed out: %s", conn->proxy.dispname);
        rc = CURLE_COULDNT_RESOLVE_PROXY;
      }
      else {
        failf(data, "Resolving host timed out: %s", conn->host.dispname);
        rc = CURLE_COULDNT_RESOLVE_HOST;
      }
    }
    else if(conn->async.done) {
      if(conn->bits.proxy) {
        failf(data, "Could not resolve proxy: %s (%s)", conn->proxy.dispname,
              ares_strerror(conn->async.status));
        rc = CURLE_COULDNT_RESOLVE_PROXY;
      }
      else {
        failf(data, "Could not resolve host: %s (%s)", conn->host.dispname,
              ares_strerror(conn->async.status));
        rc = CURLE_COULDNT_RESOLVE_HOST;
      }
    }
    else
      rc = CURLE_OPERATION_TIMEDOUT;

    /* close the connection, since we can't return failure here without
       cleaning up this connection properly */
    conn->bits.close = TRUE;
  }

  return rc;
}
Beispiel #29
0
/*
 * Curl_wait_for_resolv() waits for a resolve to finish. This function should
 * be avoided since using this risk getting the multi interface to "hang".
 *
 * If 'entry' is non-NULL, make it point to the resolved dns entry
 *
 * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, and
 * CURLE_OPERATION_TIMEDOUT if a time-out occurred.
 */
CURLcode Curl_wait_for_resolv(struct connectdata *conn,
                              struct Curl_dns_entry **entry)
{
  CURLcode rc=CURLE_OK;
  struct SessionHandle *data = conn->data;
  long timeout;
  struct timeval now = Curl_tvnow();

  /* now, see if there's a connect timeout or a regular timeout to
     use instead of the default one */
  if(conn->data->set.connecttimeout)
    timeout = conn->data->set.connecttimeout;
  else if(conn->data->set.timeout)
    timeout = conn->data->set.timeout;
  else
    timeout = CURL_TIMEOUT_RESOLVE * 1000; /* default name resolve timeout */

  /* Wait for the name resolve query to complete. */
  while(1) {
    struct timeval *tvp, tv, store;
    long timediff;
    int itimeout;

    itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeout;

    store.tv_sec = itimeout/1000;
    store.tv_usec = (itimeout%1000)*1000;

    tvp = ares_timeout(data->state.areschannel, &store, &tv);

    /* use the timeout period ares returned to us above */
    ares_waitperform(conn, (int)(tvp->tv_sec * 1000 + tvp->tv_usec/1000));

    if(conn->async.done)
      break;

    timediff = Curl_tvdiff(Curl_tvnow(), now); /* spent time */
    timeout -= timediff?timediff:1; /* always deduct at least 1 */
    if(timeout < 0) {
      /* our timeout, so we cancel the ares operation */
      ares_cancel(data->state.areschannel);
      break;
    }
  }

  /* Operation complete, if the lookup was successful we now have the entry
     in the cache. */

  if(entry)
    *entry = conn->async.dns;

  if(!conn->async.dns) {
    /* a name was not resolved */
    if((timeout < 0) || (conn->async.status == ARES_ETIMEOUT)) {
      failf(data, "Resolving host timed out: %s", conn->host.dispname);
      rc = CURLE_COULDNT_RESOLVE_HOST;
    }
    else if(conn->async.done) {
      failf(data, "Could not resolve host: %s (%s)", conn->host.dispname,
            ares_strerror(conn->async.status));
      rc = CURLE_COULDNT_RESOLVE_HOST;
    }
    else
      rc = CURLE_OPERATION_TIMEDOUT;

    /* close the connection, since we can't return failure here without
       cleaning up this connection properly */
    conn->bits.close = TRUE;
  }

  return rc;
}
Beispiel #30
0
/* This is a function that locks and waits until the name resolve operation
   has completed.

   If 'entry' is non-NULL, make it point to the resolved dns entry

   Return CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, and
   CURLE_OPERATION_TIMEDOUT if a time-out occurred.
*/
CURLcode Curl_wait_for_resolv(struct connectdata *conn,
                              struct Curl_dns_entry **entry)
{
  CURLcode rc=CURLE_OK;
  struct SessionHandle *data = conn->data;
  struct timeval now = Curl_tvnow();
  bool timedout = FALSE;
  long timeout = 300; /* default name resolve timeout in seconds */
  long elapsed = 0; /* time taken so far */

  /* now, see if there's a connect timeout or a regular timeout to
     use instead of the default one */
  if(conn->data->set.connecttimeout)
    timeout = conn->data->set.connecttimeout;
  else if(conn->data->set.timeout)
    timeout = conn->data->set.timeout;

  /* Wait for the name resolve query to complete. */
  while (1) {
    int nfds=0;
    fd_set read_fds, write_fds;
    struct timeval *tvp, tv, store;
    int count;

    store.tv_sec = (int)(timeout - elapsed);
    store.tv_usec = 0;
    
    FD_ZERO(&read_fds);
    FD_ZERO(&write_fds);
    nfds = ares_fds(data->state.areschannel, &read_fds, &write_fds);
    if (nfds == 0)
      break;
    tvp = ares_timeout(data->state.areschannel,
                       &store, &tv);
    count = select(nfds, &read_fds, &write_fds, NULL, tvp);
    if (count < 0 && errno != EINVAL)
      break;
    else if(!count) {
      /* timeout */
      timedout = TRUE;
      break;
    }
    ares_process(data->state.areschannel, &read_fds, &write_fds);

    elapsed = Curl_tvdiff(Curl_tvnow(), now)/1000; /* spent time */
  }

  /* Operation complete, if the lookup was successful we now have the entry
     in the cache. */
    
  if(entry)
    *entry = conn->async.dns;

  if(!conn->async.dns) {
    /* a name was not resolved */
    if(timedout || (conn->async.status == ARES_ETIMEOUT)) {
      failf(data, "Resolving host timed out: %s", conn->name);
      rc = CURLE_OPERATION_TIMEDOUT;
    }
    else if(conn->async.done) {
      failf(data, "Could not resolve host: %s (%s)", conn->name,
            ares_strerror(conn->async.status));
      rc = CURLE_COULDNT_RESOLVE_HOST;
    }
    else
      rc = CURLE_OPERATION_TIMEDOUT;

    /* close the connection, since we can't return failure here without
       cleaning up this connection properly */
    Curl_disconnect(conn);
  }
  
  return rc;
}