Skip to main content

Crate dnsbox

Crate dnsbox 

Source
Expand description

§dnsbox

High-performance DNS message parsing and building, for both queries and responses.

The design goals, in order:

  1. 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)].
  2. Zero-copy, allocation-free parsing. Messages are parsed as views over the caller’s buffer; names and record data are decoded lazily.
  3. Fast building. Messages are written straight into a caller-supplied buffer, with name compression handled by the builder.
  4. Broad RFC coverage. EDNS(0), DNSSEC, SVCB/HTTPS, and the long tail of record types — see ROADMAP.md for 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.

FeatureDefaultAdds
stdyesstd::io TCP helpers (tcp::read_message, tcp::write_message), $INCLUDE from the file system (zone::FsIncludes); implies alloc
allocVec-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-digestDS digests and NSEC3 hashing (dnssec::verify_ds, dnssec::nsec3_hash) without alloc; with alloc, ZONEMD digests
dnssecDNSSEC and SIG(0) signature verification and signing: RSA, ECDSA P-256/P-384, Ed25519, Ed448; implies alloc and dnssec-digest
tsigthe TSIG HMAC backend (tsig::HmacKey: HMAC-MD5, SHA-1, SHA-2)
cookie-siphashRFC 9018 server cookies (edns::ServerCookie::generate / verify)
serdeSerialize / 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, Display prints the mnemonic or the generic form (TYPE65534) and FromStr parses both back.
  • Views borrow the caller’s buffer (Message<'a>, Name<'a>, every type in rdata); parse / from_wire read wire data, from_text presentation format; as_wire returns a view’s wire form, as_bytes the contents of a buffer or an opaque field.
  • Builders write into an OutBuf: a WireWriter over a caller’s &mut [u8] (new), or, with alloc, a Vec<u8> (new_vec); any OutBuf (from_buf). set_* methods configure a builder in place; with_* methods take a value and return it modified (builder style).
  • Every public type is Send and Sync (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;alloc
pub use owned::OwnedQuestion;alloc
pub use owned::OwnedRData;alloc
pub use owned::OwnedRecord;alloc
pub 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).
ownedalloc
Owned, heap-backed messages, questions and records (alloc feature).
rdata
Record data (RDATA): the ParseRdata / ComposeRdata traits, the typed RData enum, 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 Display implementations: 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>.