Expand description
§dnsbox
High-performance DNS message parsing and building, for both queries and responses.
The design goals, in order:
- Safe on hostile input. Parsing never panics and never reads out of
bounds; malformed messages are rejected with an
Error. The crate is#![forbid(unsafe_code)]. - Zero-copy, allocation-free parsing. Messages are parsed as views over the caller’s buffer; names and record data are decoded lazily.
- Fast building. Messages are written straight into a caller-supplied buffer, with name compression handled by the builder.
- Broad RFC coverage. EDNS(0), DNSSEC, SVCB/HTTPS, and the long tail
of record types — see
ROADMAP.mdfor the plan.
The crate is no_std; the alloc and std features add owned types and
standard-library integration (see Cargo features).
§Parsing
use dnsbox::{Message, Rtype, rdata::RData};
let msg = Message::parse(wire)?;
for rr in msg.answers() {
let rr = rr?;
if let RData::A(a) = rr.data()? {
println!("{} has address {}", rr.name(), a.addr);
}
}§Building
use dnsbox::{Class, MessageBuilder, NameBuf, Rtype, Flags};
let name: NameBuf = "example.com".parse()?;
let mut buf = [0u8; 512];
let mut b = MessageBuilder::new(&mut buf)?;
b.set_id(0x1234);
b.set_flags(Flags::default().with_rd(true));
b.push_question(&name, Rtype::A, Class::IN)?;
let wire = b.finish();
assert_eq!(wire.len(), 29);§Text, owned data and serde
A Message displays in dig style (BIND 9’s layout, no allocation).
With alloc, OwnedMessage and friends (owned) copy a message
out of its buffer and write it back through the builder. Text parses
back too: ParseRdataText and RData::parse_text read a record’s
presentation format, and zone::ZoneReader reads RFC 1035 master
files, both without allocating. The serde
feature (no_std) serializes protocol numbers (Rtype, Class,
Opcode, Rcode, every registry newtype) as mnemonics such as
"MX" or "TYPE65534" in human-readable formats and as integers
otherwise, names as presentation strings, Flags as a struct of
bits, and, with alloc, the owned types.
§Cargo features
Every feature is additive, and the crate builds with none of them
(no_std, no allocation, no dependencies). Items that need a feature
are labelled with it in the documentation.
| Feature | Default | Adds |
|---|---|---|
std | yes | std::io TCP helpers (tcp::read_message, tcp::write_message), $INCLUDE from the file system (zone::FsIncludes); implies alloc |
alloc | Vec-backed builders (MessageBuilder::new_vec), the owned types (owned), zone::ZoneReader::records and zone::parse, DNSSEC RRset sorting and ZONEMD collation, the SIG(0) adapters over the DNSSEC traits | |
dnssec-digest | DS digests and NSEC3 hashing (dnssec::verify_ds, dnssec::nsec3_hash) without alloc; with alloc, ZONEMD digests | |
dnssec | DNSSEC and SIG(0) signature verification and signing: RSA, ECDSA P-256/P-384, Ed25519, Ed448; implies alloc and dnssec-digest | |
tsig | the TSIG HMAC backend (tsig::HmacKey: HMAC-MD5, SHA-1, SHA-2) | |
cookie-siphash | RFC 9018 server cookies (edns::ServerCookie::generate / verify) | |
serde | Serialize / Deserialize (no_std) for the registries, names, header flags and, with alloc, the owned types |
dnsbox never implements cryptography: the crypto features enable the
optional, no_std purecrypto
dependency. Every crypto-using API sits behind a trait
(dnssec::Verifier, dnssec::Signer, tsig::TsigKey,
sig0::Sig0Signer, …) so other backends can be plugged in, and the
wire-format side (signed data, MAC input, canonical forms) works without
any feature.
§Errors
Fallible functions return Result<T> with the crate-wide
Error: one byte, Copy, #[non_exhaustive]. Zone-file errors carry
their position (zone::ZoneError) and convert into Error with ?.
Parsing never panics on hostile input; see SECURITY.md.
§Conventions
- Protocol numbers (
Rtype,Class,Opcode,Rcode,edns::OptionCode,dnssec::Algorithm, …) are open newtypes: unknown values round-trip,Displayprints the mnemonic or the generic form (TYPE65534) andFromStrparses both back. - Views borrow the caller’s buffer (
Message<'a>,Name<'a>, every type inrdata);parse/from_wireread wire data,from_textpresentation format;as_wirereturns a view’s wire form,as_bytesthe contents of a buffer or an opaque field. - Builders write into an
OutBuf: aWireWriterover a caller’s&mut [u8](new), or, withalloc, aVec<u8>(new_vec); anyOutBuf(from_buf).set_*methods configure a builder in place;with_*methods take a value and return it modified (builder style). - Every public type is
SendandSync(when its type parameters are).
See ARCHITECTURE.md in the repository for the module layout and the
extension recipes (adding record types, EDNS options, …).
Re-exports§
pub use builder::Checkpoint;pub use builder::MessageBuilder;pub use charstr::CharStr;pub use class::Class;pub use header::Flags;pub use header::Header;pub use header::Opcode;pub use header::Rcode;pub use message::Message;pub use message::Question;pub use message::Record;pub use message::Section;pub use name::Label;pub use name::Name;pub use name::NameBuf;pub use name::ToName;pub use owned::OwnedMessage;allocpub use owned::OwnedQuestion;allocpub use owned::OwnedRData;allocpub use owned::OwnedRecord;allocpub use rdata::ComposeRdata;pub use rdata::ParseRdata;pub use rdata::ParseRdataText;pub use rdata::RData;pub use rtype::Rtype;pub use wire::Composer;pub use wire::NameEncoding;pub use wire::OutBuf;pub use wire::WireReader;pub use wire::WireWriter;
Modules§
- builder
- Single-pass message building (RFC 1035 §4.1).
- charstr
<character-string>s (RFC 1035 §3.3): a length octet followed by up to 255 bytes of arbitrary data.- class
- Resource record CLASSes and QCLASSes (RFC 1035 §3.2.4–3.2.5, RFC 6895 §3.2).
- dnssec
- DNSSEC (RFC 4033, RFC 4034, RFC 4035, RFC 5155, RFC 6840): algorithm registries, canonical forms, key tags, DS digests, NSEC3 hashing, RRSIG validation and signing, the chain of trust, authenticated denial of existence, and ZONEMD zone digests (RFC 8976).
- dso
- DNS Stateful Operations: DSO (RFC 8490).
- edns
- EDNS(0) (RFC 6891): the OPT pseudo-record, option codes, and typed options.
- header
- The fixed 12-byte DNS message header (RFC 1035 §4.1.1).
- message
- Zero-copy message views (RFC 1035 §4.1).
- name
- Domain names (RFC 1035 §2.3.4, §3.1, §4.1.4).
- notify
- Zone change notification: NOTIFY (RFC 1996).
- owned
alloc - Owned, heap-backed messages, questions and records (
allocfeature). - rdata
- Record data (RDATA): the
ParseRdata/ComposeRdatatraits, the typedRDataenum, and one module per record type (or tightly related family). - rtype
- Resource record TYPEs and QTYPEs (RFC 1035 §3.2.2–3.2.3, RFC 6895 §3.1).
- sig0
- SIG(0) transaction signatures (RFC 2931).
- tcp
- DNS over TCP framing (RFC 1035 §4.2.2, RFC 7766 §8).
- text
- Presentation-format (zone-file text) helpers shared by
Displayimplementations: escaping (RFC 1035 §5.1), hex, base64 and base32hex (RFC 4648), and the generic RDATA form of RFC 3597 §5. - tsig
- Transaction signatures: TSIG (RFC 8945).
- update
- Dynamic UPDATE messages (RFC 2136).
- wire
- Bounds-checked wire-format primitives.
- xfr
- Zone transfers: AXFR (RFC 5936) and IXFR (RFC 1995).
- zone
- Presentation format and master (zone) files (RFC 1035 §5).
Enums§
- Error
- Errors produced while parsing or building DNS messages.
Type Aliases§
- Result
- Shorthand for
core::result::Result<T, dnsbox::Error>.