diff options
| author | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2018-12-03 16:58:04 -0200 |
|---|---|---|
| committer | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2018-12-11 10:15:49 -0200 |
| commit | 8663a6407791d4eba48c804683ece9b6f85db3e0 (patch) | |
| tree | 6dd09e97eaac5fa33e938aa676e70cef1e7c684a | |
| parent | c6a525169b56a04e9eadab888a21cec76ff6110c (diff) | |
| download | mullvadvpn-8663a6407791d4eba48c804683ece9b6f85db3e0.tar.xz mullvadvpn-8663a6407791d4eba48c804683ece9b6f85db3e0.zip | |
Implement `is_offline` for Linux
| -rw-r--r-- | Cargo.lock | 65 | ||||
| -rw-r--r-- | talpid-core/Cargo.toml | 2 | ||||
| -rw-r--r-- | talpid-core/src/offline/linux.rs | 73 | ||||
| -rw-r--r-- | talpid-core/src/offline/mod.rs | 6 |
4 files changed, 145 insertions, 1 deletions
diff --git a/Cargo.lock b/Cargo.lock index 23bbdcab5f..4a642f31b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -326,6 +326,14 @@ dependencies = [ ] [[package]] +name = "eui48" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "failure" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -570,6 +578,24 @@ dependencies = [ ] [[package]] +name = "iproute2" +version = "0.0.2" +source = "git+https://github.com/mullvad/netlink?branch=best-effort-nla-parsing#132ab47bcbb32079ba4ededaa76a3d7b6257da40" +dependencies = [ + "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "eui48 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "ipnetwork 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "netlink-socket 0.0.2 (git+https://github.com/mullvad/netlink?branch=best-effort-nla-parsing)", + "rtnetlink 0.0.3 (git+https://github.com/mullvad/netlink?branch=best-effort-nla-parsing)", + "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "itoa" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1086,6 +1112,18 @@ dependencies = [ ] [[package]] +name = "netlink-socket" +version = "0.0.2" +source = "git+https://github.com/mullvad/netlink?branch=best-effort-nla-parsing#132ab47bcbb32079ba4ededaa76a3d7b6257da40" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "nftnl" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1471,11 +1509,31 @@ dependencies = [ ] [[package]] +name = "rtnetlink" +version = "0.0.3" +source = "git+https://github.com/mullvad/netlink?branch=best-effort-nla-parsing#132ab47bcbb32079ba4ededaa76a3d7b6257da40" +dependencies = [ + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "netlink-socket 0.0.2 (git+https://github.com/mullvad/netlink?branch=best-effort-nla-parsing)", + "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "rustc-demangle" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "rustc-serialize" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "rustc_version" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1705,6 +1763,7 @@ dependencies = [ "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "ipnetwork 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "iproute2 0.0.2 (git+https://github.com/mullvad/netlink?branch=best-effort-nla-parsing)", "jsonrpc-core 8.0.2 (git+https://github.com/mullvad/jsonrpc?branch=make-ipc-server-concurrent-part-deux)", "jsonrpc-macros 8.0.1 (git+https://github.com/mullvad/jsonrpc?branch=make-ipc-server-concurrent-part-deux)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1718,6 +1777,7 @@ dependencies = [ "os_pipe 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "pfctl 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "resolv-conf 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rtnetlink 0.0.3 (git+https://github.com/mullvad/netlink?branch=best-effort-nla-parsing)", "shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "system-configuration 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "talpid-ipc 0.1.0", @@ -2317,6 +2377,7 @@ dependencies = [ "checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" +"checksum eui48 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4970a61eb89c625299a850532620d811b70afac4cd8304cb2e9bf7e63e83ad56" "checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7" "checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596" "checksum fern 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "57915fe00a83af935983eb2d00b0ecc62419c4741b28c207ecbf98fd4a1b94c8" @@ -2343,6 +2404,7 @@ dependencies = [ "checksum ioctl-sys 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5e2c4b26352496eaaa8ca7cfa9bd99e93419d3f7983dc6e99c2a35fe9e33504a" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum ipnetwork 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d1d8b990621b5b0806fac3dbf71d1833a4c0a9e25702d10bd8b2c629c7ae01c" +"checksum iproute2 0.0.2 (git+https://github.com/mullvad/netlink?branch=best-effort-nla-parsing)" = "<none>" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum jsonrpc-client-core 0.5.0 (git+https://github.com/mullvad/jsonrpc-client-rs?rev=e9dbdc80)" = "<none>" "checksum jsonrpc-client-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f29cb249837420fb0cee7fb0fbf1d22679e121b160e71bb5e0d90b9df241c23e" @@ -2380,6 +2442,7 @@ dependencies = [ "checksum mnl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9ddf564b33717090dd6127325e590b13176b2346589c392a0cb274f2e5f8b8f7" "checksum mnl-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7cb01017fef6e68b6c437aed2b7601264dc94759f4c2b41f820f13854d41b3" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" +"checksum netlink-socket 0.0.2 (git+https://github.com/mullvad/netlink?branch=best-effort-nla-parsing)" = "<none>" "checksum nftnl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e05c68d4e54cf42fc4ef946a3bbe7779adfa1c1ce4868f06d0ee48479e8cba87" "checksum nftnl-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c2b00ddf077770bde037202e75296aecc5a0f94351196a5c46219c1c8c3a48c8" "checksum nix 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d37e713a259ff641624b6cb20e3b12b2952313ba36b6823c0f16e6cfd9e5de17" @@ -2421,7 +2484,9 @@ dependencies = [ "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum resolv-conf 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c62bd95a41841efdf7fca2ae9951e64a8d8eae7e5da196d8ce489a2241491a92" "checksum rs-release 0.1.7 (git+https://github.com/mullvad/rs-release?branch=snailquote-unescape)" = "<none>" +"checksum rtnetlink 0.0.3 (git+https://github.com/mullvad/netlink?branch=best-effort-nla-parsing)" = "<none>" "checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" +"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7153dd96dade874ab973e098cb62fcdbb89a03682e46b144fd09550998d4a4a7" "checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" diff --git a/talpid-core/Cargo.toml b/talpid-core/Cargo.toml index 3be2dfe4cc..ee3b17ad20 100644 --- a/talpid-core/Cargo.toml +++ b/talpid-core/Cargo.toml @@ -33,8 +33,10 @@ nix = "0.12" [target.'cfg(target_os = "linux")'.dependencies] dbus = "0.6" failure = "0.1" +iproute2 = { git = "https://github.com/mullvad/netlink", branch = "best-effort-nla-parsing" } notify = "4.0" resolv-conf = "0.6.1" +rtnetlink = { git = "https://github.com/mullvad/netlink", branch = "best-effort-nla-parsing" } nftnl = { version = "0.1", features = ["nftnl-1-1-0"] } mnl = { version = "0.1", features = ["mnl-1-0-4"] } which = "2.0" diff --git a/talpid-core/src/offline/linux.rs b/talpid-core/src/offline/linux.rs new file mode 100644 index 0000000000..4b76120fb4 --- /dev/null +++ b/talpid-core/src/offline/linux.rs @@ -0,0 +1,73 @@ +extern crate iproute2; +extern crate rtnetlink; + +use error_chain::ChainedError; +use futures::{future::Either, sync::mpsc::UnboundedSender, Future}; +use log::warn; + +use self::iproute2::Link; +use self::rtnetlink::LinkLayerType; + +use tunnel_state_machine::TunnelCommand; + +error_chain! { + errors { + GetLinksError { + description("Failed to get list of IP links") + } + NetlinkConnectionError { + description("Failed to connect to netlink socket") + } + NetlinkError { + description("Error while communicating on the netlink socket") + } + NetlinkDisconnected { + description("Netlink connection has unexpectedly disconnected") + } + } +} + +pub struct MonitorHandle; + +pub fn spawn_monitor(_sender: UnboundedSender<TunnelCommand>) -> Result<MonitorHandle> { + Ok(MonitorHandle) +} + +pub fn is_offline() -> bool { + check_if_offline().unwrap_or_else(|error| { + let chained_error = error.chain_err(|| "Failed to check for internet connection"); + warn!("{}", chained_error.display_chain()); + false + }) +} + +fn check_if_offline() -> Result<bool> { + Ok(list_links_providing_connectivity()?.next().is_none()) +} + +fn list_links_providing_connectivity() -> Result<impl Iterator<Item = Link>> { + Ok(list_links()?.into_iter().filter(link_provides_connectivity)) +} + +fn link_provides_connectivity(link: &Link) -> bool { + // Some tunnels have the link layer type set to None + link.link_layer_type() != LinkLayerType::Loopback + && link.link_layer_type() != LinkLayerType::None + && link.flags().is_running() +} + +fn list_links() -> Result<Vec<Link>> { + let (connection, connection_handle) = + iproute2::new_connection().chain_err(|| ErrorKind::NetlinkConnectionError)?; + let links_request = connection_handle.link().get().execute(); + + match connection.select2(links_request).wait() { + Ok(Either::A(_)) => bail!(ErrorKind::NetlinkDisconnected), + Ok(Either::B((links, _))) => Ok(links), + Err(Either::A((error, _))) => Err(Error::with_chain(error, ErrorKind::NetlinkError)), + Err(Either::B((error, _))) => Err(Error::with_chain( + failure::Fail::compat(error), + ErrorKind::GetLinksError, + )), + } +} diff --git a/talpid-core/src/offline/mod.rs b/talpid-core/src/offline/mod.rs index 38ebc3fb1e..e73de2efc1 100644 --- a/talpid-core/src/offline/mod.rs +++ b/talpid-core/src/offline/mod.rs @@ -9,7 +9,11 @@ mod imp; #[path = "windows.rs"] mod imp; -#[cfg(not(any(windows, target_os = "macos")))] +#[cfg(target_os = "linux")] +#[path = "linux.rs"] +mod imp; + +#[cfg(not(any(windows, target_os = "linux", target_os = "macos")))] #[path = "dummy.rs"] mod imp; |
