1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
//! Passive DNS parsing (UDP/53).
//!
//! Parses DNS query/response messages observed in UDP/53 traffic.
//!
//! [`DnsUdpParser`] is the integration point — a
//! [`DatagramParser`](crate::DatagramParser) impl yielding a typed
//! [`DnsMessage`] stream. Pair it with [`crate::FlowDatagramDriver`],
//! [`PcapFlowSource::datagrams`](crate::pcap::PcapFlowSource::datagrams),
//! or netring's `datagram_stream`. With correlation enabled
//! ([`DnsUdpParser::with_correlation`]) it matches responses to
//! queries — round-trip time lands in `DnsResponse::elapsed`, and
//! `on_tick` emits [`DnsMessage::Unanswered`] for queries that time
//! out. The [`Correlator`] is also public for advanced
//! custom-scoped correlation.
//!
//! # Quick start (stateless message parsing)
//!
//! ```no_run
//! use flowscope::dns::{parse_message, DnsParseResult};
//!
//! let payload: &[u8] = b""; // your UDP/53 payload
//! match parse_message(payload) {
//! Ok(DnsParseResult::Query(q)) => println!("query: {} questions", q.questions.len()),
//! Ok(DnsParseResult::Response(r)) => println!("response: rcode={:?}", r.rcode),
//! Err(_e) => {} // malformed — ignore
//! }
//! ```
//!
//! # Scope
//!
//! - **UDP/53 only** in v0.1. TCP/53 (large responses, AXFR/IXFR)
//! and DoT (TLS/853) are deferred.
//! - **Passive** — no resolution, no validation.
//! - DNSSEC: RRSIG/DNSKEY surface as [`DnsRdata::Other`] with raw
//! rdata; we don't validate.
//! - **Common record types** decoded: A, AAAA, CNAME, NS, PTR, MX.
//! Everything else: `DnsRdata::Other { rtype, data }`.
//!
//! # Convenience accessors
//!
//! ## [`DnsQuery`] / [`DnsResponse`]
//!
//! | Field / method | Returns | Notes |
//! |----------------|---------|-------|
//! | `id` | `u16` | transaction ID (matches query ↔ response) |
//! | `questions` | `Vec<DnsQuestion>` | name + rtype + rclass per query slot |
//! | `answers` (response) | `Vec<DnsRecord>` | A / AAAA / CNAME / NS / PTR / MX |
//! | `rcode` (response) | [`DnsRcode`] | response code |
//! | `elapsed` (correlated response) | `Option<Duration>` | round-trip time |
//!
//! ## [`DnsFlags`]
//!
//! | Method | Returns |
//! |--------|---------|
//! | [`is_response`](DnsFlags::is_response) | `bool` |
//! | [`is_authoritative`](DnsFlags::is_authoritative) | `bool` |
//! | [`is_truncated`](DnsFlags::is_truncated) | `bool` |
//! | [`is_recursion_desired`](DnsFlags::is_recursion_desired) | `bool` |
//! | [`is_recursion_available`](DnsFlags::is_recursion_available) | `bool` |
//! | [`opcode`](DnsFlags::opcode) | `u8` |
//! | [`rcode_raw`](DnsFlags::rcode_raw) | `u8` |
pub use Correlator;
pub use ;
pub use ;
pub use ;
pub use ;
pub use DnsResolutionCache;
pub use DnsTcpParser;
pub use *;
/// Slug returned by [`DnsUdpParser`]'s `parser_kind()`. See
/// `flowscope::parser_kinds::DNS_UDP`.
///
/// Stability: locked from 0.8 forward.
pub const PARSER_KIND_UDP: &str = "dns-udp";
/// Slug returned by [`DnsTcpParser`]'s `parser_kind()`. See
/// `flowscope::parser_kinds::DNS_TCP`.
///
/// Stability: locked from 0.8 forward.
pub const PARSER_KIND_TCP: &str = "dns-tcp";