|
@@ -7,8 +7,7 @@ use core::{mem, ptr, slice, str};
|
|
|
|
|
|
use alloc::boxed::Box;
|
|
|
use alloc::str::SplitWhitespace;
|
|
|
-use alloc::string::{String, ToString};
|
|
|
-use alloc::vec::{IntoIter, Vec};
|
|
|
+use alloc::vec::Vec;
|
|
|
|
|
|
use c_str::{CStr, CString};
|
|
|
|
|
@@ -17,19 +16,14 @@ use platform::rlb::{Line, RawLineBuffer};
|
|
|
use platform::types::*;
|
|
|
use platform::{Pal, Sys};
|
|
|
|
|
|
-use self::dns::{Dns, DnsQuery};
|
|
|
-
|
|
|
use header::arpa_inet::{htons, inet_aton};
|
|
|
use header::errno::*;
|
|
|
use header::fcntl::O_RDONLY;
|
|
|
-use header::netinet_in::{in_addr, sockaddr_in, IPPROTO_UDP};
|
|
|
+use header::netinet_in::{in_addr, sockaddr_in};
|
|
|
use header::stdlib::atoi;
|
|
|
use header::strings::strcasecmp;
|
|
|
-use header::sys_socket;
|
|
|
-use header::sys_socket::constants::{AF_INET, SOCK_DGRAM};
|
|
|
+use header::sys_socket::constants::AF_INET;
|
|
|
use header::sys_socket::{sockaddr, socklen_t};
|
|
|
-use header::time;
|
|
|
-use header::time::timespec;
|
|
|
use header::unistd::SEEK_SET;
|
|
|
|
|
|
#[cfg(target_os = "linux")]
|
|
@@ -40,17 +34,14 @@ pub mod sys;
|
|
|
#[path = "redox.rs"]
|
|
|
pub mod sys;
|
|
|
|
|
|
-const MAXADDRS: usize = 35;
|
|
|
-const MAXALIASES: usize = 35;
|
|
|
+//TODO: use self::db::Db;
|
|
|
+pub mod db;
|
|
|
|
|
|
-struct LookupHost(IntoIter<in_addr>);
|
|
|
+use self::lookup::{lookup_addr, lookup_host};
|
|
|
+pub mod lookup;
|
|
|
|
|
|
-impl Iterator for LookupHost {
|
|
|
- type Item = in_addr;
|
|
|
- fn next(&mut self) -> Option<Self::Item> {
|
|
|
- self.0.next()
|
|
|
- }
|
|
|
-}
|
|
|
+const MAXADDRS: usize = 35;
|
|
|
+const MAXALIASES: usize = 35;
|
|
|
|
|
|
#[repr(C)]
|
|
|
pub struct hostent {
|
|
@@ -69,6 +60,13 @@ pub struct netent {
|
|
|
n_net: c_ulong, /* network # */
|
|
|
}
|
|
|
|
|
|
+#[repr(C)]
|
|
|
+pub struct protoent {
|
|
|
+ p_name: *mut c_char, /* official protocol name */
|
|
|
+ p_aliases: *mut *mut c_char, /* alias list */
|
|
|
+ p_proto: c_int, /* protocol # */
|
|
|
+}
|
|
|
+
|
|
|
#[repr(C)]
|
|
|
pub struct servent {
|
|
|
s_name: *mut c_char, /* official service name */
|
|
@@ -77,13 +75,6 @@ pub struct servent {
|
|
|
s_proto: *mut c_char, /* protocol to use */
|
|
|
}
|
|
|
|
|
|
-#[repr(C)]
|
|
|
-pub struct protoent {
|
|
|
- p_name: *mut c_char, /* official protocol name */
|
|
|
- p_aliases: *mut *mut c_char, /* alias list */
|
|
|
- p_proto: c_int, /* protocol # */
|
|
|
-}
|
|
|
-
|
|
|
#[repr(C)]
|
|
|
pub struct addrinfo {
|
|
|
ai_flags: c_int, /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
|
|
@@ -196,230 +187,6 @@ fn bytes_to_box_str(bytes: &[u8]) -> Box<str> {
|
|
|
Box::from(core::str::from_utf8(bytes).unwrap_or(""))
|
|
|
}
|
|
|
|
|
|
-fn lookup_host(host: &str) -> Result<LookupHost, c_int> {
|
|
|
- let dns_string = sys::get_dns_server();
|
|
|
-
|
|
|
- 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 = unsafe { mem::transmute::<[u8; 4], u32>(dns_arr) };
|
|
|
-
|
|
|
- let mut timespec = timespec::default();
|
|
|
- Sys::clock_gettime(time::constants::CLOCK_REALTIME, &mut timespec);
|
|
|
- let tid = (timespec.tv_nsec >> 16) as u16;
|
|
|
-
|
|
|
- let packet = Dns {
|
|
|
- transaction_id: tid,
|
|
|
- flags: 0x0100,
|
|
|
- queries: vec![DnsQuery {
|
|
|
- name: host.to_string(),
|
|
|
- q_type: 0x0001,
|
|
|
- q_class: 0x0001,
|
|
|
- }],
|
|
|
- answers: vec![],
|
|
|
- };
|
|
|
-
|
|
|
- let packet_data = packet.compile();
|
|
|
- let packet_data_len = packet_data.len();
|
|
|
-
|
|
|
- let packet_data_box = packet_data.into_boxed_slice();
|
|
|
- let packet_data_ptr = Box::into_raw(packet_data_box) as *mut _ as *mut c_void;
|
|
|
-
|
|
|
- let dest = sockaddr_in {
|
|
|
- sin_family: AF_INET as u16,
|
|
|
- sin_port: htons(53),
|
|
|
- sin_addr: in_addr { s_addr: dns_addr },
|
|
|
- ..Default::default()
|
|
|
- };
|
|
|
- let dest_ptr = &dest as *const _ as *const sockaddr;
|
|
|
-
|
|
|
- let sock = unsafe {
|
|
|
- let sock = sys_socket::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP as i32);
|
|
|
- if sys_socket::connect(sock, dest_ptr, mem::size_of_val(&dest) as socklen_t) < 0 {
|
|
|
- return Err(EIO);
|
|
|
- }
|
|
|
- if sys_socket::send(sock, packet_data_ptr, packet_data_len, 0) < 0 {
|
|
|
- Box::from_raw(packet_data_ptr);
|
|
|
- return Err(EIO);
|
|
|
- }
|
|
|
- sock
|
|
|
- };
|
|
|
-
|
|
|
- unsafe {
|
|
|
- Box::from_raw(packet_data_ptr);
|
|
|
- }
|
|
|
-
|
|
|
- let i = 0 as socklen_t;
|
|
|
- let mut buf = [0u8; 65536];
|
|
|
- let buf_ptr = buf.as_mut_ptr() as *mut c_void;
|
|
|
-
|
|
|
- let count = unsafe { sys_socket::recv(sock, buf_ptr, 65536, 0) };
|
|
|
- if count < 0 {
|
|
|
- return Err(EIO);
|
|
|
- }
|
|
|
-
|
|
|
- match Dns::parse(&buf[..count as usize]) {
|
|
|
- Ok(response) => {
|
|
|
- let mut addrs = vec![];
|
|
|
- for answer in response.answers.iter() {
|
|
|
- if answer.a_type == 0x0001 && answer.a_class == 0x0001 && answer.data.len() == 4
|
|
|
- {
|
|
|
- let addr = in_addr {
|
|
|
- s_addr: unsafe {
|
|
|
- mem::transmute::<[u8; 4], u32>([
|
|
|
- answer.data[0],
|
|
|
- answer.data[1],
|
|
|
- answer.data[2],
|
|
|
- answer.data[3],
|
|
|
- ])
|
|
|
- },
|
|
|
- };
|
|
|
- addrs.push(addr);
|
|
|
- }
|
|
|
- }
|
|
|
- Ok(LookupHost(addrs.into_iter()))
|
|
|
- }
|
|
|
- Err(_err) => Err(EINVAL),
|
|
|
- }
|
|
|
- } else {
|
|
|
- Err(EINVAL)
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-fn lookup_addr(addr: in_addr) -> Result<Vec<Vec<u8>>, c_int> {
|
|
|
- let dns_string = sys::get_dns_server();
|
|
|
-
|
|
|
- let dns_vec: Vec<u8> = dns_string
|
|
|
- .trim()
|
|
|
- .split('.')
|
|
|
- .map(|octet| octet.parse::<u8>().unwrap_or(0))
|
|
|
- .collect();
|
|
|
-
|
|
|
- let mut dns_arr = [0u8; 4];
|
|
|
-
|
|
|
- for (i, octet) in dns_vec.iter().enumerate() {
|
|
|
- dns_arr[i] = *octet;
|
|
|
- }
|
|
|
-
|
|
|
- let mut addr_vec: Vec<u8> = unsafe { mem::transmute::<u32, [u8; 4]>(addr.s_addr).to_vec() };
|
|
|
- addr_vec.reverse();
|
|
|
- let mut name: Vec<u8> = vec![];
|
|
|
- for octet in addr_vec {
|
|
|
- for ch in format!("{}", octet).as_bytes() {
|
|
|
- name.push(*ch);
|
|
|
- }
|
|
|
- name.push(b"."[0]);
|
|
|
- }
|
|
|
- name.pop();
|
|
|
- for ch in b".IN-ADDR.ARPA" {
|
|
|
- name.push(*ch);
|
|
|
- }
|
|
|
-
|
|
|
- if dns_vec.len() == 4 {
|
|
|
- let mut timespec = timespec::default();
|
|
|
- Sys::clock_gettime(time::constants::CLOCK_REALTIME, &mut timespec);
|
|
|
- let tid = (timespec.tv_nsec >> 16) as u16;
|
|
|
-
|
|
|
- let packet = Dns {
|
|
|
- transaction_id: tid,
|
|
|
- flags: 0x0100,
|
|
|
- queries: vec![DnsQuery {
|
|
|
- name: String::from_utf8(name).unwrap(),
|
|
|
- q_type: 0x000C,
|
|
|
- q_class: 0x0001,
|
|
|
- }],
|
|
|
- answers: vec![],
|
|
|
- };
|
|
|
-
|
|
|
- let packet_data = packet.compile();
|
|
|
- let packet_data_len = packet_data.len();
|
|
|
- let packet_data_box = packet_data.into_boxed_slice();
|
|
|
- let packet_data_ptr = Box::into_raw(packet_data_box) as *mut _ as *mut c_void;
|
|
|
-
|
|
|
- let dest = sockaddr_in {
|
|
|
- sin_family: AF_INET as u16,
|
|
|
- sin_port: htons(53),
|
|
|
- sin_addr: in_addr {
|
|
|
- s_addr: unsafe { mem::transmute::<[u8; 4], u32>(dns_arr) },
|
|
|
- },
|
|
|
- ..Default::default()
|
|
|
- };
|
|
|
-
|
|
|
- let dest_ptr = &dest as *const _ as *const sockaddr;
|
|
|
-
|
|
|
- let sock = unsafe {
|
|
|
- let sock = sys_socket::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP as i32);
|
|
|
- if sys_socket::connect(sock, dest_ptr, mem::size_of_val(&dest) as socklen_t) < 0 {
|
|
|
- return Err(EIO);
|
|
|
- }
|
|
|
- sock
|
|
|
- };
|
|
|
-
|
|
|
- unsafe {
|
|
|
- if sys_socket::send(sock, packet_data_ptr, packet_data_len, 0) < 0 {
|
|
|
- return Err(EIO);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- unsafe {
|
|
|
- Box::from_raw(packet_data_ptr);
|
|
|
- }
|
|
|
-
|
|
|
- let i = mem::size_of::<sockaddr_in>() as socklen_t;
|
|
|
- let mut buf = [0u8; 65536];
|
|
|
- let buf_ptr = buf.as_mut_ptr() as *mut c_void;
|
|
|
-
|
|
|
- let count = unsafe { sys_socket::recv(sock, buf_ptr, 65536, 0) };
|
|
|
- if count < 0 {
|
|
|
- return Err(EIO);
|
|
|
- }
|
|
|
-
|
|
|
- match Dns::parse(&buf[..count as usize]) {
|
|
|
- Ok(response) => {
|
|
|
- let mut names = vec![];
|
|
|
- for answer in response.answers.iter() {
|
|
|
- if answer.a_type == 0x000C && answer.a_class == 0x0001 {
|
|
|
- // answer.data is encoded kinda weird.
|
|
|
- // Basically length-prefixed strings for each
|
|
|
- // subsection of the domain.
|
|
|
- // We need to parse this to insert periods where
|
|
|
- // they belong (ie at the end of each string)
|
|
|
- let data = parse_revdns_answer(&answer.data);
|
|
|
- names.push(data);
|
|
|
- }
|
|
|
- }
|
|
|
- Ok(names)
|
|
|
- }
|
|
|
- Err(_err) => Err(EINVAL),
|
|
|
- }
|
|
|
- } else {
|
|
|
- Err(EINVAL)
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-fn parse_revdns_answer(data: &[u8]) -> Vec<u8> {
|
|
|
- let mut cursor = 0;
|
|
|
- let mut index = 0;
|
|
|
- let mut output = data.to_vec();
|
|
|
- while index < data.len() - 1 {
|
|
|
- let offset = data[index] as usize;
|
|
|
- index = cursor + offset + 1;
|
|
|
- output[index] = b'.';
|
|
|
- cursor = index;
|
|
|
- }
|
|
|
- //we don't want an extra period at the end
|
|
|
- output.pop();
|
|
|
- output
|
|
|
-}
|
|
|
-
|
|
|
#[no_mangle]
|
|
|
pub unsafe extern "C" fn endhostent() {
|
|
|
Sys::close(HOSTDB);
|
|
@@ -800,10 +567,7 @@ pub unsafe extern "C" fn getprotoent() -> *mut protoent {
|
|
|
}
|
|
|
|
|
|
#[no_mangle]
|
|
|
-pub unsafe extern "C" fn getservbyname(
|
|
|
- name: *const c_char,
|
|
|
- proto: *const c_char,
|
|
|
-) -> *mut servent {
|
|
|
+pub unsafe extern "C" fn getservbyname(name: *const c_char, proto: *const c_char) -> *mut servent {
|
|
|
setservent(SERV_STAYOPEN);
|
|
|
let mut p: *mut servent;
|
|
|
if proto.is_null() {
|
|
@@ -1012,11 +776,7 @@ pub unsafe extern "C" fn getaddrinfo(
|
|
|
Some(CStr::from_ptr(service))
|
|
|
};
|
|
|
|
|
|
- let hints_opt = if hints.is_null() {
|
|
|
- None
|
|
|
- } else {
|
|
|
- Some(&*hints)
|
|
|
- };
|
|
|
+ let hints_opt = if hints.is_null() { None } else { Some(&*hints) };
|
|
|
|
|
|
eprintln!(
|
|
|
"getaddrinfo({:?}, {:?})",
|
|
@@ -1038,6 +798,7 @@ 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>() {
|
|
|
return EAI_FAMILY;
|
|
|
}
|
|
@@ -1088,5 +849,6 @@ pub extern "C" fn gai_strerror(errcode: c_int) -> *const c_char {
|
|
|
EAI_SYSTEM => c_str!("System error"),
|
|
|
EAI_OVERFLOW => c_str!("Overflow"),
|
|
|
_ => c_str!("Unknown error"),
|
|
|
- }.as_ptr()
|
|
|
+ }
|
|
|
+ .as_ptr()
|
|
|
}
|