mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-24 09:53:24 +00:00
Add syscall getsockopt
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
dcfbeb270d
commit
9d06f60ecc
@ -9,9 +9,7 @@ use crate::{
|
|||||||
iface::{AnyBoundSocket, AnyUnboundSocket, RawUdpSocket},
|
iface::{AnyBoundSocket, AnyUnboundSocket, RawUdpSocket},
|
||||||
poll_ifaces,
|
poll_ifaces,
|
||||||
socket::{
|
socket::{
|
||||||
util::{
|
util::{send_recv_flags::SendRecvFlags, sockaddr::SocketAddr},
|
||||||
send_recv_flags::SendRecvFlags, sock_options::SockOptionName, sockaddr::SocketAddr,
|
|
||||||
},
|
|
||||||
Socket,
|
Socket,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -216,11 +214,6 @@ impl Socket for DatagramSocket {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_sock_option(&self, optname: SockOptionName, option_val: &[u8]) -> Result<()> {
|
|
||||||
// FIXME: deal with sock options here
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: respect RecvFromFlags
|
// FIXME: respect RecvFromFlags
|
||||||
fn recvfrom(&self, buf: &mut [u8], flags: SendRecvFlags) -> Result<(usize, SocketAddr)> {
|
fn recvfrom(&self, buf: &mut [u8], flags: SendRecvFlags) -> Result<(usize, SocketAddr)> {
|
||||||
debug_assert!(flags.is_all_supported());
|
debug_assert!(flags.is_all_supported());
|
||||||
|
@ -162,11 +162,6 @@ impl Socket for StreamSocket {
|
|||||||
return_errno_with_message!(Errno::EINVAL, "getsockopt not implemented");
|
return_errno_with_message!(Errno::EINVAL, "getsockopt not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_sock_option(&self, optname: SockOptionName, option_val: &[u8]) -> Result<()> {
|
|
||||||
// TODO: implement setsockopt
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn recvfrom(&self, buf: &mut [u8], flags: SendRecvFlags) -> Result<(usize, SocketAddr)> {
|
fn recvfrom(&self, buf: &mut [u8], flags: SendRecvFlags) -> Result<(usize, SocketAddr)> {
|
||||||
let state = self.state.read();
|
let state = self.state.read();
|
||||||
let (recv_size, remote_endpoint) = match &*state {
|
let (recv_size, remote_endpoint) = match &*state {
|
||||||
|
@ -2,7 +2,7 @@ use crate::{fs::file_handle::FileLike, prelude::*};
|
|||||||
|
|
||||||
pub use self::util::send_recv_flags::SendRecvFlags;
|
pub use self::util::send_recv_flags::SendRecvFlags;
|
||||||
pub use self::util::shutdown_cmd::SockShutdownCmd;
|
pub use self::util::shutdown_cmd::SockShutdownCmd;
|
||||||
pub use self::util::sock_options::SockOptionName;
|
pub use self::util::sock_options::{SockOptionLevel, SockOptionName};
|
||||||
pub use self::util::sockaddr::SocketAddr;
|
pub use self::util::sockaddr::SocketAddr;
|
||||||
|
|
||||||
pub mod ip;
|
pub mod ip;
|
||||||
@ -51,7 +51,12 @@ pub trait Socket: FileLike + Send + Sync {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set options on the socket
|
/// Set options on the socket
|
||||||
fn set_sock_option(&self, optname: SockOptionName, option_val: &[u8]) -> Result<()> {
|
fn set_sock_option(
|
||||||
|
&self,
|
||||||
|
opt_level: SockOptionLevel,
|
||||||
|
optname: SockOptionName,
|
||||||
|
option_val: &[u8],
|
||||||
|
) -> Result<()> {
|
||||||
return_errno_with_message!(Errno::EINVAL, "setsockopt not implemented");
|
return_errno_with_message!(Errno::EINVAL, "setsockopt not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,4 +23,19 @@ pub enum SockOptionName {
|
|||||||
SO_LINGER = 13,
|
SO_LINGER = 13,
|
||||||
SO_BSDCOMPAT = 14,
|
SO_BSDCOMPAT = 14,
|
||||||
SO_REUSEPORT = 15,
|
SO_REUSEPORT = 15,
|
||||||
|
SO_RCVTIMEO_NEW = 66,
|
||||||
|
SO_SNDTIMEO_NEW = 67,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(i32)]
|
||||||
|
#[derive(Debug, Clone, Copy, TryFromInt, PartialEq, Eq)]
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
/// Sock Opt level. The definition is from https://elixir.bootlin.com/linux/v6.0.9/source/include/linux/socket.h#L343
|
||||||
|
pub enum SockOptionLevel {
|
||||||
|
SOL_IP = 0,
|
||||||
|
SOL_SOCKET = 1,
|
||||||
|
SOL_TCP = 6,
|
||||||
|
SOL_UDP = 17,
|
||||||
|
SOL_IPV6 = 41,
|
||||||
|
SOL_RAW = 255,
|
||||||
}
|
}
|
||||||
|
46
services/libs/jinux-std/src/syscall/getsockopt.rs
Normal file
46
services/libs/jinux-std/src/syscall/getsockopt.rs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
use crate::{
|
||||||
|
fs::file_table::FileDescripter,
|
||||||
|
log_syscall_entry,
|
||||||
|
net::socket::{SockOptionLevel, SockOptionName},
|
||||||
|
prelude::*,
|
||||||
|
syscall::SYS_SETSOCKOPT,
|
||||||
|
util::{read_val_from_user, write_val_to_user},
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::SyscallReturn;
|
||||||
|
|
||||||
|
pub fn sys_getsockopt(
|
||||||
|
sockfd: FileDescripter,
|
||||||
|
level: i32,
|
||||||
|
optname: i32,
|
||||||
|
optval: Vaddr,
|
||||||
|
optlen_addr: Vaddr,
|
||||||
|
) -> Result<SyscallReturn> {
|
||||||
|
log_syscall_entry!(SYS_SETSOCKOPT);
|
||||||
|
let level = SockOptionLevel::try_from(level)?;
|
||||||
|
let sock_option_name = SockOptionName::try_from(optname)?;
|
||||||
|
if optval == 0 || optlen_addr == 0 {
|
||||||
|
return_errno_with_message!(Errno::EINVAL, "optval or optlen_addr is null pointer");
|
||||||
|
}
|
||||||
|
let optlen: u32 = read_val_from_user(optlen_addr)?;
|
||||||
|
debug!(
|
||||||
|
"level = {level:?}, sockfd = {sockfd}, optname = {sock_option_name:?}, optlen = {optlen}"
|
||||||
|
);
|
||||||
|
let current = current!();
|
||||||
|
let file_table = current.file_table().lock();
|
||||||
|
let socket = file_table
|
||||||
|
.get_file(sockfd)?
|
||||||
|
.as_socket()
|
||||||
|
.ok_or_else(|| Error::with_message(Errno::ENOTSOCK, "the file is not socket"))?;
|
||||||
|
|
||||||
|
// FIXME: This is only a workaround. Writing zero means the socket does not have error.
|
||||||
|
// The linux manual says that writing a non-zero value if there are errors. But what value is it?
|
||||||
|
if sock_option_name == SockOptionName::SO_ERROR {
|
||||||
|
assert!(optlen == 4);
|
||||||
|
write_val_to_user(optval, &0i32)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: do real getsockopt
|
||||||
|
|
||||||
|
Ok(SyscallReturn::Return(0))
|
||||||
|
}
|
@ -78,6 +78,7 @@ use self::execve::sys_execveat;
|
|||||||
use self::getpeername::sys_getpeername;
|
use self::getpeername::sys_getpeername;
|
||||||
use self::getrandom::sys_getrandom;
|
use self::getrandom::sys_getrandom;
|
||||||
use self::getsockname::sys_getsockname;
|
use self::getsockname::sys_getsockname;
|
||||||
|
use self::getsockopt::sys_getsockopt;
|
||||||
use self::listen::sys_listen;
|
use self::listen::sys_listen;
|
||||||
use self::pread64::sys_pread64;
|
use self::pread64::sys_pread64;
|
||||||
use self::recvfrom::sys_recvfrom;
|
use self::recvfrom::sys_recvfrom;
|
||||||
@ -118,6 +119,7 @@ mod getpid;
|
|||||||
mod getppid;
|
mod getppid;
|
||||||
mod getrandom;
|
mod getrandom;
|
||||||
mod getsockname;
|
mod getsockname;
|
||||||
|
mod getsockopt;
|
||||||
mod gettid;
|
mod gettid;
|
||||||
mod gettimeofday;
|
mod gettimeofday;
|
||||||
mod getuid;
|
mod getuid;
|
||||||
@ -239,6 +241,7 @@ define_syscall_nums!(
|
|||||||
SYS_GETSOCKNAME = 51,
|
SYS_GETSOCKNAME = 51,
|
||||||
SYS_GETPEERNAME = 52,
|
SYS_GETPEERNAME = 52,
|
||||||
SYS_SETSOCKOPT = 54,
|
SYS_SETSOCKOPT = 54,
|
||||||
|
SYS_GETSOCKOPT = 55,
|
||||||
SYS_CLONE = 56,
|
SYS_CLONE = 56,
|
||||||
SYS_FORK = 57,
|
SYS_FORK = 57,
|
||||||
SYS_EXECVE = 59,
|
SYS_EXECVE = 59,
|
||||||
@ -398,6 +401,7 @@ pub fn syscall_dispatch(
|
|||||||
SYS_GETSOCKNAME => syscall_handler!(3, sys_getsockname, args),
|
SYS_GETSOCKNAME => syscall_handler!(3, sys_getsockname, args),
|
||||||
SYS_GETPEERNAME => syscall_handler!(3, sys_getpeername, args),
|
SYS_GETPEERNAME => syscall_handler!(3, sys_getpeername, args),
|
||||||
SYS_SETSOCKOPT => syscall_handler!(5, sys_setsockopt, args),
|
SYS_SETSOCKOPT => syscall_handler!(5, sys_setsockopt, args),
|
||||||
|
SYS_GETSOCKOPT => syscall_handler!(5, sys_getsockopt, args),
|
||||||
SYS_CLONE => syscall_handler!(5, sys_clone, args, context.clone()),
|
SYS_CLONE => syscall_handler!(5, sys_clone, args, context.clone()),
|
||||||
SYS_FORK => syscall_handler!(0, sys_fork, context.clone()),
|
SYS_FORK => syscall_handler!(0, sys_fork, context.clone()),
|
||||||
SYS_EXECVE => syscall_handler!(3, sys_execve, args, context),
|
SYS_EXECVE => syscall_handler!(3, sys_execve, args, context),
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::log_syscall_entry;
|
use crate::log_syscall_entry;
|
||||||
use crate::net::socket::SockOptionName;
|
use crate::net::socket::{SockOptionLevel, SockOptionName};
|
||||||
use crate::util::read_bytes_from_user;
|
use crate::util::read_bytes_from_user;
|
||||||
use crate::{fs::file_table::FileDescripter, prelude::*};
|
use crate::{fs::file_table::FileDescripter, prelude::*};
|
||||||
|
|
||||||
@ -15,9 +15,6 @@ pub fn sys_setsockopt(
|
|||||||
) -> Result<SyscallReturn> {
|
) -> Result<SyscallReturn> {
|
||||||
log_syscall_entry!(SYS_SETSOCKOPT);
|
log_syscall_entry!(SYS_SETSOCKOPT);
|
||||||
let level = SockOptionLevel::try_from(level)?;
|
let level = SockOptionLevel::try_from(level)?;
|
||||||
if level != SockOptionLevel::SOL_SOCKET {
|
|
||||||
return_errno_with_message!(Errno::ENOPROTOOPT, "Unsupported sockoption level");
|
|
||||||
}
|
|
||||||
let sock_option_name = SockOptionName::try_from(optname)?;
|
let sock_option_name = SockOptionName::try_from(optname)?;
|
||||||
if optval == 0 {
|
if optval == 0 {
|
||||||
return_errno_with_message!(Errno::EINVAL, "optval is null pointer");
|
return_errno_with_message!(Errno::EINVAL, "optval is null pointer");
|
||||||
@ -25,25 +22,13 @@ pub fn sys_setsockopt(
|
|||||||
let mut sock_opt_val = vec![0u8; optlen];
|
let mut sock_opt_val = vec![0u8; optlen];
|
||||||
read_bytes_from_user(optval, &mut sock_opt_val)?;
|
read_bytes_from_user(optval, &mut sock_opt_val)?;
|
||||||
|
|
||||||
debug!("sockfd = {sockfd}, optname = {sock_option_name:?}, optval = {sock_opt_val:?}");
|
debug!("level = {level:?}, sockfd = {sockfd}, optname = {sock_option_name:?}, optval = {sock_opt_val:?}");
|
||||||
let current = current!();
|
let current = current!();
|
||||||
let file_table = current.file_table().lock();
|
let file_table = current.file_table().lock();
|
||||||
let socket = file_table
|
let socket = file_table
|
||||||
.get_file(sockfd)?
|
.get_file(sockfd)?
|
||||||
.as_socket()
|
.as_socket()
|
||||||
.ok_or(Error::with_message(
|
.ok_or_else(|| Error::with_message(Errno::ENOTSOCK, "the file is not socket"))?;
|
||||||
Errno::ENOTSOCK,
|
// TODO: do setsockopt
|
||||||
"the file is not socket",
|
|
||||||
))?;
|
|
||||||
socket.set_sock_option(sock_option_name, &sock_opt_val)?;
|
|
||||||
Ok(SyscallReturn::Return(0))
|
Ok(SyscallReturn::Return(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(i32)]
|
|
||||||
#[derive(Debug, Clone, Copy, TryFromInt, PartialEq, Eq)]
|
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
/// Sock Opt level
|
|
||||||
enum SockOptionLevel {
|
|
||||||
SOL_IP = 0,
|
|
||||||
SOL_SOCKET = 1,
|
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user