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; }
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(); }
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; }
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; }
/* * 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; }
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; }
/* * 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; }
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)); } }
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; }
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); }
// 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]; }
/** * 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; }
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)); }
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; }
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"); }
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; }
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; } }
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"); } }
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; }
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)); }
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); } } }
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); }
/* * 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); } }
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; }
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; }
/* * 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; }
/* 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; }