dnsbox 0.0.2

High-performance, zero-copy DNS message parsing and building for requests and responses, with broad RFC extension coverage.
Documentation
# dnsbox roadmap

`dnsbox` aims to be a fast, safe, `no_std` DNS wire-format library covering
both sides of the protocol: parsing and producing queries and responses,
with broad RFC extension coverage. This document lays out the design and the
order of work. Items are checked off as they land.

## Design principles

- **Safe on hostile input.** Every parser is written for untrusted network
  data: no panics, no out-of-bounds reads, bounded work per message
  (compression-pointer loops, label counts, record counts). The crate is
  `#![forbid(unsafe_code)]`; performance comes from layout and algorithms,
  not from `unsafe`.
- **Zero-copy parsing.** A parsed message is a view over the caller's
  `&[u8]`. Sections, records, names and RDATA are decoded lazily through
  iterators; nothing is allocated or copied unless asked for.
- **Single-pass, buffer-backed building.** Builders write directly into a
  caller-supplied `&mut [u8]` (or a `Vec` with `alloc`), with name
  compression, section-count bookkeeping and size limits handled internally.
- **Open enums.** Record types, classes, opcodes, rcodes, EDNS option codes
  and SvcParam keys are newtypes with associated constants, so unknown values
  round-trip losslessly (RFC 3597).
- **`no_std` first.** The core works with neither `alloc` nor `std`. `alloc`
  adds owned types and growable builders; `std` adds `std::io` glue.
- **Minimal dependencies.** None in the core. Cryptography (digests, HMAC,
  SipHash, RSA/ECDSA/EdDSA) is never implemented in dnsbox: it comes from
  the optional `purecrypto` dependency (`default-features = false`, no_std
  capable), enabled per feature (`dnssec-digest`, `dnssec`, `tsig`,
  `cookie-siphash`). Every crypto-using API sits behind a trait
  (`dnssec::{Signer, Verifier}`, `tsig::{TsigKey, TsigMac}`,
  `sig0::{Sig0Signer, Sig0Verifier}`) so alternative backends can be
  plugged in, and all wire-format work (signed data, MAC input, canonical
  forms, key tags) works without it. Other optional integrations (serde,
  async I/O) live behind features too.
- **MSRV 1.89**, edition 2024. MSRV bumps are minor-version changes.

## Milestone 0 — Foundation

- [x] Crate scaffold, CI, release automation
- [x] Error type
- [x] Header (RFC 1035 §4.1.1): ID, flags, opcode, rcode, section counts
- [x] Bounds-checked wire reader (cursor over `&[u8]`) and writer (cursor
      over `&mut [u8]`), the primitives every later layer builds on
- [x] Open newtypes: `Rtype`, `Class`, with IANA mnemonics and parsing from
      text mnemonics (`A`, `TYPE65534`, `IN`, `CLASS3`)

## Milestone 1 — Core RFC 1035 parsing

- [x] Domain names
  - [x] Wire-format label parsing with compression pointers (RFC 1035 §4.1.4)
  - [x] Hardening: forward/self-pointer rejection, hop limit, 255-octet name
        limit, 63-octet label limit
  - [x] Borrowed `Name<'a>` (lazy, pointer-following) and an inline/owned
        uncompressed form
  - [x] Case-insensitive comparison and hashing (RFC 4343), canonical
        ordering (RFC 4034 §6.1)
  - [x] Presentation format with escapes (`\.`, `\DDD`)
  - [x] Reserved label types: reject extended label types (RFC 6891 §5)
- [x] `Message<'a>` view: header + section iterators (question, answer,
      authority, additional), validated against section counts
- [x] `Question` and `Record` views (name, type, class, TTL, raw RDATA)
- [x] Unknown-type RDATA passthrough (RFC 3597)
- [x] Typed RDATA for the RFC 1035 set: A, NS, CNAME, SOA, PTR, MX, TXT,
      HINFO, plus AAAA (RFC 3596)
- [x] Whole-message validation mode (walk once, report the first error) for
      callers that want to fail fast before iterating

## Milestone 2 — Building messages

- [x] `MessageBuilder` over `&mut [u8]` with runtime-checked section
      ordering (question → answer → authority → additional)
- [x] Name compression with a fixed-size, allocation-free suffix table;
      option to disable compression (and never compress inside RDATA of
      types where RFC 3597 forbids it)
