summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--talpid-core/src/firewall/linux/dns.rs40
1 files changed, 35 insertions, 5 deletions
diff --git a/talpid-core/src/firewall/linux/dns.rs b/talpid-core/src/firewall/linux/dns.rs
index 455c6624d9..a16f70e1ef 100644
--- a/talpid-core/src/firewall/linux/dns.rs
+++ b/talpid-core/src/firewall/linux/dns.rs
@@ -13,9 +13,14 @@ use self::notify::{RecommendedWatcher, RecursiveMode, Watcher};
use self::resolv_conf::{Config, ScopedIp};
const RESOLV_CONF_PATH: &str = "/etc/resolv.conf";
+const RESOLV_CONF_BACKUP_PATH: &str = "/etc/resolv.conf.mullvadbackup";
error_chain!{
errors {
+ BackupResolvConf {
+ description("Failed to create backup of /etc/resolv.conf")
+ }
+
ParseResolvConf {
description("Failed to parse contents of /etc/resolv.conf")
}
@@ -24,6 +29,14 @@ error_chain!{
description("Failed to read /etc/resolv.conf")
}
+ RemoveBackup {
+ description("Failed to remove stale backup of /etc/resolv.conf")
+ }
+
+ RestoreResolvConf {
+ description("Failed to restore /etc/resolv.conf from backup")
+ }
+
WatchResolvConf {
description("Failed to watch /etc/resolv.conf for changes")
}
@@ -54,7 +67,7 @@ impl DnsSettings {
let mut state = self.lock_state();
let new_state = match state.take() {
None => State {
- backup: read_config()?,
+ backup: backup_config()?,
desired_dns: servers,
},
Some(previous_state) => State {
@@ -72,10 +85,11 @@ impl DnsSettings {
pub fn reset(&mut self) -> Result<()> {
if let Some(state) = self.lock_state().take() {
- write_config(&state.backup)
- } else {
- Ok(())
+ write_config(&state.backup)?;
+ let _ = fs::remove_file(RESOLV_CONF_BACKUP_PATH);
}
+
+ Ok(())
}
fn lock_state(&self) -> MutexGuard<Option<State>> {
@@ -155,7 +169,7 @@ impl DnsWatcher {
new_config.nameservers.append(&mut state.backup.nameservers);
state.backup = new_config;
- Ok(())
+ update_backup(&state.backup)
}
} else {
Ok(())
@@ -174,3 +188,19 @@ fn write_config(config: &Config) -> Result<()> {
fs::write(RESOLV_CONF_PATH, config.to_string().as_bytes())
.chain_err(|| ErrorKind::WriteResolvConf)
}
+
+fn backup_config() -> Result<Config> {
+ let contents = fs::read_to_string(RESOLV_CONF_PATH).chain_err(|| ErrorKind::ReadResolvConf)?;
+
+ fs::write(RESOLV_CONF_BACKUP_PATH, contents.as_bytes())
+ .chain_err(|| ErrorKind::BackupResolvConf)?;
+
+ let config = Config::parse(&contents).chain_err(|| ErrorKind::ParseResolvConf)?;
+
+ Ok(config)
+}
+
+fn update_backup(backup: &Config) -> Result<()> {
+ fs::write(RESOLV_CONF_BACKUP_PATH, backup.to_string().as_bytes())
+ .chain_err(|| ErrorKind::BackupResolvConf)
+}