~/problems / Files & networks / DNS resolver

DNS resolution with CNAME cycles

hard 5 levels ~90 min Anthropic

Level 1 Direct lookups

Build a small DNS resolver on top of a record store.

records is a dict-like object mapping a name to a list of records, each a tuple (rtype, value, ttl), for example:

records = {
    "example.com": [("A", "93.184.216.34", 300), ("MX", "10 mail.example.com", 60)],
    "mail.example.com": [("A", "10.0.0.5", 300)],
}

Keys are already normalized (lowercase, no trailing dot). Read the store only with records.get(name), which returns the list or None. Tests use custom stores that count or delay these calls.

Implement Resolver(records, clock=time.monotonic) (the clock matters from level 4) with:

  • resolve(name, rtype="A") -> list[str]: the values of all records of type rtype at name, in stored order.
  • Normalize the queried name first: compare case-insensitively (lowercase it) and drop one trailing dot, so "Example.COM." means "example.com".
  • Raise NotFoundError if the name has no records, or none of type rtype.

The starter defines the exception classes; keep them. NotFoundError, CycleError and UpstreamError all subclass DNSError.

r = Resolver(records)
r.resolve("EXAMPLE.com.")          # ["93.184.216.34"]
r.resolve("example.com", "MX")     # ["10 mail.example.com"]
r.resolve("example.com", "AAAA")   # raises NotFoundError

Level 2 unlocks when level 1 passes.

Level 3 unlocks when level 2 passes.

Level 4 unlocks when level 3 passes.

Level 5 unlocks when level 4 passes.

Topic: DNS resolver. Recursive CNAME resolution, cycle detection, TTL cache.

0:00
Ctrl ' run · Ctrl ↵ submit
esc