use core::{net::Ipv4Addr, ptr::copy_nonoverlapping};
extern crate alloc;
use crate::{
ErrorKind, OrtResult, ort_error,
syscall::{self, AF_INET, SOCK_DGRAM},
utils,
};
const DNS_MAX_PACKET_LEN: usize = 128;
#[rustfmt::skip]
const DNS_PACKET_PREFIX: [u8; 12] = [
0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, ];
#[rustfmt::skip]
const DNS_PACKET_SUFFIX: [u8; 4] = [
0, 1, 0, 1, ];
pub unsafe fn resolve(label: &[u8]) -> OrtResult<Ipv4Addr> {
let sock_fd = syscall::socket(AF_INET, SOCK_DGRAM, 0);
if sock_fd <= 0 {
return Err(ort_error(ErrorKind::DnsResolveFailed, "socket failed"));
}
let addr = syscall::sockaddr_in {
sin_family: AF_INET as u16,
sin_port: 53_u16.to_be(),
sin_addr: syscall::in_addr {
s_addr: u32::from_ne_bytes([127, 0, 0, 53]),
},
sin_zero: [0u8; 8],
};
let addr_len = size_of::<syscall::sockaddr_in>() as syscall::socklen_t;
let res = syscall::connect(
sock_fd,
&addr as *const _ as *const syscall::sockaddr,
addr_len,
);
if res < 0 {
return Err(ort_error(ErrorKind::DnsResolveFailed, "connect failed"));
}
let mut query = [0u8; DNS_MAX_PACKET_LEN];
let mut query_ptr = query.as_mut_ptr();
unsafe {
for dat in [&DNS_PACKET_PREFIX, label, &DNS_PACKET_SUFFIX] {
copy_nonoverlapping(dat.as_ptr(), query_ptr, dat.len());
query_ptr = query_ptr.add(dat.len());
}
}
let bytes_written = syscall::write(sock_fd, query.as_ptr().cast(), query.len());
if bytes_written != query.len() as i32 {
return Err(ort_error(ErrorKind::DnsResolveFailed, "write failed"));
}
let mut buf = [0u8; DNS_MAX_PACKET_LEN];
let bytes_read = syscall::read(sock_fd, buf.as_mut_ptr().cast(), buf.len());
if bytes_read <= 0 {
return Err(ort_error(ErrorKind::DnsResolveFailed, "read failed"));
}
let err_code = buf[3] & 0x0F;
if err_code != 0 {
let err_code_str = utils::num_to_string(err_code);
utils::print_string(c"DNS server err code: ", &err_code_str);
return Err(ort_error(ErrorKind::DnsResolveFailed, "server err code"));
}
let end = bytes_read as usize;
let ip = u32::from_be_bytes([buf[end - 4], buf[end - 3], buf[end - 2], buf[end - 1]]);
Ok(Ipv4Addr::from_bits(ip))
}