2023-09-23 16:09:44 +08:00
|
|
|
use mio::{event, windows::NamedPipe, Interest, Registry, Token};
|
2023-09-18 21:40:56 +08:00
|
|
|
use smoltcp::{
|
|
|
|
phy::{self, Device, DeviceCapabilities, Medium},
|
|
|
|
time::Instant,
|
|
|
|
};
|
|
|
|
use std::{
|
2023-09-23 21:43:40 +08:00
|
|
|
cell::RefCell,
|
2023-09-23 16:09:44 +08:00
|
|
|
fs::OpenOptions,
|
2023-09-23 21:43:40 +08:00
|
|
|
io::{self, Read, Write},
|
2023-09-18 21:40:56 +08:00
|
|
|
net::{IpAddr, Ipv4Addr},
|
2023-09-23 16:09:44 +08:00
|
|
|
os::windows::prelude::{FromRawHandle, IntoRawHandle, OpenOptionsExt},
|
2023-09-23 21:43:40 +08:00
|
|
|
rc::Rc,
|
2023-09-24 13:02:00 +08:00
|
|
|
sync::{Arc, Mutex},
|
2023-09-24 17:56:49 +08:00
|
|
|
thread::JoinHandle,
|
2023-09-18 21:40:56 +08:00
|
|
|
vec::Vec,
|
|
|
|
};
|
2023-09-23 21:57:00 +08:00
|
|
|
use windows::Win32::Storage::FileSystem::FILE_FLAG_OVERLAPPED;
|
2023-09-23 16:09:44 +08:00
|
|
|
|
|
|
|
fn server() -> io::Result<(NamedPipe, String)> {
|
2023-09-23 21:57:00 +08:00
|
|
|
use rand::Rng;
|
|
|
|
let num: u64 = rand::thread_rng().gen();
|
2023-09-23 16:09:44 +08:00
|
|
|
let name = format!(r"\\.\pipe\my-pipe-{}", num);
|
|
|
|
let pipe = NamedPipe::new(&name)?;
|
|
|
|
Ok((pipe, name))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn client(name: &str) -> io::Result<NamedPipe> {
|
|
|
|
let mut opts = OpenOptions::new();
|
|
|
|
opts.read(true).write(true).custom_flags(FILE_FLAG_OVERLAPPED.0);
|
|
|
|
let file = opts.open(name)?;
|
|
|
|
unsafe { Ok(NamedPipe::from_raw_handle(file.into_raw_handle())) }
|
|
|
|
}
|
|
|
|
|
2023-09-23 21:57:00 +08:00
|
|
|
pub(crate) fn pipe() -> io::Result<(NamedPipe, NamedPipe)> {
|
2023-09-23 16:09:44 +08:00
|
|
|
let (pipe, name) = server()?;
|
|
|
|
Ok((pipe, client(&name)?))
|
|
|
|
}
|
2023-09-18 21:40:56 +08:00
|
|
|
|
|
|
|
/// A virtual TUN (IP) interface.
|
|
|
|
pub struct WinTunInterface {
|
2023-09-24 17:56:49 +08:00
|
|
|
wintun_session: Arc<wintun::Session>,
|
2023-09-18 21:40:56 +08:00
|
|
|
mtu: usize,
|
|
|
|
medium: Medium,
|
2023-09-23 21:43:40 +08:00
|
|
|
pipe_server: Rc<RefCell<NamedPipe>>,
|
2023-09-24 13:02:00 +08:00
|
|
|
pipe_client: Arc<Mutex<NamedPipe>>,
|
2023-09-24 17:56:49 +08:00
|
|
|
wintun_reader_thread: Option<JoinHandle<()>>,
|
2023-09-18 21:40:56 +08:00
|
|
|
}
|
|
|
|
|
2023-09-19 12:55:02 +08:00
|
|
|
impl event::Source for WinTunInterface {
|
2023-09-23 16:09:44 +08:00
|
|
|
fn register(&mut self, registry: &Registry, token: Token, interests: Interest) -> io::Result<()> {
|
2023-09-23 21:43:40 +08:00
|
|
|
self.pipe_server.borrow_mut().register(registry, token, interests)?;
|
2023-09-23 16:09:44 +08:00
|
|
|
Ok(())
|
2023-09-19 12:55:02 +08:00
|
|
|
}
|
|
|
|
|
2023-09-23 16:09:44 +08:00
|
|
|
fn reregister(&mut self, registry: &Registry, token: Token, interests: Interest) -> io::Result<()> {
|
2023-09-23 21:43:40 +08:00
|
|
|
self.pipe_server.borrow_mut().reregister(registry, token, interests)?;
|
2023-09-23 16:09:44 +08:00
|
|
|
Ok(())
|
2023-09-19 12:55:02 +08:00
|
|
|
}
|
|
|
|
|
2023-09-23 16:09:44 +08:00
|
|
|
fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
|
2023-09-23 21:43:40 +08:00
|
|
|
self.pipe_server.borrow_mut().deregister(registry)?;
|
2023-09-23 16:09:44 +08:00
|
|
|
Ok(())
|
2023-09-19 12:55:02 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-18 21:40:56 +08:00
|
|
|
impl WinTunInterface {
|
|
|
|
pub fn new(name: &str, medium: Medium) -> io::Result<WinTunInterface> {
|
|
|
|
let wintun = unsafe { wintun::load() }.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
|
|
|
let tun_name = name;
|
|
|
|
let adapter = match wintun::Adapter::open(&wintun, tun_name) {
|
|
|
|
Ok(a) => a,
|
|
|
|
Err(_) => wintun::Adapter::create(&wintun, tun_name, tun_name, None)
|
|
|
|
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?,
|
|
|
|
};
|
|
|
|
|
|
|
|
let address = Ipv4Addr::new(10, 1, 0, 33);
|
|
|
|
let mask = Ipv4Addr::new(255, 255, 255, 0);
|
|
|
|
let gateway = Some(IpAddr::V4(Ipv4Addr::new(10, 1, 0, 1)));
|
|
|
|
adapter
|
|
|
|
.set_network_addresses_tuple(IpAddr::V4(address), IpAddr::V4(mask), gateway)
|
|
|
|
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
|
|
|
|
|
|
|
let session = adapter
|
|
|
|
.start_session(wintun::MAX_RING_CAPACITY)
|
|
|
|
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
2023-09-24 17:56:49 +08:00
|
|
|
let wintun_session = Arc::new(session);
|
2023-09-18 21:40:56 +08:00
|
|
|
|
2023-09-23 16:09:44 +08:00
|
|
|
let (pipe_server, pipe_client) = pipe()?;
|
|
|
|
|
2023-09-24 13:02:00 +08:00
|
|
|
let pipe_client = Arc::new(Mutex::new(pipe_client));
|
|
|
|
|
2023-09-24 17:56:49 +08:00
|
|
|
let mtu = adapter.get_mtu().map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
|
|
|
|
|
|
|
let reader_session = wintun_session.clone();
|
|
|
|
let pipe_client_clone = pipe_client.clone();
|
|
|
|
let reader_thread = std::thread::spawn(move || {
|
|
|
|
let block = || -> Result<(), Box<dyn std::error::Error>> {
|
|
|
|
loop {
|
|
|
|
let packet = reader_session.receive_blocking()?;
|
|
|
|
let bytes = packet.bytes();
|
|
|
|
|
|
|
|
let result = { pipe_client_clone.lock().unwrap().write(bytes) };
|
|
|
|
match result {
|
|
|
|
Ok(_) => {}
|
|
|
|
Err(err) if err.kind() == io::ErrorKind::WouldBlock => {
|
|
|
|
log::trace!("reader_thread phy: tx failed due to WouldBlock")
|
|
|
|
}
|
|
|
|
Err(err) => log::error!("{}", err),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
if let Err(err) = block() {
|
|
|
|
log::trace!("Reader {}", err);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2023-09-23 16:09:44 +08:00
|
|
|
Ok(WinTunInterface {
|
2023-09-24 17:56:49 +08:00
|
|
|
wintun_session,
|
2023-09-23 16:09:44 +08:00
|
|
|
mtu,
|
|
|
|
medium,
|
2023-09-23 21:43:40 +08:00
|
|
|
pipe_server: Rc::new(RefCell::new(pipe_server)),
|
2023-09-24 13:02:00 +08:00
|
|
|
pipe_client,
|
2023-09-24 17:56:49 +08:00
|
|
|
wintun_reader_thread: Some(reader_thread),
|
2023-09-23 16:09:44 +08:00
|
|
|
})
|
2023-09-18 21:40:56 +08:00
|
|
|
}
|
2023-09-24 00:30:25 +08:00
|
|
|
|
2023-09-24 13:02:00 +08:00
|
|
|
pub fn pipe_client(&self) -> Arc<Mutex<NamedPipe>> {
|
2023-09-24 00:30:25 +08:00
|
|
|
self.pipe_client.clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn pipe_client_event(&self) -> Result<(), io::Error> {
|
|
|
|
let mut buffer = vec![0; self.mtu];
|
2023-09-24 13:02:00 +08:00
|
|
|
match self
|
|
|
|
.pipe_client
|
|
|
|
.lock()
|
|
|
|
.map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string()))?
|
|
|
|
.read(&mut buffer)
|
|
|
|
{
|
2023-09-24 00:30:25 +08:00
|
|
|
Ok(len) => {
|
2023-09-24 17:56:49 +08:00
|
|
|
let write_pack = self.wintun_session.allocate_send_packet(len as u16);
|
2023-09-24 00:30:25 +08:00
|
|
|
if let Ok(mut write_pack) = write_pack {
|
|
|
|
write_pack.bytes_mut().copy_from_slice(&buffer[..len]);
|
2023-09-24 17:56:49 +08:00
|
|
|
self.wintun_session.send_packet(write_pack);
|
2023-09-24 00:30:25 +08:00
|
|
|
} else if let Err(err) = write_pack {
|
|
|
|
log::error!("phy: failed to allocate send packet: {}", err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(err) if err.kind() == io::ErrorKind::WouldBlock => {}
|
2023-09-24 13:02:00 +08:00
|
|
|
Err(err) => return Err(err),
|
2023-09-24 00:30:25 +08:00
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
2023-09-18 21:40:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for WinTunInterface {
|
|
|
|
fn drop(&mut self) {
|
2023-09-24 17:56:49 +08:00
|
|
|
if let Err(e) = self.wintun_session.shutdown() {
|
2023-09-18 21:40:56 +08:00
|
|
|
log::error!("phy: failed to shutdown interface: {}", e);
|
|
|
|
}
|
2023-09-24 17:56:49 +08:00
|
|
|
if let Some(thread) = self.wintun_reader_thread.take() {
|
|
|
|
if let Err(e) = thread.join() {
|
|
|
|
log::error!("phy: failed to join reader thread: {:?}", e);
|
|
|
|
}
|
|
|
|
}
|
2023-09-18 21:40:56 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Device for WinTunInterface {
|
|
|
|
type RxToken<'a> = RxToken;
|
|
|
|
type TxToken<'a> = TxToken;
|
|
|
|
|
|
|
|
fn capabilities(&self) -> DeviceCapabilities {
|
|
|
|
let mut v = DeviceCapabilities::default();
|
|
|
|
v.max_transmission_unit = self.mtu;
|
|
|
|
v.medium = self.medium;
|
|
|
|
v
|
|
|
|
}
|
|
|
|
|
|
|
|
fn receive(&mut self, _timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
|
2023-09-23 21:43:40 +08:00
|
|
|
let mut buffer = vec![0; self.mtu];
|
|
|
|
match self.pipe_server.borrow_mut().read(&mut buffer[..]) {
|
|
|
|
Ok(size) => {
|
|
|
|
buffer.resize(size, 0);
|
|
|
|
let rx = RxToken { buffer };
|
|
|
|
let tx = TxToken {
|
|
|
|
pipe_server: self.pipe_server.clone(),
|
|
|
|
};
|
|
|
|
Some((rx, tx))
|
|
|
|
}
|
|
|
|
Err(err) if err.kind() == io::ErrorKind::WouldBlock => None,
|
|
|
|
Err(err) => panic!("{}", err),
|
|
|
|
}
|
2023-09-18 21:40:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
fn transmit(&mut self, _timestamp: Instant) -> Option<Self::TxToken<'_>> {
|
|
|
|
Some(TxToken {
|
2023-09-23 21:43:40 +08:00
|
|
|
pipe_server: self.pipe_server.clone(),
|
2023-09-18 21:40:56 +08:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub struct RxToken {
|
|
|
|
buffer: Vec<u8>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl phy::RxToken for RxToken {
|
|
|
|
fn consume<R, F>(mut self, f: F) -> R
|
|
|
|
where
|
|
|
|
F: FnOnce(&mut [u8]) -> R,
|
|
|
|
{
|
|
|
|
f(&mut self.buffer[..])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub struct TxToken {
|
2023-09-23 21:43:40 +08:00
|
|
|
pipe_server: Rc<RefCell<NamedPipe>>,
|
2023-09-18 21:40:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl phy::TxToken for TxToken {
|
|
|
|
fn consume<R, F>(self, len: usize, f: F) -> R
|
|
|
|
where
|
|
|
|
F: FnOnce(&mut [u8]) -> R,
|
|
|
|
{
|
|
|
|
let mut buffer = vec![0; len];
|
|
|
|
let result = f(&mut buffer);
|
|
|
|
|
2023-09-23 21:43:40 +08:00
|
|
|
match self.pipe_server.borrow_mut().write(&buffer[..]) {
|
|
|
|
Ok(_) => {}
|
|
|
|
Err(err) if err.kind() == io::ErrorKind::WouldBlock => {
|
2023-09-24 13:02:00 +08:00
|
|
|
log::trace!("phy: tx failed due to WouldBlock")
|
2023-09-23 21:43:40 +08:00
|
|
|
}
|
2023-09-24 13:02:00 +08:00
|
|
|
Err(err) => log::error!("{}", err),
|
2023-09-23 21:43:40 +08:00
|
|
|
}
|
2023-09-18 21:40:56 +08:00
|
|
|
result
|
|
|
|
}
|
|
|
|
}
|
2023-09-24 00:30:25 +08:00
|
|
|
|
2023-09-24 13:02:00 +08:00
|
|
|
pub struct NamedPipeSource(pub Arc<Mutex<NamedPipe>>);
|
2023-09-24 00:30:25 +08:00
|
|
|
|
|
|
|
impl event::Source for NamedPipeSource {
|
|
|
|
fn register(&mut self, registry: &Registry, token: Token, interests: Interest) -> io::Result<()> {
|
2023-09-24 13:02:00 +08:00
|
|
|
self.0
|
|
|
|
.lock()
|
|
|
|
.map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string()))?
|
|
|
|
.register(registry, token, interests)
|
2023-09-24 00:30:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
fn reregister(&mut self, registry: &Registry, token: Token, interests: Interest) -> io::Result<()> {
|
2023-09-24 13:02:00 +08:00
|
|
|
self.0
|
|
|
|
.lock()
|
|
|
|
.map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string()))?
|
|
|
|
.reregister(registry, token, interests)
|
2023-09-24 00:30:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
|
2023-09-24 13:02:00 +08:00
|
|
|
self.0
|
|
|
|
.lock()
|
|
|
|
.map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string()))?
|
|
|
|
.deregister(registry)
|
2023-09-24 00:30:25 +08:00
|
|
|
}
|
|
|
|
}
|