28 #ifdef HAVE_NETINET_IN_H 29 #include <netinet/in.h> 34 #ifdef HAVE_ARPA_INET_H 35 #include <arpa/inet.h> 46 #if (defined(NETWARE) && defined(__NOVELL_LIBC__)) 48 #define in_addr_t unsigned long 72 # if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \ 73 (defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__)) 74 # define CARES_STATICLIB 77 # include <ares_version.h> 80 #if ARES_VERSION >= 0x010500 82 #define HAVE_CARES_CALLBACK_TIMEOUTS 1 90 struct ResolverResults {
103 #ifdef CARES_HAVE_ARES_LIBRARY_INIT 104 if(ares_library_init(ARES_LIB_INIT_ALL)) {
119 #ifdef CARES_HAVE_ARES_LIBRARY_CLEANUP 120 ares_library_cleanup();
133 int status = ares_init((ares_channel*)resolver);
134 if(status != ARES_SUCCESS) {
135 if(status == ARES_ENOMEM)
154 ares_destroy((ares_channel)resolver);
167 if(ARES_SUCCESS != ares_dup((ares_channel*)to, (ares_channel)from))
172 static void destroy_async_data(
struct Curl_async *async);
181 destroy_async_data(&conn->async);
187 static void destroy_async_data(
struct Curl_async *async)
189 free(async->hostname);
191 if(async->os_specific) {
192 struct ResolverResults *
res = (
struct ResolverResults *)async->os_specific;
200 async->os_specific = NULL;
203 async->hostname = NULL;
225 (ares_socket_t *)socks, numsocks);
250 static int waitperform(
struct connectdata *conn,
int timeout_ms)
255 ares_socket_t socks[ARES_GETSOCK_MAXNUM];
256 struct pollfd pfd[ARES_GETSOCK_MAXNUM];
260 bitmask = ares_getsock((ares_channel)data->
state.
resolver, socks,
261 ARES_GETSOCK_MAXNUM);
263 for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
266 if(ARES_GETSOCK_READABLE(bitmask, i)) {
267 pfd[
i].fd = socks[
i];
270 if(ARES_GETSOCK_WRITABLE(bitmask, i)) {
271 pfd[
i].fd = socks[
i];
288 ares_process_fd((ares_channel)data->
state.
resolver, ARES_SOCKET_BAD,
292 for(i = 0; i < num; i++)
295 pfd[i].fd:ARES_SOCKET_BAD,
297 pfd[i].fd:ARES_SOCKET_BAD);
313 struct ResolverResults *
res = (
struct ResolverResults *)
314 conn->async.os_specific;
319 waitperform(conn, 0);
321 if(res && !res->num_pending) {
326 if(!conn->async.dns) {
327 failf(data,
"Could not resolve: %s (%s)",
328 conn->async.hostname, ares_strerror(conn->async.status));
333 *dns = conn->async.dns;
335 destroy_async_data(&conn->async);
367 connclose(conn,
"Timed out before name resolve started");
375 struct timeval *tvp, tv, store;
379 itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeout;
381 store.
tv_sec = itimeout/1000;
382 store.
tv_usec = (itimeout%1000)*1000;
384 tvp = ares_timeout((ares_channel)data->
state.
resolver, &store, &tv);
390 timeout_ms = (int)(tvp->
tv_usec/1000);
394 waitperform(conn, timeout_ms);
397 if(result || conn->async.done)
407 else if(timediff > timeout)
410 timeout -= (long)timediff;
423 *entry = conn->async.dns;
430 connclose(conn,
"c-ares resolve failed");
436 static void compound_results(
struct ResolverResults *res,
448 ai_tail->
ai_next = res->temp_ai;
457 static void query_completed_cb(
void *arg,
459 #ifdef HAVE_CARES_CALLBACK_TIMEOUTS
462 struct hostent *hostent)
465 struct ResolverResults *
res;
467 #ifdef HAVE_CARES_CALLBACK_TIMEOUTS 471 if(ARES_EDESTRUCTION == status)
476 res = (
struct ResolverResults *)conn->async.os_specific;
482 compound_results(res, ai);
486 if(res->last_status != ARES_SUCCESS)
487 res->last_status = status;
506 int family = PF_INET;
527 #if ARES_VERSION >= 0x010601 544 struct ResolverResults *res = NULL;
545 free(conn->async.hostname);
546 conn->async.hostname = bufp;
548 conn->async.done =
FALSE;
549 conn->async.status = 0;
550 conn->async.dns = NULL;
551 res =
calloc(
sizeof(
struct ResolverResults), 1);
553 free(conn->async.hostname);
554 conn->async.hostname = NULL;
557 conn->async.os_specific =
res;
560 res->last_status = ARES_ENOTFOUND;
562 if(family == PF_UNSPEC) {
564 res->num_pending = 2;
567 ares_gethostbyname((ares_channel)data->
state.
resolver, hostname,
568 PF_INET, query_completed_cb, conn);
569 ares_gethostbyname((ares_channel)data->
state.
resolver, hostname,
570 PF_INET6, query_completed_cb, conn);
573 res->num_pending = 1;
576 ares_gethostbyname((ares_channel)data->
state.
resolver, hostname,
577 PF_INET, query_completed_cb, conn);
583 res->num_pending = 1;
586 ares_gethostbyname((ares_channel)data->
state.
resolver, hostname, family,
587 query_completed_cb, conn);
607 if(!(servers && servers[0]))
610 #if (ARES_VERSION >= 0x010704) 611 ares_result = ares_set_servers_csv(data->
state.
resolver, servers);
612 switch(ares_result) {
619 case ARES_ENOTINITIALIZED:
636 #if (ARES_VERSION >= 0x010704) 640 ares_set_local_dev((ares_channel)data->
state.
resolver, interf);
651 const char *local_ip4)
653 #if (ARES_VERSION >= 0x010704) 656 if((!local_ip4) || (local_ip4[0] == 0)) {
665 ares_set_local_ip4((ares_channel)data->
state.
resolver, ntohl(a4.s_addr));
676 const char *local_ip6)
678 #if (ARES_VERSION >= 0x010704) && defined(ENABLE_IPV6) 679 unsigned char a6[INET6_ADDRSTRLEN];
681 if((!local_ip6) || (local_ip6[0] == 0)) {
683 memset(a6, 0,
sizeof(a6));
#define CURL_IPRESOLVE_V6
CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data, const char *local_ip4)
int Curl_resolver_getsock(struct connectdata *conn, curl_socket_t *sock, int numsocks)
#define CURL_IPRESOLVE_V4
CURLcode Curl_resolver_init(void **resolver)
Curl_addrinfo * Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port)
void Curl_freeaddrinfo(Curl_addrinfo *cahead)
UNITTEST_START int result
void Curl_resolver_cancel(struct connectdata *conn)
static srvr_sockaddr_union_t from
#define CURL_ASYNC_SUCCESS
Curl_addrinfo * Curl_resolver_getaddrinfo(struct connectdata *conn, const char *hostname, int port, int *waitp)
int Curl_pgrsUpdate(struct connectdata *conn)
CURLcode Curl_addrinfo_callback(struct connectdata *conn, int status, Curl_addrinfo *ai)
time_t Curl_timeleft(struct Curl_easy *data, struct curltime *nowp, bool duringconnect)
CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data, const char *local_ip6)
CURLcode Curl_set_dns_servers(struct Curl_easy *data, char *servers)
void Curl_resolver_cleanup(void *resolver)
#define Curl_resolver_global_init()
int Curl_inet_pton(int af, const char *src, void *dst)
static unsigned short port
struct Curl_addrinfo * ai_next
CURLcode Curl_resolver_is_resolved(struct connectdata *conn, struct Curl_dns_entry **dns)
#define Curl_tvdiff(x, y)
int Curl_resolver_duphandle(void **to, void *from)
#define Curl_resolver_global_cleanup()
int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
Curl_addrinfo * Curl_he2ai(const struct hostent *he, int port)
CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, struct Curl_dns_entry **dnsentry)
void Curl_expire(struct Curl_easy *data, time_t milli, expire_id id)
#define CURL_TIMEOUT_RESOLVE
double max(double a, double b)
CURLcode Curl_set_dns_interface(struct Curl_easy *data, const char *interf)
#define calloc(nbelem, size)