diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2020-10-01 13:19:49 +0200 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2020-10-09 13:44:03 +0200 |
| commit | fb82b29b6ed7f73ba862eb731584c7e64bf270bc (patch) | |
| tree | c18ae651da21679c986fc6fd8a7c16e67a840b10 /mullvad-cli/src/format.rs | |
| parent | d6d010e40eae0fbba4fed8381a7c887aceee79ce (diff) | |
| download | mullvadvpn-fb82b29b6ed7f73ba862eb731584c7e64bf270bc.tar.xz mullvadvpn-fb82b29b6ed7f73ba862eb731584c7e64bf270bc.zip | |
Move state formatting code to format.rs
Diffstat (limited to 'mullvad-cli/src/format.rs')
| -rw-r--r-- | mullvad-cli/src/format.rs | 162 |
1 files changed, 161 insertions, 1 deletions
diff --git a/mullvad-cli/src/format.rs b/mullvad-cli/src/format.rs index 4f69d05317..92f6076e66 100644 --- a/mullvad-cli/src/format.rs +++ b/mullvad-cli/src/format.rs @@ -1,4 +1,14 @@ -use mullvad_management_interface::types::KeygenEvent; +use mullvad_management_interface::types::{ + error_state::{ + firewall_policy_error::ErrorType as FirewallPolicyErrorType, Cause as ErrorStateCause, + FirewallPolicyError, GenerationError, + }, + tunnel_state, + tunnel_state::State::*, + ErrorState, KeygenEvent, ProxyType, TransportProtocol, TunnelEndpoint, TunnelState, TunnelType, +}; +use mullvad_types::auth_failed::AuthFailed; +use std::fmt::Write; pub fn print_keygen_event(key_event: &KeygenEvent) { use mullvad_management_interface::types::keygen_event::KeygenEvent as EventType; @@ -18,3 +28,153 @@ pub fn print_keygen_event(key_event: &KeygenEvent) { } } } + +pub fn print_state(state: &TunnelState) { + print!("Tunnel status: "); + match state.state.as_ref().unwrap() { + Error(error) => print_error_state(error.error_state.as_ref().unwrap()), + Connected(tunnel_state::Connected { relay_info }) => { + let endpoint = relay_info + .as_ref() + .unwrap() + .tunnel_endpoint + .as_ref() + .unwrap(); + println!("Connected to {}", format_endpoint(&endpoint)); + } + Connecting(tunnel_state::Connecting { relay_info }) => { + let endpoint = relay_info + .as_ref() + .unwrap() + .tunnel_endpoint + .as_ref() + .unwrap(); + println!("Connecting to {}...", format_endpoint(&endpoint)); + } + Disconnected(_) => println!("Disconnected"), + Disconnecting(_) => println!("Disconnecting..."), + } +} + +fn format_endpoint(endpoint: &TunnelEndpoint) -> String { + let mut out = format!( + "{} {} over {}", + match TunnelType::from_i32(endpoint.tunnel_type).expect("unknown tunnel protocol") { + TunnelType::Wireguard => "WireGuard", + TunnelType::Openvpn => "OpenVPN", + }, + endpoint.address, + format_protocol( + TransportProtocol::from_i32(endpoint.protocol).expect("unknown transport protocol") + ), + ); + + if let Some(ref proxy) = endpoint.proxy { + write!( + &mut out, + " via {} {} over {}", + match ProxyType::from_i32(proxy.proxy_type).expect("unknown proxy type") { + ProxyType::Shadowsocks => "Shadowsocks", + ProxyType::Custom => "custom bridge", + }, + proxy.address, + format_protocol( + TransportProtocol::from_i32(proxy.protocol).expect("unknown transport protocol") + ), + ) + .unwrap(); + } + + out +} + +fn print_error_state(error_state: &ErrorState) { + if error_state.blocking_error.is_some() { + eprintln!("Mullvad daemon failed to setup firewall rules!"); + eprintln!("Deamon cannot block traffic from flowing, non-local traffic will leak"); + } + + match ErrorStateCause::from_i32(error_state.cause) { + Some(ErrorStateCause::AuthFailed) => { + println!( + "Blocked: {}", + AuthFailed::from(error_state.auth_fail_reason.as_ref()) + ); + } + #[cfg(target_os = "linux")] + Some(ErrorStateCause::SetFirewallPolicyError) => { + println!("Blocked: {}", error_state_to_string(error_state)); + println!("Your kernel might be terribly out of date or missing nftables"); + } + _ => println!("Blocked: {}", error_state_to_string(error_state)), + } +} + +fn error_state_to_string(error_state: &ErrorState) -> String { + use ErrorStateCause::*; + + let error_str = match ErrorStateCause::from_i32(error_state.cause).expect("unknown error cause") + { + AuthFailed => { + return if error_state.auth_fail_reason.is_empty() { + "Authentication with remote server failed".to_string() + } else { + format!( + "Authentication with remote server failed: {}", + error_state.auth_fail_reason + ) + }; + } + Ipv6Unavailable => "Failed to configure IPv6 because it's disabled in the platform", + SetFirewallPolicyError => { + return policy_error_to_string(error_state.policy_error.as_ref().unwrap()) + } + SetDnsError => "Failed to set system DNS server", + StartTunnelError => "Failed to start connection to remote server", + TunnelParameterError => { + return format!( + "Failure to generate tunnel parameters: {}", + tunnel_parameter_error_to_string(error_state.parameter_error) + ); + } + IsOffline => "This device is offline, no tunnels can be established", + TapAdapterProblem => "A problem with the TAP adapter has been detected", + #[cfg(target_os = "android")] + VpnPermissionDenied => "The Android VPN permission was denied when creating the tunnel", + #[cfg(not(target_os = "android"))] + _ => unreachable!("unknown error cause"), + }; + + error_str.to_string() +} + +fn tunnel_parameter_error_to_string(parameter_error: i32) -> &'static str { + match GenerationError::from_i32(parameter_error).expect("unknown generation error") { + GenerationError::NoMatchingRelay => "Failure to select a matching tunnel relay", + GenerationError::NoMatchingBridgeRelay => "Failure to select a matching bridge relay", + GenerationError::NoWireguardKey => "No wireguard key available", + GenerationError::CustomTunnelHostResolutionError => { + "Can't resolve hostname for custom tunnel host" + } + } +} + +fn policy_error_to_string(policy_error: &FirewallPolicyError) -> String { + let cause = match FirewallPolicyErrorType::from_i32(policy_error.r#type) + .expect("unknown policy error") + { + FirewallPolicyErrorType::Generic => return "Failed to set firewall policy".to_string(), + FirewallPolicyErrorType::Locked => format!( + "An application prevented the firewall policy from being set: {} (pid {})", + policy_error.lock_name, policy_error.lock_pid + ), + }; + format!("Failed to set firewall policy: {}", cause) +} + +fn format_protocol(protocol: TransportProtocol) -> &'static str { + match protocol { + TransportProtocol::Udp => "UDP", + TransportProtocol::Tcp => "TCP", + } +} |