- [x] Automatic section counts
- [x] Size limits and truncation: stop at a max size, set TC, roll back the
      partial RRset (RFC 2181 §9); `Truncation::Error` / `SetTc` policies,
      reserve for OPT/TSIG, `copy_section` / `copy_message`
- [x] Convenience constructors: query for (name, type), response skeleton
      from a parsed query (copies ID, opcode, RD, CD, question; EDNS echo
      with `start_response_edns`)
- [x] Growable `Vec`-backed builder (`alloc`)
- [x] TCP framing helpers (2-byte length prefix, RFC 1035 §4.2.2 / RFC 7766):
      frame splitting, allocation-free `FrameReassembler`, `std::io`
      helpers, length-prefixed builder
- [x] Appending pre-encoded records (`push_raw_records`) and copying parsed
      records with name recompression

## Milestone 3 — EDNS(0)

- [x] OPT pseudo-record (RFC 6891): UDP payload size, extended RCODE
      (combined with the header RCODE), version, DO bit (other flag bits
      preserved), option iteration and building; open `OptionCode` with
      the full IANA registry
- [x] Options:
  - [x] Client Subnet (RFC 7871)
  - [x] Cookies (RFC 7873, RFC 9018 interoperable server cookies; SipHash
        from purecrypto behind `cookie-siphash`)
  - [x] Padding (RFC 7830) with RFC 8467 padding policies in the builder
  - [x] TCP keepalive (RFC 7828)
  - [x] Extended DNS Errors (RFC 8914)
  - [x] NSID (RFC 5001)
  - [x] Chain query (RFC 7901), Key tag (RFC 8145), Expire (RFC 7314)
  - [x] Zone version (RFC 9660), Report-Channel (RFC 9567)
  - [x] DAU/DHU/N3U (RFC 6975)
- [x] Unknown options pass through untouched

## Milestone 4 — Record type coverage

- [x] SRV (RFC 2782), NAPTR (RFC 3403), CAA (RFC 8659), SSHFP (RFC 4255,
      RFC 6594), TLSA (RFC 6698), SMIMEA (RFC 8162), OPENPGPKEY (RFC 7929)
- [x] DNAME (RFC 6672), LOC (RFC 1876), RP / AFSDB (RFC 1183), URI
      (RFC 7553), CERT (RFC 4398), DHCID (RFC 4701), NID/L32/L64/LP
      (RFC 6742), EUI48/EUI64 (RFC 7043), CSYNC (RFC 7477), ZONEMD
      (RFC 8976; zone digests in Milestone 5), APL
      (RFC 3123), IPSECKEY (RFC 4025), HIP (RFC 8005), KX (RFC 2230)
- [x] SVCB and HTTPS (RFC 9460) with typed SvcParams: mandatory, alpn,
      no-default-alpn, port, ipv4hint, ipv6hint, ech, dohpath (RFC 9461),
      ohttp (RFC 9540), plus tls-supported-groups, docpath, pvd, oots;
      unknown keys pass through; `SvcbBuilder`; presentation parsing
      (`Svcb::from_text`)
- [x] Obsolete/legacy types: X25, ISDN, RT, GPOS, NSAP, NSAP-PTR, PX, A6,
      NXT, EID, NIMLOC, ATMA, SINK, NINFO, RKEY, TALINK, SPF, AVC, RESINFO,
      WALLET typed; UINFO/UID/GID/UNSPEC opaque with mnemonics
- [x] Presentation-format (zone-file style) `Display` for every typed RDATA

## Milestone 5 — DNSSEC

Wire format and validation logic live in dnsbox and need no crypto; the
digest and signature calls come from `purecrypto` behind features
(`dnssec-digest`: DS digests and NSEC3 hashing, no `alloc`; `dnssec`:
signatures), through the pluggable `Verifier` / `Signer` traits.

- [x] DNSKEY, RRSIG, NSEC, DS (RFC 4034), NSEC3, NSEC3PARAM (RFC 5155),
      CDS/CDNSKEY (RFC 7344, RFC 8078 delete forms), KEY/SIG (RFC 2535,
      RFC 2931), DLV/TA
- [x] Open newtypes for algorithm numbers, DS digest types and NSEC3 hash
      algorithms (IANA registries)
- [x] Type bitmap parsing and building
- [x] Canonical RR form and canonical RRset ordering (RFC 4034 §6,
      RFC 6840 §5.1), allocation-free
