aboutsummaryrefslogtreecommitdiffstats
path: root/src/wireguard
diff options
context:
space:
mode:
authorMathias Hall-Andersen <mathias@hall-andersen.dk>2019-11-24 18:41:43 +0100
committerMathias Hall-Andersen <mathias@hall-andersen.dk>2019-11-24 18:41:43 +0100
commit3bff078e3f1c59454d8db14e5dc7603e6fdbeaba (patch)
treeda301a422eb8aa38ac7960324b8b6fe2d0909302 /src/wireguard
parentDaemonization (diff)
downloadwireguard-rs-3bff078e3f1c59454d8db14e5dc7603e6fdbeaba.tar.xz
wireguard-rs-3bff078e3f1c59454d8db14e5dc7603e6fdbeaba.zip
Make IO traits suitable for Tun events (up/down)
Diffstat (limited to 'src/wireguard')
-rw-r--r--src/wireguard/mod.rs2
-rw-r--r--src/wireguard/peer.rs16
-rw-r--r--src/wireguard/router/device.rs12
-rw-r--r--src/wireguard/router/peer.rs18
-rw-r--r--src/wireguard/router/tests.rs2
-rw-r--r--src/wireguard/router/workers.rs8
-rw-r--r--src/wireguard/tests.rs14
-rw-r--r--src/wireguard/timers.rs8
-rw-r--r--src/wireguard/wireguard.rs50
9 files changed, 77 insertions, 53 deletions
diff --git a/src/wireguard/mod.rs b/src/wireguard/mod.rs
index 79feed7..711aa2b 100644
--- a/src/wireguard/mod.rs
+++ b/src/wireguard/mod.rs
@@ -20,7 +20,7 @@ pub use types::dummy_keypair;
#[cfg(test)]
use super::platform::dummy;
-use super::platform::{bind, tun, Endpoint};
+use super::platform::{tun, udp, Endpoint};
use peer::PeerInner;
use types::KeyPair;
use wireguard::HandshakeJob;
diff --git a/src/wireguard/peer.rs b/src/wireguard/peer.rs
index 92844b6..5bcd070 100644
--- a/src/wireguard/peer.rs
+++ b/src/wireguard/peer.rs
@@ -2,8 +2,8 @@ use super::router;
use super::timers::{Events, Timers};
use super::HandshakeJob;
-use super::bind::Bind;
use super::tun::Tun;
+use super::udp::UDP;
use super::wireguard::WireguardInner;
use std::fmt;
@@ -17,12 +17,12 @@ use spin::{Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};
use crossbeam_channel::Sender;
use x25519_dalek::PublicKey;
-pub struct Peer<T: Tun, B: Bind> {
+pub struct Peer<T: Tun, B: UDP> {
pub router: Arc<router::Peer<B::Endpoint, Events<T, B>, T::Writer, B::Writer>>,
pub state: Arc<PeerInner<T, B>>,
}
-pub struct PeerInner<T: Tun, B: Bind> {
+pub struct PeerInner<T: Tun, B: UDP> {
// internal id (for logging)
pub id: u64,
@@ -44,7 +44,7 @@ pub struct PeerInner<T: Tun, B: Bind> {
pub timers: RwLock<Timers>,
}
-impl<T: Tun, B: Bind> Clone for Peer<T, B> {
+impl<T: Tun, B: UDP> Clone for Peer<T, B> {
fn clone(&self) -> Peer<T, B> {
Peer {
router: self.router.clone(),
@@ -53,7 +53,7 @@ impl<T: Tun, B: Bind> Clone for Peer<T, B> {
}
}
-impl<T: Tun, B: Bind> PeerInner<T, B> {
+impl<T: Tun, B: UDP> PeerInner<T, B> {
#[inline(always)]
pub fn timers(&self) -> RwLockReadGuard<Timers> {
self.timers.read()
@@ -65,20 +65,20 @@ impl<T: Tun, B: Bind> PeerInner<T, B> {
}
}
-impl<T: Tun, B: Bind> fmt::Display for Peer<T, B> {
+impl<T: Tun, B: UDP> fmt::Display for Peer<T, B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "peer(id = {})", self.id)
}
}
-impl<T: Tun, B: Bind> Deref for Peer<T, B> {
+impl<T: Tun, B: UDP> Deref for Peer<T, B> {
type Target = PeerInner<T, B>;
fn deref(&self) -> &Self::Target {
&self.state
}
}
-impl<T: Tun, B: Bind> Peer<T, B> {
+impl<T: Tun, B: UDP> Peer<T, B> {
/// Bring the peer down. Causing:
///
/// - Timers to be stopped and disabled.
diff --git a/src/wireguard/router/device.rs b/src/wireguard/router/device.rs
index 34273d5..621010b 100644
--- a/src/wireguard/router/device.rs
+++ b/src/wireguard/router/device.rs
@@ -21,9 +21,9 @@ use super::SIZE_MESSAGE_PREFIX;
use super::route::RoutingTable;
-use super::super::{bind, tun, Endpoint, KeyPair};
+use super::super::{tun, udp, 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: udp::Writer<E>> {
// inbound writer (TUN)
pub inbound: T,
@@ -45,7 +45,7 @@ pub struct EncryptionState {
pub death: Instant, // (birth + reject-after-time - keepalive-timeout - rekey-timeout)
}
-pub struct DecryptionState<E: Endpoint, C: Callbacks, T: tun::Writer, B: bind::Writer<E>> {
+pub struct DecryptionState<E: Endpoint, C: Callbacks, T: tun::Writer, B: udp::Writer<E>> {
pub keypair: Arc<KeyPair>,
pub confirmed: AtomicBool,
pub protector: Mutex<AntiReplay>,
@@ -53,12 +53,12 @@ pub struct DecryptionState<E: Endpoint, C: Callbacks, T: tun::Writer, B: bind::W
pub death: Instant, // time when the key can no longer be used for decryption
}
-pub struct Device<E: Endpoint, C: Callbacks, T: tun::Writer, B: bind::Writer<E>> {
+pub struct Device<E: Endpoint, C: Callbacks, T: tun::Writer, B: udp::Writer<E>> {
state: Arc<DeviceInner<E, C, T, B>>, // reference to device state
handles: Vec<thread::JoinHandle<()>>, // join handles for workers
}
-impl<E: Endpoint, C: Callbacks, T: tun::Writer, B: bind::Writer<E>> Drop for Device<E, C, T, B> {
+impl<E: Endpoint, C: Callbacks, T: tun::Writer, B: udp::Writer<E>> Drop for Device<E, C, T, B> {
fn drop(&mut self) {
debug!("router: dropping device");
@@ -82,7 +82,7 @@ impl<E: Endpoint, C: Callbacks, T: tun::Writer, B: bind::Writer<E>> Drop for Dev
}
}
-impl<E: Endpoint, C: Callbacks, T: tun::Writer, B: bind::Writer<E>> Device<E, C, T, B> {
+impl<E: Endpoint, C: Callbacks, T: tun::Writer, B: udp::Writer<E>> Device<E, C, T, B> {
pub fn new(num_workers: usize, tun: T) -> Device<E, C, T, B> {
// allocate shared device state
let inner = DeviceInner {
diff --git a/src/wireguard/router/peer.rs b/src/wireguard/router/peer.rs
index c09e786..fff4dfc 100644
--- a/src/wireguard/router/peer.rs
+++ b/src/wireguard/router/peer.rs
@@ -12,7 +12,7 @@ use log::debug;
use spin::Mutex;
use super::super::constants::*;
-use super::super::{bind, tun, Endpoint, KeyPair};
+use super::super::{tun, udp, Endpoint, KeyPair};
use super::anti_replay::AntiReplay;
use super::device::DecryptionState;
@@ -36,7 +36,7 @@ pub struct KeyWheel {
retired: Vec<u32>, // retired ids
}
-pub struct PeerInner<E: Endpoint, C: Callbacks, T: tun::Writer, B: bind::Writer<E>> {
+pub struct PeerInner<E: Endpoint, C: Callbacks, T: tun::Writer, B: udp::Writer<E>> {
pub device: Arc<DeviceInner<E, C, T, B>>,
pub opaque: C::Opaque,
pub outbound: Mutex<SyncSender<JobOutbound>>,
@@ -47,13 +47,13 @@ pub struct PeerInner<E: Endpoint, C: Callbacks, T: tun::Writer, B: bind::Writer<
pub endpoint: Mutex<Option<E>>,
}
-pub struct Peer<E: Endpoint, C: Callbacks, T: tun::Writer, B: bind::Writer<E>> {
+pub struct Peer<E: Endpoint, C: Callbacks, T: tun::Writer, B: udp::Writer<E>> {
state: Arc<PeerInner<E, C, T, B>>,
thread_outbound: Option<thread::JoinHandle<()>>,
thread_inbound: Option<thread::JoinHandle<()>>,
}
-impl<E: Endpoint, C: Callbacks, T: tun::Writer, B: bind::Writer<E>> Deref for Peer<E, C, T, B> {
+impl<E: Endpoint, C: Callbacks, T: tun::Writer, B: udp::Writer<E>> Deref for Peer<E, C, T, B> {
type Target = Arc<PeerInner<E, C, T, B>>;
fn deref(&self) -> &Self::Target {
@@ -71,7 +71,7 @@ impl EncryptionState {
}
}
-impl<E: Endpoint, C: Callbacks, T: tun::Writer, B: bind::Writer<E>> DecryptionState<E, C, T, B> {
+impl<E: Endpoint, C: Callbacks, T: tun::Writer, B: udp::Writer<E>> DecryptionState<E, C, T, B> {
fn new(
peer: &Arc<PeerInner<E, C, T, B>>,
keypair: &Arc<KeyPair>,
@@ -86,7 +86,7 @@ impl<E: Endpoint, C: Callbacks, T: tun::Writer, B: bind::Writer<E>> DecryptionSt
}
}
-impl<E: Endpoint, C: Callbacks, T: tun::Writer, B: bind::Writer<E>> Drop for Peer<E, C, T, B> {
+impl<E: Endpoint, C: Callbacks, T: tun::Writer, B: udp::Writer<E>> Drop for Peer<E, C, T, B> {
fn drop(&mut self) {
let peer = &self.state;
@@ -133,7 +133,7 @@ impl<E: Endpoint, C: Callbacks, T: tun::Writer, B: bind::Writer<E>> Drop for Pee
}
}
-pub fn new_peer<E: Endpoint, C: Callbacks, T: tun::Writer, B: bind::Writer<E>>(
+pub fn new_peer<E: Endpoint, C: Callbacks, T: tun::Writer, B: udp::Writer<E>>(
device: Arc<DeviceInner<E, C, T, B>>,
opaque: C::Opaque,
) -> Peer<E, C, T, B> {
@@ -180,7 +180,7 @@ pub fn new_peer<E: Endpoint, C: Callbacks, T: tun::Writer, B: bind::Writer<E>>(
}
}
-impl<E: Endpoint, C: Callbacks, T: tun::Writer, B: bind::Writer<E>> PeerInner<E, C, T, B> {
+impl<E: Endpoint, C: Callbacks, T: tun::Writer, B: udp::Writer<E>> PeerInner<E, C, T, B> {
/// Send a raw message to the peer (used for handshake messages)
///
/// # Arguments
@@ -352,7 +352,7 @@ impl<E: Endpoint, C: Callbacks, T: tun::Writer, B: bind::Writer<E>> PeerInner<E,
}
}
-impl<E: Endpoint, C: Callbacks, T: tun::Writer, B: bind::Writer<E>> Peer<E, C, T, B> {
+impl<E: Endpoint, C: Callbacks, T: tun::Writer, B: udp::Writer<E>> Peer<E, C, T, B> {
/// Set the endpoint of the peer
///
/// # Arguments
diff --git a/src/wireguard/router/tests.rs b/src/wireguard/router/tests.rs
index 24c1b56..2d6bb63 100644
--- a/src/wireguard/router/tests.rs
+++ b/src/wireguard/router/tests.rs
@@ -7,10 +7,10 @@ use std::time::Duration;
use num_cpus;
-use super::super::bind::*;
use super::super::dummy;
use super::super::dummy_keypair;
use super::super::tests::make_packet_dst;
+use super::super::udp::*;
use super::KeyPair;
use super::SIZE_MESSAGE_PREFIX;
use super::{Callbacks, Device};
diff --git a/src/wireguard/router/workers.rs b/src/wireguard/router/workers.rs
index cd8015b..3ed6311 100644
--- a/src/wireguard/router/workers.rs
+++ b/src/wireguard/router/workers.rs
@@ -19,7 +19,7 @@ use super::types::Callbacks;
use super::REJECT_AFTER_MESSAGES;
use super::super::types::KeyPair;
-use super::super::{bind, tun, Endpoint};
+use super::super::{tun, udp, Endpoint};
pub const SIZE_TAG: usize = 16;
@@ -40,7 +40,7 @@ pub enum JobParallel {
}
#[allow(type_alias_bounds)]
-pub type JobInbound<E, C, T, B: bind::Writer<E>> = (
+pub type JobInbound<E, C, T, B: udp::Writer<E>> = (
Arc<DecryptionState<E, C, T, B>>,
E,
oneshot::Receiver<Option<JobDecryption>>,
@@ -50,7 +50,7 @@ pub type JobOutbound = oneshot::Receiver<JobEncryption>;
/* TODO: Replace with run-queue
*/
-pub fn worker_inbound<E: Endpoint, C: Callbacks, T: tun::Writer, B: bind::Writer<E>>(
+pub fn worker_inbound<E: Endpoint, C: Callbacks, T: tun::Writer, B: udp::Writer<E>>(
device: Arc<DeviceInner<E, C, T, B>>, // related device
peer: Arc<PeerInner<E, C, T, B>>, // related peer
receiver: Receiver<JobInbound<E, C, T, B>>,
@@ -137,7 +137,7 @@ pub fn worker_inbound<E: Endpoint, C: Callbacks, T: tun::Writer, B: bind::Writer
/* TODO: Replace with run-queue
*/
-pub fn worker_outbound<E: Endpoint, C: Callbacks, T: tun::Writer, B: bind::Writer<E>>(
+pub fn worker_outbound<E: Endpoint, C: Callbacks, T: tun::Writer, B: udp::Writer<E>>(
peer: Arc<PeerInner<E, C, T, B>>,
receiver: Receiver<JobOutbound>,
) {
diff --git a/src/wireguard/tests.rs b/src/wireguard/tests.rs
index 83ef594..8217d72 100644
--- a/src/wireguard/tests.rs
+++ b/src/wireguard/tests.rs
@@ -1,5 +1,5 @@
use super::wireguard::Wireguard;
-use super::{bind, dummy, tun};
+use super::{dummy, tun, udp};
use std::net::IpAddr;
use std::thread;
@@ -84,13 +84,17 @@ fn test_pure_wireguard() {
// create WG instances for dummy TUN devices
- let (fake1, tun_reader1, tun_writer1, mtu1) = dummy::TunTest::create(1500, true);
+ let (fake1, tun_reader1, tun_writer1, _) = dummy::TunTest::create(1500, true);
let wg1: Wireguard<dummy::TunTest, dummy::PairBind> =
- Wireguard::new(vec![tun_reader1], tun_writer1, mtu1);
+ Wireguard::new(vec![tun_reader1], tun_writer1);
- let (fake2, tun_reader2, tun_writer2, mtu2) = dummy::TunTest::create(1500, true);
+ wg1.set_mtu(1500);
+
+ let (fake2, tun_reader2, tun_writer2, _) = dummy::TunTest::create(1500, true);
let wg2: Wireguard<dummy::TunTest, dummy::PairBind> =
- Wireguard::new(vec![tun_reader2], tun_writer2, mtu2);
+ Wireguard::new(vec![tun_reader2], tun_writer2);
+
+ wg2.set_mtu(1500);
// create pair bind to connect the interfaces "over the internet"
diff --git a/src/wireguard/timers.rs b/src/wireguard/timers.rs
index 5eb69dc..18f49bf 100644
--- a/src/wireguard/timers.rs
+++ b/src/wireguard/timers.rs
@@ -9,7 +9,7 @@ use hjul::{Runner, Timer};
use super::constants::*;
use super::router::{message_data_len, Callbacks};
use super::{Peer, PeerInner};
-use super::{bind, tun};
+use super::{udp, tun};
use super::types::KeyPair;
pub struct Timers {
@@ -35,7 +35,7 @@ impl Timers {
}
}
-impl<T: tun::Tun, B: bind::Bind> PeerInner<T, B> {
+impl<T: tun::Tun, B: udp::UDP> PeerInner<T, B> {
pub fn get_keepalive_interval(&self) -> u64 {
self.timers().keepalive_interval
@@ -224,7 +224,7 @@ impl Timers {
pub fn new<T, B>(runner: &Runner, peer: Peer<T, B>) -> Timers
where
T: tun::Tun,
- B: bind::Bind,
+ B: udp::UDP,
{
// create a timer instance for the provided peer
Timers {
@@ -335,7 +335,7 @@ impl Timers {
pub struct Events<T, B>(PhantomData<(T, B)>);
-impl<T: tun::Tun, B: bind::Bind> Callbacks for Events<T, B> {
+impl<T: tun::Tun, B: udp::UDP> Callbacks for Events<T, B> {
type Opaque = Arc<PeerInner<T, B>>;
/* Called after the router encrypts a transport message destined for the peer.
diff --git a/src/wireguard/wireguard.rs b/src/wireguard/wireguard.rs
index eb43512..41f6857 100644
--- a/src/wireguard/wireguard.rs
+++ b/src/wireguard/wireguard.rs
@@ -4,9 +4,13 @@ use super::router;
use super::timers::{Events, Timers};
use super::{Peer, PeerInner};
-use super::bind::Reader as BindReader;
-use super::bind::{Bind, Writer};
-use super::tun::{Reader, Tun, MTU};
+use super::tun;
+use super::tun::Reader as TunReader;
+
+use super::udp;
+use super::udp::Reader as UDPReader;
+use super::udp::Writer as UDPWriter;
+
use super::Endpoint;
use hjul::Runner;
@@ -34,13 +38,15 @@ const SIZE_HANDSHAKE_QUEUE: usize = 128;
const THRESHOLD_UNDER_LOAD: usize = SIZE_HANDSHAKE_QUEUE / 4;
const DURATION_UNDER_LOAD: Duration = Duration::from_millis(10_000);
-pub struct WireguardInner<T: Tun, B: Bind> {
+pub struct WireguardInner<T: tun::Tun, B: udp::UDP> {
// identifier (for logging)
id: u32,
start: Instant,
+ // current MTU
+ mtu: AtomicUsize,
+
// provides access to the MTU value of the tun device
- mtu: T::MTU,
send: RwLock<Option<B::Writer>>,
// identity and configuration map
@@ -56,7 +62,7 @@ pub struct WireguardInner<T: Tun, B: Bind> {
queue: Mutex<Sender<HandshakeJob<B::Endpoint>>>,
}
-impl<T: Tun, B: Bind> PeerInner<T, B> {
+impl<T: tun::Tun, B: udp::UDP> PeerInner<T, B> {
/* Queue a handshake request for the parallel workers
* (if one does not already exist)
*
@@ -87,20 +93,20 @@ pub enum HandshakeJob<E> {
New(PublicKey),
}
-impl<T: Tun, B: Bind> fmt::Display for WireguardInner<T, B> {
+impl<T: tun::Tun, B: udp::UDP> fmt::Display for WireguardInner<T, B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "wireguard({:x})", self.id)
}
}
-impl<T: Tun, B: Bind> Deref for Wireguard<T, B> {
+impl<T: tun::Tun, B: udp::UDP> Deref for Wireguard<T, B> {
type Target = Arc<WireguardInner<T, B>>;
fn deref(&self) -> &Self::Target {
&self.state
}
}
-pub struct Wireguard<T: Tun, B: Bind> {
+pub struct Wireguard<T: tun::Tun, B: udp::UDP> {
runner: Runner,
state: Arc<WireguardInner<T, B>>,
}
@@ -127,7 +133,7 @@ const fn padding(size: usize, mtu: usize) -> usize {
min(mtu, size + (pad - size % pad) % pad)
}
-impl<T: Tun, B: Bind> Wireguard<T, B> {
+impl<T: tun::Tun, B: udp::UDP> Wireguard<T, B> {
/// Brings the WireGuard device down.
/// Usually called when the associated interface is brought down.
///
@@ -269,7 +275,8 @@ impl<T: Tun, B: Bind> Wireguard<T, B> {
loop {
// create vector big enough for any message given current MTU
- let size = wg.mtu.mtu() + handshake::MAX_HANDSHAKE_MSG_SIZE;
+ let mtu = wg.mtu.load(Ordering::Relaxed);
+ let size = mtu + handshake::MAX_HANDSHAKE_MSG_SIZE;
let mut msg: Vec<u8> = Vec::with_capacity(size);
msg.resize(size, 0);
@@ -283,6 +290,11 @@ impl<T: Tun, B: Bind> Wireguard<T, B> {
};
msg.truncate(size);
+ // TODO: start device down
+ if mtu == 0 {
+ continue;
+ }
+
// message type de-multiplexer
if msg.len() < std::mem::size_of::<u32>() {
continue;
@@ -326,13 +338,17 @@ impl<T: Tun, B: Bind> Wireguard<T, B> {
});
}
+ pub fn set_mtu(&self, mtu: usize) {
+ self.mtu.store(mtu, Ordering::Relaxed);
+ }
+
pub fn set_writer(&self, writer: B::Writer) {
// TODO: Consider unifying these and avoid Clone requirement on writer
*self.state.send.write() = Some(writer.clone());
self.state.router.set_outbound_writer(writer);
}
- pub fn new(mut readers: Vec<T::Reader>, writer: T::Writer, mtu: T::MTU) -> Wireguard<T, B> {
+ pub fn new(mut readers: Vec<T::Reader>, writer: T::Writer) -> Wireguard<T, B> {
// create device state
let mut rng = OsRng::new().unwrap();
@@ -342,7 +358,7 @@ impl<T: Tun, B: Bind> Wireguard<T, B> {
let wg = Arc::new(WireguardInner {
start: Instant::now(),
id: rng.gen(),
- mtu: mtu.clone(),
+ mtu: AtomicUsize::new(0),
peers: RwLock::new(HashMap::new()),
send: RwLock::new(None),
router: router::Device::new(num_cpus::get(), writer), // router owns the writing half
@@ -475,10 +491,9 @@ impl<T: Tun, B: Bind> Wireguard<T, B> {
);
while let Some(reader) = readers.pop() {
let wg = wg.clone();
- let mtu = mtu.clone();
thread::spawn(move || loop {
// create vector big enough for any transport message (based on MTU)
- let mtu = mtu.mtu();
+ let mtu = wg.mtu.load(Ordering::Relaxed);
let size = mtu + router::SIZE_MESSAGE_PREFIX;
let mut msg: Vec<u8> = Vec::with_capacity(size + router::CAPACITY_MESSAGE_POSTFIX);
msg.resize(size, 0);
@@ -493,6 +508,11 @@ impl<T: Tun, B: Bind> Wireguard<T, B> {
};
debug!("TUN worker, IP packet of {} bytes (MTU = {})", payload, mtu);
+ // TODO: start device down
+ if mtu == 0 {
+ continue;
+ }
+
// truncate padding
let padded = padding(payload, mtu);
log::trace!(