From 09588d7a1fcb0859fceb345751f372f6462d7fa1 Mon Sep 17 00:00:00 2001 From: jiegec Date: Tue, 12 Mar 2019 09:54:07 +0800 Subject: [PATCH] Fix Sockaddr, implement sys_rusage and fix readv --- kernel/src/syscall/fs.rs | 3 +- kernel/src/syscall/mod.rs | 2 +- kernel/src/syscall/net.rs | 75 ++++++++++++++++++++++++-------------- kernel/src/syscall/time.rs | 32 ++++++++++++++++ 4 files changed, 83 insertions(+), 29 deletions(-) diff --git a/kernel/src/syscall/fs.rs b/kernel/src/syscall/fs.rs index 3c7f2cf..33833a8 100644 --- a/kernel/src/syscall/fs.rs +++ b/kernel/src/syscall/fs.rs @@ -260,7 +260,8 @@ pub fn sys_readv(fd: usize, iov_ptr: *const IoVec, iov_count: usize) -> SysResul let mut iovs = IoVecs::check_and_new(iov_ptr, iov_count, &proc.memory_set, true)?; // read all data to a buf - let file = proc.get_file(fd)?; + let mut file = proc.get_file(fd)?.clone(); + drop(proc); let mut buf = iovs.new_buf(true); let len = file.read(buf.as_mut_slice())?; // copy data to user diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 05406ab..283cecc 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -97,7 +97,7 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize { 087 => sys_unlink(args[0] as *const u8), 096 => sys_gettimeofday(args[0] as *mut TimeVal, args[1] as *const u8), // 097 => sys_getrlimit(), -// 098 => sys_getrusage(), + 098 => sys_getrusage(args[0], args[1] as *mut RUsage), 099 => sys_sysinfo(args[0] as *mut SysInfo), 110 => sys_getppid(), // 133 => sys_mknod(), diff --git a/kernel/src/syscall/net.rs b/kernel/src/syscall/net.rs index e184f42..cffff95 100644 --- a/kernel/src/syscall/net.rs +++ b/kernel/src/syscall/net.rs @@ -18,6 +18,7 @@ const SOCK_TYPE_MASK: usize = 0xf; const IPPROTO_IP: usize = 0; const IPPROTO_ICMP: usize = 1; +const IPPROTO_TCP: usize = 6; fn get_ephemeral_port() -> u16 { // TODO selects non-conflict high port @@ -127,6 +128,13 @@ pub fn sys_setsockopt( Ok(0) } +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; + pub fn sys_getsockopt( fd: usize, level: usize, @@ -138,8 +146,32 @@ pub fn sys_getsockopt( "getsockopt: fd: {}, level: {}, optname: {} optval: {:?} optlen: {:?}", fd, level, optname, optval, optlen ); - warn!("sys_getsockopt is unimplemented"); - Err(SysError::ENOPROTOOPT) + let proc = process(); + proc.memory_set.check_mut_ptr(optlen)?; + match level { + SOL_SOCKET => { + match optname { + SO_SNDBUF | SO_RCVBUF => { + proc.memory_set.check_mut_array(optval, 4)?; + unsafe { + *(optval as *mut u32) = 1024; + *optlen = 4; + } + Ok(0) + } + _ => Err(SysError::ENOPROTOOPT) + } + } + IPPROTO_TCP => { + match optname { + TCP_CONGESTION => { + Ok(0) + } + _ => Err(SysError::ENOPROTOOPT) + } + } + _ => Err(SysError::ENOPROTOOPT) + } } impl Process { @@ -685,23 +717,12 @@ pub fn sys_getsockname(fd: usize, addr: *mut SockAddr, addr_len: *mut u32) -> Sy fd, addr, addr_len ); - // smoltcp tcp sockets do not support backlog - // open multiple sockets for each connection let mut proc = process(); if addr.is_null() { return Err(SysError::EINVAL); } - proc.memory_set.check_mut_ptr(addr_len)?; - - let max_addr_len = unsafe { *addr_len } as usize; - if max_addr_len < size_of::() { - return Err(SysError::EINVAL); - } - - proc.memory_set.check_mut_array(addr, max_addr_len)?; - let iface = &*(NET_DRIVERS.read()[0]); let wrapper = proc.get_socket_mut(fd)?; if let SocketType::Tcp(state) = &wrapper.socket_type { @@ -712,7 +733,18 @@ pub fn sys_getsockname(fd: usize, addr: *mut SockAddr, addr_len: *mut u32) -> Sy } Ok(0) } else { - Err(SysError::EINVAL) + let mut sockets = iface.sockets(); + let socket = sockets.get::(wrapper.handle); + let endpoint = socket.local_endpoint(); + if endpoint.is_specified() { + let sockaddr_in = SockAddr::from(socket.local_endpoint()); + unsafe { + sockaddr_in.write_to(&mut proc, addr, addr_len)?; + } + Ok(0) + } else { + Err(SysError::EINVAL) + } } } else { Err(SysError::EINVAL) @@ -733,15 +765,6 @@ pub fn sys_getpeername(fd: usize, addr: *mut SockAddr, addr_len: *mut u32) -> Sy return Err(SysError::EINVAL); } - proc.memory_set.check_mut_ptr(addr_len)?; - - let max_addr_len = unsafe { *addr_len } as usize; - if max_addr_len < size_of::() { - return Err(SysError::EINVAL); - } - - proc.memory_set.check_mut_array(addr, max_addr_len)?; - let iface = &*(NET_DRIVERS.read()[0]); let wrapper = proc.get_socket_mut(fd)?; if let SocketType::Tcp(_) = wrapper.socket_type { @@ -800,9 +823,9 @@ pub fn sys_dup2_socket(proc: &mut Process, wrapper: SocketWrapper, fd: usize) -> Ok(fd) } -#[repr(C)] +// cancel alignment +#[repr(packed)] pub struct SockAddrIn { - sin_family: u16, sin_port: u16, sin_addr: u32, sin_zero: [u8; 8], @@ -810,7 +833,6 @@ pub struct SockAddrIn { #[repr(C)] pub struct SockAddrUn { - sun_family: u16, sun_path: [u8; 108], } @@ -833,7 +855,6 @@ impl From for SockAddr { family: AF_INET as u16, payload: SockAddrPayload { addr_in: SockAddrIn { - sin_family: AF_INET as u16, sin_port: u16::to_be(endpoint.port), sin_addr: u32::to_be(u32::from_be_bytes(ipv4.0)), sin_zero: [0; 8], diff --git a/kernel/src/syscall/time.rs b/kernel/src/syscall/time.rs index 983d105..75272a2 100644 --- a/kernel/src/syscall/time.rs +++ b/kernel/src/syscall/time.rs @@ -112,3 +112,35 @@ pub fn sys_time(time: *mut u64) -> SysResult { } Ok(sec as usize) } + +// ignore other fields for now +#[repr(C)] +pub struct RUsage { + utime: TimeVal, + stime: TimeVal +} + +pub fn sys_getrusage(who: usize, rusage: *mut RUsage) -> SysResult { + info!("getrusage: who: {}, rusage: {:?}", who, rusage); + let proc = process(); + proc.memory_set.check_mut_ptr(rusage)?; + + let tick_base = *TICK_BASE; + let tick = unsafe { crate::trap::TICK as u64 }; + + let usec = (tick - tick_base) * USEC_PER_TICK as u64; + let new_rusage = RUsage { + utime: TimeVal { + sec: usec / USEC_PER_SEC, + usec: usec % USEC_PER_SEC, + }, + stime: TimeVal { + sec: usec / USEC_PER_SEC, + usec: usec % USEC_PER_SEC, + } + }; + unsafe { + *rusage = new_rusage + }; + Ok(0) +}