1 // Copyright 2016 The Rust Project Developers. See the COPYRIGHT 2 // file at the top-level directory of this distribution and at 3 // http://rust-lang.org/COPYRIGHT. 4 // 5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or 6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license 7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your 8 // option. This file may not be copied, modified, or distributed 9 // except according to those terms. 10 11 pub use self::{answer::DnsAnswer, query::DnsQuery}; 12 13 use alloc::{string::String, vec::Vec}; 14 use core::{slice, u16}; 15 16 mod answer; 17 mod query; 18 19 #[allow(non_camel_case_types)] 20 #[derive(Copy, Clone, Debug, Default)] 21 #[repr(packed)] 22 pub struct n16 { 23 inner: u16, 24 } 25 26 impl n16 { as_bytes(&self) -> &[u8]27 pub fn as_bytes(&self) -> &[u8] { 28 let left_8bits = (self.inner >> 8) as u8; 29 let right_8bits = self.inner as u8; 30 unsafe { 31 let bytes: [u8; 2] = [left_8bits, right_8bits]; 32 slice::from_raw_parts(bytes.as_ptr(), 2) 33 } 34 } 35 // pub fn as_bytes(&self) -> &[u8] { 36 // unsafe { slice::from_raw_parts((&self.inner as *const u16) as *const u8, 2) } 37 // } 38 from_bytes(bytes: &[u8]) -> Self39 pub fn from_bytes(bytes: &[u8]) -> Self { 40 n16 { 41 inner: unsafe { 42 slice::from_raw_parts(bytes.as_ptr() as *const u16, bytes.len() / 2)[0] 43 }, 44 } 45 } 46 } 47 48 impl From<u16> for n16 { from(value: u16) -> Self49 fn from(value: u16) -> Self { 50 n16 { 51 inner: value.to_be(), 52 } 53 } 54 } 55 56 impl From<n16> for u16 { from(value: n16) -> Self57 fn from(value: n16) -> Self { 58 u16::from_be(value.inner) 59 } 60 } 61 62 #[derive(Clone, Debug)] 63 pub struct Dns { 64 pub transaction_id: u16, 65 pub flags: u16, 66 pub queries: Vec<DnsQuery>, 67 pub answers: Vec<DnsAnswer>, 68 } 69 70 impl Dns { compile(&self) -> Vec<u8>71 pub fn compile(&self) -> Vec<u8> { 72 let mut data = Vec::new(); 73 74 macro_rules! push_u8 { 75 ($value:expr) => { 76 data.push($value); 77 }; 78 }; 79 80 macro_rules! push_n16 { 81 ($value:expr) => { 82 data.extend_from_slice(n16::from($value).as_bytes()); 83 }; 84 }; 85 86 push_n16!(self.transaction_id); 87 push_n16!(self.flags); 88 push_n16!(self.queries.len() as u16); 89 push_n16!(self.answers.len() as u16); 90 push_n16!(0); 91 push_n16!(0); 92 93 for query in self.queries.iter() { 94 for part in query.name.split('.') { 95 push_u8!(part.len() as u8); 96 data.extend_from_slice(part.as_bytes()); 97 } 98 push_u8!(0); 99 push_n16!(query.q_type); 100 push_n16!(query.q_class); 101 } 102 data 103 } 104 parse(data: &[u8]) -> Result<Self, String>105 pub fn parse(data: &[u8]) -> Result<Self, String> { 106 let name_ind = 0b1100_0000; 107 let mut i = 0; 108 109 macro_rules! pop_u8 { 110 () => {{ 111 i += 1; 112 if i > data.len() { 113 return Err(format!("{}: {}: pop_u8", file!(), line!())); 114 } 115 data[i - 1] 116 }}; 117 }; 118 119 macro_rules! pop_n16 { 120 () => {{ 121 i += 2; 122 if i > data.len() { 123 return Err(format!("{}: {}: pop_n16", file!(), line!())); 124 } 125 let x = u16::from(n16::from_bytes(&data[i - 2..i])); 126 x 127 }}; 128 }; 129 130 macro_rules! pop_data { 131 () => {{ 132 let mut data = Vec::new(); 133 134 let data_len = pop_n16!(); 135 for _data_i in 0..data_len { 136 data.push(pop_u8!()); 137 } 138 139 data 140 }}; 141 }; 142 143 macro_rules! pop_name { 144 () => {{ 145 let mut name = String::new(); 146 let old_i = i; 147 148 loop { 149 let name_len = pop_u8!(); 150 if name_len & name_ind == name_ind { 151 i -= 1; 152 i = (pop_n16!() - ((name_ind as u16) << 8)) as usize; 153 continue; 154 } 155 if name_len == 0 { 156 break; 157 } 158 if !name.is_empty() { 159 name.push('.'); 160 } 161 for _name_i in 0..name_len { 162 name.push(pop_u8!() as char); 163 } 164 } 165 166 if i <= old_i { 167 i = old_i + 2; 168 } 169 170 name 171 }}; 172 }; 173 174 let transaction_id = pop_n16!(); 175 let flags = pop_n16!(); 176 let queries_len = pop_n16!(); 177 let answers_len = pop_n16!(); 178 pop_n16!(); 179 pop_n16!(); 180 181 let mut queries = Vec::new(); 182 for _query_i in 0..queries_len { 183 queries.push(DnsQuery { 184 name: pop_name!(), 185 q_type: pop_n16!(), 186 q_class: pop_n16!(), 187 }); 188 } 189 190 let mut answers = Vec::new(); 191 for _answer_i in 0..answers_len { 192 answers.push(DnsAnswer { 193 name: pop_name!(), 194 a_type: pop_n16!(), 195 a_class: pop_n16!(), 196 ttl_a: pop_n16!(), 197 ttl_b: pop_n16!(), 198 data: pop_data!(), 199 }); 200 } 201 202 Ok(Dns { 203 transaction_id, 204 flags, 205 queries, 206 answers, 207 }) 208 } 209 } 210