diff --git a/kernel/src/net/posix.rs b/kernel/src/net/posix.rs index 693e2214..798be768 100644 --- a/kernel/src/net/posix.rs +++ b/kernel/src/net/posix.rs @@ -109,7 +109,6 @@ impl SockAddr { use crate::net::socket::AddressFamily; let addr = unsafe { addr.as_ref() }.ok_or(SystemError::EFAULT)?; - unsafe { match AddressFamily::try_from(addr.family)? { AddressFamily::INet => { @@ -128,6 +127,22 @@ impl SockAddr { return Ok(Endpoint::Ip(wire::IpEndpoint::new(ip, port))); } + AddressFamily::INet6 => { + if len < addr.len()? { + log::error!("len < addr.len()"); + return Err(SystemError::EINVAL); + } + log::debug!("INet6"); + let addr_in: SockAddrIn = addr.addr_in; + + use smoltcp::wire; + let ip: wire::IpAddress = wire::IpAddress::from(wire::Ipv6Address::from_bytes( + &u32::from_be(addr_in.sin_addr).to_be_bytes()[..], + )); + let port = u16::from_be(addr_in.sin_port); + + return Ok(Endpoint::Ip(wire::IpEndpoint::new(ip, port))); + } AddressFamily::Unix => { let addr_un: SockAddrUn = addr.addr_un; diff --git a/kernel/src/net/socket/family.rs b/kernel/src/net/socket/family.rs index 1e0e7135..3a17feb0 100644 --- a/kernel/src/net/socket/family.rs +++ b/kernel/src/net/socket/family.rs @@ -102,14 +102,14 @@ pub enum AddressFamily { Max = 46, } -use system_error::SystemError; - impl core::convert::TryFrom for AddressFamily { type Error = system_error::SystemError; fn try_from(x: u16) -> Result { use num_traits::FromPrimitive; - use SystemError::*; - return ::from_u16(x).ok_or(EINVAL); + return ::from_u16(x).ok_or({ + log::debug!("AddressFamily::try_from failed: x={}", x); + Self::Error::EINVAL + }); } } @@ -117,5 +117,8 @@ use crate::net::socket; use alloc::sync::Arc; pub trait Family { - fn socket(stype: socket::PSOCK, protocol: u32) -> Result, SystemError>; + fn socket( + stype: socket::PSOCK, + protocol: u32, + ) -> Result, system_error::SystemError>; } diff --git a/kernel/src/net/socket/inet/mod.rs b/kernel/src/net/socket/inet/mod.rs index 074208ca..1955234e 100644 --- a/kernel/src/net/socket/inet/mod.rs +++ b/kernel/src/net/socket/inet/mod.rs @@ -22,8 +22,10 @@ use smoltcp::wire::*; /// According to the Linux man pages and the Linux implementation, `getsockname()` will _not_ fail /// even if the socket is unbound. Instead, it will return an unspecified socket address. This /// unspecified endpoint helps with that. -const UNSPECIFIED_LOCAL_ENDPOINT: IpEndpoint = +const UNSPECIFIED_LOCAL_ENDPOINT_V4: IpEndpoint = IpEndpoint::new(IpAddress::Ipv4(Ipv4Address::UNSPECIFIED), 0); +const UNSPECIFIED_LOCAL_ENDPOINT_V6: IpEndpoint = + IpEndpoint::new(IpAddress::Ipv6(Ipv6Address::UNSPECIFIED), 0); pub trait InetSocket: Socket { /// `on_iface_events` diff --git a/kernel/src/net/socket/inet/stream/inner.rs b/kernel/src/net/socket/inet/stream/inner.rs index 5e093832..20f7943f 100644 --- a/kernel/src/net/socket/inet/stream/inner.rs +++ b/kernel/src/net/socket/inet/stream/inner.rs @@ -8,7 +8,7 @@ use alloc::vec::Vec; use smoltcp; use system_error::SystemError::{self, *}; -use super::inet::UNSPECIFIED_LOCAL_ENDPOINT; +use super::inet::UNSPECIFIED_LOCAL_ENDPOINT_V4; // pub const DEFAULT_METADATA_BUF_SIZE: usize = 1024; pub const DEFAULT_RX_BUF_SIZE: usize = 512 * 1024; @@ -31,13 +31,13 @@ where #[derive(Debug)] pub enum Init { - Unbound(Box>), + Unbound((Box>, bool)), Bound((socket::inet::BoundInner, smoltcp::wire::IpEndpoint)), } impl Init { - pub(super) fn new() -> Self { - Init::Unbound(Box::new(new_smoltcp_socket())) + pub(super) fn new(v4: bool) -> Self { + Init::Unbound((Box::new(new_smoltcp_socket()), v4)) } /// 传入一个已经绑定的socket @@ -55,7 +55,7 @@ impl Init { local_endpoint: smoltcp::wire::IpEndpoint, ) -> Result { match self { - Init::Unbound(socket) => { + Init::Unbound((socket, _)) => { let bound = socket::inet::BoundInner::bind(*socket, &local_endpoint.addr)?; bound .port_manager() @@ -63,7 +63,10 @@ impl Init { // bound.iface().common().bind_socket() Ok(Init::Bound((bound, local_endpoint))) } - Init::Bound(_) => Err(EINVAL), + Init::Bound(_) => { + log::debug!("Already Bound"); + Err(EINVAL) + } } } @@ -72,14 +75,14 @@ impl Init { remote_endpoint: smoltcp::wire::IpEndpoint, ) -> Result<(socket::inet::BoundInner, smoltcp::wire::IpEndpoint), (Self, SystemError)> { match self { - Init::Unbound(socket) => { + Init::Unbound((socket, v4)) => { let (bound, address) = socket::inet::BoundInner::bind_ephemeral(*socket, remote_endpoint.addr) - .map_err(|err| (Self::new(), err))?; + .map_err(|err| (Self::new(v4), err))?; let bound_port = bound .port_manager() .bind_ephemeral_port(Types::Tcp) - .map_err(|err| (Self::new(), err))?; + .map_err(|err| (Self::new(v4), err))?; let endpoint = smoltcp::wire::IpEndpoint::new(address, bound_port); Ok((bound, endpoint)) } @@ -308,7 +311,8 @@ impl Listening { if let Some(name) = socket.local_endpoint() { return name; } else { - return UNSPECIFIED_LOCAL_ENDPOINT; + // TODO: IPV6 + return UNSPECIFIED_LOCAL_ENDPOINT_V4; } }) } diff --git a/kernel/src/net/socket/inet/stream/mod.rs b/kernel/src/net/socket/inet/stream/mod.rs index 7a416bdd..5cd9e928 100644 --- a/kernel/src/net/socket/inet/stream/mod.rs +++ b/kernel/src/net/socket/inet/stream/mod.rs @@ -7,7 +7,7 @@ use crate::net::event_poll::EPollEventType; use crate::net::net_core::poll_ifaces; use crate::net::socket::*; use crate::sched::SchedMode; -use inet::{InetSocket, UNSPECIFIED_LOCAL_ENDPOINT}; +use inet::{InetSocket, UNSPECIFIED_LOCAL_ENDPOINT_V4, UNSPECIFIED_LOCAL_ENDPOINT_V6}; use smoltcp; mod inner; @@ -29,9 +29,9 @@ pub struct TcpSocket { } impl TcpSocket { - pub fn new(nonblock: bool) -> Arc { + pub fn new(nonblock: bool, v4: bool) -> Arc { Arc::new_cyclic(|me| Self { - inner: RwLock::new(Some(Inner::Init(Init::new()))), + inner: RwLock::new(Some(Inner::Init(Init::new(v4)))), shutdown: Shutdown::new(), nonblock: AtomicBool::new(nonblock), wait_queue: WaitQueue::default(), @@ -69,7 +69,11 @@ impl TcpSocket { writer.replace(Inner::Init(bound)); Ok(()) } - _ => Err(EINVAL), + any => { + writer.replace(any); + log::error!("TcpSocket::do_bind: not Init"); + Err(EINVAL) + } } } @@ -230,7 +234,13 @@ impl Socket for TcpSocket { fn get_name(&self) -> Result { match self.inner.read().as_ref().expect("Tcp Inner is None") { - Inner::Init(Init::Unbound(_)) => Ok(Endpoint::Ip(UNSPECIFIED_LOCAL_ENDPOINT)), + Inner::Init(Init::Unbound((_, v4))) => { + if *v4 { + Ok(Endpoint::Ip(UNSPECIFIED_LOCAL_ENDPOINT_V4)) + } else { + Ok(Endpoint::Ip(UNSPECIFIED_LOCAL_ENDPOINT_V6)) + } + } Inner::Init(Init::Bound((_, local))) => Ok(Endpoint::Ip(*local)), Inner::Connecting(connecting) => Ok(Endpoint::Ip(connecting.get_name())), Inner::Established(established) => Ok(Endpoint::Ip(established.local_endpoint())), @@ -242,6 +252,7 @@ impl Socket for TcpSocket { if let Endpoint::Ip(addr) = endpoint { return self.do_bind(addr); } + log::warn!("TcpSocket::bind: invalid endpoint"); return Err(EINVAL); } diff --git a/kernel/src/net/socket/inet/syscall.rs b/kernel/src/net/socket/inet/syscall.rs index a89ce13e..bb541f87 100644 --- a/kernel/src/net/socket/inet/syscall.rs +++ b/kernel/src/net/socket/inet/syscall.rs @@ -8,6 +8,7 @@ use inet::{TcpSocket, UdpSocket}; use crate::net::socket::*; fn create_inet_socket( + v4: bool, socket_type: PSOCK, protocol: smoltcp::wire::IpProtocol, ) -> Result, SystemError> { @@ -16,7 +17,8 @@ fn create_inet_socket( match socket_type { PSOCK::Datagram => match protocol { HopByHop | Udp => { - return Ok(UdpSocket::new(false)); + return Err(EPROTONOSUPPORT); + // return Ok(UdpSocket::new(false)); } _ => { return Err(EPROTONOSUPPORT); @@ -24,7 +26,7 @@ fn create_inet_socket( }, PSOCK::Stream => match protocol { HopByHop | Tcp => { - return Ok(TcpSocket::new(false)); + return Ok(TcpSocket::new(false, v4)); } _ => { return Err(EPROTONOSUPPORT); @@ -42,7 +44,20 @@ fn create_inet_socket( pub struct Inet; impl family::Family for Inet { fn socket(stype: PSOCK, protocol: u32) -> Result, SystemError> { - let socket = create_inet_socket(stype, smoltcp::wire::IpProtocol::from(protocol as u8))?; + let socket = + create_inet_socket(true, stype, smoltcp::wire::IpProtocol::from(protocol as u8))?; + Ok(Inode::new(socket)) + } +} + +pub struct Inet6; +impl family::Family for Inet6 { + fn socket(stype: PSOCK, protocol: u32) -> Result, SystemError> { + let socket = create_inet_socket( + false, + stype, + smoltcp::wire::IpProtocol::from(protocol as u8), + )?; Ok(Inode::new(socket)) } } diff --git a/kernel/src/net/socket/utils.rs b/kernel/src/net/socket/utils.rs index 2def9bfb..7e14d88c 100644 --- a/kernel/src/net/socket/utils.rs +++ b/kernel/src/net/socket/utils.rs @@ -13,12 +13,11 @@ pub fn create_socket( type AF = socket::AddressFamily; let inode = match family { AF::INet => socket::inet::Inet::socket(socket_type, protocol)?, - AF::INet6 => { - todo!("AF_INET6 unimplemented"); - } + // AF::INet6 => socket::inet::Inet6::socket(socket_type, protocol)?, AF::Unix => socket::unix::Unix::socket(socket_type, protocol)?, _ => { - todo!("unsupport address family"); + log::warn!("unsupport address family"); + return Err(SystemError::EAFNOSUPPORT); } }; inode.set_nonblock(is_nonblock);