4.1 How a Question Is Answered

Every door ends here. The native socket's resolve, lookup and reverse, and every stub query, become one or more tasks, and each task takes the same path.

4.1.1 The path #

  1. Parse. The name is parsed from presentation form. A trailing dot makes no difference. Escapes are not interpreted; a label is the bytes between dots. A name with an empty label, a label over 63 bytes, or more than 255 bytes on the wire does not parse, and the task is answered notfound at once.
  2. Synthetic names. The name as asked is checked against the synthetic names (§4.2). A match answers the task.
  3. Candidates. The name becomes its list of candidates (§4.3). An empty list — a single label with no applicable search domain — answers the task notfound.
  4. Routing. Each candidate in turn is routed to one scope (§4.4). When no scope can take it, the task is answered unavailable.
  5. The cache. Unless the request asked to bypass the cache, the cache is consulted under that scope (§4.5).
  6. The network. Otherwise the candidate is sent upstream (§4.6 to §4.8).
  7. The next candidate. A notfound for a candidate — from the cache or from a server — moves to the next candidate when there is one. Any other result answers the task.
  8. The last candidate. When the last candidate is notfound, the task is answered notfound.

4.1.2 The empty name is the root #

An empty name, or . alone, parses as the root. The root is not a single label, so it is not expanded (§4.3): it is its own one candidate, routed and asked like any other name.

4.1.3 Each candidate is routed separately #

Each candidate is routed on its own, so the expansions of one single label can go to different scopes. Each has its own attempt budget (§4.6).

4.1.4 What each way out reports #

Ends atOutcomesourceserverinterfacercode
Name does not parsenotfoundlocalnilnil0
Synthetic nameper §4.2synthetic or hostsnilnil0
No candidatesnotfoundlocalnilnil0
No scope can take the candidateunavailablelocalnilnil0
Cache hitas cachedcachethe server whose reply was cachedthe scope's interfacethe cached reply's response code
A server's replyfound or notfounddnsthe serverthe scope's interfacethe server's response code
Every candidate notfoundnotfoundas the last candidate's cache hit or server's reply, in the two rows aboveas that rowas that rowas that row
Attempts exhaustedunavailablelocalnilthe scope's interface0
No servers left in the scopeunavailablelocalnilnil0
In-flight ceiling reachedunavailablelocalnilnil0

A single label whose every expansion came back NXDOMAIN from a server therefore reports dns, the server that answered the last candidate, that candidate's scope's interface, and response code 3; when the last candidate's NXDOMAIN came from the cache, it reports cache with the cached server and code.

4.1.4.1 Answers from the fallback scope #

interface is nil for every answer from the fallback scope, which has no interface: its cache hits, its servers' replies and its exhausted attempts alike.

4.1.4.2 Validation #

validation is unvalidated in every case: resolvd performs no DNSSEC validation (PSPU §6.6).

4.1.5 What an answer carries #

An answer's records are the answer-section records of the reply that decided it, after the filtering of §4.8, or the synthetic records of §4.2. The engine also carries the candidate the answer was found at; the stub door uses it to add a CNAME (§6.2) and lookup uses it as the start of its CNAME chase (§4.9).

4.1.6 An asker that leaves #

While a native or stub TCP question is waiting for the engine, its stream is polled for hangup and errors. A definite hangup, error or invalid socket abandons the question before ready upstream replies are processed: all of its transactions are cancelled, including both families of an any lookup. Other questions continue normally.

Replies to cancelled transactions are ignored; they do not populate the cache. Answers already cached before cancellation remain cached.

An abandoned question is removed from the waiting clients and no answer write is attempted for it. Cancellation does not count as an upstream failure, refusal or answer.

A write-half-close is supported: the client may stop sending while still waiting for its answer. Readable end of file alone therefore does not cancel a question. In particular, a TCP FIN cannot reliably distinguish a complete departure from a write-half-close. Without a definite hangup or error, the request retains its admission slot and runs through the usual engine attempts and deadlines. UDP has no disconnect notification.

Edit this page