Nameserver Resolution Reference

Testcase specifications refer to several distinct views of the nameservers that serve a zone. The views are not interchangeable; each testcase picks the view that matches what is actually being verified.

This page is the single source of truth for those names. Testcase specs link symbol mentions back to the matching section below.

The functions in this page live in engine/nsdiscovery except Zone.GlueNames and Zone.ApexNSNames, which are methods on *zone.Zone in engine/zone .

A nameserver address in IPv4-mapped IPv6 form (RFC 4291 section 2.5.5.2) is queried as the IPv4 address it carries: the IPv4 switch of the profile governs it, and it shares that address’s cache.

GlueNameservers

Nameservers from the parent’s delegation glue, as name+address pairs. The parent’s claim about who serves the zone.

func GlueNameservers(ctx context.Context, z *zone.Zone) ([]nameserver.Nameserver, error)

Equivalent to z.Glue(ctx) with a nil-zone guard. Returns an error if z is nil; otherwise propagates errors from the underlying zone lookup.

Source: engine/nsdiscovery/nsdiscovery.go.

GlueNames

Glue NS names from the parent zone, names only.

func (z *Zone) GlueNames(ctx context.Context) ([]dnsname.Name, error)

Method on *zone.Zone. Returns the cached glue names for the zone or fetches them from the parent on first call.

Source: engine/zone/zone.go.

ApexNameservers

Nameservers resolved from the child zone’s own apex NS RRset, as name+address pairs. The child’s claim about itself.

func ApexNameservers(ctx context.Context, z *zone.Zone) ([]nameserver.Nameserver, error)

Equivalent to z.NS(ctx) with a nil-zone guard. For in-domain names this resolves via the zone’s own glue; not-in-domain names are resolved via the recursor.

Source: engine/nsdiscovery/nsdiscovery.go.

ApexNSNames

Apex NS names from the zone itself, names only.

func (z *Zone) ApexNSNames(ctx context.Context) ([]dnsname.Name, error)

Method on *zone.Zone. Returns the union of NS names reported at the zone apex by every authoritative server, deduplicated case-insensitively and sorted. Differs from NSNames, which stops at the first successful response.

Source: engine/zone/zone.go.

AllNameservers

Deduplicated union of GlueNameservers and ApexNameservers. The zone’s combined view, as name+address pairs.

func AllNameservers(ctx context.Context, z *zone.Zone) ([]nameserver.Nameserver, error)

The dedup key is the lower-cased name/address string, so the same name with two different addresses is kept as two entries. Output is sorted by that same key.

Source: engine/nsdiscovery/nsdiscovery.go.

AllNSNames

Deduplicated union of Zone.GlueNames and Zone.ApexNSNames. The zone’s combined view, names only.

func AllNSNames(ctx context.Context, z *zone.Zone) ([]dnsname.Name, error)

Names are lowercased and sorted lexicographically. If either underlying call returns an error, the error is propagated and no result is returned.

Source: engine/nsdiscovery/nsdiscovery.go.

DelegationNameservers

Parent-queried delegation view of the zone’s nameservers, with domain-aware address resolution. Appropriate for delegation consistency checks that need the parent’s authoritative answer.

func DelegationNameservers(ctx context.Context, z *zone.Zone) ([]NSItem, error)

Returns NSItem values pairing names with addresses from in-domain glue (if present) and not-in-domain recursive resolution (for not-in-domain names). Result is sorted and deduplicated.

An unreachable delegation chain returns an empty slice with a nil error; callers must check len().

Source: engine/nsdiscovery/delegation.go.

ZoneNameservers

Authoritative AA NS at the apex, paired with in-domain and not-in-domain addresses via recursion.

func ZoneNameservers(ctx context.Context, z *zone.Zone) ([]NSItem, error)

