diff options
| -rw-r--r-- | CHANGELOG.md | 1 | ||||
| -rw-r--r-- | talpid-core/src/security/linux/dns/mod.rs | 6 | ||||
| -rw-r--r-- | talpid-core/src/security/linux/dns/static_resolv_conf.rs | 5 | ||||
| -rw-r--r-- | talpid-core/src/security/linux/dns/systemd_resolved.rs | 39 |
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) |
