Merge branch 'netdb-openssh' into 'master'
Implement getnameinfo and getaddrinfo loopback See merge request redox-os/relibc!693
This commit is contained in:
+39
-35
@@ -33,21 +33,19 @@ impl Iterator for LookupHost {
|
||||
}
|
||||
|
||||
pub fn lookup_host(host: &str) -> Result<LookupHost, c_int> {
|
||||
if let Some(host_direct_addr) = parse_ipv4_string(host) {
|
||||
// already an ip address
|
||||
return Ok(LookupHost(
|
||||
vec![in_addr {
|
||||
s_addr: host_direct_addr,
|
||||
}]
|
||||
.into_iter(),
|
||||
));
|
||||
}
|
||||
|
||||
let dns_string = get_dns_server().map_err(|e| e.0)?;
|
||||
|
||||
let dns_vec: Vec<u8> = dns_string
|
||||
.trim()
|
||||
.split('.')
|
||||
.map(|octet| octet.parse::<u8>().unwrap_or(0))
|
||||
.collect();
|
||||
|
||||
if dns_vec.len() == 4 {
|
||||
let mut dns_arr = [0u8; 4];
|
||||
for (i, octet) in dns_vec.iter().enumerate() {
|
||||
dns_arr[i] = *octet;
|
||||
}
|
||||
let dns_addr = u32::from_ne_bytes(dns_arr);
|
||||
|
||||
if let Some(dns_addr) = parse_ipv4_string(&dns_string) {
|
||||
let mut timespec = timespec::default();
|
||||
unsafe {
|
||||
Sys::clock_gettime(time::constants::CLOCK_REALTIME, &mut timespec);
|
||||
@@ -140,26 +138,14 @@ pub fn lookup_host(host: &str) -> Result<LookupHost, c_int> {
|
||||
pub fn lookup_addr(addr: in_addr) -> Result<Vec<Vec<u8>>, c_int> {
|
||||
let dns_string = get_dns_server().map_err(|e| e.0)?;
|
||||
|
||||
let dns_vec: Vec<u8> = dns_string
|
||||
.trim()
|
||||
.split('.')
|
||||
.map(|octet| octet.parse::<u8>().unwrap_or(0))
|
||||
.collect();
|
||||
if let Some(dns_addr) = parse_ipv4_string(&dns_string) {
|
||||
let addr: [u8; 4] = addr.s_addr.to_ne_bytes();
|
||||
// Address intentionally backwards for reverse lookup
|
||||
let name = format!(
|
||||
"{}.{}.{}.{}.in-addr.arpa",
|
||||
addr[3], addr[2], addr[1], addr[0]
|
||||
);
|
||||
|
||||
let mut dns_arr = [0u8; 4];
|
||||
|
||||
for (i, octet) in dns_vec.iter().enumerate() {
|
||||
dns_arr[i] = *octet;
|
||||
}
|
||||
|
||||
let addr: [u8; 4] = addr.s_addr.to_ne_bytes();
|
||||
// Address intentionally backwards for reverse lookup
|
||||
let name = format!(
|
||||
"{}.{}.{}.{}.in-addr.arpa",
|
||||
addr[3], addr[2], addr[1], addr[0]
|
||||
);
|
||||
|
||||
if dns_vec.len() == 4 {
|
||||
let mut timespec = timespec::default();
|
||||
unsafe { Sys::clock_gettime(time::constants::CLOCK_REALTIME, &mut timespec) };
|
||||
let tid = (timespec.tv_nsec >> 16) as u16;
|
||||
@@ -183,9 +169,7 @@ pub fn lookup_addr(addr: in_addr) -> Result<Vec<Vec<u8>>, c_int> {
|
||||
let dest = sockaddr_in {
|
||||
sin_family: AF_INET as u16,
|
||||
sin_port: htons(53),
|
||||
sin_addr: in_addr {
|
||||
s_addr: u32::from_ne_bytes(dns_arr),
|
||||
},
|
||||
sin_addr: in_addr { s_addr: dns_addr },
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
@@ -278,6 +262,26 @@ fn parse_revdns_answer(data: &[u8]) -> Vec<u8> {
|
||||
output
|
||||
}
|
||||
|
||||
pub fn parse_ipv4_string(ip_string: &str) -> Option<u32> {
|
||||
let dns_vec: Vec<u8> = ip_string
|
||||
.trim()
|
||||
.split('.')
|
||||
.map(|octet| octet.parse::<u8>().unwrap_or(0))
|
||||
.collect();
|
||||
|
||||
if dns_vec.len() != 4 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut dns_arr = [0u8; 4];
|
||||
|
||||
for (i, octet) in dns_vec.iter().enumerate() {
|
||||
dns_arr[i] = *octet;
|
||||
}
|
||||
|
||||
Some(u32::from_ne_bytes(dns_arr))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use alloc::str;
|
||||
|
||||
+74
-36
@@ -5,11 +5,13 @@ mod dns;
|
||||
use core::{
|
||||
cell::Cell,
|
||||
fmt::Write,
|
||||
mem, ptr, slice,
|
||||
mem,
|
||||
net::Ipv4Addr,
|
||||
ptr, slice,
|
||||
str::{self, FromStr},
|
||||
};
|
||||
|
||||
use alloc::{borrow::ToOwned, boxed::Box, str::SplitWhitespace, vec::Vec};
|
||||
use alloc::{borrow::ToOwned, boxed::Box, str::SplitWhitespace, string::ToString, vec::Vec};
|
||||
|
||||
use crate::{
|
||||
c_str::{CStr, CString},
|
||||
@@ -323,23 +325,7 @@ pub unsafe extern "C" fn gethostbyname(name: *const c_char) -> *mut hostent {
|
||||
// Addresses and hostnames are both valid, so we'll check addresses first
|
||||
// The standard doesn't define what to do when called with addresses
|
||||
// Some implementations just skip resolution and copy the address to h_name
|
||||
let mut octets = name_str.split('.');
|
||||
let mut s_addr = [0u8; 4];
|
||||
let mut is_addr = true;
|
||||
for item in &mut s_addr {
|
||||
if let Some(n) = octets.next().and_then(|x| u8::from_str(x).ok()) {
|
||||
*item = n;
|
||||
} else {
|
||||
is_addr = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if octets.next() != None {
|
||||
is_addr = false;
|
||||
}
|
||||
|
||||
if is_addr {
|
||||
let s_addr = u32::from_ne_bytes(s_addr);
|
||||
if let Some(s_addr) = parse_ipv4_string(name_str) {
|
||||
let addr = in_addr { s_addr };
|
||||
return gethostbyaddr(&addr as *const _ as *const c_void, 4, AF_INET);
|
||||
}
|
||||
@@ -878,29 +864,81 @@ pub unsafe extern "C" fn getnameinfo(
|
||||
servlen: socklen_t,
|
||||
flags: c_int,
|
||||
) -> c_int {
|
||||
//TODO: getnameinfo
|
||||
if addrlen as usize != mem::size_of::<sockaddr_in>() {
|
||||
if addr.is_null() || addrlen as usize != mem::size_of::<sockaddr_in>() {
|
||||
return EAI_FAMILY;
|
||||
}
|
||||
|
||||
let addr = &*(addr as *const sockaddr_in);
|
||||
let sa = &*(addr as *const sockaddr_in);
|
||||
|
||||
let host_opt = if host.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(slice::from_raw_parts_mut(host, hostlen as usize))
|
||||
};
|
||||
if !serv.is_null() && servlen > 0 {
|
||||
if flags & NI_NUMERICSERV != 0 {
|
||||
let port_str = sa.sin_port.to_be().to_string();
|
||||
let port_bytes = port_str.as_bytes();
|
||||
if (servlen as usize) <= port_bytes.len() {
|
||||
return EAI_MEMORY; // Buffer too small
|
||||
}
|
||||
ptr::copy_nonoverlapping(port_bytes.as_ptr() as *const c_char, serv, port_bytes.len());
|
||||
*serv.add(port_bytes.len()) = 0;
|
||||
} else {
|
||||
// TODO: Implement service name lookup (e.g., from /etc/services)
|
||||
*serv = 0;
|
||||
}
|
||||
}
|
||||
|
||||
let serv_opt = if serv.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(slice::from_raw_parts_mut(serv, servlen as usize))
|
||||
};
|
||||
if !host.is_null() && hostlen > 0 {
|
||||
if flags & NI_NUMERICHOST != 0 {
|
||||
let ip_addr = Ipv4Addr::from(sa.sin_addr.s_addr.to_be());
|
||||
let ip_str = ip_addr.to_string();
|
||||
let ip_bytes = ip_str.as_bytes();
|
||||
if (hostlen as usize) <= ip_bytes.len() {
|
||||
return EAI_MEMORY; // Buffer too small
|
||||
}
|
||||
ptr::copy_nonoverlapping(ip_bytes.as_ptr() as *const c_char, host, ip_bytes.len());
|
||||
*host.add(ip_bytes.len()) = 0;
|
||||
} else {
|
||||
match lookup_addr(sa.sin_addr.clone()).map(|host_names| host_names.into_iter().next()) {
|
||||
Ok(Some(hostname)) => {
|
||||
if (hostlen as usize) <= hostname.len() {
|
||||
return EAI_MEMORY; // Buffer too small
|
||||
}
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(
|
||||
hostname.as_ptr() as *const c_char,
|
||||
host,
|
||||
hostname.len(),
|
||||
);
|
||||
*host.add(hostname.len()) = 0;
|
||||
}
|
||||
}
|
||||
Ok(None) => {
|
||||
if flags & NI_NAMEREQD != 0 {
|
||||
return EAI_NONAME;
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
if flags & NI_NAMEREQD != 0 {
|
||||
return EAI_NONAME;
|
||||
}
|
||||
let ip_addr = Ipv4Addr::from(sa.sin_addr.s_addr.to_be());
|
||||
let ip_str = ip_addr.to_string();
|
||||
let ip_bytes = ip_str.as_bytes();
|
||||
if (hostlen as usize) <= ip_bytes.len() {
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(
|
||||
ip_bytes.as_ptr() as *const c_char,
|
||||
host,
|
||||
ip_bytes.len(),
|
||||
);
|
||||
*host.add(ip_bytes.len()) = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eprintln!("getnameinfo({:p}, {}, {:#x})", addr, addrlen, flags);
|
||||
|
||||
platform::ERRNO.set(ENOSYS);
|
||||
EAI_SYSTEM
|
||||
0
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
||||
Reference in New Issue
Block a user