diff options
| author | Emīls <emils@mullvad.net> | 2021-03-01 12:37:05 +0000 |
|---|---|---|
| committer | Emīls <emils@mullvad.net> | 2021-03-01 20:29:34 +0000 |
| commit | c2fe8beebd7641657974f76ab6dc33ed379e2e26 (patch) | |
| tree | 280b8660f44c7ac7bcd3ec5ec1630803a1e72642 | |
| parent | cc3b225e2eec9e2f49441903457379c0c3906512 (diff) | |
| download | mullvadvpn-c2fe8beebd7641657974f76ab6dc33ed379e2e26.tar.xz mullvadvpn-c2fe8beebd7641657974f76ab6dc33ed379e2e26.zip | |
Stop using NM if it's too new
| -rw-r--r-- | CHANGELOG.md | 3 | ||||
| -rw-r--r-- | talpid-core/src/dns/linux/network_manager.rs | 1 | ||||
| -rw-r--r-- | talpid-dbus/src/network_manager.rs | 82 | ||||
| -rw-r--r-- | talpid-platform-metadata/src/linux.rs | 2 |
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 |
