diff --git a/modules/axnet/Cargo.toml b/modules/axnet/Cargo.toml index b9c1903e..f982a6f1 100644 --- a/modules/axnet/Cargo.toml +++ b/modules/axnet/Cargo.toml @@ -44,7 +44,7 @@ features = [ "medium-ethernet", "medium-ip", "proto-ipv4", - "socket-raw", "socket-icmp", "socket-udp", "socket-tcp", "socket-dns", + "socket-raw", "socket-icmp", "socket-udp", "socket-tcp", "socket-dns", "proto-igmp", # "fragmentation-buffer-size-65536", "proto-ipv4-fragmentation", # "reassembly-buffer-size-65536", "reassembly-buffer-count-32", # "assembler-max-segment-count-32", diff --git a/modules/axnet/src/smoltcp_impl/udp.rs b/modules/axnet/src/smoltcp_impl/udp.rs index 1030f10c..bc8ab1b4 100644 --- a/modules/axnet/src/smoltcp_impl/udp.rs +++ b/modules/axnet/src/smoltcp_impl/udp.rs @@ -1,4 +1,5 @@ use core::net::SocketAddr; +use core::ops::DerefMut; use core::sync::atomic::{AtomicBool, Ordering}; use axerrno::{ax_err, ax_err_type, AxError, AxResult}; @@ -7,6 +8,11 @@ use axio::{PollState, Read, Write}; use axsync::Mutex; use spin::RwLock; +use crate::net_impl::{current_time_nanos, NANOS_PER_MICROS}; +use crate::net_impl::{LOOPBACK, LOOPBACK_DEV}; +use smoltcp::time::Instant; +use smoltcp::wire::IpAddress as IpAddr; + use smoltcp::iface::SocketHandle; use smoltcp::socket::udp::{self, BindError, SendError}; use smoltcp::wire::{IpEndpoint, IpListenEndpoint}; @@ -190,11 +196,11 @@ impl UdpSocket { /// Close the socket. pub fn shutdown(&self) -> AxResult { + SOCKET_SET.poll_interfaces(); SOCKET_SET.with_socket_mut::(self.handle, |socket| { debug!("UDP socket {}: shutting down", self.handle); socket.close(); }); - SOCKET_SET.poll_interfaces(); Ok(()) } @@ -213,6 +219,21 @@ impl UdpSocket { }) }) } + + pub fn set_socket_ttl(&self, ttl: u8) { + SOCKET_SET.with_socket_mut::(self.handle, |socket| { + socket.set_hop_limit(Some(ttl)) + }); + } + + pub fn add_membership(&self, multicast_addr: IpAddr, interface_addr: IpAddr) { + let timestamp = Instant::from_micros_const((current_time_nanos() / NANOS_PER_MICROS) as i64); + error!( + ">>> setsockopt IP_ADD_MEMBERSHIP: multiaddr: {}, interfaceaddr: {}", + multicast_addr, interface_addr + ); + let _ = LOOPBACK.lock().join_multicast_group(LOOPBACK_DEV.lock().deref_mut(), multicast_addr, timestamp); + } } /// Private methods diff --git a/ulib/axstarry/src/syscall_fs/imp/io.rs b/ulib/axstarry/src/syscall_fs/imp/io.rs index dcb8c3d0..5108661f 100644 --- a/ulib/axstarry/src/syscall_fs/imp/io.rs +++ b/ulib/axstarry/src/syscall_fs/imp/io.rs @@ -418,9 +418,6 @@ pub fn syscall_open(args: [usize; 6]) -> SyscallResult { pub fn syscall_close(args: [usize; 6]) -> SyscallResult { let fd = args[0]; info!("Into syscall_close. fd: {}", fd); - - error!(">>> Into syscall_close. fd: {}", fd); - let process = current_process(); let mut fd_table = process.fd_manager.fd_table.lock(); if fd >= fd_table.len() { diff --git a/ulib/axstarry/src/syscall_net/imp.rs b/ulib/axstarry/src/syscall_net/imp.rs index 0b09314e..daad6a10 100644 --- a/ulib/axstarry/src/syscall_net/imp.rs +++ b/ulib/axstarry/src/syscall_net/imp.rs @@ -14,6 +14,9 @@ use axnet::{into_core_sockaddr, IpAddr, SocketAddr}; use axprocess::current_process; use num_enum::TryFromPrimitive; +use alloc::vec::Vec; +use core::str; + pub const SOCKET_TYPE_MASK: usize = 0xFF; /// # Arguments @@ -266,6 +269,27 @@ pub fn syscall_getpeername(args: [usize; 6]) -> SyscallResult { Err(_) => unreachable!(), } } +/// extracts valid UTF-8 strings from a byte slice. +pub fn extract_valid_utf8(input: [u8]) -> Vec<&str> { + let input_str = match str::from_utf8(input) { + Ok(s) => s, + Err(_) => return Vec::new(), + }; + + let mut valid_utf8_strings = Vec::new(); + + let mut start = 0; + for (end, _) in input_str.char_indices() { + if str::from_utf8(&input[start..end]).is_ok() { + valid_utf8_strings.push(&input_str[start..end]); + start = end; + } + } + + valid_utf8_strings +} + + // TODO: flags /// Calling sendto() will bind the socket if it's not bound. @@ -322,10 +346,18 @@ pub fn syscall_sendto(args: [usize; 6]) -> SyscallResult { } else { None }; + let inner = socket.inner.lock(); let send_result = match &*inner { SocketInner::Udp(s) => { error!(">>> udp sendto "); + let valid_utf8_strings = extract_valid_utf8(&buf); + for s in valid_utf8_strings { + if s.len() > 0 { + error!(">>> udp {:?} send: {}", socket.name(), s); + } + } + // udp socket not bound if s.local_addr().is_err() { s.bind(into_core_sockaddr(SocketAddr::new_ipv4( @@ -335,7 +367,9 @@ pub fn syscall_sendto(args: [usize; 6]) -> SyscallResult { .unwrap(); } match addr { - Some(addr) => s.send_to(buf, into_core_sockaddr(addr.into())), + Some(addr) => { + s.send_to(buf, into_core_sockaddr(addr.into())) + }, None => { // not connected and no target is given if s.peer_addr().is_err() { @@ -431,6 +465,14 @@ pub fn syscall_recvfrom(args: [usize; 6]) -> SyscallResult { } let buf = unsafe { from_raw_parts_mut(buf, len) }; info!("recv addr: {:?}", socket.name().unwrap()); + + let valid_utf8_strings = extract_valid_utf8(&buf); + for s in valid_utf8_strings { + if s.len() > 0 { + error!(">>> udp {:?} recv_from: {}", socket.name(), s); + } + } + match socket.recv_from(buf) { Ok((len, addr)) => { info!("socket {fd} recv {len} bytes from {addr:?}"); @@ -483,15 +525,21 @@ pub fn syscall_set_sock_opt(args: [usize; 6]) -> SyscallResult { let opt = unsafe { from_raw_parts(opt_value, opt_len as usize) }; match level { - SocketOptionLevel::IP => Ok(0), + SocketOptionLevel::IP => { + let Ok(option) = IpOption::try_from(opt_name) else { + warn!("[setsockopt()] option {opt_name} not supported in socket level"); + return Ok(0); + }; + + option.set(socket, opt) + } SocketOptionLevel::Socket => { let Ok(option) = SocketOption::try_from(opt_name) else { warn!("[setsockopt()] option {opt_name} not supported in socket level"); return Ok(0); }; - option.set(socket, opt); - Ok(0) + option.set(socket, opt) } SocketOptionLevel::Tcp => { let Ok(option) = TcpSocketOption::try_from(opt_name) else { diff --git a/ulib/axstarry/src/syscall_net/socket.rs b/ulib/axstarry/src/syscall_net/socket.rs index f540cb92..ef550502 100644 --- a/ulib/axstarry/src/syscall_net/socket.rs +++ b/ulib/axstarry/src/syscall_net/socket.rs @@ -18,7 +18,7 @@ use axnet::{ use axsync::Mutex; use num_enum::TryFromPrimitive; -use crate::TimeVal; +use crate::{SyscallError, SyscallResult, TimeVal}; pub const SOCKET_TYPE_MASK: usize = 0xFF; @@ -68,6 +68,16 @@ pub enum SocketOptionLevel { Tcp = 6, } +#[derive(TryFromPrimitive, Debug)] +#[repr(usize)] +#[allow(non_camel_case_types)] +pub enum IpOption { + IP_MULTICAST_IF = 32, + IP_MULTICAST_TTL = 33, + IP_MULTICAST_LOOP = 34, + IP_ADD_MEMBERSHIP = 35, +} + #[derive(TryFromPrimitive, Debug)] #[repr(usize)] #[allow(non_camel_case_types)] @@ -79,6 +89,7 @@ pub enum SocketOption { SO_RCVBUF = 8, SO_KEEPALIVE = 9, SO_RCVTIMEO = 20, + SO_SNDTIMEO = 21, } #[derive(TryFromPrimitive, PartialEq)] @@ -91,8 +102,55 @@ pub enum TcpSocketOption { TCP_CONGESTION = 13, } +impl IpOption { + pub fn set(&self, socket: &Socket, opt: &[u8]) -> SyscallResult { + match self { + IpOption::IP_MULTICAST_IF => { + // 我们只会使用LOOPBACK作为多播接口 + Ok((0)) + } + IpOption::IP_MULTICAST_TTL => { + let mut inner = socket.inner.lock(); + match &mut *inner { + SocketInner::Udp(s) => { + let ttl = u8::from_ne_bytes(<[u8; 1]>::try_from(&opt[0..1]).unwrap()); + s.set_socket_ttl(ttl as u8); + Ok((0)) + } + _ => panic!("setsockopt IP_MULTICAST_TTL on a non-udp socket"), + } + } + IpOption::IP_MULTICAST_LOOP => { + Ok((0)) + } + IpOption::IP_ADD_MEMBERSHIP => { + let multicast_addr = IpAddr::v4( + opt[0], + opt[1], + opt[2], + opt[3], + ); + let interface_addr = IpAddr::v4( + opt[4], + opt[5], + opt[6], + opt[7], + ); + let mut inner = socket.inner.lock(); + match &mut *inner { + SocketInner::Udp(s) => { + s.add_membership(multicast_addr, interface_addr) + } + _ => panic!("setsockopt IP_ADD_MEMBERSHIP on a non-udp socket"), + } + Ok((0)) + } + } + } +} + impl SocketOption { - pub fn set(&self, socket: &Socket, opt: &[u8]) { + pub fn set(&self, socket: &Socket, opt: &[u8]) -> SyscallResult { match self { SocketOption::SO_REUSEADDR => { if opt.len() < 4 { @@ -103,6 +161,7 @@ impl SocketOption { socket.set_reuse_addr(opt_value != 0); // socket.reuse_addr = opt_value != 0; + Ok((0)) } SocketOption::SO_DONTROUTE => { if opt.len() < 4 { @@ -113,6 +172,7 @@ impl SocketOption { socket.set_reuse_addr(opt_value != 0); // socket.reuse_addr = opt_value != 0; + Ok((0)) } SocketOption::SO_SNDBUF => { if opt.len() < 4 { @@ -123,6 +183,7 @@ impl SocketOption { socket.set_send_buf_size(opt_value as u64); // socket.send_buf_size = opt_value as usize; + Ok((0)) } SocketOption::SO_RCVBUF => { if opt.len() < 4 { @@ -133,6 +194,7 @@ impl SocketOption { socket.set_recv_buf_size(opt_value as u64); // socket.recv_buf_size = opt_value as usize; + Ok((0)) } SocketOption::SO_KEEPALIVE => { if opt.len() < 4 { @@ -164,6 +226,7 @@ impl SocketOption { drop(inner); socket.set_recv_buf_size(opt_value as u64); // socket.recv_buf_size = opt_value as usize; + Ok((0)) } SocketOption::SO_RCVTIMEO => { if opt.len() < size_of::() { @@ -176,10 +239,14 @@ impl SocketOption { } else { Some(timeout) }); + Ok((0)) } SocketOption::SO_ERROR => { panic!("can't set SO_ERROR"); } + SocketOption::SO_SNDTIMEO => { + Err(SyscallError::EPERM) + } } } @@ -285,6 +352,9 @@ impl SocketOption { SocketOption::SO_ERROR => { // 当前没有存储错误列表,因此不做处理 } + SocketOption::SO_SNDTIMEO => { + panic!("unimplemented!") + } } } } @@ -446,15 +516,12 @@ impl Socket { pub fn new(domain: Domain, socket_type: SocketType, protocol: usize) -> Self { let inner = match socket_type { SocketType::SOCK_STREAM | SocketType::SOCK_SEQPACKET => { - error!(">>>>>>>>> socket_type is: SOCK_STREAM"); SocketInner::Tcp(TcpSocket::new()) } SocketType::SOCK_DGRAM => { - error!(">>>>>>>>> socket_type is: SOCK_DGRAM: {}", protocol); SocketInner::Udp(UdpSocket::new()) } SocketType::SOCK_RAW => { - error!(">>>>>>>>> socket_type is: SOCK_RAW"); let Ok(proto) = NetlinkProto::try_from(protocol) else { unimplemented!() }; @@ -537,15 +604,13 @@ impl Socket { let mut inner = self.inner.lock(); match &mut *inner { SocketInner::Tcp(s) => { - error!(">>> tcp bind "); s.bind(into_core_sockaddr(addr.into())) } SocketInner::Udp(s) => { - error!(">>> udp bind "); - s.bind(into_core_sockaddr(addr.into())) + let ret = s.bind(into_core_sockaddr(addr.into())); + ret } SocketInner::Netlink(s) => { - error!(">>> netlink bind "); s.bind(addr.nl_groups) } } @@ -639,7 +704,6 @@ impl Socket { let inner = self.inner.lock(); match &*inner { SocketInner::Tcp(s) => { - error!(">>> tcp recv_from "); let addr = s.peer_addr()?; match self.get_recv_timeout() { @@ -650,7 +714,6 @@ impl Socket { .map(|(len, sa)| (len, SocketAddr::from(sa))) } SocketInner::Udp(s) => { - error!(">>> udp recv_from "); match self.get_recv_timeout() { Some(time) => s .recv_from_timeout(buf, time.turn_to_ticks()) @@ -663,7 +726,6 @@ impl Socket { } } SocketInner::Netlink(s) => { - error!(">>> netlink recv_from "); s.recv_from(buf) .map(|val| (val, SocketAddr::new_netlink(s.nl_groups))) },