Merge branch 'getsockopt' into 'main'

netstack: Add GetSockOpt

See merge request redox-os/base!101
This commit is contained in:
Jeremy Soller
2026-01-25 08:56:57 -07:00
3 changed files with 117 additions and 1 deletions
+49 -1
View File
@@ -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),
+36
View File
@@ -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)),
}
}
}
+32
View File
@@ -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)),
}
}
}