- [x] Key tag computation, DS digest input construction
- [x] NSEC3 hashing (base32hex owner names)
- [x] RRSIG validation logic: signed data, labels/wildcard reconstruction,
      RFC 1982 validity window, key matching (RFC 4035 §5.3)
- [x] Signature verification and signing via purecrypto (`dnssec`
      feature): RSA/SHA-1, RSA/SHA-1-NSEC3, RSA/SHA-256, RSA/SHA-512, ECDSA
      P-256/P-384, Ed25519, Ed448; DNSKEY/DS generation from keys. GOST,
      SM2/SM3, DSA and RSA/MD5 are not supported (`UnsupportedAlgorithm`)
- [x] Authenticated denial of existence: NSEC/NSEC3 proof checking
      (RFC 4035 §5.4, RFC 5155 §8, RFC 6840 §4, RFC 7129) with
      closest-encloser proofs, Opt-Out as insecure and RFC 9276 iteration
      limits (`dnssec::denial`)
- [x] Chain of trust: DNSKEY authentication from DS or trust anchors,
      RRset and wildcard-answer verification, KeyTrap work bound
      (`dnssec::chain`)
- [x] ZONEMD zone digest computation and verification (RFC 8976,
      `dnssec::zonemd`)

## Milestone 6 — Transactions, updates and zone transfer

- [x] TSIG (RFC 8945): record parsing, MAC input construction, signing and
      verification (requests, responses, TCP streams, error responses)
      through the `TsigKey` / `TsigMac` traits; HMAC-MD5/SHA-1/SHA-2 from
      purecrypto behind the `tsig` feature
- [x] SIG(0) (RFC 2931): signed-data construction, sign/find/verify through
      `Sig0Signer` / `Sig0Verifier`; RSA/ECDSA/EdDSA via the DNSSEC
      backend adapters
- [x] Dynamic UPDATE (RFC 2136) message helpers (zone/prerequisite/update
      sections, every prerequisite and deletion encoding)
- [x] NOTIFY (RFC 1996)
- [x] AXFR/IXFR (RFC 5936, RFC 1995) multi-message stream helpers
- [x] DNS Stateful Operations (RFC 8490) TLV framing

## Milestone 7 — Text formats and owned data (`alloc`)

- [x] Owned `OwnedMessage` / `OwnedRecord` / `OwnedRData` types with
      conversion from views, from zone-file records and from text
- [x] Zone-file / presentation-format parser (RFC 1035 §5) for records:
      `ParseRdataText` for every type, `ZoneReader` with `$ORIGIN`,
      `$TTL`, `$INCLUDE` and `$GENERATE`
- [x] `dig`-style message `Display`
- [x] Optional `serde` support

## Milestone 8 — Performance and assurance

- [x] Criterion benchmarks: parse/iterate/build for typical queries,
      large responses, heavily compressed messages; comparisons against
      `hickory-proto` and `domain` (`benches/`, `BENCH.md`)
- [x] cargo-fuzz targets: message parsing (plus EDNS, TSIG/SIG(0), UPDATE,
      NOTIFY, XFR and DSO views), name decompression, RDATA (every
      registered type), EDNS options, build→parse round-trip,
      presentation-format parser (whole zone files; every type's
      displayed RDATA parses back)
- [x] Property tests: build→parse and parse→build→parse identity
- [x] Interop corpus: real-world captures, plus responses from BIND,
      Unbound, Knot and PowerDNS (also NSD, Knot Resolver, PowerDNS
      Recursor, public resolvers)
- [x] Allocation-free hot path verified in CI (no-alloc build + tests)
- [x] Hot-path tuning: name decoder and suffix cache, fixed-field
      parsing, label-trie compression table (`BENCH.md`: faster than
      `domain` and `hickory-proto` on every benchmark)

## Milestone 9 — 1.0

- [x] API review: naming, error granularity, feature layout (the
      conventions are in `ARCHITECTURE.md`, the breaking changes in
      `CHANGELOG.md`)
- [ ] Complete rustdoc with examples on every public item
- [ ] SECURITY.md threat model finalized after a fuzzing campaign
- [ ] Stability commitment and MSRV policy documented

## Out of scope

`dnsbox` is a wire-format library. Resolvers, caches, server frameworks and
socket handling belong in crates built on top of it. Transport framing
helpers (TCP length prefix, DoT/DoH/DoQ message shaping per RFC 7858,
RFC 8484, RFC 9250) are in scope only insofar as they are pure byte
transformations.