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