use crate::io; use crate::net::{Ipv4Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; use crate::os::xous::ffi::lend_mut; use crate::os::xous::services::{DnsLendMut, dns_server}; #[repr(C, align(4096))] struct LookupHostQuery([u8; 4096]); pub struct LookupHost { data: LookupHostQuery, port: u16, offset: usize, count: usize, } impl Iterator for LookupHost { type Item = SocketAddr; fn next(&mut self) -> Option { if self.offset >= self.data.0.len() { return None; } match self.data.0.get(self.offset) { Some(&4) => { self.offset += 1; if self.offset + 4 > self.data.0.len() { return None; } let result = Some(SocketAddr::V4(SocketAddrV4::new( Ipv4Addr::new( self.data.0[self.offset], self.data.0[self.offset + 1], self.data.0[self.offset + 2], self.data.0[self.offset + 3], ), self.port, ))); self.offset += 4; result } Some(&6) => { self.offset += 1; if self.offset + 16 > self.data.0.len() { return None; } let mut new_addr = [0u8; 16]; for (src, octet) in self.data.0[(self.offset + 1)..(self.offset + 16 + 1)] .iter() .zip(new_addr.iter_mut()) { *octet = *src; } let result = Some(SocketAddr::V6(SocketAddrV6::new(new_addr.into(), self.port, 0, 0))); self.offset += 16; result } _ => None, } } } pub fn lookup_host(query: &str, port: u16) -> io::Result { let mut result = LookupHost { data: LookupHostQuery([0u8; 4096]), offset: 0, count: 0, port }; // Copy the query into the message that gets sent to the DNS server for (query_byte, result_byte) in query.as_bytes().iter().zip(result.data.0.iter_mut()) { *result_byte = *query_byte; } lend_mut( dns_server(), DnsLendMut::RawLookup.into(), &mut result.data.0, 0, query.as_bytes().len(), ) .unwrap(); if result.data.0[0] != 0 { return Err(io::const_error!(io::ErrorKind::InvalidInput, "DNS failure")); } assert_eq!(result.offset, 0); result.count = result.data.0[1] as usize; // Advance the offset to the first record result.offset = 2; Ok(result) }