1 use alloc::{ 2 boxed::Box, 3 string::{String, ToString}, 4 vec::{IntoIter, Vec}, 5 }; 6 use core::mem; 7 8 use crate::platform::{types::*, Pal, Sys}; 9 10 use crate::header::{ 11 arpa_inet::htons, 12 errno::*, 13 netinet_in::{in_addr, sockaddr_in, IPPROTO_UDP}, 14 sys_socket::{ 15 self, 16 constants::{AF_INET, SOCK_DGRAM}, 17 sockaddr, socklen_t, 18 }, 19 time::{self, timespec}, 20 }; 21 22 use super::{ 23 dns::{Dns, DnsQuery}, 24 sys::get_dns_server, 25 }; 26 27 pub struct LookupHost(IntoIter<in_addr>); 28 29 impl Iterator for LookupHost { 30 type Item = in_addr; 31 fn next(&mut self) -> Option<Self::Item> { 32 self.0.next() 33 } 34 } 35 36 pub fn lookup_host(host: &str) -> Result<LookupHost, c_int> { 37 let dns_string = get_dns_server(); 38 39 let dns_vec: Vec<u8> = dns_string 40 .trim() 41 .split('.') 42 .map(|octet| octet.parse::<u8>().unwrap_or(0)) 43 .collect(); 44 45 if dns_vec.len() == 4 { 46 let mut dns_arr = [0u8; 4]; 47 for (i, octet) in dns_vec.iter().enumerate() { 48 dns_arr[i] = *octet; 49 } 50 let dns_addr = unsafe { mem::transmute::<[u8; 4], u32>(dns_arr) }; 51 52 let mut timespec = timespec::default(); 53 Sys::clock_gettime(time::constants::CLOCK_REALTIME, &mut timespec); 54 let tid = (timespec.tv_nsec >> 16) as u16; 55 56 let packet = Dns { 57 transaction_id: tid, 58 flags: 0x0100, 59 queries: vec![DnsQuery { 60 name: host.to_string(), 61 q_type: 0x0001, 62 q_class: 0x0001, 63 }], 64 answers: vec![], 65 }; 66 67 let packet_data = packet.compile(); 68 let packet_data_len = packet_data.len(); 69 70 let packet_data_box = packet_data.into_boxed_slice(); 71 let packet_data_ptr = Box::into_raw(packet_data_box) as *mut _ as *mut c_void; 72 73 let dest = sockaddr_in { 74 sin_family: AF_INET as u16, 75 sin_port: htons(53), 76 sin_addr: in_addr { s_addr: dns_addr }, 77 ..Default::default() 78 }; 79 let dest_ptr = &dest as *const _ as *const sockaddr; 80 81 let sock = unsafe { 82 let sock = sys_socket::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP as i32); 83 if sys_socket::connect(sock, dest_ptr, mem::size_of_val(&dest) as socklen_t) < 0 { 84 return Err(EIO); 85 } 86 if sys_socket::send(sock, packet_data_ptr, packet_data_len, 0) < 0 { 87 Box::from_raw(packet_data_ptr); 88 return Err(EIO); 89 } 90 sock 91 }; 92 93 unsafe { 94 Box::from_raw(packet_data_ptr); 95 } 96 97 let i = 0 as socklen_t; 98 let mut buf = vec![0u8; 65536]; 99 let buf_ptr = buf.as_mut_ptr() as *mut c_void; 100 101 let count = unsafe { sys_socket::recv(sock, buf_ptr, 65536, 0) }; 102 if count < 0 { 103 return Err(EIO); 104 } 105 106 match Dns::parse(&buf[..count as usize]) { 107 Ok(response) => { 108 let mut addrs = vec![]; 109 for answer in response.answers.iter() { 110 if answer.a_type == 0x0001 && answer.a_class == 0x0001 && answer.data.len() == 4 111 { 112 let addr = in_addr { 113 s_addr: unsafe { 114 mem::transmute::<[u8; 4], u32>([ 115 answer.data[0], 116 answer.data[1], 117 answer.data[2], 118 answer.data[3], 119 ]) 120 }, 121 }; 122 addrs.push(addr); 123 } 124 } 125 Ok(LookupHost(addrs.into_iter())) 126 } 127 Err(_err) => Err(EINVAL), 128 } 129 } else { 130 Err(EINVAL) 131 } 132 } 133 134 pub fn lookup_addr(addr: in_addr) -> Result<Vec<Vec<u8>>, c_int> { 135 let dns_string = get_dns_server(); 136 137 let dns_vec: Vec<u8> = dns_string 138 .trim() 139 .split('.') 140 .map(|octet| octet.parse::<u8>().unwrap_or(0)) 141 .collect(); 142 143 let mut dns_arr = [0u8; 4]; 144 145 for (i, octet) in dns_vec.iter().enumerate() { 146 dns_arr[i] = *octet; 147 } 148 149 let mut addr_vec: Vec<u8> = unsafe { mem::transmute::<u32, [u8; 4]>(addr.s_addr).to_vec() }; 150 addr_vec.reverse(); 151 let mut name: Vec<u8> = vec![]; 152 for octet in addr_vec { 153 for ch in format!("{}", octet).as_bytes() { 154 name.push(*ch); 155 } 156 name.push(b"."[0]); 157 } 158 name.pop(); 159 for ch in b".IN-ADDR.ARPA" { 160 name.push(*ch); 161 } 162 163 if dns_vec.len() == 4 { 164 let mut timespec = timespec::default(); 165 Sys::clock_gettime(time::constants::CLOCK_REALTIME, &mut timespec); 166 let tid = (timespec.tv_nsec >> 16) as u16; 167 168 let packet = Dns { 169 transaction_id: tid, 170 flags: 0x0100, 171 queries: vec![DnsQuery { 172 name: String::from_utf8(name).unwrap(), 173 q_type: 0x000C, 174 q_class: 0x0001, 175 }], 176 answers: vec![], 177 }; 178 179 let packet_data = packet.compile(); 180 let packet_data_len = packet_data.len(); 181 let packet_data_box = packet_data.into_boxed_slice(); 182 let packet_data_ptr = Box::into_raw(packet_data_box) as *mut _ as *mut c_void; 183 184 let dest = sockaddr_in { 185 sin_family: AF_INET as u16, 186 sin_port: htons(53), 187 sin_addr: in_addr { 188 s_addr: unsafe { mem::transmute::<[u8; 4], u32>(dns_arr) }, 189 }, 190 ..Default::default() 191 }; 192 193 let dest_ptr = &dest as *const _ as *const sockaddr; 194 195 let sock = unsafe { 196 let sock = sys_socket::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP as i32); 197 if sys_socket::connect(sock, dest_ptr, mem::size_of_val(&dest) as socklen_t) < 0 { 198 return Err(EIO); 199 } 200 sock 201 }; 202 203 unsafe { 204 if sys_socket::send(sock, packet_data_ptr, packet_data_len, 0) < 0 { 205 return Err(EIO); 206 } 207 } 208 209 unsafe { 210 Box::from_raw(packet_data_ptr); 211 } 212 213 let i = mem::size_of::<sockaddr_in>() as socklen_t; 214 let mut buf = [0u8; 65536]; 215 let buf_ptr = buf.as_mut_ptr() as *mut c_void; 216 217 let count = unsafe { sys_socket::recv(sock, buf_ptr, 65536, 0) }; 218 if count < 0 { 219 return Err(EIO); 220 } 221 222 match Dns::parse(&buf[..count as usize]) { 223 Ok(response) => { 224 let mut names = vec![]; 225 for answer in response.answers.iter() { 226 if answer.a_type == 0x000C && answer.a_class == 0x0001 { 227 // answer.data is encoded kinda weird. 228 // Basically length-prefixed strings for each 229 // subsection of the domain. 230 // We need to parse this to insert periods where 231 // they belong (ie at the end of each string) 232 let data = parse_revdns_answer(&answer.data); 233 names.push(data); 234 } 235 } 236 Ok(names) 237 } 238 Err(_err) => Err(EINVAL), 239 } 240 } else { 241 Err(EINVAL) 242 } 243 } 244 245 fn parse_revdns_answer(data: &[u8]) -> Vec<u8> { 246 let mut cursor = 0; 247 let mut index = 0; 248 let mut output = data.to_vec(); 249 while index < data.len() - 1 { 250 let offset = data[index] as usize; 251 index = cursor + offset + 1; 252 output[index] = b'.'; 253 cursor = index; 254 } 255 //we don't want an extra period at the end 256 output.pop(); 257 output 258 } 259