Open-Source Wikis

/

curl

/

Systems

/

DNS resolution

curl/curl

DNS resolution

Active contributors: Daniel Stenberg, Stefan Eissing, Viktor Szakats

Purpose

curl resolves hostnames in one of four ways, all sharing a single in-memory cache. The frontend is lib/hostip.c; the backends are lib/asyn-base.c (async dispatch), lib/asyn-ares.c (c-ares), lib/asyn-thrdd.c (thread pool), and lib/doh.c (DNS-over-HTTPS). The resolved-address cache is lib/dnscache.c.

Key abstractions

Symbol File Description
struct Curl_dns_entry lib/hostip.h A cached set of addresses for one (hostname, port) pair
struct Curl_addrinfo lib/curl_addrinfo.h Linked list of addresses, replaces getaddrinfo for portability
struct Curl_async lib/asyn.h Per-handle async-resolver state
Curl_resolv() lib/hostip.c The "resolve this name" entry point
Curl_resolv_pollset() lib/hostip.c Tells the multi loop which FDs to poll while resolving
Curl_dnscache_* lib/dnscache.c Insert / lookup / evict cached entries
Curl_doh() lib/doh.c DoH worker: builds an HTTPS request, parses RFC 8484 wire format

Resolver selection

Selection is compile-time via configure/CMake flags:

Build flag Backend Notes
--enable-ares / CURL_USE_ARES c-ares Fully async; no extra threads. lib/asyn-ares.c
--enable-threaded-resolver POSIX thread pool One thread per pending resolve. lib/asyn-thrdd.c
(default if neither) Synchronous getaddrinfo Blocks the calling thread. lib/hostip4.c, lib/hostip6.c
Runtime DNS-over-HTTPS Activated via CURLOPT_DOH_URL. lib/doh.c

Most modern builds use threaded-resolver because it works on every platform and integrates with the multi loop without external dependencies.

How it works

sequenceDiagram
    participant Multi
    participant Hostip as hostip.c
    participant Cache as dnscache.c
    participant Async as asyn-thrdd / asyn-ares
    participant DoH as doh.c
    Multi->>Hostip: Curl_resolv("example.com",443)
    Hostip->>Cache: lookup
    alt cache hit
      Cache-->>Hostip: entry
      Hostip-->>Multi: ready
    else cache miss
      alt CURLOPT_DOH_URL set
        Hostip->>DoH: spawn private easy handle
        DoH-->>Hostip: RFC 8484 reply parsed
      else
        Hostip->>Async: kickoff
      end
      Multi->>Multi: state = MSTATE_RESOLVING
      Note over Multi,Async: each tick, hostip checks if async finished
      Async-->>Hostip: addresses
      Hostip->>Cache: insert
      Hostip-->>Multi: ready
    end

While MSTATE_RESOLVING, the resolver-specific Curl_resolv_pollset reports the FDs the multi loop should poll (c-ares' control socket, the DoH transfer's socket, or none for the threaded resolver). Once the resolver returns, Curl_dnscache_insert puts the entry in the cache and the connection setup proceeds to MSTATE_CONNECTING.

DoH

DoH is unusual: instead of a system resolver call, libcurl issues a real HTTPS request to a DoH server (like https://dns.google/dns-query) for the resolution. The implementation in lib/doh.c reuses the regular libcurl easy/multi machinery: it allocates a private easy handle, sends the RFC 8484 wire-format query, parses the response, and feeds the addresses into the standard cache.

This means a DoH-resolved host itself still has to be resolved — the DoH server hostname is resolved once (synchronously or via the configured resolver) and then the connection to it is reused for all subsequent DoH lookups via the conn cache.

DNS cache

lib/dnscache.c is a hash from (host, port) to Curl_dns_entry. Entries have a TTL (CURLOPT_DNS_CACHE_TIMEOUT, default 60 seconds). Lookups are constant-time; eviction is lazy (checked on lookup) plus explicit (curl_share_cleanup).

The cache is shareable across multi handles via curl_share_setopt(sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS) — see Connection management.

fake_addrinfo (lib/fake_addrinfo.c) supplies a synthetic resolver result for --resolve and CURLOPT_RESOLVE overrides, e.g. --resolve example.com:443:127.0.0.1. These pre-populate the cache and never expire until curl_share_cleanup or end of run.

HTTPS RR

Recent versions parse HTTPS resource records (lib/httpsrr.c) so that, for example, an HTTPS RR can advertise an alternative HTTP/3 endpoint or ECH support. The parser is invoked alongside A/AAAA lookups and feeds into the connection setup.

Integration points

  • Transfer engine: MSTATE_RESOLVING polls Curl_resolv_pollset. See Transfer engine.
  • Connection cache: resolved entries are looked up before connection-cache lookup so HSTS/alt-svc can rewrite the destination first. See Connection management.
  • Share handle: CURL_LOCK_DATA_DNS shares the cache between handles.
  • Happy Eyeballs: cf-ip-happy uses both v4 and v6 addresses returned by the resolver. See Connection filters.

Entry points for modification

  • New resolver backend → add a new lib/asyn-*.c implementing Curl_resolver_* functions; plumb selection in lib/curl_setup.h and the build files.
  • Different cache eviction policy → Curl_dnscache_* in lib/dnscache.c.
  • Add or fix a DoH transport detail → lib/doh.c. Note that DoH responses use the same code path as any other HTTPS request: a bug there can manifest as a DoH bug.
  • HTTPS RR parsing → lib/httpsrr.c. The integration point with the connection setup is in lib/url.c.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

DNS resolution – curl wiki | Factory