Merge branch 'getsockopt' into 'main'
netstack: Add GetSockOpt See merge request redox-os/base!101
This commit is contained in:
@@ -26,10 +26,15 @@ use syscall::{
|
||||
use super::Interface;
|
||||
use crate::router::route_table::RouteTable;
|
||||
use crate::scheme::smoltcp::iface::SocketHandle;
|
||||
use crate::scheme::Router;
|
||||
use crate::Smolnetd;
|
||||
use smoltcp::socket::AnySocket;
|
||||
|
||||
use super::SocketSet;
|
||||
|
||||
const SO_RCVBUF: usize = 8;
|
||||
const SO_SNDBUF: usize = 7;
|
||||
|
||||
pub struct Context {
|
||||
pub iface: Interface,
|
||||
pub route_table: Rc<RefCell<RouteTable>>,
|
||||
@@ -237,6 +242,16 @@ where
|
||||
) -> SyscallResult<usize>;
|
||||
|
||||
fn handle_shutdown(&mut self, file: &mut SchemeFile<Self>, how: usize) -> SyscallResult<usize>;
|
||||
|
||||
fn get_sock_opt(
|
||||
&self,
|
||||
file: &SchemeFile<Self>,
|
||||
name: usize,
|
||||
buf: &mut [u8],
|
||||
) -> SyscallResult<usize> {
|
||||
// Return Err for default implementation
|
||||
Err(SyscallError::new(syscall::ENOPROTOOPT))
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Handle<SocketT>
|
||||
@@ -446,7 +461,40 @@ where
|
||||
// TODO: SO_REUSEADDR from null socket
|
||||
Ok(0)
|
||||
}
|
||||
// SocketCall::GetSockOpt => self.handle_getsockopt(id, metadata[1] as i32, payload),
|
||||
SocketCall::GetSockOpt => {
|
||||
let handle = self
|
||||
.handles
|
||||
.get_mut(&fd)
|
||||
.ok_or_else(|| SyscallError::new(syscall::EBADF))?;
|
||||
|
||||
match *handle {
|
||||
Handle::File(ref mut file) => {
|
||||
let mut socket_set = self.socket_set.borrow_mut();
|
||||
let socket = socket_set.get_mut::<SocketT>(file.socket_handle());
|
||||
SocketT::get_sock_opt(socket, file, metadata[1] as usize, payload)
|
||||
}
|
||||
Handle::Null(_) => {
|
||||
// TODO
|
||||
// The socket exists but hasn't been bound/connected yet.
|
||||
// We return default values for buffer sizes to satisfy apps like iperf3.
|
||||
// Figure out maybe a better way?
|
||||
let name = metadata[1] as usize;
|
||||
if name == SO_RCVBUF || name == SO_SNDBUF {
|
||||
let val: i32 = (Router::MTU * Smolnetd::SOCKET_BUFFER_SIZE) as i32;
|
||||
let bytes = val.to_ne_bytes();
|
||||
|
||||
if payload.len() < bytes.len() {
|
||||
return Err(SyscallError::new(syscall::EINVAL));
|
||||
}
|
||||
payload[..bytes.len()].copy_from_slice(&bytes);
|
||||
Ok(bytes.len())
|
||||
} else {
|
||||
Err(SyscallError::new(syscall::EINVAL))
|
||||
}
|
||||
}
|
||||
Handle::SchemeRoot => Err(SyscallError::new(syscall::EBADF)),
|
||||
}
|
||||
}
|
||||
// SocketCall::SendMsg => self.handle_sendmsg(id, payload, ctx),
|
||||
// SocketCall::RecvMsg => self.handle_recvmsg(id, payload),
|
||||
// SocketCall::Unbind => self.handle_unbind(id),
|
||||
|
||||
@@ -10,6 +10,9 @@ use super::socket::{Context, DupResult, SchemeFile, SchemeSocket, SocketFile};
|
||||
use super::{parse_endpoint, SchemeWrapper, SocketSet};
|
||||
use crate::port_set::PortSet;
|
||||
|
||||
const SO_SNDBUF: usize = 7;
|
||||
const SO_RCVBUF: usize = 8;
|
||||
|
||||
pub type TcpScheme = SchemeWrapper<TcpSocket<'static>>;
|
||||
|
||||
impl<'a> SchemeSocket for TcpSocket<'a> {
|
||||
@@ -334,4 +337,37 @@ impl<'a> SchemeSocket for TcpSocket<'a> {
|
||||
}
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn get_sock_opt(
|
||||
&self,
|
||||
_file: &SchemeFile<Self>,
|
||||
name: usize,
|
||||
buf: &mut [u8],
|
||||
) -> SyscallResult<usize> {
|
||||
match name {
|
||||
SO_RCVBUF => {
|
||||
let val = self.recv_capacity() as i32;
|
||||
let bytes = val.to_ne_bytes();
|
||||
|
||||
if buf.len() < bytes.len() {
|
||||
return Err(SyscallError::new(syscall::EINVAL));
|
||||
}
|
||||
|
||||
buf[0..bytes.len()].copy_from_slice(&bytes);
|
||||
Ok(bytes.len())
|
||||
}
|
||||
SO_SNDBUF => {
|
||||
let val = self.send_capacity() as i32;
|
||||
let bytes = val.to_ne_bytes();
|
||||
|
||||
if buf.len() < bytes.len() {
|
||||
return Err(SyscallError::new(syscall::EINVAL));
|
||||
}
|
||||
|
||||
buf[0..bytes.len()].copy_from_slice(&bytes);
|
||||
Ok(bytes.len())
|
||||
}
|
||||
_ => Err(SyscallError::new(syscall::ENOPROTOOPT)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,9 @@ use crate::port_set::PortSet;
|
||||
use crate::router::Router;
|
||||
use std::fmt::Write;
|
||||
|
||||
const SO_SNDBUF: usize = 7;
|
||||
const SO_RCVBUF: usize = 8;
|
||||
|
||||
pub type UdpScheme = SchemeWrapper<UdpSocket<'static>>;
|
||||
|
||||
impl<'a> SchemeSocket for UdpSocket<'a> {
|
||||
@@ -318,4 +321,33 @@ impl<'a> SchemeSocket for UdpSocket<'a> {
|
||||
}
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn get_sock_opt(
|
||||
&self,
|
||||
_file: &SchemeFile<Self>,
|
||||
name: usize,
|
||||
buf: &mut [u8],
|
||||
) -> SyscallResult<usize> {
|
||||
match name {
|
||||
SO_RCVBUF => {
|
||||
let val = self.payload_recv_capacity() as i32;
|
||||
let bytes = val.to_ne_bytes();
|
||||
if buf.len() < bytes.len() {
|
||||
return Err(SyscallError::new(syscall::EINVAL));
|
||||
}
|
||||
buf[..bytes.len()].copy_from_slice(&bytes);
|
||||
Ok(bytes.len())
|
||||
}
|
||||
SO_SNDBUF => {
|
||||
let val = self.payload_send_capacity() as i32;
|
||||
let bytes = val.to_ne_bytes();
|
||||
if buf.len() < bytes.len() {
|
||||
return Err(SyscallError::new(syscall::EINVAL));
|
||||
}
|
||||
buf[..bytes.len()].copy_from_slice(&bytes);
|
||||
Ok(bytes.len())
|
||||
}
|
||||
_ => Err(SyscallError::new(syscall::ENOPROTOOPT)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user