DNS wire format encoder/decoder per RFC 1035.
Pure functional module โ no side effects. Handles the subset of DNS needed for mDNS/DNS-SD service discovery.
Uses Erlang's :binary module for efficient parsing.
- Name encoding with length-prefixed labels
- Name decoding with pointer compression
- Record types: A, AAAA, PTR, SRV, TXT
- Complete message encode/decode
Example
# Encode a query
query = %{
id: 0, qr: :query, aa: false,
questions: [%{name: "_matterc._udp.local", type: :ptr, class: :in}],
answers: [], authority: [], additional: []
}
binary = DNS.encode_message(query)
# Decode a message
{:ok, msg} = DNS.decode_message(binary)
Summary
Functions
Decode a binary DNS message.
Decode a domain name from a DNS message binary.
Decode TXT record data into a list of strings.
Encode a complete DNS message to binary.
Encode a domain name as length-prefixed labels.
Encode record-type-specific data (rdata).
Encode TXT record data from a list of strings.
Functions
Decode a binary DNS message.
Returns {:ok, message_map} or {:error, reason}.
@spec decode_name(binary(), non_neg_integer()) :: {String.t(), non_neg_integer()}
Decode a domain name from a DNS message binary.
Handles pointer compression (top 2 bits = 0b11 โ offset pointer).
Returns {name, bytes_consumed} where bytes_consumed is the number
of bytes read from the current position (not following pointers).
Decode TXT record data into a list of strings.
Encode a complete DNS message to binary.
Message format
%{
id: 0,
qr: :query | :response,
aa: boolean(),
questions: [%{name: String.t(), type: atom(), class: :in}],
answers: [record()],
authority: [record()],
additional: [record()]
}Record format
%{
name: String.t(),
type: :a | :aaaa | :ptr | :srv | :txt,
class: :in,
cache_flush: boolean(), # mDNS cache-flush bit (optional, default false)
ttl: non_neg_integer(),
data: term() # type-specific
}
Encode a domain name as length-prefixed labels.
Examples
iex> DNS.encode_name("local")
<<5, "local", 0>>
iex> DNS.encode_name("_matterc._udp.local")
<<9, "_matterc", 4, "_udp", 5, "local", 0>>
Encode record-type-specific data (rdata).
Encode TXT record data from a list of strings.
Each string is length-prefixed (1 byte length + string bytes). An empty list produces a single zero byte (RFC 6763 ยง6.1).
Examples
iex> DNS.encode_txt(["D=3840", "CM=1"])
<<6, "D=3840", 4, "CM=1">>