use crate::error::Result;
pub trait NetworkBackend: Send + Sync {
fn send(&self, data: &[u8]) -> Result<usize>;
fn recv(&self, buf: &mut [u8]) -> Result<usize>;
fn mac(&self) -> [u8; 6];
fn mtu(&self) -> u16;
}
#[cfg(target_os = "linux")]
pub struct TapBackend {
inner: crate::linux::LinuxTap,
}
#[cfg(target_os = "linux")]
impl TapBackend {
pub fn new(name: &str, mac: [u8; 6], mtu: u16) -> Result<Self> {
let config = crate::linux::TapConfig::new()
.with_name(name)
.with_mac(mac)
.with_mtu(mtu);
let inner = crate::linux::LinuxTap::new(config)?;
Ok(Self { inner })
}
pub fn new_default() -> Result<Self> {
let inner = crate::linux::LinuxTap::new(crate::linux::TapConfig::default())?;
Ok(Self { inner })
}
pub fn with_config(config: crate::linux::TapConfig) -> Result<Self> {
let inner = crate::linux::LinuxTap::new(config)?;
Ok(Self { inner })
}
#[must_use]
pub fn name(&self) -> &str {
self.inner.name()
}
pub fn bring_up(&self) -> Result<()> {
self.inner.bring_up()
}
pub fn bring_down(&self) -> Result<()> {
self.inner.bring_down()
}
#[must_use]
pub fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
self.inner.as_raw_fd()
}
}
#[cfg(target_os = "linux")]
impl NetworkBackend for TapBackend {
fn send(&self, data: &[u8]) -> Result<usize> {
self.inner.send(data)
}
fn recv(&self, buf: &mut [u8]) -> Result<usize> {
self.inner.recv(buf)
}
fn mac(&self) -> [u8; 6] {
self.inner.mac()
}
fn mtu(&self) -> u16 {
self.inner.mtu()
}
}
#[cfg(target_os = "macos")]
pub struct VmnetBackend {
inner: arcbox_vmnet::Vmnet,
}
#[cfg(target_os = "macos")]
impl VmnetBackend {
pub fn new(mac: [u8; 6], mtu: u16) -> Result<Self> {
let config = arcbox_vmnet::VmnetConfig::shared()
.with_mac(mac)
.with_mtu(mtu);
let inner = arcbox_vmnet::Vmnet::new(config)?;
Ok(Self { inner })
}
pub fn with_config(config: arcbox_vmnet::VmnetConfig) -> Result<Self> {
let inner = arcbox_vmnet::Vmnet::new(config)?;
Ok(Self { inner })
}
pub fn new_shared() -> Result<Self> {
let inner = arcbox_vmnet::Vmnet::new_shared()?;
Ok(Self { inner })
}
pub fn new_host_only() -> Result<Self> {
let inner = arcbox_vmnet::Vmnet::new_host_only()?;
Ok(Self { inner })
}
pub fn new_bridged(interface: &str) -> Result<Self> {
let inner = arcbox_vmnet::Vmnet::new_bridged(interface)?;
Ok(Self { inner })
}
#[must_use]
pub fn is_running(&self) -> bool {
self.inner.is_running()
}
#[must_use]
pub fn max_packet_size(&self) -> usize {
self.inner.max_packet_size()
}
pub fn stop(&self) {
self.inner.stop();
}
}
#[cfg(target_os = "macos")]
impl NetworkBackend for VmnetBackend {
fn send(&self, data: &[u8]) -> Result<usize> {
Ok(self.inner.write_packet(data)?)
}
fn recv(&self, buf: &mut [u8]) -> Result<usize> {
Ok(self.inner.read_packet(buf)?)
}
fn mac(&self) -> [u8; 6] {
self.inner.mac()
}
fn mtu(&self) -> u16 {
self.inner.mtu()
}
}