We are going to (re)implement authoritative query logic for in memory data source. The currently used query logic is restricted due to the less smart nature of underlying data source (i.e., sqlite3) and is not suitable for in memory data source, which is expected to be optimized for performance and implements smartness inside it.

This is an initial "design" idea of the revised logic. We'll fix details as we implement them, so this is not a perfect, fixed design, but is provided to show our general ideas. Once we start the implementation, more detailed and complete design will be documented with the source code in the doxygen format, and this document will eventually be stale.

Background: BIND 9's query logic

BIND 9 implements generic query logic in bind9/bin/named/query.c:query_find(). It's "generic" in that the single function can support both authoritative and recursive (cache) cases, and also handles the case when recursion process is completed. It's carefully written and supports various protocol features and non protocol functionalities. But, partly due to the rich set of responsibilities, it's a very complicated, hard to understand function, consisting of 1374 lines of code, a very big switch, complicated process flow with goto's (including ones going backwards).

Overall approach and goals

The plan is to reuse the high level logic of BIND 9's query_find() with:

  • simplifying it
  • focusing on most common scenarios
  • and, as a result, improving performance in future versions (performance is not in the goal of initial work)


I can think of the following simplification:

  • (obviously) authoritative only
  • single zone only: do not chase CNAME targets in other zones; do not add additional RRs in other zones (this may change in future versions, but we can begin with this without losing lookup efficiency in the client in practice)
  • possibly replacing the switch-case with the command design pattern, or at least delegate the logic in each case block to another method

Then the implementation would generally look like this:

    result = zone_table.find(qname);
    while (keep_doing) {
        db_result =, qtype);
        switch (db_result) { // this could be a single dispatch of "command"
        case SUCCESS:
            // normal case: add result to answer section, fill in authority
            // and additional sections
        case DELEGATION:
            // add NS to authority section, fill in additional section
        case NXDOMAIN:
        case NXRRSET:
            // add SOA to authority section
        case CNAME:
        case DNAME:
            // replace qname, continue lookup (only in this case keep_doing
            // will be true)

Additional section processing

In BIND 9, additional section processing is very generalized and RR type-agnostic through a layer of abstractions. Generality is good, but it also makes the code unreadable, and causes performance bottleneck.

In reality, we can focus on the case of additional records for the NS and MX RRs, and handle other cases as corner cases, possible in less efficient way (and protocol-wise, we could even ignore some of other RRs that might involve additional section processing).

So my plan is to begin with focusing on NS (and then MX) explicitly as part of query logic. this may also help performance optimization in near future. we'll then consider generalization through additional features in the RRset and Rdata classes (like BIND 9 does).

Task plans for incremental development

Each sub task is intended to be completed in 1-2 days, and review should be pretty straightforward.

  1. look up the zone table (which fail) and simply return SERVFAIL. (the following tasks assume zone table lookup succeeds) (ideally the underlying in memory data source is ready for use at this point. but if not, we should be able to use a simple mock for testing)
  2. DB lookup succeeds. simply return it in the answer section
  3. DB lookup results in NXDOMAIN. simply return SOA in the authority section
  4. DB lookup results in NXRRSET. simply return SOA in the authority section
  5. Additional processing for NS
  6. support CNAME case
  7. support DNAME case
  8. support type ANY query


Once the basic logic is completed, we should implement more advanced features and/or minor cases, which include:

  • DNSSEC processing
  • special logic for DS query
  • duplicate RR suppression
  • generalize the logic so that we can use it with other data sources
  • and, eventually other advanced features such as ACL)

The current initial design does not fully take into account these points yet.

Last modified 8 years ago Last modified on Nov 29, 2010, 1:08:45 PM