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},
|
||||
poll_ifaces,
|
||||
socket::{
|
||||
util::{
|
||||
send_recv_flags::SendRecvFlags, sock_options::SockOptionName, sockaddr::SocketAddr,
|
||||
},
|
||||
util::{send_recv_flags::SendRecvFlags, sockaddr::SocketAddr},
|
||||
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
|
||||
fn recvfrom(&self, buf: &mut [u8], flags: SendRecvFlags) -> Result<(usize, SocketAddr)> {
|
||||
debug_assert!(flags.is_all_supported());
|
||||
|
@ -162,11 +162,6 @@ impl Socket for StreamSocket {
|
||||
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)> {
|
||||
let state = self.state.read();
|
||||
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::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 mod ip;
|
||||
@ -51,7 +51,12 @@ pub trait Socket: FileLike + Send + Sync {
|
||||
}
|
||||
|
||||
/// 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");
|
||||
}
|
||||
|
||||
|
@ -23,4 +23,19 @@ pub enum SockOptionName {
|
||||
SO_LINGER = 13,
|
||||
SO_BSDCOMPAT = 14,
|
||||
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::getrandom::sys_getrandom;
|
||||
use self::getsockname::sys_getsockname;
|
||||
use self::getsockopt::sys_getsockopt;
|
||||
use self::listen::sys_listen;
|
||||
use self::pread64::sys_pread64;
|
||||
use self::recvfrom::sys_recvfrom;
|
||||
@ -118,6 +119,7 @@ mod getpid;
|
||||
mod getppid;
|
||||
mod getrandom;
|
||||
mod getsockname;
|
||||
mod getsockopt;
|
||||
mod gettid;
|
||||
mod gettimeofday;
|
||||
mod getuid;
|
||||
@ -239,6 +241,7 @@ define_syscall_nums!(
|
||||
SYS_GETSOCKNAME = 51,
|
||||
SYS_GETPEERNAME = 52,
|
||||
SYS_SETSOCKOPT = 54,
|
||||
SYS_GETSOCKOPT = 55,
|
||||
SYS_CLONE = 56,
|
||||
SYS_FORK = 57,
|
||||
SYS_EXECVE = 59,
|
||||
@ -398,6 +401,7 @@ pub fn syscall_dispatch(
|
||||
SYS_GETSOCKNAME => syscall_handler!(3, sys_getsockname, args),
|
||||
SYS_GETPEERNAME => syscall_handler!(3, sys_getpeername, 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_FORK => syscall_handler!(0, sys_fork, context.clone()),
|
||||
SYS_EXECVE => syscall_handler!(3, sys_execve, args, context),
|
||||
|
@ -1,5 +1,5 @@
|
||||
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::{fs::file_table::FileDescripter, prelude::*};
|
||||
|
||||
@ -15,9 +15,6 @@ pub fn sys_setsockopt(
|
||||
) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_SETSOCKOPT);
|
||||
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)?;
|
||||
if optval == 0 {
|
||||
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];
|
||||
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 file_table = current.file_table().lock();
|
||||
let socket = file_table
|
||||
.get_file(sockfd)?
|
||||
.as_socket()
|
||||
.ok_or(Error::with_message(
|
||||
Errno::ENOTSOCK,
|
||||
"the file is not socket",
|
||||
))?;
|
||||
socket.set_sock_option(sock_option_name, &sock_opt_val)?;
|
||||
.ok_or_else(|| Error::with_message(Errno::ENOTSOCK, "the file is not socket"))?;
|
||||
// TODO: do setsockopt
|
||||
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