Skip to main content

Module parser

Module parser 

Source
Expand description

Minimal DNS message parser scoped to what the SEAM-1 / L2-04 proxy needs.

Pure logic, no I/O. The proxy parses the wire-format query, makes an allowlist decision against crate::dns_proxy::DnsProxyConfig::hostname_allowlist, then either forwards the bytes verbatim upstream (allow path) or builds a REFUSED response from the parsed view (deny path).

§Phase 2 scope (multi-question)

  • Exactly one question on the hot path. A DNS message with QDCOUNT == 0 is rejected as malformed (nothing to evaluate). HIGH-D1 hardened the single-question API (parse_query) further: any packet declaring QDCOUNT != 1 is rejected at the parser layer with DnsParseError::QdcountUnsupported. RFC 1035 §4.1.2 permits QDCOUNT > 1, but real-world recursive resolvers (Unbound, Knot, BIND) serve at most the first question and the supervisor’s threat model (hostile guests) does not justify the policy-bypass / log-evasion surface that “parse first question, forward all bytes” exposes. The typed offline API parse_query_multi still returns one QuestionOutcome per declared question for tools that legitimately need to walk multi-question packets (e.g. fixture inspection).
  • No pointer-compression in QNAME. RFC 1035 §4.1.4 allows a label to be replaced by a 2-byte pointer to an earlier label. Real workload-side queries almost never use compression — the questions section is the only labels the message carries — so the parser rejects pointers as a defense against malformed/adversarial inputs that could otherwise drive the parser into a cycle. Compression in responses is handled by passing the wire bytes through untouched on the allow path.
  • IN class only. qclass != 1 is rejected for any question.
  • RFC 1035 length bounds. Labels capped at 63 octets; total QNAME capped at 253 octets (the RFC 1035 §3.1 maximum once you remove the trailing root label and the length prefixes).

§What the parser surfaces

DnsQueryView carries the transaction id (echoed back in the proxy’s response when denying), the flags word (so the proxy can OR in QR=1 + RCODE=REFUSED for the deny path), the lowercased trailing-dot-stripped query name, and the raw wire-format qtype / qclass fields. The proxy maps the raw qtype to the bounded cellos_core::DnsQueryType enum via cellos_core::qtype_to_dns_query_type; query types outside that set produce a denied_query_type decision rather than a parser error.

Structs§

DnsQueryView
Minimal view of a parsed single-question DNS query.

Enums§

DnsParseError
Errors the parser can surface. Each maps to a reasonCode on the emitted dns_query event:
QuestionOutcome
Per-question outcome returned by parse_query_multi.

Functions§

parse_query
Parse the question section of a workload DNS query (single-question API).
parse_query_multi
Parse every question declared by QDCOUNT and return one QuestionOutcome per question.