Moved IO traits into platform module
This commit is contained in:
@@ -2,10 +2,8 @@ use spin::Mutex;
|
|||||||
use std::net::{IpAddr, SocketAddr};
|
use std::net::{IpAddr, SocketAddr};
|
||||||
use x25519_dalek::{PublicKey, StaticSecret};
|
use x25519_dalek::{PublicKey, StaticSecret};
|
||||||
|
|
||||||
use super::BindOwner;
|
use super::*;
|
||||||
use super::PlatformBind;
|
use bind::Owner;
|
||||||
use super::Tun;
|
|
||||||
use super::Wireguard;
|
|
||||||
|
|
||||||
/// The goal of the configuration interface is, among others,
|
/// The goal of the configuration interface is, among others,
|
||||||
/// to hide the IO implementations (over which the WG device is generic),
|
/// to hide the IO implementations (over which the WG device is generic),
|
||||||
@@ -21,17 +19,26 @@ pub struct PeerState {
|
|||||||
allowed_ips: Vec<(IpAddr, u32)>,
|
allowed_ips: Vec<(IpAddr, u32)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UDPState<O: BindOwner> {
|
struct UDPState<O: bind::Owner> {
|
||||||
fwmark: Option<u32>,
|
fwmark: Option<u32>,
|
||||||
owner: O,
|
owner: O,
|
||||||
port: u16,
|
port: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WireguardConfig<T: Tun, B: PlatformBind> {
|
pub struct WireguardConfig<T: tun::Tun, B: bind::Platform> {
|
||||||
wireguard: Wireguard<T, B>,
|
wireguard: Wireguard<T, B>,
|
||||||
network: Mutex<Option<UDPState<B::Owner>>>,
|
network: Mutex<Option<UDPState<B::Owner>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: tun::Tun, B: bind::Platform> WireguardConfig<T, B> {
|
||||||
|
fn new(wg: Wireguard<T, B>) -> WireguardConfig<T, B> {
|
||||||
|
WireguardConfig {
|
||||||
|
wireguard: wg,
|
||||||
|
network: Mutex::new(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub enum ConfigError {
|
pub enum ConfigError {
|
||||||
NoSuchPeer,
|
NoSuchPeer,
|
||||||
NotListening,
|
NotListening,
|
||||||
@@ -41,8 +48,8 @@ impl ConfigError {
|
|||||||
fn errno(&self) -> i32 {
|
fn errno(&self) -> i32 {
|
||||||
// TODO: obtain the correct error values
|
// TODO: obtain the correct error values
|
||||||
match self {
|
match self {
|
||||||
NoSuchPeer => 1,
|
ConfigError::NoSuchPeer => 1,
|
||||||
NotListening => 2,
|
ConfigError::NotListening => 2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,7 +187,7 @@ pub trait Configuration {
|
|||||||
fn get_peers(&self) -> Vec<PeerState>;
|
fn get_peers(&self) -> Vec<PeerState>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Tun, B: PlatformBind> Configuration for WireguardConfig<T, B> {
|
impl<T: tun::Tun, B: bind::Platform> Configuration for WireguardConfig<T, B> {
|
||||||
fn set_private_key(&self, sk: Option<StaticSecret>) {
|
fn set_private_key(&self, sk: Option<StaticSecret>) {
|
||||||
self.wireguard.set_key(sk)
|
self.wireguard.set_key(sk)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
mod config;
|
mod config;
|
||||||
|
|
||||||
use super::platform::{BindOwner, PlatformBind};
|
use super::platform::{bind, tun};
|
||||||
use super::wireguard::tun::Tun;
|
|
||||||
use super::wireguard::Wireguard;
|
use super::wireguard::Wireguard;
|
||||||
|
|
||||||
|
pub use config::Configuration;
|
||||||
|
pub use config::WireguardConfig;
|
||||||
|
|||||||
19
src/main.rs
19
src/main.rs
@@ -10,8 +10,23 @@ mod configuration;
|
|||||||
mod platform;
|
mod platform;
|
||||||
mod wireguard;
|
mod wireguard;
|
||||||
|
|
||||||
use platform::PlatformTun;
|
mod tests;
|
||||||
|
|
||||||
|
use platform::tun;
|
||||||
|
|
||||||
|
use configuration::WireguardConfig;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let (readers, writer, mtu) = platform::TunInstance::create("test").unwrap();
|
/*
|
||||||
|
let (mut readers, writer, mtu) = platform::TunInstance::create("test").unwrap();
|
||||||
|
let wg = wireguard::Wireguard::new(readers, writer, mtu);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
fn test_wg_configuration() {
|
||||||
|
let (mut readers, writer, mtu) = platform::dummy::
|
||||||
|
|
||||||
|
let wg = wireguard::Wireguard::new(readers, writer, mtu);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|||||||
43
src/platform/bind.rs
Normal file
43
src/platform/bind.rs
Normal file
@@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,19 +2,14 @@ use std::error::Error;
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::marker;
|
use std::marker;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
|
||||||
use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
|
use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::Mutex;
|
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
|
pub struct VoidOwner {}
|
||||||
* for use in unit tests thoughout the project.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Error implementation */
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum BindError {
|
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)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct VoidBind {}
|
pub struct VoidBind {}
|
||||||
|
|
||||||
impl bind::Reader<UnitEndpoint> for VoidBind {
|
impl Reader<UnitEndpoint> for VoidBind {
|
||||||
type Error = BindError;
|
type Error = BindError;
|
||||||
|
|
||||||
fn read(&self, _buf: &mut [u8]) -> Result<(usize, UnitEndpoint), Self::Error> {
|
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;
|
type Error = BindError;
|
||||||
|
|
||||||
fn write(&self, _buf: &[u8], _dst: &UnitEndpoint) -> Result<(), Self::Error> {
|
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 Error = BindError;
|
||||||
type Endpoint = UnitEndpoint;
|
type Endpoint = UnitEndpoint;
|
||||||
|
|
||||||
@@ -238,7 +121,7 @@ pub struct PairReader<E> {
|
|||||||
_marker: marker::PhantomData<E>,
|
_marker: marker::PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl bind::Reader<UnitEndpoint> for PairReader<UnitEndpoint> {
|
impl Reader<UnitEndpoint> for PairReader<UnitEndpoint> {
|
||||||
type Error = BindError;
|
type Error = BindError;
|
||||||
fn read(&self, buf: &mut [u8]) -> Result<(usize, UnitEndpoint), Self::Error> {
|
fn read(&self, buf: &mut [u8]) -> Result<(usize, UnitEndpoint), Self::Error> {
|
||||||
let vec = self
|
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;
|
type Error = BindError;
|
||||||
fn write(&self, buf: &[u8], _dst: &UnitEndpoint) -> Result<(), Self::Error> {
|
fn write(&self, buf: &[u8], _dst: &UnitEndpoint) -> Result<(), Self::Error> {
|
||||||
let owned = buf.to_owned();
|
let owned = buf.to_owned();
|
||||||
@@ -305,35 +188,24 @@ impl PairBind {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl bind::Bind for PairBind {
|
impl Bind for PairBind {
|
||||||
type Error = BindError;
|
type Error = BindError;
|
||||||
type Endpoint = UnitEndpoint;
|
type Endpoint = UnitEndpoint;
|
||||||
type Reader = PairReader<Self::Endpoint>;
|
type Reader = PairReader<Self::Endpoint>;
|
||||||
type Writer = PairWriter<Self::Endpoint>;
|
type Writer = PairWriter<Self::Endpoint>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn keypair(initiator: bool) -> KeyPair {
|
impl Owner for VoidOwner {
|
||||||
let k1 = Key {
|
type Error = BindError;
|
||||||
key: [0x53u8; 32],
|
|
||||||
id: 0x646e6573,
|
fn set_fwmark(&self, _value: Option<u32>) -> Option<Self::Error> {
|
||||||
};
|
None
|
||||||
let k2 = Key {
|
}
|
||||||
key: [0x52u8; 32],
|
}
|
||||||
id: 0x76636572,
|
|
||||||
};
|
impl Platform for PairBind {
|
||||||
if initiator {
|
type Owner = VoidOwner;
|
||||||
KeyPair {
|
fn bind(_port: u16) -> Result<(Vec<Self::Reader>, Self::Writer, Self::Owner), Self::Error> {
|
||||||
birth: Instant::now(),
|
Err(BindError::Disconnected)
|
||||||
initiator: true,
|
|
||||||
send: k1,
|
|
||||||
recv: k2,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
KeyPair {
|
|
||||||
birth: Instant::now(),
|
|
||||||
initiator: false,
|
|
||||||
send: k2,
|
|
||||||
recv: k1,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
1
src/platform/dummy/endpoint.rs
Normal file
1
src/platform/dummy/endpoint.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
13
src/platform/dummy/mod.rs
Normal file
13
src/platform/dummy/mod.rs
Normal file
@@ -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::*;
|
||||||
172
src/platform/dummy/tun.rs
Normal file
172
src/platform/dummy/tun.rs
Normal file
@@ -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,4 @@
|
|||||||
use super::super::super::wireguard::tun::*;
|
use super::super::tun::*;
|
||||||
use super::super::PlatformTun;
|
|
||||||
use super::super::Tun;
|
|
||||||
|
|
||||||
use libc::*;
|
use libc::*;
|
||||||
|
|
||||||
@@ -127,7 +125,7 @@ impl Tun for LinuxTun {
|
|||||||
type MTU = LinuxTunMTU;
|
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> {
|
fn create(name: &str) -> Result<(Vec<Self::Reader>, Self::Writer, Self::MTU), Self::Error> {
|
||||||
// construct request struct
|
// construct request struct
|
||||||
let mut req = Ifreq {
|
let mut req = Ifreq {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use super::super::Bind;
|
use super::super::bind::*;
|
||||||
use super::super::Endpoint;
|
use super::super::Endpoint;
|
||||||
use super::super::PlatformBind;
|
|
||||||
|
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
|
|||||||
@@ -1,33 +1,15 @@
|
|||||||
use std::error::Error;
|
mod endpoint;
|
||||||
|
|
||||||
use super::wireguard::bind::Bind;
|
pub mod bind;
|
||||||
use super::wireguard::tun::Tun;
|
pub mod tun;
|
||||||
use super::wireguard::Endpoint;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
pub use endpoint::Endpoint;
|
||||||
mod dummy;
|
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
mod linux;
|
mod linux;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
pub mod dummy;
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
pub use linux::LinuxTun as TunInstance;
|
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>;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -54,3 +54,8 @@ pub trait Tun: Send + Sync + 'static {
|
|||||||
type MTU: MTU;
|
type MTU: MTU;
|
||||||
type Error: Error;
|
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>;
|
||||||
|
}
|
||||||
1
src/tests.rs
Normal file
1
src/tests.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
@@ -16,9 +16,11 @@ mod tests;
|
|||||||
/// - Bind type, specifying how WireGuard messages are sent/received from the internet and what constitutes an "endpoint"
|
/// - Bind type, specifying how WireGuard messages are sent/received from the internet and what constitutes an "endpoint"
|
||||||
pub use wireguard::{Peer, Wireguard};
|
pub use wireguard::{Peer, Wireguard};
|
||||||
|
|
||||||
pub use types::bind;
|
#[cfg(test)]
|
||||||
pub use types::tun;
|
pub use types::dummy_keypair;
|
||||||
pub use types::Endpoint;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub use types::dummy;
|
use super::platform::dummy;
|
||||||
|
|
||||||
|
use super::platform::{bind, tun, Endpoint};
|
||||||
|
use types::{Key, KeyPair};
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ use super::types::{Callbacks, RouterError};
|
|||||||
use super::workers::{worker_parallel, JobParallel, Operation};
|
use super::workers::{worker_parallel, JobParallel, Operation};
|
||||||
use super::SIZE_MESSAGE_PREFIX;
|
use super::SIZE_MESSAGE_PREFIX;
|
||||||
|
|
||||||
use super::super::types::{bind, tun, Endpoint, KeyPair};
|
use super::super::{bind, tun, Endpoint, KeyPair};
|
||||||
|
|
||||||
pub struct DeviceInner<E: Endpoint, C: Callbacks, T: tun::Writer, B: bind::Writer<E>> {
|
pub struct DeviceInner<E: Endpoint, C: Callbacks, T: tun::Writer, B: bind::Writer<E>> {
|
||||||
// inbound writer (TUN)
|
// inbound writer (TUN)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use treebitmap::IpLookupTable;
|
|||||||
use zerocopy::LayoutVerified;
|
use zerocopy::LayoutVerified;
|
||||||
|
|
||||||
use super::super::constants::*;
|
use super::super::constants::*;
|
||||||
use super::super::types::{bind, tun, Endpoint, KeyPair};
|
use super::super::{bind, tun, Endpoint, KeyPair};
|
||||||
|
|
||||||
use super::anti_replay::AntiReplay;
|
use super::anti_replay::AntiReplay;
|
||||||
use super::device::DecryptionState;
|
use super::device::DecryptionState;
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ use num_cpus;
|
|||||||
use pnet::packet::ipv4::MutableIpv4Packet;
|
use pnet::packet::ipv4::MutableIpv4Packet;
|
||||||
use pnet::packet::ipv6::MutableIpv6Packet;
|
use pnet::packet::ipv6::MutableIpv6Packet;
|
||||||
|
|
||||||
use super::super::types::bind::*;
|
use super::super::bind::*;
|
||||||
use super::super::types::*;
|
use super::super::dummy;
|
||||||
|
use super::super::dummy_keypair;
|
||||||
use super::{Callbacks, Device, SIZE_MESSAGE_PREFIX};
|
use super::{Callbacks, Device, SIZE_MESSAGE_PREFIX};
|
||||||
|
|
||||||
extern crate test;
|
extern crate test;
|
||||||
@@ -151,7 +151,7 @@ mod tests {
|
|||||||
// add new peer
|
// add new peer
|
||||||
let opaque = Arc::new(AtomicUsize::new(0));
|
let opaque = Arc::new(AtomicUsize::new(0));
|
||||||
let peer = router.new_peer(opaque.clone());
|
let peer = router.new_peer(opaque.clone());
|
||||||
peer.add_keypair(dummy::keypair(true));
|
peer.add_keypair(dummy_keypair(true));
|
||||||
|
|
||||||
// add subnet to peer
|
// add subnet to peer
|
||||||
let (mask, len, ip) = ("192.168.1.0", 24, "192.168.1.20");
|
let (mask, len, ip) = ("192.168.1.0", 24, "192.168.1.20");
|
||||||
@@ -211,7 +211,7 @@ mod tests {
|
|||||||
let peer = router.new_peer(opaque.clone());
|
let peer = router.new_peer(opaque.clone());
|
||||||
let mask: IpAddr = mask.parse().unwrap();
|
let mask: IpAddr = mask.parse().unwrap();
|
||||||
if set_key {
|
if set_key {
|
||||||
peer.add_keypair(dummy::keypair(true));
|
peer.add_keypair(dummy_keypair(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
// map subnet to peer
|
// map subnet to peer
|
||||||
@@ -340,7 +340,7 @@ mod tests {
|
|||||||
let peer1 = router1.new_peer(opaq1.clone());
|
let peer1 = router1.new_peer(opaq1.clone());
|
||||||
let mask: IpAddr = mask.parse().unwrap();
|
let mask: IpAddr = mask.parse().unwrap();
|
||||||
peer1.add_subnet(mask, *len);
|
peer1.add_subnet(mask, *len);
|
||||||
peer1.add_keypair(dummy::keypair(false));
|
peer1.add_keypair(dummy_keypair(false));
|
||||||
|
|
||||||
let (mask, len, _ip, _okay) = p2;
|
let (mask, len, _ip, _okay) = p2;
|
||||||
let peer2 = router2.new_peer(opaq2.clone());
|
let peer2 = router2.new_peer(opaq2.clone());
|
||||||
@@ -370,7 +370,7 @@ mod tests {
|
|||||||
// this should cause a key-confirmation packet (keepalive or staged packet)
|
// this should cause a key-confirmation packet (keepalive or staged packet)
|
||||||
// this also causes peer1 to learn the "endpoint" for peer2
|
// this also causes peer1 to learn the "endpoint" for peer2
|
||||||
assert!(peer1.get_endpoint().is_none());
|
assert!(peer1.get_endpoint().is_none());
|
||||||
peer2.add_keypair(dummy::keypair(true));
|
peer2.add_keypair(dummy_keypair(true));
|
||||||
|
|
||||||
wait();
|
wait();
|
||||||
assert!(opaq2.send().is_some());
|
assert!(opaq2.send().is_some());
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ use super::messages::{TransportHeader, TYPE_TRANSPORT};
|
|||||||
use super::peer::PeerInner;
|
use super::peer::PeerInner;
|
||||||
use super::types::Callbacks;
|
use super::types::Callbacks;
|
||||||
|
|
||||||
use super::super::types::{bind, tun, Endpoint};
|
use super::super::{bind, tun, Endpoint};
|
||||||
use super::ip::*;
|
use super::ip::*;
|
||||||
|
|
||||||
pub const SIZE_TAG: usize = 16;
|
pub const SIZE_TAG: usize = 16;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use super::types::tun::Tun;
|
|
||||||
use super::types::{bind, dummy, tun};
|
|
||||||
use super::wireguard::Wireguard;
|
use super::wireguard::Wireguard;
|
||||||
|
use super::{bind, dummy, tun};
|
||||||
|
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ use log::info;
|
|||||||
|
|
||||||
use hjul::{Runner, Timer};
|
use hjul::{Runner, Timer};
|
||||||
|
|
||||||
|
use super::{bind, tun};
|
||||||
use super::constants::*;
|
use super::constants::*;
|
||||||
use super::router::{Callbacks, message_data_len};
|
use super::router::{Callbacks, message_data_len};
|
||||||
use super::types::{bind, tun};
|
|
||||||
use super::wireguard::{Peer, PeerInner};
|
use super::wireguard::{Peer, PeerInner};
|
||||||
|
|
||||||
pub struct Timers {
|
pub struct Timers {
|
||||||
|
|||||||
@@ -1,6 +1,33 @@
|
|||||||
use clear_on_drop::clear::Clear;
|
use clear_on_drop::clear::Clear;
|
||||||
use std::time::Instant;
|
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)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Key {
|
pub struct Key {
|
||||||
pub key: [u8; 32],
|
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};
|
|
||||||
@@ -3,10 +3,10 @@ use super::handshake;
|
|||||||
use super::router;
|
use super::router;
|
||||||
use super::timers::{Events, Timers};
|
use super::timers::{Events, Timers};
|
||||||
|
|
||||||
use super::types::bind::Reader as BindReader;
|
use super::bind::Reader as BindReader;
|
||||||
use super::types::bind::{Bind, Writer};
|
use super::bind::{Bind, Writer};
|
||||||
use super::types::tun::{Reader, Tun, MTU};
|
use super::tun::{Reader, Tun, MTU};
|
||||||
use super::types::Endpoint;
|
use super::Endpoint;
|
||||||
|
|
||||||
use hjul::Runner;
|
use hjul::Runner;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user