1 use super::*; 2 3 // Header is a representation of a DNS message header. 4 #[derive(Default, Debug, Copy, Clone, PartialEq, Eq)] 5 pub struct Header { 6 pub id: u16, 7 pub response: bool, 8 pub op_code: OpCode, 9 pub authoritative: bool, 10 pub truncated: bool, 11 pub recursion_desired: bool, 12 pub recursion_available: bool, 13 pub rcode: RCode, 14 } 15 16 impl fmt::Display for Header { 17 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 18 write!( 19 f, 20 "dnsmessage.Header{{id: {}, response: {}, op_code: {}, authoritative: {}, truncated: {}, recursion_desired: {}, recursion_available: {}, rcode: {} }}", 21 self.id, 22 self.response, 23 self.op_code, 24 self.authoritative, 25 self.truncated, 26 self.recursion_desired, 27 self.recursion_available, 28 self.rcode 29 ) 30 } 31 } 32 33 impl Header { 34 pub fn pack(&self) -> (u16, u16) { 35 let id = self.id; 36 let mut bits = (self.op_code as u16) << 11 | self.rcode as u16; 37 if self.recursion_available { 38 bits |= HEADER_BIT_RA 39 } 40 if self.recursion_desired { 41 bits |= HEADER_BIT_RD 42 } 43 if self.truncated { 44 bits |= HEADER_BIT_TC 45 } 46 if self.authoritative { 47 bits |= HEADER_BIT_AA 48 } 49 if self.response { 50 bits |= HEADER_BIT_QR 51 } 52 53 (id, bits) 54 } 55 } 56 57 #[derive(Copy, Clone, PartialOrd, PartialEq, Eq)] 58 pub enum Section { 59 NotStarted = 0, 60 Header = 1, 61 Questions = 2, 62 Answers = 3, 63 Authorities = 4, 64 Additionals = 5, 65 Done = 6, 66 } 67 68 impl Default for Section { 69 fn default() -> Self { 70 Section::NotStarted 71 } 72 } 73 74 impl From<u8> for Section { 75 fn from(v: u8) -> Self { 76 match v { 77 0 => Section::NotStarted, 78 1 => Section::Header, 79 2 => Section::Questions, 80 3 => Section::Answers, 81 4 => Section::Authorities, 82 5 => Section::Additionals, 83 _ => Section::Done, 84 } 85 } 86 } 87 88 impl fmt::Display for Section { 89 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 90 let s = match *self { 91 Section::NotStarted => "NotStarted", 92 Section::Header => "Header", 93 Section::Questions => "question", 94 Section::Answers => "answer", 95 Section::Authorities => "authority", 96 Section::Additionals => "additional", 97 Section::Done => "Done", 98 }; 99 write!(f, "{}", s) 100 } 101 } 102 103 // header is the wire format for a DNS message header. 104 #[derive(Default)] 105 pub struct HeaderInternal { 106 pub id: u16, 107 pub bits: u16, 108 pub questions: u16, 109 pub answers: u16, 110 pub authorities: u16, 111 pub additionals: u16, 112 } 113 114 impl HeaderInternal { 115 pub(crate) fn count(&self, sec: Section) -> u16 { 116 match sec { 117 Section::Questions => self.questions, 118 Section::Answers => self.answers, 119 Section::Authorities => self.authorities, 120 Section::Additionals => self.additionals, 121 _ => 0, 122 } 123 } 124 125 // pack appends the wire format of the header to msg. 126 pub(crate) fn pack(&self, mut msg: Vec<u8>) -> Vec<u8> { 127 msg = pack_uint16(msg, self.id); 128 msg = pack_uint16(msg, self.bits); 129 msg = pack_uint16(msg, self.questions); 130 msg = pack_uint16(msg, self.answers); 131 msg = pack_uint16(msg, self.authorities); 132 msg = pack_uint16(msg, self.additionals); 133 msg 134 } 135 136 pub(crate) fn unpack(&mut self, msg: &[u8], off: usize) -> Result<usize> { 137 let (id, off) = unpack_uint16(msg, off)?; 138 self.id = id; 139 140 let (bits, off) = unpack_uint16(msg, off)?; 141 self.bits = bits; 142 143 let (questions, off) = unpack_uint16(msg, off)?; 144 self.questions = questions; 145 146 let (answers, off) = unpack_uint16(msg, off)?; 147 self.answers = answers; 148 149 let (authorities, off) = unpack_uint16(msg, off)?; 150 self.authorities = authorities; 151 152 let (additionals, off) = unpack_uint16(msg, off)?; 153 self.additionals = additionals; 154 155 Ok(off) 156 } 157 158 pub(crate) fn header(&self) -> Header { 159 Header { 160 id: self.id, 161 response: (self.bits & HEADER_BIT_QR) != 0, 162 op_code: ((self.bits >> 11) & 0xF) as OpCode, 163 authoritative: (self.bits & HEADER_BIT_AA) != 0, 164 truncated: (self.bits & HEADER_BIT_TC) != 0, 165 recursion_desired: (self.bits & HEADER_BIT_RD) != 0, 166 recursion_available: (self.bits & HEADER_BIT_RA) != 0, 167 rcode: RCode::from((self.bits & 0xF) as u8), 168 } 169 } 170 } 171