burrow/tun/src/unix/mod.rs
2023-12-17 01:26:37 +08:00

76 lines
1.8 KiB
Rust

use std::{
io::{Error, Read},
os::fd::{AsRawFd, FromRawFd, IntoRawFd, RawFd},
};
use tracing::instrument;
mod queue;
#[cfg(target_vendor = "apple")]
#[path = "apple/mod.rs"]
mod imp;
#[cfg(target_os = "linux")]
#[path = "linux/mod.rs"]
mod imp;
use fehler::throws;
pub use imp::TunInterface;
pub use queue::TunQueue;
impl AsRawFd for TunInterface {
fn as_raw_fd(&self) -> RawFd {
self.socket.as_raw_fd()
}
}
impl FromRawFd for TunInterface {
unsafe fn from_raw_fd(fd: RawFd) -> TunInterface {
let socket = socket2::Socket::from_raw_fd(fd);
TunInterface { socket }
}
}
impl IntoRawFd for TunInterface {
fn into_raw_fd(self) -> RawFd {
self.socket.into_raw_fd()
}
}
impl TunInterface {
#[throws]
#[instrument]
pub fn recv(&mut self, buf: &mut [u8]) -> usize {
// there might be a more efficient way to implement this
let tmp_buf = &mut [0u8; 1500];
let len = self.socket.read(tmp_buf)?;
buf[..len - 4].copy_from_slice(&tmp_buf[4..len]);
len - 4
}
#[throws]
#[instrument]
pub fn set_nonblocking(&mut self, nb: bool) {
self.socket.set_nonblocking(nb)?;
}
}
#[instrument]
pub fn ifname_to_string(buf: [libc::c_char; libc::IFNAMSIZ]) -> String {
// TODO: Switch to `CStr::from_bytes_until_nul` when stabilized
unsafe {
std::ffi::CStr::from_ptr(buf.as_ptr() as *const _)
.to_str()
.unwrap()
.to_string()
}
}
#[instrument]
pub fn string_to_ifname(name: &str) -> [libc::c_char; libc::IFNAMSIZ] {
let mut buf = [0 as libc::c_char; libc::IFNAMSIZ];
let len = name.len().min(buf.len());
buf[..len].copy_from_slice(unsafe { &*(name.as_bytes() as *const _ as *const [libc::c_char]) });
buf
}