dns (dns_erlang v4.2.0)

View Source

The dns module is the primary entry point for the functionality in this library. The module exports various types used in type specs, such as message/0, which indicates a #dns_message{} record, query/0 which represents a single #dns_query{} record, questions/0, which represents a list of queries, etc.

It also exports functions for encoding and decoding messages, TSIG supporting functions, and various utility functions for comparing domain names, converting domain names into different cases, converting to and from label lists, etc.

Summary

Types

DNS Message class. See RFC 1035: §4.1.2.

Decoding errors.

Domain name, expressed as a sequence of label/0, as defined in RFC 1035: §3.1.

DNS labels. See RFC 1035: §2.3.1.

A list of dns:label/0

DNS wire message format.

DNS Message ID. See RFC 1035: §4.1.1.

DNS Message class. See RFC 1035: §4.1.3.

DNS Message class. See RFC 1035: §4.1.2.

Unix timestamp in seconds.

Functions: parsing

Decode a binary DNS message.

Encode a message/0 record.

Encode a dns_message record - will truncate the message as needed.

Functions: utilities

Compare two domain names insensitive of case.

Compare two domain names insensitive of case.

Splits a dname into a list of labels and removes unneeded escapes.

Returns provided name with case-insensitive characters in lowercase.

Splits a dname into a list of labels in lowercase and removes unneeded escapes.

Returns provided name with case-insensitive characters in uppercase.

Escapes dots in a DNS label

Returns a random integer suitable for use as DNS message identifier.

Return current unix time in seconds.

Return the unix time in seconds from a timestamp or universal time.

Types: integer codes

Unsigned 2-bits integer

Unsigned 4-bits integer

Unsigned 8-bits integer

Unsigned 16-bits integer

Unsigned 32-bits integer

Unsigned 48-bits integer

Unsigned 64-bits integer

Types

class()

-type class() :: uint16().

DNS Message class. See RFC 1035: §4.1.2.

decode_error()

-type decode_error() :: formerr | truncated | trailing_garbage.

Decoding errors.

Can be one of the following:

  • formerr: the message was malformed.
  • truncated: the message was partially decoded, as data was found missing from the message.
  • trailing_garbage: the message was successfully decoded, but there was trailing garbage at the end of the message.

dname()

-type dname() :: binary().

Domain name, expressed as a sequence of label/0, as defined in RFC 1035: §3.1.

label()

-type label() :: binary().

DNS labels. See RFC 1035: §2.3.1.

The labels must follow the rules for ARPANET host names. They must start with a letter, end with a letter or digit, and have as interior characters only letters, digits, and hyphen. There are also some restrictions on the length. Labels must be 63 characters or less.

labels()

-type labels() :: [label()].

A list of dns:label/0

message_bin()

-type message_bin() :: <<_:96, _:_*8>>.

DNS wire message format.

The general form is a 96bits header, followed by a variable number of questions, answers, authorities, and additional records.

message_id()

-type message_id() :: uint16().

DNS Message ID. See RFC 1035: §4.1.1.

ttl()

-type ttl() :: 0..1 bsl 31 - 1.

DNS Message class. See RFC 1035: §4.1.3.

type()

-type type() :: uint16().

DNS Message class. See RFC 1035: §4.1.2.

unix_time()

-type unix_time() :: 0..4294967295.

Unix timestamp in seconds.

Functions: TSIG

add_tsig(Msg, Alg, Name, Secret, ErrCode)

-spec add_tsig(message(), tsig_alg(), dname(), binary(), tsig_error()) -> message().

