summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--talpid-core/src/security/linux/dns/mod.rs103
1 files changed, 59 insertions, 44 deletions
diff --git a/talpid-core/src/security/linux/dns/mod.rs b/talpid-core/src/security/linux/dns/mod.rs
index 95498469b1..e9756b56b2 100644
--- a/talpid-core/src/security/linux/dns/mod.rs
+++ b/talpid-core/src/security/linux/dns/mod.rs
@@ -29,38 +29,80 @@ error_chain! {
}
}
-pub enum DnsMonitor {
+pub struct DnsMonitor {
+ inner: Option<DnsMonitorHolder>,
+}
+
+impl super::super::DnsMonitorT for DnsMonitor {
+ type Error = Error;
+
+ fn new(_cache_dir: impl AsRef<Path>) -> Result<Self> {
+ Ok(DnsMonitor { inner: None })
+ }
+
+ fn set(&mut self, interface: &str, servers: &[IpAddr]) -> Result<()> {
+ self.reset()?;
+ // Creating a new DNS monitor for each set, in case the system changed how it manages DNS.
+ let mut inner = DnsMonitorHolder::new()?;
+ inner.set(interface, servers)?;
+ self.inner = Some(inner);
+ Ok(())
+ }
+
+ fn reset(&mut self) -> Result<()> {
+ if let Some(mut inner) = self.inner.take() {
+ inner.reset()?;
+ }
+ Ok(())
+ }
+}
+
+pub enum DnsMonitorHolder {
Resolvconf(Resolvconf),
StaticResolvConf(StaticResolvConf),
SystemdResolved(SystemdResolved),
NetworkManager(NetworkManager),
}
-impl fmt::Display for DnsMonitor {
+impl fmt::Display for DnsMonitorHolder {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ use self::DnsMonitorHolder::*;
let name = match self {
- DnsMonitor::Resolvconf(..) => "resolvconf",
- DnsMonitor::StaticResolvConf(..) => "/etc/resolv.conf",
- DnsMonitor::SystemdResolved(..) => "systemd-resolved",
- DnsMonitor::NetworkManager(..) => "network manager",
+ Resolvconf(..) => "resolvconf",
+ StaticResolvConf(..) => "/etc/resolv.conf",
+ SystemdResolved(..) => "systemd-resolved",
+ NetworkManager(..) => "network manager",
};
f.write_str(name)
}
}
-impl super::super::DnsMonitorT for DnsMonitor {
- type Error = Error;
+impl DnsMonitorHolder {
+ fn new() -> Result<Self> {
+ let dns_module = env::var_os("TALPID_DNS_MODULE");
- fn new(_cache_dir: impl AsRef<Path>) -> Result<Self> {
- DnsMonitor::new_internal()
+ let manager = match dns_module.as_ref().and_then(|value| value.to_str()) {
+ Some("static-file") => DnsMonitorHolder::StaticResolvConf(StaticResolvConf::new()?),
+ Some("resolvconf") => DnsMonitorHolder::Resolvconf(Resolvconf::new()?),
+ Some("systemd") => DnsMonitorHolder::SystemdResolved(SystemdResolved::new()?),
+ Some("network-manager") => DnsMonitorHolder::NetworkManager(NetworkManager::new()?),
+ Some(_) | None => Self::with_detected_dns_manager()?,
+ };
+ log::debug!("Managing DNS via {}", manager);
+ Ok(manager)
}
- fn set(&mut self, interface: &str, servers: &[IpAddr]) -> Result<()> {
- self.reset()?;
- // Resetting the DNS manager in case the previously selected one isn't valid
- *self = DnsMonitor::new_internal()?;
+ fn with_detected_dns_manager() -> Result<Self> {
+ SystemdResolved::new()
+ .map(DnsMonitorHolder::SystemdResolved)
+ .or_else(|_| NetworkManager::new().map(DnsMonitorHolder::NetworkManager))
+ .or_else(|_| Resolvconf::new().map(DnsMonitorHolder::Resolvconf))
+ .or_else(|_| StaticResolvConf::new().map(DnsMonitorHolder::StaticResolvConf))
+ .chain_err(|| ErrorKind::NoDnsMonitor)
+ }
- use self::DnsMonitor::*;
+ fn set(&mut self, interface: &str, servers: &[IpAddr]) -> Result<()> {
+ use self::DnsMonitorHolder::*;
match self {
Resolvconf(ref mut resolvconf) => resolvconf.set_dns(interface, servers)?,
StaticResolvConf(ref mut static_resolv_conf) => {
@@ -69,46 +111,19 @@ impl super::super::DnsMonitorT for DnsMonitor {
SystemdResolved(ref mut systemd_resolved) => {
systemd_resolved.set_dns(interface, &servers)?
}
- NetworkManager(ref mut network_manager) => network_manager.set_dns(&servers)?,
+ NetworkManager(ref mut network_manager) => network_manager.set_dns(servers)?,
}
Ok(())
}
fn reset(&mut self) -> Result<()> {
- use self::DnsMonitor::*;
-
+ use self::DnsMonitorHolder::*;
match self {
Resolvconf(ref mut resolvconf) => resolvconf.reset()?,
StaticResolvConf(ref mut static_resolv_conf) => static_resolv_conf.reset()?,
SystemdResolved(ref mut systemd_resolved) => systemd_resolved.reset()?,
NetworkManager(ref mut network_manager) => network_manager.reset()?,
}
-
Ok(())
}
}
-
-impl DnsMonitor {
- fn new_internal() -> Result<Self> {
- let dns_module = env::var_os("TALPID_DNS_MODULE");
-
- let manager = match dns_module.as_ref().and_then(|value| value.to_str()) {
- Some("static-file") => DnsMonitor::StaticResolvConf(StaticResolvConf::new()?),
- Some("resolvconf") => DnsMonitor::Resolvconf(Resolvconf::new()?),
- Some("systemd") => DnsMonitor::SystemdResolved(SystemdResolved::new()?),
- Some("network-manager") => DnsMonitor::NetworkManager(NetworkManager::new()?),
- Some(_) | None => Self::with_detected_dns_manager()?,
- };
- log::debug!("Managing DNS via {}", manager);
- Ok(manager)
- }
-
- fn with_detected_dns_manager() -> Result<Self> {
- SystemdResolved::new()
- .map(DnsMonitor::SystemdResolved)
- .or_else(|_| NetworkManager::new().map(DnsMonitor::NetworkManager))
- .or_else(|_| Resolvconf::new().map(DnsMonitor::Resolvconf))
- .or_else(|_| StaticResolvConf::new().map(DnsMonitor::StaticResolvConf))
- .chain_err(|| ErrorKind::NoDnsMonitor)
- }
-}