summaryrefslogtreecommitdiffhomepage
path: root/talpid-core/src
diff options
context:
space:
mode:
authorEmīls <emils@mullvad.net>2021-01-04 17:00:58 +0000
committerEmīls <emils@mullvad.net>2021-01-07 11:19:02 +0000
commite63ce4218f37dc0e14972d531e4d879a5ddbc181 (patch)
tree406eff6514453828bfbde776a736a276cf7ab7d2 /talpid-core/src
parent3d276db4ba1d6a6e9258d3597f9277045f371b10 (diff)
downloadmullvadvpn-e63ce4218f37dc0e14972d531e4d879a5ddbc181.tar.xz
mullvadvpn-e63ce4218f37dc0e14972d531e4d879a5ddbc181.zip
Match content of /etc/resolv.conf for systemd-resolved
Diffstat (limited to 'talpid-core/src')
-rw-r--r--talpid-core/src/dns/linux/systemd_resolved.rs52
1 files changed, 41 insertions, 11 deletions
diff --git a/talpid-core/src/dns/linux/systemd_resolved.rs b/talpid-core/src/dns/linux/systemd_resolved.rs
index de754345cd..8cc7b0b02a 100644
--- a/talpid-core/src/dns/linux/systemd_resolved.rs
+++ b/talpid-core/src/dns/linux/systemd_resolved.rs
@@ -6,7 +6,7 @@ use dbus::{
};
use lazy_static::lazy_static;
use libc::{AF_INET, AF_INET6};
-use std::{fs, net::IpAddr, path::Path, sync::Arc, time::Duration};
+use std::{fs, io, net::IpAddr, path::Path, sync::Arc, time::Duration};
use talpid_types::ErrorExt as _;
pub type Result<T> = std::result::Result<T, Error>;
@@ -17,6 +17,12 @@ pub enum Error {
#[error(display = "Failed to initialize a connection to D-Bus")]
ConnectDBus(#[error(source)] dbus::Error),
+ #[error(display = "Failed to read /etc/resolv.conf: _0")]
+ ReadResolvConfError(#[error(source)] io::Error),
+
+ #[error(display = "/etc/resolv.conf contents do not match systemd-resolved resolv.conf")]
+ ResolvConfDiffers,
+
#[error(display = "/etc/resolv.conf is not a symlink to Systemd resolved")]
NotSymlinkedToResolvConf,
@@ -92,20 +98,44 @@ impl SystemdResolved {
}
fn ensure_resolv_conf_is_resolved_symlink() -> Result<()> {
- let link_target =
- fs::read_link(RESOLV_CONF_PATH).map_err(|_| Error::NotSymlinkedToResolvConf)?;
+ match fs::read_link(RESOLV_CONF_PATH) {
+ Ok(link_target) => {
+ // if /etc/resolv.conf is not symlinked to the stub resolve.conf file , managing DNS
+ // through systemd-resolved will not ensure that our resolver is given priority -
+ // sometimes this will mean adding 1 and 2 seconds of latency to DNS
+ // queries, other times our resolver won't be considered at all. In
+ // this case, it's better to fall back to cruder management methods.
+ if Self::path_is_resolvconf_stub(&link_target)
+ || Self::resolv_conf_is_static_stub(&link_target)?
+ || Self::ensure_resolvconf_contents().is_ok()
+ {
+ Ok(())
+ } else {
+ Err(Error::NotSymlinkedToResolvConf)
+ }
+ }
+ // etc/resolv.conf is not a symlink
+ Err(err) if err.kind() == io::ErrorKind::InvalidInput => {
+ Self::ensure_resolvconf_contents()
+ }
+ Err(err) => {
+ log::trace!("Failed to read /etc/resolv.conf symlink - {}", err);
+ Err(Error::NotSymlinkedToResolvConf)
+ }
+ }
+ }
- // if /etc/resolv.conf is not symlinked to the stub resolve.conf file , managing DNS
- // through systemd-resolved will not ensure that our resolver is given priority - sometimes
- // this will mean adding 1 and 2 seconds of latency to DNS queries, other times our
- // resolver won't be considered at all. In this case, it's better to fall back to cruder
- // management methods.
- if Self::path_is_resolvconf_stub(&link_target)
- || Self::resolv_conf_is_static_stub(&link_target)?
+ fn ensure_resolvconf_contents() -> Result<()> {
+ let resolv_conf =
+ fs::read_to_string(RESOLV_CONF_PATH).map_err(Error::ReadResolvConfError)?;
+ if RESOLVED_STUB_PATHS
+ .iter()
+ .filter_map(|path| fs::read_to_string(path).ok())
+ .any(|link_contents| link_contents == resolv_conf)
{
Ok(())
} else {
- Err(Error::NotSymlinkedToResolvConf)
+ Err(Error::ResolvConfDiffers)
}
}