summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--talpid-core/src/security/linux/dns/mod.rs6
-rw-r--r--talpid-core/src/security/linux/dns/static_resolv_conf.rs5
-rw-r--r--talpid-core/src/security/linux/dns/systemd_resolved.rs39
4 files changed, 46 insertions, 5 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3c5e159df2..d2d8451e3c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -37,6 +37,7 @@ Line wrap the file at 100 chars. Th
- The app will have it's window resized correctly when display scaling settings are changed. This
should also fix bad window behaviour on startup.
- Fixed systemd-resolved DNS management.
+- Skip systemd-resolved as the DNS manager if it's running in consumer mode.
## [2018.4-beta2] - 2018-10-08
diff --git a/talpid-core/src/security/linux/dns/mod.rs b/talpid-core/src/security/linux/dns/mod.rs
index 2e1760bd1c..0ab82c5d15 100644
--- a/talpid-core/src/security/linux/dns/mod.rs
+++ b/talpid-core/src/security/linux/dns/mod.rs
@@ -1,3 +1,5 @@
+extern crate resolv_conf;
+
mod network_manager;
mod resolvconf;
mod static_resolv_conf;
@@ -10,6 +12,8 @@ use self::resolvconf::Resolvconf;
use self::static_resolv_conf::StaticResolvConf;
use self::systemd_resolved::SystemdResolved;
+const RESOLV_CONF_PATH: &str = "/etc/resolv.conf";
+
error_chain! {
errors {
NoDnsSettingsManager {
@@ -37,7 +41,7 @@ impl fmt::Display for DnsSettings {
let name = match self {
DnsSettings::Resolvconf(..) => "resolvconf",
DnsSettings::StaticResolvConf(..) => "/etc/resolv.conf",
- DnsSettings::SystemdResolved(..) => "systemd-resolve",
+ DnsSettings::SystemdResolved(..) => "systemd-resolved",
DnsSettings::NetworkManager(..) => "network manager",
};
f.write_str(name)
diff --git a/talpid-core/src/security/linux/dns/static_resolv_conf.rs b/talpid-core/src/security/linux/dns/static_resolv_conf.rs
index e9e81e5446..6ece9ba44c 100644
--- a/talpid-core/src/security/linux/dns/static_resolv_conf.rs
+++ b/talpid-core/src/security/linux/dns/static_resolv_conf.rs
@@ -1,5 +1,4 @@
extern crate notify;
-extern crate resolv_conf;
use std::net::IpAddr;
use std::ops::DerefMut;
@@ -9,9 +8,9 @@ use std::{fs, io, thread};
use error_chain::ChainedError;
use self::notify::{RecommendedWatcher, RecursiveMode, Watcher};
-use self::resolv_conf::{Config, ScopedIp};
+use super::resolv_conf::{Config, ScopedIp};
+use super::RESOLV_CONF_PATH;
-const RESOLV_CONF_PATH: &str = "/etc/resolv.conf";
const RESOLV_CONF_BACKUP_PATH: &str = "/etc/resolv.conf.mullvadbackup";
error_chain! {
diff --git a/talpid-core/src/security/linux/dns/systemd_resolved.rs b/talpid-core/src/security/linux/dns/systemd_resolved.rs
index 5c416187fd..78e55a048b 100644
--- a/talpid-core/src/security/linux/dns/systemd_resolved.rs
+++ b/talpid-core/src/security/linux/dns/systemd_resolved.rs
@@ -1,6 +1,8 @@
extern crate dbus;
-use std::net::IpAddr;
+use std::fs;
+use std::net::{IpAddr, Ipv4Addr};
+use std::path::Path;
use error_chain::ChainedError;
use libc::{AF_INET, AF_INET6};
@@ -10,6 +12,8 @@ use self::dbus::stdintf::*;
use self::dbus::{BusType, Interface, Member, MessageItem, MessageItemArray, Signature};
use super::super::iface_index;
+use super::{resolv_conf, RESOLV_CONF_PATH};
+
error_chain! {
errors {
@@ -38,6 +42,9 @@ error_chain! {
}
+const DYNAMIC_RESOLV_CONF_PATH: &str = "/run/systemd/resolve/resolv.conf";
+const RESOLVED_DNS_SERVER_ADDRESS: [u8; 4] = [127, 0, 0, 53];
+
const RESOLVED_BUS: &str = "org.freedesktop.resolve1";
const RPC_TIMEOUT_MS: i32 = 1000;
@@ -65,6 +72,7 @@ impl SystemdResolved {
interface_link: None,
};
+ SystemdResolved::ensure_resolved_is_active()?;
systemd_resolved.ensure_resolved_exists()?;
Ok(systemd_resolved)
@@ -79,6 +87,35 @@ impl SystemdResolved {
Ok(())
}
+ fn ensure_resolved_is_active() -> Result<()> {
+ ensure!(
+ Self::resolv_conf_is_resolved_symlink() || Self::resolv_conf_has_resolved_dns()?,
+ ErrorKind::NoSystemdResolved
+ );
+
+ Ok(())
+ }
+
+ fn resolv_conf_is_resolved_symlink() -> bool {
+ fs::read_link(RESOLV_CONF_PATH)
+ .map(|resolv_conf_target| resolv_conf_target == Path::new(DYNAMIC_RESOLV_CONF_PATH))
+ .unwrap_or_else(|_| false)
+ }
+
+ fn resolv_conf_has_resolved_dns() -> Result<bool> {
+ let resolv_conf_contents =
+ fs::read_to_string(RESOLV_CONF_PATH).chain_err(|| ErrorKind::NoSystemdResolved)?;
+ let parsed_resolv_conf = resolv_conf::Config::parse(resolv_conf_contents)
+ .chain_err(|| ErrorKind::NoSystemdResolved)?;
+ let resolved_dns_server =
+ resolv_conf::ScopedIp::V4(Ipv4Addr::from(RESOLVED_DNS_SERVER_ADDRESS));
+
+ Ok(parsed_resolv_conf
+ .nameservers
+ .into_iter()
+ .any(|nameserver| nameserver == resolved_dns_server))
+ }
+
fn as_manager_object<'a>(&'a self) -> dbus::ConnPath<'a, &'a dbus::Connection> {
self.dbus_connection
.with_path(RESOLVED_BUS, "/org/freedesktop/resolve1", RPC_TIMEOUT_MS)