xref: /webrtc/mdns/src/message/mod.rs (revision 7ceeeeb0)
1 #[cfg(test)]
2 mod message_test;
3 
4 pub mod builder;
5 pub mod header;
6 pub mod name;
7 mod packer;
8 pub mod parser;
9 pub mod question;
10 pub mod resource;
11 
12 use crate::error::*;
13 use header::*;
14 use packer::*;
15 use parser::*;
16 use question::*;
17 use resource::*;
18 
19 use std::collections::HashMap;
20 use std::fmt;
21 
22 // Message formats
23 
24 // A Type is a type of DNS request and response.
25 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
26 pub enum DnsType {
27     // ResourceHeader.Type and question.Type
28     A = 1,
29     Ns = 2,
30     Cname = 5,
31     Soa = 6,
32     Ptr = 12,
33     Mx = 15,
34     Txt = 16,
35     Aaaa = 28,
36     Srv = 33,
37     Opt = 41,
38 
39     // question.Type
40     Wks = 11,
41     Hinfo = 13,
42     Minfo = 14,
43     Axfr = 252,
44     All = 255,
45 
46     Unsupported = 0,
47 }
48 
49 impl Default for DnsType {
50     fn default() -> Self {
51         DnsType::Unsupported
52     }
53 }
54 
55 impl From<u16> for DnsType {
56     fn from(v: u16) -> Self {
57         match v {
58             1 => DnsType::A,
59             2 => DnsType::Ns,
60             5 => DnsType::Cname,
61             6 => DnsType::Soa,
62             12 => DnsType::Ptr,
63             15 => DnsType::Mx,
64             16 => DnsType::Txt,
65             28 => DnsType::Aaaa,
66             33 => DnsType::Srv,
67             41 => DnsType::Opt,
68 
69             // question.Type
70             11 => DnsType::Wks,
71             13 => DnsType::Hinfo,
72             14 => DnsType::Minfo,
73             252 => DnsType::Axfr,
74             255 => DnsType::All,
75 
76             _ => DnsType::Unsupported,
77         }
78     }
79 }
80 
81 impl fmt::Display for DnsType {
82     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83         let s = match *self {
84             DnsType::A => "A",
85             DnsType::Ns => "NS",
86             DnsType::Cname => "CNAME",
87             DnsType::Soa => "SOA",
88             DnsType::Ptr => "PTR",
89             DnsType::Mx => "MX",
90             DnsType::Txt => "TXT",
91             DnsType::Aaaa => "AAAA",
92             DnsType::Srv => "SRV",
93             DnsType::Opt => "OPT",
94             DnsType::Wks => "WKS",
95             DnsType::Hinfo => "HINFO",
96             DnsType::Minfo => "MINFO",
97             DnsType::Axfr => "AXFR",
98             DnsType::All => "ALL",
99             _ => "Unsupported",
100         };
101         write!(f, "{}", s)
102     }
103 }
104 
105 impl DnsType {
106     // pack_type appends the wire format of field to msg.
107     pub(crate) fn pack(&self, msg: Vec<u8>) -> Vec<u8> {
108         pack_uint16(msg, *self as u16)
109     }
110 
111     pub(crate) fn unpack(&mut self, msg: &[u8], off: usize) -> Result<usize> {
112         let (t, o) = unpack_uint16(msg, off)?;
113         *self = DnsType::from(t);
114         Ok(o)
115     }
116 
117     pub(crate) fn skip(msg: &[u8], off: usize) -> Result<usize> {
118         skip_uint16(msg, off)
119     }
120 }
121 
122 // A Class is a type of network.
123 #[derive(Default, Copy, Clone, Debug, PartialEq, Eq)]
124 pub struct DnsClass(pub u16);
125 
126 // ResourceHeader.Class and question.Class
127 pub const DNSCLASS_INET: DnsClass = DnsClass(1);
128 pub const DNSCLASS_CSNET: DnsClass = DnsClass(2);
129 pub const DNSCLASS_CHAOS: DnsClass = DnsClass(3);
130 pub const DNSCLASS_HESIOD: DnsClass = DnsClass(4);
131 // question.Class
132 pub const DNSCLASS_ANY: DnsClass = DnsClass(255);
133 
134 impl fmt::Display for DnsClass {
135     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136         let other = format!("{}", self.0);
137         let s = match *self {
138             DNSCLASS_INET => "ClassINET",
139             DNSCLASS_CSNET => "ClassCSNET",
140             DNSCLASS_CHAOS => "ClassCHAOS",
141             DNSCLASS_HESIOD => "ClassHESIOD",
142             DNSCLASS_ANY => "ClassANY",
143             _ => other.as_str(),
144         };
145         write!(f, "{}", s)
146     }
147 }
148 
149 impl DnsClass {
150     // pack_class appends the wire format of field to msg.
151     pub(crate) fn pack(&self, msg: Vec<u8>) -> Vec<u8> {
152         pack_uint16(msg, self.0)
153     }
154 
155     pub(crate) fn unpack(&mut self, msg: &[u8], off: usize) -> Result<usize> {
156         let (c, o) = unpack_uint16(msg, off)?;
157         *self = DnsClass(c);
158         Ok(o)
159     }
160 
161     pub(crate) fn skip(msg: &[u8], off: usize) -> Result<usize> {
162         skip_uint16(msg, off)
163     }
164 }
165 
166 // An OpCode is a DNS operation code.
167 pub type OpCode = u16;
168 
169 // An RCode is a DNS response status code.
170 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
171 pub enum RCode {
172     // Message.Rcode
173     Success = 0,
174     FormatError = 1,
175     ServerFailure = 2,
176     NameError = 3,
177     NotImplemented = 4,
178     Refused = 5,
179     Unsupported,
180 }
181 
182 impl Default for RCode {
183     fn default() -> Self {
184         RCode::Success
185     }
186 }
187 
188 impl From<u8> for RCode {
189     fn from(v: u8) -> Self {
190         match v {
191             0 => RCode::Success,
192             1 => RCode::FormatError,
193             2 => RCode::ServerFailure,
194             3 => RCode::NameError,
195             4 => RCode::NotImplemented,
196             5 => RCode::Refused,
197             _ => RCode::Unsupported,
198         }
199     }
200 }
201 
202 impl fmt::Display for RCode {
203     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204         let s = match *self {
205             RCode::Success => "RCodeSuccess",
206             RCode::FormatError => "RCodeFormatError",
207             RCode::ServerFailure => "RCodeServerFailure",
208             RCode::NameError => "RCodeNameError",
209             RCode::NotImplemented => "RCodeNotImplemented",
210             RCode::Refused => "RCodeRefused",
211             RCode::Unsupported => "RCodeUnsupported",
212         };
213         write!(f, "{}", s)
214     }
215 }
216 
217 // Internal constants.
218 
219 // PACK_STARTING_CAP is the default initial buffer size allocated during
220 // packing.
221 //
222 // The starting capacity doesn't matter too much, but most DNS responses
223 // Will be <= 512 bytes as it is the limit for DNS over UDP.
224 const PACK_STARTING_CAP: usize = 512;
225 
226 // UINT16LEN is the length (in bytes) of a uint16.
227 const UINT16LEN: usize = 2;
228 
229 // UINT32LEN is the length (in bytes) of a uint32.
230 const UINT32LEN: usize = 4;
231 
232 // HEADER_LEN is the length (in bytes) of a DNS header.
233 //
234 // A header is comprised of 6 uint16s and no padding.
235 const HEADER_LEN: usize = 6 * UINT16LEN;
236 
237 const HEADER_BIT_QR: u16 = 1 << 15; // query/response (response=1)
238 const HEADER_BIT_AA: u16 = 1 << 10; // authoritative
239 const HEADER_BIT_TC: u16 = 1 << 9; // truncated
240 const HEADER_BIT_RD: u16 = 1 << 8; // recursion desired
241 const HEADER_BIT_RA: u16 = 1 << 7; // recursion available
242 
243 // Message is a representation of a DNS message.
244 #[derive(Default, Debug)]
245 pub struct Message {
246     pub header: Header,
247     pub questions: Vec<Question>,
248     pub answers: Vec<Resource>,
249     pub authorities: Vec<Resource>,
250     pub additionals: Vec<Resource>,
251 }
252 
253 impl fmt::Display for Message {
254     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
255         let mut s = "dnsmessage.Message{Header: ".to_owned();
256         s += self.header.to_string().as_str();
257 
258         s += ", Questions: ";
259         let v: Vec<String> = self.questions.iter().map(|q| q.to_string()).collect();
260         s += &v.join(", ");
261 
262         s += ", Answers: ";
263         let v: Vec<String> = self.answers.iter().map(|q| q.to_string()).collect();
264         s += &v.join(", ");
265 
266         s += ", Authorities: ";
267         let v: Vec<String> = self.authorities.iter().map(|q| q.to_string()).collect();
268         s += &v.join(", ");
269 
270         s += ", Additionals: ";
271         let v: Vec<String> = self.additionals.iter().map(|q| q.to_string()).collect();
272         s += &v.join(", ");
273 
274         write!(f, "{}", s)
275     }
276 }
277 
278 impl Message {
279     // Unpack parses a full Message.
280     pub fn unpack(&mut self, msg: &[u8]) -> Result<()> {
281         let mut p = Parser::default();
282         self.header = p.start(msg)?;
283         self.questions = p.all_questions()?;
284         self.answers = p.all_answers()?;
285         self.authorities = p.all_authorities()?;
286         self.additionals = p.all_additionals()?;
287         Ok(())
288     }
289 
290     // Pack packs a full Message.
291     pub fn pack(&mut self) -> Result<Vec<u8>> {
292         self.append_pack(vec![])
293     }
294 
295     // append_pack is like Pack but appends the full Message to b and returns the
296     // extended buffer.
297     pub fn append_pack(&mut self, b: Vec<u8>) -> Result<Vec<u8>> {
298         // Validate the lengths. It is very unlikely that anyone will try to
299         // pack more than 65535 of any particular type, but it is possible and
300         // we should fail gracefully.
301         if self.questions.len() > u16::MAX as usize {
302             return Err(Error::ErrTooManyQuestions);
303         }
304         if self.answers.len() > u16::MAX as usize {
305             return Err(Error::ErrTooManyAnswers);
306         }
307         if self.authorities.len() > u16::MAX as usize {
308             return Err(Error::ErrTooManyAuthorities);
309         }
310         if self.additionals.len() > u16::MAX as usize {
311             return Err(Error::ErrTooManyAdditionals);
312         }
313 
314         let (id, bits) = self.header.pack();
315 
316         let questions = self.questions.len() as u16;
317         let answers = self.answers.len() as u16;
318         let authorities = self.authorities.len() as u16;
319         let additionals = self.additionals.len() as u16;
320 
321         let h = HeaderInternal {
322             id,
323             bits,
324             questions,
325             answers,
326             authorities,
327             additionals,
328         };
329 
330         let compression_off = b.len();
331         let mut msg = h.pack(b);
332 
333         // RFC 1035 allows (but does not require) compression for packing. RFC
334         // 1035 requires unpacking implementations to support compression, so
335         // unconditionally enabling it is fine.
336         //
337         // DNS lookups are typically done over UDP, and RFC 1035 states that UDP
338         // DNS messages can be a maximum of 512 bytes long. Without compression,
339         // many DNS response messages are over this limit, so enabling
340         // compression will help ensure compliance.
341         let mut compression = Some(HashMap::new());
342 
343         for question in &self.questions {
344             msg = question.pack(msg, &mut compression, compression_off)?;
345         }
346         for answer in &mut self.answers {
347             msg = answer.pack(msg, &mut compression, compression_off)?;
348         }
349         for authority in &mut self.authorities {
350             msg = authority.pack(msg, &mut compression, compression_off)?;
351         }
352         for additional in &mut self.additionals {
353             msg = additional.pack(msg, &mut compression, compression_off)?;
354         }
355 
356         Ok(msg)
357     }
358 }
359