1pub mod name;
7
8use crate::binutils::*;
9use crate::body::name::Name;
10use crate::ParseError;
11use std::borrow::Cow;
12use std::net::{Ipv4Addr, Ipv6Addr};
13use std::str;
14
15const INIT_RR_SIZE: usize = 64;
16
17macro_rules! types {
18 (
19 $(
20 #[$inner:meta]
21 $variant:tt = $value:literal
22 )+
23 ) => {
24 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd)]
26 pub enum Type {
27 $(
28 #[$inner]
29 $variant,
30 )*
31 Unknown(u16),
33 }
34
35 impl TryFrom<QType> for Type {
36 type Error = &'static str;
37
38 #[inline]
39 fn try_from(value: QType) -> Result<Self, Self::Error> {
40 match value {
41 $(QType::$variant => Ok(Self::$variant),)*
42 QType::Unknown(n) => Ok(Self::Unknown(n)),
43 _ => Err("QType is not a valid Type")
44 }
45 }
46 }
47
48 impl From<u16> for Type {
49 #[inline]
50 fn from(value: u16) -> Self {
51 match value {
52 $($value => Self::$variant,)*
53 _ => Self::Unknown(value),
54 }
55 }
56 }
57
58 impl From<Type> for u16 {
59 #[inline]
60 fn from(value: Type) -> Self {
61 match value {
62 $(Type::$variant => $value,)*
63 Type::Unknown(n) => n,
64 }
65 }
66 }
67
68 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd)]
70 pub enum QType {
71 $(
72 #[$inner]
73 $variant,
74 )*
75 All,
77 Unknown(u16),
79 }
80
81 impl From<Type> for QType {
82 #[inline]
83 fn from(value: Type) -> Self {
84 match value {
85 $(Type::$variant => Self::$variant,)*
86 Type::Unknown(n) => Self::Unknown(n),
87 }
88 }
89 }
90
91 impl From<u16> for QType {
92 #[inline]
93 fn from(value: u16) -> Self {
94 match value {
95 $($value => Self::$variant,)*
96 255 => Self::All,
97 _ => Self::Unknown(value),
98 }
99 }
100 }
101
102 impl From<QType> for u16 {
103 #[inline]
104 fn from(value: QType) -> Self {
105 match value {
106 $(QType::$variant => $value,)*
107 QType::All => 255,
108 QType::Unknown(n) => n,
109 }
110 }
111 }
112 };
113}
114
115#[derive(Clone, Debug)]
129pub struct Question<'a> {
130 pub name: Name<'a>,
132 pub qtype: QType,
134 pub class: Class,
136}
137
138impl From<Question<'_>> for Vec<u8> {
139 #[inline]
140 fn from(question: Question<'_>) -> Self {
141 let mut out = question.name.into();
142 push_u16(&mut out, question.qtype.into());
143 push_u16(&mut out, question.class.into());
144 out
145 }
146}
147
148impl<'a> Question<'a> {
149 #[inline]
157 pub fn parse(buff: &'a [u8], start: usize) -> Result<(Self, usize), crate::ParseError> {
158 let (name, size) = Name::parse(buff, start)?;
159 let n = start + size;
160 Ok((
161 Question {
162 name,
163 qtype: safe_u16_read(buff, n)?.into(),
164 class: safe_u16_read(buff, n + 2)?.into(),
165 },
166 size + 4,
167 ))
168 }
169
170 #[inline]
172 pub fn serialize(&self, packet: &mut Vec<u8>) {
173 self.name.serialize(packet);
174 push_u16(packet, self.qtype.into());
175 push_u16(packet, self.class.into());
176 }
177}
178
179#[derive(Debug, Clone)]
204pub struct ResourceRecord<'a> {
205 pub preamble: RecordPreamble<'a>,
207 pub data: RecordData<'a>,
209}
210
211impl From<ResourceRecord<'_>> for Vec<u8> {
212 #[inline]
213 fn from(rr: ResourceRecord<'_>) -> Self {
214 let mut out = Vec::with_capacity(INIT_RR_SIZE);
215 rr.serialize(&mut out);
216 out
217 }
218}
219
220impl<'a> ResourceRecord<'a> {
221 #[inline]
223 pub fn parse(buff: &'a [u8], pos: usize) -> Result<(Self, usize), ParseError> {
224 let (preamble, size) = RecordPreamble::parse(buff, pos)?;
225 let (data, len) = RecordData::parse(buff, pos + size, &preamble)?;
226 Ok((Self { preamble, data }, size + len))
227 }
228
229 #[inline]
231 pub fn serialize(&self, packet: &mut Vec<u8>) {
232 self.preamble.serialize(packet);
233 self.data.serialize(packet);
234 }
235}
236
237#[derive(Debug, Clone)]
239pub struct RecordPreamble<'a> {
240 pub name: Name<'a>,
242 pub rrtype: Type,
244 pub class: Class,
246 pub ttl: i32,
248 pub rdlen: u16,
250}
251
252impl<'a> RecordPreamble<'a> {
253 #[inline]
254 fn parse(buff: &'a [u8], pos: usize) -> Result<(Self, usize), ParseError> {
255 let (name, size) = Name::parse(buff, pos)?;
256 let n = size + pos;
257 Ok((
258 RecordPreamble {
259 name,
260 rrtype: safe_u16_read(buff, n)?.into(),
261 class: safe_u16_read(buff, n + 2)?.into(),
262 ttl: safe_i32_read(buff, n + 4)?,
263 rdlen: safe_u16_read(buff, n + 8)?,
264 },
265 size + 10,
266 ))
267 }
268
269 #[inline]
270 fn serialize(&self, packet: &mut Vec<u8>) {
271 self.name.serialize(packet);
272 push_u16(packet, self.rrtype.into());
273 push_u16(packet, self.class.into());
274 push_i32(packet, self.ttl);
275 push_u16(packet, self.rdlen);
276 }
277}
278
279#[non_exhaustive]
281#[derive(Debug, Clone)]
282pub enum RecordData<'a> {
283 A(Ipv4Addr),
285 Ns(Name<'a>),
287 Cname(Name<'a>),
289 Mx {
291 preference: u16,
293 exchange: Name<'a>,
295 },
296 Txt(Cow<'a, str>),
298 Aaaa(Ipv6Addr),
300 Unknown(Cow<'a, [u8]>),
302}
303
304impl<'a> RecordData<'a> {
305 #[inline]
306 fn parse(
307 buff: &'a [u8],
308 pos: usize,
309 rrpreamble: &RecordPreamble<'_>,
310 ) -> Result<(Self, usize), ParseError> {
311 match rrpreamble.rrtype {
312 Type::A => Ok((Self::A(safe_ipv4_read(buff, pos)?), 4)),
313 Type::Ns => {
314 let (name, n) = Name::parse(buff, pos)?;
315 Ok((Self::Ns(name), n))
316 }
317 Type::Cname => {
318 let (name, n) = Name::parse(buff, pos)?;
319 Ok((Self::Cname(name), n))
320 }
321 Type::Mx => {
322 let (exchange, n) = Name::parse(buff, pos + 2)?;
323 Ok((
324 Self::Mx {
325 preference: safe_u16_read(buff, pos)?,
326 exchange,
327 },
328 n + 2,
329 ))
330 }
331 Type::Txt => {
332 let len = safe_u8_read(buff, pos)?;
333 let str_bytes = str::from_utf8(&buff[pos..pos + len as usize])?;
334 Ok((Self::Txt(Cow::from(str_bytes)), len as _))
335 }
336 Type::Aaaa => Ok((Self::Aaaa(safe_ipv6_read(buff, pos)?), 16)),
337 Type::Unknown(_) => {
338 let len = rrpreamble.rdlen as _;
339 let end = pos + len;
340 if buff.len() < end {
341 Err(ParseError::OobRead(end))?
342 }
343 let cow_bytes = Cow::from(&buff[pos..end]);
344 Ok((Self::Unknown(cow_bytes), len))
345 }
346 }
347 }
348
349 #[inline]
350 fn serialize(&self, packet: &mut Vec<u8>) {
351 use std::ops::Deref;
352 match self {
353 Self::A(ip) => packet.extend(ip.octets()),
354 Self::Ns(name) => name.serialize(packet),
355 Self::Cname(name) => name.serialize(packet),
356 Self::Mx {
357 preference,
358 exchange,
359 } => {
360 push_u16(packet, *preference);
361 exchange.serialize(packet);
362 }
363 Self::Txt(txt) => {
364 packet.push(txt.len() as _);
368 packet.extend(txt.as_bytes());
369 }
370 Self::Aaaa(ip) => packet.extend(ip.octets()),
371 Self::Unknown(buff) => packet.extend(buff.deref()),
372 }
373 }
374}
375
376types! {
377 A = 1
379 Ns = 2
381 Cname = 5
383 Mx = 15
385 Txt = 16
387 Aaaa = 28
389}
390
391#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd)]
395pub enum Class {
396 IN,
398 CS,
400 CH,
402 HS,
404 Any,
406 Unknown(u16),
408}
409
410impl From<u16> for Class {
411 #[inline]
412 fn from(value: u16) -> Self {
413 match value {
414 1 => Self::IN,
415 2 => Self::CS,
416 3 => Self::CH,
417 4 => Self::HS,
418 255 => Self::Any,
419 _ => Self::Unknown(value),
420 }
421 }
422}
423
424impl From<Class> for u16 {
425 #[inline]
426 fn from(value: Class) -> Self {
427 match value {
428 Class::IN => 1,
429 Class::CS => 2,
430 Class::CH => 3,
431 Class::HS => 4,
432 Class::Any => 255,
433 Class::Unknown(n) => n,
434 }
435 }
436}
437
438#[cfg(test)]
439mod tests {
440 use super::*;
441
442 #[test]
443 fn class_transformations() {
444 assert_eq!(Class::IN, From::from(1u16));
445 assert_eq!(Class::CS, From::from(2u16));
446 assert_eq!(Class::CH, From::from(3u16));
447 assert_eq!(Class::HS, From::from(4u16));
448 assert_eq!(Class::Any, From::from(255u16));
449 assert_eq!(Class::Unknown(225u16), From::from(225u16));
450
451 assert_eq!(1u16, From::from(Class::IN));
452 assert_eq!(2u16, From::from(Class::CS));
453 assert_eq!(3u16, From::from(Class::CH));
454 assert_eq!(4u16, From::from(Class::HS));
455 assert_eq!(255u16, From::from(Class::Any));
456 assert_eq!(225u16, From::from(Class::Unknown(225u16)));
457 }
458
459 #[test]
460 fn qtype_transformations() {
461 assert_eq!(QType::A, From::from(1u16));
462 assert_eq!(QType::Ns, From::from(2u16));
463 assert_eq!(QType::Cname, From::from(5u16));
464 assert_eq!(QType::Mx, From::from(15u16));
465 assert_eq!(QType::All, From::from(255u16));
466 assert_eq!(QType::Unknown(225u16), From::from(225u16));
467
468 assert_eq!(1u16, From::from(QType::A));
469 assert_eq!(2u16, From::from(QType::Ns));
470 assert_eq!(5u16, From::from(QType::Cname));
471 assert_eq!(15u16, From::from(QType::Mx));
472 assert_eq!(255u16, From::from(QType::All));
473 assert_eq!(225u16, From::from(QType::Unknown(225u16)));
474 }
475}