From 73a05428d4c659d950bcf26aad9d7bd3164b8f7e Mon Sep 17 00:00:00 2001 From: Stefan Eissing Date: Thu, 30 Jul 2026 13:49:58 +0200 Subject: [PATCH] dnscache: use Curl_peer in resolve and dnscache operations Removes unused/duplicate members in async/ares/doh structs. Closes #22446 --- lib/asyn-ares.c | 114 ++++-------------- lib/asyn-base.c | 12 +- lib/asyn-thrdd.c | 167 ++++++++------------------ lib/asyn.h | 32 ++--- lib/cf-dns.c | 37 ++---- lib/curl_addrinfo.c | 15 +++ lib/curl_addrinfo.h | 5 + lib/dnscache.c | 284 +++++++++++++++++++++++++------------------- lib/dnscache.h | 17 ++- lib/doh.c | 29 ++--- lib/doh.h | 2 - lib/hostip.c | 182 ++++++++++++++-------------- 12 files changed, 395 insertions(+), 501 deletions(-) diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c index 72bfda510a..a3dcd7071d 100644 --- a/lib/asyn-ares.c +++ b/lib/asyn-ares.c @@ -208,19 +208,6 @@ void Curl_async_ares_destroy(struct Curl_easy *data, ares_destroy(ares->channel); ares->channel = NULL; } - if(ares->res_A) { - Curl_freeaddrinfo(ares->res_A); - ares->res_A = NULL; - } - if(ares->res_AAAA) { - Curl_freeaddrinfo(ares->res_AAAA); - ares->res_AAAA = NULL; - } -#ifdef USE_HTTPSRR - curlx_safefree(ares->https_name); - Curl_httpsrr_destroy(ares->hinfo); - ares->hinfo = NULL; -#endif } CURLcode Curl_async_pollset(struct Curl_easy *data, @@ -276,8 +263,8 @@ CURLcode Curl_async_take_result(struct Curl_easy *data, if(CURL_DNSQ_IS_ADDR(async->dns_queries)) { dns = Curl_dnsc_mk_addr2(data, async->dns_queries, - &ares->res_AAAA, &ares->res_A, - async->hostname, async->port); + &async->ai_AAAA, &async->ai_A, + async->peer); if(!dns) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -286,8 +273,7 @@ CURLcode Curl_async_take_result(struct Curl_easy *data, #ifdef HTTPSRR_WORKS if(!dns && (async->dns_queries & CURL_DNSQ_HTTPS)) { - dns = Curl_dnsc_mk_https(data, &ares->hinfo, - async->hostname, async->port); + dns = Curl_dnsc_mk_https(data, &async->httpsrr, async->peer); if(!dns) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -349,67 +335,6 @@ static timediff_t async_ares_poll_timeout(struct async_ares_ctx *ares, return 1000; } -static const struct Curl_addrinfo *async_ares_get_ai( - const struct Curl_addrinfo *ai, - int ai_family, - unsigned int index) -{ - unsigned int i = 0; - for(i = 0; ai; ai = ai->ai_next) { - if(ai->ai_family == ai_family) { - if(i == index) - return ai; - ++i; - } - } - return NULL; -} - -const struct Curl_addrinfo *Curl_async_get_ai(struct Curl_easy *data, - struct Curl_resolv_async *async, - int ai_family, - unsigned int index) -{ - struct async_ares_ctx *ares = &async->ares; - - (void)data; - switch(ai_family) { - case AF_INET: - if(ares->res_A) - return async_ares_get_ai(ares->res_A, ai_family, index); - break; - case AF_INET6: - if(ares->res_AAAA) - return async_ares_get_ai(ares->res_AAAA, ai_family, index); - break; - default: - break; - } - return NULL; -} - -#ifdef USE_HTTPSRR -const struct Curl_https_rrinfo *Curl_async_get_https( - struct Curl_easy *data, - struct Curl_resolv_async *async) -{ - if(Curl_async_knows_https(data, async)) - return async->ares.hinfo; - return NULL; -} - -bool Curl_async_knows_https(struct Curl_easy *data, - struct Curl_resolv_async *async) -{ - (void)data; - if(async->dns_queries & CURL_DNSQ_HTTPS) - return ((async->dns_responses & CURL_DNSQ_HTTPS) || - !async->queries_ongoing); - return TRUE; /* we know it will never come */ -} - -#endif /* USE_HTTPSRR */ - /* * Curl_async_await() * @@ -566,7 +491,7 @@ static void async_ares_A_cb(void *user_data, int status, int timeouts, async->done = !async->queries_ongoing; if(status == ARES_SUCCESS) { ares->ares_status = ARES_SUCCESS; - ares->res_A = async_ares_node2addr(ares_ai->nodes); + async->ai_A = async_ares_node2addr(ares_ai->nodes); ares_freeaddrinfo(ares_ai); } else { @@ -593,7 +518,7 @@ static void async_ares_AAAA_cb(void *user_data, int status, int timeouts, async->done = !async->queries_ongoing; if(status == ARES_SUCCESS) { ares->ares_status = ARES_SUCCESS; - ares->res_AAAA = async_ares_node2addr(ares_ai->nodes); + async->ai_AAAA = async_ares_node2addr(ares_ai->nodes); ares_freeaddrinfo(ares_ai); } else { @@ -625,7 +550,7 @@ static void async_ares_rr_done(void *user_data, ares_status_t status, ares->transient_err = TRUE; if((ARES_SUCCESS != status) || !dnsrec) return; - ares->result = Curl_httpsrr_from_ares(dnsrec, &ares->hinfo); + ares->result = Curl_httpsrr_from_ares(dnsrec, &async->httpsrr); } #endif /* USE_HTTPSRR */ @@ -664,7 +589,7 @@ CURLcode Curl_async_getaddrinfo(struct Curl_easy *data, } #endif - curl_msnprintf(service, sizeof(service), "%d", async->port); + curl_msnprintf(service, sizeof(service), "%d", async->peer->port); socktype = (Curl_conn_get_transport(data, data->conn) == TRNSPRT_TCP) ? SOCK_STREAM : SOCK_DGRAM; @@ -674,12 +599,13 @@ CURLcode Curl_async_getaddrinfo(struct Curl_easy *data, struct ares_addrinfo_hints hints; memset(&hints, 0, sizeof(hints)); - CURL_TRC_DNS(data, "[AAAA] ares: query records for %s", async->hostname); + CURL_TRC_DNS(data, "[AAAA] ares: query records for %s", + async->peer->hostname); hints.ai_family = PF_INET6; hints.ai_socktype = socktype; hints.ai_flags = ARES_AI_NUMERICSERV; async->queries_ongoing++; - ares_getaddrinfo(ares->channel, async->hostname, + ares_getaddrinfo(ares->channel, async->peer->hostname, service, &hints, async_ares_AAAA_cb, async); } #endif /* CURLRES_IPV6 */ @@ -688,31 +614,33 @@ CURLcode Curl_async_getaddrinfo(struct Curl_easy *data, struct ares_addrinfo_hints hints; memset(&hints, 0, sizeof(hints)); - CURL_TRC_DNS(data, "[A] ares: query records for %s", async->hostname); + CURL_TRC_DNS(data, "[A] ares: query records for %s", + async->peer->hostname); hints.ai_family = PF_INET; hints.ai_socktype = socktype; hints.ai_flags = ARES_AI_NUMERICSERV; async->queries_ongoing++; - ares_getaddrinfo(ares->channel, async->hostname, + ares_getaddrinfo(ares->channel, async->peer->hostname, service, &hints, async_ares_A_cb, async); } #ifdef USE_HTTPSRR if(async->dns_queries & CURL_DNSQ_HTTPS) { - ares->https_name = NULL; - if(async->port != 443) { - ares->https_name = curl_maprintf("_%d._https.%s", - async->port, async->hostname); - if(!ares->https_name) + char *https_name = NULL; + if(async->peer->port != 443) { + https_name = curl_maprintf("_%u._https.%s", + async->peer->port, async->peer->hostname); + if(!https_name) return CURLE_OUT_OF_MEMORY; } CURL_TRC_DNS(data, "[HTTPS] ares: query records for %s", - ares->https_name ? ares->https_name : async->hostname); + https_name ? https_name : async->peer->hostname); async->queries_ongoing++; ares_query_dnsrec(ares->channel, - ares->https_name ? ares->https_name : async->hostname, + https_name ? https_name : async->peer->hostname, ARES_CLASS_IN, ARES_REC_TYPE_HTTPS, async_ares_rr_done, async, NULL); + curlx_free(https_name); } #endif /* USE_HTTPSRR */ diff --git a/lib/asyn-base.c b/lib/asyn-base.c index b140b0f5b9..28e0c671d1 100644 --- a/lib/asyn-base.c +++ b/lib/asyn-base.c @@ -43,8 +43,10 @@ #include "urldata.h" #include "connect.h" +#include "curl_addrinfo.h" #include "curl_trc.h" #include "hostip.h" +#include "httpsrr.h" #include "multiif.h" #include "progress.h" #include "select.h" @@ -238,6 +240,14 @@ void Curl_async_destroy(struct Curl_easy *data, #ifndef CURL_DISABLE_DOH Curl_doh_cleanup(data, async); #endif + if(async->ai_A) + Curl_freeaddrinfo(async->ai_A); + if(async->ai_AAAA) + Curl_freeaddrinfo(async->ai_AAAA); +#ifdef USE_HTTPSRR + Curl_httpsrr_destroy(async->httpsrr); +#endif + Curl_peer_unlink(&async->peer); curlx_safefree(async); } } @@ -258,7 +268,7 @@ CURLcode Curl_async_failed(struct Curl_easy *data, if(async->dns_queries & (CURL_DNSQ_A|CURL_DNSQ_AAAA)) failf(data, "Could not resolve %s: %s%s%s%s", - host_or_proxy, async->hostname, + host_or_proxy, async->peer->hostname, detail ? " (" : "", detail ? detail : "", detail ? ")" : ""); return result; } diff --git a/lib/asyn-thrdd.c b/lib/asyn-thrdd.c index 0941c08f5e..5e7c40eb53 100644 --- a/lib/asyn-thrdd.c +++ b/lib/asyn-thrdd.c @@ -209,48 +209,54 @@ static void async_thrdd_rr_done(void *user_data, ares_status_t status, async->queries_ongoing--; async->done = !async->queries_ongoing; if((ARES_SUCCESS == status) && dnsrec) - async->result = Curl_httpsrr_from_ares(dnsrec, &thrdd->rr.hinfo); + async->result = Curl_httpsrr_from_ares(dnsrec, &async->httpsrr); } static CURLcode async_rr_start(struct Curl_easy *data, struct Curl_resolv_async *async) { struct async_thrdd_ctx *thrdd = &async->thrdd; + char *https_name = NULL; int status; - char *rrname = NULL; + CURLcode result = CURLE_OK; DEBUGASSERT(!thrdd->rr.channel); - if(async->port != 443) { - rrname = curl_maprintf("_%d_.https.%s", async->port, async->hostname); - if(!rrname) - return CURLE_OUT_OF_MEMORY; + if(async->peer->port != 443) { + https_name = curl_maprintf("_%u._https.%s", + async->peer->port, async->peer->hostname); + if(!https_name) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } } status = ares_init_options(&thrdd->rr.channel, NULL, 0); if(status != ARES_SUCCESS) { thrdd->rr.channel = NULL; - curlx_free(rrname); - return CURLE_FAILED_INIT; + result = CURLE_FAILED_INIT; + goto out; } #ifdef DEBUGBUILD if(getenv("CURL_DNS_SERVER")) { const char *servers = getenv("CURL_DNS_SERVER"); status = ares_set_servers_ports_csv(thrdd->rr.channel, servers); if(status) { - curlx_free(rrname); - return CURLE_FAILED_INIT; + result = CURLE_FAILED_INIT; + goto out; } } #endif - thrdd->rr.https_name = rrname; async->queries_ongoing++; ares_query_dnsrec(thrdd->rr.channel, - rrname ? rrname : async->hostname, ARES_CLASS_IN, - ARES_REC_TYPE_HTTPS, + https_name ? https_name : async->peer->hostname, + ARES_CLASS_IN, ARES_REC_TYPE_HTTPS, async_thrdd_rr_done, async, NULL); - CURL_TRC_DNS(data, "[HTTPS-RR] initiated request for %s", - rrname ? rrname : async->hostname); - return CURLE_OK; + CURL_TRC_DNS(data, "[HTTPS] query records for %s", + https_name ? https_name : async->peer->hostname); + +out: + curlx_free(https_name); + return result; } #endif @@ -290,15 +296,9 @@ void Curl_async_thrdd_destroy(struct Curl_easy *data, ares_destroy(async->thrdd.rr.channel); async->thrdd.rr.channel = NULL; } - curlx_safefree(async->thrdd.rr.https_name); - Curl_httpsrr_destroy(async->thrdd.rr.hinfo); #endif - async_thrdd_item_destroy(async->thrdd.inc_A); - async->thrdd.inc_A = NULL; async_thrdd_item_destroy(async->thrdd.res_A); async->thrdd.res_A = NULL; - async_thrdd_item_destroy(async->thrdd.inc_AAAA); - async->thrdd.inc_AAAA = NULL; async_thrdd_item_destroy(async->thrdd.res_AAAA); async->thrdd.res_AAAA = NULL; } @@ -569,11 +569,11 @@ void Curl_async_thrdd_multi_process(struct Curl_multi *multi) if(data) async = Curl_async_get(data, item->resolv_id); if(async) { - struct async_thrdd_item **pdest = &async->thrdd.inc_A; + struct async_thrdd_item **pdest = &async->thrdd.res_A; #ifdef CURLRES_IPV6 if(item->dns_queries & CURL_DNSQ_AAAA) - pdest = &async->thrdd.inc_AAAA; + pdest = &async->thrdd.res_AAAA; #endif if(!*pdest) { *pdest = item; @@ -607,7 +607,7 @@ static CURLcode async_thrdd_query(struct Curl_easy *data, CURLcode result; item = async_thrdd_item_create(data, async->id, dns_queries, - async->hostname, async->port, + async->peer->hostname, async->peer->port, async->transport); if(!item) { result = CURLE_OUT_OF_MEMORY; @@ -676,7 +676,7 @@ out: if(result) CURL_TRC_DNS(data, "error queueing query %s:%d -> %d", - async->hostname, async->port, (int)result); + async->peer->hostname, async->peer->port, (int)result); return result; } @@ -772,33 +772,31 @@ static CURLcode async_thrdd_check_done(struct Curl_easy *data, struct async_thrdd_ctx *thrdd = &async->thrdd; (void)data; - if(thrdd->inc_A) { - thrdd->res_A = thrdd->inc_A; - thrdd->inc_A = NULL; + if(thrdd->res_A && !thrdd->processed_A) { VERBOSE(async_thrdd_report_item(data, thrdd->res_A)); + /* move addrinfos to the async result member */ async->dns_responses |= thrdd->res_A->dns_queries; + async->ai_A = thrdd->res_A->res; + thrdd->res_A->res = NULL; + thrdd->processed_A = TRUE; } - if(thrdd->inc_AAAA) { - if(thrdd->res_AAAA) { - DEBUGASSERT(0); /* should not happen */ - return CURLE_FAILED_INIT; - } + if(thrdd->res_AAAA && !thrdd->processed_AAAA) { #if defined(USE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) /* do we accept the incoming AAAA response? */ - if(!(thrdd->inc_AAAA->dns_queries & CURL_DNSQ_A) && - async_thrdd_item_missing_scope(data, thrdd->inc_AAAA)) { + if(!(thrdd->res_AAAA->dns_queries & CURL_DNSQ_A) && + async_thrdd_item_missing_scope(data, thrdd->res_AAAA)) { /* We queried "only" AF_INET6. This may be problematic when the * result has ipv6 link-local addresses and did not give * any scope id for it. glibc has a long outstanding bug * * that gives scope ids only on AF_UNSPEC queries. */ - struct async_thrdd_item *item = thrdd->inc_AAAA; + struct async_thrdd_item *item = thrdd->res_AAAA; CURLcode result; /* Reuse the item and queue it again, this time with added * CURL_DNSQ_A which resolves using AF_UNSPEC. */ - thrdd->inc_AAAA = NULL; + thrdd->res_AAAA = NULL; item->dns_queries |= CURL_DNSQ_A; if(item->res) { Curl_freeaddrinfo(item->res); @@ -819,12 +817,14 @@ static CURLcode async_thrdd_check_done(struct Curl_easy *data, } /* accepting the AAAA result, strip it of any AF_INET entries, * as we might have resolved it with AF_UNSPEC. */ - async_thrdd_item_strip_results(thrdd->inc_AAAA, AF_INET); + async_thrdd_item_strip_results(thrdd->res_AAAA, AF_INET); #endif /* USE_IPV6 && HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID */ - thrdd->res_AAAA = thrdd->inc_AAAA; - thrdd->inc_AAAA = NULL; VERBOSE(async_thrdd_report_item(data, thrdd->res_AAAA)); + /* move addrinfos to the async result member */ async->dns_responses |= thrdd->res_AAAA->dns_queries; + async->ai_AAAA = thrdd->res_AAAA->res; + thrdd->res_AAAA->res = NULL; + thrdd->processed_AAAA = TRUE; } if(async->queries_ongoing) @@ -872,9 +872,9 @@ CURLcode Curl_async_take_result(struct Curl_easy *data, const uint8_t ip_queries = async->dns_queries & (CURL_DNSQ_A | CURL_DNSQ_AAAA); bool negative = (async->dns_responses & ip_queries) == ip_queries; - if(thrdd->res_A && (thrdd->res_A->res || !thrdd->res_A->negative)) + if(thrdd->res_A && (async->ai_A || !thrdd->res_A->negative)) negative = FALSE; - if(thrdd->res_AAAA && (thrdd->res_AAAA->res || !thrdd->res_AAAA->negative)) + if(thrdd->res_AAAA && (async->ai_AAAA || !thrdd->res_AAAA->negative)) negative = FALSE; if(!thrdd->res_A && !thrdd->res_AAAA) negative = FALSE; @@ -886,13 +886,9 @@ CURLcode Curl_async_take_result(struct Curl_easy *data, goto out; } - if((thrdd->res_A && thrdd->res_A->res) || - (thrdd->res_AAAA && thrdd->res_AAAA->res)) { + if(async->ai_A || async->ai_AAAA) { dns = Curl_dnsc_mk_addr2( - data, async->dns_queries, - thrdd->res_A ? &thrdd->res_A->res : NULL, - thrdd->res_AAAA ? &thrdd->res_AAAA->res : NULL, - async->hostname, async->port); + data, async->dns_queries, &async->ai_A, &async->ai_AAAA, async->peer); if(!dns) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -901,9 +897,8 @@ CURLcode Curl_async_take_result(struct Curl_easy *data, #ifdef USE_HTTPSRR_ARES if(!dns && thrdd->rr.channel) { - Curl_httpsrr_trace(data, thrdd->rr.hinfo); - dns = Curl_dnsc_mk_https(data, &thrdd->rr.hinfo, - async->hostname, async->port); + Curl_httpsrr_trace(data, async->httpsrr); + dns = Curl_dnsc_mk_https(data, &async->httpsrr, async->peer); if(!dns) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -928,75 +923,9 @@ out: (result != CURLE_COULDNT_RESOLVE_HOST) && (result != CURLE_COULDNT_RESOLVE_PROXY)) { CURL_TRC_DNS(data, "Error %d resolving %s:%d", - (int)result, async->hostname, async->port); + (int)result, async->peer->hostname, async->peer->port); } return result; } -static const struct Curl_addrinfo *async_thrdd_get_ai( - const struct Curl_addrinfo *ai, - int ai_family, unsigned int index) -{ - unsigned int i = 0; - for(i = 0; ai; ai = ai->ai_next) { - if(ai->ai_family == ai_family) { - if(i == index) - return ai; - ++i; - } - } - return NULL; -} - -const struct Curl_addrinfo *Curl_async_get_ai(struct Curl_easy *data, - struct Curl_resolv_async *async, - int ai_family, - unsigned int index) -{ - struct async_thrdd_ctx *thrdd = &async->thrdd; - - (void)data; - switch(ai_family) { - case AF_INET: - if(thrdd->res_A) - return async_thrdd_get_ai(thrdd->res_A->res, ai_family, index); - break; -#ifdef USE_IPV6 - case AF_INET6: - if(thrdd->res_AAAA) - return async_thrdd_get_ai(thrdd->res_AAAA->res, ai_family, index); - break; -#endif - default: - break; - } - return NULL; -} - -#ifdef USE_HTTPSRR -const struct Curl_https_rrinfo *Curl_async_get_https( - struct Curl_easy *data, - struct Curl_resolv_async *async) -{ -#ifdef USE_HTTPSRR_ARES - if(Curl_async_knows_https(data, async)) - return async->thrdd.rr.hinfo; -#else - (void)data; - (void)async; -#endif - return NULL; -} - -bool Curl_async_knows_https(struct Curl_easy *data, - struct Curl_resolv_async *async) -{ - (void)data; - if(async->dns_queries & CURL_DNSQ_HTTPS) - return ((async->dns_responses & CURL_DNSQ_HTTPS) || async->done); - return TRUE; /* we know it will never come */ -} - -#endif /* USE_HTTPSRR */ - #endif /* USE_RESOLV_THREADED */ diff --git a/lib/asyn.h b/lib/asyn.h index 43e1dc6463..01611175be 100644 --- a/lib/asyn.h +++ b/lib/asyn.h @@ -82,15 +82,7 @@ void Curl_async_global_cleanup(void); CURLcode Curl_async_getaddrinfo(struct Curl_easy *data, struct Curl_resolv_async *async); -const struct Curl_addrinfo *Curl_async_get_ai(struct Curl_easy *data, - struct Curl_resolv_async *async, - int ai_family, - unsigned int index); - #ifdef USE_HTTPSRR -const struct Curl_https_rrinfo *Curl_async_get_https( - struct Curl_easy *data, - struct Curl_resolv_async *async); bool Curl_async_knows_https(struct Curl_easy *data, struct Curl_resolv_async *async); #endif /* USE_HTTPSRR */ @@ -114,15 +106,8 @@ int Curl_ares_perform(ares_channel channel, timediff_t timeout_ms); /* async resolving implementation using c-ares alone */ struct async_ares_ctx { ares_channel channel; - struct Curl_addrinfo *res_A; - struct Curl_addrinfo *res_AAAA; int ares_status; /* ARES_SUCCESS, ARES_ENOTFOUND, etc. */ CURLcode result; /* CURLE_OK or error handling response */ - struct curltime happy_eyeballs_dns_time; /* when this timer started, or 0 */ -#ifdef USE_HTTPSRR - char *https_name; - struct Curl_https_rrinfo *hinfo; -#endif BIT(transient_err); /* an A/AAAA query failed without the resolver answering that the name does not exist */ }; @@ -140,17 +125,15 @@ struct async_thrdd_item; /* Context for threaded resolver */ struct async_thrdd_ctx { - struct async_thrdd_item *inc_A; /* IPv4 incoming result */ struct async_thrdd_item *res_A; /* IPv4 final result */ - struct async_thrdd_item *inc_AAAA; /* IPv6 incoming result */ struct async_thrdd_item *res_AAAA; /* IPv6 final result */ #if defined(USE_HTTPSRR) && defined(USE_ARES) struct { ares_channel channel; - char *https_name; - struct Curl_https_rrinfo *hinfo; } rr; #endif + BIT(processed_A); + BIT(processed_AAAA); }; void Curl_async_thrdd_shutdown(struct Curl_easy *data, @@ -216,11 +199,9 @@ CURLcode Curl_async_pollset(struct Curl_easy *data, /* convert these functions if an asynch resolver is not used */ #define Curl_async_global_init() CURLE_OK #define Curl_async_global_cleanup() Curl_nop_stmt -#define Curl_async_get_ai(a, b, c, d) NULL #define Curl_async_await(a, b, c) CURLE_COULDNT_RESOLVE_HOST #define Curl_async_take_result(x, y, z) CURLE_COULDNT_RESOLVE_HOST #define Curl_async_pollset(x, y, z) CURLE_OK -#define Curl_async_get_https(x, y) NULL #define Curl_async_knows_https(x, y) TRUE #endif /* !CURLRES_ASYNCH */ @@ -232,6 +213,12 @@ CURLcode Curl_async_pollset(struct Curl_easy *data, struct Curl_resolv_async { struct Curl_resolv_async *next; + struct Curl_peer *peer; + struct Curl_addrinfo *ai_A; + struct Curl_addrinfo *ai_AAAA; +#ifdef USE_HTTPSRR + struct Curl_https_rrinfo *httpsrr; +#endif #ifdef USE_RESOLV_ARES struct async_ares_ctx ares; #elif defined(USE_RESOLV_THREADED) @@ -246,8 +233,6 @@ struct Curl_resolv_async { CURLcode result; uint32_t poll_interval; uint32_t id; /* unique id per easy handle of the resolve operation */ - /* what is being resolved */ - uint16_t port; uint8_t dns_queries; /* what queries are being performed */ uint8_t dns_responses; /* what queries had responses so far. */ uint8_t transport; @@ -261,7 +246,6 @@ struct Curl_resolv_async { exist. Only such failures may be cached as negative entries, not transient or local resolver failures. */ - char hostname[1]; }; timediff_t Curl_async_timeleft_ms(struct Curl_easy *data, diff --git a/lib/cf-dns.c b/lib/cf-dns.c index e3693e3acc..984d7a404d 100644 --- a/lib/cf-dns.c +++ b/lib/cf-dns.c @@ -567,30 +567,6 @@ CURLcode Curl_conn_dns_addr_result(struct connectdata *conn, return CURLE_FAILED_INIT; /* no one is resolving */ } -static const struct Curl_addrinfo *cf_dns_get_nth_ai( - struct Curl_cfilter *cf, - const struct Curl_addrinfo *ai, - int ai_family, unsigned int index) -{ - struct cf_dns_ctx *ctx = cf->ctx; - unsigned int i = 0; - - if((ai_family == AF_INET) && !(ctx->dns_queries & CURL_DNSQ_A)) - return NULL; -#ifdef USE_IPV6 - if((ai_family == AF_INET6) && !(ctx->dns_queries & CURL_DNSQ_AAAA)) - return NULL; -#endif - for(i = 0; ai; ai = ai->ai_next) { - if(ai->ai_family == ai_family) { - if(i == index) - return ai; - ++i; - } - } - return NULL; -} - /* Return the addrinfo at `index` for the given `family` from the * first "resolve" filter at the connection. If the DNS resolving is * not done yet or if no address for the family exists, returns NULL. @@ -613,8 +589,17 @@ const struct Curl_addrinfo *Curl_conn_dns_get_ai(struct Curl_easy *data, index, peer->hostname, peer->port, ai_family, !!ctx->dns); if(ctx->resolv_result) return NULL; - else if(ctx->dns) - return cf_dns_get_nth_ai(cf, ctx->dns->addr, ai_family, index); + else if(ctx->dns) { + /* A cached DNS entry may contain address families that we + * here never queried for. We want to give no results for those. */ + if((ai_family == AF_INET) && !(ctx->dns_queries & CURL_DNSQ_A)) + return NULL; +#ifdef USE_IPV6 + if((ai_family == AF_INET6) && !(ctx->dns_queries & CURL_DNSQ_AAAA)) + return NULL; +#endif + return Curl_addrinfo_get(ctx->dns->addr, ai_family, index); + } else return Curl_resolv_get_ai(data, ctx->resolv_id, ai_family, index); } diff --git a/lib/curl_addrinfo.c b/lib/curl_addrinfo.c index ea818a38e5..98ba7aec1c 100644 --- a/lib/curl_addrinfo.c +++ b/lib/curl_addrinfo.c @@ -79,6 +79,21 @@ void Curl_freeaddrinfo(struct Curl_addrinfo *cahead) } } +struct Curl_addrinfo *Curl_addrinfo_get(struct Curl_addrinfo *ai, + int ai_family, + unsigned int n) +{ + unsigned int i; + for(i = 0; ai; ai = ai->ai_next) { + if(ai->ai_family == ai_family) { + if(i == n) + return ai; + ++i; + } + } + return NULL; +} + #ifdef HAVE_GETADDRINFO /* * Curl_getaddrinfo_ex() diff --git a/lib/curl_addrinfo.h b/lib/curl_addrinfo.h index 046be23816..7b2b4d2834 100644 --- a/lib/curl_addrinfo.h +++ b/lib/curl_addrinfo.h @@ -62,6 +62,11 @@ struct Curl_addrinfo { void Curl_freeaddrinfo(struct Curl_addrinfo *cahead); +/* Get the n-th addrinfo of family ai_family. */ +struct Curl_addrinfo *Curl_addrinfo_get(struct Curl_addrinfo *ai, + int ai_family, + unsigned int n); + #ifdef HAVE_GETADDRINFO int Curl_getaddrinfo_ex(const char *nodename, const char *servname, diff --git a/lib/dnscache.c b/lib/dnscache.c index 73de3cacb3..44db67720b 100644 --- a/lib/dnscache.c +++ b/lib/dnscache.c @@ -60,6 +60,51 @@ #define MAX_DNS_CACHE_SIZE 29999 +struct dnsc_id { + struct Curl_str name; + uint16_t port; + char type; +}; + +static void dnsc_peer2id(struct dnsc_id *pid, char type, + struct Curl_peer *peer) +{ + curlx_str_assign(&pid->name, peer->hostname, strlen(peer->hostname)); + pid->port = peer->port; + pid->type = type; +} + +static void dnsc_str2id(struct dnsc_id *pid, char type, + struct Curl_str *name, uint16_t port) +{ + pid->name = *name; + pid->port = port; + pid->type = type; +} + +struct dnsc_key { + char data[MAX_HOSTCACHE_LEN]; + size_t len; +}; + +/* + * Create a hostcache id string for the provided host + port, to be used by + * the DNS caching. Without alloc. Return length of the id string. + */ +static void dnsc_id2key(struct dnsc_key *key, struct dnsc_id *id) +{ + size_t namelen = curlx_strlen(&id->name); + if(namelen > (sizeof(key->data) - 8)) + namelen = sizeof(key->data) - 8; + /* store and lower case the name */ + key->data[0] = id->type; + Curl_strntolower(key->data + 1, curlx_str(&id->name), namelen); + /* include the terminating 0 in key length */ + key->len = namelen + 2 + + curl_msnprintf(&key->data[namelen + 1], 7, ":%u", id->port); +} + + static void dnscache_entry_free(struct Curl_dns_entry *dns) { Curl_freeaddrinfo(dns->addr); @@ -69,25 +114,6 @@ static void dnscache_entry_free(struct Curl_dns_entry *dns) curlx_free(dns); } -/* - * Create a hostcache id string for the provided host + port, to be used by - * the DNS caching. Without alloc. Return length of the id string. - */ -static size_t create_dnscache_id(char type, const char *name, - size_t nlen, /* 0 or actual name length */ - uint16_t port, - char *buf, size_t buflen) -{ - size_t len = nlen ? nlen : strlen(name); - DEBUGASSERT(buflen >= MAX_HOSTCACHE_LEN); - if(len > (buflen - 8)) - len = buflen - 8; - /* store and lower case the name */ - buf[0] = type; - Curl_strntolower(buf + 1, name, len); - return curl_msnprintf(&buf[len + 1], 7, ":%u", port) + len + 1; -} - struct dnscache_prune_data { struct curltime now; timediff_t oldest_ms; /* oldest time in cache not pruned. */ @@ -211,35 +237,36 @@ void Curl_dnscache_clear(struct Curl_easy *data) static CURLcode fetch_addr(struct Curl_easy *data, struct Curl_dnscache *dnscache, uint8_t dns_queries, - const char *hostname, - uint16_t port, + struct Curl_peer *peer, struct Curl_dns_entry **pdns) { struct Curl_dns_entry *dns = NULL; - char entry_id[MAX_HOSTCACHE_LEN]; - size_t entry_len; - char entry_type = CURL_DNSQ_IS_ADDR(dns_queries) ? - CURL_DNST_ADDR : CURL_DNST_HTTPS; + struct dnsc_id id; + struct dnsc_key key; + char type = CURL_DNSQ_IS_ADDR(dns_queries) ? + CURL_DNST_ADDR : CURL_DNST_HTTPS; CURLcode result = CURLE_OK; *pdns = NULL; if(!dnscache) return CURLE_OK; - /* Create an entry id, based upon the hostname and port */ - entry_len = create_dnscache_id(entry_type, hostname, 0, port, - entry_id, sizeof(entry_id)); + dnsc_peer2id(&id, type, peer); + dnsc_id2key(&key, &id); /* See if it is already in our dns cache */ - dns = Curl_hash_pick(&dnscache->entries, entry_id, entry_len + 1); + dns = Curl_hash_pick(&dnscache->entries, key.data, key.len); /* No entry found in cache, check if we might have a wildcard entry */ - if(!dns && data->state.wildcard_resolve && CURL_DNSQ_IS_ADDR(dns_queries)) { - entry_len = create_dnscache_id(CURL_DNST_ADDR, "*", 1, port, - entry_id, sizeof(entry_id)); + if(!dns && (type == CURL_DNST_ADDR) && data->state.wildcard_resolve) { + struct Curl_str wildname; + + curlx_str_assign(&wildname, "*", 1); + dnsc_str2id(&id, CURL_DNST_ADDR, &wildname, peer->port); + dnsc_id2key(&key, &id); /* See if it is already in our dns cache */ - dns = Curl_hash_pick(&dnscache->entries, entry_id, entry_len + 1); + dns = Curl_hash_pick(&dnscache->entries, key.data, key.len); } if(dns && (data->set.dns_cache_timeout_ms != -1)) { @@ -253,7 +280,7 @@ static CURLcode fetch_addr(struct Curl_easy *data, if(dnscache_entry_is_stale(&user, dns)) { infof(data, "Hostname in DNS cache was stale, zapped"); dns = NULL; /* the memory deallocation is being handled by the hash */ - Curl_hash_delete(&dnscache->entries, entry_id, entry_len + 1); + Curl_hash_delete(&dnscache->entries, key.data, key.len); } } @@ -297,8 +324,7 @@ static CURLcode fetch_addr(struct Curl_easy *data, */ CURLcode Curl_dnscache_get(struct Curl_easy *data, uint8_t dns_queries, - const char *hostname, - uint16_t port, + struct Curl_peer *peer, struct Curl_dns_entry **pentry) { struct Curl_dnscache *dnscache = dnscache_get(data); @@ -306,7 +332,7 @@ CURLcode Curl_dnscache_get(struct Curl_easy *data, CURLcode result = CURLE_OK; dnscache_lock(data, dnscache); - result = fetch_addr(data, dnscache, dns_queries, hostname, port, &dns); + result = fetch_addr(data, dnscache, dns_queries, peer, &dns); if(!result && dns) dns->refcount++; /* we pass out a reference */ else if(result) { @@ -316,7 +342,7 @@ CURLcode Curl_dnscache_get(struct Curl_easy *data, dnscache_unlock(data, dnscache); CURL_TRC_DNS(data, "cache lookup %s:%u queries=%s -> %d %sfound", - hostname, port, Curl_resolv_query_str(dns_queries), + peer->hostname, peer->port, Curl_resolv_query_str(dns_queries), (int)result, dns ? "" : "not "); *pentry = dns; return result; @@ -414,24 +440,23 @@ static bool dnscache_ai_has_family(struct Curl_addrinfo *ai, return FALSE; } -static struct Curl_dns_entry *dnsc_entry_create( - struct Curl_easy *data, - const char *hostname, - size_t hostlen, - uint16_t port, - bool permanent) +static struct Curl_dns_entry *dnsc_entry_create(struct Curl_easy *data, + struct dnsc_id *pid, + bool permanent) { struct Curl_dns_entry *dns = NULL; /* Create a new cache entry, struct already has the hostname NUL */ - dns = curlx_calloc(1, sizeof(struct Curl_dns_entry) + hostlen); + dns = curlx_calloc(1, sizeof(struct Curl_dns_entry) + + curlx_strlen(&pid->name)); if(!dns) goto out; dns->refcount = 1; /* the cache has the first reference */ - dns->port = port; - if(hostlen) - memcpy(dns->hostname, hostname, hostlen); + dns->hostlen = curlx_strlen(&pid->name); + dns->port = pid->port; + if(dns->hostlen) + memcpy(dns->hostname, curlx_str(&pid->name), dns->hostlen); if(permanent) { dns->timestamp.tv_sec = 0; /* an entry that never goes stale */ @@ -515,26 +540,30 @@ out: } struct Curl_dns_entry *Curl_dnsc_mk_addr(struct Curl_easy *data, - uint8_t dns_queries, - struct Curl_addrinfo **paddr, - const char *hostname, - uint16_t port) + uint8_t dns_queries, + struct Curl_addrinfo **paddr, + struct Curl_peer *peer) { - struct Curl_dns_entry *dns = dnsc_entry_create( - data, hostname, hostname ? strlen(hostname) : 0, port, FALSE); + struct dnsc_id id; + struct Curl_dns_entry *dns; + + dnsc_peer2id(&id, CURL_DNST_ADDR, peer); + dns = dnsc_entry_create(data, &id, FALSE); dns = dnsc_entry_assign_addr(data, dns, dns_queries, paddr, NULL); return dns; } struct Curl_dns_entry *Curl_dnsc_mk_addr2(struct Curl_easy *data, - uint8_t dns_queries, - struct Curl_addrinfo **paddr1, - struct Curl_addrinfo **paddr2, - const char *hostname, - uint16_t port) + uint8_t dns_queries, + struct Curl_addrinfo **paddr1, + struct Curl_addrinfo **paddr2, + struct Curl_peer *peer) { - struct Curl_dns_entry *dns = dnsc_entry_create( - data, hostname, hostname ? strlen(hostname) : 0, port, FALSE); + struct dnsc_id id; + struct Curl_dns_entry *dns; + + dnsc_peer2id(&id, CURL_DNST_ADDR, peer); + dns = dnsc_entry_create(data, &id, FALSE); dns = dnsc_entry_assign_addr(data, dns, dns_queries, paddr1, paddr2); return dns; } @@ -570,11 +599,13 @@ out: struct Curl_dns_entry *Curl_dnsc_mk_https(struct Curl_easy *data, struct Curl_https_rrinfo **phinfo, - const char *hostname, - uint16_t port) + struct Curl_peer *peer) { - struct Curl_dns_entry *dns = dnsc_entry_create( - data, hostname, hostname ? strlen(hostname) : 0, port, FALSE); + struct dnsc_id id; + struct Curl_dns_entry *dns; + + dnsc_peer2id(&id, CURL_DNST_HTTPS, peer); + dns = dnsc_entry_create(data, &id, FALSE); dns = dnsc_entry_assign_https(dns, phinfo); return dns; } @@ -582,28 +613,20 @@ struct Curl_dns_entry *Curl_dnsc_mk_https(struct Curl_easy *data, static struct Curl_dns_entry *dnsc_add_https(struct Curl_easy *data, struct Curl_dnscache *dnscache, struct Curl_https_rrinfo **phinfo, - const char *hostname, - size_t hlen, - uint16_t port, + struct dnsc_id *id, bool permanent) { - char entry_id[MAX_HOSTCACHE_LEN]; - size_t entry_len; struct Curl_dns_entry *dns, *dns2; + struct dnsc_key key; - dns = dnsc_entry_create(data, hostname, hostname ? strlen(hostname) : 0, - port, permanent); + dns = dnsc_entry_create(data, id, permanent); dns = dnsc_entry_assign_https(dns, phinfo); if(!dns) return NULL; - /* Create an entry id, based upon the hostname and port */ - entry_len = create_dnscache_id(CURL_DNST_HTTPS, hostname, hlen, port, - entry_id, sizeof(entry_id)); - /* Store the resolved data in our DNS cache. */ - dns2 = Curl_hash_add(&dnscache->entries, entry_id, entry_len + 1, - (void *)dns); + dnsc_id2key(&key, id); + dns2 = Curl_hash_add(&dnscache->entries, key.data, key.len, (void *)dns); if(!dns2) { dnscache_entry_free(dns); return NULL; @@ -620,28 +643,51 @@ static struct Curl_dns_entry *dnsc_add_addr(struct Curl_easy *data, struct Curl_dnscache *dnscache, uint8_t dns_queries, struct Curl_addrinfo **paddr, - const char *hostname, - size_t hlen, - uint16_t port, + struct dnsc_id *id, + struct dnsc_key *key, bool permanent) { - char entry_id[MAX_HOSTCACHE_LEN]; - size_t entry_len; struct Curl_dns_entry *dns; struct Curl_dns_entry *dns2; - dns = dnsc_entry_create(data, hostname, hlen, port, permanent); + dns = dnsc_entry_create(data, id, permanent); + dns = dnsc_entry_assign_addr(data, dns, dns_queries, paddr, NULL); + if(!dns) + return NULL; + + /* Store the resolved data in our DNS cache. */ + dns2 = Curl_hash_add(&dnscache->entries, key->data, key->len, (void *)dns); + if(!dns2) { + dnscache_entry_free(dns); + return NULL; + } + + dns = dns2; + dns->refcount++; /* mark entry as in-use */ + return dns; +} + +static struct Curl_dns_entry * +dnsc_add_peer_addr(struct Curl_easy *data, + struct Curl_dnscache *dnscache, + uint8_t dns_queries, + struct Curl_addrinfo **paddr, + struct dnsc_id *id, + bool permanent) +{ + struct Curl_dns_entry *dns; + struct Curl_dns_entry *dns2; + struct dnsc_key key; + + dns = dnsc_entry_create(data, id, permanent); dns = dnsc_entry_assign_addr(data, dns, dns_queries, paddr, NULL); if(!dns) return NULL; - /* Create an entry id, based upon the hostname and port */ - entry_len = create_dnscache_id(CURL_DNST_ADDR, hostname, hlen, port, - entry_id, sizeof(entry_id)); /* Store the resolved data in our DNS cache. */ - dns2 = Curl_hash_add(&dnscache->entries, entry_id, entry_len + 1, - (void *)dns); + dnsc_id2key(&key, id); + dns2 = Curl_hash_add(&dnscache->entries, key.data, key.len, (void *)dns); if(!dns2) { dnscache_entry_free(dns); return NULL; @@ -656,21 +702,22 @@ CURLcode Curl_dnscache_add(struct Curl_easy *data, struct Curl_dns_entry *entry) { struct Curl_dnscache *dnscache = dnscache_get(data); - char id[MAX_HOSTCACHE_LEN]; - size_t idlen; + struct Curl_str name; + struct dnsc_id id; + struct dnsc_key key; if(!dnscache) return CURLE_FAILED_INIT; if(!entry || (entry->type == CURL_DNST_INIT)) return CURLE_BAD_FUNCTION_ARGUMENT; - /* Create an entry id, based upon the hostname and port */ - idlen = create_dnscache_id(entry->type, entry->hostname, 0, entry->port, - id, sizeof(id)); + curlx_str_assign(&name, entry->hostname, entry->hostlen); + dnsc_str2id(&id, entry->type, &name, entry->port); + dnsc_id2key(&key, &id); /* Store the resolved data in our DNS cache and up ref count */ dnscache_lock(data, dnscache); - if(!Curl_hash_add(&dnscache->entries, id, idlen + 1, (void *)entry)) { + if(!Curl_hash_add(&dnscache->entries, key.data, key.len, (void *)entry)) { dnscache_unlock(data, dnscache); return CURLE_OUT_OF_MEMORY; } @@ -684,11 +731,11 @@ CURLcode Curl_dnscache_add(struct Curl_easy *data, CURLcode Curl_dnscache_add_negative(struct Curl_easy *data, uint8_t dns_queries, - const char *host, - uint16_t port) + struct Curl_peer *peer) { struct Curl_dnscache *dnscache = dnscache_get(data); struct Curl_dns_entry *dns = NULL; + struct dnsc_id id; CURLcode result = CURLE_OK; DEBUGASSERT(dnscache); @@ -699,15 +746,15 @@ CURLcode Curl_dnscache_add_negative(struct Curl_easy *data, if(dns_queries & CURL_DNSQ_ADDR) { /* put this new host in the cache */ - dns = dnsc_add_addr(data, dnscache, dns_queries, NULL, - host, strlen(host), port, FALSE); + dnsc_peer2id(&id, CURL_DNST_ADDR, peer); + dns = dnsc_add_peer_addr(data, dnscache, dns_queries, NULL, &id, FALSE); if(!dns) result = CURLE_OUT_OF_MEMORY; } #ifdef USE_HTTPSRR else if(dns_queries == CURL_DNSQ_HTTPS) { - dns = dnsc_add_https(data, dnscache, NULL, - host, strlen(host), port, FALSE); + dnsc_peer2id(&id, CURL_DNST_HTTPS, peer); + dns = dnsc_add_https(data, dnscache, NULL, &id, FALSE); if(!dns) result = CURLE_OUT_OF_MEMORY; } @@ -722,7 +769,8 @@ CURLcode Curl_dnscache_add_negative(struct Curl_easy *data, * entry alive: */ dns->refcount--; CURL_TRC_DNS(data, "cache negative name resolve for %s:%d type=%s", - host, port, Curl_resolv_query_str(dns_queries)); + peer->hostname, peer->port, + Curl_resolv_query_str(dns_queries)); } dnscache_unlock(data, dnscache); return result; @@ -777,6 +825,8 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) { struct Curl_dnscache *dnscache = dnscache_get(data); struct curl_slist *hostp; + struct dnsc_id id; + struct dnsc_key key; if(!dnscache) return CURLE_FAILED_INIT; @@ -785,14 +835,12 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) data->state.wildcard_resolve = FALSE; for(hostp = data->state.resolve; hostp; hostp = hostp->next) { - char entry_id[MAX_HOSTCACHE_LEN]; const char *host = hostp->data; struct Curl_str source; if(!host) continue; if(*host == '-') { curl_off_t num = 0; - size_t entry_len; host++; if(!curlx_str_single(&host, '[')) { if(curlx_str_until(&host, &source, MAX_IPADR_LEN, ']') || @@ -809,19 +857,17 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) if(!curlx_str_number(&host, &num, 0xffff)) { /* Create an entry id, based upon the hostname and port */ - entry_len = create_dnscache_id(CURL_DNST_ADDR, curlx_str(&source), - curlx_strlen(&source), (uint16_t)num, - entry_id, sizeof(entry_id)); + dnsc_str2id(&id, CURL_DNST_ADDR, &source, (uint16_t)num); + dnsc_id2key(&key, &id); dnscache_lock(data, dnscache); /* delete entry, ignore if it did not exist */ - Curl_hash_delete(&dnscache->entries, entry_id, entry_len + 1); + Curl_hash_delete(&dnscache->entries, key.data, key.len); dnscache_unlock(data, dnscache); } } else { struct Curl_dns_entry *dns; struct Curl_addrinfo *head = NULL, *tail = NULL; - size_t entry_len; char address[64]; curl_off_t tmpofft = 0; uint16_t port = 0; @@ -913,15 +959,12 @@ err: return CURLE_SETOPT_OPTION_SYNTAX; } - /* Create an entry id, based upon the hostname and port */ - entry_len = create_dnscache_id(CURL_DNST_ADDR, - curlx_str(&source), curlx_strlen(&source), - port, entry_id, sizeof(entry_id)); - + dnsc_str2id(&id, CURL_DNST_ADDR, &source, port); + dnsc_id2key(&key, &id); dnscache_lock(data, dnscache); /* See if it is already in our dns cache */ - dns = Curl_hash_pick(&dnscache->entries, entry_id, entry_len + 1); + dns = Curl_hash_pick(&dnscache->entries, key.data, key.len); if(dns) { infof(data, "RESOLVE %.*s:%u - old addresses discarded", @@ -938,13 +981,12 @@ err: 4. when adding a non-permanent entry, we want it to get a "fresh" timeout that starts _now_. */ - Curl_hash_delete(&dnscache->entries, entry_id, entry_len + 1); + Curl_hash_delete(&dnscache->entries, key.data, key.len); } /* put this new host in the cache, override all address queries */ - dns = dnsc_add_addr(data, dnscache, CURL_DNSQ_ADDR, - &head, curlx_str(&source), - curlx_strlen(&source), port, permanent); + dns = dnsc_add_addr(data, dnscache, CURL_DNSQ_ADDR, &head, + &id, &key, permanent); if(dns) /* release the returned reference; the cache itself will keep the * entry alive: */ @@ -956,8 +998,8 @@ err: return CURLE_OUT_OF_MEMORY; infof(data, "[DNS] added %.*s:%u:%s to cache%s", - (int)curlx_strlen(&source), curlx_str(&source), port, addresses, - permanent ? "" : " (non-permanent)"); + (int)curlx_strlen(&id.name), curlx_str(&id.name), id.port, + addresses, permanent ? "" : " (non-permanent)"); /* Wildcard hostname */ if(curlx_str_casecompare(&source, "*")) { diff --git a/lib/dnscache.h b/lib/dnscache.h index c029eb9d30..1b9518b3bf 100644 --- a/lib/dnscache.h +++ b/lib/dnscache.h @@ -35,6 +35,7 @@ struct connectdata; struct easy_pollset; struct Curl_https_rrinfo; struct Curl_multi; +struct Curl_peer; #define CURL_DNST_INIT '\0' #define CURL_DNST_ADDR 'A' @@ -47,6 +48,7 @@ struct Curl_dns_entry { #endif /* timestamp == 0 -- permanent CURLOPT_RESOLVE entry (does not time out) */ struct curltime timestamp; + size_t hostlen; /* reference counter, entry is freed on reaching 0 */ uint32_t refcount; /* hostname port number that resolved to addr. */ @@ -70,21 +72,18 @@ struct Curl_dns_entry { struct Curl_dns_entry *Curl_dnsc_mk_addr(struct Curl_easy *data, uint8_t dns_queries, struct Curl_addrinfo **paddr, - const char *hostname, - uint16_t port); + struct Curl_peer *peer); struct Curl_dns_entry *Curl_dnsc_mk_addr2(struct Curl_easy *data, uint8_t dns_queries, struct Curl_addrinfo **paddr1, struct Curl_addrinfo **paddr2, - const char *hostname, - uint16_t port); + struct Curl_peer *peer); #ifdef USE_HTTPSRR struct Curl_dns_entry *Curl_dnsc_mk_https(struct Curl_easy *data, struct Curl_https_rrinfo **phinfo, - const char *hostname, - uint16_t port); + struct Curl_peer *peer); #endif /* USE_HTTPSRR */ /* unlink a dns entry, frees all resources if it was the last reference. @@ -119,8 +118,7 @@ void Curl_dnscache_clear(struct Curl_easy *data); */ CURLcode Curl_dnscache_get(struct Curl_easy *data, uint8_t dns_queries, - const char *hostname, - uint16_t port, + struct Curl_peer *peer, struct Curl_dns_entry **pentry); /* @@ -134,8 +132,7 @@ CURLcode Curl_dnscache_add(struct Curl_easy *data, * it could not be resolved. */ CURLcode Curl_dnscache_add_negative(struct Curl_easy *data, uint8_t dns_queries, - const char *host, - uint16_t port); + struct Curl_peer *peer); /* * Populate the cache with specified entries from CURLOPT_RESOLVE. diff --git a/lib/doh.c b/lib/doh.c index 6d39f6ff0e..d335204199 100644 --- a/lib/doh.c +++ b/lib/doh.c @@ -463,7 +463,7 @@ CURLcode Curl_doh(struct Curl_easy *data, size_t i; DEBUGASSERT(!async->doh); - DEBUGASSERT(async->hostname[0]); + DEBUGASSERT(async->peer->hostname[0]); if(async->doh) { DEBUGASSERT(0); /* should not happen */ Curl_doh_cleanup(data, async); @@ -479,13 +479,10 @@ CURLcode Curl_doh(struct Curl_easy *data, curlx_dyn_init(&dohp->probe_resp[i].body, DYN_DOH_RESPONSE); } - dohp->host = async->hostname; - dohp->port = async->port; - /* create IPv4 DoH request */ if(async->dns_queries & CURL_DNSQ_A) { result = doh_probe_run(data, CURL_DNS_TYPE_A, - async->hostname, data->set.str[STRING_DOH], + async->peer->hostname, data->set.str[STRING_DOH], data->multi, async->id, &dohp->probe_resp[DOH_SLOT_IPV4].probe_mid); if(result) @@ -497,7 +494,7 @@ CURLcode Curl_doh(struct Curl_easy *data, if(async->dns_queries & CURL_DNSQ_AAAA) { /* create IPv6 DoH request */ result = doh_probe_run(data, CURL_DNS_TYPE_AAAA, - async->hostname, data->set.str[STRING_DOH], + async->peer->hostname, data->set.str[STRING_DOH], data->multi, async->id, &dohp->probe_resp[DOH_SLOT_IPV6].probe_mid); if(result) @@ -509,13 +506,14 @@ CURLcode Curl_doh(struct Curl_easy *data, #ifdef USE_HTTPSRR if(async->dns_queries & CURL_DNSQ_HTTPS) { char *qname = NULL; - if(async->port != PORT_HTTPS) { - qname = curl_maprintf("_%d._https.%s", async->port, async->hostname); + if(async->peer->port != PORT_HTTPS) { + qname = curl_maprintf("_%u._https.%s", + async->peer->port, async->peer->hostname); if(!qname) goto error; } result = doh_probe_run(data, CURL_DNS_TYPE_HTTPS, - qname ? qname : async->hostname, + qname ? qname : async->peer->hostname, data->set.str[STRING_DOH], data->multi, async->id, &dohp->probe_resp[DOH_SLOT_HTTPS_RR].probe_mid); @@ -1209,7 +1207,7 @@ CURLcode Curl_doh_take_result(struct Curl_easy *data, if(CURL_DNSQ_IS_ADDR(async->dns_queries) && dohp->probe_resp[DOH_SLOT_IPV4].probe_mid == UINT32_MAX && dohp->probe_resp[DOH_SLOT_IPV6].probe_mid == UINT32_MAX) { - failf(data, "Could not DoH-resolve: %s", dohp->host); + failf(data, "Could not DoH-resolve: %s", async->peer->hostname); return async->for_proxy ? CURLE_COULDNT_RESOLVE_PROXY : CURLE_COULDNT_RESOLVE_HOST; } @@ -1240,7 +1238,7 @@ CURLcode Curl_doh_take_result(struct Curl_easy *data, CURL_TRC_DNS(data, "[%s] [DoH] error: %s type %s for %s", Curl_resolv_query_str(async->dns_queries), doh_strerror(rc[slot]), - doh_type2name(p->dnstype), dohp->host); + doh_type2name(p->dnstype), async->peer->hostname); } } /* next slot */ @@ -1250,11 +1248,11 @@ CURLcode Curl_doh_take_result(struct Curl_easy *data, struct Curl_addrinfo *ai; if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_doh)) { - CURL_TRC_DNS(data, "hostname: %s", dohp->host); + CURL_TRC_DNS(data, "hostname: %s", async->peer->hostname); doh_show(data, &de); } - result = doh2ai(&de, dohp->host, dohp->port, &ai); + result = doh2ai(&de, async->peer->hostname, async->peer->port, &ai); if(result) { /* a decoded response without any usable address, e.g. only CNAME records, is an authoritative "no data" answer */ @@ -1264,8 +1262,7 @@ CURLcode Curl_doh_take_result(struct Curl_easy *data, } /* we got a response, create a dns entry. */ - dns = Curl_dnsc_mk_addr(data, async->dns_queries, - &ai, dohp->host, dohp->port); + dns = Curl_dnsc_mk_addr(data, async->dns_queries, &ai, async->peer); if(!dns) { result = CURLE_OUT_OF_MEMORY; goto error; @@ -1297,7 +1294,7 @@ CURLcode Curl_doh_take_result(struct Curl_easy *data, infof(data, "Some HTTPS RR to process"); } Curl_httpsrr_trace(data, hrr); - dns = Curl_dnsc_mk_https(data, &hrr, async->hostname, async->port); + dns = Curl_dnsc_mk_https(data, &hrr, async->peer); if(!dns) { result = CURLE_OUT_OF_MEMORY; goto error; diff --git a/lib/doh.h b/lib/doh.h index f4ecec0881..5179c28cae 100644 --- a/lib/doh.h +++ b/lib/doh.h @@ -110,8 +110,6 @@ struct doh_response { struct doh_probes { struct doh_response probe_resp[DOH_SLOT_COUNT]; unsigned int pending; /* still outstanding probes */ - uint16_t port; - const char *host; }; /* diff --git a/lib/hostip.c b/lib/hostip.c index 7427f8fdd9..3eb85d7e3f 100644 --- a/lib/hostip.c +++ b/lib/hostip.c @@ -342,11 +342,11 @@ static bool tailmatch(const char *full, size_t flen, } static CURLcode hostip_resolv_failed(struct Curl_easy *data, - const char *hostname, + struct Curl_peer *peer, bool for_proxy) { failf(data, "Could not resolve %s: %s", - for_proxy ? "proxy" : "host", hostname); + for_proxy ? "proxy" : "host", peer->hostname); return RESOLV_FAIL(for_proxy); } @@ -383,14 +383,12 @@ CURLcode Curl_resolv_announce_start(struct Curl_easy *data, static struct Curl_resolv_async *hostip_async_new(struct Curl_easy *data, uint8_t dns_queries, - const char *hostname, - uint16_t port, + struct Curl_peer *peer, uint8_t transport, bool for_proxy, timediff_t timeout_ms) { struct Curl_resolv_async *async; - size_t hostlen = strlen(hostname); if(!data->multi) { DEBUGASSERT(0); @@ -398,7 +396,7 @@ static struct Curl_resolv_async *hostip_async_new(struct Curl_easy *data, } /* struct size already includes the NUL for hostname */ - async = curlx_calloc(1, sizeof(*async) + hostlen); + async = curlx_calloc(1, sizeof(*async)); if(!async) return NULL; @@ -412,18 +410,15 @@ static struct Curl_resolv_async *hostip_async_new(struct Curl_easy *data, else data->multi->last_resolv_id++; async->id = data->multi->last_resolv_id; + Curl_peer_link(&async->peer, peer); async->dns_queries = dns_queries; - async->port = port; async->transport = transport; async->for_proxy = for_proxy; async->start = *Curl_pgrs_now(data); async->timeout_ms = timeout_ms; - if(hostlen) { - memcpy(async->hostname, hostname, hostlen); - async->is_ipaddr = Curl_is_ipaddr(async->hostname); - if(async->is_ipaddr) - async->is_ipv4addr = Curl_is_ipv4addr(async->hostname); - } + async->is_ipaddr = Curl_is_ipaddr(peer->hostname); + if(async->is_ipaddr) + async->is_ipv4addr = Curl_is_ipv4addr(peer->hostname); return async; } @@ -450,7 +445,8 @@ static CURLcode hostip_resolv_take_result(struct Curl_easy *data, "ongoing=%d for %s:%d", Curl_resolv_query_str(async->dns_queries), Curl_resolv_query_str(async->dns_responses), - async->queries_ongoing, async->hostname, async->port); + async->queries_ongoing, + async->peer->hostname, async->peer->port); result = CURLE_OK; } else if(IS_RESOLV_FAIL(result)) { @@ -461,12 +457,12 @@ static CURLcode hostip_resolv_take_result(struct Curl_easy *data, is so it does not get treated as one. */ CURL_TRC_DNS(data, "[%s] resolve error %d for %s:%u", Curl_resolv_query_str(async->dns_queries), - (int)result, async->hostname, async->port); + (int)result, async->peer->hostname, async->peer->port); } else { CURL_TRC_DNS(data, "[%s] resolve complete for %s:%u", Curl_resolv_query_str(async->dns_queries), - async->hostname, async->port); + async->peer->hostname, async->peer->port); DEBUGASSERT(*pdns); } @@ -504,16 +500,18 @@ const struct Curl_addrinfo *Curl_resolv_get_ai(struct Curl_easy *data, unsigned int index) { struct Curl_resolv_async *async = Curl_async_get(data, resolv_id); - (void)index; - if(!async) - return NULL; - if((ai_family == AF_INET) && !(async->dns_queries & CURL_DNSQ_A)) + if(!async || !CURL_DNSQ_IS_ADDR(async->dns_queries)) return NULL; + switch(ai_family) { + case AF_INET: + return Curl_addrinfo_get(async->ai_A, ai_family, index); #ifdef USE_IPV6 - if((ai_family == AF_INET6) && !(async->dns_queries & CURL_DNSQ_AAAA)) - return NULL; + case AF_INET6: + return Curl_addrinfo_get(async->ai_AAAA, ai_family, index); #endif - return Curl_async_get_ai(data, async, ai_family, index); + default: + return NULL; + } } #ifdef USE_HTTPSRR @@ -532,19 +530,22 @@ CURLcode Curl_resolv_https(struct Curl_easy *data, const struct Curl_https_rrinfo * Curl_resolv_get_https(struct Curl_easy *data, uint32_t resolv_id) { - struct Curl_resolv_async *async = Curl_async_get(data, resolv_id); - if(!async) + struct Curl_resolv_async *async; + if(!Curl_resolv_knows_https(data, resolv_id)) return NULL; - return Curl_async_get_https(data, async); + async = Curl_async_get(data, resolv_id); + return async ? async->httpsrr : NULL; } bool Curl_resolv_knows_https(struct Curl_easy *data, uint32_t resolv_id) { struct Curl_resolv_async *async = Curl_async_get(data, resolv_id); - if(!async) - return TRUE; - return Curl_async_knows_https(data, async); + if(async && (async->dns_queries & CURL_DNSQ_HTTPS)) + return ((async->dns_responses & CURL_DNSQ_HTTPS) || + !async->queries_ongoing); + return TRUE; /* we know it will never come */ } + #endif /* USE_HTTPSRR */ #endif /* USE_CURL_ASYNC */ @@ -555,8 +556,7 @@ bool Curl_resolv_knows_https(struct Curl_easy *data, uint32_t resolv_id) that must not be cached as negative entries. */ static CURLcode hostip_resolv_start(struct Curl_easy *data, uint8_t dns_queries, - const char *hostname, - uint16_t port, + struct Curl_peer *peer, uint8_t transport, bool for_proxy, timediff_t timeout_ms, @@ -582,40 +582,40 @@ static CURLcode hostip_resolv_start(struct Curl_easy *data, /* Check for "known" things to resolve ourselves. */ if(addr_queries) { #ifndef USE_RESOLVE_ON_IPS - if(Curl_is_ipaddr(hostname)) { + if(Curl_is_ipaddr(peer->hostname)) { /* test655 verifies that the announce is done, even though there * is no real resolving. So, keep doing this. */ result = Curl_resolv_announce_start(data, NULL); if(result) goto out; /* shortcut literal IP addresses, if we are not told to resolve them. */ - result = Curl_str2addr(hostname, port, &addr); + result = Curl_str2addr(peer->hostname, peer->port, &addr); goto out; } #endif - hostname_len = strlen(hostname); - if(curl_strequal(hostname, "localhost") || - curl_strequal(hostname, "localhost.") || - tailmatch(hostname, hostname_len, STRCONST(".localhost")) || - tailmatch(hostname, hostname_len, STRCONST(".localhost."))) { + hostname_len = strlen(peer->hostname); + if(curl_strequal(peer->hostname, "localhost") || + curl_strequal(peer->hostname, "localhost.") || + tailmatch(peer->hostname, hostname_len, STRCONST(".localhost")) || + tailmatch(peer->hostname, hostname_len, STRCONST(".localhost."))) { result = Curl_resolv_announce_start(data, NULL); if(result) goto out; - addr = get_localhost(port, hostname); + addr = get_localhost(peer->port, peer->hostname); if(!addr) result = CURLE_OUT_OF_MEMORY; goto out; } } #ifndef CURL_DISABLE_DOH - if(!Curl_is_ipaddr(hostname) && allowDOH && data->set.doh) { + if(!Curl_is_ipaddr(peer->hostname) && allowDOH && data->set.doh) { result = Curl_resolv_announce_start(data, NULL); if(result) goto out; if(!async) { - async = hostip_async_new(data, dns_queries, hostname, port, - transport, for_proxy, timeout_ms); + async = hostip_async_new(data, dns_queries, peer, transport, + for_proxy, timeout_ms); if(!async) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -637,8 +637,8 @@ static CURLcode hostip_resolv_start(struct Curl_easy *data, #ifdef CURLRES_ASYNCH (void)addr; if(!async) { - async = hostip_async_new(data, dns_queries, hostname, port, - transport, for_proxy, timeout_ms); + async = hostip_async_new(data, dns_queries, peer, transport, + for_proxy, timeout_ms); if(!async) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -657,7 +657,8 @@ static CURLcode hostip_resolv_start(struct Curl_easy *data, result = Curl_resolv_announce_start(data, NULL); if(result) goto out; - addr = Curl_sync_getaddrinfo(data, dns_queries, hostname, port, transport); + addr = Curl_sync_getaddrinfo(data, dns_queries, peer->hostname, peer->port, + transport); if(!addr) { result = RESOLV_FAIL(for_proxy); /* the synchronous resolvers do not tell a transient failure from @@ -671,7 +672,7 @@ out: if(addr) { /* we got a response, create a dns entry, add to cache, return */ DEBUGASSERT(!*pdns); - *pdns = Curl_dnsc_mk_addr(data, dns_queries, &addr, hostname, port); + *pdns = Curl_dnsc_mk_addr(data, dns_queries, &addr, peer); if(!*pdns) result = CURLE_OUT_OF_MEMORY; } @@ -701,8 +702,7 @@ out: static CURLcode hostip_resolv(struct Curl_easy *data, uint8_t dns_queries, - const char *hostname, - uint16_t port, + struct Curl_peer *peer, uint8_t transport, bool for_proxy, timediff_t timeout_ms, @@ -724,40 +724,40 @@ static CURLcode hostip_resolv(struct Curl_easy *data, #endif /* We should intentionally error and not resolve .onion TLDs */ - hostname_len = strlen(hostname); + hostname_len = strlen(peer->hostname); DEBUGASSERT(hostname_len); if(hostname_len >= 7 && - (curl_strequal(&hostname[hostname_len - 6], ".onion") || - curl_strequal(&hostname[hostname_len - 7], ".onion."))) { + (curl_strequal(&peer->hostname[hostname_len - 6], ".onion") || + curl_strequal(&peer->hostname[hostname_len - 7], ".onion."))) { failf(data, "Not resolving .onion address (RFC 7686)"); goto out; } #ifdef DEBUGBUILD CURL_TRC_DNS(data, "[%s] hostip_resolv(%s:%u)", - Curl_resolv_query_str(dns_queries), hostname, port); + Curl_resolv_query_str(dns_queries), peer->hostname, peer->port); if((CURL_DNSQ_IS_ADDR(dns_queries) == CURL_DNSQ_AAAA) && getenv("CURL_DBG_RESOLV_FAIL_IPV6")) { infof(data, "DEBUG fail ipv6 resolve"); - result = hostip_resolv_failed(data, hostname, for_proxy); + result = hostip_resolv_failed(data, peer, for_proxy); goto out; } #endif /* Let's check our DNS cache first */ - result = Curl_dnscache_get(data, dns_queries, hostname, port, pdns); + result = Curl_dnscache_get(data, dns_queries, peer, pdns); if(*pdns) { - infof(data, "Hostname %s was found in DNS cache", hostname); + infof(data, "Hostname %s was found in DNS cache", peer->hostname); result = CURLE_OK; } else if(result) { infof(data, "Negative DNS entry"); - result = hostip_resolv_failed(data, hostname, for_proxy); + result = hostip_resolv_failed(data, peer, for_proxy); } else { /* No luck, we need to start resolving. */ cache_dns = TRUE; - result = hostip_resolv_start(data, dns_queries, hostname, port, - transport, for_proxy, timeout_ms, allowDOH, + result = hostip_resolv_start(data, dns_queries, peer, transport, + for_proxy, timeout_ms, allowDOH, presolv_id, pdns, &negative); CURL_TRC_DNS(data, "[%s] hostip_resolv started -> %d", Curl_resolv_query_str(dns_queries), (int)result); @@ -768,12 +768,13 @@ out: Curl_dns_entry_unlink(data, pdns); if(IS_RESOLV_FAIL(result)) { if(cache_dns && negative) - Curl_dnscache_add_negative(data, dns_queries, hostname, port); + Curl_dnscache_add_negative(data, dns_queries, peer); if(dns_queries & (CURL_DNSQ_A|CURL_DNSQ_AAAA)) - failf(data, "Could not resolve: %s:%u", hostname, port); + failf(data, "Could not resolve: %s:%u", peer->hostname, peer->port); } else { - failf(data, "Error %d resolving %s:%u", (int)result, hostname, port); + failf(data, "Error %d resolving %s:%u", + (int)result, peer->hostname, peer->port); } } else if(cache_dns && *pdns) { @@ -792,13 +793,19 @@ CURLcode Curl_resolv_blocking(struct Curl_easy *data, uint8_t transport, struct Curl_dns_entry **pdns) { + struct Curl_peer *peer = NULL; CURLcode result; uint32_t resolv_id; + DEBUGASSERT(hostname && *hostname); *pdns = NULL; + + result = Curl_peer_create(data, data->conn->scheme, hostname, port, &peer); + if(result) + goto out; + /* We cannot do a blocking resolve using DoH currently */ - result = hostip_resolv(data, dns_queries, - hostname, port, transport, FALSE, 0, FALSE, + result = hostip_resolv(data, dns_queries, peer, transport, FALSE, 0, FALSE, &resolv_id, pdns); switch(result) { case CURLE_OK: @@ -814,6 +821,9 @@ CURLcode Curl_resolv_blocking(struct Curl_easy *data, default: break; } + +out: + Curl_peer_unlink(&peer); return result; } @@ -831,8 +841,7 @@ CURL_NORETURN static void alarmfunc(int sig) static CURLcode resolv_alarm_timeout(struct Curl_easy *data, uint8_t dns_queries, - const char *hostname, - uint16_t port, + struct Curl_peer *peer, uint8_t transport, bool for_proxy, timediff_t timeout_ms, @@ -852,7 +861,7 @@ static CURLcode resolv_alarm_timeout(struct Curl_easy *data, volatile unsigned int prev_alarm = 0; CURLcode result; - DEBUGASSERT(hostname && *hostname); + DEBUGASSERT(peer->hostname && *peer->hostname); DEBUGASSERT(timeout_ms > 0); DEBUGASSERT(!data->set.no_signal); #ifndef CURL_DISABLE_DOH @@ -913,7 +922,7 @@ static CURLcode resolv_alarm_timeout(struct Curl_easy *data, /* Perform the actual name resolution. This might be interrupted by an * alarm if it takes too long. */ - result = hostip_resolv(data, dns_queries, hostname, port, transport, + result = hostip_resolv(data, dns_queries, peer, transport, for_proxy, timeout_ms, FALSE, presolv_id, entry); clean_up: @@ -967,27 +976,26 @@ clean_up: #ifdef USE_UNIX_SOCKETS static CURLcode resolv_unix(struct Curl_easy *data, - const char *unix_path, - bool abstract_path, + struct Curl_peer *peer, struct Curl_dns_entry **pdns) { struct Curl_addrinfo *addr; CURLcode result; - DEBUGASSERT(unix_path); + DEBUGASSERT(peer->unix_socket); *pdns = NULL; - result = Curl_unix2addr(unix_path, abstract_path, &addr); + result = Curl_unix2addr(peer->hostname, (bool)peer->abstract_uds, &addr); if(result) { if(result == CURLE_TOO_LARGE) { /* Long paths are not supported for now */ - failf(data, "Unix socket path too long: '%s'", unix_path); + failf(data, "Unix socket path too long: '%s'", peer->hostname); result = CURLE_COULDNT_RESOLVE_HOST; } return result; } - *pdns = Curl_dnsc_mk_addr(data, 0, &addr, NULL, 0); + *pdns = Curl_dnsc_mk_addr(data, 0, &addr, peer); return *pdns ? CURLE_OK : CURLE_OUT_OF_MEMORY; } #endif /* USE_UNIX_SOCKETS */ @@ -1032,10 +1040,10 @@ CURLcode Curl_resolv(struct Curl_easy *data, #ifdef USE_UNIX_SOCKETS if((dns_queries & CURL_DNSQ_ADDR) && peer->unix_socket) - return resolv_unix(data, peer->hostname, (bool)peer->abstract_uds, pdns); + return resolv_unix(data, peer, pdns); #else if(peer->unix_socket) - return hostip_resolv_failed(data, peer->hostname, for_proxy); + return hostip_resolv_failed(data, peer, for_proxy); #endif #ifdef USE_ALARM_TIMEOUT @@ -1045,10 +1053,8 @@ CURLcode Curl_resolv(struct Curl_easy *data, timeout_ms = 0; } if(timeout_ms && !Curl_doh_wanted(data)) { - return resolv_alarm_timeout(data, dns_queries, - peer->hostname, peer->port, - transport, for_proxy, timeout_ms, - presolv_id, pdns); + return resolv_alarm_timeout(data, dns_queries, peer, transport, + for_proxy, timeout_ms, presolv_id, pdns); } } #endif /* !USE_ALARM_TIMEOUT */ @@ -1058,9 +1064,8 @@ CURLcode Curl_resolv(struct Curl_easy *data, infof(data, "timeout on name lookup is not supported"); #endif - return hostip_resolv(data, dns_queries, peer->hostname, peer->port, - transport, for_proxy, timeout_ms, TRUE, presolv_id, - pdns); + return hostip_resolv(data, dns_queries, peer, transport, + for_proxy, timeout_ms, TRUE, presolv_id, pdns); } #ifdef USE_CURL_ASYNC @@ -1087,11 +1092,10 @@ CURLcode Curl_resolv_take_result(struct Curl_easy *data, uint32_t resolv_id, return CURLE_FAILED_INIT; /* check if we have the name resolved by now (from someone else) */ - result = Curl_dnscache_get(data, async->dns_queries, - async->hostname, async->port, pdns); + result = Curl_dnscache_get(data, async->dns_queries, async->peer, pdns); if(*pdns) { /* Tell a possibly async resolver we no longer need the results. */ - infof(data, "Hostname '%s' was found in DNS cache", async->hostname); + infof(data, "Hostname '%s' was found in DNS cache", async->peer->hostname); Curl_async_shutdown(data, async); return CURLE_OK; } @@ -1115,14 +1119,14 @@ CURLcode Curl_resolv_take_result(struct Curl_easy *data, uint32_t resolv_id, nothing about the name and would poison the cache for every transfer using it. */ if(async->negative_answer) - Curl_dnscache_add_negative(data, async->dns_queries, - async->hostname, async->port); + Curl_dnscache_add_negative(data, async->dns_queries, async->peer); if(async->dns_queries & (CURL_DNSQ_A|CURL_DNSQ_AAAA)) - failf(data, "Could not resolve: %s:%u", async->hostname, async->port); + failf(data, "Could not resolve: %s:%u", + async->peer->hostname, async->peer->port); } else if(result) { failf(data, "Error %d resolving %s:%u", - (int)result, async->hostname, async->port); + (int)result, async->peer->hostname, async->peer->port); } return result; }