1#[cfg(test)]
2mod message_test;
3
4pub mod builder;
5pub mod header;
6pub mod name;
7mod packer;
8pub mod parser;
9pub mod question;
10pub mod resource;
11
12use std::collections::HashMap;
13use std::fmt;
14
15use header::*;
16use packer::*;
17use parser::*;
18use question::*;
19use resource::*;
20
21use crate::error::*;
22
23#[derive(Default, Copy, Clone, Debug, PartialEq, Eq)]
27pub enum DnsType {
28 A = 1,
30 Ns = 2,
31 Cname = 5,
32 Soa = 6,
33 Ptr = 12,
34 Mx = 15,
35 Txt = 16,
36 Aaaa = 28,
37 Srv = 33,
38 Opt = 41,
39
40 Wks = 11,
42 Hinfo = 13,
43 Minfo = 14,
44 Axfr = 252,
45 All = 255,
46
47 #[default]
48 Unsupported = 0,
49}
50
51impl From<u16> for DnsType {
52 fn from(v: u16) -> Self {
53 match v {
54 1 => DnsType::A,
55 2 => DnsType::Ns,
56 5 => DnsType::Cname,
57 6 => DnsType::Soa,
58 12 => DnsType::Ptr,
59 15 => DnsType::Mx,
60 16 => DnsType::Txt,
61 28 => DnsType::Aaaa,
62 33 => DnsType::Srv,
63 41 => DnsType::Opt,
64
65 11 => DnsType::Wks,
67 13 => DnsType::Hinfo,
68 14 => DnsType::Minfo,
69 252 => DnsType::Axfr,
70 255 => DnsType::All,
71
72 _ => DnsType::Unsupported,
73 }
74 }
75}
76
77impl fmt::Display for DnsType {
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 let s = match *self {
80 DnsType::A => "A",
81 DnsType::Ns => "NS",
82 DnsType::Cname => "CNAME",
83 DnsType::Soa => "SOA",
84 DnsType::Ptr => "PTR",
85 DnsType::Mx => "MX",
86 DnsType::Txt => "TXT",
87 DnsType::Aaaa => "AAAA",
88 DnsType::Srv => "SRV",
89 DnsType::Opt => "OPT",
90 DnsType::Wks => "WKS",
91 DnsType::Hinfo => "HINFO",
92 DnsType::Minfo => "MINFO",
93 DnsType::Axfr => "AXFR",
94 DnsType::All => "ALL",
95 _ => "Unsupported",
96 };
97 write!(f, "{s}")
98 }
99}
100
101impl DnsType {
102 pub(crate) fn pack(&self, msg: Vec<u8>) -> Vec<u8> {
104 pack_uint16(msg, *self as u16)
105 }
106
107 pub(crate) fn unpack(&mut self, msg: &[u8], off: usize) -> Result<usize> {
108 let (t, o) = unpack_uint16(msg, off)?;
109 *self = DnsType::from(t);
110 Ok(o)
111 }
112
113 pub(crate) fn skip(msg: &[u8], off: usize) -> Result<usize> {
114 skip_uint16(msg, off)
115 }
116}
117
118#[derive(Default, Copy, Clone, Debug, PartialEq, Eq)]
120pub struct DnsClass(pub u16);
121
122pub const DNSCLASS_INET: DnsClass = DnsClass(1);
124pub const DNSCLASS_CSNET: DnsClass = DnsClass(2);
125pub const DNSCLASS_CHAOS: DnsClass = DnsClass(3);
126pub const DNSCLASS_HESIOD: DnsClass = DnsClass(4);
127pub const DNSCLASS_ANY: DnsClass = DnsClass(255);
129
130impl fmt::Display for DnsClass {
131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132 let other = format!("{}", self.0);
133 let s = match *self {
134 DNSCLASS_INET => "ClassINET",
135 DNSCLASS_CSNET => "ClassCSNET",
136 DNSCLASS_CHAOS => "ClassCHAOS",
137 DNSCLASS_HESIOD => "ClassHESIOD",
138 DNSCLASS_ANY => "ClassANY",
139 _ => other.as_str(),
140 };
141 write!(f, "{s}")
142 }
143}
144
145impl DnsClass {
146 pub(crate) fn pack(&self, msg: Vec<u8>) -> Vec<u8> {
148 pack_uint16(msg, self.0)
149 }
150
151 pub(crate) fn unpack(&mut self, msg: &[u8], off: usize) -> Result<usize> {
152 let (c, o) = unpack_uint16(msg, off)?;
153 *self = DnsClass(c);
154 Ok(o)
155 }
156
157 pub(crate) fn skip(msg: &[u8], off: usize) -> Result<usize> {
158 skip_uint16(msg, off)
159 }
160}
161
162pub type OpCode = u16;
164
165#[derive(Default, Copy, Clone, Debug, PartialEq, Eq)]
167pub enum RCode {
168 #[default]
170 Success = 0,
171 FormatError = 1,
172 ServerFailure = 2,
173 NameError = 3,
174 NotImplemented = 4,
175 Refused = 5,
176 Unsupported,
177}
178
179impl From<u8> for RCode {
180 fn from(v: u8) -> Self {
181 match v {
182 0 => RCode::Success,
183 1 => RCode::FormatError,
184 2 => RCode::ServerFailure,
185 3 => RCode::NameError,
186 4 => RCode::NotImplemented,
187 5 => RCode::Refused,
188 _ => RCode::Unsupported,
189 }
190 }
191}
192
193impl fmt::Display for RCode {
194 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
195 let s = match *self {
196 RCode::Success => "RCodeSuccess",
197 RCode::FormatError => "RCodeFormatError",
198 RCode::ServerFailure => "RCodeServerFailure",
199 RCode::NameError => "RCodeNameError",
200 RCode::NotImplemented => "RCodeNotImplemented",
201 RCode::Refused => "RCodeRefused",
202 RCode::Unsupported => "RCodeUnsupported",
203 };
204 write!(f, "{s}")
205 }
206}
207
208const PACK_STARTING_CAP: usize = 512;
216
217const UINT16LEN: usize = 2;
219
220const UINT32LEN: usize = 4;
222
223const HEADER_LEN: usize = 6 * UINT16LEN;
227
228const HEADER_BIT_QR: u16 = 1 << 15; const HEADER_BIT_AA: u16 = 1 << 10; const HEADER_BIT_TC: u16 = 1 << 9; const HEADER_BIT_RD: u16 = 1 << 8; const HEADER_BIT_RA: u16 = 1 << 7; #[derive(Default, Debug)]
236pub struct Message {
237 pub header: Header,
238 pub questions: Vec<Question>,
239 pub answers: Vec<Resource>,
240 pub authorities: Vec<Resource>,
241 pub additionals: Vec<Resource>,
242}
243
244impl fmt::Display for Message {
245 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
246 let mut s = "dnsmessage.Message{Header: ".to_owned();
247 s += self.header.to_string().as_str();
248
249 s += ", Questions: ";
250 let v: Vec<String> = self.questions.iter().map(|q| q.to_string()).collect();
251 s += &v.join(", ");
252
253 s += ", Answers: ";
254 let v: Vec<String> = self.answers.iter().map(|q| q.to_string()).collect();
255 s += &v.join(", ");
256
257 s += ", Authorities: ";
258 let v: Vec<String> = self.authorities.iter().map(|q| q.to_string()).collect();
259 s += &v.join(", ");
260
261 s += ", Additionals: ";
262 let v: Vec<String> = self.additionals.iter().map(|q| q.to_string()).collect();
263 s += &v.join(", ");
264
265 write!(f, "{s}")
266 }
267}
268
269impl Message {
270 pub fn unpack(&mut self, msg: &[u8]) -> Result<()> {
272 let mut p = Parser::default();
273 self.header = p.start(msg)?;
274 self.questions = p.all_questions()?;
275 self.answers = p.all_answers()?;
276 self.authorities = p.all_authorities()?;
277 self.additionals = p.all_additionals()?;
278 Ok(())
279 }
280
281 pub fn pack(&mut self) -> Result<Vec<u8>> {
283 self.append_pack(vec![])
284 }
285
286 pub fn append_pack(&mut self, b: Vec<u8>) -> Result<Vec<u8>> {
289 if self.questions.len() > u16::MAX as usize {
293 return Err(Error::ErrTooManyQuestions);
294 }
295 if self.answers.len() > u16::MAX as usize {
296 return Err(Error::ErrTooManyAnswers);
297 }
298 if self.authorities.len() > u16::MAX as usize {
299 return Err(Error::ErrTooManyAuthorities);
300 }
301 if self.additionals.len() > u16::MAX as usize {
302 return Err(Error::ErrTooManyAdditionals);
303 }
304
305 let (id, bits) = self.header.pack();
306
307 let questions = self.questions.len() as u16;
308 let answers = self.answers.len() as u16;
309 let authorities = self.authorities.len() as u16;
310 let additionals = self.additionals.len() as u16;
311
312 let h = HeaderInternal {
313 id,
314 bits,
315 questions,
316 answers,
317 authorities,
318 additionals,
319 };
320
321 let compression_off = b.len();
322 let mut msg = h.pack(b);
323
324 let mut compression = Some(HashMap::new());
333
334 for question in &self.questions {
335 msg = question.pack(msg, &mut compression, compression_off)?;
336 }
337 for answer in &mut self.answers {
338 msg = answer.pack(msg, &mut compression, compression_off)?;
339 }
340 for authority in &mut self.authorities {
341 msg = authority.pack(msg, &mut compression, compression_off)?;
342 }
343 for additional in &mut self.additionals {
344 msg = additional.pack(msg, &mut compression, compression_off)?;
345 }
346
347 Ok(msg)
348 }
349}