fix for php. include incomplete code for UnixSocket

This commit is contained in:
WangRunji 2019-04-23 22:00:38 +08:00
parent f846ba11f2
commit 9106bd46f2
13 changed files with 475 additions and 67 deletions

@ -3,7 +3,7 @@
<ProdID>0</ProdID> <ProdID>0</ProdID>
<ISVSVN>0</ISVSVN> <ISVSVN>0</ISVSVN>
<StackMaxSize>0x100000</StackMaxSize> <StackMaxSize>0x100000</StackMaxSize>
<HeapMaxSize>0x1000000</HeapMaxSize> <HeapMaxSize>0x2000000</HeapMaxSize>
<TCSNum>8</TCSNum> <TCSNum>8</TCSNum>
<TCSPolicy>1</TCSPolicy> <TCSPolicy>1</TCSPolicy>
<DisableDebug>0</DisableDebug> <DisableDebug>0</DisableDebug>

@ -373,7 +373,7 @@ impl File for StdoutFile {
atime: Timespec { sec: 0, nsec: 0 }, atime: Timespec { sec: 0, nsec: 0 },
mtime: Timespec { sec: 0, nsec: 0 }, mtime: Timespec { sec: 0, nsec: 0 },
ctime: Timespec { sec: 0, nsec: 0 }, ctime: Timespec { sec: 0, nsec: 0 },
type_: FileType::File, type_: FileType::CharDevice,
mode: 0, mode: 0,
nlinks: 0, nlinks: 0,
uid: 0, uid: 0,
@ -489,7 +489,7 @@ impl File for StdinFile {
atime: Timespec { sec: 0, nsec: 0 }, atime: Timespec { sec: 0, nsec: 0 },
mtime: Timespec { sec: 0, nsec: 0 }, mtime: Timespec { sec: 0, nsec: 0 },
ctime: Timespec { sec: 0, nsec: 0 }, ctime: Timespec { sec: 0, nsec: 0 },
type_: FileType::File, type_: FileType::CharDevice,
mode: 0, mode: 0,
nlinks: 0, nlinks: 0,
uid: 0, uid: 0,

@ -1,5 +1,4 @@
use super::*; use super::*;
use crate::syscall::AsSocket;
use std::any::Any; use std::any::Any;
use std::collections::btree_map::BTreeMap; use std::collections::btree_map::BTreeMap;
use std::fmt; use std::fmt;

@ -9,7 +9,8 @@ use super::*;
pub use self::file::{File, FileRef, SgxFile, StdinFile, StdoutFile}; pub use self::file::{File, FileRef, SgxFile, StdinFile, StdoutFile};
pub use self::file_table::{FileDesc, FileTable}; pub use self::file_table::{FileDesc, FileTable};
pub use self::inode_file::{INodeExt, INodeFile, ROOT_INODE}; pub use self::inode_file::{INodeExt, INodeFile, ROOT_INODE};
pub use self::socket_file::SocketFile; pub use self::socket_file::{SocketFile, AsSocket};
pub use self::unix_socket::{UnixSocketFile, AsUnixSocket};
use self::inode_file::OpenOptions; use self::inode_file::OpenOptions;
pub use self::pipe::Pipe; pub use self::pipe::Pipe;
pub use self::io_multiplexing::*; pub use self::io_multiplexing::*;
@ -27,6 +28,7 @@ mod sgx_impl;
mod io_multiplexing; mod io_multiplexing;
mod access; mod access;
mod null; mod null;
mod unix_socket;
pub fn do_open(path: &str, flags: u32, mode: u32) -> Result<FileDesc, Error> { pub fn do_open(path: &str, flags: u32, mode: u32) -> Result<FileDesc, Error> {
@ -363,7 +365,7 @@ pub fn do_sendfile(
let in_file = file_table.get(in_fd)?; let in_file = file_table.get(in_fd)?;
let out_file = file_table.get(out_fd)?; let out_file = file_table.get(out_fd)?;
let mut buffer: [u8; 1024] = unsafe { uninitialized() }; let mut buffer: [u8; 1024 * 11] = unsafe { uninitialized() };
let mut read_offset = match offset { let mut read_offset = match offset {
Some(offset) => offset, Some(offset) => offset,

@ -90,7 +90,21 @@ impl File for SocketFile {
} }
fn metadata(&self) -> Result<Metadata, Error> { fn metadata(&self) -> Result<Metadata, Error> {
unimplemented!() Ok(Metadata {
dev: 0,
inode: 0,
size: 0,
blk_size: 0,
blocks: 0,
atime: Timespec { sec: 0, nsec: 0 },
mtime: Timespec { sec: 0, nsec: 0 },
ctime: Timespec { sec: 0, nsec: 0 },
type_: FileType::Socket,
mode: 0,
nlinks: 0,
uid: 0,
gid: 0
})
} }
fn set_len(&self, len: u64) -> Result<(), Error> { fn set_len(&self, len: u64) -> Result<(), Error> {
@ -113,3 +127,15 @@ impl File for SocketFile {
self self
} }
} }
pub trait AsSocket {
fn as_socket(&self) -> Result<&SocketFile, Error>;
}
impl AsSocket for FileRef {
fn as_socket(&self) -> Result<&SocketFile, Error> {
self.as_any()
.downcast_ref::<SocketFile>()
.ok_or(Error::new(Errno::EBADF, "not a socket"))
}
}

@ -0,0 +1,310 @@
use super::*;
use std::collections::btree_map::BTreeMap;
use util::ring_buf::{RingBufReader, RingBufWriter, RingBuf};
use std::sync::SgxMutex as Mutex;
use alloc::prelude::ToString;
use std::fmt;
pub struct UnixSocketFile {
inner: Mutex<UnixSocket>
}
impl File for UnixSocketFile {
fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
let mut inner = self.inner.lock().unwrap();
inner.read(buf)
}
fn write(&self, buf: &[u8]) -> Result<usize, Error> {
let mut inner = self.inner.lock().unwrap();
inner.write(buf)
}
fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result<usize, Error> {
self.read(buf)
}
fn write_at(&self, _offset: usize, buf: &[u8]) -> Result<usize, Error> {
self.write(buf)
}
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize, Error> {
let mut inner = self.inner.lock().unwrap();
let mut total_len = 0;
for buf in bufs {
match inner.read(buf) {
Ok(len) => {
total_len += len;
}
Err(_) if total_len != 0 => break,
Err(e) => return Err(e.into()),
}
}
Ok(total_len)
}
fn writev(&self, bufs: &[&[u8]]) -> Result<usize, Error> {
let mut inner = self.inner.lock().unwrap();
let mut total_len = 0;
for buf in bufs {
match inner.write(buf) {
Ok(len) => {
total_len += len;
}
Err(_) if total_len != 0 => break,
Err(e) => return Err(e.into()),
}
}
Ok(total_len)
}
fn seek(&self, pos: SeekFrom) -> Result<off_t, Error> {
errno!(ESPIPE, "UnixSocket does not support seek")
}
fn metadata(&self) -> Result<Metadata, Error> {
Ok(Metadata {
dev: 0,
inode: 0,
size: 0,
blk_size: 0,
blocks: 0,
atime: Timespec { sec: 0, nsec: 0 },
mtime: Timespec { sec: 0, nsec: 0 },
ctime: Timespec { sec: 0, nsec: 0 },
type_: FileType::Socket,
mode: 0,
nlinks: 0,
uid: 0,
gid: 0
})
}
fn set_len(&self, len: u64) -> Result<(), Error> {
unimplemented!()
}
fn sync_all(&self) -> Result<(), Error> {
unimplemented!()
}
fn sync_data(&self) -> Result<(), Error> {
unimplemented!()
}
fn read_entry(&self) -> Result<String, Error> {
unimplemented!()
}
fn as_any(&self) -> &Any {
self
}
}
impl UnixSocketFile {
pub fn new(socket_type: c_int, protocol: c_int) -> Result<Self, Error> {
let inner = UnixSocket::new(socket_type, protocol)?;
Ok(UnixSocketFile { inner: Mutex::new(inner) })
}
pub fn bind(&self, path: impl AsRef<str>) -> Result<(), Error> {
let mut inner = self.inner.lock().unwrap();
inner.bind(path)
}
pub fn listen(&self) -> Result<(), Error> {
let mut inner = self.inner.lock().unwrap();
inner.listen()
}
pub fn accept(&self) -> Result<UnixSocketFile, Error> {
let mut inner = self.inner.lock().unwrap();
let new_socket = inner.accept()?;
Ok(UnixSocketFile { inner: Mutex::new(new_socket) })
}
pub fn connect(&self, path: impl AsRef<str>) -> Result<(), Error> {
let mut inner = self.inner.lock().unwrap();
inner.connect(path)
}
}
impl Debug for UnixSocketFile {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "UnixSocketFile {{ ... }}")
}
}
pub trait AsUnixSocket {
fn as_unix_socket(&self) -> Result<&UnixSocketFile, Error>;
}
impl AsUnixSocket for FileRef {
fn as_unix_socket(&self) -> Result<&UnixSocketFile, Error> {
self.as_any()
.downcast_ref::<UnixSocketFile>()
.ok_or(Error::new(Errno::EBADF, "not a unix socket"))
}
}
pub struct UnixSocket {
obj: Option<Arc<UnixSocketObject>>,
status: Status,
}
enum Status {
None,
Listening,
Connected(Channel),
}
impl UnixSocket {
/// C/S 1: Create a new unix socket
pub fn new(socket_type: c_int, protocol: c_int) -> Result<Self, Error> {
if socket_type == libc::SOCK_STREAM && protocol == 0 {
Ok(UnixSocket {
obj: None,
status: Status::None
})
} else {
errno!(ENOSYS, "unimplemented unix socket type")
}
}
/// Server 2: Bind the socket to a file system path
pub fn bind(&mut self, path: impl AsRef<str>) -> Result<(), Error> {
// TODO: check permission
if self.obj.is_some() {
return errno!(EINVAL, "The socket is already bound to an address.");
}
self.obj = Some(UnixSocketObject::create(path)?);
Ok(())
}
/// Server 3: Listen to a socket
pub fn listen(&mut self) -> Result<(), Error> {
self.status = Status::Listening;
Ok(())
}
/// Server 4: Accept a connection on listening. Non-blocking.
pub fn accept(&mut self) -> Result<UnixSocket, Error> {
match self.status {
Status::Listening => {}
_ => return errno!(EINVAL, "unix socket is not listening"),
};
let socket = self.obj.as_mut().unwrap().pop()
.ok_or(Error::new(EAGAIN, "no connections are present to be accepted"))?;
Ok(socket)
}
/// Client 2: Connect to a path
pub fn connect(&mut self, path: impl AsRef<str>) -> Result<(), Error> {
if let Status::Listening = self.status {
return errno!(EINVAL, "unix socket is listening?");
}
let obj = UnixSocketObject::get(path)
.ok_or(Error::new(EINVAL, "unix socket path not found"))?;
let (channel1, channel2) = Channel::new_pair();
self.status = Status::Connected(channel1);
obj.push(UnixSocket {
obj: Some(obj.clone()),
status: Status::Connected(channel2),
});
Ok(())
}
pub fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
if let Status::Connected(channel) = &self.status {
channel.reader.read(buf)
} else {
errno!(EBADF, "UnixSocket is not connected")
}
}
pub fn write(&self, buf: &[u8]) -> Result<usize, Error> {
if let Status::Connected(channel) = &self.status {
channel.writer.write(buf)
} else {
errno!(EBADF, "UnixSocket is not connected")
}
}
}
impl Drop for UnixSocket {
fn drop(&mut self) {
if let Status::Listening = self.status {
let path = &self.obj.as_ref().unwrap().path;
UnixSocketObject::remove(path);
}
}
}
pub struct UnixSocketObject {
path: String,
accepted_sockets: Mutex<VecDeque<UnixSocket>>,
}
impl UnixSocketObject {
fn push(&self, unix_socket: UnixSocket) {
let mut queue = self.accepted_sockets.lock().unwrap();
queue.push_back(unix_socket);
}
fn pop(&self) -> Option<UnixSocket> {
let mut queue = self.accepted_sockets.lock().unwrap();
queue.pop_front()
}
fn get(path: impl AsRef<str>) -> Option<Arc<Self>> {
let mut paths = UNIX_SOCKET_OBJS.lock().unwrap();
paths.get(path.as_ref()).map(|obj| obj.clone())
}
fn create(path: impl AsRef<str>) -> Result<Arc<Self>, Error> {
let mut paths = UNIX_SOCKET_OBJS.lock().unwrap();
if paths.contains_key(path.as_ref()) {
return errno!(EADDRINUSE, "unix socket path already exists");
}
let obj = Arc::new(UnixSocketObject {
path: path.as_ref().to_string(),
accepted_sockets: Mutex::new(VecDeque::new())
});
paths.insert(path.as_ref().to_string(), obj.clone());
Ok(obj)
}
fn remove(path: impl AsRef<str>) {
let mut paths = UNIX_SOCKET_OBJS.lock().unwrap();
paths.remove(path.as_ref());
}
}
struct Channel {
reader: RingBufReader,
writer: RingBufWriter
}
unsafe impl Send for Channel {}
unsafe impl Sync for Channel {}
impl Channel {
fn new_pair() -> (Channel, Channel) {
let buf1 = RingBuf::new(DEFAULT_BUF_SIZE);
let buf2 = RingBuf::new(DEFAULT_BUF_SIZE);
let channel1 = Channel {
reader: buf1.reader,
writer: buf2.writer,
};
let channel2 = Channel {
reader: buf2.reader,
writer: buf1.writer,
};
(channel1, channel2)
}
}
pub const DEFAULT_BUF_SIZE: usize = 1 * 1024 * 1024;
lazy_static! {
static ref UNIX_SOCKET_OBJS: Mutex<BTreeMap<String, Arc<UnixSocketObject>>>
= Mutex::new(BTreeMap::new());
}

@ -36,7 +36,7 @@ macro_rules! debug_trace {
macro_rules! errno { macro_rules! errno {
($errno: ident, $msg: expr) => {{ ($errno: ident, $msg: expr) => {{
println!( error!(
"ERROR: {} ({}, line {} in file {})", "ERROR: {} ({}, line {} in file {})",
$errno, $errno,
$msg, $msg,
@ -54,7 +54,7 @@ macro_rules! try_libc {
if ret == -1 { if ret == -1 {
let errno = unsafe { libc::errno() }; let errno = unsafe { libc::errno() };
// println will cause libc ocall and overwrite errno // println will cause libc ocall and overwrite errno
println!( error!(
"ERROR from libc: {} (line {} in file {})", "ERROR from libc: {} (line {} in file {})",
errno, errno,
line!(), line!(),

@ -101,7 +101,7 @@ pub fn do_wait4(child_filter: &ChildProcessFilter, exit_status: &mut i32) -> Res
waiter waiter
}; };
let child_pid = Waiter::sleep_until_woken_with_result(waiter); let child_pid = waiter.sleep_until_woken_with_result();
let mut current = current_ref.lock().unwrap(); let mut current = current_ref.lock().unwrap();
let child_i = { let child_i = {

@ -4,8 +4,8 @@ use std::ptr;
use xmas_elf::{header, program, sections, ElfFile}; use xmas_elf::{header, program, sections, ElfFile};
pub const DEFAULT_STACK_SIZE: usize = 1 * 1024 * 1024; pub const DEFAULT_STACK_SIZE: usize = 1 * 1024 * 1024;
pub const DEFAULT_HEAP_SIZE: usize = 2 * 1024 * 1024; pub const DEFAULT_HEAP_SIZE: usize = 10 * 1024 * 1024;
pub const DEFAULT_MMAP_SIZE: usize = 8 * 1024 * 1024; pub const DEFAULT_MMAP_SIZE: usize = 40 * 1024 * 1024;
pub fn do_init(elf_file: &ElfFile, elf_buf: &[u8]) -> Result<ProcessVM, Error> { pub fn do_init(elf_file: &ElfFile, elf_buf: &[u8]) -> Result<ProcessVM, Error> {
let mut code_seg = get_code_segment(elf_file)?; let mut code_seg = get_code_segment(elf_file)?;

@ -113,7 +113,8 @@ fn init_files(parent_ref: &ProcessRef, file_actions: &[FileAction]) -> Result<Fi
} }
} }
&FileAction::Close(fd) => { &FileAction::Close(fd) => {
cloned_file_table.del(fd)?; // ignore error
cloned_file_table.del(fd);
} }
} }
} }

@ -48,14 +48,14 @@ where
self.inner.lock().unwrap().data self.inner.lock().unwrap().data
} }
pub fn sleep_until_woken_with_result(waiter: Waiter<D, R>) -> R { pub fn sleep_until_woken_with_result(self) -> R {
while !waiter.inner.lock().unwrap().is_woken { while !self.inner.lock().unwrap().is_woken {
unsafe { unsafe {
wait_event(waiter.thread); wait_event(self.thread);
} }
} }
waiter.inner.lock().unwrap().result.unwrap() self.inner.lock().unwrap().result.unwrap()
} }
} }

@ -7,7 +7,7 @@
//! 3. Dispatch the syscall to `do_*` (at this file) //! 3. Dispatch the syscall to `do_*` (at this file)
//! 4. Do some memory checks then call `mod::do_*` (at each module) //! 4. Do some memory checks then call `mod::do_*` (at each module)
use fs::{AccessFlags, AccessModes, FcntlCmd, File, FileDesc, FileRef, SocketFile, AT_FDCWD}; use fs::*;
use misc::{resource_t, rlimit_t, utsname_t}; use misc::{resource_t, rlimit_t, utsname_t};
use prelude::*; use prelude::*;
use process::{pid_t, ChildProcessFilter, CloneFlags, FileAction, FutexFlags, FutexOp}; use process::{pid_t, ChildProcessFilter, CloneFlags, FileAction, FutexFlags, FutexOp};
@ -48,10 +48,15 @@ pub extern "C" fn dispatch_syscall(
); );
#[cfg(feature = "syscall_timing")] #[cfg(feature = "syscall_timing")]
let time_start = { let time_start = {
if crate::process::current_pid() == 1 && num == SYS_EXIT { static mut LAST_PRINT: usize = 0;
print_syscall_timing(); let time = crate::time::do_gettimeofday().as_usec();
unsafe {
if time / 1000000 / 5 > LAST_PRINT {
LAST_PRINT = time / 1000000 / 5;
print_syscall_timing();
}
} }
crate::time::do_gettimeofday().as_usec() time
}; };
let ret = match num { let ret = match num {
@ -248,6 +253,11 @@ pub extern "C" fn dispatch_syscall(
arg3 as *mut c_void, arg3 as *mut c_void,
arg4 as *mut libc::socklen_t, arg4 as *mut libc::socklen_t,
), ),
SYS_GETPEERNAME => do_getpeername(
arg0 as c_int,
arg1 as *mut libc::sockaddr,
arg2 as *mut libc::socklen_t,
),
SYS_SENDTO => do_sendto( SYS_SENDTO => do_sendto(
arg0 as c_int, arg0 as c_int,
arg1 as *const c_void, arg1 as *const c_void,
@ -295,6 +305,9 @@ fn print_syscall_timing() {
} }
println!("{:>3}: {:>6} us", i, time); println!("{:>3}: {:>6} us", i, time);
} }
for x in unsafe { SYSCALL_TIMING.iter_mut() } {
*x = 0;
}
} }
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
@ -936,8 +949,16 @@ fn do_socket(domain: c_int, socket_type: c_int, protocol: c_int) -> Result<isize
domain, socket_type, protocol domain, socket_type, protocol
); );
let socket = SocketFile::new(domain, socket_type, protocol)?; let file_ref: Arc<Box<File>> = match domain {
let file_ref: Arc<Box<File>> = Arc::new(Box::new(socket)); // libc::AF_LOCAL => {
// let unix_socket = UnixSocketFile::new(socket_type, protocol)?;
// Arc::new(Box::new(unix_socket))
// }
_ => {
let socket = SocketFile::new(domain, socket_type, protocol)?;
Arc::new(Box::new(socket))
}
};
let current_ref = process::get_current(); let current_ref = process::get_current();
let mut proc = current_ref.lock().unwrap(); let mut proc = current_ref.lock().unwrap();
@ -958,10 +979,18 @@ fn do_connect(
let current_ref = process::get_current(); let current_ref = process::get_current();
let mut proc = current_ref.lock().unwrap(); let mut proc = current_ref.lock().unwrap();
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?; let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
let socket = file_ref.as_socket()?; if let Ok(socket) = file_ref.as_socket() {
let ret = try_libc!(libc::ocall::connect(socket.fd(), addr, addr_len));
let ret = try_libc!(libc::ocall::connect(socket.fd(), addr, addr_len)); Ok(ret as isize)
Ok(ret as isize) } else if let Ok(unix_socket) = file_ref.as_unix_socket() {
let addr = addr as *const libc::sockaddr_un;
check_ptr(addr)?; // TODO: check addr_len
let path = clone_cstring_safely(unsafe { (&*addr).sun_path.as_ptr() })?.to_string_lossy().into_owned();
unix_socket.connect(path)?;
Ok(0)
} else {
errno!(EBADF, "not a socket")
}
} }
fn do_accept4( fn do_accept4(
@ -977,13 +1006,26 @@ fn do_accept4(
let current_ref = process::get_current(); let current_ref = process::get_current();
let mut proc = current_ref.lock().unwrap(); let mut proc = current_ref.lock().unwrap();
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?; let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
let socket = file_ref.as_socket()?; if let Ok(socket) = file_ref.as_socket() {
let socket = file_ref.as_socket()?;
let new_socket = socket.accept(addr, addr_len, flags)?; let new_socket = socket.accept(addr, addr_len, flags)?;
let new_file_ref: Arc<Box<File>> = Arc::new(Box::new(new_socket)); let new_file_ref: Arc<Box<File>> = Arc::new(Box::new(new_socket));
let new_fd = proc.get_files().lock().unwrap().put(new_file_ref, false); let new_fd = proc.get_files().lock().unwrap().put(new_file_ref, false);
Ok(new_fd as isize) Ok(new_fd as isize)
} else if let Ok(unix_socket) = file_ref.as_unix_socket() {
let addr = addr as *mut libc::sockaddr_un;
check_mut_ptr(addr)?; // TODO: check addr_len
let new_socket = unix_socket.accept()?;
let new_file_ref: Arc<Box<File>> = Arc::new(Box::new(new_socket));
let new_fd = proc.get_files().lock().unwrap().put(new_file_ref, false);
Ok(0)
} else {
errno!(EBADF, "not a socket")
}
} }
fn do_shutdown(fd: c_int, how: c_int) -> Result<isize, Error> { fn do_shutdown(fd: c_int, how: c_int) -> Result<isize, Error> {
@ -991,10 +1033,12 @@ fn do_shutdown(fd: c_int, how: c_int) -> Result<isize, Error> {
let current_ref = process::get_current(); let current_ref = process::get_current();
let mut proc = current_ref.lock().unwrap(); let mut proc = current_ref.lock().unwrap();
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?; let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
let socket = file_ref.as_socket()?; if let Ok(socket) = file_ref.as_socket() {
let ret = try_libc!(libc::ocall::shutdown(socket.fd(), how));
let ret = try_libc!(libc::ocall::shutdown(socket.fd(), how)); Ok(ret as isize)
Ok(ret as isize) } else {
errno!(EBADF, "not a socket")
}
} }
fn do_bind( fn do_bind(
@ -1006,10 +1050,19 @@ fn do_bind(
let current_ref = process::get_current(); let current_ref = process::get_current();
let mut proc = current_ref.lock().unwrap(); let mut proc = current_ref.lock().unwrap();
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?; let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
let socket = file_ref.as_socket()?; if let Ok(socket) = file_ref.as_socket() {
check_ptr(addr)?; // TODO: check addr_len
let ret = try_libc!(libc::ocall::bind(socket.fd(), addr, addr_len)); let ret = try_libc!(libc::ocall::bind(socket.fd(), addr, addr_len));
Ok(ret as isize) Ok(ret as isize)
} else if let Ok(unix_socket) = file_ref.as_unix_socket() {
let addr = addr as *const libc::sockaddr_un;
check_ptr(addr)?; // TODO: check addr_len
let path = clone_cstring_safely(unsafe { (&*addr).sun_path.as_ptr() })?.to_string_lossy().into_owned();
unix_socket.bind(path)?;
Ok(0)
} else {
errno!(EBADF, "not a socket")
}
} }
fn do_listen(fd: c_int, backlog: c_int) -> Result<isize, Error> { fn do_listen(fd: c_int, backlog: c_int) -> Result<isize, Error> {
@ -1017,10 +1070,15 @@ fn do_listen(fd: c_int, backlog: c_int) -> Result<isize, Error> {
let current_ref = process::get_current(); let current_ref = process::get_current();
let mut proc = current_ref.lock().unwrap(); let mut proc = current_ref.lock().unwrap();
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?; let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
let socket = file_ref.as_socket()?; if let Ok(socket) = file_ref.as_socket() {
let ret = try_libc!(libc::ocall::listen(socket.fd(), backlog));
let ret = try_libc!(libc::ocall::listen(socket.fd(), backlog)); Ok(ret as isize)
Ok(ret as isize) } else if let Ok(unix_socket) = file_ref.as_unix_socket() {
unix_socket.listen()?;
Ok(0)
} else {
errno!(EBADF, "not a socket")
}
} }
fn do_setsockopt( fn do_setsockopt(
@ -1037,16 +1095,21 @@ fn do_setsockopt(
let current_ref = process::get_current(); let current_ref = process::get_current();
let mut proc = current_ref.lock().unwrap(); let mut proc = current_ref.lock().unwrap();
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?; let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
let socket = file_ref.as_socket()?; if let Ok(socket) = file_ref.as_socket() {
let ret = try_libc!(libc::ocall::setsockopt(
let ret = try_libc!(libc::ocall::setsockopt( socket.fd(),
socket.fd(), level,
level, optname,
optname, optval,
optval, optlen
optlen ));
)); Ok(ret as isize)
Ok(ret as isize) } else if let Ok(unix_socket) = file_ref.as_unix_socket() {
warn!("setsockopt for unix socket is unimplemented");
Ok(0)
} else {
errno!(EBADF, "not a socket")
}
} }
fn do_getsockopt( fn do_getsockopt(
@ -1075,6 +1138,25 @@ fn do_getsockopt(
Ok(ret as isize) Ok(ret as isize)
} }
fn do_getpeername(
fd: c_int,
addr: *mut libc::sockaddr,
addr_len: *mut libc::socklen_t,
) -> Result<isize, Error> {
info!("getpeername: fd: {}, addr: {:?}, addr_len: {:?}", fd, addr, addr_len);
let current_ref = process::get_current();
let mut proc = current_ref.lock().unwrap();
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
let socket = file_ref.as_socket()?;
let ret = try_libc!(libc::ocall::getpeername(
socket.fd(),
addr,
addr_len
));
Ok(ret as isize)
}
fn do_sendto( fn do_sendto(
fd: c_int, fd: c_int,
base: *const c_void, base: *const c_void,
@ -1230,18 +1312,6 @@ fn do_epoll_wait(
Ok(count as isize) Ok(count as isize)
} }
pub trait AsSocket {
fn as_socket(&self) -> Result<&SocketFile, Error>;
}
impl AsSocket for FileRef {
fn as_socket(&self) -> Result<&SocketFile, Error> {
self.as_any()
.downcast_ref::<SocketFile>()
.ok_or(Error::new(Errno::EBADF, "not a socket"))
}
}
fn do_uname(name: *mut utsname_t) -> Result<isize, Error> { fn do_uname(name: *mut utsname_t) -> Result<isize, Error> {
check_mut_ptr(name)?; check_mut_ptr(name)?;
let name = unsafe { &mut *name }; let name = unsafe { &mut *name };

@ -1,6 +1,6 @@
#include <stddef.h> #include <stddef.h>
#define DATA_SPACE_SIZE (96*1024*1024) #define DATA_SPACE_SIZE (128*1024*1024)
static char __prealloced_data_space[DATA_SPACE_SIZE] static char __prealloced_data_space[DATA_SPACE_SIZE]
__attribute__ (( __attribute__ ((