Queries the delegation servers for the apex NS RRset, keeps only responses with AA set, and pairs the resulting names with addresses. Differs from DelegationNameservers in that the names come from the child zone’s own apex NS RRset, not the parent’s delegation. Useful for detecting lame delegations where parent and child disagree.

Source: engine/nsdiscovery/delegation.go.

ParentNameservers

The parent zone’s own nameservers, found by walking the delegation chain from the root down to the parent of z.

func ParentNameservers(ctx context.Context, z *zone.Zone) ([]nameserver.Nameserver, error)

Results are memoised in a Cache attached to the context via WithCache (one cache per engine run, isolated between runs). With no cache attached, every call re-walks the chain.

For the root zone and zones whose names appear in the recursor’s fake-address map (undelegated test setups), an empty slice and nil error are returned without caching.

If an intermediate name returns NXDOMAIN with AA set, the walker probes the same server once at z.Name and, if it answers with a referral (NS records for the child zone in the authority section), accepts that server as the parent. This handles the RFC 8020 contradiction where a parent denies an empty non-terminal but still holds a working delegation at the child. Without the probe, every NS in such a parent would be discarded and the delegation view exposed to downstream tests would be empty; Basic01 names the same condition with B01_PARENT_NXDOMAIN_HIDES_DELEGATION.

Source: engine/nsdiscovery/parent.go.

Fan-out Limits

A run bounds the nameserver names and addresses it takes from DNS responses, after RFC 1034 section 5.3.3, which requires a resolver to bound the packets it sends even when the data it follows is misconfigured. The bounds have no protocol counterpart; their values are implementation defined.

BoundValueSet
ns_names_per_zone32The NS names of one zone: GlueNames , ApexNSNames , the apex NS names of Zone.NS, a referral the recursor follows, an NS RRset of the parent walk, and the names of DelegationNameservers and ZoneNameservers .
addresses_per_ns16The addresses of one NS name, from glue or from address resolution.
addresses_per_run512The distinct nameserver addresses one run queries.

A set of names is lowercased and a set of addresses is taken as is; either set is deduplicated, sorted in byte order of the presentation form, and cut after the bound. A name or address past the cut is absent from the set and is not queried through it.

The run bound counts an address when the run first queries it, before any cache is read. A query to a further address is not sent and reads as no response. When the run queries in parallel, which addresses fall past this bound depends on the order of the queries.

When a bound cuts a set, the run logs LIMIT_REACHED in module SYSTEM at level NOTICE. The entry does not change the score. It is logged at most once per testcase, bound and name, in the testcase whose work first cuts the set; a set computed once per run reports its cut once.

ArgumentTypeMeaning
boundstringThe bound, as named in the table above or in DNSSEC Limits .
limitintThe value of the bound.
countintThe size of the set before the cut; for addresses_per_run, the bound plus one; for nsec3_iterations, the iteration count; for keys_per_tag, the DNSKEYs with the key tag and algorithm of the RRSIG; for rrsigs_per_rrset, the RRSIGs over the RRset.
domainstringThe zone whose names, or the NS name whose addresses, the bound cut; for addresses_per_run, the NS name of the first query not sent; for a DNSSEC bound, the zone under test.

Source: engine/nameserver/limits.go.

DNSSEC Limits

DNSSEC testcases log LIMIT_REACHED for the bounds below, each defined in the Implementation Notes of the testcases named, at most once per testcase and bound. The Edge Cases of each testcase state the effect on its verdicts.

BoundValueTestcases
nsec3_iterations50DNSSEC07, DNSSEC20, DNSSEC22
keys_per_tag4DNSSEC02, DNSSEC07, DNSSEC08, DNSSEC09, DNSSEC10, DNSSEC16, DNSSEC17, DNSSEC21, DNSSEC22, DNSSEC24
rrsigs_per_rrset8DNSSEC02, DNSSEC07, DNSSEC08, DNSSEC09, DNSSEC10, DNSSEC16, DNSSEC17, DNSSEC21, DNSSEC22, DNSSEC24