erldns_zone_cache (erldns v10.5.5)

View Source

A cache holding all of the zone data.

This module expects all input to use normalised (that is, lowercase) names, therefore it is the responsibility of the client to call this API with normalised names. This is to avoid normalising already normalised names, which can result into computational waste. As the client might need to call multiple points of this API, the client can ensure to normalise once and use multiple times.

Telemetry events

[erldns, zone, put]

Emitted at the end of put_zone/1, after the zone and its records have been inserted.

  • Measurements:
    count := 1
  • Metadata:
    zone_name := dns:dname()
    zone_labels := dns:labels()

[erldns, zone, delete]

Emitted at the end of delete_zone/1, after the zone, its records, and sync counters have been removed.

  • Measurements:
    count := 1
  • Metadata:
    zone_name := dns:dname()
    zone_labels := dns:labels()

Summary

Types

Classification of a name in a zone.

One-shot resolution result.

API: Boolean Operations

Check if the name is in any available zone.

Check if the exact record name is in the zone, without recursing nor traversing the zone tree.

Check if the record name, or any wildcard or parent wildcard, is in the zone.

Check if the record name, or any wildcard, or parent wildcard, or descendant, is in the zone.

Single-pass classification of how a name exists in the zone.

API: Lookups

Find an authoritative zone for a given qname.

Find an authoritative zone for a given qname and qtype.

Get the list of NS and glue records for the given name.

Get the list of NS and glue records for the given name.

Return the record set for the given dname.

Return the record set for the given dname in the given zone.

Get all records for the given type and given name.

Get all records for the given name and type in the given zone.

Return matching records of the given type, or a status when there are none.

Return the entire subtree at the given dname: all records at that node and at any descendant.

Return matching records or a status when there are none.

Return records for the given dname or at any parent that has a wildcard.

Return records for the given dname or at any parent that has a wildcard or exact records.

Return current sync counter

Get all records for the given zone.

Get a zone for the specific name.

API: Mutations

Remove a zone from the cache without waiting for a response.

Put a name and its records into the cache, along with a SHA which can be used to determine if the zone requires updating.

Given a zone name, list of records, and a digest, update the zone metadata in cache.

API: Utilities

Return a list of tuples with each tuple as a name and the version SHA for the zone.

Types

existence_type()

-type existence_type() :: ent | nxdomain | exact | wildcard.

Classification of a name in a zone.

It can be:

  • exact (records at node)
  • wildcard (matched by a parent wildcard)
  • ent (empty non-terminal)
  • or nxdomain (not in zone)

resolved_records()

-type resolved_records() :: ent | nxdomain | {exact, [dns:rr()]} | {wildcard, [dns:rr()]}.

One-shot resolution result.

It can be:

  • ent
  • nxdomain
  • {exact, [dns:rr()]} — records at the query name (list may be empty for typed lookup)
  • {wildcard, [dns:rr()]} — records from a parent wildcard (list may be empty for typed lookup)

API: Boolean Operations

is_in_any_zone/1

-spec is_in_any_zone(dns:dname() | dns:labels()) -> boolean().

Check if the name is in any available zone.

is_name_in_zone/2

-spec is_name_in_zone(erldns:zone(), dns:dname() | dns:labels()) -> boolean().

Check if the exact record name is in the zone, without recursing nor traversing the zone tree.

is_record_name_in_zone/2

-spec is_record_name_in_zone(erldns:zone(), dns:dname() | dns:labels()) -> boolean().

Check if the record name, or any wildcard or parent wildcard, is in the zone.

is_record_name_in_zone_strict/2

-spec is_record_name_in_zone_strict(erldns:zone(), dns:dname() | dns:labels()) -> boolean().

Check if the record name, or any wildcard, or parent wildcard, or descendant, is in the zone.

Will also return true if a wildcard is present at the node, or if any descendant has existing records (and the queried name is an ENT).

zone_name_existence/2

-spec zone_name_existence(erldns:zone(), dns:dname() | dns:labels()) -> existence_type().

Single-pass classification of how a name exists in the zone.

This can return: exact match, wildcard match, empty non-terminal (ENT), or nxdomain (no match). Note that according to RFC4592, wildcards match only non-existing names; this means that an ENT blocks a wildcard.

API: Lookups

get_authoritative_zone/1

-spec get_authoritative_zone(dns:dname() | dns:labels()) ->
                                erldns:zone() | zone_not_found | not_authoritative.

Find an authoritative zone for a given qname.

get_authoritative_zone/2

-spec get_authoritative_zone(dns:labels(), dns:type()) ->
                                erldns:zone() | zone_not_found | not_authoritative.

Find an authoritative zone for a given qname and qtype.

get_delegations/1

-spec get_delegations(dns:dname() | dns:labels()) -> [dns:rr()].

Get the list of NS and glue records for the given name.

This function will always return a list, even if it is empty.

get_delegations(Name, Labels)

-spec get_delegations(dns:dname(), dns:labels()) -> [dns:rr()].

Get the list of NS and glue records for the given name.

Expects name and labels to refer to the same domain.

This function will always return a list, even if it is empty.

get_records_by_name/1

-spec get_records_by_name(dns:dname() | dns:labels()) -> [dns:rr()].

Return the record set for the given dname.

get_records_by_name/2

-spec get_records_by_name(erldns:zone(), dns:dname() | dns:labels()) -> [dns:rr()].

Return the record set for the given dname in the given zone.

Returns only exact records at that node; no wildcard expansion and no subtree.

