diff options
| -rw-r--r-- | mullvad-daemon/src/bin/problem-report.rs | 19 | ||||
| -rw-r--r-- | mullvad-daemon/src/cli.rs | 28 | ||||
| -rw-r--r-- | mullvad-daemon/src/logging.rs | 4 | ||||
| -rw-r--r-- | mullvad-daemon/src/main.rs | 92 | ||||
| -rw-r--r-- | mullvad-paths/src/lib.rs | 4 | ||||
| -rw-r--r-- | mullvad-paths/src/logs.rs | 33 |
6 files changed, 102 insertions, 78 deletions
diff --git a/mullvad-daemon/src/bin/problem-report.rs b/mullvad-daemon/src/bin/problem-report.rs index b5df2d7fa9..dcd67ba227 100644 --- a/mullvad-daemon/src/bin/problem-report.rs +++ b/mullvad-daemon/src/bin/problem-report.rs @@ -14,7 +14,6 @@ extern crate error_chain; extern crate lazy_static; extern crate regex; -#[cfg(windows)] extern crate mullvad_paths; extern crate mullvad_rpc; @@ -46,22 +45,6 @@ const LINE_SEPARATOR: &str = "\n"; #[cfg(windows)] const LINE_SEPARATOR: &str = "\r\n"; -/// Location of log files to be collected -#[cfg(windows)] -lazy_static! { - static ref LOG_DIRECTORY: PathBuf = { - let program_data_dir = - env::var_os("ALLUSERSPROFILE").expect("Missing %ALLUSERSPROFILE% environment variable"); - - PathBuf::from(program_data_dir).join(mullvad_paths::PRODUCT_NAME) - }; -} - -#[cfg(unix)] -lazy_static! { - static ref LOG_DIRECTORY: PathBuf = PathBuf::from("/var/log/mullvad-daemon"); -} - /// Custom macro to write a line to an output formatter that uses platform-specific newline /// character sequences. macro_rules! write_line { @@ -202,7 +185,7 @@ fn collect_report( } fn logs_from_log_directory() -> Result<impl Iterator<Item = Result<PathBuf>>> { - let log_dir = &*LOG_DIRECTORY; + let log_dir = mullvad_paths::get_log_dir().chain_err(|| "Unable to get log directory")?; fs::read_dir(&log_dir) .chain_err(|| ErrorKind::LogDirError(log_dir.clone())) diff --git a/mullvad-daemon/src/cli.rs b/mullvad-daemon/src/cli.rs index c6dcfd8def..48c039011c 100644 --- a/mullvad-daemon/src/cli.rs +++ b/mullvad-daemon/src/cli.rs @@ -7,8 +7,7 @@ use version; pub struct Config { pub log_level: log::LevelFilter, - pub log_file: Option<PathBuf>, - pub tunnel_log_file: Option<PathBuf>, + pub log_to_file: bool, pub log_stdout_timestamps: bool, pub run_as_service: bool, pub register_service: bool, @@ -23,8 +22,7 @@ pub fn get_config() -> Config { 1 => log::LevelFilter::Debug, _ => log::LevelFilter::Trace, }; - let log_file = matches.value_of_os("log_file").map(PathBuf::from); - let tunnel_log_file = matches.value_of_os("tunnel_log_file").map(PathBuf::from); + let log_to_file = !matches.is_present("disable_log_to_file"); let log_stdout_timestamps = !matches.is_present("disable_stdout_timestamps"); let run_as_service = cfg!(windows) && matches.is_present("run_as_service"); @@ -32,8 +30,7 @@ pub fn get_config() -> Config { Config { log_level, - log_file, - tunnel_log_file, + log_to_file, log_stdout_timestamps, run_as_service, register_service, @@ -52,23 +49,14 @@ fn create_app() -> App<'static, 'static> { .help("Sets the level of verbosity."), ) .arg( - Arg::with_name("log_file") - .long("log") - .takes_value(true) - .value_name("PATH") - .help("Activates file logging to the given path."), - ) - .arg( - Arg::with_name("tunnel_log_file") - .long("tunnel-log") - .takes_value(true) - .value_name("PATH") - .help("Save log from tunnel implementation process to this file path."), + Arg::with_name("disable_log_to_file") + .long("disable-log-to-file") + .help("Disable logging to file"), ) .arg( Arg::with_name("disable_stdout_timestamps") - .long("disable-stdout-timestamps") - .help("Don't log timestamps when logging to stdout, useful when running as a systemd service") + .long("disable-stdout-timestamps") + .help("Don't log timestamps when logging to stdout, useful when running as a systemd service") ); if cfg!(windows) { diff --git a/mullvad-daemon/src/logging.rs b/mullvad-daemon/src/logging.rs index 2ef62ad8cb..89154ff20e 100644 --- a/mullvad-daemon/src/logging.rs +++ b/mullvad-daemon/src/logging.rs @@ -16,10 +16,6 @@ error_chain! { description("Unable to open log file for writing") display("Unable to open log file for writing: {}", path.display()) } - CreateDirError(path: PathBuf) { - description("Unable to create directory for log") - display("Unable to create directory for log: {}", path.display()) - } } foreign_links { SetLoggerError(log::SetLoggerError); diff --git a/mullvad-daemon/src/main.rs b/mullvad-daemon/src/main.rs index 9bace35a2e..cc0bf33a0d 100644 --- a/mullvad-daemon/src/main.rs +++ b/mullvad-daemon/src/main.rs @@ -70,7 +70,6 @@ use mullvad_types::relay_list::{Relay, RelayList}; use mullvad_types::states::{DaemonState, SecurityState, TargetState}; use mullvad_types::version::{AppVersion, AppVersionInfo}; -use std::env; use std::io; use std::net::IpAddr; use std::path::{Path, PathBuf}; @@ -81,9 +80,7 @@ use std::time::{Duration, Instant}; use talpid_core::firewall::{Firewall, FirewallProxy, SecurityPolicy}; use talpid_core::mpsc::IntoSender; use talpid_core::tunnel::{self, TunnelEvent, TunnelMetadata, TunnelMonitor}; -use talpid_types::net::{TunnelEndpoint, TunnelOptions}; - -use std::fs; +use talpid_types::net::{TunnelEndpoint, TunnelEndpointData, TunnelOptions}; error_chain!{ @@ -128,6 +125,10 @@ static MIN_TUNNEL_ALIVE_TIME: Duration = Duration::from_millis(1000); static MAX_RELAY_CACHE_AGE: Duration = Duration::from_secs(3600); static RELAY_CACHE_UPDATE_TIMEOUT: Duration = Duration::from_millis(3000); +const DAEMON_LOG_FILENAME: &str = "daemon.log"; +const OPENVPN_LOG_FILENAME: &str = "openvpn.log"; +const WIREGUARD_LOG_FILENAME: &str = "wireguard.log"; + /// All events that can happen in the daemon. Sent from various threads and exposed interfaces. pub enum DaemonEvent { @@ -205,13 +206,13 @@ struct Daemon { current_relay: Option<Relay>, tunnel_endpoint: Option<TunnelEndpoint>, tunnel_metadata: Option<TunnelMetadata>, - tunnel_log: Option<PathBuf>, + log_dir: Option<PathBuf>, resource_dir: PathBuf, } impl Daemon { pub fn new( - tunnel_log: Option<PathBuf>, + log_dir: Option<PathBuf>, resource_dir: PathBuf, cache_dir: PathBuf, ) -> Result<Self> { @@ -263,7 +264,7 @@ impl Daemon { current_relay: None, tunnel_endpoint: None, tunnel_metadata: None, - tunnel_log: tunnel_log, + log_dir, resource_dir, }) } @@ -704,8 +705,6 @@ impl Daemon { self.set_security_policy()?; - self.prepare_tunnel_log_file()?; - let tunnel_monitor = self.spawn_tunnel_monitor(self.tunnel_endpoint.unwrap(), &account_token)?; self.tunnel_close_handle = Some(tunnel_monitor.close_handle()); @@ -715,29 +714,6 @@ impl Daemon { Ok(()) } - fn prepare_tunnel_log_file(&self) -> Result<()> { - if let Some(ref file) = self.tunnel_log { - if let Some(log_dir) = file.parent() { - fs::create_dir_all(log_dir).chain_err(|| "Unable to create tunnel log dir")?; - } - - let mut backup = file.clone(); - backup.set_extension("old.log"); - fs::rename(file, backup).unwrap_or_else(|error| { - if error.kind() != io::ErrorKind::NotFound { - warn!( - "Failed to create backup of previous tunnel log file ({})", - error - ); - } - }); - - fs::File::create(file).chain_err(|| "Unable to create the tunnel log file")?; - } - - Ok(()) - } - fn spawn_tunnel_monitor( &self, tunnel_endpoint: TunnelEndpoint, @@ -752,17 +728,45 @@ impl Daemon { .send(DaemonEvent::TunnelEvent(event)); }; + let tunnel_log = if let Some(ref log_dir) = self.log_dir { + let filename = match tunnel_endpoint.tunnel { + TunnelEndpointData::OpenVpn(_) => OPENVPN_LOG_FILENAME, + TunnelEndpointData::Wireguard(_) => WIREGUARD_LOG_FILENAME, + }; + let tunnel_log = log_dir.join(filename); + Self::prepare_tunnel_log_file(&tunnel_log)?; + Some(tunnel_log) + } else { + None + }; + let tunnel_options = self.settings.get_tunnel_options(); TunnelMonitor::new( tunnel_endpoint, &tunnel_options, account_token, - self.tunnel_log.as_ref().map(PathBuf::as_path), + tunnel_log.as_ref().map(PathBuf::as_path), &self.resource_dir, on_tunnel_event, ).chain_err(|| ErrorKind::TunnelError("Unable to start tunnel monitor")) } + fn prepare_tunnel_log_file(file: &PathBuf) -> Result<()> { + let mut backup = file.clone(); + backup.set_extension("old.log"); + fs::rename(file, backup).unwrap_or_else(|error| { + if error.kind() != io::ErrorKind::NotFound { + warn!( + "Failed to create backup of previous tunnel log file ({})", + error + ); + } + }); + + fs::File::create(file).chain_err(|| "Unable to create the tunnel log file")?; + Ok(()) + } + fn spawn_tunnel_monitor_wait_thread(&self, tunnel_monitor: TunnelMonitor) { let error_tx = self.tx.clone(); thread::spawn(move || { @@ -850,12 +854,23 @@ quick_main!(run); fn run() -> Result<()> { let config = cli::get_config(); + let log_dir = if config.log_to_file { + Some(mullvad_paths::log_dir().chain_err(|| "Unable to get log directory")?) + } else { + None + }; + let log_file = log_dir.as_ref().map(|dir| dir.join(DAEMON_LOG_FILENAME)); + logging::init_logger( config.log_level, - config.log_file.as_ref(), + log_file.as_ref(), config.log_stdout_timestamps, ).chain_err(|| "Unable to initialize logger")?; log_version(); + if let Some(ref log_dir) = log_dir { + info!("Logging to {}", log_dir.display()); + } + run_platform(config) } @@ -887,11 +902,16 @@ fn run_standalone(config: cli::Config) -> Result<()> { warn!("Running daemon as a non-administrator user, clients might refuse to connect"); } + let log_dir = if config.log_to_file { + Some(mullvad_paths::log_dir().chain_err(|| "Unable to get log directory")?) + } else { + None + }; let resource_dir = mullvad_paths::get_resource_dir(); let cache_dir = mullvad_paths::get_cache_dir().chain_err(|| "Unable to get cache dir")?; - let daemon = Daemon::new(config.tunnel_log_file, resource_dir, cache_dir) - .chain_err(|| "Unable to initialize daemon")?; + let daemon = + Daemon::new(log_dir, resource_dir, cache_dir).chain_err(|| "Unable to initialize daemon")?; let shutdown_handle = daemon.shutdown_handle(); shutdown::set_shutdown_signal_handler(move || shutdown_handle.shutdown()) diff --git a/mullvad-paths/src/lib.rs b/mullvad-paths/src/lib.rs index 4629d8efb1..8447a77d69 100644 --- a/mullvad-paths/src/lib.rs +++ b/mullvad-paths/src/lib.rs @@ -18,12 +18,16 @@ const APP_INFO: AppInfo = app_dirs::AppInfo { error_chain! { errors { CreateDirFailed { description("Failed to create directory") } + #[cfg(windows)] NoProgramDataDir { description("Missing %ALLUSERSPROFILE% environment variable") } } } mod cache; pub use cache::get_cache_dir; +mod logs; +pub use logs::{get_log_dir, log_dir}; + mod resources; pub use resources::get_resource_dir; diff --git a/mullvad-paths/src/logs.rs b/mullvad-paths/src/logs.rs new file mode 100644 index 0000000000..822fc92c4c --- /dev/null +++ b/mullvad-paths/src/logs.rs @@ -0,0 +1,33 @@ +use {ErrorKind, Result, ResultExt}; + +use std::fs; +use std::env; +use std::path::PathBuf; + +/// Creates and returns the logging directory. +pub fn log_dir() -> Result<PathBuf> { + let dir = get_log_dir()?; + fs::create_dir_all(&dir).chain_err(|| ErrorKind::CreateDirFailed)?; + Ok(dir) +} + +/// Get the logging directory, but don't try to create it. +pub fn get_log_dir() -> Result<PathBuf> { + match env::var_os("MULLVAD_LOG_DIR") { + Some(path) => Ok(PathBuf::from(path)), + None => get_default_log_dir(), + } +} + +#[cfg(unix)] +fn get_default_log_dir() -> Result<PathBuf> { + Ok(PathBuf::from("/var/log/mullvad-daemon")) +} + +#[cfg(windows)] +fn get_default_log_dir() -> Result<PathBuf> { + let program_data_dir = Path::new( + ::std::env::var_os("ALLUSERSPROFILE").ok_or_else(|| ErrorKind::NoProgramDataDir)?, + ); + Ok(program_data_dir.join(::PRODUCT_NAME)) +} |
