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 { 27 pub fn as_bytes(&self) -> &[u8] { 28 unsafe { slice::from_raw_parts((&self.inner as *const u16) as *const u8, 2) } 29 } 30 31 pub fn from_bytes(bytes: &[u8]) -> Self { 32 n16 { 33 inner: unsafe { 34 slice::from_raw_parts(bytes.as_ptr() as *const u16, bytes.len() / 2)[0] 35 }, 36 } 37 } 38 } 39 40 impl From<u16> for n16 { 41 fn from(value: u16) -> Self { 42 n16 { 43 inner: value.to_be(), 44 } 45 } 46 } 47 48 impl From<n16> for u16 { 49 fn from(value: n16) -> Self { 50 u16::from_be(value.inner) 51 } 52 } 53 54 #[derive(Clone, Debug)] 55 pub struct Dns { 56 pub transaction_id: u16, 57 pub flags: u16, 58 pub queries: Vec<DnsQuery>, 59 pub answers: Vec<DnsAnswer>, 60 } 61 62 impl Dns { 63 pub fn compile(&self) -> Vec<u8> { 64 let mut data = Vec::new(); 65 66 macro_rules! push_u8 { 67 ($value:expr) => { 68 data.push($value); 69 }; 70 }; 71 72 macro_rules! push_n16 { 73 ($value:expr) => { 74 data.extend_from_slice(n16::from($value).as_bytes()); 75 }; 76 }; 77 78 push_n16!(self.transaction_id); 79 push_n16!(self.flags); 80 push_n16!(self.queries.len() as u16); 81 push_n16!(self.answers.len() as u16); 82 push_n16!(0); 83 push_n16!(0); 84 85 for query in self.queries.iter() { 86 for part in query.name.split('.') { 87 push_u8!(part.len() as u8); 88 data.extend_from_slice(part.as_bytes()); 89 } 90 push_u8!(0); 91 push_n16!(query.q_type); 92 push_n16!(query.q_class); 93 } 94 data 95 } 96 97 pub fn parse(data: &[u8]) -> Result<Self, String> { 98 let name_ind = 0b1100_0000; 99 let mut i = 0; 100 101 macro_rules! pop_u8 { 102 () => {{ 103 i += 1; 104 if i > data.len() { 105 return Err(format!("{}: {}: pop_u8", file!(), line!())); 106 } 107 data[i - 1] 108 }}; 109 }; 110 111 macro_rules! pop_n16 { 112 () => {{ 113 i += 2; 114 if i > data.len() { 115 return Err(format!("{}: {}: pop_n16", file!(), line!())); 116 } 117 u16::from(n16::from_bytes(&data[i - 2..i])) 118 }}; 119 }; 120 121 macro_rules! pop_data { 122 () => {{ 123 let mut data = Vec::new(); 124 125 let data_len = pop_n16!(); 126 for _data_i in 0..data_len { 127 data.push(pop_u8!()); 128 } 129 130 data 131 }}; 132 }; 133 134 macro_rules! pop_name { 135 () => {{ 136 let mut name = String::new(); 137 let old_i = i; 138 139 loop { 140 let name_len = pop_u8!(); 141 if name_len & name_ind == name_ind { 142 i -= 1; 143 i = (pop_n16!() - ((name_ind as u16) << 8)) as usize; 144 continue; 145 } 146 if name_len == 0 { 147 break; 148 } 149 if !name.is_empty() { 150 name.push('.'); 151 } 152 for _name_i in 0..name_len { 153 name.push(pop_u8!() as char); 154 } 155 } 156 157 if i <= old_i { 158 i = old_i + 2; 159 } 160 161 name 162 }}; 163 }; 164 165 let transaction_id = pop_n16!(); 166 let flags = pop_n16!(); 167 let queries_len = pop_n16!(); 168 let answers_len = pop_n16!(); 169 pop_n16!(); 170 pop_n16!(); 171 172 let mut queries = Vec::new(); 173 for _query_i in 0..queries_len { 174 queries.push(DnsQuery { 175 name: pop_name!(), 176 q_type: pop_n16!(), 177 q_class: pop_n16!(), 178 }); 179 } 180 181 let mut answers = Vec::new(); 182 for _answer_i in 0..answers_len { 183 answers.push(DnsAnswer { 184 name: pop_name!(), 185 a_type: pop_n16!(), 186 a_class: pop_n16!(), 187 ttl_a: pop_n16!(), 188 ttl_b: pop_n16!(), 189 data: pop_data!(), 190 }); 191 } 192 193 Ok(Dns { 194 transaction_id, 195 flags, 196 queries, 197 answers, 198 }) 199 } 200 } 201