summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2018-12-03 16:58:04 -0200
committerJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2018-12-11 10:15:49 -0200
commit8663a6407791d4eba48c804683ece9b6f85db3e0 (patch)
tree6dd09e97eaac5fa33e938aa676e70cef1e7c684a
parentc6a525169b56a04e9eadab888a21cec76ff6110c (diff)
downloadmullvadvpn-8663a6407791d4eba48c804683ece9b6f85db3e0.tar.xz
mullvadvpn-8663a6407791d4eba48c804683ece9b6f85db3e0.zip
Implement `is_offline` for Linux
-rw-r--r--Cargo.lock65
-rw-r--r--talpid-core/Cargo.toml2
-rw-r--r--talpid-core/src/offline/linux.rs73
-rw-r--r--talpid-core/src/offline/mod.rs6
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;