Equivalent to add_tsig(Msg, Alg, Name, Secret, ErrCode, #{name => Name, alg => Alg}).

add_tsig(Msg, Alg, Name, Secret, ErrCode, Options)

-spec add_tsig(message(), tsig_alg(), dname(), binary(), tsig_error(), encode_tsig_opts()) -> message().

Generates and then appends a TSIG RR to a message.

Supports MD5, SHA1, SHA224, SHA256, SHA384 and SHA512 algorithms.

verify_tsig(MsgBin, Name, Secret)

-spec verify_tsig(message_bin(), dname(), binary()) -> {ok, tsig_mac()} | {error, tsig_error()}.

Equivalent to verify_tsig(MsgBin, Name, Secret, #{}).

verify_tsig(MsgBin, Name, Secret, Options)

-spec verify_tsig(message_bin(), dname(), binary(), tsig_opts()) ->
                     {ok, tsig_mac()} | {error, tsig_error()}.

Verifies a TSIG message signature.

Functions: parsing

decode_message(MsgBin)

-spec decode_message(message_bin()) -> {decode_error(), message() | undefined, binary()} | message().

Decode a binary DNS message.

encode_message(Msg)

-spec encode_message(message()) -> message_bin().

Encode a message/0 record.

encode_message(Msg, Opts)

-spec encode_message(message(), encode_message_opts()) ->
                        {false, message_bin()} |
                        {false, message_bin(), tsig_mac()} |
                        {true, message_bin(), message()} |
                        {true, message_bin(), tsig_mac(), message()}.

Encode a dns_message record - will truncate the message as needed.

Functions: utilities

compare_dname/2

-spec compare_dname(dname(), dname()) -> boolean().

Compare two domain names insensitive of case.

compare_labels(LabelsA, LabelsB)

-spec compare_labels(labels(), labels()) -> boolean().

Compare two domain names insensitive of case.

dname_to_labels/1

-spec dname_to_labels(dname()) -> labels().

Splits a dname into a list of labels and removes unneeded escapes.

dname_to_lower/1

-spec dname_to_lower(dname()) -> dname().

Returns provided name with case-insensitive characters in lowercase.

dname_to_lower_labels(Name)

-spec dname_to_lower_labels(dname()) -> labels().

Splits a dname into a list of labels in lowercase and removes unneeded escapes.

dname_to_upper/1

-spec dname_to_upper(dname()) -> dname().

Returns provided name with case-insensitive characters in uppercase.

escape_label(Label)

-spec escape_label(label()) -> label().

Escapes dots in a DNS label

random_id()

-spec random_id() -> message_id().

Returns a random integer suitable for use as DNS message identifier.

unix_time()

-spec unix_time() -> unix_time().

Return current unix time in seconds.

unix_time/1

-spec unix_time(erlang:timestamp() | calendar:datetime1970()) -> unix_time().

Return the unix time in seconds from a timestamp or universal time.

Types: TSIG

alg()

-type alg() :: 3 | 6 | 5 | 7 | 8 | 10.

tsig_alg()

-type tsig_alg() :: binary().

tsig_error()

-type tsig_error() :: 0 | 16..18.

tsig_mac()

-type tsig_mac() :: binary().

Types: integer codes

eoptcode()

-type eoptcode() :: uint16().

ercode()

-type ercode() :: 0 | 16.

llqerrcode()

-type llqerrcode() :: 0..6.

llqopcode()

-type llqopcode() :: 1..3.

opcode()

-type opcode() :: uint4().

rcode()

-type rcode() :: uint4().

uint2()

-type uint2() :: 0..1.

Unsigned 2-bits integer

uint4()

-type uint4() :: 0..15.

Unsigned 4-bits integer

uint8()

-type uint8() :: 0..1 bsl 8 - 1.

Unsigned 8-bits integer

uint16()

-type uint16() :: 0..1 bsl 16 - 1.

Unsigned 16-bits integer

uint32()

-type uint32() :: 0..1 bsl 32 - 1.

Unsigned 32-bits integer

uint48()

-type uint48() :: 0..1 bsl 48 - 1.

Unsigned 48-bits integer

uint64()

-type uint64() :: 0..1 bsl 64 - 1.

Unsigned 64-bits integer

Types: options

encode_message_opts()

-type encode_message_opts() ::
          #{max_size => 512..65535, tc_mode => default | axfr | llq_event, tsig => encode_tsig_opts()}.

encode_tsig_opts()

-type encode_tsig_opts() ::
          #{name := dname(),
            alg := tsig_alg(),
            msgid => message_id(),
            secret => binary(),
            errcode => tsig_error(),
            other => binary(),
            time => unix_time(),
            fudge => non_neg_integer(),
            mac => tsig_mac(),
            tail => boolean()}.

svcb_svc_params()

-type svcb_svc_params() :: #{1..6 => none | char() | binary()}.

tsig_opts()

-type tsig_opts() ::
          #{time => unix_time(),
            fudge => non_neg_integer(),
            mac => tsig_mac(),
            tail => boolean(),
            atom() => _}.

Types: records

additional()

-type additional() :: [optrr() | rr()].

answers()

-type answers() :: [rr()].

authority()

-type authority() :: [rr()].

message()

