2019-02-28 08:31:10 +04:00
|
|
|
//! Syscalls for networking
|
|
|
|
|
|
|
|
use super::*;
|
2019-03-20 07:36:41 +04:00
|
|
|
use crate::drivers::SOCKET_ACTIVITY;
|
2019-03-29 09:23:49 +04:00
|
|
|
use crate::fs::FileLike;
|
2019-04-04 16:01:59 +04:00
|
|
|
use crate::net::{
|
2019-04-04 16:31:46 +04:00
|
|
|
Endpoint, LinkLevelEndpoint, PacketSocketState, RawSocketState, Socket, TcpSocketState,
|
|
|
|
UdpSocketState, SOCKETS,
|
2019-04-04 16:01:59 +04:00
|
|
|
};
|
2019-03-29 09:23:49 +04:00
|
|
|
use crate::sync::{MutexGuard, SpinNoIrq, SpinNoIrqLock as Mutex};
|
|
|
|
use alloc::boxed::Box;
|
2019-03-10 04:39:22 +04:00
|
|
|
use core::cmp::min;
|
2019-02-28 10:46:46 +04:00
|
|
|
use core::mem::size_of;
|
|
|
|
use smoltcp::wire::*;
|
2019-02-28 08:31:10 +04:00
|
|
|
|
|
|
|
pub fn sys_socket(domain: usize, socket_type: usize, protocol: usize) -> SysResult {
|
2019-04-04 16:01:59 +04:00
|
|
|
let domain = AddressFamily::from(domain as u16);
|
2019-02-28 10:46:46 +04:00
|
|
|
info!(
|
2019-04-04 16:01:59 +04:00
|
|
|
"socket: domain: {:?}, socket_type: {}, protocol: {}",
|
2019-02-28 10:46:46 +04:00
|
|
|
domain, socket_type, protocol
|
|
|
|
);
|
2019-02-28 08:31:10 +04:00
|
|
|
let mut proc = process();
|
2019-03-29 09:23:49 +04:00
|
|
|
let socket: Box<dyn Socket> = match domain {
|
2019-04-04 16:01:59 +04:00
|
|
|
AddressFamily::Internet | AddressFamily::Unix => {
|
|
|
|
match SocketType::from(socket_type as u8 & SOCK_TYPE_MASK) {
|
|
|
|
SocketType::Stream => Box::new(TcpSocketState::new()),
|
|
|
|
SocketType::Datagram => Box::new(UdpSocketState::new()),
|
|
|
|
SocketType::Raw => Box::new(RawSocketState::new(protocol as u8)),
|
|
|
|
_ => return Err(SysError::EINVAL),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
AddressFamily::Packet => match SocketType::from(socket_type as u8 & SOCK_TYPE_MASK) {
|
|
|
|
SocketType::Raw => Box::new(PacketSocketState::new()),
|
2019-03-29 09:23:49 +04:00
|
|
|
_ => return Err(SysError::EINVAL),
|
2019-02-28 10:46:46 +04:00
|
|
|
},
|
2019-03-29 09:23:49 +04:00
|
|
|
_ => return Err(SysError::EAFNOSUPPORT),
|
|
|
|
};
|
|
|
|
let fd = proc.get_free_fd();
|
|
|
|
proc.files.insert(fd, FileLike::Socket(socket));
|
|
|
|
Ok(fd)
|
2019-02-28 10:46:46 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn sys_setsockopt(
|
|
|
|
fd: usize,
|
|
|
|
level: usize,
|
|
|
|
optname: usize,
|
2019-04-04 10:32:58 +04:00
|
|
|
optval: *const u8,
|
|
|
|
optlen: usize,
|
2019-02-28 10:46:46 +04:00
|
|
|
) -> SysResult {
|
|
|
|
info!(
|
|
|
|
"setsockopt: fd: {}, level: {}, optname: {}",
|
|
|
|
fd, level, optname
|
|
|
|
);
|
2019-04-04 10:32:58 +04:00
|
|
|
let mut proc = process();
|
|
|
|
proc.vm.check_read_array(optval, optlen)?;
|
|
|
|
let data = unsafe { slice::from_raw_parts(optval, optlen) };
|
|
|
|
let socket = proc.get_socket(fd)?;
|
|
|
|
socket.setsockopt(level, optname, data)
|
2019-02-28 10:46:46 +04:00
|
|
|
}
|
|
|
|
|
2019-03-07 10:21:26 +04:00
|
|
|
pub fn sys_getsockopt(
|
|
|
|
fd: usize,
|
|
|
|
level: usize,
|
|
|
|
optname: usize,
|
|
|
|
optval: *mut u8,
|
|
|
|
optlen: *mut u32,
|
|
|
|
) -> SysResult {
|
|
|
|
info!(
|
|
|
|
"getsockopt: fd: {}, level: {}, optname: {} optval: {:?} optlen: {:?}",
|
|
|
|
fd, level, optname, optval, optlen
|
|
|
|
);
|
2019-03-12 05:54:07 +04:00
|
|
|
let proc = process();
|
2019-03-22 19:45:57 +04:00
|
|
|
proc.vm.check_write_ptr(optlen)?;
|
2019-03-12 05:54:07 +04:00
|
|
|
match level {
|
2019-03-16 20:33:05 +04:00
|
|
|
SOL_SOCKET => match optname {
|
|
|
|
SO_SNDBUF => {
|
2019-03-22 19:45:57 +04:00
|
|
|
proc.vm.check_write_array(optval, 4)?;
|
2019-03-16 20:33:05 +04:00
|
|
|
unsafe {
|
2019-03-29 09:23:49 +04:00
|
|
|
*(optval as *mut u32) = crate::net::TCP_SENDBUF as u32;
|
2019-03-16 20:33:05 +04:00
|
|
|
*optlen = 4;
|
2019-03-12 05:54:07 +04:00
|
|
|
}
|
2019-03-16 20:33:05 +04:00
|
|
|
Ok(0)
|
2019-03-12 05:54:07 +04:00
|
|
|
}
|
2019-03-16 20:33:05 +04:00
|
|
|
SO_RCVBUF => {
|
2019-03-22 19:45:57 +04:00
|
|
|
proc.vm.check_write_array(optval, 4)?;
|
2019-03-16 20:33:05 +04:00
|
|
|
unsafe {
|
2019-03-29 09:23:49 +04:00
|
|
|
*(optval as *mut u32) = crate::net::TCP_RECVBUF as u32;
|
2019-03-16 20:33:05 +04:00
|
|
|
*optlen = 4;
|
2019-03-12 05:54:07 +04:00
|
|
|
}
|
2019-03-16 20:33:05 +04:00
|
|
|
Ok(0)
|
2019-03-12 05:54:07 +04:00
|
|
|
}
|
2019-03-16 20:33:05 +04:00
|
|
|
_ => Err(SysError::ENOPROTOOPT),
|
|
|
|
},
|
|
|
|
IPPROTO_TCP => match optname {
|
|
|
|
TCP_CONGESTION => Ok(0),
|
|
|
|
_ => Err(SysError::ENOPROTOOPT),
|
|
|
|
},
|
|
|
|
_ => Err(SysError::ENOPROTOOPT),
|
2019-03-12 05:54:07 +04:00
|
|
|
}
|
2019-03-07 10:21:26 +04:00
|
|
|
}
|
|
|
|
|
2019-03-10 04:39:22 +04:00
|
|
|
pub fn sys_connect(fd: usize, addr: *const SockAddr, addr_len: usize) -> SysResult {
|
2019-02-28 10:46:46 +04:00
|
|
|
info!(
|
2019-03-10 04:39:22 +04:00
|
|
|
"sys_connect: fd: {}, addr: {:?}, addr_len: {}",
|
|
|
|
fd, addr, addr_len
|
2019-02-28 10:46:46 +04:00
|
|
|
);
|
|
|
|
|
2019-03-02 20:44:46 +04:00
|
|
|
let mut proc = process();
|
2019-03-10 04:39:22 +04:00
|
|
|
let endpoint = sockaddr_to_endpoint(&mut proc, addr, addr_len)?;
|
2019-03-29 09:23:49 +04:00
|
|
|
let socket = proc.get_socket(fd)?;
|
|
|
|
socket.connect(endpoint)?;
|
|
|
|
Ok(0)
|
2019-03-04 20:57:40 +04:00
|
|
|
}
|
|
|
|
|
2019-02-28 10:46:46 +04:00
|
|
|
pub fn sys_sendto(
|
|
|
|
fd: usize,
|
2019-03-19 14:33:13 +04:00
|
|
|
base: *const u8,
|
2019-02-28 10:46:46 +04:00
|
|
|
len: usize,
|
2019-03-23 20:36:13 +04:00
|
|
|
_flags: usize,
|
2019-03-10 04:39:22 +04:00
|
|
|
addr: *const SockAddr,
|
2019-02-28 10:46:46 +04:00
|
|
|
addr_len: usize,
|
|
|
|
) -> SysResult {
|
2019-03-02 20:44:46 +04:00
|
|
|
info!(
|
2019-03-19 14:33:13 +04:00
|
|
|
"sys_sendto: fd: {} base: {:?} len: {} addr: {:?} addr_len: {}",
|
|
|
|
fd, base, len, addr, addr_len
|
2019-03-02 20:44:46 +04:00
|
|
|
);
|
2019-03-04 11:34:02 +04:00
|
|
|
|
2019-03-02 20:44:46 +04:00
|
|
|
let mut proc = process();
|
2019-03-22 19:45:57 +04:00
|
|
|
proc.vm.check_read_array(base, len)?;
|
2019-03-02 20:44:46 +04:00
|
|
|
|
2019-03-19 14:33:13 +04:00
|
|
|
let slice = unsafe { slice::from_raw_parts(base, len) };
|
2019-03-29 09:23:49 +04:00
|
|
|
let endpoint = if addr.is_null() {
|
|
|
|
None
|
2019-03-23 14:23:02 +04:00
|
|
|
} else {
|
|
|
|
let endpoint = sockaddr_to_endpoint(&mut proc, addr, addr_len)?;
|
|
|
|
info!("sys_sendto: sending to endpoint {:?}", endpoint);
|
2019-03-29 09:23:49 +04:00
|
|
|
Some(endpoint)
|
|
|
|
};
|
|
|
|
let socket = proc.get_socket(fd)?;
|
|
|
|
socket.write(&slice, endpoint)
|
2019-02-28 10:46:46 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn sys_recvfrom(
|
|
|
|
fd: usize,
|
2019-03-19 14:33:13 +04:00
|
|
|
base: *mut u8,
|
2019-02-28 10:46:46 +04:00
|
|
|
len: usize,
|
|
|
|
flags: usize,
|
2019-03-10 04:39:22 +04:00
|
|
|
addr: *mut SockAddr,
|
2019-03-04 20:57:40 +04:00
|
|
|
addr_len: *mut u32,
|
2019-02-28 10:46:46 +04:00
|
|
|
) -> SysResult {
|
2019-03-02 20:44:46 +04:00
|
|
|
info!(
|
2019-03-19 14:33:13 +04:00
|
|
|
"sys_recvfrom: fd: {} base: {:?} len: {} flags: {} addr: {:?} addr_len: {:?}",
|
|
|
|
fd, base, len, flags, addr, addr_len
|
2019-03-02 20:44:46 +04:00
|
|
|
);
|
2019-03-04 20:57:40 +04:00
|
|
|
|
2019-03-02 20:44:46 +04:00
|
|
|
let mut proc = process();
|
2019-03-22 19:45:57 +04:00
|
|
|
proc.vm.check_write_array(base, len)?;
|
2019-03-02 20:44:46 +04:00
|
|
|
|
2019-03-29 09:23:49 +04:00
|
|
|
let socket = proc.get_socket(fd)?;
|
2019-03-19 14:33:13 +04:00
|
|
|
let mut slice = unsafe { slice::from_raw_parts_mut(base, len) };
|
2019-03-29 09:23:49 +04:00
|
|
|
let (result, endpoint) = socket.read(&mut slice);
|
2019-03-04 20:57:40 +04:00
|
|
|
|
2019-03-19 14:33:13 +04:00
|
|
|
if result.is_ok() && !addr.is_null() {
|
|
|
|
let sockaddr_in = SockAddr::from(endpoint);
|
|
|
|
unsafe {
|
|
|
|
sockaddr_in.write_to(&mut proc, addr, addr_len)?;
|
2019-03-02 20:44:46 +04:00
|
|
|
}
|
|
|
|
}
|
2019-03-19 14:33:13 +04:00
|
|
|
|
|
|
|
result
|
2019-02-28 10:46:46 +04:00
|
|
|
}
|
2019-03-01 04:03:10 +04:00
|
|
|
|
2019-03-10 04:39:22 +04:00
|
|
|
pub fn sys_bind(fd: usize, addr: *const SockAddr, addr_len: usize) -> SysResult {
|
|
|
|
info!("sys_bind: fd: {} addr: {:?} len: {}", fd, addr, addr_len);
|
2019-03-06 06:19:19 +04:00
|
|
|
let mut proc = process();
|
|
|
|
|
2019-03-10 04:39:22 +04:00
|
|
|
let mut endpoint = sockaddr_to_endpoint(&mut proc, addr, addr_len)?;
|
2019-04-04 16:01:59 +04:00
|
|
|
info!("sys_bind: fd: {} bind to {:?}", fd, endpoint);
|
2019-03-06 06:19:19 +04:00
|
|
|
|
2019-03-29 09:23:49 +04:00
|
|
|
let socket = proc.get_socket(fd)?;
|
|
|
|
socket.bind(endpoint)
|
2019-03-06 06:19:19 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn sys_listen(fd: usize, backlog: usize) -> SysResult {
|
2019-03-07 05:47:36 +04:00
|
|
|
info!("sys_listen: fd: {} backlog: {}", fd, backlog);
|
2019-03-06 06:19:19 +04:00
|
|
|
// smoltcp tcp sockets do not support backlog
|
|
|
|
// open multiple sockets for each connection
|
|
|
|
let mut proc = process();
|
|
|
|
|
2019-03-29 09:23:49 +04:00
|
|
|
let socket = proc.get_socket(fd)?;
|
|
|
|
socket.listen()
|
2019-03-06 06:57:28 +04:00
|
|
|
}
|
|
|
|
|
2019-03-07 14:07:54 +04:00
|
|
|
pub fn sys_shutdown(fd: usize, how: usize) -> SysResult {
|
|
|
|
info!("sys_shutdown: fd: {} how: {}", fd, how);
|
|
|
|
let mut proc = process();
|
|
|
|
|
2019-03-29 09:23:49 +04:00
|
|
|
let socket = proc.get_socket(fd)?;
|
|
|
|
socket.shutdown()
|
2019-03-07 14:07:54 +04:00
|
|
|
}
|
|
|
|
|
2019-03-10 04:39:22 +04:00
|
|
|
pub fn sys_accept(fd: usize, addr: *mut SockAddr, addr_len: *mut u32) -> SysResult {
|
2019-03-06 16:24:55 +04:00
|
|
|
info!(
|
|
|
|
"sys_accept: fd: {} addr: {:?} addr_len: {:?}",
|
|
|
|
fd, addr, addr_len
|
|
|
|
);
|
2019-03-06 06:57:28 +04:00
|
|
|
// smoltcp tcp sockets do not support backlog
|
|
|
|
// open multiple sockets for each connection
|
|
|
|
let mut proc = process();
|
|
|
|
|
2019-03-29 09:23:49 +04:00
|
|
|
let socket = proc.get_socket(fd)?;
|
|
|
|
let (new_socket, remote_endpoint) = socket.accept()?;
|
2019-03-06 06:19:19 +04:00
|
|
|
|
2019-03-29 09:23:49 +04:00
|
|
|
let new_fd = proc.get_free_fd();
|
|
|
|
proc.files.insert(new_fd, FileLike::Socket(new_socket));
|
|
|
|
|
|
|
|
if !addr.is_null() {
|
|
|
|
let sockaddr_in = SockAddr::from(remote_endpoint);
|
|
|
|
unsafe {
|
|
|
|
sockaddr_in.write_to(&mut proc, addr, addr_len)?;
|
2019-03-06 06:19:19 +04:00
|
|
|
}
|
|
|
|
}
|
2019-03-29 09:23:49 +04:00
|
|
|
Ok(new_fd)
|
2019-03-06 06:57:28 +04:00
|
|
|
}
|
2019-03-06 11:35:10 +04:00
|
|
|
|
2019-03-10 04:39:22 +04:00
|
|
|
pub fn sys_getsockname(fd: usize, addr: *mut SockAddr, addr_len: *mut u32) -> SysResult {
|
2019-03-06 16:24:55 +04:00
|
|
|
info!(
|
|
|
|
"sys_getsockname: fd: {} addr: {:?} addr_len: {:?}",
|
|
|
|
fd, addr, addr_len
|
|
|
|
);
|
|
|
|
|
2019-03-06 11:35:10 +04:00
|
|
|
let mut proc = process();
|
|
|
|
|
2019-03-07 12:42:24 +04:00
|
|
|
if addr.is_null() {
|
2019-03-06 11:35:10 +04:00
|
|
|
return Err(SysError::EINVAL);
|
|
|
|
}
|
|
|
|
|
2019-03-29 09:23:49 +04:00
|
|
|
let socket = proc.get_socket(fd)?;
|
|
|
|
let endpoint = socket.endpoint().ok_or(SysError::EINVAL)?;
|
|
|
|
let sockaddr_in = SockAddr::from(endpoint);
|
|
|
|
unsafe {
|
|
|
|
sockaddr_in.write_to(&mut proc, addr, addr_len)?;
|
2019-03-06 11:35:10 +04:00
|
|
|
}
|
2019-03-29 09:23:49 +04:00
|
|
|
Ok(0)
|
2019-03-07 05:47:36 +04:00
|
|
|
}
|
|
|
|
|
2019-03-10 04:39:22 +04:00
|
|
|
pub fn sys_getpeername(fd: usize, addr: *mut SockAddr, addr_len: *mut u32) -> SysResult {
|
2019-03-07 12:55:02 +04:00
|
|
|
info!(
|
|
|
|
"sys_getpeername: fd: {} addr: {:?} addr_len: {:?}",
|
|
|
|
fd, addr, addr_len
|
|
|
|
);
|
|
|
|
|
|
|
|
// smoltcp tcp sockets do not support backlog
|
|
|
|
// open multiple sockets for each connection
|
|
|
|
let mut proc = process();
|
|
|
|
|
|
|
|
if addr as usize == 0 {
|
|
|
|
return Err(SysError::EINVAL);
|
|
|
|
}
|
|
|
|
|
2019-03-29 09:23:49 +04:00
|
|
|
let socket = proc.get_socket(fd)?;
|
|
|
|
let remote_endpoint = socket.remote_endpoint().ok_or(SysError::EINVAL)?;
|
|
|
|
let sockaddr_in = SockAddr::from(remote_endpoint);
|
|
|
|
unsafe {
|
|
|
|
sockaddr_in.write_to(&mut proc, addr, addr_len)?;
|
2019-03-07 12:55:02 +04:00
|
|
|
}
|
2019-03-29 09:23:49 +04:00
|
|
|
Ok(0)
|
2019-03-07 12:55:02 +04:00
|
|
|
}
|
|
|
|
|
2019-03-29 09:23:49 +04:00
|
|
|
impl Process {
|
|
|
|
fn get_socket(&mut self, fd: usize) -> Result<&mut Box<dyn Socket>, SysError> {
|
|
|
|
match self.get_file_like(fd)? {
|
|
|
|
FileLike::Socket(socket) => Ok(socket),
|
|
|
|
_ => Err(SysError::EBADF),
|
2019-03-16 20:33:05 +04:00
|
|
|
}
|
2019-03-07 05:47:36 +04:00
|
|
|
}
|
2019-03-07 12:42:24 +04:00
|
|
|
}
|
|
|
|
|
2019-03-12 05:54:07 +04:00
|
|
|
// cancel alignment
|
|
|
|
#[repr(packed)]
|
2019-03-10 04:39:22 +04:00
|
|
|
pub struct SockAddrIn {
|
2019-04-04 17:38:32 +04:00
|
|
|
pub sin_port: u16,
|
|
|
|
pub sin_addr: u32,
|
|
|
|
pub sin_zero: [u8; 8],
|
2019-03-07 12:42:24 +04:00
|
|
|
}
|
|
|
|
|
2019-03-10 04:39:22 +04:00
|
|
|
#[repr(C)]
|
|
|
|
pub struct SockAddrUn {
|
2019-04-04 17:38:32 +04:00
|
|
|
pub sun_path: [u8; 108],
|
2019-03-10 04:39:22 +04:00
|
|
|
}
|
|
|
|
|
2019-04-04 16:31:46 +04:00
|
|
|
// beware of alignment issue
|
|
|
|
#[repr(C, packed)]
|
2019-04-04 16:01:59 +04:00
|
|
|
pub struct SockAddrLl {
|
2019-04-04 17:38:32 +04:00
|
|
|
pub sll_protocol: u16,
|
|
|
|
pub sll_ifindex: u32,
|
|
|
|
pub sll_hatype: u16,
|
|
|
|
pub sll_pkttype: u8,
|
|
|
|
pub sll_halen: u8,
|
|
|
|
pub sll_addr: [u8; 8],
|
2019-04-04 16:01:59 +04:00
|
|
|
}
|
|
|
|
|
2019-03-10 04:39:22 +04:00
|
|
|
#[repr(C)]
|
|
|
|
pub union SockAddrPayload {
|
2019-04-04 17:38:32 +04:00
|
|
|
pub addr_in: SockAddrIn,
|
|
|
|
pub addr_un: SockAddrUn,
|
|
|
|
pub addr_ll: SockAddrLl,
|
2019-03-10 04:39:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
pub struct SockAddr {
|
2019-04-04 17:38:32 +04:00
|
|
|
pub family: u16,
|
|
|
|
pub payload: SockAddrPayload,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
pub struct SockAddrPlaceholder {
|
|
|
|
pub family: u16,
|
|
|
|
pub data: [u8; 14],
|
2019-03-10 04:39:22 +04:00
|
|
|
}
|
|
|
|
|
2019-04-04 16:01:59 +04:00
|
|
|
impl From<Endpoint> for SockAddr {
|
|
|
|
fn from(endpoint: Endpoint) -> Self {
|
|
|
|
if let Endpoint::Ip(ip) = endpoint {
|
|
|
|
match ip.addr {
|
|
|
|
IpAddress::Ipv4(ipv4) => SockAddr {
|
|
|
|
family: AddressFamily::Internet.into(),
|
|
|
|
payload: SockAddrPayload {
|
|
|
|
addr_in: SockAddrIn {
|
|
|
|
sin_port: u16::to_be(ip.port),
|
|
|
|
sin_addr: u32::to_be(u32::from_be_bytes(ipv4.0)),
|
|
|
|
sin_zero: [0; 8],
|
|
|
|
},
|
2019-03-10 04:39:22 +04:00
|
|
|
},
|
|
|
|
},
|
2019-04-04 16:01:59 +04:00
|
|
|
_ => unimplemented!("only ipv4"),
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
unimplemented!("only ip");
|
2019-03-07 12:42:24 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-10 04:39:22 +04:00
|
|
|
/// Convert sockaddr to endpoint
|
|
|
|
// Check len is long enough
|
|
|
|
fn sockaddr_to_endpoint(
|
|
|
|
proc: &mut Process,
|
|
|
|
addr: *const SockAddr,
|
|
|
|
len: usize,
|
2019-04-04 16:01:59 +04:00
|
|
|
) -> Result<Endpoint, SysError> {
|
2019-03-10 04:39:22 +04:00
|
|
|
if len < size_of::<u16>() {
|
|
|
|
return Err(SysError::EINVAL);
|
|
|
|
}
|
2019-03-22 19:45:57 +04:00
|
|
|
proc.vm.check_read_array(addr as *const u8, len)?;
|
2019-03-10 04:39:22 +04:00
|
|
|
unsafe {
|
2019-04-04 16:01:59 +04:00
|
|
|
match AddressFamily::from((*addr).family) {
|
|
|
|
AddressFamily::Internet => {
|
2019-03-10 04:39:22 +04:00
|
|
|
if len < size_of::<u16>() + size_of::<SockAddrIn>() {
|
|
|
|
return Err(SysError::EINVAL);
|
|
|
|
}
|
|
|
|
let port = u16::from_be((*addr).payload.addr_in.sin_port);
|
|
|
|
let addr = IpAddress::from(Ipv4Address::from_bytes(
|
|
|
|
&u32::from_be((*addr).payload.addr_in.sin_addr).to_be_bytes()[..],
|
|
|
|
));
|
2019-04-04 16:01:59 +04:00
|
|
|
Ok(Endpoint::Ip((addr, port).into()))
|
|
|
|
}
|
|
|
|
AddressFamily::Unix => Err(SysError::EINVAL),
|
|
|
|
AddressFamily::Packet => {
|
|
|
|
if len < size_of::<u16>() + size_of::<SockAddrLl>() {
|
|
|
|
return Err(SysError::EINVAL);
|
|
|
|
}
|
2019-04-04 16:31:46 +04:00
|
|
|
Ok(Endpoint::LinkLevel(LinkLevelEndpoint::new(
|
|
|
|
(*addr).payload.addr_ll.sll_ifindex as usize,
|
|
|
|
)))
|
2019-03-10 04:39:22 +04:00
|
|
|
}
|
|
|
|
_ => Err(SysError::EINVAL),
|
2019-03-07 12:42:24 +04:00
|
|
|
}
|
|
|
|
}
|
2019-03-10 04:39:22 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl SockAddr {
|
|
|
|
/// Write to user sockaddr
|
|
|
|
/// Check mutability for user
|
|
|
|
unsafe fn write_to(
|
|
|
|
self,
|
|
|
|
proc: &mut Process,
|
|
|
|
addr: *mut SockAddr,
|
|
|
|
addr_len: *mut u32,
|
|
|
|
) -> SysResult {
|
|
|
|
// Ignore NULL
|
|
|
|
if addr.is_null() {
|
|
|
|
return Ok(0);
|
|
|
|
}
|
|
|
|
|
2019-03-22 19:45:57 +04:00
|
|
|
proc.vm.check_write_ptr(addr_len)?;
|
2019-03-10 04:39:22 +04:00
|
|
|
let max_addr_len = *addr_len as usize;
|
2019-04-04 16:01:59 +04:00
|
|
|
let full_len = match AddressFamily::from(self.family) {
|
|
|
|
AddressFamily::Internet => size_of::<u16>() + size_of::<SockAddrIn>(),
|
|
|
|
AddressFamily::Unix => return Err(SysError::EINVAL),
|
2019-03-10 04:39:22 +04:00
|
|
|
_ => return Err(SysError::EINVAL),
|
|
|
|
};
|
|
|
|
|
|
|
|
let written_len = min(max_addr_len, full_len);
|
|
|
|
if written_len > 0 {
|
2019-03-22 19:45:57 +04:00
|
|
|
proc.vm.check_write_array(addr as *mut u8, written_len)?;
|
2019-03-10 04:39:22 +04:00
|
|
|
let source = slice::from_raw_parts(&self as *const SockAddr as *const u8, written_len);
|
|
|
|
let target = slice::from_raw_parts_mut(addr as *mut u8, written_len);
|
|
|
|
target.copy_from_slice(source);
|
|
|
|
}
|
|
|
|
addr_len.write(full_len as u32);
|
|
|
|
return Ok(0);
|
2019-03-07 12:42:24 +04:00
|
|
|
}
|
|
|
|
}
|
2019-03-29 09:23:49 +04:00
|
|
|
|
2019-04-04 16:01:59 +04:00
|
|
|
enum_with_unknown! {
|
|
|
|
/// Address families
|
|
|
|
pub doc enum AddressFamily(u16) {
|
|
|
|
/// Unspecified
|
|
|
|
Unspecified = 0,
|
|
|
|
/// Unix domain sockets
|
|
|
|
Unix = 1,
|
|
|
|
/// Internet IP Protocol
|
|
|
|
Internet = 2,
|
|
|
|
/// Packet family
|
|
|
|
Packet = 17,
|
|
|
|
}
|
|
|
|
}
|
2019-03-29 09:23:49 +04:00
|
|
|
|
2019-04-04 16:01:59 +04:00
|
|
|
const SOCK_TYPE_MASK: u8 = 0xf;
|
|
|
|
|
|
|
|
enum_with_unknown! {
|
|
|
|
/// Socket types
|
|
|
|
pub doc enum SocketType(u8) {
|
|
|
|
/// Stream
|
|
|
|
Stream = 1,
|
|
|
|
/// Datagram
|
|
|
|
Datagram = 2,
|
|
|
|
/// Raw
|
|
|
|
Raw = 3,
|
|
|
|
}
|
|
|
|
}
|
2019-03-29 09:23:49 +04:00
|
|
|
|
|
|
|
const IPPROTO_IP: usize = 0;
|
|
|
|
const IPPROTO_ICMP: usize = 1;
|
|
|
|
const IPPROTO_TCP: usize = 6;
|
|
|
|
|
|
|
|
const SOL_SOCKET: usize = 1;
|
|
|
|
const SO_SNDBUF: usize = 7;
|
|
|
|
const SO_RCVBUF: usize = 8;
|
|
|
|
const SO_LINGER: usize = 13;
|
|
|
|
|
|
|
|
const TCP_CONGESTION: usize = 13;
|
2019-04-04 10:32:58 +04:00
|
|
|
|
|
|
|
const IP_HDRINCL: usize = 3;
|