summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorEmīls <emils@mullvad.net>2021-03-01 12:37:05 +0000
committerEmīls <emils@mullvad.net>2021-03-01 20:29:34 +0000
commitc2fe8beebd7641657974f76ab6dc33ed379e2e26 (patch)
tree280b8660f44c7ac7bcd3ec5ec1630803a1e72642
parentcc3b225e2eec9e2f49441903457379c0c3906512 (diff)
downloadmullvadvpn-c2fe8beebd7641657974f76ab6dc33ed379e2e26.tar.xz
mullvadvpn-c2fe8beebd7641657974f76ab6dc33ed379e2e26.zip
Stop using NM if it's too new
-rw-r--r--CHANGELOG.md3
-rw-r--r--talpid-core/src/dns/linux/network_manager.rs1
-rw-r--r--talpid-dbus/src/network_manager.rs82
-rw-r--r--talpid-platform-metadata/src/linux.rs2
4 files changed, 69 insertions, 19 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7de0c43522..27dd6b45f8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -55,6 +55,9 @@ Line wrap the file at 100 chars. Th
- Fix "cannot find the file" error while creating a Wintun adapter by upgrading Wintun.
- Retry when creating a WireGuard tunnel fails due to no default routes being found.
+#### Linux
+- Stop using NM for managing DNS if it's newer than 1.26.
+
## [2021.2] - 2021-02-18
This release is for desktop only.
diff --git a/talpid-core/src/dns/linux/network_manager.rs b/talpid-core/src/dns/linux/network_manager.rs
index b51308368b..b1b6ba2cca 100644
--- a/talpid-core/src/dns/linux/network_manager.rs
+++ b/talpid-core/src/dns/linux/network_manager.rs
@@ -17,6 +17,7 @@ impl NetworkManager {
let connection = DBus::new()?;
connection.ensure_resolv_conf_is_managed()?;
connection.ensure_network_manager_exists()?;
+ connection.nm_version_dns_works()?;
let manager = NetworkManager {
connection,
device: None,
diff --git a/talpid-dbus/src/network_manager.rs b/talpid-dbus/src/network_manager.rs
index 9253a68ac8..b714996dad 100644
--- a/talpid-dbus/src/network_manager.rs
+++ b/talpid-dbus/src/network_manager.rs
@@ -53,6 +53,8 @@ const DBUS_UNKNOWN_METHOD: &str = "org.freedesktop.DBus.Error.UnknownMethod";
const MINIMUM_SUPPORTED_MAJOR_VERSION: u32 = 1;
const MINIMUM_SUPPORTED_MINOR_VERSION: u32 = 16;
+const MAXIMUM_SUPPORTED_MAJOR_VERSION: u32 = 1;
+const MAXIMUM_SUPPORTED_MINOR_VERSION: u32 = 26;
const NM_DEVICE_STATE_CHANGED: &'static str = "StateChanged";
@@ -69,8 +71,14 @@ pub enum Error {
#[error(display = "Configuration has no device associated to it")]
NoDevice,
- #[error(display = "NetworkManager is too old - {}", _0)]
- NMTooOld(String),
+ #[error(display = "NetworkManager is too old - {}.{}", _0, _1)]
+ NMTooOld(u32, u32),
+
+ #[error(display = "NetworkManager is too new to manage DNS - {}.{}", _0, _1)]
+ NMTooNewFroDns(u32, u32),
+
+ #[error(display = "Failed to parse NetworkManager version string - {}", _0)]
+ ParseNmVersionError(String),
#[error(display = "Device inactive: {}", _0)]
DeviceNotReady(u32),
@@ -113,7 +121,7 @@ impl NetworkManager {
}
pub fn create_wg_tunnel(&self, config: &DeviceConfig) -> Result<WireguardTunnel> {
- self.ensure_nm_is_new_enough_for_wireguard()?;
+ self.nm_supports_wireguard()?;
let tunnel = self.create_wg_tunnel_inner(config)?;
if let Err(err) = self.wait_until_device_is_ready(&tunnel.device_path) {
if let Err(removal_error) = self.remove_tunnel(tunnel) {
@@ -183,29 +191,54 @@ impl NetworkManager {
})
}
- fn ensure_nm_is_new_enough_for_wireguard(&self) -> Result<()> {
- let version: String = self.version()?;
- let version_too_old = || Error::NMTooOld(version.clone());
- let mut parts = version
- .split(".")
- .map(|part| part.parse().map_err(|_| version_too_old()));
+ pub fn nm_supports_wireguard(&self) -> Result<()> {
+ let (major, minor) = self.version()?;
+ Self::ensure_nm_is_new_enough_for_wireguard(major, minor)?;
+ Self::ensure_nm_is_old_enough_for_dns(major, minor)
+ }
+
+ pub fn nm_version_dns_works(&self) -> Result<()> {
+ let (major, minor) = self.version()?;
+ Self::ensure_nm_is_old_enough_for_dns(major, minor)
+ }
- let major_version: u32 = parts.next().ok_or_else(|| version_too_old())??;
- let minor_version: u32 = parts.next().ok_or_else(|| version_too_old())??;
+ pub fn version_string(&self) -> Result<String> {
+ let manager = self.nm_manager();
+ manager.get(NM_MANAGER, "Version").map_err(Error::Dbus)
+ }
- if major_version < MINIMUM_SUPPORTED_MAJOR_VERSION
- || (minor_version < MINIMUM_SUPPORTED_MINOR_VERSION
- && major_version == MINIMUM_SUPPORTED_MAJOR_VERSION)
+ fn ensure_nm_is_new_enough_for_wireguard(major: u32, minor: u32) -> Result<()> {
+ if major < MINIMUM_SUPPORTED_MAJOR_VERSION
+ || (minor < MINIMUM_SUPPORTED_MINOR_VERSION && major == MINIMUM_SUPPORTED_MAJOR_VERSION)
{
- Err(version_too_old())
+ Err(Error::NMTooOld(major, minor))
} else {
Ok(())
}
}
- pub fn version(&self) -> Result<String> {
- let manager = self.nm_manager();
- manager.get(NM_MANAGER, "Version").map_err(Error::Dbus)
+ fn ensure_nm_is_old_enough_for_dns(major_version: u32, minor_version: u32) -> Result<()> {
+ if major_version > MAXIMUM_SUPPORTED_MAJOR_VERSION
+ || (minor_version > MAXIMUM_SUPPORTED_MINOR_VERSION
+ && major_version >= MAXIMUM_SUPPORTED_MAJOR_VERSION)
+ {
+ Err(Error::NMTooNewFroDns(major_version, minor_version))
+ } else {
+ Ok(())
+ }
+ }
+
+ fn version(&self) -> Result<(u32, u32)> {
+ let version = self.version_string()?;
+ Self::parse_nm_version(&version).ok_or(Error::ParseNmVersionError(version))
+ }
+
+ fn parse_nm_version(version: &str) -> Option<(u32, u32)> {
+ let mut parts = version.split(".").map(|part| part.parse().ok());
+
+ let major_version: u32 = parts.next()??;
+ let minor_version: u32 = parts.next()??;
+ Some((major_version, minor_version))
}
fn add_connection_2(
@@ -709,3 +742,16 @@ fn eq_file_content<P: AsRef<Path>>(a: &P, b: &P) -> bool {
_ => false,
})
}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn test_valid_versions() {
+ NetworkManager::ensure_nm_is_new_enough_for_wireguard(1, 16).unwrap();
+ NetworkManager::ensure_nm_is_old_enough_for_dns(1, 26).unwrap();
+ assert!(NetworkManager::ensure_nm_is_new_enough_for_wireguard(1, 14).is_err());
+ assert!(NetworkManager::ensure_nm_is_old_enough_for_dns(1, 28).is_err());
+ }
+}
diff --git a/talpid-platform-metadata/src/linux.rs b/talpid-platform-metadata/src/linux.rs
index 016fb123c3..600078c030 100644
--- a/talpid-platform-metadata/src/linux.rs
+++ b/talpid-platform-metadata/src/linux.rs
@@ -94,7 +94,7 @@ fn kernel_version() -> Option<(String, String)> {
/// > 1.26.0
fn nm_version() -> Option<(String, String)> {
let nm = talpid_dbus::network_manager::NetworkManager::new().ok()?;
- Some(("nm".to_string(), nm.version().ok()?))
+ Some(("nm".to_string(), nm.version_string().ok()?))
}
/// `/sys/module/wireguard/version` contains only a numeric version string