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 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> {
|
||||
debug!(
|
||||
"sendmsg: fd: {}, msg: {:?}, flags: 0x{:x}",
|
||||
|
@ -27,9 +27,11 @@ use crate::fs::{
|
||||
};
|
||||
use crate::misc::{resource_t, rlimit_t, utsname_t};
|
||||
use crate::net::{
|
||||
do_epoll_create, do_epoll_create1, do_epoll_ctl, do_epoll_pwait, do_epoll_wait, do_poll,
|
||||
do_recvmsg, do_select, do_sendmsg, msghdr, msghdr_mut, AsSocket, AsUnixSocket, EpollEvent,
|
||||
SocketFile, UnixSocketFile,
|
||||
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, SocketFile,
|
||||
UnixSocketFile,
|
||||
};
|
||||
use crate::process::{
|
||||
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)
|
||||
}
|
||||
|
||||
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> {
|
||||
check_mut_ptr(name)?;
|
||||
let name = unsafe { &mut *name };
|
||||
|
Loading…
Reference in New Issue
Block a user