summaryrefslogtreecommitdiffhomepage
path: root/mullvad-cli/src/format.rs
diff options
context:
space:
mode:
authorOskar Nyberg <oskar@mullvad.net>2020-10-01 13:19:49 +0200
committerOskar Nyberg <oskar@mullvad.net>2020-10-09 13:44:03 +0200
commitfb82b29b6ed7f73ba862eb731584c7e64bf270bc (patch)
treec18ae651da21679c986fc6fd8a7c16e67a840b10 /mullvad-cli/src/format.rs
parentd6d010e40eae0fbba4fed8381a7c887aceee79ce (diff)
downloadmullvadvpn-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.rs162
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",
+ }
+}