Skip to content

Instantly share code, notes, and snippets.

@luqmana
Created December 8, 2022 02:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save luqmana/710a4461ffeb1905372cba7182ee0db0 to your computer and use it in GitHub Desktop.
Save luqmana/710a4461ffeb1905372cba7182ee0db0 to your computer and use it in GitHub Desktop.
#![allow(dead_code)]
use std::os::fd::AsRawFd;
extern "C" {
pub fn ioctl(fildes: i32, request: i32, ...) -> i32;
}
const VNIC_IOC_INFO: i32 = 0x1710003;
const MAXMACADDRLEN: usize = 20;
const MAXPATHLEN: usize = 1024;
const MPT_MAXCID: usize = 32;
const MPT_MAXIPADDR: usize = 32;
const MPT_MAXCIDLEN: usize = 256;
const MRP_NCPUS: usize = 256;
#[derive(Copy, Clone, Debug, Default)]
#[repr(C)]
struct VnicInfoIoc {
pub vnic_id: u32,
pub link_id: u32,
pub mac_addr_type: VnicMacAddrType,
pub mac_len: u32,
pub mac_addr: [u8; MAXMACADDRLEN],
pub mac_slot: u32,
pub mac_prefix_len: u32,
pub vid: u16,
pub vrid: u32,
pub af: u32,
pub force: bool,
pub resource_props: MacResourceProps,
}
#[derive(Copy, Clone, Debug, Default)]
#[repr(i32)]
enum VnicMacAddrType {
#[default]
Unknown = -1,
Fixed,
Random,
Factory,
Auto,
Primary,
Vrid,
}
#[derive(Copy, Clone, Debug)]
#[repr(C, packed(4))]
struct MacResourceProps {
pub mask: u32,
pub maxbw: u64,
pub priority: MacPriorityLevel,
pub cpus: MacCPUsProps,
pub protect: MacProtect,
pub nrxrings: u32,
pub ntxrings: u32,
pub pool: [u8; MAXPATHLEN],
}
impl Default for MacResourceProps {
fn default() -> Self {
Self {
mask: 0,
maxbw: 0,
priority: MacPriorityLevel::Low,
cpus: MacCPUsProps::default(),
protect: MacProtect::default(),
nrxrings: 0,
ntxrings: 0,
pool: [0; MAXPATHLEN],
}
}
}
#[derive(Copy, Clone, Debug)]
#[repr(i32)]
enum MacPriorityLevel {
Low,
Medium,
High,
Reset,
}
#[derive(Copy, Clone, Debug)]
#[repr(C)]
struct MacCPUsProps {
pub ncpus: u32,
pub cpus: [u32; MRP_NCPUS],
pub rx_fanout_cnt: u32,
pub rx_fanout_cpus: [u32; MRP_NCPUS],
pub rx_pollid: u32,
pub rx_workerid: u32,
pub rx_intr_cpu: i32,
pub tx_fanout_cpus: [i32; MRP_NCPUS],
pub tx_intr_cpus: MacTxIntrCPUs,
pub fanout_mode: MacCpuMode,
}
impl Default for MacCPUsProps {
fn default() -> Self {
Self {
ncpus: 0,
cpus: [0; MRP_NCPUS],
rx_fanout_cnt: 0,
rx_fanout_cpus: [0; MRP_NCPUS],
rx_pollid: 0,
rx_workerid: 0,
rx_intr_cpu: 0,
tx_fanout_cpus: [0; MRP_NCPUS],
tx_intr_cpus: MacTxIntrCPUs::default(),
fanout_mode: MacCpuMode::Fanout,
}
}
}
#[derive(Copy, Clone, Debug)]
#[repr(C)]
struct MacTxIntrCPUs {
pub mtc_intr_cpu: [i32; MRP_NCPUS],
pub mtc_retargeted_cpu: [i32; MRP_NCPUS],
}
impl Default for MacTxIntrCPUs {
fn default() -> Self {
Self {
mtc_intr_cpu: [0; MRP_NCPUS],
mtc_retargeted_cpu: [0; MRP_NCPUS],
}
}
}
#[derive(Copy, Clone, Debug)]
#[repr(i32)]
enum MacCpuMode {
Fanout = 1,
Cpus,
}
#[derive(Copy, Clone, Debug)]
#[repr(C)]
struct MacProtect {
pub types: u32,
pub ipaddrcnt: u32,
pub ipaddrs: [MacIpaddr; MPT_MAXIPADDR],
pub cidcnt: u32,
pub cids: [MacDhcpCid; MPT_MAXCID],
}
impl Default for MacProtect {
fn default() -> Self {
Self {
types: 0,
ipaddrcnt: 0,
ipaddrs: [MacIpaddr::default(); MPT_MAXIPADDR],
cidcnt: 0,
cids: [MacDhcpCid::default(); MPT_MAXCID],
}
}
}
#[derive(Copy, Clone, Debug, Default)]
#[repr(C)]
struct MacIpaddr {
pub version: u32,
pub addr: In6Addr,
pub netmask: u8,
}
#[derive(Copy, Clone, Debug)]
#[repr(C)]
struct In6Addr {
pub data: In6Data,
}
impl Default for In6Addr {
fn default() -> Self {
Self {
data: In6Data { parts: [0; 8] },
}
}
}
#[repr(C)]
union In6Data {
pub parts: [u16; 8],
pub align: u32,
}
impl Copy for In6Data {}
impl Clone for In6Data {
fn clone(&self) -> Self {
unsafe {
let mut c = In6Data { parts: [0; 8] };
for (i, x) in self.parts.iter().enumerate() {
c.parts[i] = *x;
}
c
}
}
}
impl std::fmt::Debug for In6Data {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "In6Data {{ parts: {:?} }}", unsafe { self.parts })
}
}
#[derive(Copy, Clone, Debug)]
#[repr(C)]
struct MacDhcpCid {
pub id: [u8; MPT_MAXCIDLEN],
pub len: u32,
pub form: MacDhcpCidFrom,
}
impl Default for MacDhcpCid {
fn default() -> Self {
Self {
id: [0; MPT_MAXCIDLEN],
len: 0,
form: MacDhcpCidFrom::Typed,
}
}
}
#[derive(Copy, Clone, Debug)]
#[repr(i32)]
enum MacDhcpCidFrom {
Typed = 1,
Hex,
Str,
}
fn dld_fd() -> Result<std::fs::File, std::io::Error> {
std::fs::OpenOptions::new()
.read(true)
.write(true)
.open("/dev/dld")
}
fn get_vnic_info(link_id: u32) -> Result<VnicInfoIoc, std::io::Error> {
let fd = dld_fd()?;
unsafe {
let arg = VnicInfoIoc {
vnic_id: link_id,
..Default::default()
};
let res = ioctl(fd.as_raw_fd(), VNIC_IOC_INFO, &arg);
eprintln!("ioctl returned {res}");
if res == -1 {
let err = std::io::Error::last_os_error();
eprintln!("ioctl failed: {err}");
return Err(err);
}
Ok(arg)
}
}
fn main() {
let Some(link) = std::env::args().nth(1) else {
eprintln!("Usage: linkinfo <link id>");
std::process::exit(1);
};
let Ok(link_id) = link.parse::<u32>() else {
eprintln!("invalid link id");
std::process::exit(1);
};
match get_vnic_info(link_id) {
Ok(info) => {
println!("{info:?}");
}
Err(err) => {
eprintln!("Failed to get vnic info: {err}");
}
}
}
@luqmana
Copy link
Author

luqmana commented Dec 8, 2022

$ ./main 122
ioctl returned 0
Failed to get vnic info: Not owner (os error 1)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment