Add netdevice ioctl command
This commit is contained in:
parent
5e9a617350
commit
e13242e7e5
@ -200,6 +200,14 @@ enclave {
|
||||
void occlum_ocall_print_log(uint32_t level, [in, string] const char* msg);
|
||||
void occlum_ocall_flush_log(void);
|
||||
|
||||
int occlum_ocall_ioctl_repack(
|
||||
int fd,
|
||||
int request,
|
||||
[in, out, size=len] char *buf,
|
||||
int len,
|
||||
[out] int* recv_len
|
||||
) propagate_errno;
|
||||
|
||||
int occlum_ocall_ioctl(
|
||||
int fd,
|
||||
int request,
|
||||
|
@ -10,3 +10,18 @@ pub struct WinSize {
|
||||
pub ws_xpixel: u16,
|
||||
pub ws_ypixel: u16,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct IfConf {
|
||||
pub ifc_len: i32,
|
||||
pub ifc_buf: *const u8,
|
||||
}
|
||||
|
||||
const IFNAMSIZ: usize = 16;
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct IfReq {
|
||||
pub ifr_name: [u8; IFNAMSIZ],
|
||||
pub ifr_union: [u8; 24],
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
use super::*;
|
||||
|
||||
pub use self::builtin::WinSize;
|
||||
pub use self::builtin::*;
|
||||
pub use self::non_builtin::{NonBuiltinIoctlCmd, StructuredIoctlArgType, StructuredIoctlNum};
|
||||
|
||||
#[macro_use]
|
||||
@ -37,6 +37,21 @@ impl_ioctl_nums_and_cmds! {
|
||||
TIOCNOTTY => (0x5422, ()),
|
||||
// Get the number of bytes in the input buffer
|
||||
FIONREAD => (0x541B, mut i32),
|
||||
// Low-level access to Linux network devices on man7/netdevice.7
|
||||
// Only non-privileged operations are supported for now
|
||||
SIOCGIFNAME => (0x8910, mut IfReq),
|
||||
SIOCGIFCONF => (0x8912, mut IfConf),
|
||||
SIOCGIFFLAGS => (0x8913, mut IfReq),
|
||||
SIOCGIFADDR => (0x8915, mut IfReq),
|
||||
SIOCGIFDSTADDR => (0x8917, mut IfReq),
|
||||
SIOCGIFBRDADDR => (0x8919, mut IfReq),
|
||||
SIOCGIFNETMASK => (0x891B, mut IfReq),
|
||||
SIOCGIFMTU => (0x8921, mut IfReq),
|
||||
SIOCGIFHWADDR => (0x8927, mut IfReq),
|
||||
SIOCGIFINDEX => (0x8933, mut IfReq),
|
||||
SIOCGIFPFLAGS => (0x8935, mut IfReq),
|
||||
SIOCGIFTXQLEN => (0x8942, mut IfReq),
|
||||
SIOCGIFMAP => (0x8970, mut IfReq),
|
||||
}
|
||||
|
||||
/// This is the centralized place to add sanity checks for the argument values
|
||||
|
@ -14,7 +14,8 @@ pub use self::file_flags::{AccessMode, CreationFlags, StatusFlags};
|
||||
pub use self::flock::{Flock, FlockType};
|
||||
pub use self::fsync::{do_fdatasync, do_fsync};
|
||||
pub use self::ioctl::{
|
||||
do_ioctl, occlum_ocall_ioctl, IoctlCmd, StructuredIoctlArgType, StructuredIoctlNum,
|
||||
do_ioctl, occlum_ocall_ioctl, BuiltinIoctlNum, IfConf, IoctlCmd, StructuredIoctlArgType,
|
||||
StructuredIoctlNum,
|
||||
};
|
||||
pub use self::link::do_link;
|
||||
pub use self::lseek::do_lseek;
|
||||
|
@ -14,8 +14,8 @@ pub use self::dev_fs::AsDevRandom;
|
||||
pub use self::event_file::{AsEvent, EventCreationFlags, EventFile};
|
||||
pub use self::file::{File, FileRef};
|
||||
pub use self::file_ops::{
|
||||
occlum_ocall_ioctl, AccessMode, CreationFlags, FileMode, Flock, FlockType, IoctlCmd, Stat,
|
||||
StatusFlags, StructuredIoctlArgType, StructuredIoctlNum,
|
||||
occlum_ocall_ioctl, AccessMode, BuiltinIoctlNum, CreationFlags, FileMode, Flock, FlockType,
|
||||
IfConf, IoctlCmd, Stat, StatusFlags, StructuredIoctlArgType, StructuredIoctlNum,
|
||||
};
|
||||
pub use self::file_table::{FileDesc, FileTable};
|
||||
pub use self::fs_view::FsView;
|
||||
|
82
src/libos/src/net/socket_file/ioctl_impl.rs
Normal file
82
src/libos/src/net/socket_file/ioctl_impl.rs
Normal file
@ -0,0 +1,82 @@
|
||||
use super::*;
|
||||
use fs::{occlum_ocall_ioctl, BuiltinIoctlNum, IoctlCmd};
|
||||
|
||||
impl SocketFile {
|
||||
pub(super) fn ioctl_impl(&self, cmd: &mut IoctlCmd) -> Result<i32> {
|
||||
if let IoctlCmd::SIOCGIFCONF(arg_ref) = cmd {
|
||||
return self.ioctl_getifconf(arg_ref);
|
||||
}
|
||||
|
||||
let cmd_num = cmd.cmd_num() as c_int;
|
||||
let cmd_arg_ptr = cmd.arg_ptr() as *mut c_void;
|
||||
let ret = try_libc!({
|
||||
let mut retval: i32 = 0;
|
||||
let status = occlum_ocall_ioctl(
|
||||
&mut retval as *mut i32,
|
||||
self.fd(),
|
||||
cmd_num,
|
||||
cmd_arg_ptr,
|
||||
cmd.arg_len(),
|
||||
);
|
||||
assert!(status == sgx_status_t::SGX_SUCCESS);
|
||||
retval
|
||||
});
|
||||
// FIXME: add sanity checks for results returned for socket-related ioctls
|
||||
cmd.validate_arg_and_ret_vals(ret)?;
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
fn ioctl_getifconf(&self, arg_ref: &mut IfConf) -> Result<i32> {
|
||||
if !arg_ref.ifc_buf.is_null() && arg_ref.ifc_len == 0 {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
let ret = try_libc!({
|
||||
let mut recv_len: i32 = 0;
|
||||
let mut retval: i32 = 0;
|
||||
let status = occlum_ocall_ioctl_repack(
|
||||
&mut retval as *mut i32,
|
||||
self.fd(),
|
||||
BuiltinIoctlNum::SIOCGIFCONF as i32,
|
||||
arg_ref.ifc_buf,
|
||||
arg_ref.ifc_len,
|
||||
&mut recv_len as *mut i32,
|
||||
);
|
||||
assert!(status == sgx_status_t::SGX_SUCCESS);
|
||||
// If ifc_req is NULL, SIOCGIFCONF returns the necessary buffer
|
||||
// size in bytes for receiving all available addresses in ifc_len
|
||||
// which is irrelevant to the orginal ifc_len.
|
||||
if !arg_ref.ifc_buf.is_null() {
|
||||
assert!(arg_ref.ifc_len >= recv_len);
|
||||
}
|
||||
|
||||
arg_ref.ifc_len = recv_len;
|
||||
retval
|
||||
});
|
||||
Ok(ret)
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
// Used to ioctl arguments with pointer members.
|
||||
//
|
||||
// Before the call the area the pointers points to should be assembled into
|
||||
// one continous memory block. Then the block is repacked to ioctl arguments
|
||||
// in the ocall implementation in host.
|
||||
//
|
||||
// ret: holds the return value of ioctl in host
|
||||
// fd: the host fd for the device
|
||||
// cmd_num: request number of the ioctl
|
||||
// buf: the data to exchange with host
|
||||
// len: the size of the buf
|
||||
// recv_len: accepts transferred data length when buf is used to get data from host
|
||||
//
|
||||
fn occlum_ocall_ioctl_repack(
|
||||
ret: *mut i32,
|
||||
fd: c_int,
|
||||
cmd_num: c_int,
|
||||
buf: *const u8,
|
||||
len: i32,
|
||||
recv_len: *mut i32,
|
||||
) -> sgx_status_t;
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
use super::*;
|
||||
use crate::fs::IfConf;
|
||||
|
||||
mod ioctl_impl;
|
||||
mod recv;
|
||||
mod send;
|
||||
|
||||
use fs::{occlum_ocall_ioctl, AccessMode, CreationFlags, File, FileRef, IoctlCmd, StatusFlags};
|
||||
use fs::{AccessMode, CreationFlags, File, FileRef, IoctlCmd, StatusFlags};
|
||||
use std::any::Any;
|
||||
use std::io::{Read, Seek, SeekFrom, Write};
|
||||
|
||||
@ -107,23 +109,7 @@ impl File for SocketFile {
|
||||
}
|
||||
|
||||
fn ioctl(&self, cmd: &mut IoctlCmd) -> Result<i32> {
|
||||
let cmd_num = cmd.cmd_num() as c_int;
|
||||
let cmd_arg_ptr = cmd.arg_ptr() as *mut c_void;
|
||||
let ret = try_libc!({
|
||||
let mut retval: i32 = 0;
|
||||
let status = occlum_ocall_ioctl(
|
||||
&mut retval as *mut i32,
|
||||
self.fd(),
|
||||
cmd_num,
|
||||
cmd_arg_ptr,
|
||||
cmd.arg_len(),
|
||||
);
|
||||
assert!(status == sgx_status_t::SGX_SUCCESS);
|
||||
retval
|
||||
});
|
||||
// FIXME: add sanity checks for results returned for socket-related ioctls
|
||||
cmd.validate_arg_and_ret_vals(ret)?;
|
||||
Ok(ret)
|
||||
self.ioctl_impl(cmd)
|
||||
}
|
||||
|
||||
fn get_access_mode(&self) -> Result<AccessMode> {
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "ocalls.h"
|
||||
#include <errno.h>
|
||||
#include <net/if.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/eventfd.h>
|
||||
#include <sys/ioctl.h>
|
||||
@ -12,9 +13,33 @@ int occlum_ocall_eventfd(unsigned int initval, int flags) {
|
||||
return eventfd(initval, flags);
|
||||
}
|
||||
|
||||
int occlum_ocall_ioctl_repack(int fd, int request, char *buf, int len, int *recv_len) {
|
||||
int ret = 0;
|
||||
|
||||
switch (request) {
|
||||
case SIOCGIFCONF:
|
||||
if (recv_len == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct ifconf config = { .ifc_len = len, .ifc_buf = buf };
|
||||
ret = ioctl(fd, SIOCGIFCONF, &config);
|
||||
if (ret == 0) {
|
||||
*recv_len = config.ifc_len;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int occlum_ocall_ioctl(int fd, int request, void *arg, size_t len) {
|
||||
if (((arg == NULL) ^ (len == 0)) == 1) {
|
||||
printf("invalid ioctl parameters\n");
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
#include <net/if.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
@ -216,6 +218,62 @@ int test_sgx_ioctl_SGXIOC_CREATE_AND_VERIFY_REPORT(void) {
|
||||
return do_sgx_ioctl_test(do_SGXIOC_CREATE_AND_VERIFY_REPORT);
|
||||
}
|
||||
|
||||
#define CONFIG_SIZE 512
|
||||
int test_ioctl_SIOCGIFCONF(void) {
|
||||
struct ifreq *req;
|
||||
struct ifconf conf;
|
||||
char buf[CONFIG_SIZE];
|
||||
memset(buf, 0, CONFIG_SIZE);
|
||||
|
||||
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
conf.ifc_len = 0;
|
||||
conf.ifc_buf = buf;
|
||||
if (ioctl(sock, SIOCGIFCONF, &conf) < 0) {
|
||||
close(sock);
|
||||
THROW_ERROR("empty length ioctl failed");
|
||||
}
|
||||
|
||||
if (conf.ifc_len != 0) {
|
||||
close(sock);
|
||||
THROW_ERROR("wrong returned length");
|
||||
}
|
||||
|
||||
conf.ifc_len = CONFIG_SIZE;
|
||||
conf.ifc_buf = 0;
|
||||
if (ioctl(sock, SIOCGIFCONF, &conf) < 0) {
|
||||
close(sock);
|
||||
THROW_ERROR("empty buffer ioctl failed");
|
||||
}
|
||||
|
||||
int ret_len = conf.ifc_len;
|
||||
|
||||
conf.ifc_len = CONFIG_SIZE;
|
||||
conf.ifc_buf = buf;
|
||||
if (ioctl(sock, SIOCGIFCONF, &conf) < 0) {
|
||||
close(sock);
|
||||
THROW_ERROR("buffer passed ioctl failed");
|
||||
}
|
||||
|
||||
if (conf.ifc_len != ret_len) {
|
||||
close(sock);
|
||||
THROW_ERROR("wrong return length");
|
||||
}
|
||||
|
||||
close(sock);
|
||||
|
||||
req = (struct ifreq *)buf;
|
||||
int num = conf.ifc_len / sizeof (struct ifreq);
|
||||
|
||||
printf(" interface names got:\n");
|
||||
for (int i = 0; i < num; i++) {
|
||||
printf(" %d: %s\n", i + 1, req->ifr_name);
|
||||
req ++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Test suite
|
||||
// ============================================================================
|
||||
@ -226,7 +284,8 @@ static test_case_t test_cases[] = {
|
||||
TEST_CASE(test_sgx_ioctl_SGXIOC_GET_EPID_GROUP_ID),
|
||||
TEST_CASE(test_sgx_ioctl_SGXIOC_GEN_QUOTE),
|
||||
TEST_CASE(test_sgx_ioctl_SGXIOC_SELF_TARGET),
|
||||
TEST_CASE(test_sgx_ioctl_SGXIOC_CREATE_AND_VERIFY_REPORT)
|
||||
TEST_CASE(test_sgx_ioctl_SGXIOC_CREATE_AND_VERIFY_REPORT),
|
||||
TEST_CASE(test_ioctl_SIOCGIFCONF),
|
||||
};
|
||||
|
||||
int main() {
|
||||
|
Loading…
Reference in New Issue
Block a user