Moved IO traits into platform module
This commit is contained in:
@@ -16,9 +16,11 @@ mod tests;
|
||||
/// - Bind type, specifying how WireGuard messages are sent/received from the internet and what constitutes an "endpoint"
|
||||
pub use wireguard::{Peer, Wireguard};
|
||||
|
||||
pub use types::bind;
|
||||
pub use types::tun;
|
||||
pub use types::Endpoint;
|
||||
#[cfg(test)]
|
||||
pub use types::dummy_keypair;
|
||||
|
||||
#[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::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>> {
|
||||
// inbound writer (TUN)
|
||||
|
||||
@@ -14,7 +14,7 @@ use treebitmap::IpLookupTable;
|
||||
use zerocopy::LayoutVerified;
|
||||
|
||||
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::device::DecryptionState;
|
||||
|
||||
@@ -9,9 +9,9 @@ use num_cpus;
|
||||
use pnet::packet::ipv4::MutableIpv4Packet;
|
||||
use pnet::packet::ipv6::MutableIpv6Packet;
|
||||
|
||||
use super::super::types::bind::*;
|
||||
use super::super::types::*;
|
||||
|
||||
use super::super::bind::*;
|
||||
use super::super::dummy;
|
||||
use super::super::dummy_keypair;
|
||||
use super::{Callbacks, Device, SIZE_MESSAGE_PREFIX};
|
||||
|
||||
extern crate test;
|
||||
@@ -151,7 +151,7 @@ mod tests {
|
||||
// add new peer
|
||||
let opaque = Arc::new(AtomicUsize::new(0));
|
||||
let peer = router.new_peer(opaque.clone());
|
||||
peer.add_keypair(dummy::keypair(true));
|
||||
peer.add_keypair(dummy_keypair(true));
|
||||
|
||||
// add subnet to peer
|
||||
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 mask: IpAddr = mask.parse().unwrap();
|
||||
if set_key {
|
||||
peer.add_keypair(dummy::keypair(true));
|
||||
peer.add_keypair(dummy_keypair(true));
|
||||
}
|
||||
|
||||
// map subnet to peer
|
||||
@@ -340,7 +340,7 @@ mod tests {
|
||||
let peer1 = router1.new_peer(opaq1.clone());
|
||||
let mask: IpAddr = mask.parse().unwrap();
|
||||
peer1.add_subnet(mask, *len);
|
||||
peer1.add_keypair(dummy::keypair(false));
|
||||
peer1.add_keypair(dummy_keypair(false));
|
||||
|
||||
let (mask, len, _ip, _okay) = p2;
|
||||
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 also causes peer1 to learn the "endpoint" for peer2
|
||||
assert!(peer1.get_endpoint().is_none());
|
||||
peer2.add_keypair(dummy::keypair(true));
|
||||
peer2.add_keypair(dummy_keypair(true));
|
||||
|
||||
wait();
|
||||
assert!(opaq2.send().is_some());
|
||||
|
||||
@@ -17,7 +17,7 @@ use super::messages::{TransportHeader, TYPE_TRANSPORT};
|
||||
use super::peer::PeerInner;
|
||||
use super::types::Callbacks;
|
||||
|
||||
use super::super::types::{bind, tun, Endpoint};
|
||||
use super::super::{bind, tun, Endpoint};
|
||||
use super::ip::*;
|
||||
|
||||
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::{bind, dummy, tun};
|
||||
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
@@ -7,9 +7,9 @@ use log::info;
|
||||
|
||||
use hjul::{Runner, Timer};
|
||||
|
||||
use super::{bind, tun};
|
||||
use super::constants::*;
|
||||
use super::router::{Callbacks, message_data_len};
|
||||
use super::types::{bind, tun};
|
||||
use super::wireguard::{Peer, PeerInner};
|
||||
|
||||
pub struct Timers {
|
||||
|
||||
@@ -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,339 +0,0 @@
|
||||
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::*;
|
||||
|
||||
/* 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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* TUN implementation */
|
||||
|
||||
#[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")
|
||||
}
|
||||
}
|
||||
|
||||
/* Endpoint implementation */
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct UnitEndpoint {}
|
||||
|
||||
impl Endpoint for UnitEndpoint {
|
||||
fn from_address(_: SocketAddr) -> UnitEndpoint {
|
||||
UnitEndpoint {}
|
||||
}
|
||||
|
||||
fn into_address(&self) -> SocketAddr {
|
||||
"127.0.0.1:8080".parse().unwrap()
|
||||
}
|
||||
|
||||
fn clear_src(&mut self) {}
|
||||
}
|
||||
|
||||
impl UnitEndpoint {
|
||||
pub fn new() -> UnitEndpoint {
|
||||
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 {
|
||||
type Error = BindError;
|
||||
|
||||
fn read(&self, _buf: &mut [u8]) -> Result<(usize, UnitEndpoint), Self::Error> {
|
||||
Ok((0, UnitEndpoint {}))
|
||||
}
|
||||
}
|
||||
|
||||
impl bind::Writer<UnitEndpoint> for VoidBind {
|
||||
type Error = BindError;
|
||||
|
||||
fn write(&self, _buf: &[u8], _dst: &UnitEndpoint) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl bind::Bind for VoidBind {
|
||||
type Error = BindError;
|
||||
type Endpoint = UnitEndpoint;
|
||||
|
||||
type Reader = VoidBind;
|
||||
type Writer = VoidBind;
|
||||
}
|
||||
|
||||
impl VoidBind {
|
||||
pub fn new() -> VoidBind {
|
||||
VoidBind {}
|
||||
}
|
||||
}
|
||||
|
||||
/* Pair Bind */
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct PairReader<E> {
|
||||
recv: Arc<Mutex<Receiver<Vec<u8>>>>,
|
||||
_marker: marker::PhantomData<E>,
|
||||
}
|
||||
|
||||
impl bind::Reader<UnitEndpoint> for PairReader<UnitEndpoint> {
|
||||
type Error = BindError;
|
||||
fn read(&self, buf: &mut [u8]) -> Result<(usize, UnitEndpoint), Self::Error> {
|
||||
let vec = self
|
||||
.recv
|
||||
.lock()
|
||||
.unwrap()
|
||||
.recv()
|
||||
.map_err(|_| BindError::Disconnected)?;
|
||||
let len = vec.len();
|
||||
buf[..len].copy_from_slice(&vec[..]);
|
||||
Ok((vec.len(), UnitEndpoint {}))
|
||||
}
|
||||
}
|
||||
|
||||
impl bind::Writer<UnitEndpoint> for PairWriter<UnitEndpoint> {
|
||||
type Error = BindError;
|
||||
fn write(&self, buf: &[u8], _dst: &UnitEndpoint) -> Result<(), Self::Error> {
|
||||
let owned = buf.to_owned();
|
||||
match self.send.lock().unwrap().send(owned) {
|
||||
Err(_) => Err(BindError::Disconnected),
|
||||
Ok(_) => Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct PairWriter<E> {
|
||||
send: Arc<Mutex<SyncSender<Vec<u8>>>>,
|
||||
_marker: marker::PhantomData<E>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct PairBind {}
|
||||
|
||||
impl PairBind {
|
||||
pub fn pair<E>() -> (
|
||||
(PairReader<E>, PairWriter<E>),
|
||||
(PairReader<E>, PairWriter<E>),
|
||||
) {
|
||||
let (tx1, rx1) = sync_channel(128);
|
||||
let (tx2, rx2) = sync_channel(128);
|
||||
(
|
||||
(
|
||||
PairReader {
|
||||
recv: Arc::new(Mutex::new(rx1)),
|
||||
_marker: marker::PhantomData,
|
||||
},
|
||||
PairWriter {
|
||||
send: Arc::new(Mutex::new(tx2)),
|
||||
_marker: marker::PhantomData,
|
||||
},
|
||||
),
|
||||
(
|
||||
PairReader {
|
||||
recv: Arc::new(Mutex::new(rx2)),
|
||||
_marker: marker::PhantomData,
|
||||
},
|
||||
PairWriter {
|
||||
send: Arc::new(Mutex::new(tx1)),
|
||||
_marker: marker::PhantomData,
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl bind::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,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
use std::net::SocketAddr;
|
||||
|
||||
pub trait Endpoint: Send + 'static {
|
||||
fn from_address(addr: SocketAddr) -> Self;
|
||||
fn into_address(&self) -> SocketAddr;
|
||||
fn clear_src(&mut self);
|
||||
}
|
||||
@@ -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};
|
||||
@@ -1,56 +0,0 @@
|
||||
use std::error::Error;
|
||||
|
||||
pub trait Writer: Send + Sync + 'static {
|
||||
type Error: Error;
|
||||
|
||||
/// Receive a cryptkey routed IP packet
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - src: Buffer containing the IP packet to be written
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Unit type or an error
|
||||
fn write(&self, src: &[u8]) -> Result<(), Self::Error>;
|
||||
}
|
||||
|
||||
pub trait Reader: Send + 'static {
|
||||
type Error: Error;
|
||||
|
||||
/// Reads an IP packet into dst[offset:] from the tunnel device
|
||||
///
|
||||
/// The reason for providing space for a prefix
|
||||
/// is to efficiently accommodate platforms on which the packet is prefaced by a header.
|
||||
/// This space is later used to construct the transport message inplace.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - buf: Destination buffer (enough space for MTU bytes + header)
|
||||
/// - offset: Offset for the beginning of the IP packet
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// The size of the IP packet (ignoring the header) or an std::error::Error instance:
|
||||
fn read(&self, buf: &mut [u8], offset: usize) -> Result<usize, Self::Error>;
|
||||
}
|
||||
|
||||
pub trait MTU: Send + Sync + Clone + 'static {
|
||||
/// Returns the MTU of the device
|
||||
///
|
||||
/// This function needs to be efficient (called for every read).
|
||||
/// The goto implementation strategy is to .load an atomic variable,
|
||||
/// then use e.g. netlink to update the variable in a separate thread.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// The MTU of the interface in bytes
|
||||
fn mtu(&self) -> usize;
|
||||
}
|
||||
|
||||
pub trait Tun: Send + Sync + 'static {
|
||||
type Writer: Writer;
|
||||
type Reader: Reader;
|
||||
type MTU: MTU;
|
||||
type Error: Error;
|
||||
}
|
||||
@@ -3,10 +3,10 @@ use super::handshake;
|
||||
use super::router;
|
||||
use super::timers::{Events, Timers};
|
||||
|
||||
use super::types::bind::Reader as BindReader;
|
||||
use super::types::bind::{Bind, Writer};
|
||||
use super::types::tun::{Reader, Tun, MTU};
|
||||
use super::types::Endpoint;
|
||||
use super::bind::Reader as BindReader;
|
||||
use super::bind::{Bind, Writer};
|
||||
use super::tun::{Reader, Tun, MTU};
|
||||
use super::Endpoint;
|
||||
|
||||
use hjul::Runner;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user