dns_zone (dns_erlang v5.0.11)

View Source

DNS Zone File Parser and Encoder

This module provides functionality to parse and encode DNS zone files according to RFC 1035 and related specifications.

Specification Compliance

RFC-Defined Features (Standard):

Supported RFC Features:

BIND Extensions (Non-Standard):

The parser uses Erlang's parsetools (leex and yecc) for lexical analysis and parsing.

Examples

Parsing

% Parse a zone file from disk
{ok, Records} = dns_zone:parse_file("example.com.zone").

% Parse zone data from a string
ZoneData = <<"
example.com. 3600 IN SOA ns1.example.com. admin.example.com. (
                      2024010101 ; serial
                      3600       ; refresh
                      1800       ; retry
                      604800     ; expire
                      86400 )    ; minimum
example.com. 3600 IN NS ns1.example.com.
www 3600 IN A 192.0.2.1
">>,
{ok, Records} = dns_zone:parse_string(ZoneData).

Encoding

% Encode a single record
RR = #dns_rr{
    name = ~"www.example.com.",
    type = ?DNS_TYPE_A,
    class = ?DNS_CLASS_IN,
    ttl = 3600,
    data = #dns_rrdata_a{ip = {192, 0, 2, 1}}
},
Line = dns_zone:encode_rr(RR, #{origin => ~"example.com.", relative_names => true}).
% Returns: "www 3600 IN A 192.0.2.1"

% Encode a complete zone
Records = [...],
ZoneData = dns_zone:encode_string(Records, #{origin => ~"example.com", default_ttl => 3600}).

% Write zone to file
ok = dns_zone:encode_file(Records, ~"example.com.", "output.zone").

Summary

Types

Options for encoding zone files.

Detailed error information with context and suggestions.

Error location information.

Error type classification.

Options for parsing zone files.

Functions

Encode a list of DNS resource records and write to a zone file with options.

Encode RDATA (record data) to zone file format with options.

Encode a single DNS resource record to zone file format.

Encode a single DNS resource record to zone file format with options.

Encode a list of DNS resource records to zone file format with options.

Format a parse error into a human-readable string.

Parse a zone file from disk.

Parse a zone file from disk with options.

Parse zone file content from a string or binary.

Parse zone file content from a string or binary with options.

Types

encode_options()

-type encode_options() ::
          #{origin => dns:dname(),
            relative_names => boolean(),
            ttl_format => seconds | units,
            default_ttl => dns:ttl() | undefined,
            omit_class => boolean(),
            separator => binary()}.

Options for encoding zone files.

  • origin => Domain - Origin domain for relative name calculation (default: <<>>)
  • relative_names => boolean() - Use @ and relative names (default: true)
  • ttl_format => seconds | units - TTL format: 3600 or 1h (default: seconds)

  • default_ttl => TTL - Include $TTL directive if set (default: undefined)
  • omit_class => boolean() - Omit IN class (default: false)
  • separator => binary() - Separator between fields (default: ~" ")

error_detail()

-type error_detail() ::
          #{type := error_type(),
            message := unicode:unicode_binary(),
            location => error_location(),
            context => binary(),
            suggestion => unicode:unicode_binary(),
            details => term()}.

Detailed error information with context and suggestions.

  • type - Classification of the error
  • location - Where the error occurred (line, column, file)
  • message - Human-readable error description
  • context - The line of text where error occurred (if available)
  • suggestion - Helpful suggestion for fixing the error (if available)
  • details - Original technical error details

error_location()

-type error_location() ::
          #{line => pos_integer(),
            column => pos_integer() | undefined,
            file => file:filename_all() | undefined}.

Error location information.

  • line - Line number where error occurred (1-indexed)
  • column - Column number if available (1-indexed)
  • file - Filename if parsing from file

error_type()

-type error_type() :: file | lexer | parser | semantic.

Error type classification.

  • file - File I/O error (e.g., file not found)
  • lexer - Lexical analysis error (invalid tokens)
  • parser - Syntax parsing error (grammar violation)
  • semantic - Semantic validation error (invalid data)

parse_options()

-type parse_options() ::
          #{origin => dns:dname(),
            default_ttl => dns:ttl(),
            default_class => dns:class(),
            base_dir => file:name_all(),
            filename => file:name_all(),
            chunk_size => non_neg_integer()}.

Options for parsing zone files.

  • origin - Initial $ORIGIN for relative domain names (default: <<>>)
  • default_ttl - Default TTL for records without explicit TTL (default: 0)
  • default_class - Default DNS class (default: ?DNS_CLASS_IN)
  • base_dir - Base directory for $INCLUDE directives (default: "")
  • filename - Source filename for error reporting (internal, set by parse_file)

Functions

encode_file(Records, Filename)

-spec encode_file([dns:rr()], file:filename()) -> ok | {error, term()}.

