summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--mullvad-daemon/src/bin/problem-report.rs19
-rw-r--r--mullvad-daemon/src/cli.rs28
-rw-r--r--mullvad-daemon/src/logging.rs4
-rw-r--r--mullvad-daemon/src/main.rs92
-rw-r--r--mullvad-paths/src/lib.rs4
-rw-r--r--mullvad-paths/src/logs.rs33
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))
+}