checkpoint

This commit is contained in:
Jett Chen 2023-12-10 03:44:31 +08:00
parent ede0d13bca
commit db1750a045
39 changed files with 514 additions and 359 deletions

View file

@ -15,4 +15,4 @@ mod options;
pub mod tokio;
pub use options::TunOptions;
pub use os_imp::{TunInterface, TunQueue};
pub use os_imp::{retrieve, TunInterface, TunQueue};

View file

@ -5,31 +5,42 @@ use fehler::throws;
use super::TunInterface;
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize, schemars::JsonSchema))]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize, schemars::JsonSchema)
)]
pub struct TunOptions {
/// (Windows + Linux) Name the tun interface.
pub(crate) name: Option<String>,
pub name: Option<String>,
/// (Linux) Don't include packet information.
pub(crate) no_pi: Option<()>,
pub no_pi: bool,
/// (Linux) Avoid opening an existing persistant device.
pub(crate) tun_excl: Option<()>,
pub tun_excl: bool,
/// (MacOS) Whether to seek the first available utun device.
pub(crate) seek_utun: Option<()>,
pub seek_utun: Option<i32>,
/// (Linux) The IP address of the tun interface.
pub(crate) address: Option<String>,
pub address: Option<String>,
}
impl TunOptions {
pub fn new() -> Self { Self::default() }
pub fn new() -> Self {
Self::default()
}
pub fn name(mut self, name: &str) -> Self {
self.name = Some(name.to_owned());
self
}
pub fn no_pi(mut self, enable: bool) { self.no_pi = enable.then_some(()); }
pub fn no_pi(mut self, enable: bool) -> Self {
self.no_pi = enable;
self
}
pub fn tun_excl(mut self, enable: bool) { self.tun_excl = enable.then_some(()); }
pub fn tun_excl(mut self, enable: bool) -> Self {
self.tun_excl = enable;
self
}
pub fn address(mut self, address: impl ToString) -> Self {
self.address = Some(address.to_string());
@ -37,5 +48,7 @@ impl TunOptions {
}
#[throws]
pub fn open(self) -> TunInterface { TunInterface::new_with_options(self)? }
pub fn open(self) -> TunInterface {
TunInterface::new_with_options(self)?
}
}

View file

@ -12,9 +12,7 @@ impl TunInterface {
#[instrument]
pub fn new(mut tun: crate::TunInterface) -> io::Result<Self> {
tun.set_nonblocking(true)?;
Ok(Self {
inner: AsyncFd::new(tun)?,
})
Ok(Self { inner: AsyncFd::new(tun)? })
}
#[instrument]
@ -31,22 +29,22 @@ impl TunInterface {
// #[instrument]
pub async fn recv(&mut self, buf: &mut [u8]) -> io::Result<usize> {
loop {
// log::debug!("TunInterface receiving...");
// tracing::debug!("TunInterface receiving...");
let mut guard = self.inner.readable_mut().await?;
// log::debug!("Got! readable_mut");
// tracing::debug!("Got! readable_mut");
match guard.try_io(|inner| {
let raw_ref = (*inner).get_mut();
let recved = raw_ref.recv(buf);
recved
}) {
Ok(result) => {
log::debug!("HORRAY");
return result
},
tracing::debug!("HORRAY");
return result;
}
Err(_would_block) => {
log::debug!("WouldBlock");
continue
},
tracing::debug!("WouldBlock");
continue;
}
}
}
}

View file

@ -9,11 +9,12 @@ use byteorder::{ByteOrder, NetworkEndian};
use fehler::throws;
use libc::{c_char, iovec, writev, AF_INET, AF_INET6};
use socket2::{Domain, SockAddr, Socket, Type};
use tracing::{self, instrument};
use tracing::{self, debug, instrument};
mod kern_control;
mod sys;
pub mod sys;
use crate::retrieve;
use kern_control::SysControlSocket;
pub use super::queue::TunQueue;
@ -34,8 +35,13 @@ impl TunInterface {
#[throws]
#[instrument]
pub fn new_with_options(options: TunOptions) -> TunInterface {
let ti = TunInterface::connect(0)?;
if let Some(addr) = options.address{
debug!("Opening tun interface with options: {:?}", &options);
let ti = if let Some(n) = options.seek_utun {
retrieve().ok_or(Error::new(std::io::ErrorKind::NotFound, "No utun found"))?
} else {
TunInterface::connect(0)?
};
if let Some(addr) = options.address {
if let Ok(addr) = addr.parse() {
ti.set_ipv4_addr(addr)?;
}

View file

@ -2,20 +2,11 @@ use std::mem;
use libc::{c_char, c_int, c_short, c_uint, c_ulong, sockaddr};
pub use libc::{
c_void,
sockaddr_ctl,
sockaddr_in,
socklen_t,
AF_SYSTEM,
AF_SYS_CONTROL,
IFNAMSIZ,
c_void, sockaddr_ctl, sockaddr_in, socklen_t, AF_SYSTEM, AF_SYS_CONTROL, IFNAMSIZ,
SYSPROTO_CONTROL,
};
use nix::{
ioctl_read_bad,
ioctl_readwrite,
ioctl_write_ptr_bad,
request_code_readwrite,
ioctl_read_bad, ioctl_readwrite, ioctl_write_ptr_bad, request_code_readwrite,
request_code_write,
};

View file

@ -26,7 +26,9 @@ pub struct TunInterface {
impl TunInterface {
#[throws]
#[instrument]
pub fn new() -> TunInterface { Self::new_with_options(TunOptions::new())? }
pub fn new() -> TunInterface {
Self::new_with_options(TunOptions::new())?
}
#[throws]
#[instrument]
@ -212,5 +214,7 @@ impl TunInterface {
#[throws]
#[instrument]
pub fn send(&self, buf: &[u8]) -> usize { self.socket.send(buf)? }
pub fn send(&self, buf: &[u8]) -> usize {
self.socket.send(buf)?
}
}

View file

@ -1,11 +1,13 @@
use std::mem::size_of;
use std::{
io::{Error, Read},
mem,
os::fd::{AsRawFd, FromRawFd, IntoRawFd, RawFd},
};
use tracing::instrument;
use tracing::{debug, error, instrument};
use super::TunOptions;
use super::{syscall, TunOptions};
mod queue;
@ -17,9 +19,13 @@ mod imp;
#[path = "linux/mod.rs"]
mod imp;
use crate::os_imp::imp::sys;
use crate::os_imp::imp::sys::resolve_ctl_info;
use fehler::throws;
pub use imp::TunInterface;
use libc::{getpeername, sockaddr_ctl, sockaddr_storage, socklen_t, AF_SYSTEM, AF_SYS_CONTROL};
pub use queue::TunQueue;
use socket2::SockAddr;
impl AsRawFd for TunInterface {
fn as_raw_fd(&self) -> RawFd {
@ -47,8 +53,8 @@ impl TunInterface {
// 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
buf[..len - 4].copy_from_slice(&tmp_buf[4..len]);
len - 4
}
#[throws]
@ -76,3 +82,35 @@ pub fn string_to_ifname(name: &str) -> [libc::c_char; libc::IFNAMSIZ] {
buf[..len].copy_from_slice(unsafe { &*(name.as_bytes() as *const _ as *const [libc::c_char]) });
buf
}
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
pub fn retrieve() -> Option<TunInterface> {
(3..100)
.filter_map(|i| {
let result = unsafe {
let mut addr = sockaddr_ctl {
sc_len: size_of::<sockaddr_ctl>() as u8,
sc_family: 0,
ss_sysaddr: 0,
sc_id: 0,
sc_unit: 0,
sc_reserved: Default::default(),
};
let mut len = mem::size_of::<sockaddr_ctl>() as libc::socklen_t;
let res = syscall!(getpeername(i, &mut addr as *mut _ as *mut _, len as *mut _));
tracing::debug!("getpeername{}: {:?}", i, res);
if res.is_err() {
return None;
}
if addr.sc_family == sys::AF_SYSTEM as u8
&& addr.ss_sysaddr == sys::AF_SYS_CONTROL as u16
{
Some(TunInterface::from_raw_fd(i))
} else {
None
}
};
result
})
.next()
}

View file

@ -25,7 +25,9 @@ impl Debug for TunInterface {
impl TunInterface {
#[throws]
pub fn new() -> TunInterface { Self::new_with_options(TunOptions::new())? }
pub fn new() -> TunInterface {
Self::new_with_options(TunOptions::new())?
}
#[throws]
pub(crate) fn new_with_options(options: TunOptions) -> TunInterface {
@ -37,17 +39,18 @@ impl TunInterface {
if handle.is_null() {
unsafe { GetLastError() }.ok()?
}
TunInterface {
handle,
name: name_owned,
}
TunInterface { handle, name: name_owned }
}
pub fn name(&self) -> String { self.name.clone() }
pub fn name(&self) -> String {
self.name.clone()
}
}
impl Drop for TunInterface {
fn drop(&mut self) { unsafe { sys::WINTUN.WintunCloseAdapter(self.handle) } }
fn drop(&mut self) {
unsafe { sys::WINTUN.WintunCloseAdapter(self.handle) }
}
}
pub(crate) mod sys {