xref: /webrtc/mdns/src/message/parser.rs (revision ffe74184)
1*ffe74184SMartin Algesten use crate::error::*;
2*ffe74184SMartin Algesten use crate::message::header::{Header, HeaderInternal, Section};
3*ffe74184SMartin Algesten use crate::message::name::Name;
4*ffe74184SMartin Algesten use crate::message::question::Question;
5*ffe74184SMartin Algesten use crate::message::resource::{unpack_resource_body, Resource, ResourceBody, ResourceHeader};
6*ffe74184SMartin Algesten use crate::message::{DnsClass, DnsType};
7*ffe74184SMartin Algesten 
8*ffe74184SMartin Algesten // A Parser allows incrementally parsing a DNS message.
9*ffe74184SMartin Algesten //
10*ffe74184SMartin Algesten // When parsing is started, the Header is parsed. Next, each question can be
11*ffe74184SMartin Algesten // either parsed or skipped. Alternatively, all Questions can be skipped at
12*ffe74184SMartin Algesten // once. When all Questions have been parsed, attempting to parse Questions
13*ffe74184SMartin Algesten // will return (nil, nil) and attempting to skip Questions will return
14*ffe74184SMartin Algesten // (true, nil). After all Questions have been either parsed or skipped, all
15*ffe74184SMartin Algesten // Answers, Authorities and Additionals can be either parsed or skipped in the
16*ffe74184SMartin Algesten // same way, and each type of Resource must be fully parsed or skipped before
17*ffe74184SMartin Algesten // proceeding to the next type of Resource.
18*ffe74184SMartin Algesten //
19*ffe74184SMartin Algesten // Note that there is no requirement to fully skip or parse the message.
20*ffe74184SMartin Algesten #[derive(Default)]
21*ffe74184SMartin Algesten pub struct Parser<'a> {
22*ffe74184SMartin Algesten     pub msg: &'a [u8],
23*ffe74184SMartin Algesten     pub header: HeaderInternal,
24*ffe74184SMartin Algesten 
25*ffe74184SMartin Algesten     pub section: Section,
26*ffe74184SMartin Algesten     pub off: usize,
27*ffe74184SMartin Algesten     pub index: usize,
28*ffe74184SMartin Algesten     pub res_header_valid: bool,
29*ffe74184SMartin Algesten     pub res_header: ResourceHeader,
30*ffe74184SMartin Algesten }
31*ffe74184SMartin Algesten 
32*ffe74184SMartin Algesten impl<'a> Parser<'a> {
33*ffe74184SMartin Algesten     // start parses the header and enables the parsing of Questions.
start(&mut self, msg: &'a [u8]) -> Result<Header>34*ffe74184SMartin Algesten     pub fn start(&mut self, msg: &'a [u8]) -> Result<Header> {
35*ffe74184SMartin Algesten         *self = Parser {
36*ffe74184SMartin Algesten             msg,
37*ffe74184SMartin Algesten             ..Default::default()
38*ffe74184SMartin Algesten         };
39*ffe74184SMartin Algesten         self.off = self.header.unpack(msg, 0)?;
40*ffe74184SMartin Algesten         self.section = Section::Questions;
41*ffe74184SMartin Algesten         Ok(self.header.header())
42*ffe74184SMartin Algesten     }
43*ffe74184SMartin Algesten 
check_advance(&mut self, sec: Section) -> Result<()>44*ffe74184SMartin Algesten     fn check_advance(&mut self, sec: Section) -> Result<()> {
45*ffe74184SMartin Algesten         if self.section < sec {
46*ffe74184SMartin Algesten             return Err(Error::ErrNotStarted);
47*ffe74184SMartin Algesten         }
48*ffe74184SMartin Algesten         if self.section > sec {
49*ffe74184SMartin Algesten             return Err(Error::ErrSectionDone);
50*ffe74184SMartin Algesten         }
51*ffe74184SMartin Algesten         self.res_header_valid = false;
52*ffe74184SMartin Algesten         if self.index == self.header.count(sec) as usize {
53*ffe74184SMartin Algesten             self.index = 0;
54*ffe74184SMartin Algesten             self.section = Section::from(1 + self.section as u8);
55*ffe74184SMartin Algesten             return Err(Error::ErrSectionDone);
56*ffe74184SMartin Algesten         }
57*ffe74184SMartin Algesten         Ok(())
58*ffe74184SMartin Algesten     }
59*ffe74184SMartin Algesten 
resource(&mut self, sec: Section) -> Result<Resource>60*ffe74184SMartin Algesten     fn resource(&mut self, sec: Section) -> Result<Resource> {
61*ffe74184SMartin Algesten         let header = self.resource_header(sec)?;
62*ffe74184SMartin Algesten         self.res_header_valid = false;
63*ffe74184SMartin Algesten         let (body, off) =
64*ffe74184SMartin Algesten             unpack_resource_body(header.typ, self.msg, self.off, header.length as usize)?;
65*ffe74184SMartin Algesten         self.off = off;
66*ffe74184SMartin Algesten         self.index += 1;
67*ffe74184SMartin Algesten         Ok(Resource {
68*ffe74184SMartin Algesten             header,
69*ffe74184SMartin Algesten             body: Some(body),
70*ffe74184SMartin Algesten         })
71*ffe74184SMartin Algesten     }
72*ffe74184SMartin Algesten 
resource_header(&mut self, sec: Section) -> Result<ResourceHeader>73*ffe74184SMartin Algesten     fn resource_header(&mut self, sec: Section) -> Result<ResourceHeader> {
74*ffe74184SMartin Algesten         if self.res_header_valid {
75*ffe74184SMartin Algesten             return Ok(self.res_header.clone());
76*ffe74184SMartin Algesten         }
77*ffe74184SMartin Algesten         self.check_advance(sec)?;
78*ffe74184SMartin Algesten         let mut hdr = ResourceHeader::default();
79*ffe74184SMartin Algesten         let off = hdr.unpack(self.msg, self.off, 0)?;
80*ffe74184SMartin Algesten 
81*ffe74184SMartin Algesten         self.res_header_valid = true;
82*ffe74184SMartin Algesten         self.res_header = hdr.clone();
83*ffe74184SMartin Algesten         self.off = off;
84*ffe74184SMartin Algesten         Ok(hdr)
85*ffe74184SMartin Algesten     }
86*ffe74184SMartin Algesten 
skip_resource(&mut self, sec: Section) -> Result<()>87*ffe74184SMartin Algesten     fn skip_resource(&mut self, sec: Section) -> Result<()> {
88*ffe74184SMartin Algesten         if self.res_header_valid {
89*ffe74184SMartin Algesten             let new_off = self.off + self.res_header.length as usize;
90*ffe74184SMartin Algesten             if new_off > self.msg.len() {
91*ffe74184SMartin Algesten                 return Err(Error::ErrResourceLen);
92*ffe74184SMartin Algesten             }
93*ffe74184SMartin Algesten             self.off = new_off;
94*ffe74184SMartin Algesten             self.res_header_valid = false;
95*ffe74184SMartin Algesten             self.index += 1;
96*ffe74184SMartin Algesten             return Ok(());
97*ffe74184SMartin Algesten         }
98*ffe74184SMartin Algesten         self.check_advance(sec)?;
99*ffe74184SMartin Algesten 
100*ffe74184SMartin Algesten         self.off = Resource::skip(self.msg, self.off)?;
101*ffe74184SMartin Algesten         self.index += 1;
102*ffe74184SMartin Algesten         Ok(())
103*ffe74184SMartin Algesten     }
104*ffe74184SMartin Algesten 
105*ffe74184SMartin Algesten     // question parses a single question.
question(&mut self) -> Result<Question>106*ffe74184SMartin Algesten     pub fn question(&mut self) -> Result<Question> {
107*ffe74184SMartin Algesten         self.check_advance(Section::Questions)?;
108*ffe74184SMartin Algesten         let mut name = Name::new("")?;
109*ffe74184SMartin Algesten         let mut off = name.unpack(self.msg, self.off)?;
110*ffe74184SMartin Algesten         let mut typ = DnsType::Unsupported;
111*ffe74184SMartin Algesten         off = typ.unpack(self.msg, off)?;
112*ffe74184SMartin Algesten         let mut class = DnsClass::default();
113*ffe74184SMartin Algesten         off = class.unpack(self.msg, off)?;
114*ffe74184SMartin Algesten         self.off = off;
115*ffe74184SMartin Algesten         self.index += 1;
116*ffe74184SMartin Algesten         Ok(Question { name, typ, class })
117*ffe74184SMartin Algesten     }
118*ffe74184SMartin Algesten 
119*ffe74184SMartin Algesten     // all_questions parses all Questions.
all_questions(&mut self) -> Result<Vec<Question>>120*ffe74184SMartin Algesten     pub fn all_questions(&mut self) -> Result<Vec<Question>> {
121*ffe74184SMartin Algesten         // Multiple questions are valid according to the spec,
122*ffe74184SMartin Algesten         // but servers don't actually support them. There will
123*ffe74184SMartin Algesten         // be at most one question here.
124*ffe74184SMartin Algesten         //
125*ffe74184SMartin Algesten         // Do not pre-allocate based on info in self.header, since
126*ffe74184SMartin Algesten         // the data is untrusted.
127*ffe74184SMartin Algesten         let mut qs = vec![];
128*ffe74184SMartin Algesten         loop {
129*ffe74184SMartin Algesten             match self.question() {
130*ffe74184SMartin Algesten                 Err(err) => {
131*ffe74184SMartin Algesten                     if Error::ErrSectionDone == err {
132*ffe74184SMartin Algesten                         return Ok(qs);
133*ffe74184SMartin Algesten                     } else {
134*ffe74184SMartin Algesten                         return Err(err);
135*ffe74184SMartin Algesten                     }
136*ffe74184SMartin Algesten                 }
137*ffe74184SMartin Algesten                 Ok(q) => qs.push(q),
138*ffe74184SMartin Algesten             }
139*ffe74184SMartin Algesten         }
140*ffe74184SMartin Algesten     }
141*ffe74184SMartin Algesten 
142*ffe74184SMartin Algesten     // skip_question skips a single question.
skip_question(&mut self) -> Result<()>143*ffe74184SMartin Algesten     pub fn skip_question(&mut self) -> Result<()> {
144*ffe74184SMartin Algesten         self.check_advance(Section::Questions)?;
145*ffe74184SMartin Algesten         let mut off = Name::skip(self.msg, self.off)?;
146*ffe74184SMartin Algesten         off = DnsType::skip(self.msg, off)?;
147*ffe74184SMartin Algesten         off = DnsClass::skip(self.msg, off)?;
148*ffe74184SMartin Algesten         self.off = off;
149*ffe74184SMartin Algesten         self.index += 1;
150*ffe74184SMartin Algesten         Ok(())
151*ffe74184SMartin Algesten     }
152*ffe74184SMartin Algesten 
153*ffe74184SMartin Algesten     // skip_all_questions skips all Questions.
skip_all_questions(&mut self) -> Result<()>154*ffe74184SMartin Algesten     pub fn skip_all_questions(&mut self) -> Result<()> {
155*ffe74184SMartin Algesten         loop {
156*ffe74184SMartin Algesten             if let Err(err) = self.skip_question() {
157*ffe74184SMartin Algesten                 if Error::ErrSectionDone == err {
158*ffe74184SMartin Algesten                     return Ok(());
159*ffe74184SMartin Algesten                 } else {
160*ffe74184SMartin Algesten                     return Err(err);
161*ffe74184SMartin Algesten                 }
162*ffe74184SMartin Algesten             }
163*ffe74184SMartin Algesten         }
164*ffe74184SMartin Algesten     }
165*ffe74184SMartin Algesten 
166*ffe74184SMartin Algesten     // answer_header parses a single answer ResourceHeader.
answer_header(&mut self) -> Result<ResourceHeader>167*ffe74184SMartin Algesten     pub fn answer_header(&mut self) -> Result<ResourceHeader> {
168*ffe74184SMartin Algesten         self.resource_header(Section::Answers)
169*ffe74184SMartin Algesten     }
170*ffe74184SMartin Algesten 
171*ffe74184SMartin Algesten     // answer parses a single answer Resource.
answer(&mut self) -> Result<Resource>172*ffe74184SMartin Algesten     pub fn answer(&mut self) -> Result<Resource> {
173*ffe74184SMartin Algesten         self.resource(Section::Answers)
174*ffe74184SMartin Algesten     }
175*ffe74184SMartin Algesten 
176*ffe74184SMartin Algesten     // all_answers parses all answer Resources.
all_answers(&mut self) -> Result<Vec<Resource>>177*ffe74184SMartin Algesten     pub fn all_answers(&mut self) -> Result<Vec<Resource>> {
178*ffe74184SMartin Algesten         // The most common query is for A/AAAA, which usually returns
179*ffe74184SMartin Algesten         // a handful of IPs.
180*ffe74184SMartin Algesten         //
181*ffe74184SMartin Algesten         // Pre-allocate up to a certain limit, since self.header is
182*ffe74184SMartin Algesten         // untrusted data.
183*ffe74184SMartin Algesten         let mut n = self.header.answers as usize;
184*ffe74184SMartin Algesten         if n > 20 {
185*ffe74184SMartin Algesten             n = 20
186*ffe74184SMartin Algesten         }
187*ffe74184SMartin Algesten         let mut a = Vec::with_capacity(n);
188*ffe74184SMartin Algesten         loop {
189*ffe74184SMartin Algesten             match self.answer() {
190*ffe74184SMartin Algesten                 Err(err) => {
191*ffe74184SMartin Algesten                     if Error::ErrSectionDone == err {
192*ffe74184SMartin Algesten                         return Ok(a);
193*ffe74184SMartin Algesten                     } else {
194*ffe74184SMartin Algesten                         return Err(err);
195*ffe74184SMartin Algesten                     }
196*ffe74184SMartin Algesten                 }
197*ffe74184SMartin Algesten                 Ok(r) => a.push(r),
198*ffe74184SMartin Algesten             }
199*ffe74184SMartin Algesten         }
200*ffe74184SMartin Algesten     }
201*ffe74184SMartin Algesten 
202*ffe74184SMartin Algesten     // skip_answer skips a single answer Resource.
skip_answer(&mut self) -> Result<()>203*ffe74184SMartin Algesten     pub fn skip_answer(&mut self) -> Result<()> {
204*ffe74184SMartin Algesten         self.skip_resource(Section::Answers)
205*ffe74184SMartin Algesten     }
206*ffe74184SMartin Algesten 
207*ffe74184SMartin Algesten     // skip_all_answers skips all answer Resources.
skip_all_answers(&mut self) -> Result<()>208*ffe74184SMartin Algesten     pub fn skip_all_answers(&mut self) -> Result<()> {
209*ffe74184SMartin Algesten         loop {
210*ffe74184SMartin Algesten             if let Err(err) = self.skip_answer() {
211*ffe74184SMartin Algesten                 if Error::ErrSectionDone == err {
212*ffe74184SMartin Algesten                     return Ok(());
213*ffe74184SMartin Algesten                 } else {
214*ffe74184SMartin Algesten                     return Err(err);
215*ffe74184SMartin Algesten                 }
216*ffe74184SMartin Algesten             }
217*ffe74184SMartin Algesten         }
218*ffe74184SMartin Algesten     }
219*ffe74184SMartin Algesten 
220*ffe74184SMartin Algesten     // authority_header parses a single authority ResourceHeader.
authority_header(&mut self) -> Result<ResourceHeader>221*ffe74184SMartin Algesten     pub fn authority_header(&mut self) -> Result<ResourceHeader> {
222*ffe74184SMartin Algesten         self.resource_header(Section::Authorities)
223*ffe74184SMartin Algesten     }
224*ffe74184SMartin Algesten 
225*ffe74184SMartin Algesten     // authority parses a single authority Resource.
authority(&mut self) -> Result<Resource>226*ffe74184SMartin Algesten     pub fn authority(&mut self) -> Result<Resource> {
227*ffe74184SMartin Algesten         self.resource(Section::Authorities)
228*ffe74184SMartin Algesten     }
229*ffe74184SMartin Algesten 
230*ffe74184SMartin Algesten     // all_authorities parses all authority Resources.
all_authorities(&mut self) -> Result<Vec<Resource>>231*ffe74184SMartin Algesten     pub fn all_authorities(&mut self) -> Result<Vec<Resource>> {
232*ffe74184SMartin Algesten         // Authorities contains SOA in case of NXDOMAIN and friends,
233*ffe74184SMartin Algesten         // otherwise it is empty.
234*ffe74184SMartin Algesten         //
235*ffe74184SMartin Algesten         // Pre-allocate up to a certain limit, since self.header is
236*ffe74184SMartin Algesten         // untrusted data.
237*ffe74184SMartin Algesten         let mut n = self.header.authorities as usize;
238*ffe74184SMartin Algesten         if n > 10 {
239*ffe74184SMartin Algesten             n = 10;
240*ffe74184SMartin Algesten         }
241*ffe74184SMartin Algesten         let mut a = Vec::with_capacity(n);
242*ffe74184SMartin Algesten         loop {
243*ffe74184SMartin Algesten             match self.authority() {
244*ffe74184SMartin Algesten                 Err(err) => {
245*ffe74184SMartin Algesten                     if Error::ErrSectionDone == err {
246*ffe74184SMartin Algesten                         return Ok(a);
247*ffe74184SMartin Algesten                     } else {
248*ffe74184SMartin Algesten                         return Err(err);
249*ffe74184SMartin Algesten                     }
250*ffe74184SMartin Algesten                 }
251*ffe74184SMartin Algesten                 Ok(r) => a.push(r),
252*ffe74184SMartin Algesten             }
253*ffe74184SMartin Algesten         }
254*ffe74184SMartin Algesten     }
255*ffe74184SMartin Algesten 
256*ffe74184SMartin Algesten     // skip_authority skips a single authority Resource.
skip_authority(&mut self) -> Result<()>257*ffe74184SMartin Algesten     pub fn skip_authority(&mut self) -> Result<()> {
258*ffe74184SMartin Algesten         self.skip_resource(Section::Authorities)
259*ffe74184SMartin Algesten     }
260*ffe74184SMartin Algesten 
261*ffe74184SMartin Algesten     // skip_all_authorities skips all authority Resources.
skip_all_authorities(&mut self) -> Result<()>262*ffe74184SMartin Algesten     pub fn skip_all_authorities(&mut self) -> Result<()> {
263*ffe74184SMartin Algesten         loop {
264*ffe74184SMartin Algesten             if let Err(err) = self.skip_authority() {
265*ffe74184SMartin Algesten                 if Error::ErrSectionDone == err {
266*ffe74184SMartin Algesten                     return Ok(());
267*ffe74184SMartin Algesten                 } else {
268*ffe74184SMartin Algesten                     return Err(err);
269*ffe74184SMartin Algesten                 }
270*ffe74184SMartin Algesten             }
271*ffe74184SMartin Algesten         }
272*ffe74184SMartin Algesten     }
273*ffe74184SMartin Algesten 
274*ffe74184SMartin Algesten     // additional_header parses a single additional ResourceHeader.
additional_header(&mut self) -> Result<ResourceHeader>275*ffe74184SMartin Algesten     pub fn additional_header(&mut self) -> Result<ResourceHeader> {
276*ffe74184SMartin Algesten         self.resource_header(Section::Additionals)
277*ffe74184SMartin Algesten     }
278*ffe74184SMartin Algesten 
279*ffe74184SMartin Algesten     // additional parses a single additional Resource.
additional(&mut self) -> Result<Resource>280*ffe74184SMartin Algesten     pub fn additional(&mut self) -> Result<Resource> {
281*ffe74184SMartin Algesten         self.resource(Section::Additionals)
282*ffe74184SMartin Algesten     }
283*ffe74184SMartin Algesten 
284*ffe74184SMartin Algesten     // all_additionals parses all additional Resources.
all_additionals(&mut self) -> Result<Vec<Resource>>285*ffe74184SMartin Algesten     pub fn all_additionals(&mut self) -> Result<Vec<Resource>> {
286*ffe74184SMartin Algesten         // Additionals usually contain OPT, and sometimes A/AAAA
287*ffe74184SMartin Algesten         // glue records.
288*ffe74184SMartin Algesten         //
289*ffe74184SMartin Algesten         // Pre-allocate up to a certain limit, since self.header is
290*ffe74184SMartin Algesten         // untrusted data.
291*ffe74184SMartin Algesten         let mut n = self.header.additionals as usize;
292*ffe74184SMartin Algesten         if n > 10 {
293*ffe74184SMartin Algesten             n = 10;
294*ffe74184SMartin Algesten         }
295*ffe74184SMartin Algesten         let mut a = Vec::with_capacity(n);
296*ffe74184SMartin Algesten         loop {
297*ffe74184SMartin Algesten             match self.additional() {
298*ffe74184SMartin Algesten                 Err(err) => {
299*ffe74184SMartin Algesten                     if Error::ErrSectionDone == err {
300*ffe74184SMartin Algesten                         return Ok(a);
301*ffe74184SMartin Algesten                     } else {
302*ffe74184SMartin Algesten                         return Err(err);
303*ffe74184SMartin Algesten                     }
304*ffe74184SMartin Algesten                 }
305*ffe74184SMartin Algesten                 Ok(r) => a.push(r),
306*ffe74184SMartin Algesten             }
307*ffe74184SMartin Algesten         }
308*ffe74184SMartin Algesten     }
309*ffe74184SMartin Algesten 
310*ffe74184SMartin Algesten     // skip_additional skips a single additional Resource.
skip_additional(&mut self) -> Result<()>311*ffe74184SMartin Algesten     pub fn skip_additional(&mut self) -> Result<()> {
312*ffe74184SMartin Algesten         self.skip_resource(Section::Additionals)
313*ffe74184SMartin Algesten     }
314*ffe74184SMartin Algesten 
315*ffe74184SMartin Algesten     // skip_all_additionals skips all additional Resources.
skip_all_additionals(&mut self) -> Result<()>316*ffe74184SMartin Algesten     pub fn skip_all_additionals(&mut self) -> Result<()> {
317*ffe74184SMartin Algesten         loop {
318*ffe74184SMartin Algesten             if let Err(err) = self.skip_additional() {
319*ffe74184SMartin Algesten                 if Error::ErrSectionDone == err {
320*ffe74184SMartin Algesten                     return Ok(());
321*ffe74184SMartin Algesten                 } else {
322*ffe74184SMartin Algesten                     return Err(err);
323*ffe74184SMartin Algesten                 }
324*ffe74184SMartin Algesten             }
325*ffe74184SMartin Algesten         }
326*ffe74184SMartin Algesten     }
327*ffe74184SMartin Algesten 
328*ffe74184SMartin Algesten     // resource_body parses a single resource_boy.
329*ffe74184SMartin Algesten     //
330*ffe74184SMartin Algesten     // One of the XXXHeader methods must have been called before calling this
331*ffe74184SMartin Algesten     // method.
resource_body(&mut self) -> Result<Box<dyn ResourceBody>>332*ffe74184SMartin Algesten     pub fn resource_body(&mut self) -> Result<Box<dyn ResourceBody>> {
333*ffe74184SMartin Algesten         if !self.res_header_valid {
334*ffe74184SMartin Algesten             return Err(Error::ErrNotStarted);
335*ffe74184SMartin Algesten         }
336*ffe74184SMartin Algesten         let (rb, _off) = unpack_resource_body(
337*ffe74184SMartin Algesten             self.res_header.typ,
338*ffe74184SMartin Algesten             self.msg,
339*ffe74184SMartin Algesten             self.off,
340*ffe74184SMartin Algesten             self.res_header.length as usize,
341*ffe74184SMartin Algesten         )?;
342*ffe74184SMartin Algesten         self.off += self.res_header.length as usize;
343*ffe74184SMartin Algesten         self.res_header_valid = false;
344*ffe74184SMartin Algesten         self.index += 1;
345*ffe74184SMartin Algesten         Ok(rb)
346*ffe74184SMartin Algesten     }
347*ffe74184SMartin Algesten }
348