-type message() ::
          #dns_message{id :: dns:message_id(),
                       qr :: boolean(),
                       oc :: dns:opcode(),
                       aa :: boolean(),
                       tc :: boolean(),
                       rd :: boolean(),
                       ra :: boolean(),
                       ad :: boolean(),
                       cd :: boolean(),
                       rc :: dns:rcode(),
                       qc :: dns:uint16(),
                       anc :: dns:uint16(),
                       auc :: dns:uint16(),
                       adc :: dns:uint16(),
                       questions :: dns:questions(),
                       answers :: dns:answers(),
                       authority :: dns:authority(),
                       additional :: dns:additional()}.

Main DNS message structure.

opt_cookie()

-type opt_cookie() :: #dns_opt_cookie{client :: <<_:64>>, server :: undefined | <<_:64, _:_*8>>}.

opt_ecs()

-type opt_ecs() ::
          #dns_opt_ecs{family :: dns:uint16(),
                       source_prefix_length :: dns:uint8(),
                       scope_prefix_length :: dns:uint8(),
                       address :: binary()}.

opt_llq()

-type opt_llq() ::
          #dns_opt_llq{opcode :: dns:uint16(),
                       errorcode :: dns:uint16(),
                       id :: dns:uint64(),
                       leaselife :: dns:uint32()}.

opt_nsid()

-type opt_nsid() :: #dns_opt_nsid{data :: binary()}.

opt_owner()

-type opt_owner() ::
          #dns_opt_owner{seq :: dns:uint8(),
                         primary_mac :: <<_:48>>,
                         wakeup_mac :: <<>> | <<_:48>>,
                         password :: <<>> | <<_:48>>}.

opt_ul()

-type opt_ul() :: #dns_opt_ul{lease :: dns:uint32()}.

opt_unknown()

-type opt_unknown() :: #dns_opt_unknown{id :: integer(), bin :: binary()}.

optrr()

-type optrr() ::
          #dns_optrr{udp_payload_size :: dns:uint16(),
                     ext_rcode :: dns:uint8(),
                     version :: dns:uint8(),
                     dnssec :: boolean(),
                     data :: [dns:optrr_elem()]}.

optrr_elem()

-type optrr_elem() ::
          opt_nsid() | opt_ul() | opt_unknown() | opt_ecs() | opt_llq() | opt_owner() | opt_cookie().

query()

-type query() :: #dns_query{name :: dns:dname(), class :: dns:class(), type :: dns:type()}.

questions()

-type questions() :: [query()].

records()

-type records() :: additional() | answers() | authority() | questions().

rr()

-type rr() ::
          #dns_rr{name :: dns:dname(),
                  type :: dns:type(),
                  class :: dns:class(),
                  ttl :: dns:ttl(),
                  data :: dns:rrdata()}.

rrdata()

