mirror of
https://github.com/curl/curl.git
synced 2026-07-31 11:38:06 +03:00
Merge b2f459ac85 into 1d7b8e6c29
This commit is contained in:
commit
a75e1f76fa
12 changed files with 344 additions and 344 deletions
|
|
@ -217,7 +217,6 @@ void Curl_async_ares_destroy(struct Curl_easy *data,
|
|||
ares->res_AAAA = NULL;
|
||||
}
|
||||
#ifdef USE_HTTPSRR
|
||||
curlx_safefree(ares->https_name);
|
||||
Curl_httpsrr_destroy(ares->hinfo);
|
||||
ares->hinfo = NULL;
|
||||
#endif
|
||||
|
|
@ -277,7 +276,7 @@ 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->peer);
|
||||
if(!dns) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
|
|
@ -286,8 +285,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, &ares->hinfo, async->peer);
|
||||
if(!dns) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
|
|
@ -349,22 +347,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,
|
||||
|
|
@ -375,17 +357,14 @@ const struct Curl_addrinfo *Curl_async_get_ai(struct Curl_easy *data,
|
|||
(void)data;
|
||||
switch(ai_family) {
|
||||
case AF_INET:
|
||||
if(ares->res_A)
|
||||
return async_ares_get_ai(ares->res_A, ai_family, index);
|
||||
break;
|
||||
return Curl_addrinfo_get(ares->res_A, ai_family, index);
|
||||
#ifdef USE_IPV6
|
||||
case AF_INET6:
|
||||
if(ares->res_AAAA)
|
||||
return async_ares_get_ai(ares->res_AAAA, ai_family, index);
|
||||
break;
|
||||
return Curl_addrinfo_get(ares->res_AAAA, ai_family, index);
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef USE_HTTPSRR
|
||||
|
|
@ -664,7 +643,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 +653,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 +668,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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -238,6 +238,7 @@ void Curl_async_destroy(struct Curl_easy *data,
|
|||
#ifndef CURL_DISABLE_DOH
|
||||
Curl_doh_cleanup(data, async);
|
||||
#endif
|
||||
Curl_peer_unlink(&async->peer);
|
||||
curlx_safefree(async);
|
||||
}
|
||||
}
|
||||
|
|
@ -258,7 +259,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -216,41 +216,47 @@ 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,7 +296,6 @@ 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);
|
||||
|
|
@ -607,7 +612,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 +681,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;
|
||||
}
|
||||
|
||||
|
|
@ -892,7 +897,7 @@ CURLcode Curl_async_take_result(struct Curl_easy *data,
|
|||
data, async->dns_queries,
|
||||
thrdd->res_A ? &thrdd->res_A->res : NULL,
|
||||
thrdd->res_AAAA ? &thrdd->res_AAAA->res : NULL,
|
||||
async->hostname, async->port);
|
||||
async->peer);
|
||||
if(!dns) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
|
|
@ -902,8 +907,7 @@ 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);
|
||||
dns = Curl_dnsc_mk_https(data, &thrdd->rr.hinfo, async->peer);
|
||||
if(!dns) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
|
|
@ -928,26 +932,11 @@ 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,
|
||||
|
|
@ -959,12 +948,12 @@ const struct Curl_addrinfo *Curl_async_get_ai(struct Curl_easy *data,
|
|||
switch(ai_family) {
|
||||
case AF_INET:
|
||||
if(thrdd->res_A)
|
||||
return async_thrdd_get_ai(thrdd->res_A->res, ai_family, index);
|
||||
return Curl_addrinfo_get(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);
|
||||
return Curl_addrinfo_get(thrdd->res_AAAA->res, ai_family, index);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -118,9 +118,7 @@ struct async_ares_ctx {
|
|||
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
|
||||
|
|
@ -147,7 +145,6 @@ struct async_thrdd_ctx {
|
|||
#if defined(USE_HTTPSRR) && defined(USE_ARES)
|
||||
struct {
|
||||
ares_channel channel;
|
||||
char *https_name;
|
||||
struct Curl_https_rrinfo *hinfo;
|
||||
} rr;
|
||||
#endif
|
||||
|
|
@ -232,6 +229,7 @@ CURLcode Curl_async_pollset(struct Curl_easy *data,
|
|||
|
||||
struct Curl_resolv_async {
|
||||
struct Curl_resolv_async *next;
|
||||
struct Curl_peer *peer;
|
||||
#ifdef USE_RESOLV_ARES
|
||||
struct async_ares_ctx ares;
|
||||
#elif defined(USE_RESOLV_THREADED)
|
||||
|
|
@ -246,8 +244,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 +257,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,
|
||||
|
|
|
|||
37
lib/cf-dns.c
37
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
284
lib/dnscache.c
284
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, "*")) {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
29
lib/doh.c
29
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("_%d._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;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
160
lib/hostip.c
160
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,15 +500,10 @@ 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)ai_family;
|
||||
(void)index;
|
||||
if(!async)
|
||||
if(!async || !CURL_DNSQ_IS_ADDR(async->dns_queries))
|
||||
return NULL;
|
||||
if((ai_family == AF_INET) && !(async->dns_queries & CURL_DNSQ_A))
|
||||
return NULL;
|
||||
#ifdef USE_IPV6
|
||||
if((ai_family == AF_INET6) && !(async->dns_queries & CURL_DNSQ_AAAA))
|
||||
return NULL;
|
||||
#endif
|
||||
return Curl_async_get_ai(data, async, ai_family, index);
|
||||
}
|
||||
|
||||
|
|
@ -555,8 +546,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 +572,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 +627,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 +647,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 +662,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 +692,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 +714,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 +758,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 +783,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 +811,9 @@ CURLcode Curl_resolv_blocking(struct Curl_easy *data,
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
Curl_peer_unlink(&peer);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -831,8 +831,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 +851,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 +912,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 +966,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 +1030,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 +1043,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 +1054,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 +1082,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 +1109,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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue