Changelog
View SourceAll notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
main
v5.0.16
Fixed
decode_query/1no longer rejects rfc1995 IXFR queries asformerrbut asnotimp.
v5.0.15
Fixed
decode_message/1now decodes rfc2136 UPDATE messages, whiledecode_query/1does not anymore as it shouldn't have, returningnotimp.
v5.0.14
Updated
- Optimized
dns_domain:to_wire/3(compressed name encoding): 1.4–2.8x faster on typical names, up to 17–22x on many-label names such as IPv6 reverse PTRs, with 1.1–3x less allocation. - Optimized
dns_domain:from_wire/1,2(wire-format name decoding): ~1.1–1.2x faster on typical compressed names, up to 1.4–1.5x on pointer chains, with up to 18% less allocation on pointer-heavy names. - Optimized message encoding: ~1.1–1.3x faster on typical bounded responses with 5–35% less allocation across message shapes.
Fixed
- Correct name compression in the additional section of
encode_message/2for non-EDNS responses - NSEC/NSEC3/CSYNC/NXT type bitmap encoding shifted every type after the first by one bit position in any window whose first present type is a multiple of 256
- MINFO records failed to decode inside full messages (
formerr) due to swappeddns_domain:from_wire/2arguments in the MINFO rdata decoder encode_message/2subtracted the question section twice when sizing the OPT RR and additional records, wrongly dropping them (including the EDNS OPT RR, contra RFC 6891) from responses within question-size bytes ofmax_size- LOC latitude and longitude used
2^31 - 1instead of2^31as the equator/prime-meridian reference point (RFC 1876 §2) - LOC
size/horiz/vertoutside the representable 0–9e9 cm range now raisebadarg, and in-range values round to nearest instead of truncating (RFC 1876 §2) encode_message/2withtc_mode => llq_eventraisedbadmatchwhen the authority/additional tail or the question section exceededmax_size; it now truncates and sets TC- Zero-length
<character-string>s were dropped when encoding TXT, SPF, RESINFO and WALLET records (RFC 1035 §3.3) - A NAPTR record whose REGEXP is not valid UTF-8 decoded into a record holding an error tuple instead of being rejected (RFC 3403 §4.1)
- An EDNS OPT RR advertising a UDP payload size below 512 is clamped to 512 instead of raising
badarg(RFC 6891 §6.2.3) encode_message/2with an unsupportedtsigalgorithm raisedcase_clauseinstead ofbadarg- An SVCB/HTTPS
alpnid longer than 255 bytes silently truncated its length octet, producing undecodable wire data; it now raises{svcb_invalid_alpn_id, _} - SVCB/HTTPS
mandatory,ipv4hintandipv6hintvalues that are not a whole number of elements are rejected instead of silently dropping the remainder (RFC 9460 §7.4, §8) - An EDNS OPT RR with a non-root owner name, and a message carrying more than one OPT RR, now decode to
formerr(RFC 6891 §6.1.1) RDLENGTH = 0for a type this library decodes now decodes toformerrinstead of an opaque<<>>(RFC 1035 §3.2.1)- An OPT RR anywhere but first in the additional section was ignored when sizing the response and dropped from truncated ones (RFC 6891 §6.1.1)
- URI targets were replaced by their normalized form when decoding, losing data and changing the canonical RDATA that RRSIGs cover (RFC 7553 §4.5)
- A DNSKEY or CDNSKEY with a DSA algorithm but rdata too short to parse as one crashed on re-encode (RFC 2536 §2)
- Re-encoding a DSA DNSKEY whose P began with a zero byte truncated G and Y, producing an undecodable record (RFC 2536 §2)
encode_rrdata/2crashed withbadmapon every KX record, and with it the DNSSEC canonical form (RFC 2230)- A repeated or out-of-order NSEC/NSEC3/CSYNC type-bitmap window decoded to a types list containing duplicates (RFC 4034 §4.1.2)
- LOC precision octets with a base nibble above nine were accepted instead of being left opaque (RFC 1876 §2)
encode_message/1,2would emit a message carrying two OPT RRs, which the decoder rejects (RFC 6891 §6.1.1)- A non-canonically encoded RSA DNSKEY/CDNSKEY public key changed shape when re-encoded, altering the canonical RDATA an RRSIG covers (RFC 3110 §2)
v5.0.13
Fixed
- Correctly return
formerron invalid NOTIFY DNS messages (rfc1996 §3.7: a NOTIFY carries exactly one question (QDCOUNT=1) and at most one), (#130)
v5.0.12
Fixed
- A malformed EDNS COOKIE option (RFC 7873) in a received message now decodes to a
formerrresult instead of raisingbad_cookie.
v5.0.11
Fixed
- WALLET (type 262) RDATA uses TXT-style character-strings on the wire and in zone files (
dataas a list of binaries), per IANA WALLET. - Zone file parsing and RDATA decoding: improved handling of BIND-style presentations and record types;
- Empty TXT/RESINFO RDATA are rejected during semantic validation;
- Empty A/AAAA RDATA is rejected (no longer skipped);
v5.0.10
Updated
- Minimal performance improvement for
dns_domain:to_lower/1,dns_domain:to_upper/1, anddns_domain:are_equal/2
v5.0.9
Updated
- Minimal performance improvement for
dns_domain:are_equal_labels/2
v5.0.8
Fixed
- Handle truncated RR headers in additional and body sections (#121)
v5.0.7
Changed
- Minor internal cleanups in the dnssec module (better function naming)
v5.0.6
Added
dnssecexports record types it works over as types.
Fixed
- Fixed encoding and decoding of ECDSA signatures
- Refactored
dnssecto use the newerdns_domainAPI internally in a more efficient way - Incremented test coverage for DNSSEC
Removed
- Internal ASN1 parser, as it is supported by OTP's
public_keymodule.
v5.0.5
Fixed
- SVCB/HTTPS params: treat numeric keys key0–key6 as reserved and equivalent to named params (mandatory, alpn, no-default-alpn, port, ipv4hint, ech, ipv6hint). Validate them the same at ingestion in zone parsing, JSON parsing, and wire decoding; key0–key6 are no longer accepted as generic unknown keys (#110, #111)
- SVCB params JSON docs: document key0–key6 equivalence to named params, no-default-alpn as null, and keyNNNN format (value binary or null) in generated JSON documentation
- SVCB params wire: decode unknown keys with zero-length value as
none(not<<>>) so round-trip andto_jsonstay consistent (null vs empty binary) - SVCB params JSON: reject invalid param keys in
to_json/1(e.g. key > 65535) with{svcb_param_invalid_key, K}instead of emitting a map withundefinedas key - Ensure strict parsing of IPv4 and IPv6 in zonefiles respectively (#108)
v5.0.4
Fixed
- Fix parsing SVCB json records when
svc_paramsare missing
v5.0.3
Fixed
- Fix FQDNs an (C)DNSKEY payloads in zonefile encoding
v5.0.2
Changed
- Use nulls instead of none in SVCB params JSON payloads #107
v5.0.1
Fixed
- Fix an issue with the hex package not including all needed files
v5.0.0
Added
- Add new
dns_jsonmodule for bidirectional Record <-> JSON/Map transcoding - Add DNS zone file encoding functionality — convert DNS resource records to RFC 1035 zone file format
dns_domain:to_lower/1anddns_domain:to_upper/1for case conversiondns_domain:are_equal/2anddns_domain:are_equal_labels/2for case-insensitive comparisondns_domain:escape_label/1anddns_domain:unescape_label/1for label escaping- Improved performance with chunked binary pattern matching
- Better RFC1035 and RFC9267 compliance with accurate wire format size tracking
Changed
- Require OTP 27 or later (
minimum_otp_vsnset to "27") dns:encode_message/2changed how truncation is returned to a clearer type- Migrate domain name operations to new
dns_domainmodule
All domain name processing functions have been moved to a new optimized
dns_domain module. The old implementations in dns and related helper
modules have been removed and replaced with calls to the new module.
Migration guide
All domain name functions have been moved to dns_domain. Update your code as follows:
% Old → New
dns:dname_to_lower(Name) -> dns_domain:to_lower(Name)
dns:dname_to_upper(Name) -> dns_domain:to_upper(Name)
dns:dname_to_labels(Name) -> dns_domain:split(Name)
dns:labels_to_dname(Labels) -> dns_domain:join(Labels)
dns:dname_to_lower_labels(Name) -> dns_domain:split(dns_domain:to_lower(Name))
dns:compare_dname(NameA, NameB) -> dns_domain:are_equal(NameA, NameB)
dns:compare_labels(LabelsA, LabelsB) -> dns_domain:are_equal_labels(LabelsA, LabelsB)
dns:escape_label(Label) -> dns_domain:escape_label(Label)
dns_encode:encode_dname(Name) -> dns_domain:to_wire(Name)
dns_encode:encode_dname(CM, Pos, N) -> dns_domain:to_wire(CM, Pos, N)Note: The wrapper functions in dns module (dname_to_labels/1, labels_to_dname/1,
dname_to_lower_labels/1, dname_to_upper/1, dname_to_lower/1, compare_dname/2,
compare_labels/2, escape_label/1) have been removed. Use dns_domain functions directly now.
Error Handling Changes:
- decoding invalid wire packets previously used
throw/1for errors (decode_loop,bad_pointer), it useserror/1now - Update error handling:
try dns:decode_message(...) catch error:Reason -> ... end
Removed
- Removed old
dns_recordanddns_record_infomodules
4.9.1
Fixed
- Fix a bug that would incorrectly calculate pointers, introduced in 4.9.0
4.9.0
Added
- Add extended support for SVCB and HTTPS Resource Records — RFC9460
- Add support for OPENPGPKEY (Type 61) — RFC 7929
- Add support for SMIMEA (Type 53) — RFC 8162
- Add support for URI (Type 256) — RFC 7553
- Add support for WALLET (Type 262) — IANA Registration
- Add support for EUI48 (Type 108) and EUI64 (Type 109) — RFC 7043
- Add support for CSYNC (Type 62) — RFC 7477
- Add support for DSYNC (Type 66) — RFC 9859
- Add
dns:decode_query/1function for strict query validation to prevent DoS attacks
Changed
- Performance improvements in message encoding (~5-15% faster for encode/1, ~0-20% faster for encode/2)
4.8.1
Fixed
- Fix bad size for reserved OptRR record during encoding
4.8.0
Added
- Add support for RFC8976: Message Digest for DNS Zones
Fixed
- Fix Base64 lexing of zone files
4.7.0
Added
- Extend support for RFC8914: Extended DNS Errors.
4.6.0
Added
- Add support for DNS zone file parsing
4.5.0
Added
4.4.0
Added
4.3.0
Added
- Add support for TLSA records.
4.2.0
Added
- Add shortcuts for normalizing and converting domains into labels.
- Add a helper for comparing label lists.
- Add helpers to convert from and to codes into their string representation.
4.1.0
Added
- Add support for RFC7873 EDNS cookies encoding and decoding
4.0.1
Fixed
- Fix additional count when truncating a message
4.0.0
Changed
- Use
erlang:system_time/1for timestamps. - Use maps instead of proplists for options to be passed to encoding, decoding, TSIG, and DNSSEC functions.
- Encoding logic builds responses that contain the full question section, and optionally drop the answers if the response is to be truncated.
- Use consistent record names.
- Split names functions into a standalone
dns_namesmodule. - Extends and reorganise documentation.
3.1.3
Fixed
- Fix: now using the reserved space for the OPT RR records during the encoding of the message (#74)
3.1.2
Added
- Add NXNAME type to terms types.
3.1.1
Fixed
- Fix EDNS0 compliance for truncated records and unsupported versions
3.1.0
Fixed
- Fix EDNS0 compliance for truncated records and unsupported versions
3.0.5
Fixed
- Fix
max_sizein encode_message opts
3.0.4
Changed
- Upgrade dependencies
- Apply linter specs
3.0.3
Changed
- Performance improvements in string manipulations
3.0.2
Fixed
- Fix type definitions
3.0.1
Fixed
- Ensure ASN1 compilation before building package
3.0.0
Added
- Add xref, dialyzer, and ex_doc
- Add strict typing and RFC references to all records
- Add support for TXT splitting of strings over the maximum permitted size
2.0.0
Changed
- Bump to OTP/27
- Replace "jsx" with "json"
Added
- Erlfmt
- CONTRIBUTING.md
- CHANGELOG.md
- Release process to hex.pm
1.1.0
N/A