diff options
Diffstat (limited to '')
-rw-r--r-- | src/platform/bind.rs | 43 | ||||
-rw-r--r-- | src/platform/dummy.rs | 22 | ||||
-rw-r--r-- | src/platform/dummy/bind.rs (renamed from src/wireguard/types/dummy.rs) | 170 | ||||
-rw-r--r-- | src/platform/dummy/endpoint.rs | 1 | ||||
-rw-r--r-- | src/platform/dummy/mod.rs | 13 | ||||
-rw-r--r-- | src/platform/dummy/tun.rs | 172 | ||||
-rw-r--r-- | src/platform/endpoint.rs (renamed from src/wireguard/types/endpoint.rs) | 0 | ||||
-rw-r--r-- | src/platform/linux/tun.rs | 6 | ||||
-rw-r--r-- | src/platform/linux/udp.rs | 3 | ||||
-rw-r--r-- | src/platform/mod.rs | 32 | ||||
-rw-r--r-- | src/platform/tun.rs (renamed from src/wireguard/types/tun.rs) | 5 |
11 files changed, 265 insertions, 202 deletions
diff --git a/src/platform/bind.rs b/src/platform/bind.rs new file mode 100644 index 0000000..f22a5d7 --- /dev/null +++ b/src/platform/bind.rs @@ -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>; +} diff --git a/src/platform/dummy.rs b/src/platform/dummy.rs deleted file mode 100644 index 208febe..0000000 --- a/src/platform/dummy.rs +++ /dev/null @@ -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) - } -} diff --git a/src/wireguard/types/dummy.rs b/src/platform/dummy/bind.rs index 384f123..14143ae 100644 --- a/src/wireguard/types/dummy.rs +++ b/src/platform/dummy/bind.rs @@ -2,19 +2,14 @@ use std::error::Error; use std::fmt; use std::marker; use std::net::SocketAddr; -use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::mpsc::{sync_channel, Receiver, SyncSender}; use std::sync::Arc; use std::sync::Mutex; -use std::time::Instant; -use super::*; +use super::super::bind::*; +use super::super::Endpoint; -/* This submodule provides pure/dummy implementations of the IO interfaces - * for use in unit tests thoughout the project. - */ - -/* Error implementation */ +pub struct VoidOwner {} #[derive(Debug)] pub enum BindError { @@ -85,122 +80,10 @@ impl UnitEndpoint { } } -/* */ - -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 tun::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 tun::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 tun::MTU for TunMTU { - fn mtu(&self) -> usize { - self.mtu.load(Ordering::Acquire) - } -} - -impl tun::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) - } -} - -/* Void Bind */ - #[derive(Clone, Copy)] pub struct VoidBind {} -impl bind::Reader<UnitEndpoint> for VoidBind { +impl Reader<UnitEndpoint> for VoidBind { type Error = BindError; fn read(&self, _buf: &mut [u8]) -> Result<(usize, UnitEndpoint), Self::Error> { @@ -208,7 +91,7 @@ impl bind::Reader<UnitEndpoint> for VoidBind { } } -impl bind::Writer<UnitEndpoint> for VoidBind { +impl Writer<UnitEndpoint> for VoidBind { type Error = BindError; fn write(&self, _buf: &[u8], _dst: &UnitEndpoint) -> Result<(), Self::Error> { @@ -216,7 +99,7 @@ impl bind::Writer<UnitEndpoint> for VoidBind { } } -impl bind::Bind for VoidBind { +impl Bind for VoidBind { type Error = BindError; type Endpoint = UnitEndpoint; @@ -238,7 +121,7 @@ pub struct PairReader<E> { _marker: marker::PhantomData<E>, } -impl bind::Reader<UnitEndpoint> for PairReader<UnitEndpoint> { +impl Reader<UnitEndpoint> for PairReader<UnitEndpoint> { type Error = BindError; fn read(&self, buf: &mut [u8]) -> Result<(usize, UnitEndpoint), Self::Error> { let vec = self @@ -253,7 +136,7 @@ impl bind::Reader<UnitEndpoint> for PairReader<UnitEndpoint> { } } -impl bind::Writer<UnitEndpoint> for PairWriter<UnitEndpoint> { +impl Writer<UnitEndpoint> for PairWriter<UnitEndpoint> { type Error = BindError; fn write(&self, buf: &[u8], _dst: &UnitEndpoint) -> Result<(), Self::Error> { let owned = buf.to_owned(); @@ -305,35 +188,24 @@ impl PairBind { } } -impl bind::Bind for PairBind { +impl Bind for PairBind { type Error = BindError; type Endpoint = UnitEndpoint; type Reader = PairReader<Self::Endpoint>; type Writer = PairWriter<Self::Endpoint>; } -pub fn 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, - } +impl Owner for VoidOwner { + type Error = BindError; + + fn set_fwmark(&self, _value: Option<u32>) -> Option<Self::Error> { + None + } +} + +impl Platform for PairBind { + type Owner = VoidOwner; + fn bind(_port: u16) -> Result<(Vec<Self::Reader>, Self::Writer, Self::Owner), Self::Error> { + Err(BindError::Disconnected) } } diff --git a/src/platform/dummy/endpoint.rs b/src/platform/dummy/endpoint.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/platform/dummy/endpoint.rs @@ -0,0 +1 @@ + diff --git a/src/platform/dummy/mod.rs b/src/platform/dummy/mod.rs new file mode 100644 index 0000000..884bd7e --- /dev/null +++ b/src/platform/dummy/mod.rs @@ -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::*; diff --git a/src/platform/dummy/tun.rs b/src/platform/dummy/tun.rs new file mode 100644 index 0000000..9fe9480 --- /dev/null +++ b/src/platform/dummy/tun.rs @@ -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) + } +} diff --git a/src/wireguard/types/endpoint.rs b/src/platform/endpoint.rs index 4702aab..4702aab 100644 --- a/src/wireguard/types/endpoint.rs +++ b/src/platform/endpoint.rs diff --git a/src/platform/linux/tun.rs b/src/platform/linux/tun.rs index 5b7b105..090569a 100644 --- a/src/platform/linux/tun.rs +++ b/src/platform/linux/tun.rs @@ -1,6 +1,4 @@ -use super::super::super::wireguard::tun::*; -use super::super::PlatformTun; -use super::super::Tun; +use super::super::tun::*; use libc::*; @@ -127,7 +125,7 @@ impl Tun for LinuxTun { type MTU = LinuxTunMTU; } -impl PlatformTun for LinuxTun { +impl Platform for LinuxTun { fn create(name: &str) -> Result<(Vec<Self::Reader>, Self::Writer, Self::MTU), Self::Error> { // construct request struct let mut req = Ifreq { diff --git a/src/platform/linux/udp.rs b/src/platform/linux/udp.rs index 0a1a186..52e4c45 100644 --- a/src/platform/linux/udp.rs +++ b/src/platform/linux/udp.rs @@ -1,6 +1,5 @@ -use super::super::Bind; +use super::super::bind::*; use super::super::Endpoint; -use super::super::PlatformBind; use std::net::SocketAddr; diff --git a/src/platform/mod.rs b/src/platform/mod.rs index a0bbc13..ecd559a 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -1,33 +1,15 @@ -use std::error::Error; +mod endpoint; -use super::wireguard::bind::Bind; -use super::wireguard::tun::Tun; -use super::wireguard::Endpoint; +pub mod bind; +pub mod tun; -#[cfg(test)] -mod dummy; +pub use endpoint::Endpoint; #[cfg(target_os = "linux")] mod linux; +#[cfg(test)] +pub mod dummy; + #[cfg(target_os = "linux")] pub use linux::LinuxTun as TunInstance; - -pub trait BindOwner: Send { - type Error: Error; - - fn set_fwmark(&self, value: Option<u32>) -> Option<Self::Error>; -} - -pub trait PlatformBind: Bind { - type Owner: BindOwner; - - /// 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>; -} - -pub trait PlatformTun: Tun { - fn create(name: &str) -> Result<(Vec<Self::Reader>, Self::Writer, Self::MTU), Self::Error>; -} diff --git a/src/wireguard/types/tun.rs b/src/platform/tun.rs index 2ba16ff..f49d4af 100644 --- a/src/wireguard/types/tun.rs +++ b/src/platform/tun.rs @@ -54,3 +54,8 @@ pub trait Tun: Send + Sync + 'static { type MTU: MTU; type Error: Error; } + +/// On some platforms the application can create the TUN device itself. +pub trait Platform: Tun { + fn create(name: &str) -> Result<(Vec<Self::Reader>, Self::Writer, Self::MTU), Self::Error>; +} |