Equivalent to encode_file(Records, Filename, #{}).

encode_file(Records, Filename, Options)

-spec encode_file([dns:rr()], file:filename(), encode_options()) -> ok | {error, term()}.

Encode a list of DNS resource records and write to a zone file with options.

encode_rdata(Type, RData)

-spec encode_rdata(dns:type(), dns:rrdata()) -> iodata().

Equivalent to encode_rdata(Type, RData, #{}).

encode_rdata(Type, RData, Options)

-spec encode_rdata(dns:type(), dns:rrdata(), encode_options()) -> iodata().

Encode RDATA (record data) to zone file format with options.

Options (all optional):

  • origin => Domain - Origin domain for relative name calculation (default: <<>>)
  • relative_names => boolean() - Use @ and relative names (default: true)
  • separator => binary() - Separator between fields (default: ~" ")

Examples

% Encode an MX record RDATA with custom separator
RData = #dns_rrdata_mx{preference = 10, exchange = ~"mail.example.com."},
RDataStr = dns_zone:encode_rdata(?DNS_TYPE_MX, RData, #{separator => ~"\t"}).
% Returns: "10\tmail.example.com."

% Encode an NS record RDATA with relative names
RData = #dns_rrdata_ns{dname = ~"ns1.example.com."},
RDataStr = dns_zone:encode_rdata(?DNS_TYPE_NS, RData, #{
    origin => ~"example.com.",
    relative_names => true
}).
% Returns: "ns1" (if ns1 is under example.com.)

encode_rr(RR)

-spec encode_rr(dns:rr()) -> iodata().

Encode a single DNS resource record to zone file format.

Returns a string representing the record in zone file format.

Examples

RR = #dns_rr{
    name = ~"www.example.com.",
    type = ?DNS_TYPE_A,
    class = ?DNS_CLASS_IN,
    ttl = 3600,
    data = #dns_rrdata_a{ip = {192, 0, 2, 1}}
},
Line = dns_zone:encode_rr(RR).
% Returns: "www.example.com. 3600 IN A 192.0.2.1"

encode_rr(RR, Options)

-spec encode_rr(dns:rr(), encode_options()) -> iodata().

Encode a single DNS resource record to zone file format with options.

Options (all optional):

  • origin => Domain - Origin domain for relative name calculation
  • relative_names => boolean() - Use @ and relative names (default: true)
  • ttl_format => seconds | units - TTL format: 3600 or 1h (default: seconds)

  • omit_class => boolean() - Omit IN class (default: false)

Examples

RR = #dns_rr{
    name = ~"www.example.com.",
    type = ?DNS_TYPE_A,
    class = ?DNS_CLASS_IN,
    ttl = 3600,
    data = #dns_rrdata_a{ip = {192, 0, 2, 1}}
},
Line = dns_zone:encode_rr(RR, #{origin => ~"example.com.", relative_names => true}).
% Returns: "www 3600 IN A 192.0.2.1"

encode_string(Records)

-spec encode_string([dns:rr()]) -> iodata().

Equivalent to encode_string(Records, #{}).

encode_string(Records, Options)

-spec encode_string([dns:rr()], encode_options()) -> iodata().

Encode a list of DNS resource records to zone file format with options.

Examples

Records = [...],
ZoneData = dns_zone:encode_string(Records, #{
    origin => ~"example.com",
    default_ttl => 3600,
    relative_names => true
}).

format_error(Error)

-spec format_error(error_detail()) -> iolist().

Format a parse error into a human-readable string.

Takes an error from parse_file/1,2 or parse_string/1,2 and returns a formatted string suitable for display to users.

Examples

case dns_zone:parse_file("bad.zone") of
    {ok, Records} -> ok;
    {error, Error} ->
        io:format("~s", [dns_zone:format_error(Error)])
end.

parse_file(Filename)

-spec parse_file(file:filename()) -> {ok, [dns:rr()]} | {error, error_detail()}.

Parse a zone file from disk.

Returns {ok, Records} where Records is a list of #dns_rr{} records, or {error, Reason} if parsing fails.

Examples

{ok, Records} = dns_zone:parse_file("/path/to/zone.db").

parse_file(Filename, Options)

-spec parse_file(file:filename(), parse_options()) -> {ok, [dns:rr()]} | {error, error_detail()}.

Parse a zone file from disk with options.

Options (all optional):

  • origin => Domain - Set the initial $ORIGIN
  • default_ttl => TTL - Set the default TTL
  • default_class => Class - Set the default class (defaults to IN)
  • base_dir => Dir - Set base directory for $INCLUDE directives

Examples

{ok, Records} = dns_zone:parse_file("zone.db", #{origin => ~"example.com."}).

{ok, Records} = dns_zone:parse_file("zone.db", #{
    origin => ~"example.com.",
    default_ttl => 3600
}).

parse_string(Data)

-spec parse_string(binary() | string()) -> {ok, [dns:rr()]} | {error, error_detail()}.

Parse zone file content from a string or binary.

Examples

ZoneData = ~"example.com. IN A 192.0.2.1",
{ok, Records} = dns_zone:parse_string(ZoneData).

parse_string(Data, Options)

-spec parse_string(binary() | string(), parse_options()) -> {ok, [dns:rr()]} | {error, error_detail()}.

Parse zone file content from a string or binary with options.