From c480fa636243c25499a7e53f95c2d88886d773e9 Mon Sep 17 00:00:00 2001 From: Akshit Gaur Date: Sun, 25 Jan 2026 14:05:51 +0530 Subject: [PATCH] netstack: Add GetSockOpt --- netstack/src/scheme/socket.rs | 50 ++++++++++++++++++++++++++++++++++- netstack/src/scheme/tcp.rs | 36 +++++++++++++++++++++++++ netstack/src/scheme/udp.rs | 32 ++++++++++++++++++++++ 3 files changed, 117 insertions(+), 1 deletion(-) diff --git a/netstack/src/scheme/socket.rs b/netstack/src/scheme/socket.rs index 3703932869..a00aa44084 100644 --- a/netstack/src/scheme/socket.rs +++ b/netstack/src/scheme/socket.rs @@ -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>, @@ -237,6 +242,16 @@ where ) -> SyscallResult; fn handle_shutdown(&mut self, file: &mut SchemeFile, how: usize) -> SyscallResult; + + fn get_sock_opt( + &self, + file: &SchemeFile, + name: usize, + buf: &mut [u8], + ) -> SyscallResult { + // Return Err for default implementation + Err(SyscallError::new(syscall::ENOPROTOOPT)) + } } pub enum Handle @@ -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::(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), diff --git a/netstack/src/scheme/tcp.rs b/netstack/src/scheme/tcp.rs index 584426b340..8c46eec49c 100644 --- a/netstack/src/scheme/tcp.rs +++ b/netstack/src/scheme/tcp.rs @@ -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>; 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, + name: usize, + buf: &mut [u8], + ) -> SyscallResult { + 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)), + } + } } diff --git a/netstack/src/scheme/udp.rs b/netstack/src/scheme/udp.rs index 59037c2a02..918d38f80a 100644 --- a/netstack/src/scheme/udp.rs +++ b/netstack/src/scheme/udp.rs @@ -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>; 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, + name: usize, + buf: &mut [u8], + ) -> SyscallResult { + 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)), + } + } }