From: Stefan Eissing Date: Mon, 11 Aug 2025 09:39:03 +0000 (+0200) Subject: resolving: dns error tracing X-Git-Tag: curl-8_16_0~201 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9cc4e24ad92f281b13700f44fe6ce4138812226b;p=thirdparty%2Fcurl.git resolving: dns error tracing * Add more tracing information to c-ares errors. * remove CURL_ASYNC_SUCCESS, rename `ares->last_status` to `ares->ares_status`. Give trace explanation for "common" errors * add ares "csv" information to tracing on failure * DoH: invoke `Curl_resolver_error()` on failure to populate error buf Closes #18247 --- diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c index 815d7ab57f..bb3f4af0b9 100644 --- a/lib/asyn-ares.c +++ b/lib/asyn-ares.c @@ -337,28 +337,55 @@ CURLcode Curl_async_is_resolved(struct Curl_easy *data, Curl_resolv_unlink(data, &data->state.async.dns); data->state.async.done = TRUE; result = ares->result; - if(ares->last_status == CURL_ASYNC_SUCCESS && !result) { + if(ares->ares_status == ARES_SUCCESS && !result) { data->state.async.dns = Curl_dnscache_mk_entry(data, ares->temp_ai, data->state.async.hostname, 0, data->state.async.port, FALSE); ares->temp_ai = NULL; /* temp_ai now owned by entry */ #ifdef HTTPSRR_WORKS - if(data->state.async.dns) { - struct Curl_https_rrinfo *lhrr = Curl_httpsrr_dup_move(&ares->hinfo); - if(!lhrr) - result = CURLE_OUT_OF_MEMORY; - else - data->state.async.dns->hinfo = lhrr; - } + if(data->state.async.dns) { + struct Curl_https_rrinfo *lhrr = Curl_httpsrr_dup_move(&ares->hinfo); + if(!lhrr) + result = CURLE_OUT_OF_MEMORY; + else + data->state.async.dns->hinfo = lhrr; + } #endif if(!result && data->state.async.dns) result = Curl_dnscache_add(data, data->state.async.dns); } /* if we have not found anything, report the proper * CURLE_COULDNT_RESOLVE_* code */ - if(!result && !data->state.async.dns) + if(!result && !data->state.async.dns) { result = Curl_resolver_error(data); + if(ares->ares_status != ARES_SUCCESS) { + const char *msg; + switch(ares->ares_status) { + case ARES_ECONNREFUSED: + msg = "connection to DNS server refused"; + break; + case ARES_ETIMEOUT: + msg = "query to DNS server timed out"; + break; + case ARES_ENOTFOUND: + msg = "DNS server did not find the address"; + break; + case ARES_EREFUSED: + msg = "DNS server refused query"; + break; + default: + msg = "resolve failed"; + break; + } + CURL_TRC_DNS(data, "asyn-ares: %s (error %d)", msg, ares->ares_status); +#if ARES_VERSION >= 0x011800 /* >= v1.24.0 */ + CURL_TRC_DNS(data, "asyn-ares config: %s", + ares_get_servers_csv(ares->channel)); +#endif + } + } + if(result) Curl_resolv_unlink(data, &data->state.async.dns); *dns = data->state.async.dns; @@ -511,14 +538,14 @@ static void async_ares_hostbyname_cb(void *user_data, be valid so only defer it when we know the 'status' says its fine! */ return; - if(CURL_ASYNC_SUCCESS == status) { - ares->last_status = status; /* one success overrules any error */ + if(ARES_SUCCESS == status) { + ares->ares_status = status; /* one success overrules any error */ async_addr_concat(&ares->temp_ai, Curl_he2ai(hostent, data->state.async.port)); } - else if(ares->last_status != ARES_SUCCESS) { - /* no success so far, remember error */ - ares->last_status = status; + else if(ares->ares_status != ARES_SUCCESS) { + /* no success so far, remember last error */ + ares->ares_status = status; } ares->num_pending--; @@ -666,21 +693,22 @@ async_ares_node2addr(struct ares_addrinfo_node *node) } static void async_ares_addrinfo_cb(void *user_data, int status, int timeouts, - struct ares_addrinfo *result) + struct ares_addrinfo *ares_ai) { struct Curl_easy *data = (struct Curl_easy *)user_data; struct async_ares_ctx *ares = &data->state.async.ares; (void)timeouts; - CURL_TRC_DNS(data, "asyn-ares: addrinfo callback, status=%d", status); - if(ARES_SUCCESS == status) { - ares->temp_ai = async_ares_node2addr(result->nodes); - ares->last_status = CURL_ASYNC_SUCCESS; - ares_freeaddrinfo(result); + if(ares->ares_status != ARES_SUCCESS) /* do not overwrite success */ + ares->ares_status = status; + if(status == ARES_SUCCESS) { + ares->temp_ai = async_ares_node2addr(ares_ai->nodes); + ares_freeaddrinfo(ares_ai); } ares->num_pending--; - CURL_TRC_DNS(data, "ares: addrinfo done, status=%d, pending=%d, " - "addr=%sfound", - status, ares->num_pending, ares->temp_ai ? "" : "not "); + CURL_TRC_DNS(data, "ares: addrinfo done, query status=%d, " + "overall status=%d, pending=%d, addr=%sfound", + status, ares->ares_status, ares->num_pending, + ares->temp_ai ? "" : "not "); } #endif @@ -736,7 +764,8 @@ struct Curl_addrinfo *Curl_async_getaddrinfo(struct Curl_easy *data, return NULL; /* initial status - failed */ - ares->last_status = ARES_ENOTFOUND; + ares->ares_status = ARES_ENOTFOUND; + ares->result = CURLE_OK; #ifdef HAVE_CARES_GETADDRINFO { diff --git a/lib/asyn-thrdd.c b/lib/asyn-thrdd.c index 82ce2b0469..509ec427a8 100644 --- a/lib/asyn-thrdd.c +++ b/lib/asyn-thrdd.c @@ -173,7 +173,7 @@ addr_ctx_create(const char *hostname, int port, goto err_exit; } #endif - addr_ctx->sock_error = CURL_ASYNC_SUCCESS; + addr_ctx->sock_error = 0; /* Copying hostname string because original can be destroyed by parent * thread during gethostbyname execution. diff --git a/lib/asyn.h b/lib/asyn.h index 69aeb8b482..de7cd8406b 100644 --- a/lib/asyn.h +++ b/lib/asyn.h @@ -143,7 +143,7 @@ struct async_ares_ctx { int num_pending; /* number of outstanding c-ares requests */ struct Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares parts */ - int last_status; + int ares_status; /* ARES_SUCCESS, ARES_ENOTFOUND, etc. */ CURLcode result; /* CURLE_OK or error handling response */ #ifndef HAVE_CARES_GETADDRINFO struct curltime happy_eyeballs_dns_time; /* when this timer started, or 0 */ diff --git a/lib/doh.c b/lib/doh.c index ac9743b0a9..030b026fe2 100644 --- a/lib/doh.c +++ b/lib/doh.c @@ -1249,8 +1249,8 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data, p->dnstype, &de); #ifndef CURL_DISABLE_VERBOSE_STRINGS if(rc[slot]) { - infof(data, "DoH: %s type %s for %s", doh_strerror(rc[slot]), - doh_type2name(p->dnstype), dohp->host); + CURL_TRC_DNS(data, "DoH: %s type %s for %s", doh_strerror(rc[slot]), + doh_type2name(p->dnstype), dohp->host); } #endif } /* next slot */ diff --git a/lib/hostip.c b/lib/hostip.c index 6ad961ff87..74ed5c0277 100644 --- a/lib/hostip.c +++ b/lib/hostip.c @@ -1547,6 +1547,8 @@ CURLcode Curl_resolv_check(struct Curl_easy *data, #ifndef CURL_DISABLE_DOH if(data->conn->bits.doh) { result = Curl_doh_is_resolved(data, dns); + if(result) + Curl_resolver_error(data); } else #endif diff --git a/lib/hostip.h b/lib/hostip.h index 3743b73961..633157782b 100644 --- a/lib/hostip.h +++ b/lib/hostip.h @@ -47,8 +47,6 @@ #define CURL_TIMEOUT_RESOLVE 300 /* when using asynch methods, we allow this many seconds for a name resolve */ -#define CURL_ASYNC_SUCCESS CURLE_OK - struct addrinfo; struct hostent; struct Curl_easy;