From 4c81c925862fb7b6b8a8cbb2db921e6616f5493c Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 29 Aug 2024 20:12:43 -0700 Subject: [PATCH] wifi: Properly parse all NM config files for backend Previously there was a half-baked parser that looked for a fixed value in a fixed place, but this was not robust. This approach is properly robust, in case various different files set or override it. --- Cargo.lock | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 2 +- src/wifi.rs | 59 +++++++++++++++++++++++++++---------------- 3 files changed, 110 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index be6413e..7fd0041 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -306,10 +306,31 @@ dependencies = [ "lazy_static", "nom", "pathdiff", + "rust-ini", "serde", "toml", ] +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom", + "once_cell", + "tiny-keccak", +] + [[package]] name = "cpufeatures" version = "0.2.12" @@ -325,6 +346,12 @@ version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-common" version = "0.1.6" @@ -345,6 +372,15 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "dlv-list" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" +dependencies = [ + "const-random", +] + [[package]] name = "either" version = "1.13.0" @@ -499,6 +535,12 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" + [[package]] name = "hashbrown" version = "0.14.5" @@ -536,7 +578,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.14.5", ] [[package]] @@ -698,6 +740,16 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "ordered-multimap" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ed8acf08e98e744e5384c8bc63ceb0364e68a6854187221c18df61c4797690e" +dependencies = [ + "dlv-list", + "hashbrown 0.13.2", +] + [[package]] name = "ordered-stream" version = "0.2.0" @@ -885,6 +937,16 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +[[package]] +name = "rust-ini" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e2a3bcec1f113553ef1c88aae6c020a369d03d55b58de9869a0908930385091" +dependencies = [ + "cfg-if", + "ordered-multimap", +] + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -1088,6 +1150,15 @@ dependencies = [ "once_cell", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tokio" version = "1.39.2" diff --git a/Cargo.toml b/Cargo.toml index c24e7a0..59b5ef7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ strip="symbols" anyhow = "1" async-trait = "0.1" clap = { version = "4.5", default-features = false, features = ["derive", "help", "std", "usage"] } -config = { version = "0.14", default-features = false, features = ["async", "toml"] } +config = { version = "0.14", default-features = false, features = ["async", "ini", "toml"] } inotify = { version = "0.10", default-features = false, features = ["stream"] } lazy_static = "1" libc = "0.2" diff --git a/src/wifi.rs b/src/wifi.rs index dc013bc..36bd2ce 100644 --- a/src/wifi.rs +++ b/src/wifi.rs @@ -6,15 +6,17 @@ */ use anyhow::{anyhow, bail, ensure, Error, Result}; +use config::builder::AsyncState; +use config::{ConfigBuilder, FileFormat}; use std::str::FromStr; use strum::{Display, EnumString}; use tokio::fs; use tracing::error; use zbus::Connection; -use crate::path; use crate::process::{run_script, script_output}; use crate::systemd::{daemon_reload, SystemdUnit}; +use crate::{path, read_config_directory}; const OVERRIDE_CONTENTS: &str = "[Service] ExecStart= @@ -30,7 +32,10 @@ const TRACE_CMD_PATH: &str = "/usr/bin/trace-cmd"; const MIN_BUFFER_SIZE: u32 = 100; -const WIFI_BACKEND_PATH: &str = "/etc/NetworkManager/conf.d/99-valve-wifi-backend.conf"; +const WIFI_BACKEND_PATHS: &[&str] = &[ + "/usr/lib/etc/NetworkManager/conf.d", + "/etc/NetworkManager/conf.d", +]; #[derive(Display, EnumString, PartialEq, Debug, Copy, Clone)] #[strum(serialize_all = "snake_case", ascii_case_insensitive)] @@ -209,15 +214,19 @@ pub(crate) async fn set_wifi_debug_mode( } pub(crate) async fn get_wifi_backend() -> Result { - let wifi_backend_contents = fs::read_to_string(path(WIFI_BACKEND_PATH)) - .await? - .trim() - .to_string(); - for line in wifi_backend_contents.lines() { - if line.starts_with("wifi.backend=") { - let backend = line.trim_start_matches("wifi.backend=").trim(); - return Ok(WifiBackend::from_str(backend)?); - } + let mut builder = ConfigBuilder::::default(); + for dir in WIFI_BACKEND_PATHS { + println!("{dir}"); + builder = read_config_directory(builder, path(dir), &["conf"], FileFormat::Ini).await?; + } + println!("{builder:?}"); + let config = builder.build().await?; + println!("{config:?}"); + + if let Some(backend) = config.get_table("device")?.remove("wifi.backend") { + let backend = backend.into_string()?; + println!("{backend:?}"); + return Ok(WifiBackend::from_str(backend.as_str())?); } bail!("Wi-Fi backend not found in config"); @@ -330,29 +339,35 @@ mod test { async fn test_get_wifi_backend() { let _h = testing::start(); - create_dir_all(path(WIFI_BACKEND_PATH).parent().unwrap()) - .await - .expect("create_dir_all"); + for dir in WIFI_BACKEND_PATHS { + create_dir_all(path(dir)).await.expect("create_dir_all"); + } assert!(get_wifi_backend().await.is_err()); - write(path(WIFI_BACKEND_PATH), "[device]") + write(path(WIFI_BACKEND_PATHS[0]).join("test.conf"), "[device]") .await .expect("write"); assert!(get_wifi_backend().await.is_err()); - write(path(WIFI_BACKEND_PATH), "[device]\nwifi.backend=fake\n") - .await - .expect("write"); + write( + path(WIFI_BACKEND_PATHS[0]).join("test.conf"), + "[device]\nwifi.backend=fake\n", + ) + .await + .expect("write"); assert!(get_wifi_backend().await.is_err()); - write(path(WIFI_BACKEND_PATH), "[device]\nwifi.backend=iwd\n") - .await - .expect("write"); + write( + path(WIFI_BACKEND_PATHS[0]).join("test.conf"), + "[device]\nwifi.backend=iwd\n", + ) + .await + .expect("write"); assert_eq!(get_wifi_backend().await.unwrap(), WifiBackend::Iwd); write( - path(WIFI_BACKEND_PATH), + path(WIFI_BACKEND_PATHS[0]).join("test.conf"), "[device]\nwifi.backend=wpa_supplicant\n", ) .await