From f56bfc4883e2ea4720fc97ff3873b2ca5c48c24c Mon Sep 17 00:00:00 2001 From: Wildan M Date: Thu, 8 Jan 2026 04:05:19 +0700 Subject: [PATCH] Adapt inet socket implementing SYS_CALL --- src/platform/redox/socket.rs | 178 ++++++++++++++--------------------- 1 file changed, 71 insertions(+), 107 deletions(-) diff --git a/src/platform/redox/socket.rs b/src/platform/redox/socket.rs index ecc8cec19c..ef6d478550 100644 --- a/src/platform/redox/socket.rs +++ b/src/platform/redox/socket.rs @@ -31,61 +31,59 @@ use crate::{ }, }; -macro_rules! bind_or_connect { - (bind $path:expr) => { - concat!("/", $path) - }; - (connect $path:expr) => { - $path - }; - ($mode:ident into, $socket:expr, $address:expr, $address_len:expr) => {{ - let fd = bind_or_connect!($mode copy, $socket, $address, $address_len)?; +unsafe fn bind_or_connect( + op: SocketCall, + socket: c_int, + address: *const sockaddr, + address_len: socklen_t, +) -> Result { + if (address_len as usize) < mem::size_of::() { + return Err(Errno(EINVAL)); + } - let _ = syscall::dup2(fd, $socket as usize, &[])?; - Result::::Ok(0) - }}; - ($mode:ident copy, $socket:expr, $address:expr, $address_len:expr) => {{ - if ($address_len as usize) < mem::size_of::() { - return Err(Errno(EINVAL)); - } + let path = match (*address).sa_family as c_int { + AF_INET => { + if (address_len as usize) != mem::size_of::() { + return Err(Errno(EINVAL)); + } - let path = match (*$address).sa_family as c_int { - AF_INET => { - if ($address_len as usize) != mem::size_of::() { - return Err(Errno(EINVAL)); + let data = &*(address as *const sockaddr_in); + let addr = slice::from_raw_parts( + &data.sin_addr.s_addr as *const _ as *const u8, + mem::size_of_val(&data.sin_addr.s_addr), + ); + let port = in_port_t::from_be(data.sin_port); + + match op { + SocketCall::Bind => { + format!("/{}.{}.{}.{}:{}", addr[0], addr[1], addr[2], addr[3], port) } - let data = &*($address as *const sockaddr_in); - let addr = slice::from_raw_parts( - &data.sin_addr.s_addr as *const _ as *const u8, - mem::size_of_val(&data.sin_addr.s_addr), - ); - let port = in_port_t::from_be(data.sin_port); - let path = format!( - bind_or_connect!($mode "{}.{}.{}.{}:{}"), - addr[0], - addr[1], - addr[2], - addr[3], - port - ); + SocketCall::Connect => { + format!("{}.{}.{}.{}:{}", addr[0], addr[1], addr[2], addr[3], port) + } + _ => unreachable!(), + } + } + AF_UNIX => { + eprintln!("bind/connect with AF_UNIX were replaced with SYS_CALL."); + return Err(Errno(EAFNOSUPPORT)); + } + _ => return Err(Errno(EAFNOSUPPORT)), + }; + let fd = syscall::dup(socket as usize, path.as_bytes())?; + Ok(fd) +} - path - }, - AF_UNIX => { - // NOTE: bind/connect with AF_UNIX were replaced with SYS_CALL. - eprintln!( - "bind/connect with AF_UNIX were replaced with SYS_CALL." - ); - return Err(Errno(EAFNOSUPPORT)); - }, - _ => { - return Err(Errno(EAFNOSUPPORT)); - }, - }; - - // Duplicate the socket, and then duplicate the copy back to the original fd - syscall::dup($socket as usize, path.as_bytes()) - }}; +pub unsafe fn bind_or_connect_into( + op: SocketCall, + socket: c_int, + address: *const sockaddr, + address_len: socklen_t, +) -> Result { + // Duplicate the socket, and then duplicate the copy back to the original fd + let fd = FdGuard::new(bind_or_connect(op, socket, address, address_len)?); + syscall::dup2(fd.as_raw_fd(), socket as usize, &[])?; + Ok(0) } unsafe fn inner_af_unix(buf: &[u8], address: *mut sockaddr, address_len: *mut socklen_t) { @@ -137,7 +135,7 @@ unsafe fn inner_af_inet( let ret = sockaddr_in { sin_family: AF_INET as sa_family_t, - sin_port: u16::to_be(port), + sin_port: in_port_t::to_be(port), sin_addr: addr, ..sockaddr_in::default() @@ -148,21 +146,6 @@ unsafe fn inner_af_inet( *address_len = len as socklen_t; } -unsafe fn inner_get_name( - local: bool, - socket: c_int, - address: *mut sockaddr, - address_len: *mut socklen_t, -) -> Result<()> { - // Format: [udp|tcp:]remote/local, chan:path - let mut buf = [0; 256]; - let len = syscall::fpath(socket as usize, &mut buf)?; - - inner_get_name_inner(local, address, address_len, &buf[..len])?; - - Ok(()) -} - unsafe fn inner_get_name_inner( local: bool, address: *mut sockaddr, @@ -527,7 +510,7 @@ impl PalSocket for Sys { unsafe fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> Result<()> { match (*address).sa_family as c_int { AF_INET => { - bind_or_connect!(bind into, socket, address, address_len)?; + bind_or_connect_into(SocketCall::Bind, socket, address, address_len)?; } AF_UNIX => { let data = &*(address as *const sockaddr_un); @@ -601,7 +584,7 @@ impl PalSocket for Sys { address_len: socklen_t, ) -> Result { match (*address).sa_family as c_int { - AF_INET => bind_or_connect!(connect into, socket, address, address_len), + AF_INET => bind_or_connect_into(SocketCall::Connect, socket, address, address_len), AF_UNIX => { let data = &*(address as *const sockaddr_un); @@ -658,37 +641,15 @@ impl PalSocket for Sys { address: *mut sockaddr, address_len: *mut socklen_t, ) -> Result<()> { - // This is needed until the netstack supports GetPeerName. - let (family, _) = socket_domain_type(socket)?; + let mut buf = [0; 256]; + let len = redox_rt::sys::sys_call( + socket as usize, + &mut buf, + CallFlags::empty(), + &[SocketCall::GetPeerName as u64], + )?; - match family { - AF_INET => inner_get_name(false, socket, address, address_len), - AF_UNIX => { - let mut buf = [0; 256]; - let len = redox_rt::sys::sys_call( - socket as usize, - &mut buf, - CallFlags::empty(), - &[SocketCall::GetPeerName as u64], - )?; - if buf.starts_with(b"/scheme/uds_stream/") { - inner_af_unix(&buf[19..len], address, address_len); - } else if buf.starts_with(b"/scheme/uds_dgram/") { - inner_af_unix(&buf[18..len], address, address_len); - } else { - // Socket doesn't belong to any scheme - trace!( - "socket {:?} doesn't match either tcp, udp or chan schemes", - str::from_utf8(buf) - ); - return Err(Errno(ENOTSOCK)); - } - Ok(()) - } - _ => { - return Err(Errno(EAFNOSUPPORT)); - } - } + inner_get_name_inner(false, address, address_len, &buf[..len]) } unsafe fn getsockname( @@ -696,7 +657,10 @@ impl PalSocket for Sys { address: *mut sockaddr, address_len: *mut socklen_t, ) -> Result<()> { - inner_get_name(true, socket, address, address_len) + let mut buf = [0; 256]; + let len = syscall::fpath(socket as usize, &mut buf)?; + + inner_get_name_inner(true, address, address_len, &buf[..len]) } unsafe fn getsockopt( @@ -805,7 +769,7 @@ impl PalSocket for Sys { } return Ok(count); } - if address == ptr::null_mut() || address_len == ptr::null_mut() { + if address.is_null() || address_len.is_null() { Self::read(socket, slice::from_raw_parts_mut(buf as *mut u8, len)) } else { Self::getpeername(socket, address, address_len)?; @@ -973,7 +937,12 @@ impl PalSocket for Sys { if dest_addr == ptr::null() || dest_len == 0 { Self::write(socket, slice::from_raw_parts(buf as *const u8, len)) } else { - let fd = FdGuard::new(bind_or_connect!(connect copy, socket, dest_addr, dest_len)?); + let fd = FdGuard::new(bind_or_connect( + SocketCall::Connect, + socket, + dest_addr, + dest_len, + )?); Self::write( fd.as_c_fd().unwrap(), slice::from_raw_parts(buf as *const u8, len), @@ -1019,11 +988,6 @@ impl PalSocket for Sys { SO_RCVTIMEO => return set_timeout(b"read_timeout"), SO_SNDTIMEO => return set_timeout(b"write_timeout"), _ => { - let (family, _) = socket_domain_type(socket)?; - if family == AF_INET { - // netstack does not support SYS_CALL - return Ok(()); - } let metadata = [SocketCall::SetSockOpt as u64, option_name as u64]; let payload = slice::from_raw_parts_mut(option_value as *mut u8, option_len as usize);