Implement getaddrinfo (somewhat)

This commit is contained in:
Jeremy Soller
2019-01-21 20:36:56 -07:00
parent f3c858c151
commit c59f268fcd
10 changed files with 134 additions and 13 deletions
+76 -7
View File
@@ -5,6 +5,7 @@ mod dns;
use core::str::FromStr;
use core::{mem, ptr, slice, str};
use alloc::borrow::ToOwned;
use alloc::boxed::Box;
use alloc::str::SplitWhitespace;
use alloc::vec::Vec;
@@ -13,11 +14,11 @@ use c_str::{CStr, CString};
use header::arpa_inet::htons;
use header::errno::*;
use header::fcntl::O_RDONLY;
use header::netinet_in::{in_addr, sockaddr_in};
use header::netinet_in::{in_addr, sockaddr_in, sockaddr_in6};
use header::stdlib::atoi;
use header::strings::strcasecmp;
use header::sys_socket::constants::{AF_UNSPEC, AF_INET};
use header::sys_socket::{sockaddr, socklen_t};
use header::sys_socket::{sa_family_t, sockaddr, socklen_t};
use header::unistd::SEEK_SET;
use platform;
use platform::rlb::{Line, RawLineBuffer};
@@ -670,15 +671,72 @@ pub unsafe extern "C" fn getaddrinfo(
let hints_opt = if hints.is_null() { None } else { Some(&*hints) };
eprintln!(
trace!(
"getaddrinfo({:?}, {:?}, {:?})",
node_opt.map(|c| str::from_utf8_unchecked(c.to_bytes())),
service_opt.map(|c| str::from_utf8_unchecked(c.to_bytes())),
hints_opt
);
platform::errno = ENOSYS;
EAI_SYSTEM
//TODO: Use hints
let mut ai_flags = hints_opt.map_or(0, |hints| hints.ai_flags);
let mut ai_family = hints_opt.map_or(AF_UNSPEC, |hints| hints.ai_family);
let mut ai_socktype = hints_opt.map_or(0, |hints| hints.ai_socktype);
let mut ai_protocol = hints_opt.map_or(0, |hints| hints.ai_protocol);
*res = ptr::null_mut();
//TODO: Check hosts file
if let Some(node) = node_opt {
let lookuphost = match lookup_host(str::from_utf8_unchecked(node.to_bytes())) {
Ok(lookuphost) => lookuphost,
Err(e) => {
platform::errno = e;
return EAI_SYSTEM;
}
};
for in_addr in lookuphost {
ai_family = AF_INET;
ai_socktype = AF_UNSPEC;
ai_protocol = 0;
let ai_addr = Box::into_raw(Box::new(sockaddr_in {
sin_family: AF_INET as sa_family_t,
sin_port: 0,
sin_addr: in_addr,
sin_zero: [0; 8]
})) as *mut sockaddr;
let ai_addrlen = mem::size_of::<sockaddr_in>();
let ai_canonname = if ai_flags & AI_CANONNAME > 0 {
ai_flags &= !AI_CANONNAME;
node.to_owned().into_raw()
} else {
ptr::null_mut()
};
let addrinfo = Box::new(addrinfo {
ai_flags: 0,
ai_family,
ai_socktype,
ai_protocol,
ai_addrlen,
ai_canonname,
ai_addr,
ai_next: ptr::null_mut(),
});
let mut indirect = res;
while !(*indirect).is_null() {
indirect=&mut (**indirect).ai_next;
}
*indirect = Box::into_raw(addrinfo);
}
}
0
}
#[no_mangle]
@@ -721,8 +779,19 @@ pub unsafe extern "C" fn freeaddrinfo(res: *mut addrinfo) {
let mut ai = res;
while !ai.is_null() {
let bai = Box::from_raw(ai);
ai = (*ai).ai_next;
drop(bai);
if !bai.ai_canonname.is_null() {
CString::from_raw(bai.ai_canonname);
}
if !bai.ai_addr.is_null() {
if bai.ai_addrlen == mem::size_of::<sockaddr_in>() {
Box::from_raw(bai.ai_addr as *mut sockaddr_in);
} else if bai.ai_addrlen == mem::size_of::<sockaddr_in6>() {
Box::from_raw(bai.ai_addr as *mut sockaddr_in6);
} else {
eprintln!("freeaddrinfo: unknown ai_addrlen {}", bai.ai_addrlen);
}
}
ai = bai.ai_next;
}
}
+1 -1
View File
@@ -14,7 +14,7 @@ pub type socklen_t = u32;
#[derive(Default)]
pub struct sockaddr {
pub sa_family: sa_family_t,
pub data: [c_char; 14],
pub sa_data: [c_char; 14],
}
#[no_mangle]