1use crate::binutils::*;
6use crate::ParseError;
7
8macro_rules! u16_flag {
9 (
10 $(#[$outer:meta])*
11 $bits:literal is $typ:tt with: $(
12 #[$inner:meta]
13 $variant:tt = $value:literal
14 )+
15 ) => {
16 $(#[$outer])*
17 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
18 pub enum $typ {
19 $(
20 #[$inner]
21 $variant = $value,
22 )*
23 }
24
25 impl From<u16> for $typ {
26 #[inline]
27 fn from(n: u16) -> Self {
28 match $crate::header::mask_shift($bits, n) {
29 $($value => Self::$variant,)*
30 _ => ::std::unreachable!("Bitwise operations should make this imposible. Failed with mask {} for value {}", $bits, n),
31 }
32 }
33 }
34
35 impl From<$typ> for u16 {
36 #[inline]
37 fn from(flag: $typ) -> Self {
38 $crate::header::unshift($bits, flag as u16)
39 }
40 }
41 };
42}
43
44macro_rules! u16_flag_reserved {
45 (
46 $(#[$outer:meta])*
47 $bits:literal is $typ:tt with: $(
48 #[$inner:meta]
49 $variant:tt = $value:literal
50 )+
51 ) => {
52 $(#[$outer])*
53 #[non_exhaustive]
54 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
55 pub enum $typ {
56 $(
57 #[$inner]
58 $variant = $value,
59 )*
60 }
61
62 impl TryFrom<u16> for $typ {
63 type Error = ParseError;
64
65 #[inline]
66 fn try_from(n: u16) -> Result<Self, Self::Error> {
67 match $crate::header::mask_shift($bits, n) {
68 $($value => Ok(Self::$variant),)*
69 n => Err(ParseError::HeaderFlag(stringify!($typ), n)),
70 }
71 }
72 }
73
74 impl From<$typ> for u16 {
75 #[inline]
76 fn from(flag: $typ) -> Self {
77 $crate::header::unshift($bits, flag as u16)
78 }
79 }
80 };
81}
82
83#[inline]
84fn mask_shift(mask: u16, n: u16) -> u16 {
85 (n & mask) >> mask.trailing_zeros()
86}
87
88#[inline]
89fn unshift(mask: u16, n: u16) -> u16 {
90 n << mask.trailing_zeros()
91}
92
93#[derive(Clone, Debug)]
130pub struct DnsHeader {
131 pub id: u16,
133 pub flags: Flags,
135 pub questions: u16,
137 pub answers: u16,
139 pub authority: u16,
141 pub additional: u16,
143}
144
145impl TryFrom<&[u8]> for DnsHeader {
146 type Error = crate::ParseError;
147 #[inline]
148 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
149 if bytes.len() < 12 {
150 Err(ParseError::HeaderLength(bytes.len()))?
151 } else {
152 let header = DnsHeader {
153 id: safe_u16_read(bytes, 0)?,
154 flags: safe_u16_read(bytes, 2)?.try_into()?,
155 questions: safe_u16_read(bytes, 4)?,
156 answers: safe_u16_read(bytes, 6)?,
157 authority: safe_u16_read(bytes, 8)?,
158 additional: safe_u16_read(bytes, 10)?,
159 };
160 Ok(header)
161 }
162 }
163}
164
165impl From<&DnsHeader> for Vec<u8> {
166 #[inline]
167 fn from(header: &DnsHeader) -> Self {
168 let mut target = Vec::with_capacity(12);
169 header.serialize(&mut target);
170 target
171 }
172}
173
174impl DnsHeader {
175 #[inline]
181 pub fn serialize(&self, target: &mut Vec<u8>) {
182 push_u16(target, self.id);
183 push_u16(target, self.flags.into());
184 push_u16(target, self.questions);
185 push_u16(target, self.answers);
186 push_u16(target, self.authority);
187 push_u16(target, self.additional);
188 }
189}
190
191#[derive(Copy, Clone, Debug, PartialEq, Eq)]
209pub struct Flags {
210 pub qr: QueryResponse,
212 pub opcode: OpCode,
214 pub aa: AuthoritativeAnswer,
216 pub tc: TrunCation,
218 pub rd: RecursionDesired,
220 pub ra: RecursionAvailable,
222 pub z: Zero,
224 pub ad: AuthenticData,
226 pub cd: CheckingDisabled,
228 pub rcode: ResponseCode,
230}
231
232impl TryFrom<u16> for Flags {
233 type Error = ParseError;
234
235 #[inline]
236 fn try_from(n: u16) -> Result<Self, Self::Error> {
237 Ok(Flags {
238 qr: n.into(),
239 opcode: n.try_into()?,
240 aa: n.into(),
241 tc: n.into(),
242 rd: n.into(),
243 ra: n.into(),
244 z: n.into(),
245 ad: n.into(),
246 cd: n.into(),
247 rcode: n.try_into()?,
248 })
249 }
250}
251
252impl From<Flags> for u16 {
253 #[inline]
254 fn from(flags: Flags) -> Self {
255 u16::from(flags.qr)
256 | u16::from(flags.opcode)
257 | u16::from(flags.aa)
258 | u16::from(flags.tc)
259 | u16::from(flags.rd)
260 | u16::from(flags.ra)
261 | u16::from(flags.z)
262 | u16::from(flags.ad)
263 | u16::from(flags.cd)
264 | u16::from(flags.rcode)
265 }
266}
267
268u16_flag! {
269 0b1000000000000000 is QueryResponse with:
271 Query = 0
273 Response = 1
275}
276
277u16_flag_reserved! {
279 0b0111100000000000 is OpCode with:
281 Query = 0
283 Iquery = 1
285 Status = 2
287 Notify = 4
289 Update = 5
291 Dso = 6
293}
294
295u16_flag! {
296 0b0000010000000000 is AuthoritativeAnswer with:
298 NonAuthoritative = 0
300 Authoritative = 1
302}
303
304u16_flag! {
305 0b0000001000000000 is TrunCation with:
307 NotTruncated = 0
309 Truncated = 1
311}
312
313u16_flag! {
314 0b0000000100000000 is RecursionDesired with:
316 NotDesired = 0
318 Desired = 1
320}
321
322u16_flag! {
323 0b0000000010000000 is RecursionAvailable with:
325 NotAvailable = 0
327 Available = 1
329}
330
331u16_flag! {
332 0b0000000001000000 is Zero with:
334 Zero = 0
336 Reserved = 1
338}
339
340u16_flag! {
341 0b0000000000100000 is AuthenticData with:
343 NotAuthentic = 0
345 Authentic = 1
347}
348
349u16_flag! {
350 0b0000000000010000 is CheckingDisabled with:
352 Enabled = 0
354 Disabled = 1
356}
357
358u16_flag_reserved! {
360 0b0000000000001111 is ResponseCode with:
362 NoError = 0
364 FormErr = 1
366 ServFail = 2
368 NXDomain = 3
370 NotImp = 4
372 Refused = 5
374}
375
376#[cfg(test)]
377mod tests {
378 use super::*;
379
380 #[test]
381 fn serialize_header() {
382 let mut used = Vec::with_capacity(12);
383 let initial = vec![
384 0x12u8, 0x34u8, 0u8, 0u8, 0u8, 1u8, 0u8, 2u8, 0u8, 3u8, 0u8, 4u8,
385 ];
386 let header = DnsHeader::try_from(&initial[..]).unwrap();
387 header.serialize(&mut used);
388 assert_eq!(initial, used);
389 }
390
391 #[test]
392 fn serialize_from_header() {
393 let initial = vec![
394 0x12u8, 0x34u8, 0u8, 0u8, 0u8, 1u8, 0u8, 2u8, 0u8, 3u8, 0u8, 4u8,
395 ];
396 let header = DnsHeader::try_from(&initial[..]).unwrap();
397 let used = Vec::<u8>::from(&header);
398 assert_eq!(initial, used);
399 }
400
401 #[test]
402 fn parse_header() {
403 let buff = [
404 0x12u8, 0x34u8, 0u8, 0u8, 0u8, 1u8, 0u8, 2u8, 0u8, 3u8, 0u8, 4u8,
405 ];
406 if let Ok(head) = DnsHeader::try_from(&buff[..]) {
407 assert_eq!(head.id, 0x1234u16);
408 assert_eq!(head.questions, 1u16);
409 assert_eq!(head.answers, 2u16);
410 assert_eq!(head.authority, 3u16);
411 assert_eq!(head.additional, 4u16);
412 } else {
413 panic!("Test should error with small buffer");
414 }
415 }
416
417 #[test]
418 fn header_err() {
419 let buff = [
420 0x12u8, 0x34u8, 0u8, 0u8, 0u8, 1u8, 0u8, 1u8, 0u8, 1u8, 0u8, 1u8,
421 ];
422 if DnsHeader::try_from(&buff[..5]).is_ok() {
423 panic!("Test should error with small buffer");
424 }
425 }
426
427 #[test]
428 fn flags_standard_query() {
429 let bits: u16 = 0b0000000000000000;
430 let flags: Flags = bits.try_into().expect("Failed when transforming flags");
431 let transformed: u16 = flags.into();
432
433 assert_eq!(flags.qr, QueryResponse::Query);
434 assert_eq!(flags.opcode, OpCode::Query);
435 assert_eq!(transformed, bits);
436 }
437
438 #[test]
439 fn flags_inverse_query() {
440 let bits: u16 = 0b0000100000000000;
441 let flags: Flags = bits.try_into().expect("Failed when transforming flags");
442 let transformed: u16 = flags.into();
443
444 assert_eq!(flags.qr, QueryResponse::Query);
445 assert_eq!(flags.opcode, OpCode::Iquery);
446 assert_eq!(transformed, bits);
447 }
448
449 #[test]
450 fn flags_response_noerror() {
451 let bits: u16 = 0b1000010000000000;
452 let flags: Flags = bits.try_into().expect("Failed when transforming flags");
453 let transformed: u16 = flags.into();
454
455 assert_eq!(flags.qr, QueryResponse::Response);
456 assert_eq!(flags.aa, AuthoritativeAnswer::Authoritative);
457 assert_eq!(flags.rcode, ResponseCode::NoError);
458 assert_eq!(transformed, bits);
459 }
460
461 #[test]
462 fn flags_response_servfail() {
463 let bits: u16 = 0b1000010000000010;
464 let flags: Flags = bits.try_into().expect("Failed when transforming flags");
465 let transformed: u16 = flags.into();
466
467 assert_eq!(flags.qr, QueryResponse::Response);
468 assert_eq!(flags.aa, AuthoritativeAnswer::Authoritative);
469 assert_eq!(flags.rcode, ResponseCode::ServFail);
470 assert_eq!(transformed, bits);
471 }
472
473 #[test]
474 fn flags_response_nxdomain() {
475 let bits: u16 = 0b1000010000000011;
476 let flags: Flags = bits.try_into().expect("Failed when transforming flags");
477 let transformed: u16 = flags.into();
478
479 assert_eq!(flags.qr, QueryResponse::Response);
480 assert_eq!(flags.aa, AuthoritativeAnswer::Authoritative);
481 assert_eq!(flags.rcode, ResponseCode::NXDomain);
482 assert_eq!(transformed, bits);
483 }
484
485 #[test]
486 fn flags_response_refused() {
487 let bits: u16 = 0b1000010000000101;
488 let flags: Flags = bits.try_into().expect("Failed when transforming flags");
489 let transformed: u16 = flags.into();
490
491 assert_eq!(flags.qr, QueryResponse::Response);
492 assert_eq!(flags.aa, AuthoritativeAnswer::Authoritative);
493 assert_eq!(flags.rcode, ResponseCode::Refused);
494 assert_eq!(transformed, bits);
495 }
496}