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