Implement recvmsg syscall for netlink

master
Jiajie Chen 6 years ago
parent 6335597897
commit 1f99f1270a

@ -8,7 +8,6 @@ use alloc::vec::Vec;
use alloc::collections::BTreeMap;
use isomorphic_drivers::net::ethernet::intel::ixgbe;
use log::*;
use rcore_memory::paging::PageTable;
use smoltcp::iface::*;
use smoltcp::phy::{self, Checksum, DeviceCapabilities};
use smoltcp::time::Instant;

@ -4,6 +4,8 @@ use crate::sync::SpinNoIrqLock as Mutex;
use crate::syscall::*;
use crate::util;
use alloc::boxed::Box;
use bitflags::*;
use core::mem::size_of;
use smoltcp::socket::*;
use smoltcp::wire::*;
@ -738,6 +740,62 @@ impl Socket for PacketSocketState {
}
}
#[repr(C)]
#[derive(Debug)]
struct NetlinkMessageHeader {
nlmsg_len: u32, // length of message including header
nlmsg_type: u16, // message content
nlmsg_flags: NetlinkMessageFlags, // additional flags
nlmsg_seq: u32, // sequence number
nlmsg_pid: u32, // sending process port id
}
bitflags! {
struct NetlinkMessageFlags : u16 {
const REQUEST = 0x01;
const MULTI = 0x02;
const ACK = 0x04;
const ECHO = 0x08;
const DUMP_INTR = 0x10;
const DUMP_FILTERED = 0x20;
// GET request
const ROOT = 0x100;
const MATCH = 0x200;
const ATOMIC = 0x400;
const DUMP = 0x100 | 0x200;
// NEW request
const REPLACE = 0x100;
const EXCL = 0x200;
const CREATE = 0x400;
const APPEND = 0x800;
// DELETE request
const NONREC = 0x100;
// ACK message
const CAPPED = 0x100;
const ACK_TLVS = 0x200;
}
}
enum_with_unknown! {
/// Netlink message types
pub doc enum NetlinkMessageType(u16) {
/// New link
NewLink = 16,
/// Delete link
DelLink = 17,
/// Get link
GetLink = 18,
/// Set link
SetLink = 19,
/// New addr
NewAddr = 20,
/// Delete addr
DelAddr = 21,
/// Get addr
GetAddr = 22,
}
}
impl NetlinkSocketState {
pub fn new() -> Self {
NetlinkSocketState {}
@ -751,7 +809,17 @@ impl Socket for NetlinkSocketState {
fn write(&self, data: &[u8], _sendto_endpoint: Option<Endpoint>) -> SysResult {
debug!("data: {:x?}", &data);
unimplemented!()
if data.len() < size_of::<NetlinkMessageHeader>() {
return Err(SysError::EINVAL);
}
let header = unsafe { &*(data.as_ptr() as *const NetlinkMessageHeader) };
if header.nlmsg_len as usize > data.len() {
return Err(SysError::EINVAL);
}
let message_type = NetlinkMessageType::from(header.nlmsg_type);
debug!("header: {:?}", header);
debug!("type: {:?}", message_type);
Ok(data.len())
}
fn poll(&self) -> (bool, bool, bool) {

@ -15,7 +15,7 @@ use xmas_elf::{
use crate::arch::interrupt::{Context, TrapFrame};
use crate::fs::{FileHandle, FileLike, INodeExt, OpenOptions, FOLLOW_MAX_DEPTH};
use crate::memory::{ByFrame, GlobalFrameAlloc, KernelStack, MemoryAttr, MemorySet};
use crate::net::{Socket, SOCKETS};
use crate::net::SOCKETS;
use crate::sync::{Condvar, SpinNoIrqLock as Mutex};
use super::abi::{self, ProcInitInfo};

@ -1069,10 +1069,10 @@ pub struct IoVec {
/// A valid IoVecs request from user
#[derive(Debug)]
struct IoVecs(Vec<&'static mut [u8]>);
pub struct IoVecs(Vec<&'static mut [u8]>);
impl IoVecs {
fn check_and_new(
pub fn check_and_new(
iov_ptr: *const IoVec,
iov_count: usize,
vm: &MemorySet,
@ -1098,7 +1098,7 @@ impl IoVecs {
Ok(IoVecs(slices))
}
fn read_all_to_vec(&self) -> Vec<u8> {
pub fn read_all_to_vec(&self) -> Vec<u8> {
let mut buf = self.new_buf(false);
for slice in self.0.iter() {
buf.extend(slice.iter());
@ -1106,7 +1106,7 @@ impl IoVecs {
buf
}
fn write_all_from_slice(&mut self, buf: &[u8]) {
pub fn write_all_from_slice(&mut self, buf: &[u8]) {
let mut copied_len = 0;
for slice in self.0.iter_mut() {
let copy_len = min(slice.len(), buf.len() - copied_len);
@ -1122,7 +1122,7 @@ impl IoVecs {
/// Create a new Vec buffer from IoVecs
/// For readv: `set_len` is true, Vec.len = total_len.
/// For writev: `set_len` is false, Vec.cap = total_len.
fn new_buf(&self, set_len: bool) -> Vec<u8> {
pub fn new_buf(&self, set_len: bool) -> Vec<u8> {
let total_len = self.0.iter().map(|slice| slice.len()).sum::<usize>();
let mut buf = Vec::with_capacity(total_len);
if set_len {

@ -109,7 +109,7 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
args[5] as *mut u32,
),
// SYS_SENDMSG => sys_sendmsg(),
// SYS_RECVMSG => sys_recvmsg(),
SYS_RECVMSG => sys_recvmsg(args[0], args[1] as *mut MsgHdr, args[2]),
SYS_SHUTDOWN => sys_shutdown(args[0], args[1]),
SYS_BIND => sys_bind(args[0], args[1] as *const SockAddr, args[2]),
// 50

@ -1,5 +1,6 @@
//! Syscalls for networking
use super::fs::IoVecs;
use super::*;
use crate::drivers::SOCKET_ACTIVITY;
use crate::fs::FileLike;
@ -173,6 +174,28 @@ pub fn sys_recvfrom(
result
}
pub fn sys_recvmsg(fd: usize, msg: *mut MsgHdr, flags: usize) -> SysResult {
info!("recvmsg: fd: {}, msg: {:?}, flags: {}", fd, msg, flags);
let mut proc = process();
proc.vm.check_read_ptr(msg)?;
let hdr = unsafe { &mut *msg };
let mut iovs = IoVecs::check_and_new(hdr.msg_iov, hdr.msg_iovlen, &proc.vm, true)?;
let mut buf = iovs.new_buf(true);
let socket = proc.get_socket(fd)?;
let (result, endpoint) = socket.read(&mut buf);
if let Ok(len) = result {
// copy data to user
iovs.write_all_from_slice(&buf[..len]);
let sockaddr_in = SockAddr::from(endpoint);
unsafe {
sockaddr_in.write_to(&mut proc, hdr.msg_name, &mut hdr.msg_namelen as *mut u32)?;
}
}
unimplemented!()
}
pub fn sys_bind(fd: usize, addr: *const SockAddr, addr_len: usize) -> SysResult {
info!("sys_bind: fd: {} addr: {:?} len: {}", fd, addr, addr_len);
let mut proc = process();
@ -433,6 +456,18 @@ impl SockAddr {
}
}
#[repr(C)]
#[derive(Debug)]
pub struct MsgHdr {
msg_name: *mut SockAddr,
msg_namelen: u32,
msg_iov: *mut IoVec,
msg_iovlen: usize,
msg_control: usize,
msg_controllen: usize,
msg_flags: usize,
}
enum_with_unknown! {
/// Address families
pub doc enum AddressFamily(u16) {

Loading…
Cancel
Save