Преглед изворни кода

fix: ipv6, AddressFamily有转换问题。

Samuka007 пре 5 месеци
родитељ
комит
a303dd0964

+ 16 - 1
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;
 

+ 5 - 5
kernel/src/net/socket/family.rs

@@ -102,14 +102,14 @@ pub enum AddressFamily {
     Max = 46,
 }
 
-use system_error::SystemError;
-
 impl core::convert::TryFrom<u16> for AddressFamily {
     type Error = system_error::SystemError;
     fn try_from(x: u16) -> Result<Self, Self::Error> {
         use num_traits::FromPrimitive;
-        use SystemError::*;
-        return <Self as FromPrimitive>::from_u16(x).ok_or(EINVAL);
+        return <Self as FromPrimitive>::from_u16(x).ok_or({
+            log::debug!("AddressFamily::try_from failed: x={}", x);
+            Self::Error::EINVAL
+        });
     }
 }
 
@@ -117,5 +117,5 @@ use crate::net::socket;
 use alloc::sync::Arc;
 
 pub trait Family {
-    fn socket(stype: socket::PSOCK, protocol: u32) -> Result<Arc<socket::Inode>, SystemError>;
+    fn socket(stype: socket::PSOCK, protocol: u32) -> Result<Arc<socket::Inode>, system_error::SystemError>;
 }

+ 3 - 1
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`

+ 14 - 10
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<smoltcp::socket::tcp::Socket<'static>>),
+    Unbound((Box<smoltcp::socket::tcp::Socket<'static>>, 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<Self, SystemError> {
         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;
             }
         })
     }

+ 14 - 5
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<Self> {
+    pub fn new(nonblock: bool, v4: bool) -> Arc<Self> {
         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,11 @@ impl Socket for TcpSocket {
 
     fn get_name(&self) -> Result<Endpoint, SystemError> {
         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 +250,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);
     }
 

+ 13 - 3
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<Arc<dyn Socket>, 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,15 @@ fn create_inet_socket(
 pub struct Inet;
 impl family::Family for Inet {
     fn socket(stype: PSOCK, protocol: u32) -> Result<Arc<Inode>, 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<Arc<Inode>, SystemError> {
+        let socket = create_inet_socket(false, stype, smoltcp::wire::IpProtocol::from(protocol as u8))?;
         Ok(Inode::new(socket))
     }
 }

+ 3 - 4
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);