Move networking system call interfaces to net module
This commit is contained in:
parent
ed664d1143
commit
987e06a458
@ -8,6 +8,351 @@ use std::convert::TryFrom;
|
|||||||
use time::timeval_t;
|
use time::timeval_t;
|
||||||
use util::mem_util::from_user;
|
use util::mem_util::from_user;
|
||||||
|
|
||||||
|
pub fn do_socket(domain: c_int, socket_type: c_int, protocol: c_int) -> Result<isize> {
|
||||||
|
debug!(
|
||||||
|
"socket: domain: {}, socket_type: 0x{:x}, protocol: {}",
|
||||||
|
domain, socket_type, protocol
|
||||||
|
);
|
||||||
|
|
||||||
|
let file_ref: Arc<Box<dyn File>> = match domain {
|
||||||
|
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 fd = current!().add_file(file_ref, false);
|
||||||
|
Ok(fd as isize)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_connect(
|
||||||
|
fd: c_int,
|
||||||
|
addr: *const libc::sockaddr,
|
||||||
|
addr_len: libc::socklen_t,
|
||||||
|
) -> Result<isize> {
|
||||||
|
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 {
|
||||||
|
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() {
|
||||||
|
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)
|
||||||
|
} 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.connect(path)?;
|
||||||
|
Ok(0)
|
||||||
|
} else {
|
||||||
|
return_errno!(EBADF, "not a socket")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_accept(
|
||||||
|
fd: c_int,
|
||||||
|
addr: *mut libc::sockaddr,
|
||||||
|
addr_len: *mut libc::socklen_t,
|
||||||
|
) -> Result<isize> {
|
||||||
|
do_accept4(fd, addr, addr_len, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_accept4(
|
||||||
|
fd: c_int,
|
||||||
|
addr: *mut libc::sockaddr,
|
||||||
|
addr_len: *mut libc::socklen_t,
|
||||||
|
flags: c_int,
|
||||||
|
) -> Result<isize> {
|
||||||
|
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 {
|
||||||
|
from_user::check_mut_array(addr as *mut u8, unsafe { *addr_len } as usize)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_socket = socket.accept(addr, addr_len, flags)?;
|
||||||
|
let new_file_ref: Arc<Box<dyn File>> = Arc::new(Box::new(new_socket));
|
||||||
|
let new_fd = current!().add_file(new_file_ref, false);
|
||||||
|
|
||||||
|
Ok(new_fd as isize)
|
||||||
|
} else if let Ok(unix_socket) = file_ref.as_unix_socket() {
|
||||||
|
let addr = addr as *mut libc::sockaddr_un;
|
||||||
|
if need_check {
|
||||||
|
from_user::check_mut_ptr(addr)?;
|
||||||
|
}
|
||||||
|
// TODO: handle addr
|
||||||
|
let new_socket = unix_socket.accept()?;
|
||||||
|
let new_file_ref: Arc<Box<dyn File>> = Arc::new(Box::new(new_socket));
|
||||||
|
let new_fd = current!().add_file(new_file_ref, false);
|
||||||
|
|
||||||
|
Ok(new_fd as isize)
|
||||||
|
} else {
|
||||||
|
return_errno!(EBADF, "not a socket")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_shutdown(fd: c_int, how: c_int) -> Result<isize> {
|
||||||
|
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));
|
||||||
|
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<isize> {
|
||||||
|
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<isize> {
|
||||||
|
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 {
|
||||||
|
return_errno!(EBADF, "not a socket")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_setsockopt(
|
||||||
|
fd: c_int,
|
||||||
|
level: c_int,
|
||||||
|
optname: c_int,
|
||||||
|
optval: *const c_void,
|
||||||
|
optlen: libc::socklen_t,
|
||||||
|
) -> Result<isize> {
|
||||||
|
debug!(
|
||||||
|
"setsockopt: fd: {}, level: {}, optname: {}, optval: {:?}, optlen: {:?}",
|
||||||
|
fd, level, optname, optval, optlen
|
||||||
|
);
|
||||||
|
let file_ref = current!().file(fd as FileDesc)?;
|
||||||
|
if let Ok(socket) = file_ref.as_socket() {
|
||||||
|
let ret = try_libc!(libc::ocall::setsockopt(
|
||||||
|
socket.fd(),
|
||||||
|
level,
|
||||||
|
optname,
|
||||||
|
optval,
|
||||||
|
optlen
|
||||||
|
));
|
||||||
|
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 {
|
||||||
|
return_errno!(EBADF, "not a socket")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_getsockopt(
|
||||||
|
fd: c_int,
|
||||||
|
level: c_int,
|
||||||
|
optname: c_int,
|
||||||
|
optval: *mut c_void,
|
||||||
|
optlen: *mut libc::socklen_t,
|
||||||
|
) -> Result<isize> {
|
||||||
|
debug!(
|
||||||
|
"getsockopt: fd: {}, level: {}, optname: {}, optval: {:?}, optlen: {:?}",
|
||||||
|
fd, level, optname, optval, optlen
|
||||||
|
);
|
||||||
|
let file_ref = current!().file(fd as FileDesc)?;
|
||||||
|
let socket = file_ref.as_socket()?;
|
||||||
|
|
||||||
|
let ret = try_libc!(libc::ocall::getsockopt(
|
||||||
|
socket.fd(),
|
||||||
|
level,
|
||||||
|
optname,
|
||||||
|
optval,
|
||||||
|
optlen
|
||||||
|
));
|
||||||
|
Ok(ret as isize)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_getpeername(
|
||||||
|
fd: c_int,
|
||||||
|
addr: *mut libc::sockaddr,
|
||||||
|
addr_len: *mut libc::socklen_t,
|
||||||
|
) -> Result<isize> {
|
||||||
|
debug!(
|
||||||
|
"getpeername: fd: {}, addr: {:?}, addr_len: {:?}",
|
||||||
|
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));
|
||||||
|
Ok(ret as isize)
|
||||||
|
} else if let Ok(unix_socket) = file_ref.as_unix_socket() {
|
||||||
|
warn!("getpeername for unix socket is unimplemented");
|
||||||
|
return_errno!(
|
||||||
|
ENOTCONN,
|
||||||
|
"hack for php: Transport endpoint is not connected"
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return_errno!(EBADF, "not a socket")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_getsockname(
|
||||||
|
fd: c_int,
|
||||||
|
addr: *mut libc::sockaddr,
|
||||||
|
addr_len: *mut libc::socklen_t,
|
||||||
|
) -> Result<isize> {
|
||||||
|
debug!(
|
||||||
|
"getsockname: fd: {}, addr: {:?}, addr_len: {:?}",
|
||||||
|
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));
|
||||||
|
Ok(ret as isize)
|
||||||
|
} else if let Ok(unix_socket) = file_ref.as_unix_socket() {
|
||||||
|
warn!("getsockname for unix socket is unimplemented");
|
||||||
|
Ok(0)
|
||||||
|
} else {
|
||||||
|
return_errno!(EBADF, "not a socket")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_sendto(
|
||||||
|
fd: c_int,
|
||||||
|
base: *const c_void,
|
||||||
|
len: size_t,
|
||||||
|
flags: c_int,
|
||||||
|
addr: *const libc::sockaddr,
|
||||||
|
addr_len: libc::socklen_t,
|
||||||
|
) -> Result<isize> {
|
||||||
|
debug!(
|
||||||
|
"sendto: fd: {}, base: {:?}, len: {}, addr: {:?}, addr_len: {}",
|
||||||
|
fd, base, len, addr, addr_len
|
||||||
|
);
|
||||||
|
let file_ref = current!().file(fd as FileDesc)?;
|
||||||
|
let socket = file_ref.as_socket()?;
|
||||||
|
|
||||||
|
let ret = try_libc!(libc::ocall::sendto(
|
||||||
|
socket.fd(),
|
||||||
|
base,
|
||||||
|
len,
|
||||||
|
flags,
|
||||||
|
addr,
|
||||||
|
addr_len
|
||||||
|
));
|
||||||
|
Ok(ret as isize)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_recvfrom(
|
||||||
|
fd: c_int,
|
||||||
|
base: *mut c_void,
|
||||||
|
len: size_t,
|
||||||
|
flags: c_int,
|
||||||
|
addr: *mut libc::sockaddr,
|
||||||
|
addr_len: *mut libc::socklen_t,
|
||||||
|
) -> Result<isize> {
|
||||||
|
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()?;
|
||||||
|
|
||||||
|
let ret = try_libc!(libc::ocall::recvfrom(
|
||||||
|
socket.fd(),
|
||||||
|
base,
|
||||||
|
len,
|
||||||
|
flags,
|
||||||
|
addr,
|
||||||
|
addr_len
|
||||||
|
));
|
||||||
|
Ok(ret as isize)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_socketpair(
|
||||||
|
domain: c_int,
|
||||||
|
socket_type: c_int,
|
||||||
|
protocol: c_int,
|
||||||
|
sv: *mut c_int,
|
||||||
|
) -> Result<isize> {
|
||||||
|
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 (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);
|
||||||
|
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn do_sendmsg(fd: c_int, msg_ptr: *const msghdr, flags_c: c_int) -> Result<isize> {
|
pub fn do_sendmsg(fd: c_int, msg_ptr: *const msghdr, flags_c: c_int) -> Result<isize> {
|
||||||
debug!(
|
debug!(
|
||||||
"sendmsg: fd: {}, msg: {:?}, flags: 0x{:x}",
|
"sendmsg: fd: {}, msg: {:?}, flags: 0x{:x}",
|
||||||
|
@ -27,9 +27,11 @@ use crate::fs::{
|
|||||||
};
|
};
|
||||||
use crate::misc::{resource_t, rlimit_t, utsname_t};
|
use crate::misc::{resource_t, rlimit_t, utsname_t};
|
||||||
use crate::net::{
|
use crate::net::{
|
||||||
do_epoll_create, do_epoll_create1, do_epoll_ctl, do_epoll_pwait, do_epoll_wait, do_poll,
|
do_accept, do_accept4, do_bind, do_connect, do_epoll_create, do_epoll_create1, do_epoll_ctl,
|
||||||
do_recvmsg, do_select, do_sendmsg, msghdr, msghdr_mut, AsSocket, AsUnixSocket, EpollEvent,
|
do_epoll_pwait, do_epoll_wait, do_getpeername, do_getsockname, do_getsockopt, do_listen,
|
||||||
SocketFile, UnixSocketFile,
|
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, SocketFile,
|
||||||
|
UnixSocketFile,
|
||||||
};
|
};
|
||||||
use crate::process::{
|
use crate::process::{
|
||||||
do_arch_prctl, do_clone, do_exit, do_exit_group, do_futex, do_getegid, do_geteuid, do_getgid,
|
do_arch_prctl, do_clone, do_exit, do_exit_group, do_futex, do_getegid, do_geteuid, do_getgid,
|
||||||
@ -785,347 +787,6 @@ fn do_nanosleep(req_u: *const timespec_t, rem_u: *mut timespec_t) -> Result<isiz
|
|||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_socket(domain: c_int, socket_type: c_int, protocol: c_int) -> Result<isize> {
|
|
||||||
debug!(
|
|
||||||
"socket: domain: {}, socket_type: 0x{:x}, protocol: {}",
|
|
||||||
domain, socket_type, protocol
|
|
||||||
);
|
|
||||||
|
|
||||||
let file_ref: Arc<Box<dyn File>> = match domain {
|
|
||||||
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 fd = current!().add_file(file_ref, false);
|
|
||||||
Ok(fd as isize)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_connect(fd: c_int, addr: *const libc::sockaddr, addr_len: libc::socklen_t) -> Result<isize> {
|
|
||||||
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 {
|
|
||||||
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() {
|
|
||||||
if need_check {
|
|
||||||
check_ptr(addr as *const libc::sockaddr_in)?;
|
|
||||||
}
|
|
||||||
let ret = try_libc!(libc::ocall::connect(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;
|
|
||||||
check_ptr(addr)?;
|
|
||||||
let path = clone_cstring_safely(unsafe { (&*addr).sun_path.as_ptr() })?
|
|
||||||
.to_string_lossy()
|
|
||||||
.into_owned();
|
|
||||||
unix_socket.connect(path)?;
|
|
||||||
Ok(0)
|
|
||||||
} else {
|
|
||||||
return_errno!(EBADF, "not a socket")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_accept(
|
|
||||||
fd: c_int,
|
|
||||||
addr: *mut libc::sockaddr,
|
|
||||||
addr_len: *mut libc::socklen_t,
|
|
||||||
) -> Result<isize> {
|
|
||||||
do_accept4(fd, addr, addr_len, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_accept4(
|
|
||||||
fd: c_int,
|
|
||||||
addr: *mut libc::sockaddr,
|
|
||||||
addr_len: *mut libc::socklen_t,
|
|
||||||
flags: c_int,
|
|
||||||
) -> Result<isize> {
|
|
||||||
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 {
|
|
||||||
check_mut_array(addr as *mut u8, unsafe { *addr_len } as usize)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let file_ref = current!().file(fd as FileDesc)?;
|
|
||||||
if let Ok(socket) = file_ref.as_socket() {
|
|
||||||
if need_check {
|
|
||||||
check_mut_ptr(addr as *mut libc::sockaddr_in)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let new_socket = socket.accept(addr, addr_len, flags)?;
|
|
||||||
let new_file_ref: Arc<Box<dyn File>> = Arc::new(Box::new(new_socket));
|
|
||||||
let new_fd = current!().add_file(new_file_ref, false);
|
|
||||||
|
|
||||||
Ok(new_fd as isize)
|
|
||||||
} else if let Ok(unix_socket) = file_ref.as_unix_socket() {
|
|
||||||
let addr = addr as *mut libc::sockaddr_un;
|
|
||||||
if need_check {
|
|
||||||
check_mut_ptr(addr)?;
|
|
||||||
}
|
|
||||||
// TODO: handle addr
|
|
||||||
let new_socket = unix_socket.accept()?;
|
|
||||||
let new_file_ref: Arc<Box<dyn File>> = Arc::new(Box::new(new_socket));
|
|
||||||
let new_fd = current!().add_file(new_file_ref, false);
|
|
||||||
|
|
||||||
Ok(new_fd as isize)
|
|
||||||
} else {
|
|
||||||
return_errno!(EBADF, "not a socket")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_shutdown(fd: c_int, how: c_int) -> Result<isize> {
|
|
||||||
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));
|
|
||||||
Ok(ret as isize)
|
|
||||||
} else {
|
|
||||||
return_errno!(EBADF, "not a socket")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_bind(fd: c_int, addr: *const libc::sockaddr, addr_len: libc::socklen_t) -> Result<isize> {
|
|
||||||
debug!("bind: fd: {}, addr: {:?}, addr_len: {}", fd, addr, addr_len);
|
|
||||||
if addr.is_null() && addr_len == 0 {
|
|
||||||
return_errno!(EINVAL, "no address is specified");
|
|
||||||
}
|
|
||||||
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() {
|
|
||||||
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;
|
|
||||||
check_ptr(addr)?;
|
|
||||||
let path = 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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_listen(fd: c_int, backlog: c_int) -> Result<isize> {
|
|
||||||
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 {
|
|
||||||
return_errno!(EBADF, "not a socket")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_setsockopt(
|
|
||||||
fd: c_int,
|
|
||||||
level: c_int,
|
|
||||||
optname: c_int,
|
|
||||||
optval: *const c_void,
|
|
||||||
optlen: libc::socklen_t,
|
|
||||||
) -> Result<isize> {
|
|
||||||
debug!(
|
|
||||||
"setsockopt: fd: {}, level: {}, optname: {}, optval: {:?}, optlen: {:?}",
|
|
||||||
fd, level, optname, optval, optlen
|
|
||||||
);
|
|
||||||
let file_ref = current!().file(fd as FileDesc)?;
|
|
||||||
if let Ok(socket) = file_ref.as_socket() {
|
|
||||||
let ret = try_libc!(libc::ocall::setsockopt(
|
|
||||||
socket.fd(),
|
|
||||||
level,
|
|
||||||
optname,
|
|
||||||
optval,
|
|
||||||
optlen
|
|
||||||
));
|
|
||||||
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 {
|
|
||||||
return_errno!(EBADF, "not a socket")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_getsockopt(
|
|
||||||
fd: c_int,
|
|
||||||
level: c_int,
|
|
||||||
optname: c_int,
|
|
||||||
optval: *mut c_void,
|
|
||||||
optlen: *mut libc::socklen_t,
|
|
||||||
) -> Result<isize> {
|
|
||||||
debug!(
|
|
||||||
"getsockopt: fd: {}, level: {}, optname: {}, optval: {:?}, optlen: {:?}",
|
|
||||||
fd, level, optname, optval, optlen
|
|
||||||
);
|
|
||||||
let file_ref = current!().file(fd as FileDesc)?;
|
|
||||||
let socket = file_ref.as_socket()?;
|
|
||||||
|
|
||||||
let ret = try_libc!(libc::ocall::getsockopt(
|
|
||||||
socket.fd(),
|
|
||||||
level,
|
|
||||||
optname,
|
|
||||||
optval,
|
|
||||||
optlen
|
|
||||||
));
|
|
||||||
Ok(ret as isize)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_getpeername(
|
|
||||||
fd: c_int,
|
|
||||||
addr: *mut libc::sockaddr,
|
|
||||||
addr_len: *mut libc::socklen_t,
|
|
||||||
) -> Result<isize> {
|
|
||||||
debug!(
|
|
||||||
"getpeername: fd: {}, addr: {:?}, addr_len: {:?}",
|
|
||||||
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));
|
|
||||||
Ok(ret as isize)
|
|
||||||
} else if let Ok(unix_socket) = file_ref.as_unix_socket() {
|
|
||||||
warn!("getpeername for unix socket is unimplemented");
|
|
||||||
return_errno!(
|
|
||||||
ENOTCONN,
|
|
||||||
"hack for php: Transport endpoint is not connected"
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
return_errno!(EBADF, "not a socket")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_getsockname(
|
|
||||||
fd: c_int,
|
|
||||||
addr: *mut libc::sockaddr,
|
|
||||||
addr_len: *mut libc::socklen_t,
|
|
||||||
) -> Result<isize> {
|
|
||||||
debug!(
|
|
||||||
"getsockname: fd: {}, addr: {:?}, addr_len: {:?}",
|
|
||||||
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));
|
|
||||||
Ok(ret as isize)
|
|
||||||
} else if let Ok(unix_socket) = file_ref.as_unix_socket() {
|
|
||||||
warn!("getsockname for unix socket is unimplemented");
|
|
||||||
Ok(0)
|
|
||||||
} else {
|
|
||||||
return_errno!(EBADF, "not a socket")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_sendto(
|
|
||||||
fd: c_int,
|
|
||||||
base: *const c_void,
|
|
||||||
len: size_t,
|
|
||||||
flags: c_int,
|
|
||||||
addr: *const libc::sockaddr,
|
|
||||||
addr_len: libc::socklen_t,
|
|
||||||
) -> Result<isize> {
|
|
||||||
debug!(
|
|
||||||
"sendto: fd: {}, base: {:?}, len: {}, addr: {:?}, addr_len: {}",
|
|
||||||
fd, base, len, addr, addr_len
|
|
||||||
);
|
|
||||||
let file_ref = current!().file(fd as FileDesc)?;
|
|
||||||
let socket = file_ref.as_socket()?;
|
|
||||||
|
|
||||||
let ret = try_libc!(libc::ocall::sendto(
|
|
||||||
socket.fd(),
|
|
||||||
base,
|
|
||||||
len,
|
|
||||||
flags,
|
|
||||||
addr,
|
|
||||||
addr_len
|
|
||||||
));
|
|
||||||
Ok(ret as isize)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_recvfrom(
|
|
||||||
fd: c_int,
|
|
||||||
base: *mut c_void,
|
|
||||||
len: size_t,
|
|
||||||
flags: c_int,
|
|
||||||
addr: *mut libc::sockaddr,
|
|
||||||
addr_len: *mut libc::socklen_t,
|
|
||||||
) -> Result<isize> {
|
|
||||||
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()?;
|
|
||||||
|
|
||||||
let ret = try_libc!(libc::ocall::recvfrom(
|
|
||||||
socket.fd(),
|
|
||||||
base,
|
|
||||||
len,
|
|
||||||
flags,
|
|
||||||
addr,
|
|
||||||
addr_len
|
|
||||||
));
|
|
||||||
Ok(ret as isize)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_socketpair(
|
|
||||||
domain: c_int,
|
|
||||||
socket_type: c_int,
|
|
||||||
protocol: c_int,
|
|
||||||
sv: *mut c_int,
|
|
||||||
) -> Result<isize> {
|
|
||||||
debug!(
|
|
||||||
"socketpair: domain: {}, type:0x{:x}, protocol: {}",
|
|
||||||
domain, socket_type, protocol
|
|
||||||
);
|
|
||||||
let mut sock_pair = unsafe {
|
|
||||||
check_mut_array(sv, 2)?;
|
|
||||||
std::slice::from_raw_parts_mut(sv as *mut u32, 2)
|
|
||||||
};
|
|
||||||
|
|
||||||
if (domain == libc::AF_UNIX) {
|
|
||||||
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);
|
|
||||||
|
|
||||||
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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_uname(name: *mut utsname_t) -> Result<isize> {
|
fn do_uname(name: *mut utsname_t) -> Result<isize> {
|
||||||
check_mut_ptr(name)?;
|
check_mut_ptr(name)?;
|
||||||
let name = unsafe { &mut *name };
|
let name = unsafe { &mut *name };
|
||||||
|
Loading…
Reference in New Issue
Block a user