mirror of https://git.zx2c4.com/wireguard-rs
26 changed files with 352 additions and 270 deletions
@ -1,5 +1,7 @@
|
||||
mod config; |
||||
|
||||
use super::platform::{BindOwner, PlatformBind}; |
||||
use super::wireguard::tun::Tun; |
||||
use super::platform::{bind, tun}; |
||||
use super::wireguard::Wireguard; |
||||
|
||||
pub use config::Configuration; |
||||
pub use config::WireguardConfig; |
||||
|
||||
@ -0,0 +1,43 @@
|
||||
use super::Endpoint; |
||||
use std::error::Error; |
||||
|
||||
pub trait Reader<E: Endpoint>: Send + Sync { |
||||
type Error: Error; |
||||
|
||||
fn read(&self, buf: &mut [u8]) -> Result<(usize, E), Self::Error>; |
||||
} |
||||
|
||||
pub trait Writer<E: Endpoint>: Send + Sync + Clone + 'static { |
||||
type Error: Error; |
||||
|
||||
fn write(&self, buf: &[u8], dst: &E) -> Result<(), Self::Error>; |
||||
} |
||||
|
||||
pub trait Bind: Send + Sync + 'static { |
||||
type Error: Error; |
||||
type Endpoint: Endpoint; |
||||
|
||||
/* Until Rust gets type equality constraints these have to be generic */ |
||||
type Writer: Writer<Self::Endpoint>; |
||||
type Reader: Reader<Self::Endpoint>; |
||||
} |
||||
|
||||
/// On platforms where fwmark can be set and the
|
||||
/// implementation can bind to a new port during later configuration (UAPI support),
|
||||
/// this type provides the ability to set the fwmark and close the socket (by dropping the instance)
|
||||
pub trait Owner: Send { |
||||
type Error: Error; |
||||
|
||||
fn set_fwmark(&self, value: Option<u32>) -> Option<Self::Error>; |
||||
} |
||||
|
||||
/// On some platforms the application can itself bind to a socket.
|
||||
/// This enables configuration using the UAPI interface.
|
||||
pub trait Platform: Bind { |
||||
type Owner: Owner; |
||||
|
||||
/// Bind to a new port, returning the reader/writer and
|
||||
/// an associated instance of the owner type, which closes the UDP socket upon "drop"
|
||||
/// and enables configuration of the fwmark value.
|
||||
fn bind(port: u16) -> Result<(Vec<Self::Reader>, Self::Writer, Self::Owner), Self::Error>; |
||||
} |
||||
@ -1,22 +0,0 @@
|
||||
#[cfg(test)] |
||||
use super::super::wireguard::dummy; |
||||
use super::BindOwner; |
||||
use super::PlatformBind; |
||||
|
||||
pub struct VoidOwner {} |
||||
|
||||
impl BindOwner for VoidOwner { |
||||
type Error = dummy::BindError; |
||||
|
||||
fn set_fwmark(&self, value: Option<u32>) -> Option<Self::Error> { |
||||
None |
||||
} |
||||
} |
||||
|
||||
impl PlatformBind for dummy::PairBind { |
||||
type Owner = VoidOwner; |
||||
|
||||
fn bind(_port: u16) -> Result<(Vec<Self::Reader>, Self::Writer, Self::Owner), Self::Error> { |
||||
Err(dummy::BindError::Disconnected) |
||||
} |
||||
} |
||||
@ -0,0 +1,13 @@
|
||||
mod bind; |
||||
mod endpoint; |
||||
mod tun; |
||||
|
||||
/* A pure dummy platform available during "test-time"
|
||||
* |
||||
* The use of the dummy platform is to enable unit testing of full WireGuard, |
||||
* the configuration interface and the UAPI parser. |
||||
*/ |
||||
|
||||
pub use bind::*; |
||||
pub use endpoint::*; |
||||
pub use tun::*; |
||||
@ -0,0 +1,172 @@
|
||||
use std::error::Error; |
||||
use std::fmt; |
||||
use std::sync::atomic::{AtomicUsize, Ordering}; |
||||
use std::sync::mpsc::{sync_channel, Receiver, SyncSender}; |
||||
use std::sync::Arc; |
||||
use std::sync::Mutex; |
||||
|
||||
use super::super::tun::*; |
||||
|
||||
/* This submodule provides pure/dummy implementations of the IO interfaces
|
||||
* for use in unit tests thoughout the project. |
||||
*/ |
||||
|
||||
/* Error implementation */ |
||||
|
||||
#[derive(Debug)] |
||||
pub enum BindError { |
||||
Disconnected, |
||||
} |
||||
|
||||
impl Error for BindError { |
||||
fn description(&self) -> &str { |
||||
"Generic Bind Error" |
||||
} |
||||
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> { |
||||
None |
||||
} |
||||
} |
||||
|
||||
impl fmt::Display for BindError { |
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
||||
match self { |
||||
BindError::Disconnected => write!(f, "PairBind disconnected"), |
||||
} |
||||
} |
||||
} |
||||
|
||||
#[derive(Debug)] |
||||
pub enum TunError { |
||||
Disconnected, |
||||
} |
||||
|
||||
impl Error for TunError { |
||||
fn description(&self) -> &str { |
||||
"Generic Tun Error" |
||||
} |
||||
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> { |
||||
None |
||||
} |
||||
} |
||||
|
||||
impl fmt::Display for TunError { |
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
||||
write!(f, "Not Possible") |
||||
} |
||||
} |
||||
|
||||
pub struct TunTest {} |
||||
|
||||
pub struct TunFakeIO { |
||||
store: bool, |
||||
tx: SyncSender<Vec<u8>>, |
||||
rx: Receiver<Vec<u8>>, |
||||
} |
||||
|
||||
pub struct TunReader { |
||||
rx: Receiver<Vec<u8>>, |
||||
} |
||||
|
||||
pub struct TunWriter { |
||||
store: bool, |
||||
tx: Mutex<SyncSender<Vec<u8>>>, |
||||
} |
||||
|
||||
#[derive(Clone)] |
||||
pub struct TunMTU { |
||||
mtu: Arc<AtomicUsize>, |
||||
} |
||||
|
||||
impl Reader for TunReader { |
||||
type Error = TunError; |
||||
|
||||
fn read(&self, buf: &mut [u8], offset: usize) -> Result<usize, Self::Error> { |
||||
match self.rx.recv() { |
||||
Ok(m) => { |
||||
buf[offset..].copy_from_slice(&m[..]); |
||||
Ok(m.len()) |
||||
} |
||||
Err(_) => Err(TunError::Disconnected), |
||||
} |
||||
} |
||||
} |
||||
|
||||
impl Writer for TunWriter { |
||||
type Error = TunError; |
||||
|
||||
fn write(&self, src: &[u8]) -> Result<(), Self::Error> { |
||||
if self.store { |
||||
let m = src.to_owned(); |
||||
match self.tx.lock().unwrap().send(m) { |
||||
Ok(_) => Ok(()), |
||||
Err(_) => Err(TunError::Disconnected), |
||||
} |
||||
} else { |
||||
Ok(()) |
||||
} |
||||
} |
||||
} |
||||
|
||||
impl MTU for TunMTU { |
||||
fn mtu(&self) -> usize { |
||||
self.mtu.load(Ordering::Acquire) |
||||
} |
||||
} |
||||
|
||||
impl Tun for TunTest { |
||||
type Writer = TunWriter; |
||||
type Reader = TunReader; |
||||
type MTU = TunMTU; |
||||
type Error = TunError; |
||||
} |
||||
|
||||
impl TunFakeIO { |
||||
pub fn write(&self, msg: Vec<u8>) { |
||||
if self.store { |
||||
self.tx.send(msg).unwrap(); |
||||
} |
||||
} |
||||
|
||||
pub fn read(&self) -> Vec<u8> { |
||||
self.rx.recv().unwrap() |
||||
} |
||||
} |
||||
|
||||
impl TunTest { |
||||
pub fn create(mtu: usize, store: bool) -> (TunFakeIO, TunReader, TunWriter, TunMTU) { |
||||
let (tx1, rx1) = if store { |
||||
sync_channel(32) |
||||
} else { |
||||
sync_channel(1) |
||||
}; |
||||
let (tx2, rx2) = if store { |
||||
sync_channel(32) |
||||
} else { |
||||
sync_channel(1) |
||||
}; |
||||
|
||||
let fake = TunFakeIO { |
||||
tx: tx1, |
||||
rx: rx2, |
||||
store, |
||||
}; |
||||
let reader = TunReader { rx: rx1 }; |
||||
let writer = TunWriter { |
||||
tx: Mutex::new(tx2), |
||||
store, |
||||
}; |
||||
let mtu = TunMTU { |
||||
mtu: Arc::new(AtomicUsize::new(mtu)), |
||||
}; |
||||
|
||||
(fake, reader, writer, mtu) |
||||
} |
||||
} |
||||
|
||||
impl Platform for TunTest { |
||||
fn create(_name: &str) -> Result<(Vec<Self::Reader>, Self::Writer, Self::MTU), Self::Error> { |
||||
Err(TunError::Disconnected) |
||||
} |
||||
} |
||||
@ -1,6 +1,33 @@
|
||||
use clear_on_drop::clear::Clear; |
||||
use std::time::Instant; |
||||
|
||||
#[cfg(test)] |
||||
pub fn dummy_keypair(initiator: bool) -> KeyPair { |
||||
let k1 = Key { |
||||
key: [0x53u8; 32], |
||||
id: 0x646e6573, |
||||
}; |
||||
let k2 = Key { |
||||
key: [0x52u8; 32], |
||||
id: 0x76636572, |
||||
}; |
||||
if initiator { |
||||
KeyPair { |
||||
birth: Instant::now(), |
||||
initiator: true, |
||||
send: k1, |
||||
recv: k2, |
||||
} |
||||
} else { |
||||
KeyPair { |
||||
birth: Instant::now(), |
||||
initiator: false, |
||||
send: k2, |
||||
recv: k1, |
||||
} |
||||
} |
||||
} |
||||
|
||||
#[derive(Debug, Clone)] |
||||
pub struct Key { |
||||
pub key: [u8; 32], |
||||
@ -1,23 +0,0 @@
|
||||
use super::Endpoint; |
||||
use std::error::Error; |
||||
|
||||
pub trait Reader<E: Endpoint>: Send + Sync { |
||||
type Error: Error; |
||||
|
||||
fn read(&self, buf: &mut [u8]) -> Result<(usize, E), Self::Error>; |
||||
} |
||||
|
||||
pub trait Writer<E: Endpoint>: Send + Sync + Clone + 'static { |
||||
type Error: Error; |
||||
|
||||
fn write(&self, buf: &[u8], dst: &E) -> Result<(), Self::Error>; |
||||
} |
||||
|
||||
pub trait Bind: Send + Sync + 'static { |
||||
type Error: Error; |
||||
type Endpoint: Endpoint; |
||||
|
||||
/* Until Rust gets type equality constraints these have to be generic */ |
||||
type Writer: Writer<Self::Endpoint>; |
||||
type Reader: Reader<Self::Endpoint>; |
||||
} |
||||
@ -1,11 +0,0 @@
|
||||
mod endpoint; |
||||
mod keys; |
||||
|
||||
pub mod bind; |
||||
pub mod tun; |
||||
|
||||
#[cfg(test)] |
||||
pub mod dummy; |
||||
|
||||
pub use endpoint::Endpoint; |
||||
pub use keys::{Key, KeyPair}; |
||||
Loading…
Reference in new issue