1
0
mirror of https://github.com/rcore-os/rCore.git synced 2024-11-27 10:13:28 +04:00
rCore/kernel/src/syscall/net.rs

211 lines
5.7 KiB
Rust

//! Syscalls for networking
use super::*;
use crate::drivers::NET_DRIVERS;
use core::mem::size_of;
use smoltcp::socket::*;
use smoltcp::wire::*;
const AF_INET: usize = 2;
const SOCK_STREAM: usize = 1;
const SOCK_DGRAM: usize = 2;
const SOCK_RAW: usize = 3;
const IPPROTO_IP: usize = 0;
const IPPROTO_ICMP: usize = 1;
pub fn sys_socket(domain: usize, socket_type: usize, protocol: usize) -> SysResult {
info!(
"socket: domain: {}, socket_type: {}, protocol: {}",
domain, socket_type, protocol
);
let mut proc = process();
match domain {
AF_INET => match socket_type {
SOCK_STREAM => {
let fd = proc.get_free_inode();
let tcp_rx_buffer = TcpSocketBuffer::new(vec![0; 2048]);
let tcp_tx_buffer = TcpSocketBuffer::new(vec![0; 2048]);
let tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
let tcp_handle = proc.sockets.add(tcp_socket);
proc.files.insert(fd, FileLike::Socket(tcp_handle));
Ok(fd as isize)
}
SOCK_RAW => {
let fd = proc.get_free_inode();
let raw_rx_buffer =
RawSocketBuffer::new(vec![RawPacketMetadata::EMPTY; 2], vec![0; 2048]);
let raw_tx_buffer =
RawSocketBuffer::new(vec![RawPacketMetadata::EMPTY; 2], vec![0; 2048]);
let raw_socket = RawSocket::new(
IpVersion::Ipv4,
IpProtocol::from(protocol as u8),
raw_rx_buffer,
raw_tx_buffer,
);
let raw_handle = proc.sockets.add(raw_socket);
proc.files.insert(fd, FileLike::Socket(raw_handle));
Ok(fd as isize)
}
_ => Err(SysError::EINVAL),
},
_ => Err(SysError::EAFNOSUPPORT),
}
}
pub fn sys_setsockopt(
fd: usize,
level: usize,
optname: usize,
optval: *const u8,
optlen: usize,
) -> SysResult {
info!(
"setsockopt: fd: {}, level: {}, optname: {}",
fd, level, optname
);
warn!("sys_setsockopt is unimplemented");
Ok(0)
}
#[repr(C)]
struct SockaddrIn {
sin_family: u16,
sin_port: u16,
sin_addr: u32,
sin_zero: [u8; 8],
}
fn get_handle(proc: &mut MutexGuard<'static, Process>, fd: usize) -> Result<SocketHandle, SysError> {
if let Some(file) = proc.files.get(&fd) {
if let FileLike::Socket(handle) = file {
return Ok((*handle).clone());
} else {
Err(SysError::ENOTSOCK)
}
} else {
Err(SysError::EBADF)
}
}
pub fn sys_connect(fd: usize, addr: *const u8, addrlen: usize) -> SysResult {
info!(
"sys_connect: fd: {}, addr: {:?}, addrlen: {}",
fd, addr, addrlen
);
let mut dest = None;
let mut port = 0;
if addrlen == size_of::<SockaddrIn>() {
let sockaddr_in = unsafe { &*(addr as *const SockaddrIn) };
port = ((sockaddr_in.sin_port & 0xFF) << 8) | (sockaddr_in.sin_port >> 8);
dest = Some(IpAddress::v4(
(sockaddr_in.sin_addr & 0xFF) as u8,
((sockaddr_in.sin_addr >> 8) & 0xFF) as u8,
((sockaddr_in.sin_addr >> 16) & 0xFF) as u8,
(sockaddr_in.sin_addr >> 24) as u8,
));
}
if dest == None {
return Err(SysError::EINVAL);
}
let mut proc = process();
// little hack: kick it forward
let iface = &mut *NET_DRIVERS.lock()[0];
iface.poll(&mut proc.sockets);
// TODO: check its type
let tcp_handle = get_handle(&mut proc, fd)?;
let mut socket = proc.sockets.get::<TcpSocket>(tcp_handle);
// TODO selects non-conflict high port
static mut ephermeral_port: u16 = 49152;
let temp_port = unsafe {
if ephermeral_port == 65535 {
ephermeral_port = 49152;
} else {
ephermeral_port = ephermeral_port + 1;
}
ephermeral_port
};
match socket.connect((dest.unwrap(), port), temp_port) {
Ok(()) => Ok(0),
Err(_) => Err(SysError::EISCONN),
}
}
pub fn sys_write_socket(
proc: &mut MutexGuard<'static, Process>,
fd: usize,
base: *const u8,
len: usize,
) -> SysResult {
// little hack: kick it forward
let iface = &mut *NET_DRIVERS.lock()[0];
iface.poll(&mut proc.sockets);
// TODO: check its type
let tcp_handle = get_handle(proc, fd)?;
let mut socket = proc.sockets.get::<TcpSocket>(tcp_handle);
let slice = unsafe { slice::from_raw_parts(base, len) };
if socket.is_open() {
if socket.can_send() {
match socket.send_slice(&slice) {
Ok(size) => Ok(size as isize),
Err(err) => Err(SysError::ENOBUFS)
}
} else {
Err(SysError::ENOBUFS)
}
} else {
Err(SysError::ECONNREFUSED)
}
}
pub fn sys_select(
fd: usize,
inp: *const u8,
outp: *const u8,
exp: *const u8,
tvp: *const u8,
) -> SysResult {
info!("sys_select: fd: {}", fd);
warn!("sys_select is unimplemented");
Err(SysError::EINVAL)
}
pub fn sys_sendto(
fd: usize,
buffer: *const u8,
len: usize,
flags: usize,
addr: *const u8,
addr_len: usize,
) -> SysResult {
info!("sys_sendto: fd: {} buffer: {:?} len: {}", fd, buffer, len);
warn!("sys_sendto is unimplemented");
Err(SysError::EINVAL)
}
pub fn sys_recvfrom(
fd: usize,
buffer: *mut u8,
len: usize,
flags: usize,
addr: *const u8,
addr_len: usize,
) -> SysResult {
info!("sys_recvfrom: fd: {} buffer: {:?} len: {}", fd, buffer, len);
warn!("sys_recvfrom is unimplemented");
Err(SysError::EINVAL)
}