use smoltcp::iface::SocketHandle; use smoltcp::socket::raw::{ PacketBuffer as RawSocketBuffer, PacketMetadata as RawPacketMetadata, Socket as RawSocket, }; use smoltcp::wire::{IpProtocol, IpVersion}; use std::str; use syscall; use syscall::{Error as SyscallError, Result as SyscallResult}; use crate::router::Router; use super::socket::{Context, DupResult, SchemeFile, SchemeSocket, SocketFile}; use super::{SchemeWrapper, Smolnetd, SocketSet}; pub type IpScheme = SchemeWrapper>; impl<'a> SchemeSocket for RawSocket<'a> { type SchemeDataT = (); type DataT = (); type SettingT = (); fn new_scheme_data() -> Self::SchemeDataT { () } fn can_send(&self) -> bool { self.can_send() } fn can_recv(&self) -> bool { self.can_recv() } fn may_recv(&self) -> bool { true } fn get_setting( _file: &SocketFile, _setting: Self::SettingT, _buf: &mut [u8], ) -> SyscallResult { Ok(0) } fn set_setting( _file: &mut SocketFile, _setting: Self::SettingT, _buf: &[u8], ) -> SyscallResult { Ok(0) } fn hop_limit(&self) -> u8 { 0 } fn set_hop_limit(&mut self, _hop_limit: u8) {} fn new_socket( socket_set: &mut SocketSet, path: &str, uid: u32, _: &mut Self::SchemeDataT, _context: &Context, ) -> SyscallResult<(SocketHandle, Self::DataT)> { if uid != 0 { return Err(SyscallError::new(syscall::EACCES)); } let proto = u8::from_str_radix(path, 16).or_else(|_| Err(SyscallError::new(syscall::ENOENT)))?; let rx_buffer = RawSocketBuffer::new( vec![RawPacketMetadata::EMPTY; Smolnetd::SOCKET_BUFFER_SIZE], vec![0; Router::MTU * Smolnetd::SOCKET_BUFFER_SIZE], ); let tx_buffer = RawSocketBuffer::new( vec![RawPacketMetadata::EMPTY; Smolnetd::SOCKET_BUFFER_SIZE], vec![0; Router::MTU * Smolnetd::SOCKET_BUFFER_SIZE], ); let ip_socket = RawSocket::new( IpVersion::Ipv4, IpProtocol::from(proto), rx_buffer, tx_buffer, ); let socket_handle = socket_set.add(ip_socket); Ok((socket_handle, ())) } fn close_file(&self, _: &SchemeFile, _: &mut Self::SchemeDataT) -> SyscallResult<()> { Ok(()) } fn write_buf( &mut self, file: &mut SocketFile, buf: &[u8], ) -> SyscallResult { if self.can_send() { self.send_slice(buf).expect("Can't send slice"); Ok(buf.len()) } else if file.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK { Err(SyscallError::new(syscall::EAGAIN)) } else { Err(SyscallError::new(syscall::EWOULDBLOCK)) // internally scheduled to re-read } } fn read_buf( &mut self, file: &mut SocketFile, buf: &mut [u8], ) -> SyscallResult { if self.can_recv() { let length = self.recv_slice(buf).expect("Can't receive slice"); Ok(length) } else if file.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK { Err(SyscallError::new(syscall::EAGAIN)) } else { Err(SyscallError::new(syscall::EWOULDBLOCK)) // internally scheduled to re-read } } fn dup( _socket_set: &mut SocketSet, _file: &mut SchemeFile, _path: &str, _: &mut Self::SchemeDataT, ) -> SyscallResult> { Err(SyscallError::new(syscall::EBADF)) } fn fpath(&self, _file: &SchemeFile, buf: &mut [u8]) -> SyscallResult { let path = format!("ip:{}", self.ip_protocol()); let path = path.as_bytes(); let mut i = 0; while i < buf.len() && i < path.len() { buf[i] = path[i]; i += 1; } Ok(i) } }