From 468755fc9a2725ffe53124c716b951ea1e7b20f4 Mon Sep 17 00:00:00 2001 From: lhw Date: Wed, 26 Feb 2025 12:12:00 +0800 Subject: [PATCH 1/2] add force route --- apps/c/httpclient/expect_info.out | 9 +- modules/ruxfs/src/mounts.rs | 3 +- modules/ruxnet/src/smoltcp_impl/dns.rs | 2 +- modules/ruxnet/src/smoltcp_impl/mod.rs | 9 +- modules/ruxnet/src/smoltcp_impl/tcp.rs | 180 ++++++++++++++----------- modules/ruxnet/src/smoltcp_impl/udp.rs | 84 +++++++----- 6 files changed, 161 insertions(+), 126 deletions(-) diff --git a/apps/c/httpclient/expect_info.out b/apps/c/httpclient/expect_info.out index 35cf49e11..09aab4144 100644 --- a/apps/c/httpclient/expect_info.out +++ b/apps/c/httpclient/expect_info.out @@ -31,13 +31,12 @@ Primary CPU 0 init OK. Hello, Ruxos C HTTP client! IP: [0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+ HTTP/1.1 200 OK -Server: nginx -Date: -Content-Type: text/plain -Content-Length: -Connection: keep-alive Access-Control-Allow-Origin: * +Alt-Svc: h3=":443"; ma= Cache-Control: no-cache, no-store, must-revalidate +Date: +Content-Length: +Content-Type: text/plain; charset=utf-8 ^[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+ Shutting down... diff --git a/modules/ruxfs/src/mounts.rs b/modules/ruxfs/src/mounts.rs index b5d74cae0..39a65abc6 100644 --- a/modules/ruxfs/src/mounts.rs +++ b/modules/ruxfs/src/mounts.rs @@ -130,7 +130,8 @@ pub(crate) fn etcfs() -> VfsResult> { let file_resolv = etc_root.clone().lookup("resolv.conf")?; file_resolv.write_at( 0, - b"nameserver 127.0.0.53\n\ + b"nameserver 8.8.8.8\n\ + nameserver 114.114.114.114\n\ options edns0 trust-ad\n\ search lan\n ", diff --git a/modules/ruxnet/src/smoltcp_impl/dns.rs b/modules/ruxnet/src/smoltcp_impl/dns.rs index 53e7db29f..cf33c3494 100644 --- a/modules/ruxnet/src/smoltcp_impl/dns.rs +++ b/modules/ruxnet/src/smoltcp_impl/dns.rs @@ -66,7 +66,7 @@ impl DnsSocket { } })?; loop { - SOCKET_SET.poll_interfaces(); + SOCKET_SET.poll_interfaces(None); match SOCKET_SET.with_socket_mut::(handle, |socket| { socket.get_query_result(query_handle).map_err(|e| match e { GetQueryResultError::Pending => AxError::WouldBlock, diff --git a/modules/ruxnet/src/smoltcp_impl/mod.rs b/modules/ruxnet/src/smoltcp_impl/mod.rs index 50bfbfe9d..74a2ff2ed 100644 --- a/modules/ruxnet/src/smoltcp_impl/mod.rs +++ b/modules/ruxnet/src/smoltcp_impl/mod.rs @@ -137,9 +137,11 @@ impl<'a> SocketSetWrapper<'a> { f(socket) } - pub fn poll_interfaces(&self) { + pub fn poll_interfaces(&self, iface_name: Option) { for iface in IFACE_LIST.lock().iter() { - iface.poll(&self.0); + if iface_name.is_none() || iface_name.clone().unwrap() == iface.name() { + iface.poll(&self.0); + } } } @@ -287,7 +289,6 @@ impl<'a> TxToken for AxNetTxToken<'a> { let mut dev = self.0.borrow_mut(); let mut tx_buf = dev.alloc_tx_buffer(len).unwrap(); let ret = f(tx_buf.packet_mut()); - trace!("SEND {} bytes: {:02X?}", len, tx_buf.packet()); dev.transmit(tx_buf).unwrap(); ret } @@ -317,7 +318,7 @@ fn snoop_tcp_packet(buf: &[u8], sockets: &mut SocketSet<'_>) -> Result<(), smolt /// It may receive packets from the NIC and process them, and transmit queued /// packets to the NIC. pub fn poll_interfaces() { - SOCKET_SET.poll_interfaces(); + SOCKET_SET.poll_interfaces(None); } /// Benchmark raw socket transmit bandwidth. diff --git a/modules/ruxnet/src/smoltcp_impl/tcp.rs b/modules/ruxnet/src/smoltcp_impl/tcp.rs index 02613ead5..6b6efa736 100644 --- a/modules/ruxnet/src/smoltcp_impl/tcp.rs +++ b/modules/ruxnet/src/smoltcp_impl/tcp.rs @@ -11,6 +11,7 @@ use core::cell::UnsafeCell; use core::net::SocketAddr; use core::sync::atomic::{AtomicBool, AtomicU8, Ordering}; +use alloc::string::String; use axerrno::{ax_err, ax_err_type, AxError, AxResult}; use axio::PollState; use axsync::Mutex; @@ -53,6 +54,7 @@ pub struct TcpSocket { local_addr: UnsafeCell, peer_addr: UnsafeCell, nonblock: AtomicBool, + iface_name: Mutex>, } unsafe impl Sync for TcpSocket {} @@ -66,6 +68,7 @@ impl TcpSocket { local_addr: UnsafeCell::new(UNSPECIFIED_ENDPOINT), peer_addr: UnsafeCell::new(UNSPECIFIED_ENDPOINT), nonblock: AtomicBool::new(false), + iface_name: Mutex::new(None), } } @@ -81,6 +84,7 @@ impl TcpSocket { local_addr: UnsafeCell::new(local_addr), peer_addr: UnsafeCell::new(peer_addr), nonblock: AtomicBool::new(false), + iface_name: Mutex::new(None), } } @@ -137,6 +141,11 @@ impl TcpSocket { /// /// The local port is generated automatically. pub fn connect(&self, remote_addr: SocketAddr) -> AxResult { + let iface_name = Some(match remote_addr { + SocketAddr::V4(addr) => route_dev(addr.ip().octets()), + _ => panic!("IPv6 not supported"), + }); + *self.iface_name.lock() = iface_name; self.update_state(STATE_CLOSED, STATE_CONNECTING, || { // SAFETY: no other threads can read or write these fields. let handle = unsafe { self.handle.get().read() } @@ -146,13 +155,9 @@ impl TcpSocket { let remote_endpoint = from_core_sockaddr(remote_addr); let bound_endpoint = self.bound_endpoint()?; let binding = IFACE_LIST.lock(); - let iface_name = match remote_addr { - SocketAddr::V4(addr) => route_dev(addr.ip().octets()), - _ => panic!("IPv6 not supported"), - }; let iface = &binding .iter() - .find(|iface| iface.name() == iface_name) + .find(|iface| iface.name() == self.iface_name.lock().clone().unwrap()) .unwrap() .iface; let (local_endpoint, remote_endpoint) = SOCKET_SET @@ -183,24 +188,27 @@ impl TcpSocket { }) .unwrap_or_else(|_| ax_err!(AlreadyExists, "socket connect() failed: already connected"))?; // EISCONN - self.block_on(|| { - let PollState { writable, .. } = self.poll_connect()?; - if !writable { - // When set to non_blocking, directly return inporgress - if self.is_nonblocking() { - return Err(AxError::InProgress); - } - Err(AxError::WouldBlock) - } else if self.get_state() == STATE_CONNECTED { - Ok(()) - } else { - // When set to non_blocking, directly return inporgress - if self.is_nonblocking() { - return Err(AxError::InProgress); + self.block_on( + || { + let PollState { writable, .. } = self.poll_connect()?; + if !writable { + // When set to non_blocking, directly return inporgress + if self.is_nonblocking() { + return Err(AxError::InProgress); + } + Err(AxError::WouldBlock) + } else if self.get_state() == STATE_CONNECTED { + Ok(()) + } else { + // When set to non_blocking, directly return inporgress + if self.is_nonblocking() { + return Err(AxError::InProgress); + } + ax_err!(ConnectionRefused, "socket connect() failed") } - ax_err!(ConnectionRefused, "socket connect() failed") - } - }) + }, + self.iface_name.lock().clone(), + ) } /// Binds an unbound socket to the given address and port. @@ -259,11 +267,14 @@ impl TcpSocket { // SAFETY: `self.local_addr` should be initialized after `bind()`. let local_port = unsafe { self.local_addr.get().read().port }; - self.block_on(|| { - let (handle, (local_addr, peer_addr)) = LISTEN_TABLE.accept(local_port)?; - debug!("TCP socket accepted a new connection {}", peer_addr); - Ok(TcpSocket::new_connected(handle, local_addr, peer_addr)) - }) + self.block_on( + || { + let (handle, (local_addr, peer_addr)) = LISTEN_TABLE.accept(local_port)?; + debug!("TCP socket accepted a new connection {}", peer_addr); + Ok(TcpSocket::new_connected(handle, local_addr, peer_addr)) + }, + None, + ) } /// Close the connection. @@ -278,7 +289,7 @@ impl TcpSocket { socket.close(); }); unsafe { self.local_addr.get().write(UNSPECIFIED_ENDPOINT) }; // clear bound address - SOCKET_SET.poll_interfaces(); + SOCKET_SET.poll_interfaces(None); Ok(()) }) .unwrap_or(Ok(()))?; @@ -290,7 +301,7 @@ impl TcpSocket { let local_port = unsafe { self.local_addr.get().read().port }; unsafe { self.local_addr.get().write(UNSPECIFIED_ENDPOINT) }; // clear bound address LISTEN_TABLE.unlisten(local_port); - SOCKET_SET.poll_interfaces(); + SOCKET_SET.poll_interfaces(None); Ok(()) }) .unwrap_or(Ok(()))?; @@ -309,37 +320,40 @@ impl TcpSocket { // SAFETY: `self.handle` should be initialized in a connected socket. let handle = unsafe { self.handle.get().read().unwrap() }; - self.block_on(|| { - SOCKET_SET.with_socket_mut::(handle, |socket| { - if !socket.is_active() { - // not open - ax_err!(ConnectionRefused, "socket recv() failed") - } else if !socket.may_recv() { - // connection closed - Ok(0) - } else if socket.recv_queue() > 0 { - // data available - // TODO: use socket.recv(|buf| {...}) - if flags & MSG_DONTWAIT != 0 { - self.set_nonblocking(true); - } - if flags & MSG_PEEK != 0 { - let len = socket - .peek_slice(buf) - .map_err(|_| ax_err_type!(BadState, "socket recv() failed"))?; - Ok(len) + self.block_on( + || { + SOCKET_SET.with_socket_mut::(handle, |socket| { + if !socket.is_active() { + // not open + ax_err!(ConnectionRefused, "socket recv() failed") + } else if !socket.may_recv() { + // connection closed + Ok(0) + } else if socket.recv_queue() > 0 { + // data available + // TODO: use socket.recv(|buf| {...}) + if flags & MSG_DONTWAIT != 0 { + self.set_nonblocking(true); + } + if flags & MSG_PEEK != 0 { + let len = socket + .peek_slice(buf) + .map_err(|_| ax_err_type!(BadState, "socket recv() failed"))?; + Ok(len) + } else { + let len = socket + .recv_slice(buf) + .map_err(|_| ax_err_type!(BadState, "socket recv() failed"))?; + Ok(len) + } } else { - let len = socket - .recv_slice(buf) - .map_err(|_| ax_err_type!(BadState, "socket recv() failed"))?; - Ok(len) + // no more data + Err(AxError::WouldBlock) } - } else { - // no more data - Err(AxError::WouldBlock) - } - }) - }) + }) + }, + None, + ) } /// Transmits data in the given buffer. @@ -353,24 +367,27 @@ impl TcpSocket { // SAFETY: `self.handle` should be initialized in a connected socket. let handle = unsafe { self.handle.get().read().unwrap() }; - self.block_on(|| { - SOCKET_SET.with_socket_mut::(handle, |socket| { - if !socket.is_active() || !socket.may_send() { - // closed by remote - ax_err!(ConnectionReset, "socket send() failed") - } else if socket.can_send() { - // connected, and the tx buffer is not full - // TODO: use socket.send(|buf| {...}) - let len = socket - .send_slice(buf) - .map_err(|_| ax_err_type!(BadState, "socket send() failed"))?; - Ok(len) - } else { - // tx buffer is full - Err(AxError::WouldBlock) - } - }) - }) + self.block_on( + || { + SOCKET_SET.with_socket_mut::(handle, |socket| { + if !socket.is_active() || !socket.may_send() { + // closed by remote + ax_err!(ConnectionReset, "socket send() failed") + } else if socket.can_send() { + // connected, and the tx buffer is not full + // TODO: use socket.send(|buf| {...}) + let len = socket + .send_slice(buf) + .map_err(|_| ax_err_type!(BadState, "socket send() failed"))?; + Ok(len) + } else { + // tx buffer is full + Err(AxError::WouldBlock) + } + }) + }, + self.iface_name.lock().clone(), + ) } /// Whether the socket is readable or writable. @@ -517,16 +534,19 @@ impl TcpSocket { /// If the socket is non-blocking, it calls the function once and returns /// immediately. Otherwise, it may call the function multiple times if it /// returns [`Err(WouldBlock)`](AxError::WouldBlock). - fn block_on(&self, mut f: F) -> AxResult + fn block_on(&self, mut f: F, iface: Option) -> AxResult where F: FnMut() -> AxResult, { if self.is_nonblocking() { - f() + let res = f(); + SOCKET_SET.poll_interfaces(iface.clone()); + res } else { loop { - SOCKET_SET.poll_interfaces(); - match f() { + let res = f(); + SOCKET_SET.poll_interfaces(iface.clone()); + match res { Ok(t) => return Ok(t), Err(AxError::WouldBlock) => ruxtask::yield_now(), Err(e) => return Err(e), diff --git a/modules/ruxnet/src/smoltcp_impl/udp.rs b/modules/ruxnet/src/smoltcp_impl/udp.rs index db1692ca8..294f74098 100644 --- a/modules/ruxnet/src/smoltcp_impl/udp.rs +++ b/modules/ruxnet/src/smoltcp_impl/udp.rs @@ -10,6 +10,7 @@ use core::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; use core::sync::atomic::{AtomicBool, Ordering}; +use alloc::string::String; use axerrno::{ax_err, ax_err_type, AxError, AxResult}; use axio::PollState; use axsync::Mutex; @@ -20,7 +21,7 @@ use smoltcp::socket::udp::{self, BindError, SendError}; use smoltcp::wire::{IpEndpoint, IpListenEndpoint}; use super::addr::{from_core_sockaddr, into_core_sockaddr, is_unspecified, UNSPECIFIED_ENDPOINT}; -use super::{SocketSetWrapper, SOCKET_SET}; +use super::{route_dev, SocketSetWrapper, SOCKET_SET}; /// A UDP socket that provides POSIX-like APIs. pub struct UdpSocket { @@ -185,7 +186,7 @@ impl UdpSocket { debug!("UDP socket {}: shutting down", self.handle); socket.close(); }); - SOCKET_SET.poll_interfaces(); + SOCKET_SET.poll_interfaces(None); Ok(()) } @@ -223,24 +224,31 @@ impl UdpSocket { self.bind(res)?; } - self.block_on(|| { - SOCKET_SET.with_socket_mut::(self.handle, |socket| { - if socket.can_send() { - socket - .send_slice(buf, remote_endpoint) - .map_err(|e| match e { - SendError::BufferFull => AxError::WouldBlock, - SendError::Unaddressable => { - ax_err_type!(ConnectionRefused, "socket send() failed") - } - })?; - Ok(buf.len()) - } else { - // tx buffer is full - Err(AxError::WouldBlock) - } - }) - }) + let mut addr = [0u8; 4]; + addr.copy_from_slice(remote_endpoint.addr.as_bytes()); + let iface_name = route_dev(addr); + + self.block_on( + || { + SOCKET_SET.with_socket_mut::(self.handle, |socket| { + if socket.can_send() { + socket + .send_slice(buf, remote_endpoint) + .map_err(|e| match e { + SendError::BufferFull => AxError::WouldBlock, + SendError::Unaddressable => { + ax_err_type!(ConnectionRefused, "socket send() failed") + } + })?; + Ok(buf.len()) + } else { + // tx buffer is full + Err(AxError::WouldBlock) + } + }) + }, + Some(iface_name), + ) } fn recv_impl(&self, mut op: F) -> AxResult @@ -251,29 +259,35 @@ impl UdpSocket { return ax_err!(NotConnected, "socket send() failed"); } - self.block_on(|| { - SOCKET_SET.with_socket_mut::(self.handle, |socket| { - if socket.can_recv() { - // data available - op(socket) - } else { - // no more data - Err(AxError::WouldBlock) - } - }) - }) + self.block_on( + || { + SOCKET_SET.with_socket_mut::(self.handle, |socket| { + if socket.can_recv() { + // data available + op(socket) + } else { + // no more data + Err(AxError::WouldBlock) + } + }) + }, + None, + ) } - fn block_on(&self, mut f: F) -> AxResult + fn block_on(&self, mut f: F, iface: Option) -> AxResult where F: FnMut() -> AxResult, { if self.is_nonblocking() { - f() + let res = f(); + SOCKET_SET.poll_interfaces(iface.clone()); + res } else { loop { - SOCKET_SET.poll_interfaces(); - match f() { + let res = f(); + SOCKET_SET.poll_interfaces(iface.clone()); + match res { Ok(t) => return Ok(t), Err(AxError::WouldBlock) => ruxtask::yield_now(), Err(e) => return Err(e), From 3d8ce37e55cf2b96811c12b7d6ee7b5cbde5b9e7 Mon Sep 17 00:00:00 2001 From: Stone749990226 <749990226@qq.com> Date: Mon, 17 Feb 2025 16:46:34 +0800 Subject: [PATCH 2/2] chore: minor tweaks for future sshd support empty implement for sys_setsid, add SO_BINDTODEVICE for sys_getsockopt, add a new user in `passwd` file, add setitimer syscall id for aarch64 --- api/ruxos_posix_api/src/imp/net.rs | 3 ++- api/ruxos_posix_api/src/imp/stat.rs | 8 ++++++++ api/ruxos_posix_api/src/lib.rs | 2 +- modules/ruxfs/src/mounts.rs | 10 +++++++++- ulib/ruxmusl/src/aarch64/mod.rs | 3 +++ ulib/ruxmusl/src/aarch64/syscall_id.rs | 3 +++ 6 files changed, 26 insertions(+), 3 deletions(-) diff --git a/api/ruxos_posix_api/src/imp/net.rs b/api/ruxos_posix_api/src/imp/net.rs index 7ff277d39..3ae12d505 100644 --- a/api/ruxos_posix_api/src/imp/net.rs +++ b/api/ruxos_posix_api/src/imp/net.rs @@ -852,7 +852,8 @@ pub fn sys_getsockopt( | ctypes::SO_RCVTIMEO | ctypes::SO_REUSEADDR | ctypes::SO_SNDBUF - | ctypes::SO_SNDTIMEO => 0, + | ctypes::SO_SNDTIMEO + | ctypes::SO_BINDTODEVICE => 0, _ => return Err(LinuxError::ENOPROTOOPT), }; diff --git a/api/ruxos_posix_api/src/imp/stat.rs b/api/ruxos_posix_api/src/imp/stat.rs index ecb25edf2..706d03bc5 100644 --- a/api/ruxos_posix_api/src/imp/stat.rs +++ b/api/ruxos_posix_api/src/imp/stat.rs @@ -61,3 +61,11 @@ pub fn sys_setpgid(pid: pid_t, pgid: pid_t) -> c_int { debug!("sys_setpgid: pid {}, pgid {} ", pid, pgid); syscall_body!(sys_setpgid, Ok(0)) } + +/// set process sid (empty implementation) +/// +/// TODO: +pub fn sys_setsid() -> c_int { + warn!("sys_setsid: do nothing",); + syscall_body!(sys_setsid, Ok(0)) +} diff --git a/api/ruxos_posix_api/src/lib.rs b/api/ruxos_posix_api/src/lib.rs index 07f564e73..98e8a771b 100644 --- a/api/ruxos_posix_api/src/lib.rs +++ b/api/ruxos_posix_api/src/lib.rs @@ -52,7 +52,7 @@ pub use imp::prctl::{sys_arch_prctl, sys_prctl}; pub use imp::resources::{sys_getrlimit, sys_prlimit64, sys_setrlimit}; pub use imp::stat::{ sys_getegid, sys_geteuid, sys_getgid, sys_getpgid, sys_getuid, sys_setgid, sys_setpgid, - sys_setuid, sys_umask, + sys_setsid, sys_setuid, sys_umask, }; pub use imp::sys::{sys_sysinfo, sys_uname}; pub use imp::sys_invalid; diff --git a/modules/ruxfs/src/mounts.rs b/modules/ruxfs/src/mounts.rs index 39a65abc6..0f218ac10 100644 --- a/modules/ruxfs/src/mounts.rs +++ b/modules/ruxfs/src/mounts.rs @@ -101,7 +101,11 @@ pub(crate) fn etcfs() -> VfsResult> { etc_root.create("passwd", VfsNodeType::File)?; let file_passwd = etc_root.clone().lookup("passwd")?; // format: username:password:uid:gid:allname:homedir:shell - file_passwd.write_at(0, b"root:x:0:0:root:/root:/bin/bash\n")?; + file_passwd.write_at( + 0, + b"root:x:0:0:root:/root:/bin/busybox\n\ + syswonder:x:1000:1000:root:/root:/bin/busybox\n", + )?; // Create /etc/group etc_root.create("group", VfsNodeType::File)?; @@ -125,6 +129,10 @@ pub(crate) fn etcfs() -> VfsResult> { ff02::3 ip6-allhosts\n", )?; + etc_root.create("services", VfsNodeType::File)?; + let file_services = etc_root.clone().lookup("services")?; + file_services.write_at(0, b"ssh 22/tcp")?; + // Create /etc/resolv.conf etc_root.create("resolv.conf", VfsNodeType::File)?; let file_resolv = etc_root.clone().lookup("resolv.conf")?; diff --git a/ulib/ruxmusl/src/aarch64/mod.rs b/ulib/ruxmusl/src/aarch64/mod.rs index 1e11c624f..900db3230 100644 --- a/ulib/ruxmusl/src/aarch64/mod.rs +++ b/ulib/ruxmusl/src/aarch64/mod.rs @@ -220,6 +220,8 @@ pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize { args[0] as *const ctypes::timespec, args[1] as *mut ctypes::timespec, ) as _, + #[cfg(feature = "signal")] + SyscallId::SETITIMER => ruxos_posix_api::sys_setitimer(args[0] as _, args[1] as _) as _, SyscallId::CLOCK_SETTIME => ruxos_posix_api::sys_clock_settime( args[0] as ctypes::clockid_t, args[1] as *const ctypes::timespec, @@ -269,6 +271,7 @@ pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize { ruxos_posix_api::sys_setpgid(args[0] as pid_t, args[1] as pid_t) as _ } SyscallId::GETPGID => ruxos_posix_api::sys_getpgid(args[0] as pid_t) as _, + SyscallId::SETSID => ruxos_posix_api::sys_setsid() as _, SyscallId::UNAME => ruxos_posix_api::sys_uname(args[0] as *mut core::ffi::c_void) as _, SyscallId::GETRLIMIT => { ruxos_posix_api::sys_getrlimit(args[0] as c_int, args[1] as *mut ctypes::rlimit) diff --git a/ulib/ruxmusl/src/aarch64/syscall_id.rs b/ulib/ruxmusl/src/aarch64/syscall_id.rs index 8e2b9490b..06de80ac1 100644 --- a/ulib/ruxmusl/src/aarch64/syscall_id.rs +++ b/ulib/ruxmusl/src/aarch64/syscall_id.rs @@ -80,6 +80,8 @@ pub enum SyscallId { #[cfg(feature = "multitask")] FUTEX = 98, NANO_SLEEP = 101, + #[cfg(feature = "signal")] + SETITIMER = 103, CLOCK_SETTIME = 112, CLOCK_GETTIME = 113, CLOCK_GETRES = 114, @@ -100,6 +102,7 @@ pub enum SyscallId { TIMES = 153, SETPGID = 154, GETPGID = 155, + SETSID = 157, UNAME = 160, GETRLIMIT = 163, SETRLIMIT = 164,