Packages
erldns
9.1.0
11.0.2
11.0.1
11.0.0
10.6.0
10.5.6
10.5.5
10.5.4
10.5.3
10.5.2
10.5.1
10.5.0
10.4.4
10.4.3
10.4.2
10.4.1
10.4.0
10.3.0
10.2.1
10.2.0
10.1.0
10.0.0
10.0.0-rc4
10.0.0-rc3
10.0.0-rc2
10.0.0-rc1
9.1.0
9.0.0
9.0.0-rc3
9.0.0-rc2
9.0.0-rc1
8.1.0
8.0.0
8.0.0-rc6
8.0.0-rc5
8.0.0-rc4
8.0.0-rc3
8.0.0-rc2
8.0.0-rc1
7.0.0
7.0.0-rc9
7.0.0-rc8
7.0.0-rc7
7.0.0-rc6
7.0.0-rc5
7.0.0-rc4
7.0.0-rc3
7.0.0-rc2
7.0.0-rc12
7.0.0-rc11
7.0.0-rc10
7.0.0-rc1
6.0.2
6.0.1
6.0.0
5.0.0
4.3.1
4.3.0
4.2.4
4.2.3
4.2.2
4.2.1
4.2.0
4.1.2
4.1.1
4.1.0
4.0.0
3.0.0
1.0.0
Erlang Authoritative DNS Server
Current section
Files
Jump to
Current section
Files
src/zones/erldns_zone_encoder.erl
-module(erldns_zone_encoder).
-moduledoc false.
-include_lib("dns_erlang/include/dns.hrl").
-include_lib("kernel/include/logger.hrl").
-include_lib("erldns/include/erldns.hrl").
-export([encode/3]).
-spec encode(erldns:zone(), #{atom() => dynamic()}, [erldns_zone_codec:encoder()]) ->
not_implemented | json:encode_value().
encode(Zone, #{mode := zone_records_to_json}, Encoders) ->
encode_zone_records_to_json(Zone, Encoders);
encode(Zone, #{mode := {zone_records_to_json, RecordName}}, Encoders) ->
encode_zone_records_to_json(Zone, RecordName, Encoders);
encode(Zone, #{mode := {zone_records_to_json, RecordName, RecordType}}, Encoders) ->
encode_zone_records_to_json(Zone, RecordName, RecordType, Encoders);
encode(Zone, #{mode := zone_meta_to_json}, _) ->
zone_meta_to_json(Zone, #{});
encode(Zone, #{mode := zone_to_json}, Encoders) ->
Records = records_to_json(Zone, Encoders),
Extra = #{~"records" => Records},
zone_meta_to_json(Zone, Extra).
% Note: Private key material is purposely omitted
-spec zone_meta_to_json(erldns:zone(), dynamic()) -> json:encode_value().
zone_meta_to_json(Zone, MaybeRecords) ->
Zone0 = #{
~"name" => Zone#zone.name,
~"version" => Zone#zone.version,
~"records_count" => Zone#zone.record_count
},
ZoneJson = maps:merge(Zone0, MaybeRecords),
#{~"erldns" => #{~"zone" => ZoneJson}}.
% Internal API
encode_zone_records_to_json(Zone, Encoders) ->
Records = erldns_zone_cache:get_zone_records(Zone),
lists:flatmap(encode(Encoders), Records).
encode_zone_records_to_json(Zone, RecordName, Encoders) ->
Records = erldns_zone_cache:get_records_by_name(Zone, RecordName),
lists:flatmap(encode(Encoders), Records).
encode_zone_records_to_json(Zone, RecordName, RecordType, Encoders) ->
Type = dns_names:name_type(RecordType),
Records = erldns_zone_cache:get_records_by_name_and_type(Zone, RecordName, Type),
lists:flatmap(encode(Encoders), Records).
records_to_json(Zone, Encoders) ->
lists:flatmap(encode(Encoders), erldns_zone_cache:get_zone_records(Zone)).
encode(Encoders) ->
fun(Record) -> encode_record(Record, Encoders) end.
encode_record(Record, Encoders) ->
case encode_record(Record) of
not_implemented ->
try_custom_encoders(Record, Encoders);
EncodedRecord ->
[EncodedRecord]
end.
encode_record(#dns_rr{name = Name, type = Type = ?DNS_TYPE_SOA, ttl = Ttl, data = Data}) ->
encode_record(Name, Type, Ttl, Data);
encode_record(#dns_rr{name = Name, type = Type = ?DNS_TYPE_NS, ttl = Ttl, data = Data}) ->
encode_record(Name, Type, Ttl, Data);
encode_record(#dns_rr{name = Name, type = Type = ?DNS_TYPE_A, ttl = Ttl, data = Data}) ->
encode_record(Name, Type, Ttl, Data);
encode_record(#dns_rr{name = Name, type = Type = ?DNS_TYPE_AAAA, ttl = Ttl, data = Data}) ->
encode_record(Name, Type, Ttl, Data);
encode_record(#dns_rr{name = Name, type = Type = ?DNS_TYPE_CNAME, ttl = Ttl, data = Data}) ->
encode_record(Name, Type, Ttl, Data);
encode_record(#dns_rr{name = Name, type = Type = ?DNS_TYPE_MX, ttl = Ttl, data = Data}) ->
encode_record(Name, Type, Ttl, Data);
encode_record(#dns_rr{name = Name, type = Type = ?DNS_TYPE_HINFO, ttl = Ttl, data = Data}) ->
encode_record(Name, Type, Ttl, Data);
encode_record(#dns_rr{name = Name, type = Type = ?DNS_TYPE_TXT, ttl = Ttl, data = Data}) ->
encode_record(Name, Type, Ttl, Data);
encode_record(#dns_rr{name = Name, type = Type = ?DNS_TYPE_SSHFP, ttl = Ttl, data = Data}) ->
encode_record(Name, Type, Ttl, Data);
encode_record(#dns_rr{name = Name, type = Type = ?DNS_TYPE_SRV, ttl = Ttl, data = Data}) ->
encode_record(Name, Type, Ttl, Data);
encode_record(#dns_rr{name = Name, type = Type = ?DNS_TYPE_NAPTR, ttl = Ttl, data = Data}) ->
encode_record(Name, Type, Ttl, Data);
encode_record(#dns_rr{name = Name, type = Type = ?DNS_TYPE_CAA, ttl = Ttl, data = Data}) ->
encode_record(Name, Type, Ttl, Data);
encode_record(#dns_rr{name = Name, type = Type = ?DNS_TYPE_DS, ttl = Ttl, data = Data}) ->
encode_record(Name, Type, Ttl, Data);
encode_record(#dns_rr{name = Name, type = Type = ?DNS_TYPE_CDS, ttl = Ttl, data = Data}) ->
encode_record(Name, Type, Ttl, Data);
encode_record(#dns_rr{name = Name, type = Type = ?DNS_TYPE_DNSKEY, ttl = Ttl, data = Data}) ->
encode_record(Name, Type, Ttl, Data);
encode_record(#dns_rr{name = Name, type = Type = ?DNS_TYPE_CDNSKEY, ttl = Ttl, data = Data}) ->
encode_record(Name, Type, Ttl, Data);
encode_record(#dns_rr{name = Name, type = Type = ?DNS_TYPE_RRSIG, ttl = Ttl, data = Data}) ->
encode_record(Name, Type, Ttl, Data);
encode_record(#dns_rr{name = Name, type = Type = ?DNS_TYPE_TLSA, ttl = Ttl, data = Data}) ->
encode_record(Name, Type, Ttl, Data);
encode_record(Record) ->
?LOG_WARNING(
#{what => unable_to_encode_record, record => Record},
#{domain => [erldns, zones]}
),
not_implemented.
encode_record(Name, Type, Ttl, Data) ->
#{
~"name" => erlang:iolist_to_binary(io_lib:format("~s.", [Name])),
~"type" => dns_names:type_name(Type),
~"ttl" => Ttl,
~"content" => encode_data(Data)
}.
try_custom_encoders(_, []) ->
[];
try_custom_encoders(Record, [Encoder | Rest]) ->
case Encoder(Record) of
not_implemented ->
try_custom_encoders(Record, Rest);
EncodedData ->
[EncodedData]
end.
encode_data(#dns_rrdata_soa{
mname = Mname,
rname = Rname,
serial = Serial,
refresh = Refresh,
retry = Retry,
expire = Expire,
minimum = Minimum
}) ->
erlang:iolist_to_binary(
io_lib:format("~s. ~s. (~w ~w ~w ~w ~w)", [
Mname, Rname, Serial, Refresh, Retry, Expire, Minimum
])
);
encode_data(#dns_rrdata_ns{dname = Dname}) ->
erlang:iolist_to_binary(io_lib:format("~s.", [Dname]));
encode_data(#dns_rrdata_a{ip = Address}) ->
list_to_binary(inet_parse:ntoa(Address));
encode_data(#dns_rrdata_aaaa{ip = Address}) ->
list_to_binary(inet_parse:ntoa(Address));
encode_data(#dns_rrdata_caa{flags = Flags, tag = Tag, value = Value}) ->
erlang:iolist_to_binary(io_lib:format("~w ~s \"~s\"", [Flags, Tag, Value]));
encode_data(#dns_rrdata_cname{dname = Dname}) ->
erlang:iolist_to_binary(io_lib:format("~s.", [Dname]));
encode_data(#dns_rrdata_mx{preference = Preference, exchange = Dname}) ->
erlang:iolist_to_binary(io_lib:format("~w ~s.", [Preference, Dname]));
encode_data(#dns_rrdata_hinfo{cpu = Cpu, os = Os}) ->
erlang:iolist_to_binary(io_lib:format("~w ~w", [Cpu, Os]));
encode_data(#dns_rrdata_txt{txt = Text}) ->
erlang:iolist_to_binary(io_lib:format("~s", [Text]));
encode_data(#dns_rrdata_sshfp{alg = Alg, fp_type = Fptype, fp = Fp}) ->
erlang:iolist_to_binary(io_lib:format("~w ~w ~s", [Alg, Fptype, Fp]));
encode_data(#dns_rrdata_srv{priority = Priority, weight = Weight, port = Port, target = Dname}) ->
erlang:iolist_to_binary(io_lib:format("~w ~w ~w ~s.", [Priority, Weight, Port, Dname]));
encode_data(#dns_rrdata_naptr{
order = Order,
preference = Preference,
flags = Flags,
services = Services,
regexp = Regexp,
replacement = Replacements
}) ->
erlang:iolist_to_binary(
io_lib:format("~w ~w ~s ~s ~s ~s", [
Order, Preference, Flags, Services, Regexp, Replacements
])
);
encode_data(#dns_rrdata_ds{
keytag = KeyTag,
alg = Alg,
digest_type = DigestType,
digest = Digest
}) ->
escape_chars(
io_lib:format("~w ~w ~w ~s", [KeyTag, Alg, DigestType, Digest])
);
encode_data(#dns_rrdata_cds{
keytag = KeyTag,
alg = Alg,
digest_type = DigestType,
digest = Digest
}) ->
escape_chars(
io_lib:format("~w ~w ~w ~s", [KeyTag, Alg, DigestType, Digest])
);
encode_data(#dns_rrdata_dnskey{
flags = Flags, protocol = Protocol, alg = Alg, public_key = Key, keytag = KeyTag
}) ->
escape_chars(
io_lib:format("~w ~w ~w ~w ~w", [Flags, Protocol, Alg, Key, KeyTag])
);
encode_data(#dns_rrdata_cdnskey{
flags = Flags, protocol = Protocol, alg = Alg, public_key = Key, keytag = KeyTag
}) ->
escape_chars(
io_lib:format("~w ~w ~w ~w ~w", [Flags, Protocol, Alg, Key, KeyTag])
);
encode_data(
#dns_rrdata_rrsig{
type_covered = TypeCovered,
alg = Alg,
labels = Labels,
original_ttl = OriginalTtl,
expiration = Expiration,
inception = Inception,
keytag = KeyTag,
signers_name = SignersName,
signature = Signature
}
) ->
escape_chars(
io_lib:format(
"~w ~w ~w ~w ~w ~w ~w ~w ~s",
[
TypeCovered,
Alg,
Labels,
OriginalTtl,
Expiration,
Inception,
KeyTag,
SignersName,
Signature
]
)
);
encode_data(#dns_rrdata_tlsa{
usage = Usage,
selector = Selector,
matching_type = MatchingType,
certificate = Certificate
}) ->
escape_chars(
io_lib:format("~w ~w ~w ~s", [Usage, Selector, MatchingType, Certificate])
);
encode_data(Data) ->
?LOG_INFO(
#{what => unable_to_encode_rrdata, data => Data},
#{domain => [erldns, zones]}
),
not_implemented.
escape_chars(IoList) ->
binary:encode_hex(erlang:iolist_to_binary(IoList)).