1 use super::*; 2 use crate::error::Result; 3 use crate::error::*; 4 use crate::message::packer::*; 5 6 // An OPTResource is an OPT pseudo Resource record. 7 // 8 // The pseudo resource record is part of the extension mechanisms for DNS 9 // as defined in RFC 6891. 10 #[derive(Default, Debug, Clone, PartialEq, Eq)] 11 pub struct OptResource { 12 pub options: Vec<DnsOption>, 13 } 14 15 // An Option represents a DNS message option within OPTResource. 16 // 17 // The message option is part of the extension mechanisms for DNS as 18 // defined in RFC 6891. 19 #[derive(Default, Debug, Clone, PartialEq, Eq)] 20 pub struct DnsOption { 21 pub code: u16, // option code 22 pub data: Vec<u8>, 23 } 24 25 impl fmt::Display for DnsOption { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result26 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 27 write!( 28 f, 29 "dnsmessage.Option{{Code: {}, Data: {:?}}}", 30 self.code, self.data 31 ) 32 } 33 } 34 35 impl fmt::Display for OptResource { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 37 let s: Vec<String> = self.options.iter().map(|o| o.to_string()).collect(); 38 write!(f, "dnsmessage.OPTResource{{options: {}}}", s.join(",")) 39 } 40 } 41 42 impl ResourceBody for OptResource { real_type(&self) -> DnsType43 fn real_type(&self) -> DnsType { 44 DnsType::Opt 45 } 46 pack( &self, mut msg: Vec<u8>, _compression: &mut Option<HashMap<String, usize>>, _compression_off: usize, ) -> Result<Vec<u8>>47 fn pack( 48 &self, 49 mut msg: Vec<u8>, 50 _compression: &mut Option<HashMap<String, usize>>, 51 _compression_off: usize, 52 ) -> Result<Vec<u8>> { 53 for opt in &self.options { 54 msg = pack_uint16(msg, opt.code); 55 msg = pack_uint16(msg, opt.data.len() as u16); 56 msg = pack_bytes(msg, &opt.data); 57 } 58 Ok(msg) 59 } 60 unpack(&mut self, msg: &[u8], mut off: usize, length: usize) -> Result<usize>61 fn unpack(&mut self, msg: &[u8], mut off: usize, length: usize) -> Result<usize> { 62 let mut opts = vec![]; 63 let old_off = off; 64 while off < old_off + length { 65 let (code, new_off) = unpack_uint16(msg, off)?; 66 off = new_off; 67 68 let (l, new_off) = unpack_uint16(msg, off)?; 69 off = new_off; 70 71 let mut opt = DnsOption { 72 code, 73 data: vec![0; l as usize], 74 }; 75 if off + l as usize > msg.len() { 76 return Err(Error::ErrCalcLen); 77 } 78 opt.data.copy_from_slice(&msg[off..off + l as usize]); 79 off += l as usize; 80 opts.push(opt); 81 } 82 self.options = opts; 83 Ok(off) 84 } 85 } 86