diff options
| author | Linus Färnstrand <linus@mullvad.net> | 2019-04-03 16:57:01 +0200 |
|---|---|---|
| committer | Linus Färnstrand <linus@mullvad.net> | 2019-04-05 16:28:05 +0200 |
| commit | e13bf82221658d0dc0710a11c1cf2306b3999aa8 (patch) | |
| tree | 69d4e1742da823c650fa4bb7083acf03f3432cae | |
| parent | 95eaba22e7cc2f4e7fcf2717258486244e320aa3 (diff) | |
| download | mullvadvpn-e13bf82221658d0dc0710a11c1cf2306b3999aa8.tar.xz mullvadvpn-e13bf82221658d0dc0710a11c1cf2306b3999aa8.zip | |
Remove error-chain from tunnel monitor modules
| -rw-r--r-- | talpid-core/src/routing/mod.rs | 12 | ||||
| -rw-r--r-- | talpid-core/src/tunnel/mod.rs | 65 | ||||
| -rw-r--r-- | talpid-core/src/tunnel/openvpn.rs | 156 | ||||
| -rw-r--r-- | talpid-core/src/tunnel/wireguard/mod.rs | 74 | ||||
| -rw-r--r-- | talpid-core/src/tunnel/wireguard/wireguard_go.rs | 18 | ||||
| -rw-r--r-- | talpid-core/src/tunnel_state_machine/connecting_state.rs | 4 |
6 files changed, 170 insertions, 159 deletions
diff --git a/talpid-core/src/routing/mod.rs b/talpid-core/src/routing/mod.rs index 612c0b2396..b2e299553f 100644 --- a/talpid-core/src/routing/mod.rs +++ b/talpid-core/src/routing/mod.rs @@ -13,6 +13,8 @@ mod imp; #[path = "android.rs"] mod imp; +pub use self::imp::Error; + mod subprocess; /// A single route @@ -53,24 +55,24 @@ pub struct RouteManager { impl RouteManager { /// Creates a new RouteManager. - pub fn new() -> Result<Self, imp::Error> { + pub fn new() -> Result<Self, Error> { Ok(RouteManager { inner: imp::RouteManager::new()?, }) } /// Set routes in the routing table. - pub fn add_routes(&mut self, required_routes: RequiredRoutes) -> Result<(), imp::Error> { + pub fn add_routes(&mut self, required_routes: RequiredRoutes) -> Result<(), Error> { self.inner.add_routes(required_routes) } /// Remove previously set routes from the routing table. - pub fn delete_routes(&mut self) -> Result<(), imp::Error> { + pub fn delete_routes(&mut self) -> Result<(), Error> { self.inner.delete_routes() } /// Retrieves the gateway for the default route. - pub fn get_default_route_node(&mut self) -> Result<std::net::IpAddr, imp::Error> { + pub fn get_default_route_node(&mut self) -> Result<std::net::IpAddr, Error> { // use routing::RoutingT; self.inner.get_default_route_node() } @@ -87,7 +89,7 @@ impl Drop for RouteManager { /// This trait unifies platform specific implementations of route managers pub trait RoutingT: Sized { /// Error type of the implementation - type Error: ::std::error::Error; + type Error: std::error::Error; /// Creates a new router fn new() -> Result<Self, Self::Error>; diff --git a/talpid-core/src/tunnel/mod.rs b/talpid-core/src/tunnel/mod.rs index 04332908c4..7217d6b330 100644 --- a/talpid-core/src/tunnel/mod.rs +++ b/talpid-core/src/tunnel/mod.rs @@ -19,36 +19,36 @@ pub mod wireguard; const OPENVPN_LOG_FILENAME: &str = "openvpn.log"; const WIREGUARD_LOG_FILENAME: &str = "wireguard.log"; +/// Results from operations in the tunnel module. +pub type Result<T> = std::result::Result<T, Error>; -error_chain! { - errors { - /// Tunnel can't have IPv6 enabled because the system has disabled IPv6 support. - EnableIpv6Error { - description("Can't enable IPv6 on tunnel interface because IPv6 is disabled") - } - /// Running on an operating system which is not supported yet. - UnsupportedPlatform { - description("Tunnel type not supported on this operating system") - } - /// Failed to rotate tunnel log file - RotateLogError { - description("Failed to rotate tunnel log file") - } - /// Failure to build Wireguard configuration. - WireguardConfigError { - description("Failed to configure Wireguard with the given parameters") - } - } +/// Errors that can occur in the [`TunnelMonitor`]. +#[derive(err_derive::Error, Debug, derive_more::From)] +pub enum Error { + /// Tunnel can't have IPv6 enabled because the system has disabled IPv6 support. + #[error(display = "Can't enable IPv6 on tunnel interface because IPv6 is disabled")] + EnableIpv6Error, - links { - OpenVpnTunnelMonitoringError(openvpn::Error, openvpn::ErrorKind) - /// There was an error listening for events from the OpenVPN tunnel - ; - WirguardTunnelMonitoringError(wireguard::Error, wireguard::ErrorKind) - /// There was an error listening for events from the OpenVPN tunnel - #[cfg(any(target_os = "linux", target_os = "macos"))] - ; - } + /// Running on an operating system which is not supported yet. + #[error(display = "Tunnel type not supported on this operating system")] + UnsupportedPlatform, + + /// Failed to rotate tunnel log file + #[error(display = "Failed to rotate tunnel log file")] + RotateLogError(#[error(cause)] crate::logging::RotateLogError), + + /// Failure to build Wireguard configuration. + #[error(display = "Failed to configure Wireguard with the given parameters")] + WireguardConfigError(#[error(cause)] self::wireguard::config::Error), + + /// There was an error listening for events from the OpenVPN tunnel + #[error(display = "Failed while listening for events from the OpenVPN tunnel")] + OpenVpnTunnelMonitoringError(#[error(cause)] openvpn::Error), + + /// There was an error listening for events from the Wireguard tunnel + #[cfg(unix)] + #[error(display = "Failed while listening for events from the Wireguard tunnel")] + WirguardTunnelMonitoringError(#[error(cause)] wireguard::Error), } @@ -151,7 +151,7 @@ impl TunnelMonitor { Self::start_wireguard_tunnel(&config, log_file, on_event) } #[cfg(any(windows, target_os = "android"))] - TunnelParameters::Wireguard(_) => bail!(ErrorKind::UnsupportedPlatform), + TunnelParameters::Wireguard(_) => Err(Error::UnsupportedPlatform), } } @@ -164,8 +164,7 @@ impl TunnelMonitor { where L: Fn(TunnelEvent) + Send + Sync + Clone + 'static, { - let config = wireguard::config::Config::from_parameters(¶ms) - .chain_err(|| ErrorKind::WireguardConfigError)?; + let config = wireguard::config::Config::from_parameters(¶ms)?; let monitor = wireguard::WireguardMonitor::start( &config, log.as_ref().map(|p| p.as_path()), @@ -195,7 +194,7 @@ impl TunnelMonitor { fn ensure_ipv6_can_be_used_if_enabled(tunnel_options: &GenericTunnelOptions) -> Result<()> { if tunnel_options.enable_ipv6 && !is_ipv6_enabled_in_os() { - bail!(ErrorKind::EnableIpv6Error); + Err(Error::EnableIpv6Error) } else { Ok(()) } @@ -211,7 +210,7 @@ impl TunnelMonitor { TunnelParameters::Wireguard(_) => WIREGUARD_LOG_FILENAME, }; let tunnel_log = log_dir.join(filename); - logging::rotate_log(&tunnel_log).chain_err(|| ErrorKind::RotateLogError)?; + logging::rotate_log(&tunnel_log)?; Ok(Some(tunnel_log)) } else { Ok(None) diff --git a/talpid-core/src/tunnel/openvpn.rs b/talpid-core/src/tunnel/openvpn.rs index 8e0de74430..d8c97d468a 100644 --- a/talpid-core/src/tunnel/openvpn.rs +++ b/talpid-core/src/tunnel/openvpn.rs @@ -28,52 +28,70 @@ use talpid_types::net::openvpn; #[cfg(target_os = "linux")] use which; -error_chain! { - errors { - /// Unable to start, wait for or kill the OpenVPN process. - ChildProcessError(msg: &'static str) { - description("Unable to start, wait for or kill the OpenVPN process") - display("OpenVPN process error: {}", msg) - } - /// Unable to start or manage the IPC server listening for events from OpenVPN. - EventDispatcherError { - description("Unable to start or manage the event dispatcher IPC server") - } - #[cfg(windows)] - /// No TAP adapter was detected - MissingTapAdapter { - description("No TAP adapter was detected") - } - #[cfg(windows)] - /// TAP adapter seems to be disabled - DisabledTapAdapter { - description("The TAP adapter appears to be disabled") - } - /// The IP routing program was not found. - #[cfg(target_os = "linux")] - IpRouteNotFound { - description("The IP routing program `ip` was not found.") - } - /// The OpenVPN binary was not found. - OpenVpnNotFound(path: PathBuf) { - description("No OpenVPN binary found") - display("No OpenVPN binary found at {}", path.display()) - } - /// The OpenVPN plugin was not found. - PluginNotFound(path: PathBuf) { - description("No OpenVPN plugin found") - display("No OpenVPN plugin found at {}", path.display()) - } - /// There was an error when writing authentication credentials to temporary file. - CredentialsWriteError { - description("Error while writing credentials to temporary file") - } - /// Failures related to the proxy service. - ProxyError(msg: String) { - description("Unable to start, wait for or kill the proxy service") - display("Proxy error: {}", msg) - } - } + +/// Results from fallible operations on the OpenVPN tunnel. +pub type Result<T> = std::result::Result<T, Error>; + +/// Errors that can happen when using the OpenVPN tunnel. +#[derive(err_derive::Error, Debug)] +pub enum Error { + /// Unable to start, wait for or kill the OpenVPN process. + #[error(display = "Error in OpenVPN process management: {}", _0)] + ChildProcessError(&'static str, #[error(cause)] io::Error), + + /// Unable to start or manage the IPC server listening for events from OpenVPN. + #[error(display = "Unable to start or manage the event dispatcher IPC server")] + EventDispatcherError(#[error(cause)] talpid_ipc::Error), + + /// The OpenVPN event dispatcher exited unexpectedly + #[error(display = "The OpenVPN event dispatcher exited unexpectedly")] + EventDispatcherExited, + + /// No TAP adapter was detected + #[cfg(windows)] + #[error(display = "No TAP adapter was detected")] + MissingTapAdapter, + + /// TAP adapter seems to be disabled + #[cfg(windows)] + #[error(display = "The TAP adapter appears to be disabled")] + DisabledTapAdapter, + + /// OpenVPN process died unexpectedly + #[error(display = "OpenVPN process died unexpectedly")] + ChildProcessDied, + + /// The IP routing program was not found. + #[cfg(target_os = "linux")] + #[error(display = "The IP routing program `ip` was not found")] + IpRouteNotFound(#[error(cause)] failure::Compat<which::Error>), + + /// The OpenVPN binary was not found. + #[error(display = "No OpenVPN binary found at {}", _0)] + OpenVpnNotFound(String), + + /// The OpenVPN plugin was not found. + #[error(display = "No OpenVPN plugin found at {}", _0)] + PluginNotFound(String), + + /// Error while writing credentials to temporary file. + #[error(display = "Error while writing credentials to temporary file")] + CredentialsWriteError(#[error(cause)] io::Error), + + /// Failures related to the proxy service. + #[error(display = "Unable to start the proxy service")] + StartProxyError(#[error(cause)] io::Error), + + /// Error while monitoring proxy service + #[error(display = "Error while monitoring proxy service")] + MonitorProxyError(#[error(cause)] io::Error), + + /// The proxy exited unexpectedly + #[error( + display = "The proxy exited unexpectedly providing these details: {}", + _0 + )] + ProxyExited(String), } @@ -124,10 +142,10 @@ impl OpenVpnMonitor<OpenVpnCommand> { { let user_pass_file = Self::create_credentials_file(¶ms.config.username, ¶ms.config.password) - .chain_err(|| ErrorKind::CredentialsWriteError)?; + .map_err(Error::CredentialsWriteError)?; let proxy_auth_file = Self::create_proxy_auth_file(¶ms.options.proxy) - .chain_err(|| ErrorKind::CredentialsWriteError)?; + .map_err(Error::CredentialsWriteError)?; let user_pass_file_path = user_pass_file.to_path_buf(); @@ -205,13 +223,13 @@ impl<C: OpenVpnBuilder + 'static> OpenVpnMonitor<C> { L: Fn(openvpn_plugin::EventType, HashMap<String, String>) + Send + Sync + 'static, { let event_dispatcher = - event_server::start(on_event).chain_err(|| ErrorKind::EventDispatcherError)?; + event_server::start(on_event).map_err(Error::EventDispatcherError)?; let child = cmd .plugin(plugin_path, vec![event_dispatcher.path().to_owned()]) .log(log_path.as_ref().map(|p| p.as_path())) .start() - .chain_err(|| ErrorKind::ChildProcessError("Failed to start"))?; + .map_err(|e| Error::ChildProcessError("Failed to start", e))?; Ok(OpenVpnMonitor { child: Arc::new(child), @@ -267,21 +285,13 @@ impl<C: OpenVpnBuilder + 'static> OpenVpnMonitor<C> { // The proxy should never exit before openvpn. match proxy_result { Ok(proxy::WaitResult::ProperShutdown) => { - return Err(ErrorKind::ProxyError("The proxy exited unexpectedly without providing additional details".into()).into()); + return Err(Error::ProxyExited("No details".to_owned())); } Ok(proxy::WaitResult::UnexpectedExit(details)) => { - return Err(ErrorKind::ProxyError(format!( - "The proxy exited unexpectedly providing these details: {}", - details - )) - .into()); + return Err(Error::ProxyExited(details)); } Err(err) => { - return Err(err).chain_err(|| { - ErrorKind::ProxyError( - "Failed to wait for/monitor proxy service".into(), - ) - }); + return Err(err).map_err(Error::MonitorProxyError); } } } @@ -309,11 +319,11 @@ impl<C: OpenVpnBuilder + 'static> OpenVpnMonitor<C> { } WaitResult::Child(Err(e), _) => { log::error!("OpenVPN process wait error: {}", e); - Err(e).chain_err(|| ErrorKind::ChildProcessError("Error when waiting")) + Err(Error::ChildProcessError("Error when waiting", e)) } WaitResult::EventDispatcher => { log::error!("OpenVPN Event server exited unexpectedly"); - Err(ErrorKind::EventDispatcherError.into()) + Err(Error::EventDispatcherExited) } } } @@ -356,16 +366,16 @@ impl<C: OpenVpnBuilder + 'static> OpenVpnMonitor<C> { if let Some(log_path) = self.log_path.take() { if let Ok(log) = fs::read_to_string(log_path) { if log.contains("There are no TAP-Windows adapters on this system") { - return ErrorKind::MissingTapAdapter.into(); + return Error::MissingTapAdapter; } if log.contains("CreateFile failed on TAP device") { - return ErrorKind::DisabledTapAdapter.into(); + return Error::DisabledTapAdapter; } } } } - ErrorKind::ChildProcessError("Died unexpectedly").into() + Error::ChildProcessDied } fn create_proxy_auth_file( @@ -388,8 +398,8 @@ impl<C: OpenVpnBuilder + 'static> OpenVpnMonitor<C> { proxy_resources: &ProxyResourceData, ) -> Result<Option<Box<dyn ProxyMonitor>>> { if let Some(ref settings) = proxy_settings { - let proxy_monitor = proxy::start_proxy(settings, proxy_resources) - .chain_err(|| ErrorKind::ProxyError("Failed to start proxy service".into()))?; + let proxy_monitor = + proxy::start_proxy(settings, proxy_resources).map_err(Error::StartProxyError)?; return Ok(Some(proxy_monitor)); } Ok(None) @@ -423,7 +433,7 @@ impl<C: OpenVpnBuilder + 'static> OpenVpnMonitor<C> { log::trace!("Using OpenVPN plugin at {}", path.display()); Ok(path) } else { - bail!(ErrorKind::PluginNotFound(path)); + Err(Error::PluginNotFound(path.display().to_string())) } } @@ -443,7 +453,7 @@ impl<C: OpenVpnBuilder + 'static> OpenVpnMonitor<C> { cmd.iproute_bin( which::which("ip") .compat() - .chain_err(|| ErrorKind::IpRouteNotFound)?, + .map_err(Error::IpRouteNotFound)?, ); cmd.remote(params.config.get_tunnel_endpoint().endpoint) .user_pass(user_pass_file) @@ -467,7 +477,7 @@ impl<C: OpenVpnBuilder + 'static> OpenVpnMonitor<C> { log::trace!("Using OpenVPN at {}", path.display()); Ok(path) } else { - bail!(ErrorKind::OpenVpnNotFound(path)); + Err(Error::OpenVpnNotFound(path.display().to_string())) } } @@ -746,8 +756,8 @@ mod tests { let error = OpenVpnMonitor::new_internal(builder, |_, _| {}, "", None, TempFile::new(), None, None) .unwrap_err(); - match error.kind() { - ErrorKind::ChildProcessError(_) => (), + match error { + Error::ChildProcessError(..) => (), _ => panic!("Wrong error"), } } diff --git a/talpid-core/src/tunnel/wireguard/mod.rs b/talpid-core/src/tunnel/wireguard/mod.rs index d1c0c451d9..79034f22cd 100644 --- a/talpid-core/src/tunnel/wireguard/mod.rs +++ b/talpid-core/src/tunnel/wireguard/mod.rs @@ -1,8 +1,9 @@ #![allow(missing_docs)] + use self::config::Config; use super::{TunnelEvent, TunnelMetadata}; use crate::routing; -use std::{path::Path, sync::mpsc}; +use std::{io, path::Path, sync::mpsc}; pub mod config; mod ping_monitor; @@ -13,37 +14,38 @@ pub use self::wireguard_go::WgGoTunnel; // amount of seconds to run `ping` until it returns. const PING_TIMEOUT: u16 = 7; -error_chain! { - errors { - /// Failed to setup a tunnel device - SetupTunnelDeviceError { - description("Failed to create tunnel device") - } - /// Failed to setup wireguard tunnel - StartWireguardError(status: i32) { - display("Failed to start wireguard tunnel - {}", status) - } - /// Failed to tear down wireguard tunnel - StopWireguardError(status: i32) { - display("Failed to stop wireguard tunnel - {}", status) - } - /// Failed to set up routing - SetupRoutingError { - display("Failed to setup routing") - } - /// Failed to move or craete a log file - PrepareLogFileError { - display("Failed to setup a logging file") - } - /// Tunnel interface name contained null bytes - InterfaceNameError { - display("Tunnel interface name contains null bytes") - } - /// Pinging timed out - PingTimeoutError { - display("Ping timed out") - } - } +pub type Result<T> = std::result::Result<T, Error>; + +/// Errors that can happen in the Wireguard tunnel monitor. +#[derive(err_derive::Error, Debug)] +pub enum Error { + /// Failed to setup a tunnel device. + #[error(display = "Failed to create tunnel device")] + SetupTunnelDeviceError(#[error(cause)] crate::network_interface::Error), + + /// Failed to setup wireguard tunnel. + #[error(display = "Failed to start wireguard tunnel - {}", status)] + StartWireguardError { status: i32 }, + + /// Failed to tear down wireguard tunnel. + #[error(display = "Failed to stop wireguard tunnel - {}", status)] + StopWireguardError { status: i32 }, + + /// Failed to set up routing. + #[error(display = "Failed to setup routing")] + SetupRoutingError(#[error(cause)] crate::routing::Error), + + /// Failed to move or craete a log file. + #[error(display = "Failed to setup a logging file")] + PrepareLogFileError(#[error(cause)] io::Error), + + /// Invalid tunnel interface name. + #[error(display = "Invalid tunnel interface name")] + InterfaceNameError(#[error(cause)] std::ffi::NulError), + + /// Pinging timed out. + #[error(display = "Ping timed out")] + PingTimeoutError, } /// Spawns and monitors a wireguard tunnel @@ -65,7 +67,7 @@ impl WireguardMonitor { on_event: F, ) -> Result<WireguardMonitor> { let tunnel = Box::new(WgGoTunnel::start_tunnel(&config, log_path)?); - let router = routing::RouteManager::new().chain_err(|| ErrorKind::SetupRoutingError)?; + let router = routing::RouteManager::new().map_err(Error::SetupRoutingError)?; let event_callback = Box::new(on_event.clone()); let (close_msg_sender, close_msg_receiver) = mpsc::channel(); let mut monitor = WireguardMonitor { @@ -111,7 +113,7 @@ impl WireguardMonitor { pub fn wait(mut self) -> Result<()> { let wait_result = match self.close_msg_receiver.recv() { - Ok(CloseMsg::PingErr) => Err(ErrorKind::PingTimeoutError.into()), + Ok(CloseMsg::PingErr) => Err(Error::PingTimeoutError), Ok(CloseMsg::Stop) => Ok(()), Err(_) => Ok(()), }; @@ -148,7 +150,7 @@ impl WireguardMonitor { let default_node = self .router .get_default_route_node() - .chain_err(|| ErrorKind::SetupRoutingError)?; + .map_err(Error::SetupRoutingError)?; // route endpoints with specific routes for peer in config.peers.iter() { @@ -163,7 +165,7 @@ impl WireguardMonitor { self.router .add_routes(required_routes) - .chain_err(|| ErrorKind::SetupRoutingError) + .map_err(Error::SetupRoutingError) } fn tunnel_metadata(&self, config: &Config) -> TunnelMetadata { diff --git a/talpid-core/src/tunnel/wireguard/wireguard_go.rs b/talpid-core/src/tunnel/wireguard/wireguard_go.rs index e713a4a190..059147286d 100644 --- a/talpid-core/src/tunnel/wireguard/wireguard_go.rs +++ b/talpid-core/src/tunnel/wireguard/wireguard_go.rs @@ -1,4 +1,4 @@ -use super::{Config, ErrorKind, Result, ResultExt, Tunnel}; +use super::{Config, Error, Result, Tunnel}; use crate::network_interface::{NetworkInterface, TunnelDevice}; use std::{ffi::CString, fs, os::unix::io::AsRawFd, path::Path}; @@ -14,25 +14,24 @@ pub struct WgGoTunnel { impl WgGoTunnel { pub fn start_tunnel(config: &Config, log_path: Option<&Path>) -> Result<Self> { - let mut tunnel_device = - TunnelDevice::new().chain_err(|| ErrorKind::SetupTunnelDeviceError)?; + let mut tunnel_device = TunnelDevice::new().map_err(Error::SetupTunnelDeviceError)?; for ip in config.tunnel.addresses.iter() { tunnel_device .set_ip(*ip) - .chain_err(|| ErrorKind::SetupTunnelDeviceError)?; + .map_err(Error::SetupTunnelDeviceError)?; } tunnel_device .set_up(true) - .chain_err(|| ErrorKind::SetupTunnelDeviceError)?; + .map_err(Error::SetupTunnelDeviceError)?; let interface_name: String = tunnel_device.get_name().to_string(); let log_file = prepare_log_file(log_path)?; let wg_config_str = config.to_userspace_format(); let iface_name = - CString::new(interface_name.as_bytes()).chain_err(|| ErrorKind::InterfaceNameError)?; + CString::new(interface_name.as_bytes()).map_err(Error::InterfaceNameError)?; let handle = unsafe { wgTurnOnWithFd( @@ -46,7 +45,7 @@ impl WgGoTunnel { }; if handle < 0 { - bail!(ErrorKind::StartWireguardError(handle)); + return Err(Error::StartWireguardError { status: handle }); } Ok(WgGoTunnel { @@ -61,7 +60,7 @@ impl WgGoTunnel { if let Some(handle) = self.handle.take() { let status = unsafe { wgTurnOff(handle) }; if status < 0 { - bail!(ErrorKind::StopWireguardError(status)) + return Err(Error::StopWireguardError { status }); } } return Ok(()); @@ -77,8 +76,7 @@ impl Drop for WgGoTunnel { } fn prepare_log_file(log_path: Option<&Path>) -> Result<fs::File> { - fs::File::create(log_path.unwrap_or("/dev/null".as_ref())) - .chain_err(|| ErrorKind::PrepareLogFileError) + fs::File::create(log_path.unwrap_or("/dev/null".as_ref())).map_err(Error::PrepareLogFileError) } impl Tunnel for WgGoTunnel { diff --git a/talpid-core/src/tunnel_state_machine/connecting_state.rs b/talpid-core/src/tunnel_state_machine/connecting_state.rs index a843fa1fdd..57f4dd8a34 100644 --- a/talpid-core/src/tunnel_state_machine/connecting_state.rs +++ b/talpid-core/src/tunnel_state_machine/connecting_state.rs @@ -351,8 +351,8 @@ impl TunnelState for ConnectingState { } Err(error) => { log::error!("Failed to start tunnel: {}", error); - let block_reason = match *error.kind() { - tunnel::ErrorKind::EnableIpv6Error => BlockReason::Ipv6Unavailable, + let block_reason = match error { + tunnel::Error::EnableIpv6Error => BlockReason::Ipv6Unavailable, _ => BlockReason::StartTunnelError, }; BlockedState::enter(shared_values, block_reason) |
