dnscache: use Curl_peer in resolve and dnscache operations
No binary (build failed)
—
(log yok)
| @@ -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 */ | |
| @@ -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; | |
| } | |
| @@ -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 | |
| * <https://sourceware.org/bugzilla/show_bug.cgi?id=14413> | |
| * 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 */ | |
| @@ -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, | |
| @@ -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); | |
| } | |
| @@ -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() | |
| @@ -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, | |
| @@ -60,32 +60,58 @@ | |
| #define MAX_DNS_CACHE_SIZE 29999 | |
| - | static void dnscache_entry_free(struct Curl_dns_entry *dns) |
| + | 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) |
| { | |
| - | Curl_freeaddrinfo(dns->addr); |
| - | #ifdef USE_HTTPSRR |
| - | Curl_httpsrr_destroy(dns->hinfo); |
| - | #endif |
| - | curlx_free(dns); |
| + | 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 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; |
| + | 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 */ | |
| - | buf[0] = type; |
| - | Curl_strntolower(buf + 1, name, len); |
| - | return curl_msnprintf(&buf[len + 1], 7, ":%u", port) + len + 1; |
| + | 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); |
| + | #ifdef USE_HTTPSRR |
| + | Curl_httpsrr_destroy(dns->hinfo); |
| + | #endif |
| + | curlx_free(dns); |
| } | |
| struct dnscache_prune_data { | |
| @@ -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) |
| - | { |
| - | struct Curl_dns_entry *dns = dnsc_entry_create( |
| - | data, hostname, hostname ? strlen(hostname) : 0, port, FALSE); |
| + | uint8_t dns_queries, |
| + | struct Curl_addrinfo **paddr1, |
| + | struct Curl_addrinfo **paddr2, |
| + | struct Curl_peer *peer) |
| + | { |
| + | 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, "*")) { | |
| @@ -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. | |
| @@ -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; | |
| @@ -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; |
| }; | |
| /* | |
| @@ -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; | |
| } | |