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