-type rrdata() ::
          binary() |
          #dns_rrdata_a{ip :: inet:ip4_address()} |
          #dns_rrdata_aaaa{ip :: inet:ip6_address()} |
          #dns_rrdata_afsdb{subtype :: dns:uint16(), hostname :: dns:dname()} |
          #dns_rrdata_caa{flags :: dns:uint8(), tag :: binary(), value :: binary()} |
          #dns_rrdata_cdnskey{flags :: dns:uint16(),
                              protocol :: dns:uint8(),
                              alg :: dns:uint8(),
                              public_key :: iodata(),
                              keytag :: integer()} |
          #dns_rrdata_cds{keytag :: dns:uint16(),
                          alg :: dns:uint8(),
                          digest_type :: dns:uint8(),
                          digest :: binary()} |
          #dns_rrdata_cert{type :: dns:uint16(),
                           keytag :: dns:uint16(),
                           alg :: dns:uint8(),
                           cert :: binary()} |
          #dns_rrdata_cname{dname :: dns:dname()} |
          #dns_rrdata_dhcid{data :: binary()} |
          #dns_rrdata_dlv{keytag :: dns:uint16(),
                          alg :: dns:uint8(),
                          digest_type :: dns:uint8(),
                          digest :: binary()} |
          #dns_rrdata_dname{dname :: dns:dname()} |
          #dns_rrdata_dnskey{flags :: dns:uint16(),
                             protocol :: dns:uint8(),
                             alg :: dns:uint8(),
                             public_key :: iodata(),
                             keytag :: integer()} |
          #dns_rrdata_ds{keytag :: dns:uint16(),
                         alg :: dns:uint8(),
                         digest_type :: dns:uint8(),
                         digest :: binary()} |
          #dns_rrdata_hinfo{cpu :: binary(), os :: binary()} |
          #dns_rrdata_ipseckey{precedence :: dns:uint8(),
                               alg :: dns:uint8(),
                               gateway :: dns:dname() | inet:ip_address(),
                               public_key :: binary()} |
          #dns_rrdata_key{type :: dns:uint2(),
                          xt :: 0..1,
                          name_type :: dns:uint2(),
                          sig :: dns:uint4(),
                          protocol :: dns:uint8(),
                          alg :: dns:uint8(),
                          public_key :: binary()} |
          #dns_rrdata_kx{preference :: dns:uint16(), exchange :: dns:dname()} |
          #dns_rrdata_loc{size :: integer(),
                          horiz :: integer(),
                          vert :: integer(),
                          lat :: dns:uint32(),
                          lon :: dns:uint32(),
                          alt :: dns:uint32()} |
          #dns_rrdata_mb{madname :: dns:dname()} |
          #dns_rrdata_mg{madname :: dns:dname()} |
          #dns_rrdata_minfo{rmailbx :: dns:dname(), emailbx :: dns:dname()} |
          #dns_rrdata_mr{newname :: dns:dname()} |
          #dns_rrdata_mx{preference :: dns:uint16(), exchange :: dns:dname()} |
          #dns_rrdata_naptr{order :: dns:uint16(),
                            preference :: dns:uint16(),
                            flags :: binary(),
                            services :: binary(),
                            regexp :: binary(),
                            replacement :: dns:dname()} |
          #dns_rrdata_ns{dname :: dns:dname()} |
          #dns_rrdata_nsec{next_dname :: dns:dname(), types :: [non_neg_integer()]} |
          #dns_rrdata_nsec3{hash_alg :: dns:uint8(),
                            opt_out :: boolean(),
                            iterations :: dns:uint16(),
                            salt :: binary(),
                            hash :: binary(),
                            types :: [non_neg_integer()]} |
          #dns_rrdata_nsec3param{hash_alg :: dns:uint8(),
                                 flags :: dns:uint8(),
                                 iterations :: dns:uint16(),
                                 salt :: binary()} |
          #dns_rrdata_nxt{dname :: dns:dname(), types :: [non_neg_integer()]} |
          #dns_rrdata_ptr{dname :: dns:dname()} |
          #dns_rrdata_rp{mbox :: dns:dname(), txt :: dns:dname()} |
          #dns_rrdata_rrsig{type_covered :: dns:uint16(),
                            alg :: 3 | 5 | 6 | 7 | 8 | 10,
                            labels :: dns:uint8(),
                            original_ttl :: dns:uint32(),
                            expiration :: dns:uint32(),
                            inception :: dns:uint32(),
                            keytag :: dns:uint16(),
                            signers_name :: dns:dname(),
                            signature :: binary()} |
          #dns_rrdata_rt{preference :: dns:uint16(), host :: dns:dname()} |
          #dns_rrdata_soa{mname :: dns:dname(),
                          rname :: dns:dname(),
                          serial :: dns:uint32(),
                          refresh :: dns:uint32(),
                          retry :: dns:uint32(),
                          expire :: dns:uint32(),
                          minimum :: dns:uint32()} |
          #dns_rrdata_spf{spf :: [binary()]} |
          #dns_rrdata_srv{priority :: dns:uint16(),
                          weight :: dns:uint16(),
                          port :: dns:uint16(),
                          target :: dns:dname()} |
          #dns_rrdata_svcb{svc_priority :: dns:uint16(),
                           target_name :: dns:dname(),
                           svc_params :: dns:svcb_svc_params()} |
          #dns_rrdata_sshfp{alg :: dns:uint8(), fp_type :: dns:uint8(), fp :: binary()} |
          #dns_rrdata_tsig{alg :: dns:tsig_alg(),
                           time :: dns:uint48(),
                           fudge :: dns:uint16(),
                           mac :: binary(),
                           msgid :: dns:uint16(),
                           err :: dns:uint16(),
                           other :: binary()} |
          #dns_rrdata_txt{txt :: [binary()]}.

rrdata_rrsig()

-type rrdata_rrsig() ::
          #dns_rrdata_rrsig{type_covered :: dns:uint16(),
                            alg :: 3 | 5 | 6 | 7 | 8 | 10,
                            labels :: dns:uint8(),
                            original_ttl :: dns:uint32(),
                            expiration :: dns:uint32(),
                            inception :: dns:uint32(),
                            keytag :: dns:uint16(),
                            signers_name :: dns:dname(),
                            signature :: binary()}.