use std::ffi::{c_char, c_void};
use std::os::raw::c_int;
use std::ptr;
pub type VmnetInterfaceRef = *mut c_void;
pub type DispatchQueue = *mut c_void;
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum VmnetReturnT {
Success = 1000,
Failure = 1001,
MemFailure = 1002,
InvalidArgument = 1003,
SetupIncomplete = 1004,
InvalidAccess = 1005,
PacketTooBig = 1006,
BufferExhausted = 1007,
TooManyPackets = 1008,
SharingServiceBusy = 1009,
}
impl VmnetReturnT {
#[must_use]
pub fn is_success(self) -> bool {
self == Self::Success
}
#[must_use]
pub fn message(self) -> &'static str {
match self {
Self::Success => "success",
Self::Failure => "operation failed",
Self::MemFailure => "memory allocation failed",
Self::InvalidArgument => "invalid argument",
Self::SetupIncomplete => "setup incomplete",
Self::InvalidAccess => "invalid access",
Self::PacketTooBig => "packet too big",
Self::BufferExhausted => "buffer exhausted",
Self::TooManyPackets => "too many packets",
Self::SharingServiceBusy => "sharing service busy",
}
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum VmnetOperatingMode {
Host = 1000,
Shared = 1001,
Bridged = 1002,
}
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum VmnetInterfaceEvent {
PacketsAvailable = 1,
}
#[repr(C)]
#[derive(Debug)]
pub struct VmnetPacket {
pub vm_pkt_iov: *mut iovec,
pub vm_pkt_iovcnt: u32,
pub vm_pkt_size: u32,
pub vm_flags: u32,
}
#[repr(C)]
#[derive(Debug)]
pub struct iovec {
pub iov_base: *mut c_void,
pub iov_len: usize,
}
pub type CFDictionaryRef = *const c_void;
pub type CFMutableDictionaryRef = *mut c_void;
pub type CFStringRef = *const c_void;
pub type CFNumberRef = *const c_void;
pub type CFTypeRef = *const c_void;
pub type CFAllocatorRef = *const c_void;
pub type CFUUIDRef = *const c_void;
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub enum CFNumberType {
SInt8 = 1,
SInt16 = 2,
SInt32 = 3,
SInt64 = 4,
Float32 = 5,
Float64 = 6,
Char = 7,
Short = 8,
Int = 9,
Long = 10,
LongLong = 11,
Float = 12,
Double = 13,
}
pub type DispatchBlock = extern "C" fn();
#[link(name = "vmnet", kind = "framework")]
unsafe extern "C" {
pub fn vmnet_start_interface(
interface_desc: CFDictionaryRef,
queue: DispatchQueue,
handler: *const c_void, ) -> VmnetInterfaceRef;
pub fn vmnet_stop_interface(
interface: VmnetInterfaceRef,
queue: DispatchQueue,
handler: *const c_void, ) -> VmnetReturnT;
pub fn vmnet_read(
interface: VmnetInterfaceRef,
packets: *mut VmnetPacket,
pktcnt: *mut c_int,
) -> VmnetReturnT;
pub fn vmnet_write(
interface: VmnetInterfaceRef,
packets: *mut VmnetPacket,
pktcnt: *mut c_int,
) -> VmnetReturnT;
pub fn vmnet_interface_set_event_callback(
interface: VmnetInterfaceRef,
event_mask: VmnetInterfaceEvent,
queue: DispatchQueue,
handler: *const c_void, ) -> VmnetReturnT;
pub fn vmnet_copy_shared_interface_list() -> *mut c_void; }
#[link(name = "vmnet", kind = "framework")]
unsafe extern "C" {
pub static vmnet_operation_mode_key: CFStringRef;
pub static vmnet_shared_interface_name_key: CFStringRef;
pub static vmnet_mac_address_key: CFStringRef;
pub static vmnet_start_address_key: CFStringRef;
pub static vmnet_end_address_key: CFStringRef;
pub static vmnet_subnet_mask_key: CFStringRef;
pub static vmnet_interface_id_key: CFStringRef;
pub static vmnet_enable_isolation_key: CFStringRef;
pub static vmnet_nat66_prefix_key: CFStringRef;
pub static vmnet_mtu_key: CFStringRef;
pub static vmnet_max_packet_size_key: CFStringRef;
}
#[link(name = "CoreFoundation", kind = "framework")]
unsafe extern "C" {
pub static kCFAllocatorDefault: CFAllocatorRef;
pub static kCFBooleanTrue: CFTypeRef;
pub static kCFBooleanFalse: CFTypeRef;
pub fn CFDictionaryCreateMutable(
allocator: CFAllocatorRef,
capacity: isize,
key_callbacks: *const c_void,
value_callbacks: *const c_void,
) -> CFMutableDictionaryRef;
pub fn CFDictionarySetValue(dict: CFMutableDictionaryRef, key: CFTypeRef, value: CFTypeRef);
pub fn CFDictionaryGetValue(dict: CFDictionaryRef, key: CFTypeRef) -> CFTypeRef;
pub fn CFRelease(cf: CFTypeRef);
pub fn CFRetain(cf: CFTypeRef) -> CFTypeRef;
pub fn CFStringCreateWithCString(
alloc: CFAllocatorRef,
cstr: *const c_char,
encoding: u32,
) -> CFStringRef;
pub fn CFNumberCreate(
allocator: CFAllocatorRef,
type_: CFNumberType,
value_ptr: *const c_void,
) -> CFNumberRef;
pub fn CFNumberGetValue(
number: CFNumberRef,
type_: CFNumberType,
value_ptr: *mut c_void,
) -> bool;
pub fn CFUUIDCreate(allocator: CFAllocatorRef) -> CFUUIDRef;
pub fn CFUUIDCreateString(allocator: CFAllocatorRef, uuid: CFUUIDRef) -> CFStringRef;
}
#[link(name = "System")]
unsafe extern "C" {
pub fn dispatch_queue_create(label: *const c_char, attr: *const c_void) -> DispatchQueue;
pub fn dispatch_release(object: *mut c_void);
pub fn dispatch_async(queue: DispatchQueue, block: *const c_void);
pub fn dispatch_sync(queue: DispatchQueue, block: *const c_void);
pub static _dispatch_queue_attr_concurrent: *const c_void;
}
pub const K_CF_STRING_ENCODING_UTF8: u32 = 0x08000100;
#[must_use]
pub unsafe fn cfstring_from_str(s: &str) -> CFStringRef {
let cstr = std::ffi::CString::new(s).unwrap();
unsafe {
CFStringCreateWithCString(
kCFAllocatorDefault,
cstr.as_ptr(),
K_CF_STRING_ENCODING_UTF8,
)
}
}
#[must_use]
pub unsafe fn cfnumber_from_i64(value: i64) -> CFNumberRef {
unsafe {
CFNumberCreate(
kCFAllocatorDefault,
CFNumberType::SInt64,
(&raw const value).cast::<c_void>(),
)
}
}
#[must_use]
pub unsafe fn create_vmnet_config_dict() -> CFMutableDictionaryRef {
unsafe { CFDictionaryCreateMutable(kCFAllocatorDefault, 0, ptr::null(), ptr::null()) }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_vmnet_return_messages() {
assert_eq!(VmnetReturnT::Success.message(), "success");
assert_eq!(VmnetReturnT::Failure.message(), "operation failed");
assert!(VmnetReturnT::Success.is_success());
assert!(!VmnetReturnT::Failure.is_success());
}
#[test]
fn test_operating_modes() {
assert_eq!(VmnetOperatingMode::Host as i32, 1000);
assert_eq!(VmnetOperatingMode::Shared as i32, 1001);
assert_eq!(VmnetOperatingMode::Bridged as i32, 1002);
}
}