checkpoint
This commit is contained in:
parent
ede0d13bca
commit
db1750a045
39 changed files with 514 additions and 359 deletions
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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)?
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)?;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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)?
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue