]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
resolving: dns error tracing
authorStefan Eissing <stefan@eissing.org>
Mon, 11 Aug 2025 09:39:03 +0000 (11:39 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 11 Aug 2025 12:35:07 +0000 (14:35 +0200)
* 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

lib/asyn-ares.c
lib/asyn-thrdd.c
lib/asyn.h
lib/doh.c
lib/hostip.c
lib/hostip.h

index 815d7ab57fcdea84bab69c810ee8ed6fe4fba8c3..bb3f4af0b9d73c738827d31b26667f7bbadadcb3 100644 (file)
@@ -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
   {
index 82ce2b0469740d59a8ed50c83f622a1d13c0664f..509ec427a8777a0db2601d36b2112b4098fb2f08 100644 (file)
@@ -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.
index 69aeb8b4822a9a3a682f3b7e2df06c75fd832dde..de7cd8406bbbc60ed8ce5827a0c545da415216de 100644 (file)
@@ -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 */
index ac9743b0a9e2c8ac557499c9cae3a7279142a5a6..030b026fe2972445a090451c10a1e1586ee456fd 100644 (file)
--- 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 */
index 6ad961ff87fdb720e22eec2f08eeb80eef6f96d9..74ed5c027783cd0a7338876335e822300607481c 100644 (file)
@@ -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
index 3743b73961e1842867b0f1ebf94d449eddeca2c7..633157782b03882cdfb1d1106a19b3604f49112e 100644 (file)
@@ -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;