~/problems / Files & networks / DNS resolver

Exact and wildcard records, most specific wins

easy ~15 min

A small hosting company serves every customer shop under *.shops.example, but a few shops have their own server, and the whole *.eu.shops.example region sits in another data centre. Their zone mixes exact records and wildcard records, and a name must be answered by the most specific record that covers it.

Implement lookup(name: str, records: dict[str, str]) -> str | None.

  • Names are lowercase labels joined by dots, like "cake.eu.shops.example".
  • A key in records is either an exact name, or a wildcard "*." + suffix (for example "*.shops.example"), mapping to an IP address string.
  • A wildcard *.S covers every name that ends with "." + S and has at least one label before it. So *.shops.example covers cake.shops.example and a.b.shops.example, but not shops.example itself.

Answer with:

  1. the exact record for name, if there is one;
  2. otherwise the covering wildcard with the longest suffix;
  3. otherwise None.
records = {
    "*.shops.example":      "10.0.0.1",
    "*.eu.shops.example":   "10.0.9.9",
    "bakery.shops.example": "10.0.0.50",
    "shops.example":        "10.0.0.2",
}
lookup("bakery.shops.example", records)     # "10.0.0.50"  exact
lookup("cake.shops.example", records)       # "10.0.0.1"   *.shops.example
lookup("cake.eu.shops.example", records)    # "10.0.9.9"   the longer wildcard wins
lookup("eu.shops.example", records)         # "10.0.0.1"   *.eu.shops.example needs a label before "eu"
lookup("shops.example", records)            # "10.0.0.2"
lookup("example", records)                  # None

The real zone has tens of thousands of records and gets tens of thousands of lookups, so don't scan every record per lookup; a name only has a handful of labels.

Show hint

split name on ".". Try records.get(name) first; then for i = 1, 2, ... try the wildcard "*." + ".".join(labels[i:]). The first hit is the longest suffix.

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

0:00
Ctrl ' run · Ctrl ↵ submit
esc