From d590486029397e70daf0ae98cd7e225c73e765aa Mon Sep 17 00:00:00 2001 From: He Sun Date: Thu, 24 Sep 2020 07:38:28 +0800 Subject: [PATCH] Refactor host socket 1. Add Rust memory-safe types, e.g., socket_address, address_family and socket_type; 2. Implement Berkeley Sockets API for HostSocket. --- src/libos/src/net/io_multiplexing/epoll.rs | 4 +- src/libos/src/net/io_multiplexing/poll.rs | 4 +- src/libos/src/net/mod.rs | 22 +- src/libos/src/net/socket/address_family.rs | 71 ++++ .../src/net/{msg_flags.rs => socket/flags.rs} | 7 + .../src/net/socket/host_socket/host_socket.rs | 132 ++++++++ .../host_socket}/ioctl_impl.rs | 8 +- src/libos/src/net/socket/host_socket/mod.rs | 9 + .../host_socket}/recv.rs | 78 ++--- .../host_socket}/send.rs | 64 ++-- .../src/net/socket/host_socket/socket_file.rs | 77 +++++ src/libos/src/net/{ => socket}/iovs.rs | 0 src/libos/src/net/socket/mod.rs | 19 ++ src/libos/src/net/{ => socket}/msg.rs | 5 +- src/libos/src/net/socket/socket_address.rs | 121 +++++++ src/libos/src/net/socket/socket_type.rs | 29 ++ src/libos/src/net/{ => socket}/unix_socket.rs | 0 src/libos/src/net/socket_file/mod.rs | 154 --------- src/libos/src/net/syscalls.rs | 308 ++++++++++-------- src/libos/src/syscall/mod.rs | 3 +- 20 files changed, 722 insertions(+), 393 deletions(-) create mode 100644 src/libos/src/net/socket/address_family.rs rename src/libos/src/net/{msg_flags.rs => socket/flags.rs} (91%) create mode 100644 src/libos/src/net/socket/host_socket/host_socket.rs rename src/libos/src/net/{socket_file => socket/host_socket}/ioctl_impl.rs (94%) create mode 100644 src/libos/src/net/socket/host_socket/mod.rs rename src/libos/src/net/{socket_file => socket/host_socket}/recv.rs (71%) rename src/libos/src/net/{socket_file => socket/host_socket}/send.rs (63%) create mode 100644 src/libos/src/net/socket/host_socket/socket_file.rs rename src/libos/src/net/{ => socket}/iovs.rs (100%) create mode 100644 src/libos/src/net/socket/mod.rs rename src/libos/src/net/{ => socket}/msg.rs (97%) create mode 100644 src/libos/src/net/socket/socket_address.rs create mode 100644 src/libos/src/net/socket/socket_type.rs rename src/libos/src/net/{ => socket}/unix_socket.rs (100%) delete mode 100644 src/libos/src/net/socket_file/mod.rs diff --git a/src/libos/src/net/io_multiplexing/epoll.rs b/src/libos/src/net/io_multiplexing/epoll.rs index 1041e771..d39f3ddb 100644 --- a/src/libos/src/net/io_multiplexing/epoll.rs +++ b/src/libos/src/net/io_multiplexing/epoll.rs @@ -93,8 +93,8 @@ impl EpollFile { pub fn control(&self, op: EpollCtlCmd, fd: FileDesc, event: Option<&EpollEvent>) -> Result<()> { let host_fd = { let fd_ref = current!().file(fd)?; - if let Ok(socket) = fd_ref.as_socket() { - socket.fd() + if let Ok(socket) = fd_ref.as_host_socket() { + socket.host_fd() } else if let Ok(eventfd) = fd_ref.as_event() { eventfd.get_host_fd() } else if let Ok(epoll_file) = fd_ref.as_epfile() { diff --git a/src/libos/src/net/io_multiplexing/poll.rs b/src/libos/src/net/io_multiplexing/poll.rs index c4b85d18..8ed8a54a 100644 --- a/src/libos/src/net/io_multiplexing/poll.rs +++ b/src/libos/src/net/io_multiplexing/poll.rs @@ -112,8 +112,8 @@ pub fn do_poll(pollfds: &mut [PollEvent], timeout: *mut timeval_t) -> Result Result { + if af >= Self::MAX as u16 { + return_errno!(EINVAL, "Unknown address family"); + } else { + Ok(unsafe { core::mem::transmute(af) }) + } + } +} diff --git a/src/libos/src/net/msg_flags.rs b/src/libos/src/net/socket/flags.rs similarity index 91% rename from src/libos/src/net/msg_flags.rs rename to src/libos/src/net/socket/flags.rs index de696916..f2ad14eb 100644 --- a/src/libos/src/net/msg_flags.rs +++ b/src/libos/src/net/socket/flags.rs @@ -34,3 +34,10 @@ bitflags! { const MSG_NOTIFICATION = 0x8000; // Only applicable to SCTP socket } } + +bitflags! { + pub struct FileFlags: i32 { + const SOCK_NONBLOCK = 0x800; + const SOCK_CLOEXEC = 0x80000; + } +} diff --git a/src/libos/src/net/socket/host_socket/host_socket.rs b/src/libos/src/net/socket/host_socket/host_socket.rs new file mode 100644 index 00000000..2fce4cd9 --- /dev/null +++ b/src/libos/src/net/socket/host_socket/host_socket.rs @@ -0,0 +1,132 @@ +use super::*; + +use crate::fs::{ + occlum_ocall_ioctl, AccessMode, CreationFlags, File, FileRef, IoctlCmd, StatusFlags, +}; +use std::any::Any; +use std::io::{Read, Seek, SeekFrom, Write}; +use std::mem; + +/// Native linux socket +#[derive(Debug)] +pub struct HostSocket { + host_fd: c_int, +} + +impl HostSocket { + pub fn new( + domain: AddressFamily, + socket_type: SocketType, + file_flags: FileFlags, + protocol: i32, + ) -> Result { + let host_fd = try_libc!(libc::ocall::socket( + domain as i32, + socket_type as i32 | file_flags.bits(), + protocol + )); + Ok(Self { host_fd }) + } + + pub fn host_fd(&self) -> c_int { + self.host_fd + } + + pub fn bind(&self, addr: &SockAddr) -> Result<()> { + let (addr_ptr, addr_len) = addr.as_ptr_and_len(); + + let ret = try_libc!(libc::ocall::bind( + self.host_fd(), + addr_ptr as *const libc::sockaddr, + addr_len as u32 + )); + Ok(()) + } + + pub fn listen(&self, backlog: i32) -> Result<()> { + let ret = try_libc!(libc::ocall::listen(self.host_fd(), backlog)); + Ok(()) + } + + pub fn accept(&self, flags: FileFlags) -> Result<(Self, Option)> { + let mut sockaddr = SockAddr::default(); + let mut addr_len = sockaddr.len(); + + let ret = try_libc!(libc::ocall::accept4( + self.host_fd(), + sockaddr.as_mut_ptr() as *mut _, + &mut addr_len as *mut _ as *mut _, + flags.bits() + )); + + let addr_option = if addr_len != 0 { + sockaddr.set_len(addr_len)?; + Some(sockaddr) + } else { + None + }; + Ok((Self { host_fd: ret }, addr_option)) + } + + pub fn connect(&self, addr: &Option) -> Result<()> { + debug!("host_fd: {} addr {:?}", self.host_fd(), addr); + + let (addr_ptr, addr_len) = if let Some(sock_addr) = addr { + sock_addr.as_ptr_and_len() + } else { + (std::ptr::null(), 0) + }; + + let ret = try_libc!(libc::ocall::connect( + self.host_fd(), + addr_ptr, + addr_len as u32 + )); + Ok(()) + } + + pub fn sendto( + &self, + buf: &[u8], + flags: SendFlags, + addr_option: &Option, + ) -> Result { + let bufs = vec![buf]; + let name_option = addr_option.as_ref().map(|addr| addr.as_slice()); + self.do_sendmsg(&bufs, flags, name_option, None) + } + + pub fn recvfrom(&self, buf: &mut [u8], flags: RecvFlags) -> Result<(usize, Option)> { + let mut sockaddr = SockAddr::default(); + let mut bufs = vec![buf]; + let (bytes_recv, addr_len, _, _) = + self.do_recvmsg(&mut bufs, flags, Some(sockaddr.as_mut_slice()), None)?; + + let addr_option = if addr_len != 0 { + sockaddr.set_len(addr_len)?; + Some(sockaddr) + } else { + None + }; + Ok((bytes_recv, addr_option)) + } +} + +impl Drop for HostSocket { + fn drop(&mut self) { + let ret = unsafe { libc::ocall::close(self.host_fd) }; + assert!(ret == 0); + } +} + +pub trait HostSocketType { + fn as_host_socket(&self) -> Result<&HostSocket>; +} + +impl HostSocketType for FileRef { + fn as_host_socket(&self) -> Result<&HostSocket> { + self.as_any() + .downcast_ref::() + .ok_or_else(|| errno!(EBADF, "not a host socket")) + } +} diff --git a/src/libos/src/net/socket_file/ioctl_impl.rs b/src/libos/src/net/socket/host_socket/ioctl_impl.rs similarity index 94% rename from src/libos/src/net/socket_file/ioctl_impl.rs rename to src/libos/src/net/socket/host_socket/ioctl_impl.rs index f799beb5..93577c5a 100644 --- a/src/libos/src/net/socket_file/ioctl_impl.rs +++ b/src/libos/src/net/socket/host_socket/ioctl_impl.rs @@ -1,7 +1,7 @@ use super::*; -use fs::{occlum_ocall_ioctl, BuiltinIoctlNum, IoctlCmd}; +use fs::{occlum_ocall_ioctl, BuiltinIoctlNum, IfConf, IoctlCmd}; -impl SocketFile { +impl HostSocket { pub(super) fn ioctl_impl(&self, cmd: &mut IoctlCmd) -> Result { if let IoctlCmd::SIOCGIFCONF(arg_ref) = cmd { return self.ioctl_getifconf(arg_ref); @@ -13,7 +13,7 @@ impl SocketFile { let mut retval: i32 = 0; let status = occlum_ocall_ioctl( &mut retval as *mut i32, - self.fd(), + self.host_fd(), cmd_num, cmd_arg_ptr, cmd.arg_len(), @@ -36,7 +36,7 @@ impl SocketFile { let mut retval: i32 = 0; let status = occlum_ocall_ioctl_repack( &mut retval as *mut i32, - self.fd(), + self.host_fd(), BuiltinIoctlNum::SIOCGIFCONF as i32, arg_ref.ifc_buf, arg_ref.ifc_len, diff --git a/src/libos/src/net/socket/host_socket/mod.rs b/src/libos/src/net/socket/host_socket/mod.rs new file mode 100644 index 00000000..8734b35e --- /dev/null +++ b/src/libos/src/net/socket/host_socket/mod.rs @@ -0,0 +1,9 @@ +use super::*; + +mod host_socket; +mod ioctl_impl; +mod recv; +mod send; +mod socket_file; + +pub use self::host_socket::{HostSocket, HostSocketType}; diff --git a/src/libos/src/net/socket_file/recv.rs b/src/libos/src/net/socket/host_socket/recv.rs similarity index 71% rename from src/libos/src/net/socket_file/recv.rs rename to src/libos/src/net/socket/host_socket/recv.rs index 33f3437b..167c8761 100644 --- a/src/libos/src/net/socket_file/recv.rs +++ b/src/libos/src/net/socket/host_socket/recv.rs @@ -1,45 +1,19 @@ use super::*; use crate::untrusted::{SliceAsMutPtrAndLen, SliceAsPtrAndLen, UntrustedSliceAlloc}; -impl SocketFile { - // TODO: need sockaddr type to implement send/sento - /* - pub fn recv(&self, buf: &mut [u8], flags: MsgHdrFlags) -> Result { - let (bytes_recvd, _) = self.recvfrom(buf, flags, None)?; +impl HostSocket { + pub fn recv(&self, buf: &mut [u8], flags: RecvFlags) -> Result { + let (bytes_recvd, _) = self.recvfrom(buf, flags)?; Ok(bytes_recvd) } - pub fn recvfrom(&self, buf: &mut [u8], flags: MsgHdrFlags, src_addr: Option<&mut [u8]>) -> Result<(usize, usize)> { - let (bytes_recvd, src_addr_len, _, _) = self.do_recvmsg( - &mut buf[..], - flags, - src_addr, - None, - )?; - Ok((bytes_recvd, src_addr_len)) - }*/ - pub fn recvmsg<'a, 'b>(&self, msg: &'b mut MsgHdrMut<'a>, flags: RecvFlags) -> Result { - // Alloc untrusted iovecs to receive data via OCall - let msg_iov = msg.get_iovs(); - let u_slice_alloc = UntrustedSliceAlloc::new(msg_iov.total_bytes())?; - let mut u_slices = msg_iov - .as_slices() - .iter() - .map(|slice| { - u_slice_alloc - .new_slice_mut(slice.len()) - .expect("unexpected out of memory error in UntrustedSliceAlloc") - }) - .collect(); - let mut u_iovs = IovsMut::new(u_slices); - // Do OCall-based recvmsg let (bytes_recvd, namelen_recvd, controllen_recvd, flags_recvd) = { // Acquire mutable references to the name and control buffers - let (name, control) = msg.get_name_and_control_mut(); + let (iovs, name, control) = msg.get_iovs_name_and_control_mut(); // Fill the data, the name, and the control buffers - self.do_recvmsg(u_iovs.as_slices_mut(), flags, name, control)? + self.do_recvmsg(iovs.as_slices_mut(), flags, name, control)? }; // Update the output lengths and flags @@ -47,19 +21,39 @@ impl SocketFile { msg.set_control_len(controllen_recvd)?; msg.set_flags(flags_recvd); - // Copy data from untrusted iovecs into the output iovecs - let mut msg_iov = msg.get_iovs_mut(); - let mut u_iovs_iter = u_iovs - .as_slices() - .iter() - .flat_map(|slice| slice.iter()) - .take(bytes_recvd); - msg_iov.copy_from_iter(&mut u_iovs_iter); - Ok(bytes_recvd) } - fn do_recvmsg( + pub(super) fn do_recvmsg( + &self, + data: &mut [&mut [u8]], + flags: RecvFlags, + mut name: Option<&mut [u8]>, + mut control: Option<&mut [u8]>, + ) -> Result<(usize, usize, usize, MsgHdrFlags)> { + let data_length = data.iter().map(|s| s.len()).sum(); + let u_allocator = UntrustedSliceAlloc::new(data_length)?; + let mut u_data = { + let mut bufs = Vec::new(); + for ref buf in data.iter() { + bufs.push(u_allocator.new_slice_mut(buf.len())?); + } + bufs + }; + let retval = self.do_recvmsg_untrusted_data(&mut u_data, flags, name, control)?; + + let mut copied = 0; + for (i, buf) in data.iter_mut().enumerate() { + buf.copy_from_slice(u_data[i]); + copied += buf.len(); + if copied >= retval.0 { + break; + } + } + Ok(retval) + } + + fn do_recvmsg_untrusted_data( &self, data: &mut [&mut [u8]], flags: RecvFlags, @@ -68,7 +62,7 @@ impl SocketFile { ) -> Result<(usize, usize, usize, MsgHdrFlags)> { // Prepare the arguments for OCall // Host socket fd - let host_fd = self.host_fd; + let host_fd = self.host_fd(); // Name let (msg_name, msg_namelen) = name.as_mut_ptr_and_len(); let msg_name = msg_name as *mut c_void; diff --git a/src/libos/src/net/socket_file/send.rs b/src/libos/src/net/socket/host_socket/send.rs similarity index 63% rename from src/libos/src/net/socket_file/send.rs rename to src/libos/src/net/socket/host_socket/send.rs index d3594633..68570d40 100644 --- a/src/libos/src/net/socket_file/send.rs +++ b/src/libos/src/net/socket/host_socket/send.rs @@ -1,56 +1,57 @@ use super::*; -impl SocketFile { - // TODO: need sockaddr type to implement send/sento - /* - pub fn send(&self, buf: &[u8], flags: MsgFlags) -> Result { - self.sendto(buf, flags, None) +impl HostSocket { + pub fn send(&self, buf: &[u8], flags: SendFlags) -> Result { + self.sendto(buf, flags, &None) } - pub fn sendto(&self, buf: &[u8], flags: MsgFlags, dest_addr: Option<&[u8]>) -> Result { - Self::do_sendmsg( - self.host_fd, - &buf[..], - flags, - dest_addr, - None) - } - */ - pub fn sendmsg<'a, 'b>(&self, msg: &'b MsgHdr<'a>, flags: SendFlags) -> Result { - // Copy message's iovecs into untrusted iovecs let msg_iov = msg.get_iovs(); - let u_slice_alloc = UntrustedSliceAlloc::new(msg_iov.total_bytes())?; - let u_slices = msg_iov - .as_slices() - .iter() - .map(|src_slice| { - u_slice_alloc - .new_slice(src_slice) - .expect("unexpected out of memory") - }) - .collect(); - let u_iovs = Iovs::new(u_slices); - self.do_sendmsg(u_iovs.as_slices(), flags, msg.get_name(), msg.get_control()) + self.do_sendmsg( + msg_iov.as_slices(), + flags, + msg.get_name(), + msg.get_control(), + ) } - fn do_sendmsg( + pub(super) fn do_sendmsg( &self, data: &[&[u8]], flags: SendFlags, name: Option<&[u8]>, control: Option<&[u8]>, + ) -> Result { + let data_length = data.iter().map(|s| s.len()).sum(); + let u_allocator = UntrustedSliceAlloc::new(data_length)?; + let u_data = { + let mut bufs = Vec::new(); + for buf in data { + bufs.push(u_allocator.new_slice(buf)?); + } + bufs + }; + + self.do_sendmsg_untrusted_data(&u_data, flags, name, control) + } + + fn do_sendmsg_untrusted_data( + &self, + u_data: &[&[u8]], + flags: SendFlags, + name: Option<&[u8]>, + control: Option<&[u8]>, ) -> Result { // Prepare the arguments for OCall let mut retval: isize = 0; // Host socket fd - let host_fd = self.host_fd; + let host_fd = self.host_fd(); // Name let (msg_name, msg_namelen) = name.as_ptr_and_len(); let msg_name = msg_name as *const c_void; // Iovs - let raw_iovs: Vec = data.iter().map(|slice| slice.as_libc_iovec()).collect(); + let raw_iovs: Vec = u_data.iter().map(|slice| slice.as_libc_iovec()).collect(); let (msg_iov, msg_iovlen) = raw_iovs.as_slice().as_ptr_and_len(); // Control let (msg_control, msg_controllen) = control.as_ptr_and_len(); @@ -73,7 +74,6 @@ impl SocketFile { ); assert!(status == sgx_status_t::SGX_SUCCESS); } - let bytes_sent = if flags.contains(SendFlags::MSG_NOSIGNAL) { try_libc!(retval) } else { diff --git a/src/libos/src/net/socket/host_socket/socket_file.rs b/src/libos/src/net/socket/host_socket/socket_file.rs new file mode 100644 index 00000000..2955907c --- /dev/null +++ b/src/libos/src/net/socket/host_socket/socket_file.rs @@ -0,0 +1,77 @@ +use super::*; + +use crate::fs::{ + occlum_ocall_ioctl, AccessMode, CreationFlags, File, FileRef, IoctlCmd, StatusFlags, +}; +use std::any::Any; +use std::io::{Read, Seek, SeekFrom, Write}; + +//TODO: refactor write syscall to allow zero length with non-zero buffer +impl File for HostSocket { + fn read(&self, buf: &mut [u8]) -> Result { + self.recv(buf, RecvFlags::empty()) + } + + fn write(&self, buf: &[u8]) -> Result { + self.send(buf, SendFlags::empty()) + } + + fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result { + if offset != 0 { + return_errno!(ESPIPE, "a nonzero position is not supported"); + } + self.read(buf) + } + + fn write_at(&self, offset: usize, buf: &[u8]) -> Result { + if offset != 0 { + return_errno!(ESPIPE, "a nonzero position is not supported"); + } + self.write(buf) + } + + fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { + let (bytes_recvd, _, _, _) = self.do_recvmsg(bufs, RecvFlags::empty(), None, None)?; + Ok(bytes_recvd) + } + + fn writev(&self, bufs: &[&[u8]]) -> Result { + self.do_sendmsg(bufs, SendFlags::empty(), None, None) + } + + fn seek(&self, pos: SeekFrom) -> Result { + return_errno!(ESPIPE, "Socket does not support seek") + } + + fn ioctl(&self, cmd: &mut IoctlCmd) -> Result { + self.ioctl_impl(cmd) + } + + fn get_access_mode(&self) -> Result { + Ok(AccessMode::O_RDWR) + } + + fn get_status_flags(&self) -> Result { + let ret = try_libc!(libc::ocall::fcntl_arg0(self.host_fd(), libc::F_GETFL)); + Ok(StatusFlags::from_bits_truncate(ret as u32)) + } + + fn set_status_flags(&self, new_status_flags: StatusFlags) -> Result<()> { + let valid_flags_mask = StatusFlags::O_APPEND + | StatusFlags::O_ASYNC + | StatusFlags::O_DIRECT + | StatusFlags::O_NOATIME + | StatusFlags::O_NONBLOCK; + let raw_status_flags = (new_status_flags & valid_flags_mask).bits(); + try_libc!(libc::ocall::fcntl_arg1( + self.host_fd(), + libc::F_SETFL, + raw_status_flags as c_int + )); + Ok(()) + } + + fn as_any(&self) -> &dyn Any { + self + } +} diff --git a/src/libos/src/net/iovs.rs b/src/libos/src/net/socket/iovs.rs similarity index 100% rename from src/libos/src/net/iovs.rs rename to src/libos/src/net/socket/iovs.rs diff --git a/src/libos/src/net/socket/mod.rs b/src/libos/src/net/socket/mod.rs new file mode 100644 index 00000000..dab297ef --- /dev/null +++ b/src/libos/src/net/socket/mod.rs @@ -0,0 +1,19 @@ +use super::*; + +mod address_family; +mod flags; +mod host_socket; +mod iovs; +mod msg; +mod socket_address; +mod socket_type; +mod unix_socket; + +pub use self::address_family::AddressFamily; +pub use self::flags::{FileFlags, MsgHdrFlags, RecvFlags, SendFlags}; +pub use self::host_socket::{HostSocket, HostSocketType}; +pub use self::iovs::{Iovs, IovsMut, SliceAsLibcIovec}; +pub use self::msg::{msghdr, msghdr_mut, MsgHdr, MsgHdrMut}; +pub use self::socket_address::SockAddr; +pub use self::socket_type::SocketType; +pub use self::unix_socket::{AsUnixSocket, UnixSocketFile}; diff --git a/src/libos/src/net/msg.rs b/src/libos/src/net/socket/msg.rs similarity index 97% rename from src/libos/src/net/msg.rs rename to src/libos/src/net/socket/msg.rs index 92433d55..455508b8 100644 --- a/src/libos/src/net/msg.rs +++ b/src/libos/src/net/socket/msg.rs @@ -196,8 +196,11 @@ impl<'a> MsgHdrMut<'a> { Ok(()) } - pub fn get_name_and_control_mut(&mut self) -> (Option<&mut [u8]>, Option<&mut [u8]>) { + pub fn get_iovs_name_and_control_mut( + &mut self, + ) -> (&mut IovsMut<'a>, Option<&mut [u8]>, Option<&mut [u8]>) { ( + &mut self.iovs, self.name.as_mut().map(|name| &mut name[..]), self.control.as_mut().map(|control| &mut control[..]), ) diff --git a/src/libos/src/net/socket/socket_address.rs b/src/libos/src/net/socket/socket_address.rs new file mode 100644 index 00000000..13612898 --- /dev/null +++ b/src/libos/src/net/socket/socket_address.rs @@ -0,0 +1,121 @@ +use super::*; +use std::*; + +#[derive(Copy, Clone)] +pub struct SockAddr { + storage: libc::sockaddr_storage, + len: usize, +} + +// TODO: add more fields +impl fmt::Debug for SockAddr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SockAddr") + .field( + "family", + &AddressFamily::try_from(self.storage.ss_family).unwrap(), + ) + .field("len", &self.len) + .finish() + } +} + +impl SockAddr { + // Caller should guarentee the sockaddr and addr_len are valid + pub unsafe fn try_from_raw( + sockaddr: *const libc::sockaddr, + addr_len: libc::socklen_t, + ) -> Result { + if addr_len < std::mem::size_of::() as u32 { + return_errno!(EINVAL, "the address is too short."); + } + + if addr_len > std::mem::size_of::() as u32 { + return_errno!(EINVAL, "the address is too long."); + } + + match AddressFamily::try_from((*sockaddr).sa_family)? { + AddressFamily::INET => { + if addr_len < std::mem::size_of::() as u32 { + return_errno!(EINVAL, "short ipv4 address."); + } + } + AddressFamily::INET6 => { + let ipv6_addr_len = std::mem::size_of::() as u32; + // Omit sin6_scope_id when it is not fully provided + // 4 represents the size of sin6_scope_id which is not a must + if addr_len < ipv6_addr_len - 4 { + return_errno!(EINVAL, "wrong ipv6 address length."); + } + } + _ => warn!("address family not checked"), + } + + let mut storage = mem::MaybeUninit::::uninit(); + ptr::copy_nonoverlapping( + sockaddr as *const _ as *const u8, + storage.as_mut_ptr() as *mut u8, + addr_len as usize, + ); + Ok(Self { + storage: storage.assume_init(), + len: addr_len as usize, + }) + } + + pub fn as_ptr_and_len(&self) -> (*const libc::sockaddr, usize) { + (self.as_ptr(), self.len()) + } + + pub fn as_ptr(&self) -> *const libc::sockaddr { + &self.storage as *const _ as *const _ + } + + pub fn as_mut_ptr(&mut self) -> *mut libc::sockaddr { + &mut self.storage as *mut _ as *mut _ + } + + pub fn as_slice(&self) -> &[u8] { + unsafe { std::slice::from_raw_parts(self.as_ptr() as *const u8, self.len()) } + } + + pub fn as_mut_slice(&mut self) -> &mut [u8] { + unsafe { std::slice::from_raw_parts_mut(self.as_mut_ptr() as *mut u8, self.len()) } + } + + pub fn copy_to_slice(&self, dst: &mut [u8]) -> usize { + let (addr_ptr, addr_len) = self.as_ptr_and_len(); + let copy_len = std::cmp::min(addr_len, dst.len()); + dst[0..copy_len].copy_from_slice(unsafe { + std::slice::from_raw_parts(addr_ptr as *const u8, copy_len) + }); + copy_len + } + + pub fn len(&self) -> usize { + self.len + } + + pub fn set_len(&mut self, len: usize) -> Result<()> { + if len > Self::capacity() { + return_errno!(EINVAL, "length is too long") + } else { + self.len = len; + Ok(()) + } + } + + pub fn capacity() -> usize { + mem::size_of::() + } +} + +impl Default for SockAddr { + fn default() -> Self { + let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() }; + Self { + storage: storage, + len: mem::size_of::(), + } + } +} diff --git a/src/libos/src/net/socket/socket_type.rs b/src/libos/src/net/socket/socket_type.rs new file mode 100644 index 00000000..af1744a0 --- /dev/null +++ b/src/libos/src/net/socket/socket_type.rs @@ -0,0 +1,29 @@ +use super::*; + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[repr(i32)] +#[allow(non_camel_case_types)] +pub enum SocketType { + STREAM = 1, + DGRAM = 2, + RAW = 3, + RDM = 4, + SEQPACKET = 5, + DCCP = 6, + PACKET = 10, +} + +impl SocketType { + pub fn try_from(sock_type: i32) -> Result { + match sock_type { + 1 => Ok(SocketType::STREAM), + 2 => Ok(SocketType::DGRAM), + 3 => Ok(SocketType::RAW), + 4 => Ok(SocketType::RDM), + 5 => Ok(SocketType::SEQPACKET), + 6 => Ok(SocketType::DCCP), + 10 => Ok(SocketType::PACKET), + _ => return_errno!(EINVAL, "invalid socket type"), + } + } +} diff --git a/src/libos/src/net/unix_socket.rs b/src/libos/src/net/socket/unix_socket.rs similarity index 100% rename from src/libos/src/net/unix_socket.rs rename to src/libos/src/net/socket/unix_socket.rs diff --git a/src/libos/src/net/socket_file/mod.rs b/src/libos/src/net/socket_file/mod.rs deleted file mode 100644 index 243e8d77..00000000 --- a/src/libos/src/net/socket_file/mod.rs +++ /dev/null @@ -1,154 +0,0 @@ -use super::*; -use crate::fs::IfConf; - -mod ioctl_impl; -mod recv; -mod send; - -use fs::{AccessMode, CreationFlags, File, FileRef, IoctlCmd, StatusFlags}; -use std::any::Any; -use std::io::{Read, Seek, SeekFrom, Write}; - -/// Native Linux socket -#[derive(Debug)] -pub struct SocketFile { - host_fd: c_int, -} - -impl SocketFile { - pub fn new(domain: c_int, socket_type: c_int, protocol: c_int) -> Result { - let ret = try_libc!(libc::ocall::socket(domain, socket_type, protocol)); - Ok(SocketFile { host_fd: ret }) - } - - pub fn accept( - &self, - addr: *mut libc::sockaddr, - addr_len: *mut libc::socklen_t, - flags: c_int, - ) -> Result { - let ret = try_libc!(libc::ocall::accept4(self.host_fd, addr, addr_len, flags)); - Ok(SocketFile { host_fd: ret }) - } - - pub fn fd(&self) -> c_int { - self.host_fd - } -} - -impl Drop for SocketFile { - fn drop(&mut self) { - let ret = unsafe { libc::ocall::close(self.host_fd) }; - assert!(ret == 0); - } -} - -// TODO: rewrite read/write/readv/writev as send/recv -// TODO: implement readfrom/sendto -impl File for SocketFile { - fn read(&self, buf: &mut [u8]) -> Result { - let (buf_ptr, buf_len) = buf.as_mut().as_mut_ptr_and_len(); - let ret = try_libc!(libc::ocall::read( - self.host_fd, - buf_ptr as *mut c_void, - buf_len - )) as usize; - assert!(ret <= buf_len); - Ok(ret) - } - - fn write(&self, buf: &[u8]) -> Result { - let (buf_ptr, buf_len) = buf.as_ptr_and_len(); - let ret = try_libc_may_epipe!(libc::ocall::write( - self.host_fd, - buf_ptr as *const c_void, - buf_len - )) as usize; - assert!(ret <= buf_len); - Ok(ret) - } - - fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result { - self.read(buf) - } - - fn write_at(&self, _offset: usize, buf: &[u8]) -> Result { - self.write(buf) - } - - fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { - let mut total_len = 0; - for buf in bufs { - match self.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 { - let mut total_len = 0; - for buf in bufs { - match self.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 { - return_errno!(ESPIPE, "Socket does not support seek") - } - - fn ioctl(&self, cmd: &mut IoctlCmd) -> Result { - self.ioctl_impl(cmd) - } - - fn get_access_mode(&self) -> Result { - Ok(AccessMode::O_RDWR) - } - - fn get_status_flags(&self) -> Result { - let ret = try_libc!(libc::ocall::fcntl_arg0(self.fd(), libc::F_GETFL)); - Ok(StatusFlags::from_bits_truncate(ret as u32)) - } - - fn set_status_flags(&self, new_status_flags: StatusFlags) -> Result<()> { - let valid_flags_mask = StatusFlags::O_APPEND - | StatusFlags::O_ASYNC - | StatusFlags::O_DIRECT - | StatusFlags::O_NOATIME - | StatusFlags::O_NONBLOCK; - let raw_status_flags = (new_status_flags & valid_flags_mask).bits(); - try_libc!(libc::ocall::fcntl_arg1( - self.fd(), - libc::F_SETFL, - raw_status_flags as c_int - )); - Ok(()) - } - - fn as_any(&self) -> &dyn Any { - self - } -} - -pub trait AsSocket { - fn as_socket(&self) -> Result<&SocketFile>; -} - -impl AsSocket for FileRef { - fn as_socket(&self) -> Result<&SocketFile> { - self.as_any() - .downcast_ref::() - .ok_or_else(|| errno!(EBADF, "not a socket")) - } -} diff --git a/src/libos/src/net/syscalls.rs b/src/libos/src/net/syscalls.rs index 94ecdeeb..21275120 100644 --- a/src/libos/src/net/syscalls.rs +++ b/src/libos/src/net/syscalls.rs @@ -9,50 +9,87 @@ use time::timeval_t; use util::mem_util::from_user; pub fn do_socket(domain: c_int, socket_type: c_int, protocol: c_int) -> Result { - debug!( - "socket: domain: {}, socket_type: 0x{:x}, protocol: {}", - domain, socket_type, protocol - ); + let sock_domain = AddressFamily::try_from(domain as u16)?; + let file_flags = FileFlags::from_bits_truncate(socket_type); + let sock_type = SocketType::try_from(socket_type & (!file_flags.bits()))?; - let file_ref: Arc> = match domain { - libc::AF_LOCAL => { + let file_ref: Arc> = match sock_domain { + AddressFamily::LOCAL => { let unix_socket = UnixSocketFile::new(socket_type, protocol)?; Arc::new(Box::new(unix_socket)) } _ => { - let socket = SocketFile::new(domain, socket_type, protocol)?; + let socket = HostSocket::new(sock_domain, sock_type, file_flags, protocol)?; Arc::new(Box::new(socket)) } }; - let fd = current!().add_file(file_ref, false); + let close_on_spawn = file_flags.contains(FileFlags::SOCK_CLOEXEC); + let fd = current!().add_file(file_ref, close_on_spawn); Ok(fd as isize) } +pub fn do_bind(fd: c_int, addr: *const libc::sockaddr, addr_len: libc::socklen_t) -> Result { + if addr.is_null() || addr_len == 0 { + return_errno!(EINVAL, "no address is specified"); + } + from_user::check_array(addr as *const u8, addr_len as usize)?; + + let sock_addr = unsafe { SockAddr::try_from_raw(addr, addr_len)? }; + trace!("bind to addr: {:?}", sock_addr); + + let file_ref = current!().file(fd as FileDesc)?; + if let Ok(socket) = file_ref.as_host_socket() { + socket.bind(&sock_addr)?; + } else if let Ok(unix_socket) = file_ref.as_unix_socket() { + let addr = addr as *const libc::sockaddr_un; + from_user::check_ptr(addr)?; + let path = from_user::clone_cstring_safely(unsafe { (&*addr).sun_path.as_ptr() })? + .to_string_lossy() + .into_owned(); + unix_socket.bind(path)?; + } else { + return_errno!(EBADF, "not a socket"); + } + + Ok(0) +} + +pub fn do_listen(fd: c_int, backlog: c_int) -> Result { + let file_ref = current!().file(fd as FileDesc)?; + if let Ok(socket) = file_ref.as_host_socket() { + socket.listen(backlog)?; + } else if let Ok(unix_socket) = file_ref.as_unix_socket() { + unix_socket.listen()?; + } else { + return_errno!(EBADF, "not a socket"); + } + + Ok(0) +} + pub fn do_connect( fd: c_int, addr: *const libc::sockaddr, addr_len: libc::socklen_t, ) -> Result { - debug!( - "connect: fd: {}, addr: {:?}, addr_len: {}", - fd, addr, addr_len - ); // For SOCK_DGRAM sockets not initiated in connection-mode, // if address is a null address for the protocol, // the socket's peer address shall be reset. - let need_check: bool = !addr.is_null(); - if need_check { + let addr_set: bool = !addr.is_null(); + if addr_set { from_user::check_array(addr as *const u8, addr_len as usize)?; } + let addr_option = if addr_set { + Some(unsafe { SockAddr::try_from_raw(addr, addr_len)? }) + } else { + None + }; + let file_ref = current!().file(fd as FileDesc)?; - if let Ok(socket) = file_ref.as_socket() { - if need_check { - from_user::check_ptr(addr as *const libc::sockaddr_in)?; - } - let ret = try_libc!(libc::ocall::connect(socket.fd(), addr, addr_len)); - Ok(ret as isize) + if let Ok(socket) = file_ref.as_host_socket() { + socket.connect(&addr_option)?; } else if let Ok(unix_socket) = file_ref.as_unix_socket() { let addr = addr as *const libc::sockaddr_un; from_user::check_ptr(addr)?; @@ -60,10 +97,11 @@ pub fn do_connect( .to_string_lossy() .into_owned(); unix_socket.connect(path)?; - Ok(0) } else { return_errno!(EBADF, "not a socket") } + + Ok(0) } pub fn do_accept( @@ -80,93 +118,55 @@ pub fn do_accept4( addr_len: *mut libc::socklen_t, flags: c_int, ) -> Result { - debug!( - "accept4: fd: {}, addr: {:?}, addr_len: {:?}, flags: {:#x}", - fd, addr, addr_len, flags - ); - - let need_check: bool = !addr.is_null(); - - if addr.is_null() ^ addr_len.is_null() { - return_errno!(EINVAL, "addr and ddr_len should be both null"); - } - if need_check { + let addr_set: bool = !addr.is_null(); + if addr_set { + from_user::check_ptr(addr_len)?; from_user::check_mut_array(addr as *mut u8, unsafe { *addr_len } as usize)?; } + let file_flags = FileFlags::from_bits(flags).ok_or_else(|| errno!(EINVAL, "invalid flags"))?; + let close_on_spawn = file_flags.contains(FileFlags::SOCK_CLOEXEC); + let file_ref = current!().file(fd as FileDesc)?; - if let Ok(socket) = file_ref.as_socket() { - if need_check { - from_user::check_mut_ptr(addr as *mut libc::sockaddr_in)?; + let new_fd = if let Ok(socket) = file_ref.as_host_socket() { + let (new_socket_file, sock_addr_option) = socket.accept(file_flags)?; + let new_file_ref: Arc> = Arc::new(Box::new(new_socket_file)); + let new_fd = current!().add_file(new_file_ref, close_on_spawn); + + if addr_set && sock_addr_option.is_some() { + let sock_addr = sock_addr_option.unwrap(); + let mut buf = + unsafe { std::slice::from_raw_parts_mut(addr as *mut u8, *addr_len as usize) }; + sock_addr.copy_to_slice(&mut buf); + unsafe { + *addr_len = sock_addr.len() as u32; + } } - - let new_socket = socket.accept(addr, addr_len, flags)?; - let new_file_ref: Arc> = Arc::new(Box::new(new_socket)); - let new_fd = current!().add_file(new_file_ref, false); - - Ok(new_fd as isize) + new_fd } else if let Ok(unix_socket) = file_ref.as_unix_socket() { let addr = addr as *mut libc::sockaddr_un; - if need_check { + if addr_set { from_user::check_mut_ptr(addr)?; } // TODO: handle addr let new_socket = unix_socket.accept()?; let new_file_ref: Arc> = Arc::new(Box::new(new_socket)); - let new_fd = current!().add_file(new_file_ref, false); - - Ok(new_fd as isize) + current!().add_file(new_file_ref, false) } else { - return_errno!(EBADF, "not a socket") - } + return_errno!(EBADF, "not a socket"); + }; + + Ok(new_fd as isize) } pub fn do_shutdown(fd: c_int, how: c_int) -> Result { debug!("shutdown: fd: {}, how: {}", fd, how); let file_ref = current!().file(fd as FileDesc)?; - if let Ok(socket) = file_ref.as_socket() { - let ret = try_libc!(libc::ocall::shutdown(socket.fd(), how)); + if let Ok(socket) = file_ref.as_host_socket() { + let ret = try_libc!(libc::ocall::shutdown(socket.host_fd(), how)); Ok(ret as isize) } else { - return_errno!(EBADF, "not a socket") - } -} - -pub fn do_bind(fd: c_int, addr: *const libc::sockaddr, addr_len: libc::socklen_t) -> Result { - debug!("bind: fd: {}, addr: {:?}, addr_len: {}", fd, addr, addr_len); - if addr.is_null() && addr_len == 0 { - return_errno!(EINVAL, "no address is specified"); - } - from_user::check_array(addr as *const u8, addr_len as usize)?; - - let file_ref = current!().file(fd as FileDesc)?; - if let Ok(socket) = file_ref.as_socket() { - from_user::check_ptr(addr as *const libc::sockaddr_in)?; - let ret = try_libc!(libc::ocall::bind(socket.fd(), addr, addr_len)); - Ok(ret as isize) - } else if let Ok(unix_socket) = file_ref.as_unix_socket() { - let addr = addr as *const libc::sockaddr_un; - from_user::check_ptr(addr)?; - let path = from_user::clone_cstring_safely(unsafe { (&*addr).sun_path.as_ptr() })? - .to_string_lossy() - .into_owned(); - unix_socket.bind(path)?; - Ok(0) - } else { - return_errno!(EBADF, "not a socket") - } -} - -pub fn do_listen(fd: c_int, backlog: c_int) -> Result { - debug!("listen: fd: {}, backlog: {}", fd, backlog); - let file_ref = current!().file(fd as FileDesc)?; - if let Ok(socket) = file_ref.as_socket() { - let ret = try_libc!(libc::ocall::listen(socket.fd(), backlog)); - Ok(ret as isize) - } else if let Ok(unix_socket) = file_ref.as_unix_socket() { - unix_socket.listen()?; - Ok(0) - } else { + // TODO: support unix socket return_errno!(EBADF, "not a socket") } } @@ -183,9 +183,9 @@ pub fn do_setsockopt( fd, level, optname, optval, optlen ); let file_ref = current!().file(fd as FileDesc)?; - if let Ok(socket) = file_ref.as_socket() { + if let Ok(socket) = file_ref.as_host_socket() { let ret = try_libc!(libc::ocall::setsockopt( - socket.fd(), + socket.host_fd(), level, optname, optval, @@ -212,10 +212,10 @@ pub fn do_getsockopt( fd, level, optname, optval, optlen ); let file_ref = current!().file(fd as FileDesc)?; - let socket = file_ref.as_socket()?; + let socket = file_ref.as_host_socket()?; let ret = try_libc!(libc::ocall::getsockopt( - socket.fd(), + socket.host_fd(), level, optname, optval, @@ -234,8 +234,8 @@ pub fn do_getpeername( fd, addr, addr_len ); let file_ref = current!().file(fd as FileDesc)?; - if let Ok(socket) = file_ref.as_socket() { - let ret = try_libc!(libc::ocall::getpeername(socket.fd(), addr, addr_len)); + if let Ok(socket) = file_ref.as_host_socket() { + let ret = try_libc!(libc::ocall::getpeername(socket.host_fd(), addr, addr_len)); Ok(ret as isize) } else if let Ok(unix_socket) = file_ref.as_unix_socket() { warn!("getpeername for unix socket is unimplemented"); @@ -258,8 +258,8 @@ pub fn do_getsockname( fd, addr, addr_len ); let file_ref = current!().file(fd as FileDesc)?; - if let Ok(socket) = file_ref.as_socket() { - let ret = try_libc!(libc::ocall::getsockname(socket.fd(), addr, addr_len)); + if let Ok(socket) = file_ref.as_host_socket() { + let ret = try_libc!(libc::ocall::getsockname(socket.host_fd(), addr, addr_len)); Ok(ret as isize) } else if let Ok(unix_socket) = file_ref.as_unix_socket() { warn!("getsockname for unix socket is unimplemented"); @@ -277,29 +277,36 @@ pub fn do_sendto( addr: *const libc::sockaddr, addr_len: libc::socklen_t, ) -> Result { - debug!( - "sendto: fd: {}, base: {:?}, len: {}, flags: {} addr: {:?}, addr_len: {}", - fd, base, len, flags, addr, addr_len - ); + if len == 0 { + return Ok(0); + } + + if addr.is_null() ^ (addr_len == 0) { + return_errno!(EINVAL, "addr and ddr_len should be both null"); + } + from_user::check_array(base as *const u8, len)?; + let buf = unsafe { std::slice::from_raw_parts(base as *const u8, len as usize) }; + + let addr_set: bool = !addr.is_null(); + if addr_set { + from_user::check_mut_array(addr as *mut u8, addr_len as usize)?; + } + + let send_flags = SendFlags::from_bits(flags).unwrap(); + + let addr_option = if addr_set { + Some(unsafe { SockAddr::try_from_raw(addr, addr_len)? }) + } else { + None + }; let file_ref = current!().file(fd as FileDesc)?; - if let Ok(socket) = file_ref.as_socket() { - // TODO: check addr and addr_len according to connection mode - let ret = try_libc_may_epipe!(libc::ocall::sendto( - socket.fd(), - base, - len, - flags, - addr, - addr_len - )); - Ok(ret as isize) + if let Ok(socket) = file_ref.as_host_socket() { + socket + .sendto(buf, send_flags, &addr_option) + .map(|u| u as isize) } else if let Ok(unix) = file_ref.as_unix_socket() { - if !addr.is_null() || addr_len != 0 { - return_errno!(EISCONN, "Only connection-mode socket is supported"); - } - if !unix.is_connected() { return_errno!(ENOTCONN, "the socket has not been connected yet"); } @@ -319,22 +326,42 @@ pub fn do_recvfrom( addr: *mut libc::sockaddr, addr_len: *mut libc::socklen_t, ) -> Result { - debug!( - "recvfrom: fd: {}, base: {:?}, len: {}, flags: {}, addr: {:?}, addr_len: {:?}", - fd, base, len, flags, addr, addr_len - ); - let file_ref = current!().file(fd as FileDesc)?; - let socket = file_ref.as_socket()?; + if addr.is_null() ^ addr_len.is_null() { + return_errno!(EINVAL, "addr and ddr_len should be both null"); + } - let ret = try_libc!(libc::ocall::recvfrom( - socket.fd(), - base, - len, - flags, - addr, - addr_len - )); - Ok(ret as isize) + from_user::check_array(base as *mut u8, len)?; + let mut buf = unsafe { std::slice::from_raw_parts_mut(base as *mut u8, len as usize) }; + + // MSG_CTRUNC is a return flag but linux allows it to be set on input flags. + // We just ignore it. + let recv_flags = RecvFlags::from_bits(flags & !(MsgHdrFlags::MSG_CTRUNC.bits())) + .ok_or_else(|| errno!(EINVAL, "invalid flags"))?; + + let addr_set: bool = !addr.is_null(); + if addr_set { + from_user::check_ptr(addr_len)?; + from_user::check_mut_array(addr as *mut u8, unsafe { *addr_len } as usize)?; + } + + let file_ref = current!().file(fd as FileDesc)?; + let (data_len, sock_addr_option) = if let Ok(socket) = file_ref.as_host_socket() { + socket.recvfrom(buf, recv_flags)? + } else { + return_errno!(EBADF, "not a socket"); + }; + + if addr_set && sock_addr_option.is_some() { + let sock_addr = sock_addr_option.unwrap(); + let mut buf = + unsafe { std::slice::from_raw_parts_mut(addr as *mut u8, *addr_len as usize) }; + sock_addr.copy_to_slice(&mut buf); + unsafe { + *addr_len = sock_addr.len() as u32; + } + } + + Ok(data_len as isize) } pub fn do_socketpair( @@ -343,27 +370,26 @@ pub fn do_socketpair( protocol: c_int, sv: *mut c_int, ) -> Result { - debug!( - "socketpair: domain: {}, type:0x{:x}, protocol: {}", - domain, socket_type, protocol - ); let mut sock_pair = unsafe { from_user::check_mut_array(sv, 2)?; std::slice::from_raw_parts_mut(sv as *mut u32, 2) }; - if (domain == libc::AF_UNIX) { + let file_flags = FileFlags::from_bits_truncate(socket_type); + let close_on_spawn = file_flags.contains(FileFlags::SOCK_CLOEXEC); + + let domain = AddressFamily::try_from(domain as u16)?; + if (domain == AddressFamily::LOCAL) { let (client_socket, server_socket) = UnixSocketFile::socketpair(socket_type as i32, protocol as i32)?; + let current = current!(); let mut files = current.files().lock().unwrap(); - sock_pair[0] = files.put(Arc::new(Box::new(client_socket)), false); - sock_pair[1] = files.put(Arc::new(Box::new(server_socket)), false); + sock_pair[0] = files.put(Arc::new(Box::new(client_socket)), close_on_spawn); + sock_pair[1] = files.put(Arc::new(Box::new(server_socket)), close_on_spawn); debug!("socketpair: ({}, {})", sock_pair[0], sock_pair[1]); Ok(0) - } else if (domain == libc::AF_TIPC) { - return_errno!(EAFNOSUPPORT, "cluster domain sockets not supported") } else { return_errno!(EAFNOSUPPORT, "domain not supported") } @@ -376,7 +402,7 @@ pub fn do_sendmsg(fd: c_int, msg_ptr: *const msghdr, flags_c: c_int) -> Result Re ); let file_ref = current!().file(fd as FileDesc)?; - if let Ok(socket) = file_ref.as_socket() { + if let Ok(socket) = file_ref.as_host_socket() { let msg_mut_c = { from_user::check_mut_ptr(msg_mut_ptr)?; let msg_mut_c = unsafe { &mut *msg_mut_ptr }; diff --git a/src/libos/src/syscall/mod.rs b/src/libos/src/syscall/mod.rs index 35e15766..8e54f91d 100644 --- a/src/libos/src/syscall/mod.rs +++ b/src/libos/src/syscall/mod.rs @@ -37,8 +37,7 @@ use crate::net::{ do_accept, do_accept4, do_bind, do_connect, do_epoll_create, do_epoll_create1, do_epoll_ctl, do_epoll_pwait, do_epoll_wait, do_getpeername, do_getsockname, do_getsockopt, do_listen, do_poll, do_recvfrom, do_recvmsg, do_select, do_sendmsg, do_sendto, do_setsockopt, do_shutdown, - do_socket, do_socketpair, msghdr, msghdr_mut, AsSocket, AsUnixSocket, EpollEvent, PollEvent, - SocketFile, UnixSocketFile, + do_socket, do_socketpair, msghdr, msghdr_mut, PollEvent, }; use crate::process::{ do_arch_prctl, do_clone, do_exit, do_exit_group, do_futex, do_getegid, do_geteuid, do_getgid,