diff options
| -rw-r--r-- | talpid-core/src/firewall/linux/dns.rs | 40 |
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) +} |
