1pub mod bitmap;
14pub mod builder;
15pub mod edns;
16pub mod header;
17pub mod query;
18pub mod rdata;
19pub mod rr;
20pub mod svcb;
21pub mod types;
22
23pub use builder::DnsBuilder;
24pub use query::DnsQuestion;
25pub use rdata::DnsRData;
26pub use rr::DnsResourceRecord;
27
28use crate::layer::field::{FieldError, FieldValue};
29use crate::layer::{Layer, LayerIndex, LayerKind};
30
31pub const DNS_HEADER_LEN: usize = header::DNS_HEADER_LEN;
33
34#[derive(Debug, Clone)]
39pub struct DnsLayer {
40 pub index: LayerIndex,
41}
42
43impl DnsLayer {
44 #[must_use]
46 pub fn new(start: usize, end: usize) -> Self {
47 Self {
48 index: LayerIndex::new(LayerKind::Dns, start, end),
49 }
50 }
51
52 pub fn id(&self, buf: &[u8]) -> Result<u16, FieldError> {
58 header::read_id(buf, self.index.start)
59 }
60
61 pub fn qr(&self, buf: &[u8]) -> Result<bool, FieldError> {
63 header::read_qr(buf, self.index.start)
64 }
65
66 pub fn opcode(&self, buf: &[u8]) -> Result<u8, FieldError> {
68 header::read_opcode(buf, self.index.start)
69 }
70
71 pub fn aa(&self, buf: &[u8]) -> Result<bool, FieldError> {
73 header::read_aa(buf, self.index.start)
74 }
75
76 pub fn tc(&self, buf: &[u8]) -> Result<bool, FieldError> {
78 header::read_tc(buf, self.index.start)
79 }
80
81 pub fn rd(&self, buf: &[u8]) -> Result<bool, FieldError> {
83 header::read_rd(buf, self.index.start)
84 }
85
86 pub fn ra(&self, buf: &[u8]) -> Result<bool, FieldError> {
88 header::read_ra(buf, self.index.start)
89 }
90
91 pub fn z(&self, buf: &[u8]) -> Result<bool, FieldError> {
93 header::read_z(buf, self.index.start)
94 }
95
96 pub fn ad(&self, buf: &[u8]) -> Result<bool, FieldError> {
98 header::read_ad(buf, self.index.start)
99 }
100
101 pub fn cd(&self, buf: &[u8]) -> Result<bool, FieldError> {
103 header::read_cd(buf, self.index.start)
104 }
105
106 pub fn rcode(&self, buf: &[u8]) -> Result<u8, FieldError> {
108 header::read_rcode(buf, self.index.start)
109 }
110
111 pub fn qdcount(&self, buf: &[u8]) -> Result<u16, FieldError> {
113 header::read_qdcount(buf, self.index.start)
114 }
115
116 pub fn ancount(&self, buf: &[u8]) -> Result<u16, FieldError> {
118 header::read_ancount(buf, self.index.start)
119 }
120
121 pub fn nscount(&self, buf: &[u8]) -> Result<u16, FieldError> {
123 header::read_nscount(buf, self.index.start)
124 }
125
126 pub fn arcount(&self, buf: &[u8]) -> Result<u16, FieldError> {
128 header::read_arcount(buf, self.index.start)
129 }
130
131 pub fn questions(&self, buf: &[u8]) -> Result<Vec<DnsQuestion>, FieldError> {
137 let qdcount = self.qdcount(buf)? as usize;
138 let mut questions = Vec::with_capacity(qdcount);
139 let dns_data = &buf[self.index.start..self.index.end];
140 let mut offset = DNS_HEADER_LEN;
141
142 for _ in 0..qdcount {
143 let (q, consumed) = DnsQuestion::parse(dns_data, offset)?;
144 questions.push(q);
145 offset += consumed;
146 }
147
148 Ok(questions)
149 }
150
151 pub fn answers_rr(&self, buf: &[u8]) -> Result<Vec<DnsResourceRecord>, FieldError> {
153 let qdcount = self.qdcount(buf)? as usize;
154 let ancount = self.ancount(buf)? as usize;
155 let dns_data = &buf[self.index.start..self.index.end];
156
157 let mut offset = DNS_HEADER_LEN;
159 for _ in 0..qdcount {
160 let (_, consumed) = DnsQuestion::parse(dns_data, offset)?;
161 offset += consumed;
162 }
163
164 let mut records = Vec::with_capacity(ancount);
166 for _ in 0..ancount {
167 let (rr, consumed) = DnsResourceRecord::parse(dns_data, offset)?;
168 records.push(rr);
169 offset += consumed;
170 }
171
172 Ok(records)
173 }
174
175 pub fn authorities(&self, buf: &[u8]) -> Result<Vec<DnsResourceRecord>, FieldError> {
177 let qdcount = self.qdcount(buf)? as usize;
178 let ancount = self.ancount(buf)? as usize;
179 let nscount = self.nscount(buf)? as usize;
180 let dns_data = &buf[self.index.start..self.index.end];
181
182 let mut offset = DNS_HEADER_LEN;
184 for _ in 0..qdcount {
185 let (_, consumed) = DnsQuestion::parse(dns_data, offset)?;
186 offset += consumed;
187 }
188 for _ in 0..ancount {
189 let (_, consumed) = DnsResourceRecord::parse(dns_data, offset)?;
190 offset += consumed;
191 }
192
193 let mut records = Vec::with_capacity(nscount);
195 for _ in 0..nscount {
196 let (rr, consumed) = DnsResourceRecord::parse(dns_data, offset)?;
197 records.push(rr);
198 offset += consumed;
199 }
200
201 Ok(records)
202 }
203
204 pub fn additionals(&self, buf: &[u8]) -> Result<Vec<DnsResourceRecord>, FieldError> {
206 let qdcount = self.qdcount(buf)? as usize;
207 let ancount = self.ancount(buf)? as usize;
208 let nscount = self.nscount(buf)? as usize;
209 let arcount = self.arcount(buf)? as usize;
210 let dns_data = &buf[self.index.start..self.index.end];
211
212 let mut offset = DNS_HEADER_LEN;
214 for _ in 0..qdcount {
215 let (_, consumed) = DnsQuestion::parse(dns_data, offset)?;
216 offset += consumed;
217 }
218 for _ in 0..ancount {
219 let (_, consumed) = DnsResourceRecord::parse(dns_data, offset)?;
220 offset += consumed;
221 }
222 for _ in 0..nscount {
223 let (_, consumed) = DnsResourceRecord::parse(dns_data, offset)?;
224 offset += consumed;
225 }
226
227 let mut records = Vec::with_capacity(arcount);
229 for _ in 0..arcount {
230 let (rr, consumed) = DnsResourceRecord::parse(dns_data, offset)?;
231 records.push(rr);
232 offset += consumed;
233 }
234
235 Ok(records)
236 }
237
238 pub fn parse_all(
240 &self,
241 buf: &[u8],
242 ) -> Result<
243 (
244 Vec<DnsQuestion>,
245 Vec<DnsResourceRecord>,
246 Vec<DnsResourceRecord>,
247 Vec<DnsResourceRecord>,
248 ),
249 FieldError,
250 > {
251 let qdcount = self.qdcount(buf)? as usize;
252 let ancount = self.ancount(buf)? as usize;
253 let nscount = self.nscount(buf)? as usize;
254 let arcount = self.arcount(buf)? as usize;
255 let dns_data = &buf[self.index.start..self.index.end];
256 let mut offset = DNS_HEADER_LEN;
257
258 let mut questions = Vec::with_capacity(qdcount);
259 for _ in 0..qdcount {
260 let (q, consumed) = DnsQuestion::parse(dns_data, offset)?;
261 questions.push(q);
262 offset += consumed;
263 }
264
265 let mut answers = Vec::with_capacity(ancount);
266 for _ in 0..ancount {
267 let (rr, consumed) = DnsResourceRecord::parse(dns_data, offset)?;
268 answers.push(rr);
269 offset += consumed;
270 }
271
272 let mut authorities = Vec::with_capacity(nscount);
273 for _ in 0..nscount {
274 let (rr, consumed) = DnsResourceRecord::parse(dns_data, offset)?;
275 authorities.push(rr);
276 offset += consumed;
277 }
278
279 let mut additionals = Vec::with_capacity(arcount);
280 for _ in 0..arcount {
281 let (rr, consumed) = DnsResourceRecord::parse(dns_data, offset)?;
282 additionals.push(rr);
283 offset += consumed;
284 }
285
286 Ok((questions, answers, authorities, additionals))
287 }
288
289 pub fn get_field(&self, buf: &[u8], name: &str) -> Option<Result<FieldValue, FieldError>> {
295 match name {
296 "id" => Some(self.id(buf).map(FieldValue::U16)),
297 "qr" => Some(self.qr(buf).map(FieldValue::Bool)),
298 "opcode" => Some(self.opcode(buf).map(FieldValue::U8)),
299 "aa" => Some(self.aa(buf).map(FieldValue::Bool)),
300 "tc" => Some(self.tc(buf).map(FieldValue::Bool)),
301 "rd" => Some(self.rd(buf).map(FieldValue::Bool)),
302 "ra" => Some(self.ra(buf).map(FieldValue::Bool)),
303 "z" => Some(self.z(buf).map(FieldValue::Bool)),
304 "ad" => Some(self.ad(buf).map(FieldValue::Bool)),
305 "cd" => Some(self.cd(buf).map(FieldValue::Bool)),
306 "rcode" => Some(self.rcode(buf).map(FieldValue::U8)),
307 "qdcount" => Some(self.qdcount(buf).map(FieldValue::U16)),
308 "ancount" => Some(self.ancount(buf).map(FieldValue::U16)),
309 "nscount" => Some(self.nscount(buf).map(FieldValue::U16)),
310 "arcount" => Some(self.arcount(buf).map(FieldValue::U16)),
311 _ => None,
312 }
313 }
314
315 pub fn set_field(
317 &self,
318 buf: &mut [u8],
319 name: &str,
320 value: FieldValue,
321 ) -> Option<Result<(), FieldError>> {
322 match name {
323 "id" => Some(match value.as_u16() {
324 Some(v) => header::write_id(buf, self.index.start, v),
325 None => Err(FieldError::InvalidValue("expected u16 for id".into())),
326 }),
327 "qr" => Some(match value.as_bool() {
328 Some(v) => header::write_qr(buf, self.index.start, v),
329 None => Err(FieldError::InvalidValue("expected bool for qr".into())),
330 }),
331 "opcode" => Some(match value.as_u8() {
332 Some(v) => header::write_opcode(buf, self.index.start, v),
333 None => Err(FieldError::InvalidValue("expected u8 for opcode".into())),
334 }),
335 "aa" => Some(match value.as_bool() {
336 Some(v) => header::write_aa(buf, self.index.start, v),
337 None => Err(FieldError::InvalidValue("expected bool for aa".into())),
338 }),
339 "tc" => Some(match value.as_bool() {
340 Some(v) => header::write_tc(buf, self.index.start, v),
341 None => Err(FieldError::InvalidValue("expected bool for tc".into())),
342 }),
343 "rd" => Some(match value.as_bool() {
344 Some(v) => header::write_rd(buf, self.index.start, v),
345 None => Err(FieldError::InvalidValue("expected bool for rd".into())),
346 }),
347 "ra" => Some(match value.as_bool() {
348 Some(v) => header::write_ra(buf, self.index.start, v),
349 None => Err(FieldError::InvalidValue("expected bool for ra".into())),
350 }),
351 "z" => Some(match value.as_bool() {
352 Some(v) => header::write_z(buf, self.index.start, v),
353 None => Err(FieldError::InvalidValue("expected bool for z".into())),
354 }),
355 "ad" => Some(match value.as_bool() {
356 Some(v) => header::write_ad(buf, self.index.start, v),
357 None => Err(FieldError::InvalidValue("expected bool for ad".into())),
358 }),
359 "cd" => Some(match value.as_bool() {
360 Some(v) => header::write_cd(buf, self.index.start, v),
361 None => Err(FieldError::InvalidValue("expected bool for cd".into())),
362 }),
363 "rcode" => Some(match value.as_u8() {
364 Some(v) => header::write_rcode(buf, self.index.start, v),
365 None => Err(FieldError::InvalidValue("expected u8 for rcode".into())),
366 }),
367 "qdcount" => Some(match value.as_u16() {
368 Some(v) => header::write_qdcount(buf, self.index.start, v),
369 None => Err(FieldError::InvalidValue("expected u16 for qdcount".into())),
370 }),
371 "ancount" => Some(match value.as_u16() {
372 Some(v) => header::write_ancount(buf, self.index.start, v),
373 None => Err(FieldError::InvalidValue("expected u16 for ancount".into())),
374 }),
375 "nscount" => Some(match value.as_u16() {
376 Some(v) => header::write_nscount(buf, self.index.start, v),
377 None => Err(FieldError::InvalidValue("expected u16 for nscount".into())),
378 }),
379 "arcount" => Some(match value.as_u16() {
380 Some(v) => header::write_arcount(buf, self.index.start, v),
381 None => Err(FieldError::InvalidValue("expected u16 for arcount".into())),
382 }),
383 _ => None,
384 }
385 }
386
387 #[must_use]
389 pub fn field_names() -> &'static [&'static str] {
390 DNS_FIELDS
391 }
392}
393
394pub const DNS_FIELDS: &[&str] = &[
396 "id", "qr", "opcode", "aa", "tc", "rd", "ra", "z", "ad", "cd", "rcode", "qdcount", "ancount",
397 "nscount", "arcount",
398];
399
400impl Layer for DnsLayer {
401 fn kind(&self) -> LayerKind {
402 LayerKind::Dns
403 }
404
405 fn summary(&self, buf: &[u8]) -> String {
406 let qr = self.qr(buf).unwrap_or(false);
407 let opcode = self.opcode(buf).unwrap_or(0);
408 let rcode = self.rcode(buf).unwrap_or(0);
409 let qdcount = self.qdcount(buf).unwrap_or(0);
410 let ancount = self.ancount(buf).unwrap_or(0);
411
412 if qr {
413 format!(
414 "DNS {} {} qd={} an={}",
415 types::opcode_name(opcode),
416 types::rcode_name(rcode),
417 qdcount,
418 ancount,
419 )
420 } else {
421 let qname_str = self
422 .questions(buf)
423 .ok()
424 .and_then(|qs| qs.first().map(query::DnsQuestion::summary));
425 match qname_str {
426 Some(q) => format!("DNS {} {}", types::opcode_name(opcode), q),
427 None => format!("DNS {} qd={}", types::opcode_name(opcode), qdcount),
428 }
429 }
430 }
431
432 fn header_len(&self, buf: &[u8]) -> usize {
433 self.index
434 .len()
435 .min(buf.len().saturating_sub(self.index.start))
436 }
437
438 fn hashret(&self, buf: &[u8]) -> Vec<u8> {
439 self.id(buf)
440 .map(|id| id.to_be_bytes().to_vec())
441 .unwrap_or_default()
442 }
443
444 fn field_names(&self) -> &'static [&'static str] {
445 DNS_FIELDS
446 }
447}