get_records_by_name_and_type/2

-spec get_records_by_name_and_type(dns:dname() | dns:labels(), dns:type()) -> [dns:rr()].

Get all records for the given type and given name.

get_records_by_name_and_type/3

-spec get_records_by_name_and_type(erldns:zone(), dns:dname() | dns:labels(), dns:type()) -> [dns:rr()].

Get all records for the given name and type in the given zone.

get_records_by_name_and_type_resolved(Zone, Name, Type)

-spec get_records_by_name_and_type_resolved(erldns:zone(), dns:dname() | dns:labels(), dns:type()) ->
                                               resolved_records().

Return matching records of the given type, or a status when there are none.

Same as get_records_by_name_resolved/2 but only returns records of the given dns:type().

get_records_by_name_ent/2

-spec get_records_by_name_ent(erldns:zone(), dns:dname() | dns:labels()) -> [dns:rr()].

Return the entire subtree at the given dname: all records at that node and at any descendant.

get_records_by_name_resolved(Zone, Name)

-spec get_records_by_name_resolved(erldns:zone(), dns:dname() | dns:labels()) -> resolved_records().

Return matching records or a status when there are none.

One-shot resolution: returns either

  • the atom nxdomain (name does not exist in the zone),
  • the atom ent (empty non-terminal: no records at this node but it has descendants),
  • {exact, Records} (records at the query name; list is non-empty for untyped lookup),
  • {wildcard, Records} (records from a parent wildcard; list is non-empty for untyped lookup).

get_records_by_name_wildcard/2

-spec get_records_by_name_wildcard(erldns:zone(), dns:dname() | dns:labels()) -> [dns:rr()].

Return records for the given dname or at any parent that has a wildcard.

Walks from the name upward; at each level looks only for a wildcard (*.parent). Stops at the first wildcard found and returns those records. Does not consider exact records at ancestors, and does not block on ENT (empty non-terminals).

get_records_by_name_wildcard_strict/2

-spec get_records_by_name_wildcard_strict(erldns:zone(), dns:dname() | dns:labels()) -> [dns:rr()].

Return records for the given dname or at any parent that has a wildcard or exact records.

Walks from the name upward; at each level looks for a wildcard first, then for exact records at that parent. Stops at the first level that has either and returns those records. Does not block on ENT (empty non-terminals); only prefers exact over wildcard when both exist at the same level.

get_rrset_sync_counter/3

-spec get_rrset_sync_counter(dns:dname() | dns:labels(), dns:dname() | dns:labels(), dns:type()) ->
                                integer().

Return current sync counter

get_zone_records/1

-spec get_zone_records(erldns:zone() | dns:dname() | dns:labels()) -> [dns:rr()].

Get all records for the given zone.

lookup_zone/1

-spec lookup_zone(dns:dname() | dns:labels()) -> erldns:zone() | zone_not_found.

Get a zone for the specific name.

This function will not attempt to resolve the dname in any way, it will simply look up the name in the underlying data store.

API: Mutations

delete_zone/1

-spec delete_zone(dns:dname() | dns:labels()) -> term().

Remove a zone from the cache without waiting for a response.

delete_zone_rrset(ZoneName, Digest, RRFqdn, Type, Counter)

-spec delete_zone_rrset(dns:dname(), erldns_zones:version(), dns:dname(), integer(), integer()) ->
                           ok | zone_not_found.

Remove zone RRSet

put_zone/1

-spec put_zone(Zone | {Name, Sha, Records} | {Name, Sha, Records, Keys}) -> ok
                  when
                      Zone :: erldns:zone(),
                      Name :: dns:dname(),
                      Sha :: erldns_zones:version(),
                      Records :: [dns:rr()],
                      Keys :: [erldns:keyset()].

Put a name and its records into the cache, along with a SHA which can be used to determine if the zone requires updating.

This function will build the necessary Zone record before inserting.

The name of each record must be the fully qualified domain name (including the zone part).

Here's an example:

erldns_zone_cache:put_zone({
  <<"example.com">>, <<"someDigest">>, [
    #dns_rr{
      name = <<"example.com">>,
      type = ?DNS_TYPE_A,
      ttl = 3600,
      data = #dns_rrdata_a{ip = {1,2,3,4}}
    },
    #dns_rr{
      name = <<"www.example.com">>,
      type = ?DNS_TYPE_CNAME,
      ttl = 3600,
      data = #dns_rrdata_cname{dname = <<"example.com">>}
    }
  ]}).

put_zone_rrset(RRSet, RRFqdn, Type, Counter)

-spec put_zone_rrset(RRSet, RRFqdn, Type, Counter) -> ok | zone_not_found
                        when
                            RRSet ::
                                erldns:zone() |
                                {dns:dname(), erldns_zones:version(), [dns:rr()]} |
                                {dns:dname(), erldns_zones:version(), [dns:rr()], [term()]},
                            RRFqdn :: dns:dname(),
                            Type :: dns:type(),
                            Counter :: integer().

Put zone RRSet

update_zone_records_and_digest(ZLabels, RecordsCount, Digest)

-spec update_zone_records_and_digest(dns:labels(), non_neg_integer(), erldns_zones:version()) ->
                                        ok | zone_not_found.

Given a zone name, list of records, and a digest, update the zone metadata in cache.

API: Utilities

zone_names_and_versions()

-spec zone_names_and_versions() -> [{dns:dname(), erldns_zones:version()}].

Return a list of tuples with each tuple as a name and the version SHA for the zone.