diff options
author | Jake McGinty <me@jake.su> | 2018-02-26 03:03:15 +0000 |
---|---|---|
committer | Jake McGinty <me@jake.su> | 2018-02-26 03:03:15 +0000 |
commit | a67009a677900c12f1ba564715c7c55f288259e3 (patch) | |
tree | 104400cea175565426b6ec4dbeda732c3fad90db | |
parent | add cross-platform fs notify library (diff) | |
download | wireguard-rs-a67009a677900c12f1ba564715c7c55f288259e3.tar.xz wireguard-rs-a67009a677900c12f1ba564715c7c55f288259e3.zip |
die on SIG{INT,TERM} and config UDS deletion, per spec
-rw-r--r-- | Cargo.lock | 16 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/interface/config.rs | 5 | ||||
-rw-r--r-- | src/interface/grim_reaper.rs | 70 | ||||
-rw-r--r-- | src/interface/mod.rs | 28 | ||||
-rw-r--r-- | src/lib.rs | 2 |
6 files changed, 112 insertions, 10 deletions
@@ -1136,6 +1136,20 @@ dependencies = [ ] [[package]] +name = "tokio-signal" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-uds 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "tokio-timer" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1262,6 +1276,7 @@ dependencies = [ "subtle 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-signal 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-utun 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1452,6 +1467,7 @@ dependencies = [ "checksum time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "a15375f1df02096fb3317256ce2cee6a1f42fc84ea5ad5fc8c421cfe40c73098" "checksum tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "52b4e32d8edbf29501aabb3570f027c6ceb00ccef6538f4bddba0200503e74e8" "checksum tokio-io 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b9532748772222bf70297ec0e2ad0f17213b4a7dd0e6afb68e0a0768f69f4e4f" +"checksum tokio-signal 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c4ef9836ecceb2583e0ddf25b7ca448fac74c1115461436f85e088a8e39e7904" "checksum tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6131e780037787ff1b3f8aad9da83bca02438b72277850dd6ad0d455e0e20efc" "checksum tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "65ae5d255ce739e8537221ed2942e0445f4b3b813daebac1c0050ddaaa3587f9" "checksum tokio-utun 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5352f613ebd4d3a9ec72c087da0a34480dd942529af6897788ff7fe2689936af" @@ -52,6 +52,7 @@ tokio-core = "^0.1" tokio-uds = "^0.1" tokio-utun = "^0.1" tokio-timer = "^0.1" +tokio-signal = "^0.1" treebitmap = "^0.2" x25519-dalek = "^0.1" diff --git a/src/interface/config.rs b/src/interface/config.rs index b2e25d8..71ca155 100644 --- a/src/interface/config.rs +++ b/src/interface/config.rs @@ -136,10 +136,7 @@ impl ConfigurationServiceManager { } } - /// Creates a new `WireGuard` instance pub fn get_path(&self) -> Result<PathBuf, Error> { - // let _tun = Tun::create(Some("hey")); - // Create the socket directory if not existing let mut socket_path = Self::get_run_path().join("wireguard"); if !socket_path.exists() { @@ -162,7 +159,6 @@ impl ConfigurationServiceManager { } #[cfg(unix)] - /// Sets the permissions to a given `Path` fn chmod(path: &Path, perms: u32) -> Result<(), Error> { use std::os::unix::prelude::PermissionsExt; use std::fs::{set_permissions, Permissions}; @@ -171,7 +167,6 @@ impl ConfigurationServiceManager { } #[cfg(windows)] - /// Sets the permissions to a given `Path` fn chmod(_path: &Path, _perms: u32) -> Result<(), Error> { Ok(()) } diff --git a/src/interface/grim_reaper.rs b/src/interface/grim_reaper.rs new file mode 100644 index 0000000..0bbe7b6 --- /dev/null +++ b/src/interface/grim_reaper.rs @@ -0,0 +1,70 @@ +use failure::Error; +use futures::{self, Future, Async, Poll, Stream}; +use notify::{self, Watcher, RecursiveMode, RawEvent, raw_watcher}; +use std::{self, thread, time::Duration, path::Path}; +use tokio_core::reactor::Handle; +use tokio_signal::{self, unix::{Signal, SIGTERM}}; + +pub struct GrimReaper { + rx: futures::sync::oneshot::Receiver<()>, + signal: Box<Stream<Item = (), Error = std::io::Error>>, +} + +impl GrimReaper { + pub fn spawn(handle: &Handle, socket_path: &Path) -> Result<Self, Error> { + let (std_tx, std_rx) = std::sync::mpsc::channel::<RawEvent>(); + let (tx, rx ) = futures::sync::oneshot::channel::<()>(); + + let path = socket_path.to_owned(); + debug!("grim reaper spawning for {}.", socket_path.to_string_lossy()); + + thread::Builder::new() + .name("grim reaper".into()) + .spawn(move || { + thread::sleep(Duration::from_millis(500)); + let mut watcher = raw_watcher(std_tx).unwrap(); + watcher.watch(path, RecursiveMode::Recursive).unwrap(); + + loop { + debug!("listening"); + let event = std_rx.recv().unwrap(); + debug!("FS EVENT: {:?}", event); + if event.op.unwrap() == notify::op::REMOVE { + tx.send(()).unwrap(); + panic!("configuration socket removed, sounding death cry.") + } + } + })?; + + let sigint = tokio_signal::ctrl_c(&handle).flatten_stream(); + let sigterm = Signal::new(SIGTERM, &handle).flatten_stream().map(|_| ()); + let signal = Box::new(sigint.select(sigterm)); + + Ok(Self { rx, signal }) + } +} + +impl Future for GrimReaper { + type Item = (); + type Error = (); + + fn poll(&mut self) -> Poll<Self::Item, Self::Error> { + match self.rx.poll() { + Ok(Async::NotReady) => {}, + _ => { + info!("configuration socket removed, bubbling up to reactor core."); + return Err(()) + }, + } + + match self.signal.poll() { + Ok(Async::NotReady) => {}, + _ => { + info!("SIGINT received, bubbling up to reactor core."); + return Err(()) + }, + } + + Ok(Async::NotReady) + } +} diff --git a/src/interface/mod.rs b/src/interface/mod.rs index 532fb40..e969954 100644 --- a/src/interface/mod.rs +++ b/src/interface/mod.rs @@ -1,7 +1,9 @@ mod config; +mod grim_reaper; mod peer_server; use self::config::{ConfigurationServiceManager, UpdateEvent, Command, ConfigurationCodec}; +use self::grim_reaper::GrimReaper; use self::peer_server::PeerServer; use router::Router; @@ -13,6 +15,7 @@ use std::io; use std::rc::Rc; use std::cell::RefCell; use std::collections::HashMap; +use std::fs::remove_file; use types::{InterfaceInfo}; use x25519_dalek as x25519; @@ -115,11 +118,14 @@ impl Interface { .map_err(|e| { warn!("utun write error: {:?}", e); () }); let utun_fut = utun_write_fut.join(utun_read_fut); - let config_manager = ConfigurationServiceManager::new(&self.name); - let handle = core.handle(); - let listener = UnixListener::bind(config_manager.get_path().unwrap(), &handle).unwrap(); + let config_manager = ConfigurationServiceManager::new(&self.name); + let handle = core.handle(); + let config_path = config_manager.get_path().unwrap(); + let listener = UnixListener::bind(config_path.clone(), &handle).unwrap(); + let reaper = GrimReaper::spawn(&handle, config_path.parent().unwrap()).unwrap(); let (config_tx, config_rx) = sync::mpsc::channel::<UpdateEvent>(1024); - let h = handle.clone(); + let h = handle.clone(); + let config_server = listener.incoming().for_each({ let config_tx = config_tx.clone(); let state = self.state.clone(); @@ -231,6 +237,18 @@ impl Interface { let config_fut = peer_server.config_tx().sink_map_err(|_|()).send_all(config_fut).map_err(|e| { warn!("error {:?}", e); () }); - core.run(peer_server.join(utun_fut.join(config_fut.join(config_server)))).unwrap(); + core.run(reaper.join(peer_server.join(utun_fut.join(config_fut.join(config_server))))).unwrap(); } } + +impl Drop for Interface { + fn drop(&mut self) { + let mut socket_path = ConfigurationServiceManager::get_run_path().join("wireguard"); + socket_path.push(&self.name); + socket_path.set_extension("sock"); + if socket_path.exists() { + info!("Removing socket on drop: {}", socket_path.display()); + let _ = remove_file(&socket_path); + } + } +}
\ No newline at end of file @@ -19,6 +19,7 @@ extern crate env_logger; extern crate futures; extern crate hex; extern crate nix; +extern crate notify; extern crate pnet_packet; extern crate rand; extern crate snow; @@ -30,6 +31,7 @@ extern crate tokio_io; extern crate tokio_uds; extern crate tokio_utun; extern crate tokio_timer; +extern crate tokio_signal; extern crate treebitmap; extern crate x25519_dalek; |