summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock15
-rw-r--r--mullvad-daemon/src/management_interface.rs2
-rw-r--r--talpid-core/Cargo.toml1
-rw-r--r--talpid-core/src/dns/linux/mod.rs41
-rw-r--r--talpid-core/src/dns/linux/network_manager.rs48
-rw-r--r--talpid-core/src/dns/linux/resolvconf.rs58
-rw-r--r--talpid-core/src/dns/linux/systemd_resolved.rs172
-rw-r--r--talpid-core/src/dns/macos.rs45
-rw-r--r--talpid-core/src/lib.rs17
-rw-r--r--talpid-core/src/tunnel/openvpn.rs2
-rw-r--r--talpid-core/src/tunnel/wireguard/config.rs39
-rw-r--r--talpid-core/src/tunnel/wireguard/ping_monitor.rs39
-rw-r--r--talpid-core/src/winnet.rs52
-rw-r--r--talpid-ipc/Cargo.toml2
-rw-r--r--talpid-ipc/src/lib.rs43
15 files changed, 306 insertions, 270 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 76061d1a26..e4fac23be8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -306,6 +306,17 @@ dependencies = [
]
[[package]]
+name = "derive_more"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "digest"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1970,6 +1981,7 @@ version = "0.1.0"
dependencies = [
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"dbus 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "derive_more 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"duct 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"err-derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2015,7 +2027,7 @@ version = "0.1.0"
dependencies = [
"assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "err-derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-client-core 0.5.0 (git+https://github.com/mullvad/jsonrpc-client-rs?rev=68aac55b)",
"jsonrpc-client-ipc 0.5.0 (git+https://github.com/mullvad/jsonrpc-client-rs?rev=68aac55b)",
@@ -2633,6 +2645,7 @@ dependencies = [
"checksum derive-try-from-primitive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81dbd65eb15734b6d50dc6ac86f14f928462be0a5df6bda17761e909071ede5d"
"checksum derive_builder 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c998e6ab02a828dd9735c18f154e14100e674ed08cb4e1938f0e4177543f439"
"checksum derive_builder_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "735e24ee9e5fa8e16b86da5007856e97d592e11867e45d76e0c0d0a164a0b757"
+"checksum derive_more 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fbe9f11be34f800b3ecaaed0ec9ec2e015d1d0ba0c8644c1310f73d6e8994615"
"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c"
"checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901"
"checksum duct 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3640af123c78bedc20c1d3928e43cc0621e57011899d1ef917900c12fdb7a1ee"
diff --git a/mullvad-daemon/src/management_interface.rs b/mullvad-daemon/src/management_interface.rs
index a6bc12f8b8..22337d3b3c 100644
--- a/mullvad-daemon/src/management_interface.rs
+++ b/mullvad-daemon/src/management_interface.rs
@@ -231,7 +231,7 @@ pub struct ManagementInterfaceServer {
}
impl ManagementInterfaceServer {
- pub fn start<T>(tunnel_tx: IntoSender<ManagementCommand, T>) -> talpid_ipc::Result<Self>
+ pub fn start<T>(tunnel_tx: IntoSender<ManagementCommand, T>) -> Result<Self, talpid_ipc::Error>
where
T: From<ManagementCommand> + 'static + Send,
{
diff --git a/talpid-core/Cargo.toml b/talpid-core/Cargo.toml
index d7116a7457..1d2e0f5276 100644
--- a/talpid-core/Cargo.toml
+++ b/talpid-core/Cargo.toml
@@ -8,6 +8,7 @@ edition = "2018"
[dependencies]
atty = "0.2"
+derive_more = "0.14"
duct = "0.12"
error-chain = "0.12"
err-derive = "0.1.5"
diff --git a/talpid-core/src/dns/linux/mod.rs b/talpid-core/src/dns/linux/mod.rs
index 17ec6b7e39..5f378875f4 100644
--- a/talpid-core/src/dns/linux/mod.rs
+++ b/talpid-core/src/dns/linux/mod.rs
@@ -12,19 +12,30 @@ use std::{env, fmt, net::IpAddr, path::Path};
const RESOLV_CONF_PATH: &str = "/etc/resolv.conf";
-error_chain! {
- errors {
- NoDnsMonitor {
- description("No suitable DNS monitor implementation detected")
- }
- }
+pub type Result<T> = std::result::Result<T, Error>;
- links {
- Resolvconf(resolvconf::Error, resolvconf::ErrorKind);
- StaticResolvConf(static_resolv_conf::Error, static_resolv_conf::ErrorKind);
- SystemdResolved(systemd_resolved::Error, systemd_resolved::ErrorKind);
- NetworkManager(network_manager::Error, network_manager::ErrorKind);
- }
+/// Errors that can happen in the Linux DNS monitor
+#[derive(err_derive::Error, derive_more::From, Debug)]
+pub enum Error {
+ /// Error in systemd-resolved DNS monitor
+ #[error(display = "Error in systemd-resolved DNS monitor")]
+ SystemdResolved(#[error(cause)] systemd_resolved::Error),
+
+ /// Error in NetworkManager DNS monitor
+ #[error(display = "Error in NetworkManager DNS monitor")]
+ NetworkManager(#[error(cause)] network_manager::Error),
+
+ /// Error in resolvconf DNS monitor
+ #[error(display = "Error in resolvconf DNS monitor")]
+ Resolvconf(#[error(cause)] resolvconf::Error),
+
+ /// Error in static /etc/resolv.conf DNS monitor
+ #[error(display = "Error in static /etc/resolv.conf DNS monitor")]
+ StaticResolvConf(#[error(cause)] static_resolv_conf::Error),
+
+ /// No suitable DNS monitor implementation detected
+ #[error(display = "No suitable DNS monitor implementation detected")]
+ NoDnsMonitor,
}
pub struct DnsMonitor {
@@ -56,10 +67,10 @@ impl super::DnsMonitorT for DnsMonitor {
}
pub enum DnsMonitorHolder {
- Resolvconf(Resolvconf),
- StaticResolvConf(StaticResolvConf),
SystemdResolved(SystemdResolved),
NetworkManager(NetworkManager),
+ Resolvconf(Resolvconf),
+ StaticResolvConf(StaticResolvConf),
}
impl fmt::Display for DnsMonitorHolder {
@@ -96,7 +107,7 @@ impl DnsMonitorHolder {
.or_else(|_| NetworkManager::new().map(DnsMonitorHolder::NetworkManager))
.or_else(|_| Resolvconf::new().map(DnsMonitorHolder::Resolvconf))
.or_else(|_| StaticResolvConf::new().map(DnsMonitorHolder::StaticResolvConf))
- .chain_err(|| ErrorKind::NoDnsMonitor)
+ .map_err(|_| Error::NoDnsMonitor)
}
fn set(&mut self, interface: &str, servers: &[IpAddr]) -> Result<()> {
diff --git a/talpid-core/src/dns/linux/network_manager.rs b/talpid-core/src/dns/linux/network_manager.rs
index d42bb4efab..46777e8223 100644
--- a/talpid-core/src/dns/linux/network_manager.rs
+++ b/talpid-core/src/dns/linux/network_manager.rs
@@ -3,7 +3,6 @@ use dbus::{
stdintf::*,
BusType,
};
-use error_chain::ChainedError;
use std::{
collections::HashMap,
fs::File,
@@ -12,22 +11,21 @@ use std::{
path::Path,
};
-error_chain! {
- errors {
- NoNetworkManager {
- description("NetworkManager not detected")
- }
- NmTooOld {
- description("NetworkManager is too old")
- }
- NmNotManagingDns{
- description("NetworkManager is not managing DNS")
- }
- }
+pub type Result<T> = std::result::Result<T, Error>;
- foreign_links {
- DbusError(dbus::Error);
- }
+#[derive(err_derive::Error, Debug)]
+pub enum Error {
+ #[error(display = "NetworkManager not detected")]
+ NetworkManagerNotDetected(#[error(cause)] dbus::Error),
+
+ #[error(display = "NetworkManager is too old")]
+ TooOldNetworkManager(#[error(cause)] dbus::Error),
+
+ #[error(display = "NetworkManager is not managing DNS")]
+ NetworkManagerNotManagingDns,
+
+ #[error(display = "Error while communicating over Dbus")]
+ Dbus(#[error(cause)] dbus::Error),
}
const NM_BUS: &str = "org.freedesktop.NetworkManager";
@@ -46,7 +44,8 @@ pub struct NetworkManager {
impl NetworkManager {
pub fn new() -> Result<Self> {
- let dbus_connection = dbus::Connection::get_private(BusType::System)?;
+ let dbus_connection =
+ dbus::Connection::get_private(BusType::System).map_err(Error::Dbus)?;
let manager = NetworkManager { dbus_connection };
manager.ensure_network_manager_exists()?;
manager.ensure_resolv_conf_is_managed()?;
@@ -57,7 +56,7 @@ impl NetworkManager {
let _: Box<RefArg> = self
.as_manager()
.get(&NM_TOP_OBJECT, GLOBAL_DNS_CONF_KEY)
- .chain_err(|| ErrorKind::NoNetworkManager)?;
+ .map_err(Error::NetworkManagerNotDetected)?;
Ok(())
}
@@ -67,16 +66,13 @@ impl NetworkManager {
.dbus_connection
.with_path(NM_BUS, NM_DNS_MANAGER_PATH, RPC_TIMEOUT_MS)
.get(NM_DNS_MANAGER, RC_MANAGEMENT_MODE_KEY)
- .chain_err(|| ErrorKind::NmTooOld);
+ .map_err(Error::TooOldNetworkManager);
match management_mode {
- Err(e) => {
- log::debug!("Failed to get NM management mode - {}", e.display_chain());
- return Err(e);
- }
+ Err(e) => return Err(e),
Ok(management_mode) => {
if management_mode == "unmanaged" {
- return Err(Error::from(ErrorKind::NmNotManagingDns));
+ return Err(Error::NetworkManagerNotManagingDns);
}
}
}
@@ -85,7 +81,7 @@ impl NetworkManager {
let actual_resolv_conf = "/etc/resolv.conf";
if !eq_file_content(&expected_resolv_conf, &actual_resolv_conf) {
log::debug!("/etc/resolv.conf differs from reference resolv.conf, therefore NM is not managing DNS");
- bail!(ErrorKind::NmNotManagingDns);
+ return Err(Error::NetworkManagerNotManagingDns);
}
Ok(())
@@ -103,7 +99,7 @@ impl NetworkManager {
fn set_global_dns(&mut self, config: GlobalDnsConfig) -> Result<()> {
self.as_manager()
.set(NM_TOP_OBJECT, GLOBAL_DNS_CONF_KEY, config)
- .map_err(|e| e.into())
+ .map_err(Error::Dbus)
}
pub fn reset(&mut self) -> Result<()> {
diff --git a/talpid-core/src/dns/linux/resolvconf.rs b/talpid-core/src/dns/linux/resolvconf.rs
index 32b8fcd6b9..14ce3107a1 100644
--- a/talpid-core/src/dns/linux/resolvconf.rs
+++ b/talpid-core/src/dns/linux/resolvconf.rs
@@ -1,31 +1,30 @@
use std::{
collections::HashSet,
ffi::OsStr,
- fs,
+ fs, io,
net::IpAddr,
path::{Path, PathBuf},
};
use which::which;
-error_chain! {
- errors {
- NoResolvconf {
- description("Failed to detect 'resolvconf' program")
- }
- ResolvconfUsesResolved {
- description("The existing resolvconf binary is just a symlink to systemd-resolved")
- }
- RunResolvconf {
- description("Failed to execute 'resolvconf' program")
- }
- AddRecordError(stderr: String) {
- description("Using 'resolvconf' to add a record failed")
- display("Using 'resolvconf' to add a record failed: {}", stderr)
- }
- DeleteRecordError {
- description("Using 'resolvconf' to delete a record failed")
- }
- }
+pub type Result<T> = std::result::Result<T, Error>;
+
+#[derive(err_derive::Error, Debug)]
+pub enum Error {
+ #[error(display = "Failed to detect 'resolvconf' program")]
+ NoResolvconf,
+
+ #[error(display = "The resolvconf in PATH is just a symlink to systemd-resolved")]
+ ResolvconfUsesResolved,
+
+ #[error(display = "Failed to execute 'resolvconf' program")]
+ RunResolvconf(#[error(cause)] io::Error),
+
+ #[error(display = "Using 'resolvconf' to add a record failed: {}", stderr)]
+ AddRecordError { stderr: String },
+
+ #[error(display = "Using 'resolvconf' to delete a record failed")]
+ DeleteRecordError,
}
pub struct Resolvconf {
@@ -35,10 +34,9 @@ pub struct Resolvconf {
impl Resolvconf {
pub fn new() -> Result<Self> {
- let resolvconf_path =
- which("resolvconf").map_err(|_| Error::from(ErrorKind::NoResolvconf))?;
+ let resolvconf_path = which("resolvconf").map_err(|_| Error::NoResolvconf)?;
if Self::resolvconf_is_resolved_symlink(&resolvconf_path) {
- bail!(ErrorKind::ResolvconfUsesResolved);
+ return Err(Error::ResolvconfUsesResolved);
}
Ok(Resolvconf {
record_names: HashSet::new(),
@@ -69,12 +67,12 @@ impl Resolvconf {
.stderr_capture()
.unchecked()
.run()
- .chain_err(|| ErrorKind::RunResolvconf)?;
+ .map_err(Error::RunResolvconf)?;
- ensure!(
- output.status.success(),
- ErrorKind::AddRecordError(String::from_utf8_lossy(&output.stderr).to_string())
- );
+ if !output.status.success() {
+ let stderr = String::from_utf8_lossy(&output.stderr).to_string();
+ return Err(Error::AddRecordError { stderr });
+ }
self.record_names.insert(record_name);
@@ -89,7 +87,7 @@ impl Resolvconf {
.stderr_capture()
.unchecked()
.run()
- .chain_err(|| ErrorKind::RunResolvconf)?;
+ .map_err(Error::RunResolvconf)?;
if !output.status.success() {
log::error!(
@@ -97,7 +95,7 @@ impl Resolvconf {
record_name,
String::from_utf8_lossy(&output.stderr)
);
- result = Err(Error::from(ErrorKind::DeleteRecordError));
+ result = Err(Error::DeleteRecordError);
}
}
diff --git a/talpid-core/src/dns/linux/systemd_resolved.rs b/talpid-core/src/dns/linux/systemd_resolved.rs
index 6734a1819c..f8d0df11af 100644
--- a/talpid-core/src/dns/linux/systemd_resolved.rs
+++ b/talpid-core/src/dns/linux/systemd_resolved.rs
@@ -1,46 +1,56 @@
use super::RESOLV_CONF_PATH;
-use crate::linux::iface_index;
+use crate::{linux::iface_index, ErrorExt as _};
use dbus::{
arg::RefArg, stdintf::*, BusType, Interface, Member, Message, MessageItem, MessageItemArray,
Signature,
};
-use error_chain::ChainedError;
use lazy_static::lazy_static;
use libc::{AF_INET, AF_INET6};
use std::{
- fs,
+ fs, io,
net::{IpAddr, Ipv4Addr},
path::Path,
};
+pub type Result<T> = std::result::Result<T, Error>;
-error_chain! {
- errors {
- NoSystemdResolved {
- description("Systemd resolved not detected")
- }
- InvalidInterfaceName {
- description("Invalid network interface name")
- }
- DbusRpcError {
- description("Failed to perform RPC call on DBus")
- }
- GetLinkError {
- description("Failed to find link interface in resolved manager")
- }
- SetDnsError {
- description("Failed to configure DNS servers")
- }
- SetDomainsError {
- description("Failed to configure DNS domains")
- }
- RevertDnsError {
- description("Failed to revert DNS configuration")
- }
- DBusError {
- description("Failed to initialize a connection to dbus")
- }
- }
+#[derive(err_derive::Error, Debug)]
+pub enum Error {
+ #[error(display = "Failed to initialize a connection to D-Bus")]
+ ConnectDBus(#[error(cause)] dbus::Error),
+
+ #[error(display = "/etc/resolv.conf is not a symlink to Systemd resolved")]
+ NotSymlinkedToResolvConf,
+
+ #[error(display = "Systemd resolved DNS 127.0.0.53, is not currently configured")]
+ NoDnsPointsToResolved,
+
+ #[error(display = "Systemd resolved not detected")]
+ NoSystemdResolved(#[error(cause)] dbus::Error),
+
+ #[error(display = "Failed to read Systemd resolved's resolv.conf")]
+ ReadResolvConfFailed(#[error(cause)] io::Error),
+
+ #[error(display = "Failed to parse Systemd resolved's resolv.conf")]
+ ParseResolvConfFailed(#[error(cause)] resolv_conf::ParseError),
+
+ #[error(display = "Invalid network interface name")]
+ InvalidInterfaceName(#[error(cause)] crate::linux::IfaceIndexLookupError),
+
+ #[error(display = "Failed to find link interface in resolved manager")]
+ GetLinkError(#[error(cause)] Box<Error>),
+
+ #[error(display = "Failed to configure DNS domains")]
+ SetDomainsError(#[error(cause)] dbus::Error),
+
+ #[error(display = "Failed to revert DNS settings of interface: {}", _0)]
+ RevertDnsError(String, #[error(cause)] dbus::Error),
+
+ #[error(display = "Failed to perform RPC call on D-Bus")]
+ DBusRpcError(#[error(cause)] dbus::Error),
+
+ #[error(display = "Failed to match the returned D-Bus object with expected type")]
+ MatchDBusTypeError(#[error(cause)] dbus::arg::TypeMismatchError),
}
const DYNAMIC_RESOLV_CONF_PATH: &str = "/run/systemd/resolve/resolv.conf";
@@ -68,14 +78,15 @@ pub struct SystemdResolved {
impl SystemdResolved {
pub fn new() -> Result<Self> {
let dbus_connection =
- dbus::Connection::get_private(BusType::System).chain_err(|| ErrorKind::DBusError)?;
+ dbus::Connection::get_private(BusType::System).map_err(Error::ConnectDBus)?;
let systemd_resolved = SystemdResolved {
dbus_connection,
interface_link: None,
};
- SystemdResolved::ensure_resolved_is_active()?;
systemd_resolved.ensure_resolved_exists()?;
+ Self::ensure_resolv_conf_is_resolved_symlink()?;
+ Self::ensure_resolv_conf_has_resolved_dns()?;
Ok(systemd_resolved)
}
@@ -84,38 +95,39 @@ impl SystemdResolved {
let _: Box<RefArg> = self
.as_manager_object()
.get(&MANAGER_INTERFACE, "DNS")
- .chain_err(|| ErrorKind::NoSystemdResolved)?;
-
- Ok(())
- }
-
- fn ensure_resolved_is_active() -> Result<()> {
- ensure!(
- Self::resolv_conf_is_resolved_symlink() || Self::resolv_conf_has_resolved_dns()?,
- ErrorKind::NoSystemdResolved
- );
+ .map_err(Error::NoSystemdResolved)?;
Ok(())
}
- fn resolv_conf_is_resolved_symlink() -> bool {
- fs::read_link(RESOLV_CONF_PATH)
+ fn ensure_resolv_conf_is_resolved_symlink() -> Result<()> {
+ let is_correct_symlink = fs::read_link(RESOLV_CONF_PATH)
.map(|resolv_conf_target| resolv_conf_target == Path::new(DYNAMIC_RESOLV_CONF_PATH))
- .unwrap_or_else(|_| false)
+ .unwrap_or_else(|_| false);
+ if is_correct_symlink {
+ Ok(())
+ } else {
+ Err(Error::NotSymlinkedToResolvConf)
+ }
}
- fn resolv_conf_has_resolved_dns() -> Result<bool> {
+ fn ensure_resolv_conf_has_resolved_dns() -> Result<()> {
let resolv_conf_contents =
- fs::read_to_string(RESOLV_CONF_PATH).chain_err(|| ErrorKind::NoSystemdResolved)?;
+ fs::read_to_string(RESOLV_CONF_PATH).map_err(Error::ReadResolvConfFailed)?;
let parsed_resolv_conf = resolv_conf::Config::parse(resolv_conf_contents)
- .chain_err(|| ErrorKind::NoSystemdResolved)?;
+ .map_err(Error::ParseResolvConfFailed)?;
let resolved_dns_server =
resolv_conf::ScopedIp::V4(Ipv4Addr::from(RESOLVED_DNS_SERVER_ADDRESS));
- Ok(parsed_resolv_conf
+ if parsed_resolv_conf
.nameservers
.into_iter()
- .any(|nameserver| nameserver == resolved_dns_server))
+ .any(|nameserver| nameserver == resolved_dns_server)
+ {
+ Ok(())
+ } else {
+ Err(Error::NoDnsPointsToResolved)
+ }
}
fn as_manager_object(&self) -> dbus::ConnPath<&dbus::Connection> {
@@ -132,7 +144,9 @@ impl SystemdResolved {
}
pub fn set_dns(&mut self, interface_name: &str, servers: &[IpAddr]) -> Result<()> {
- let link_object_path = self.fetch_link(interface_name)?;
+ let link_object_path = self
+ .fetch_link(interface_name)
+ .map_err(|e| Error::GetLinkError(Box::new(e)))?;
if let Err(e) = self.reset() {
log::debug!(
"Failed to reset previous DNS settings - {}",
@@ -147,19 +161,19 @@ impl SystemdResolved {
}
fn fetch_link(&self, interface_name: &str) -> Result<dbus::Path<'static>> {
- let interface_index =
- iface_index(interface_name).chain_err(|| ErrorKind::InvalidInterfaceName)?;
+ let interface_index = iface_index(interface_name).map_err(Error::InvalidInterfaceName)?;
let mut reply = self
.as_manager_object()
.method_call_with_args(&MANAGER_INTERFACE, &GET_LINK_METHOD, |message| {
message.append_items(&[MessageItem::Int32(interface_index as i32)]);
})
- .chain_err(|| ErrorKind::DbusRpcError)?;
-
- let result = reply.as_result().chain_err(|| ErrorKind::GetLinkError)?;
-
- result.read1().chain_err(|| ErrorKind::GetLinkError)
+ .map_err(Error::DBusRpcError)?;
+ reply
+ .as_result()
+ .map_err(Error::DBusRpcError)?
+ .read1()
+ .map_err(Error::MatchDBusTypeError)
}
fn set_link_dns<'a, 'b: 'a>(
@@ -168,18 +182,12 @@ impl SystemdResolved {
servers: &[IpAddr],
) -> Result<()> {
let server_addresses = build_addresses_argument(servers);
-
- let mut reply = self
- .as_link_object(link_object_path.clone())
+ self.as_link_object(link_object_path.clone())
.method_call_with_args(&LINK_INTERFACE, &SET_DNS_METHOD, |message| {
message.append_items(&[server_addresses]);
})
- .chain_err(|| ErrorKind::DbusRpcError)?;
-
- reply
- .as_result()
- .map(|_| ())
- .chain_err(|| ErrorKind::SetDnsError)?;
+ .and_then(|mut reply| reply.as_result().map(|_| ()))
+ .map_err(Error::DBusRpcError)?;
// set the search domain to catch all DNS requests, forces the link to be the prefered
// resolver, otherwise systemd-resolved will use other interfaces to do DNS lookups
@@ -194,43 +202,31 @@ impl SystemdResolved {
.expect("failed to construct a new dbus message")
.append1(dns_domains);
- let mut reply = self
- .dbus_connection
+ self.dbus_connection
.send_with_reply_and_block(msg, RPC_TIMEOUT_MS)
- .chain_err(|| ErrorKind::SetDomainsError)?;
- reply
- .as_result()
- .map(|_| ())
- .chain_err(|| ErrorKind::SetDomainsError)
+ .and_then(|mut reply| reply.as_result().map(|_| ()))
+ .map_err(Error::SetDomainsError)
}
pub fn reset(&mut self) -> Result<()> {
if let Some((interface_name, link_object_path)) = self.interface_link.take() {
self.revert_link(link_object_path, &interface_name)
- .chain_err(|| {
- format!(
- "Failed to revert DNS settings of interface: {}",
- interface_name
- )
- })?;
+ .map_err(|e| Error::RevertDnsError(interface_name.to_owned(), e))
} else {
log::trace!("No DNS settings to reset");
- };
- Ok(())
+ Ok(())
+ }
}
fn revert_link(
&mut self,
link_object_path: dbus::Path<'static>,
interface_name: &str,
- ) -> Result<()> {
+ ) -> std::result::Result<(), dbus::Error> {
let link = self.as_link_object(link_object_path);
match link.method_call_with_args(&LINK_INTERFACE, &REVERT_METHOD, |_| {}) {
- Ok(mut reply) => reply
- .as_result()
- .map(|_| ())
- .chain_err(|| ErrorKind::RevertDnsError),
+ Ok(mut reply) => reply.as_result().map(|_| ()),
Err(error) => {
if error.name() == Some("org.freedesktop.DBus.Error.UnknownObject") {
log::info!(
@@ -239,7 +235,7 @@ impl SystemdResolved {
);
Ok(())
} else {
- Err(error).chain_err(|| ErrorKind::DbusRpcError)
+ Err(error)
}
}
}
diff --git a/talpid-core/src/dns/macos.rs b/talpid-core/src/dns/macos.rs
index 3dfc8d2be4..4c735e9e44 100644
--- a/talpid-core/src/dns/macos.rs
+++ b/talpid-core/src/dns/macos.rs
@@ -1,4 +1,3 @@
-use error_chain::ChainedError;
use log::{debug, trace};
use parking_lot::Mutex;
use std::{
@@ -22,11 +21,18 @@ use system_configuration::{
sys::schema_definitions::kSCPropNetDNSServerAddresses,
};
-error_chain! {
- errors {
- SettingDnsFailed { description("Error while setting DNS servers") }
- DynamicStoreInitError { description("Failed to initialize dynamic store") }
- }
+pub type Result<T> = std::result::Result<T, Error>;
+
+/// Errors that can happen when setting/monitoring DNS on macOS.
+#[derive(err_derive::Error, Debug)]
+pub enum Error {
+ /// Error while setting DNS servers
+ #[error(display = "Error while setting DNS servers")]
+ SettingDnsFailed,
+
+ /// Failed to initialize dynamic store
+ #[error(display = "Failed to initialize dynamic store")]
+ DynamicStoreInitError,
}
const STATE_PATH_PATTERN: &str = "State:/Network/Service/.*/DNS";
@@ -88,7 +94,7 @@ impl DnsSettings {
if store.set(path, self.0.clone()) {
Ok(())
} else {
- bail!(ErrorKind::SettingDnsFailed)
+ Err(Error::SettingDnsFailed)
}
}
@@ -187,7 +193,7 @@ impl super::DnsMonitorT for DnsMonitor {
} else {
debug!("Removing DNS for {}", service_path);
if !self.store.remove(CFString::new(&service_path)) {
- bail!(ErrorKind::SettingDnsFailed);
+ return Err(Error::SettingDnsFailed);
}
}
}
@@ -235,7 +241,7 @@ fn create_dynamic_store(state: Arc<Mutex<Option<State>>>) -> Result<SCDynamicSto
trace!("Registered for dynamic store notifications");
Ok(store)
} else {
- bail!(ErrorKind::DynamicStoreInitError)
+ Err(Error::DynamicStoreInitError)
}
}
@@ -260,9 +266,7 @@ fn dns_change_callback(
trace!("Not injecting DNS at this time");
}
Some(ref mut state) => {
- if let Err(e) = dns_change_callback_internal(store, changed_keys, state) {
- log::error!("{}", e.display_chain());
- }
+ dns_change_callback_internal(store, changed_keys, state);
}
}
}
@@ -271,7 +275,7 @@ fn dns_change_callback_internal(
store: SCDynamicStore,
changed_keys: CFArray<CFString>,
state: &mut State,
-) -> Result<()> {
+) {
for path in &changed_keys {
let should_set_dns = match DnsSettings::load(&store, path.clone()) {
None => {
@@ -291,10 +295,9 @@ fn dns_change_callback_internal(
}
};
if should_set_dns {
- state
- .dns_settings
- .save(&store, path.clone())
- .chain_err(|| format!("Failed changing DNS for {}", *path))?;
+ if let Err(e) = state.dns_settings.save(&store, path.clone()) {
+ log::error!("Failed changing DNS for {}: {}", *path, e);
+ }
// If we changed a "state" entry, also set the corresponding "setup" entry.
if let Some(setup_path_str) = state_to_setup_path(&path.to_string()) {
let setup_path = CFString::new(&setup_path_str);
@@ -304,14 +307,12 @@ fn dns_change_callback_internal(
DnsSettings::load(&store, setup_path.clone()),
);
}
- state
- .dns_settings
- .save(&store, setup_path.clone())
- .chain_err(|| format!("Failed changing DNS for {}", setup_path))?;
+ if let Err(e) = state.dns_settings.save(&store, setup_path.clone()) {
+ log::error!("Failed changing DNS for {}: {}", setup_path, e);
+ }
}
}
}
- Ok(())
}
/// Read all existing DNS settings and return them.
diff --git a/talpid-core/src/lib.rs b/talpid-core/src/lib.rs
index 40f450aa72..1147e40fd6 100644
--- a/talpid-core/src/lib.rs
+++ b/talpid-core/src/lib.rs
@@ -59,3 +59,20 @@ mod mktemp;
/// Misc utilities for the Linux platform.
#[cfg(target_os = "linux")]
mod linux;
+
+
+trait ErrorExt {
+ fn display_chain(&self) -> String;
+}
+
+impl<E: std::error::Error> ErrorExt for E {
+ fn display_chain(&self) -> String {
+ let mut s = format!("Error: {}", self);
+ let mut source = self.source();
+ while let Some(error) = source {
+ s.push_str(&format!("\nCaused by: {}", error));
+ source = error.source();
+ }
+ s
+ }
+}
diff --git a/talpid-core/src/tunnel/openvpn.rs b/talpid-core/src/tunnel/openvpn.rs
index 0d0c4a932f..d3e2b9858f 100644
--- a/talpid-core/src/tunnel/openvpn.rs
+++ b/talpid-core/src/tunnel/openvpn.rs
@@ -569,7 +569,7 @@ mod event_server {
use uuid;
/// Construct and start the IPC server with the given event listener callback.
- pub fn start<L>(on_event: L) -> talpid_ipc::Result<talpid_ipc::IpcServer>
+ pub fn start<L>(on_event: L) -> std::result::Result<talpid_ipc::IpcServer, talpid_ipc::Error>
where
L: Fn(openvpn_plugin::EventType, HashMap<String, String>) + Send + Sync + 'static,
{
diff --git a/talpid-core/src/tunnel/wireguard/config.rs b/talpid-core/src/tunnel/wireguard/config.rs
index 97d7832a60..63c99dfdce 100644
--- a/talpid-core/src/tunnel/wireguard/config.rs
+++ b/talpid-core/src/tunnel/wireguard/config.rs
@@ -17,24 +17,20 @@ pub struct Config {
const SMALLEST_IPV6_MTU: u16 = 1420;
const DEFAULT_MTU: u16 = SMALLEST_IPV6_MTU;
-error_chain! {
- errors {
- InvalidTunnelIpError {
- description("No valid tunnel IP"),
- }
+#[derive(err_derive::Error, Debug)]
+pub enum Error {
+ #[error(display = "No valid tunnel IP")]
+ InvalidTunnelIpError,
- InvalidPeerIpError {
- description("Supplied peer has no valid IPs")
- }
+ #[error(display = "Supplied peer has no valid IPs")]
+ InvalidPeerIpError,
- NoPeersSuppliedError{
- description("No peers supplied")
- }
- }
+ #[error(display = "No peers supplied")]
+ NoPeersSuppliedError,
}
impl Config {
- pub fn from_parameters(params: &wireguard::TunnelParameters) -> Result<Config> {
+ pub fn from_parameters(params: &wireguard::TunnelParameters) -> Result<Config, Error> {
let tunnel = params.connection.tunnel.clone();
let peer = vec![params.connection.peer.clone()];
Self::new(
@@ -52,8 +48,10 @@ impl Config {
connection_config: &wireguard::ConnectionConfig,
wg_options: &wireguard::TunnelOptions,
generic_options: &GenericTunnelOptions,
- ) -> Result<Config> {
- ensure!(!peers.is_empty(), ErrorKind::NoPeersSuppliedError);
+ ) -> Result<Config, Error> {
+ if peers.is_empty() {
+ return Err(Error::NoPeersSuppliedError);
+ }
let mtu = wg_options.mtu.unwrap_or(DEFAULT_MTU);
let is_ipv6_enabled = mtu >= SMALLEST_IPV6_MTU && generic_options.enable_ipv6;
@@ -64,7 +62,9 @@ impl Config {
.cloned()
.filter(|ip| ip.is_ipv4() || is_ipv6_enabled)
.collect();
- ensure!(!peer.allowed_ips.is_empty(), ErrorKind::InvalidPeerIpError);
+ if peer.allowed_ips.is_empty() {
+ return Err(Error::InvalidPeerIpError);
+ }
}
tunnel.addresses = tunnel
@@ -72,10 +72,9 @@ impl Config {
.into_iter()
.filter(|ip| ip.is_ipv4() || is_ipv6_enabled)
.collect();
- ensure!(
- !tunnel.addresses.is_empty(),
- ErrorKind::InvalidTunnelIpError
- );
+ if tunnel.addresses.is_empty() {
+ return Err(Error::InvalidTunnelIpError);
+ }
Ok(Config {
tunnel,
diff --git a/talpid-core/src/tunnel/wireguard/ping_monitor.rs b/talpid-core/src/tunnel/wireguard/ping_monitor.rs
index d471971ca6..69f22fc83f 100644
--- a/talpid-core/src/tunnel/wireguard/ping_monitor.rs
+++ b/talpid-core/src/tunnel/wireguard/ping_monitor.rs
@@ -1,23 +1,25 @@
-use std::{net::IpAddr, thread, time};
+use std::{
+ io,
+ net::IpAddr,
+ thread,
+ time::{Duration, Instant},
+};
-error_chain! {
- errors {
- PingError{
- description("Failed to run ping")
- }
+#[derive(err_derive::Error, Debug)]
+pub enum Error {
+ #[error(display = "Failed to run ping command")]
+ PingError(#[error(cause)] io::Error),
- TimeoutError {
- description("Ping timed out")
- }
- }
+ #[error(display = "Ping timed out")]
+ TimeoutError,
}
-pub fn monitor_ping(ip: IpAddr, timeout_secs: u16, interface: &str) -> Result<()> {
+pub fn monitor_ping(ip: IpAddr, timeout_secs: u16, interface: &str) -> Result<(), Error> {
loop {
- let start = time::Instant::now();
+ let start = Instant::now();
ping(ip, timeout_secs, &interface, false)?;
if let Some(remaining) =
- time::Duration::from_secs(timeout_secs.into()).checked_sub(start.elapsed())
+ Duration::from_secs(timeout_secs.into()).checked_sub(start.elapsed())
{
thread::sleep(remaining);
}
@@ -29,14 +31,15 @@ pub fn ping(
timeout_secs: u16,
interface: &str,
exit_on_first_reply: bool,
-) -> Result<()> {
+) -> Result<(), Error> {
let output = ping_cmd(ip, timeout_secs, interface, exit_on_first_reply)
.run()
- .chain_err(|| ErrorKind::PingError)?;
- if !output.status.success() {
- bail!(ErrorKind::TimeoutError);
+ .map_err(Error::PingError)?;
+ if output.status.success() {
+ Ok(())
+ } else {
+ Err(Error::TimeoutError)
}
- Ok(())
}
fn ping_cmd(
diff --git a/talpid-core/src/winnet.rs b/talpid-core/src/winnet.rs
index f6a932acfb..1211cd7545 100644
--- a/talpid-core/src/winnet.rs
+++ b/talpid-core/src/winnet.rs
@@ -3,19 +3,17 @@ use std::ptr;
use libc::{c_char, c_void, wchar_t};
use widestring::WideCString;
-error_chain! {
- errors{
- /// Failure to set metrics of network interfaces
- MetricApplication{
- description("Failed to set the metrics for a network interface")
- }
- InvalidInterfaceAlias{
- description("Supplied interface alias is invalid")
- }
- GetIpv6Status {
- description("Failed to read IPv6 status on the TAP network interface")
- }
- }
+#[derive(err_derive::Error, Debug)]
+pub enum Error {
+ /// Failure to set metrics of network interfaces
+ #[error(display = "Failed to set the metrics for a network interface")]
+ MetricApplication,
+
+ #[error(display = "Supplied interface alias is invalid")]
+ InvalidInterfaceAlias(#[error(cause)] widestring::NulError<u16>),
+
+ #[error(display = "Failed to read IPv6 status on the TAP network interface")]
+ GetIpv6Status,
}
pub type ErrorSink = extern "system" fn(msg: *const c_char, ctx: *mut c_void);
@@ -30,9 +28,9 @@ pub extern "system" fn error_sink(msg: *const c_char, _ctx: *mut c_void) {
}
/// Returns true if metrics were changed, false otherwise
-pub fn ensure_top_metric_for_interface(interface_alias: &str) -> Result<bool> {
+pub fn ensure_top_metric_for_interface(interface_alias: &str) -> Result<bool, Error> {
let interface_alias_ws =
- WideCString::from_str(interface_alias).chain_err(|| ErrorKind::InvalidInterfaceAlias)?;
+ WideCString::from_str(interface_alias).map_err(Error::InvalidInterfaceAlias)?;
let metric_result = unsafe {
WinRoute_EnsureTopMetric(
@@ -48,11 +46,14 @@ pub fn ensure_top_metric_for_interface(interface_alias: &str) -> Result<bool> {
// Metrics changed
1 => Ok(true),
// Failure
- 2 => Err(Error::from(ErrorKind::MetricApplication)),
+ 2 => Err(Error::MetricApplication),
// Unexpected value
- _ => {
- log::error!("Unexpected return code from WinRoute_EnsureTopMetric");
- Err(Error::from(ErrorKind::MetricApplication))
+ i => {
+ log::error!(
+ "Unexpected return code from WinRoute_EnsureTopMetric: {}",
+ i
+ );
+ Err(Error::MetricApplication)
}
}
}
@@ -68,7 +69,7 @@ extern "system" {
/// Checks if IPv6 is enabled for the TAP interface
-pub fn get_tap_interface_ipv6_status() -> Result<bool> {
+pub fn get_tap_interface_ipv6_status() -> Result<bool, Error> {
let tap_ipv6_status = unsafe { GetTapInterfaceIpv6Status(Some(error_sink), ptr::null_mut()) };
match tap_ipv6_status {
@@ -77,11 +78,14 @@ pub fn get_tap_interface_ipv6_status() -> Result<bool> {
// Disabled
1 => Ok(false),
// Failure
- 2 => Err(Error::from(ErrorKind::GetIpv6Status)),
+ 2 => Err(Error::GetIpv6Status),
// Unexpected value
- _ => {
- log::error!("Unexpected return code from GetTapInterfaceIpv6Status");
- Err(Error::from(ErrorKind::GetIpv6Status))
+ i => {
+ log::error!(
+ "Unexpected return code from GetTapInterfaceIpv6Status: {}",
+ i
+ );
+ Err(Error::GetIpv6Status)
}
}
}
diff --git a/talpid-ipc/Cargo.toml b/talpid-ipc/Cargo.toml
index e813011f37..e0838acfd5 100644
--- a/talpid-ipc/Cargo.toml
+++ b/talpid-ipc/Cargo.toml
@@ -7,7 +7,7 @@ license = "GPL-3.0"
edition = "2018"
[dependencies]
-error-chain = "0.12"
+err-derive = "0.1.5"
serde = "1.0"
serde_json = "1.0"
log = "0.4"
diff --git a/talpid-ipc/src/lib.rs b/talpid-ipc/src/lib.rs
index a84a982aa7..60192712cd 100644
--- a/talpid-ipc/src/lib.rs
+++ b/talpid-ipc/src/lib.rs
@@ -6,14 +6,8 @@
//! GNU General Public License as published by the Free Software Foundation, either version 3 of
//! the License, or (at your option) any later version.
-#![recursion_limit = "128"]
-
-#[macro_use]
-extern crate error_chain;
-
-
use futures::Future;
-use std::thread;
+use std::{io, thread};
use jsonrpc_core::{MetaIoHandler, Metadata};
use jsonrpc_ipc_server::{MetaExtractor, NoopExtractor, SecurityAttributes, Server, ServerBuilder};
@@ -24,16 +18,16 @@ use std::fmt;
/// An Id created by the Ipc server that the client can use to connect to it
pub type IpcServerId = String;
-error_chain! {
- errors {
- IpcServerError {
- description("Error in IPC server")
- }
+#[derive(err_derive::Error, Debug)]
+pub enum Error {
+ #[error(display = "Unable to start IPC server")]
+ StartServerError(#[error(cause)] io::Error),
- PermissionsError {
- description("Unable to set permissions for IPC endpoint")
- }
- }
+ #[error(display = "Error in IPC server")]
+ IpcServerError(#[error(cause)] io::Error),
+
+ #[error(display = "Unable to set permissions for IPC endpoint")]
+ PermissionsError(#[error(cause)] io::Error),
}
@@ -43,7 +37,10 @@ pub struct IpcServer {
}
impl IpcServer {
- pub fn start<M: Metadata + Default>(handler: MetaIoHandler<M>, path: &str) -> Result<Self> {
+ pub fn start<M: Metadata + Default>(
+ handler: MetaIoHandler<M>,
+ path: &str,
+ ) -> Result<Self, Error> {
Self::start_with_metadata(handler, NoopExtractor, path)
}
@@ -51,17 +48,17 @@ impl IpcServer {
handler: MetaIoHandler<M>,
meta_extractor: E,
path: &str,
- ) -> Result<Self>
+ ) -> Result<Self, Error>
where
M: Metadata + Default,
E: MetaExtractor<M>,
{
- let security_attributes = SecurityAttributes::allow_everyone_create()
- .chain_err(|| ErrorKind::PermissionsError)?;
+ let security_attributes =
+ SecurityAttributes::allow_everyone_create().map_err(Error::PermissionsError)?;
let server = ServerBuilder::with_meta_extractor(handler, meta_extractor)
.set_security_attributes(security_attributes)
.start(path)
- .chain_err(|| ErrorKind::IpcServerError)
+ .map_err(Error::StartServerError)
.and_then(|(fut, start, server)| {
thread::spawn(move || tokio::run(fut));
start
@@ -69,7 +66,7 @@ impl IpcServer {
.expect("server panicked")
.map(Err)
.unwrap_or_else(|| Ok(server))
- .chain_err(|| ErrorKind::IpcServerError)
+ .map_err(Error::IpcServerError)
})
.map(|server| IpcServer {
path: path.to_owned(),
@@ -80,7 +77,7 @@ impl IpcServer {
{
use std::{fs, os::unix::fs::PermissionsExt};
fs::set_permissions(&path, PermissionsExt::from_mode(0o766))
- .chain_err(|| ErrorKind::PermissionsError)?;
+ .map_err(Error::PermissionsError)?;
}
Ok(server)
}