123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992 |
- //! netdb implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/netdb.h.html
- mod dns;
- use core::str::FromStr;
- use core::{mem, ptr, str};
- use alloc::boxed::Box;
- use alloc::str::SplitWhitespace;
- use alloc::string::{String, ToString};
- use alloc::vec::{IntoIter, Vec};
- use c_str::{CStr, CString};
- use platform;
- 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::stdlib::atoi;
- use header::strings::strcasecmp;
- use header::sys_socket;
- use header::sys_socket::constants::{AF_INET, SOCK_DGRAM};
- use header::sys_socket::{sockaddr, socklen_t};
- use header::time;
- use header::time::timespec;
- use header::unistd::SEEK_SET;
- #[cfg(target_os = "linux")]
- #[path = "linux.rs"]
- pub mod sys;
- #[cfg(target_os = "redox")]
- #[path = "redox.rs"]
- pub mod sys;
- const MAXADDRS: usize = 35;
- const MAXALIASES: usize = 35;
- struct LookupHost(IntoIter<in_addr>);
- impl Iterator for LookupHost {
- type Item = in_addr;
- fn next(&mut self) -> Option<Self::Item> {
- self.0.next()
- }
- }
- #[repr(C)]
- pub struct hostent {
- h_name: *mut c_char,
- h_aliases: *mut *mut c_char,
- h_addrtype: c_int,
- h_length: c_int,
- h_addr_list: *mut *mut c_char,
- }
- #[repr(C)]
- pub struct netent {
- n_name: *mut c_char, /* official name of net */
- n_aliases: *mut *mut c_char, /* alias list */
- n_addrtype: c_int, /* net address type */
- n_net: c_ulong, /* network # */
- }
- #[repr(C)]
- pub struct servent {
- s_name: *mut c_char, /* official service name */
- s_aliases: *mut *mut c_char, /* alias list */
- s_port: c_int, /* port # */
- 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 */
- ai_family: c_int, /* PF_xxx */
- ai_socktype: c_int, /* SOCK_xxx */
- ai_protocol: c_int, /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
- ai_addrlen: size_t, /* length of ai_addr */
- ai_canonname: *mut c_char, /* canonical name for hostname */
- ai_addr: *mut sockaddr, /* binary address */
- ai_next: *mut addrinfo, /* next structure in linked list */
- }
- static mut NETDB: c_int = 0;
- static mut NET_ENTRY: netent = netent {
- n_name: ptr::null_mut(),
- n_aliases: ptr::null_mut(),
- n_addrtype: 0,
- n_net: 0,
- };
- static mut NET_NAME: Option<Vec<u8>> = None;
- static mut NET_ALIASES: [*const c_char; MAXALIASES] = [ptr::null(); MAXALIASES];
- static mut NET_NUM: Option<u64> = None;
- static mut N_POS: usize = 0;
- static mut NET_STAYOPEN: c_int = 0;
- static mut HOSTDB: c_int = 0;
- static mut HOST_ENTRY: hostent = hostent {
- h_name: ptr::null_mut(),
- h_aliases: ptr::null_mut(),
- h_addrtype: 0,
- h_length: 0,
- h_addr_list: ptr::null_mut(),
- };
- static mut HOST_NAME: Option<Vec<u8>> = None;
- static mut HOST_ALIASES: Option<Vec<Vec<u8>>> = None;
- static mut _HOST_ALIASES: Option<Vec<*mut i8>> = None;
- static mut HOST_ADDR: Option<in_addr> = None;
- static mut HOST_ADDR_LIST: [*mut c_char; 2] = [ptr::null_mut(); 2];
- static mut _HOST_ADDR_LIST: [u8; 4] = [0u8; 4];
- static mut H_POS: usize = 0;
- static mut HOST_STAYOPEN: c_int = 0;
- #[allow(non_upper_case_globals)]
- #[no_mangle]
- pub static mut h_errno: c_int = 0;
- pub const HOST_NOT_FOUND: c_int = 1;
- pub const NO_DATA: c_int = 2;
- pub const NO_RECOVERY: c_int = 3;
- pub const TRY_AGAIN: c_int = 4;
- static mut PROTODB: c_int = 0;
- static mut PROTO_ENTRY: protoent = protoent {
- p_name: ptr::null_mut(),
- p_aliases: ptr::null_mut(),
- p_proto: 0 as c_int,
- };
- static mut PROTO_NAME: Option<Vec<u8>> = None;
- static mut PROTO_ALIASES: Option<Vec<Vec<u8>>> = None;
- static mut PROTO_NUM: Option<c_int> = None;
- static mut P_POS: usize = 0;
- static mut PROTO_STAYOPEN: c_int = 0;
- static mut SERVDB: c_int = 0;
- static mut SERV_ENTRY: servent = servent {
- s_name: ptr::null_mut(),
- s_aliases: ptr::null_mut(),
- s_port: 0 as c_int,
- s_proto: ptr::null_mut(),
- };
- static mut SERV_NAME: Option<Vec<u8>> = None;
- static mut SERV_ALIASES: Option<Vec<Vec<u8>>> = None;
- static mut SERV_PORT: Option<c_int> = None;
- static mut SERV_PROTO: Option<Vec<u8>> = None;
- static mut S_POS: usize = 0;
- static mut SERV_STAYOPEN: c_int = 0;
- const NULL_ALIASES: [*mut c_char; 2] = [ptr::null_mut(); 2];
- 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);
- HOSTDB = 0;
- }
- #[no_mangle]
- pub unsafe extern "C" fn endnetent() {
- Sys::close(NETDB);
- NETDB = 0;
- }
- #[no_mangle]
- pub unsafe extern "C" fn endprotoent() {
- Sys::close(PROTODB);
- PROTODB = 0;
- }
- #[no_mangle]
- pub unsafe extern "C" fn endservent() {
- Sys::close(SERVDB);
- SERVDB = 0;
- }
- #[no_mangle]
- pub unsafe extern "C" fn gethostbyaddr(
- v: *const c_void,
- length: socklen_t,
- format: c_int,
- ) -> *const hostent {
- let addr: in_addr = *(v as *mut in_addr);
- // check the hosts file first
- let mut p: *const hostent;
- sethostent(HOST_STAYOPEN);
- while {
- p = gethostent();
- !p.is_null()
- } {
- let mut cp = (*p).h_addr_list;
- loop {
- if cp.is_null() {
- break;
- }
- if (*cp).is_null() {
- break;
- }
- let mut cp_slice: [i8; 4] = [0i8; 4];
- (*cp).copy_to(cp_slice.as_mut_ptr(), 4);
- let cp_s_addr = mem::transmute::<[i8; 4], u32>(cp_slice);
- if cp_s_addr == addr.s_addr {
- sethostent(HOST_STAYOPEN);
- return p;
- }
- cp = cp.offset(1);
- }
- }
- //TODO actually get aliases
- let mut _host_aliases: Vec<Vec<u8>> = Vec::new();
- _host_aliases.push(vec![b'\0']);
- let mut host_aliases: Vec<*mut i8> = Vec::new();
- host_aliases.push(ptr::null_mut());
- HOST_ALIASES = Some(_host_aliases);
- match lookup_addr(addr) {
- Ok(s) => {
- _HOST_ADDR_LIST = mem::transmute::<u32, [u8; 4]>(addr.s_addr);
- HOST_ADDR_LIST = [_HOST_ADDR_LIST.as_mut_ptr() as *mut c_char, ptr::null_mut()];
- let mut host_name = s[0].to_vec();
- HOST_NAME = Some(host_name);
- HOST_ENTRY = hostent {
- h_name: HOST_NAME.as_mut().unwrap().as_mut_ptr() as *mut c_char,
- h_aliases: host_aliases.as_mut_slice().as_mut_ptr() as *mut *mut i8,
- h_addrtype: format,
- h_length: length as i32,
- h_addr_list: HOST_ADDR_LIST.as_mut_ptr(),
- };
- &HOST_ENTRY
- }
- Err(e) => {
- platform::errno = e;
- ptr::null()
- }
- }
- }
- #[no_mangle]
- pub unsafe extern "C" fn gethostbyname(name: *const c_char) -> *const hostent {
- // check if some idiot gave us an address instead of a name
- let name_cstr = CStr::from_ptr(name);
- let mut octets = str::from_utf8_unchecked(name_cstr.to_bytes()).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;
- }
- }
- if octets.next() != None {
- is_addr = false;
- }
- if is_addr {
- let addr = in_addr {
- s_addr: mem::transmute::<[u8; 4], u32>(s_addr),
- };
- return gethostbyaddr(&addr as *const _ as *const c_void, 4, AF_INET);
- }
- // check the hosts file first
- let mut p: *const hostent;
- sethostent(HOST_STAYOPEN);
- while {
- p = gethostent();
- !p.is_null()
- } {
- if strcasecmp((*p).h_name, name) == 0 {
- sethostent(HOST_STAYOPEN);
- return p;
- }
- let mut cp = (*p).h_aliases;
- loop {
- if cp.is_null() {
- break;
- }
- if (*cp).is_null() {
- break;
- }
- if strcasecmp(*cp, name) == 0 {
- sethostent(HOST_STAYOPEN);
- return p;
- }
- cp = cp.offset(1);
- }
- }
- let name_cstr = CStr::from_ptr(name);
- let mut host = match lookup_host(str::from_utf8_unchecked(name_cstr.to_bytes())) {
- Ok(lookuphost) => lookuphost,
- Err(e) => {
- platform::errno = e;
- return ptr::null();
- }
- };
- let host_addr = match host.next() {
- Some(result) => result,
- None => {
- platform::errno = ENOENT;
- return ptr::null();
- }
- };
- let host_name: Vec<u8> = name_cstr.to_bytes().to_vec();
- HOST_NAME = Some(host_name);
- _HOST_ADDR_LIST = mem::transmute::<u32, [u8; 4]>(host_addr.s_addr);
- HOST_ADDR_LIST = [_HOST_ADDR_LIST.as_mut_ptr() as *mut c_char, ptr::null_mut()];
- HOST_ADDR = Some(host_addr);
- //TODO actually get aliases
- let mut _host_aliases: Vec<Vec<u8>> = Vec::new();
- _host_aliases.push(vec![b'\0']);
- let mut host_aliases: Vec<*mut i8> = Vec::new();
- host_aliases.push(ptr::null_mut());
- host_aliases.push(ptr::null_mut());
- HOST_ALIASES = Some(_host_aliases);
- HOST_ENTRY = hostent {
- h_name: HOST_NAME.as_mut().unwrap().as_mut_ptr() as *mut c_char,
- h_aliases: host_aliases.as_mut_slice().as_mut_ptr() as *mut *mut i8,
- h_addrtype: AF_INET,
- h_length: 4,
- h_addr_list: HOST_ADDR_LIST.as_mut_ptr(),
- };
- sethostent(HOST_STAYOPEN);
- &HOST_ENTRY as *const hostent
- }
- #[no_mangle]
- pub unsafe extern "C" fn gethostent() -> *const hostent {
- if HOSTDB == 0 {
- HOSTDB = Sys::open(&CString::new("/etc/hosts").unwrap(), O_RDONLY, 0);
- }
- let mut rlb = RawLineBuffer::new(HOSTDB);
- rlb.seek(H_POS);
- let mut r: Box<str> = Box::default();
- while r.is_empty() || r.split_whitespace().next() == None || r.starts_with('#') {
- r = match rlb.next() {
- Line::Some(s) => bytes_to_box_str(s),
- _ => {
- if HOST_STAYOPEN == 0 {
- endhostent();
- }
- return ptr::null();
- }
- };
- }
- rlb.next();
- H_POS = rlb.line_pos();
- let mut iter: SplitWhitespace = r.split_whitespace();
- let mut addr_vec = iter.next().unwrap().as_bytes().to_vec();
- addr_vec.push(b'\0');
- let addr_cstr = addr_vec.as_slice().as_ptr() as *const i8;
- let mut addr = mem::uninitialized();
- inet_aton(addr_cstr, &mut addr);
- _HOST_ADDR_LIST = mem::transmute::<u32, [u8; 4]>(addr.s_addr);
- HOST_ADDR_LIST = [_HOST_ADDR_LIST.as_mut_ptr() as *mut c_char, ptr::null_mut()];
- HOST_ADDR = Some(addr);
- let mut host_name = iter.next().unwrap().as_bytes().to_vec();
- host_name.push(b'\0');
- let mut _host_aliases: Vec<Vec<u8>> = Vec::new();
- while let Some(s) = iter.next() {
- let mut alias = s.as_bytes().to_vec();
- alias.push(b'\0');
- _host_aliases.push(alias);
- }
- HOST_ALIASES = Some(_host_aliases);
- let mut host_aliases: Vec<*mut i8> = HOST_ALIASES
- .as_mut()
- .unwrap()
- .iter_mut()
- .map(|x| x.as_mut_ptr() as *mut i8)
- .collect();
- host_aliases.push(ptr::null_mut());
- host_aliases.push(ptr::null_mut());
- HOST_NAME = Some(host_name);
- HOST_ENTRY = hostent {
- h_name: HOST_NAME.as_mut().unwrap().as_mut_ptr() as *mut c_char,
- h_aliases: host_aliases.as_mut_slice().as_mut_ptr() as *mut *mut i8,
- h_addrtype: AF_INET,
- h_length: 4,
- h_addr_list: HOST_ADDR_LIST.as_mut_ptr(),
- };
- _HOST_ALIASES = Some(host_aliases);
- if HOST_STAYOPEN == 0 {
- endhostent();
- }
- &HOST_ENTRY as *const hostent
- }
- pub unsafe extern "C" fn getnetbyaddr(net: u32, net_type: c_int) -> *const netent {
- unimplemented!();
- }
- pub unsafe extern "C" fn getnetbyname(name: *const c_char) -> *const netent {
- unimplemented!();
- }
- pub unsafe extern "C" fn getnetent() -> *const netent {
- unimplemented!();
- }
- #[no_mangle]
- pub unsafe extern "C" fn getprotobyname(name: *const c_char) -> *const protoent {
- let mut p: *const protoent;
- setprotoent(PROTO_STAYOPEN);
- while {
- p = getprotoent();
- !p.is_null()
- } {
- if strcasecmp((*p).p_name, name) == 0 {
- setprotoent(PROTO_STAYOPEN);
- return p;
- }
- let mut cp = (*p).p_aliases;
- loop {
- if cp.is_null() {
- setprotoent(PROTO_STAYOPEN);
- break;
- }
- if (*cp).is_null() {
- setprotoent(PROTO_STAYOPEN);
- break;
- }
- if strcasecmp(*cp, name) == 0 {
- setprotoent(PROTO_STAYOPEN);
- return p;
- }
- cp = cp.offset(1);
- }
- }
- setprotoent(PROTO_STAYOPEN);
- platform::errno = ENOENT;
- ptr::null() as *const protoent
- }
- #[no_mangle]
- pub unsafe extern "C" fn getprotobynumber(number: c_int) -> *const protoent {
- setprotoent(PROTO_STAYOPEN);
- let mut p: *const protoent;
- while {
- p = getprotoent();
- !p.is_null()
- } {
- if (*p).p_proto == number {
- setprotoent(PROTO_STAYOPEN);
- return p;
- }
- }
- setprotoent(PROTO_STAYOPEN);
- platform::errno = ENOENT;
- ptr::null() as *const protoent
- }
- #[no_mangle]
- pub unsafe extern "C" fn getprotoent() -> *const protoent {
- if PROTODB == 0 {
- PROTODB = Sys::open(&CString::new("/etc/protocols").unwrap(), O_RDONLY, 0);
- }
- let mut rlb = RawLineBuffer::new(PROTODB);
- rlb.seek(P_POS);
- let mut r: Box<str> = Box::default();
- while r.is_empty() || r.split_whitespace().next() == None || r.starts_with('#') {
- r = match rlb.next() {
- Line::Some(s) => bytes_to_box_str(s),
- _ => {
- if PROTO_STAYOPEN == 0 {
- endprotoent();
- }
- return ptr::null();
- }
- };
- }
- rlb.next();
- P_POS = rlb.line_pos();
- let mut iter: SplitWhitespace = r.split_whitespace();
- let mut proto_name: Vec<u8> = iter.next().unwrap().as_bytes().to_vec();
- proto_name.push(b'\0');
- let mut num = iter.next().unwrap().as_bytes().to_vec();
- num.push(b'\0');
- PROTO_NUM = Some(atoi(num.as_mut_slice().as_mut_ptr() as *mut i8));
- let mut _proto_aliases: Vec<Vec<u8>> = Vec::new();
- while let Some(s) = iter.next() {
- let mut alias = s.as_bytes().to_vec();
- alias.push(b'\0');
- _proto_aliases.push(alias);
- }
- let mut proto_aliases: Vec<*mut i8> = _proto_aliases
- .iter_mut()
- .map(|x| x.as_mut_ptr() as *mut i8)
- .collect();
- proto_aliases.push(ptr::null_mut());
- PROTO_ALIASES = Some(_proto_aliases);
- PROTO_NAME = Some(proto_name);
- PROTO_ENTRY = protoent {
- p_name: PROTO_NAME.as_mut().unwrap().as_mut_slice().as_mut_ptr() as *mut c_char,
- p_aliases: proto_aliases.as_mut_slice().as_mut_ptr() as *mut *mut i8,
- p_proto: PROTO_NUM.unwrap(),
- };
- if PROTO_STAYOPEN == 0 {
- endprotoent();
- }
- &PROTO_ENTRY as *const protoent
- }
- #[no_mangle]
- pub unsafe extern "C" fn getservbyname(
- name: *const c_char,
- proto: *const c_char,
- ) -> *const servent {
- setservent(SERV_STAYOPEN);
- let mut p: *const servent;
- if proto.is_null() {
- while {
- p = getservent();
- !p.is_null()
- } {
- if strcasecmp((*p).s_name, name) == 0 {
- setservent(SERV_STAYOPEN);
- return p;
- }
- }
- } else {
- while {
- p = getservent();
- !p.is_null()
- } {
- if strcasecmp((*p).s_name, name) == 0 && strcasecmp((*p).s_proto, proto) == 0 {
- setservent(SERV_STAYOPEN);
- return p;
- }
- }
- }
- setservent(SERV_STAYOPEN);
- platform::errno = ENOENT;
- ptr::null() as *const servent
- }
- #[no_mangle]
- pub unsafe extern "C" fn getservbyport(port: c_int, proto: *const c_char) -> *const servent {
- setservent(SERV_STAYOPEN);
- let mut p: *const servent;
- if proto.is_null() {
- while {
- p = getservent();
- !p.is_null()
- } {
- if (*p).s_port == port {
- setservent(SERV_STAYOPEN);
- return p;
- }
- }
- } else {
- while {
- p = getservent();
- !p.is_null()
- } {
- if (*p).s_port == port && strcasecmp((*p).s_proto, proto) == 0 {
- setservent(SERV_STAYOPEN);
- return p;
- }
- }
- }
- setservent(SERV_STAYOPEN);
- platform::errno = ENOENT;
- ptr::null()
- }
- #[no_mangle]
- pub unsafe extern "C" fn getservent() -> *const servent {
- if SERVDB == 0 {
- SERVDB = Sys::open(&CString::new("/etc/services").unwrap(), O_RDONLY, 0);
- }
- let mut rlb = RawLineBuffer::new(SERVDB);
- rlb.seek(S_POS);
- let r: Box<str> = Box::default();
- loop {
- let r = match rlb.next() {
- Line::Some(s) => bytes_to_box_str(s),
- _ => {
- if SERV_STAYOPEN == 0 {
- endservent();
- }
- return ptr::null();
- }
- };
- let mut iter = r.split_whitespace();
- let mut serv_name = match iter.next() {
- Some(serv_name) => serv_name.as_bytes().to_vec(),
- None => continue,
- };
- serv_name.push(b'\0');
- let port_proto = match iter.next() {
- Some(port_proto) => port_proto,
- None => continue,
- };
- let mut split = port_proto.split('/');
- let mut port = match split.next() {
- Some(port) => port.as_bytes().to_vec(),
- None => continue,
- };
- port.push(b'\0');
- SERV_PORT =
- Some(htons(atoi(port.as_mut_slice().as_mut_ptr() as *mut i8) as u16) as u32 as i32);
- let mut proto = match split.next() {
- Some(proto) => proto.as_bytes().to_vec(),
- None => continue,
- };
- proto.push(b'\0');
- rlb.next();
- S_POS = rlb.line_pos();
- /*
- *let mut _serv_aliases: Vec<Vec<u8>> = Vec::new();
- *loop {
- * let mut alias = match iter.next() {
- * Some(s) => s.as_bytes().to_vec(),
- * _ => break
- * };
- * alias.push(b'\0');
- * _serv_aliases.push(alias);
- *}
- *let mut serv_aliases: Vec<*mut i8> = _serv_aliases.iter_mut().map(|x| x.as_mut_ptr() as *mut i8).collect();
- *serv_aliases.push(ptr::null_mut());
- *
- */
- let mut _serv_aliases: Vec<Vec<u8>> = Vec::new();
- _serv_aliases.push(vec![b'\0']);
- let mut serv_aliases: Vec<*mut i8> = Vec::new();
- serv_aliases.push(ptr::null_mut());
- serv_aliases.push(ptr::null_mut());
- SERV_ALIASES = Some(_serv_aliases);
- SERV_NAME = Some(serv_name);
- SERV_PROTO = Some(proto);
- SERV_ENTRY = servent {
- s_name: SERV_NAME.as_mut().unwrap().as_mut_slice().as_mut_ptr() as *mut c_char,
- s_aliases: serv_aliases.as_mut_slice().as_mut_ptr() as *mut *mut i8,
- s_port: SERV_PORT.unwrap(),
- s_proto: SERV_PROTO.as_mut().unwrap().as_mut_slice().as_mut_ptr() as *mut c_char,
- };
- if SERV_STAYOPEN == 0 {
- endservent();
- }
- break &SERV_ENTRY as *const servent;
- }
- }
- #[no_mangle]
- pub unsafe extern "C" fn sethostent(stayopen: c_int) {
- HOST_STAYOPEN = stayopen;
- if HOSTDB == 0 {
- HOSTDB = Sys::open(&CString::new("/etc/hosts").unwrap(), O_RDONLY, 0)
- } else {
- Sys::lseek(HOSTDB, 0, SEEK_SET);
- }
- H_POS = 0;
- }
- #[no_mangle]
- pub unsafe extern "C" fn setnetent(stayopen: c_int) {
- NET_STAYOPEN = stayopen;
- if NETDB == 0 {
- NETDB = Sys::open(&CString::new("/etc/networks").unwrap(), O_RDONLY, 0)
- } else {
- Sys::lseek(NETDB, 0, SEEK_SET);
- N_POS = 0;
- }
- }
- #[no_mangle]
- pub unsafe extern "C" fn setprotoent(stayopen: c_int) {
- PROTO_STAYOPEN = stayopen;
- if PROTODB == 0 {
- PROTODB = Sys::open(&CString::new("/etc/protocols").unwrap(), O_RDONLY, 0)
- } else {
- Sys::lseek(PROTODB, 0, SEEK_SET);
- P_POS = 0;
- }
- }
- #[no_mangle]
- pub unsafe extern "C" fn setservent(stayopen: c_int) {
- SERV_STAYOPEN = stayopen;
- if SERVDB == 0 {
- SERVDB = Sys::open(&CString::new("/etc/services").unwrap(), O_RDONLY, 0)
- } else {
- Sys::lseek(SERVDB, 0, SEEK_SET);
- S_POS = 0;
- }
- }
- pub unsafe extern "C" fn getaddrinfo(
- node: *const c_char,
- service: *const c_char,
- hints: *const addrinfo,
- res: *mut *mut addrinfo,
- ) -> c_int {
- unimplemented!();
- }
- pub unsafe extern "C" fn getnameinfo(
- addr: *const sockaddr,
- addrlen: socklen_t,
- host: *mut c_char,
- hostlen: socklen_t,
- serv: *mut c_char,
- servlen: socklen_t,
- flags: c_int,
- ) -> c_int {
- unimplemented!();
- }
- pub extern "C" fn freeaddrinfo(res: *mut addrinfo) {
- unimplemented!();
- }
- pub extern "C" fn gai_strerror(errcode: c_int) -> *const c_char {
- unimplemented!();
- }
|