1use std::net::Ipv4Addr;
4use std::sync::Arc;
5use std::time::Duration;
6
7use dbus::arg::RefArg;
8use dbus::blocking::{Connection, Proxy};
9use dbus::{Error, Path};
10
11use nmdbus::device::Device as DeviceTrait;
12use nmdbus::device_modem::DeviceModem;
13use nmdbus::ip4config::IP4Config;
14use nmdbus::NetworkManager as DbusNetworkManager;
15
16const DBUS_NAME: &str = "org.freedesktop.NetworkManager";
17const DBUS_PATH: &str = "/org/freedesktop/NetworkManager";
18const TIMEOUT: Duration = Duration::from_secs(2);
19
20#[derive(Clone)]
21struct Dbus {
22 conn: Arc<Connection>,
23}
24
25impl Dbus {
26 fn connect() -> Result<Self, Error> {
27 Connection::new_system()
28 .map(Arc::new)
29 .map(|conn| Self { conn })
30 }
31
32 fn proxy<'a, 'b>(
33 &'b self,
34 path: impl Into<Path<'a>>,
35 ) -> Proxy<'a, &'b Connection> {
36 self.conn.with_proxy(DBUS_NAME, path, TIMEOUT)
37 }
38}
39
40#[derive(Clone)]
41pub struct NetworkManager {
42 dbus: Dbus,
43}
44
45impl NetworkManager {
46 pub fn connect() -> Result<Self, Error> {
47 Dbus::connect().map(|dbus| Self { dbus })
48 }
49
50 pub fn devices(&self) -> Result<Vec<Device>, Error> {
51 let paths = self.dbus.proxy(DBUS_PATH).get_devices()?;
52 let devices = paths
53 .into_iter()
54 .map(|path| Device {
55 dbus: self.dbus.clone(),
56 path,
57 })
58 .collect();
59
60 Ok(devices)
61 }
62}
63
64pub struct Device {
65 dbus: Dbus,
66 path: Path<'static>,
67}
68
69impl Device {
70 pub fn path(&self) -> Result<String, Error> {
74 self.dbus.proxy(&self.path).path()
75 }
76
77 pub fn interface(&self) -> Result<String, Error> {
82 self.dbus.proxy(&self.path).interface()
83 }
84
85 pub fn driver(&self) -> Result<String, Error> {
88 self.dbus.proxy(&self.path).driver()
89 }
90
91 pub fn state(&self) -> Result<DeviceState, Error> {
93 DeviceTrait::state(&self.dbus.proxy(&self.path)).map(Into::into)
94 }
95
96 pub fn kind(&self) -> Result<DeviceKind, Error> {
98 self.dbus.proxy(&self.path).device_type().map(Into::into)
99 }
100
101 pub fn ipv4_config(&self) -> Result<Ipv4Config, Error> {
104 self.dbus
105 .proxy(&self.path)
106 .ip4_config()
107 .map(|path| Ipv4Config {
108 dbus: self.dbus.clone(),
109 path,
110 })
111 }
112
113 pub fn modem_apn(&self) -> Result<String, Error> {
115 self.dbus.proxy(&self.path).apn()
116 }
117}
118
119pub struct Ipv4Config {
120 dbus: Dbus,
121 path: Path<'static>,
122}
123
124impl Ipv4Config {
125 pub fn addresses(&self) -> Result<Vec<Ipv4Addr>, Error> {
126 let data = self.dbus.proxy(&self.path).address_data()?;
127 let addrs = data
128 .into_iter()
129 .filter_map(|mut d| d.remove("address"))
130 .filter_map(|addr| addr.as_str()?.parse().ok())
131 .collect();
132
133 Ok(addrs)
134 }
135}
136
137#[repr(u32)]
138#[derive(Debug, Clone, Copy, PartialEq, Eq)]
139#[cfg_attr(
140 feature = "serde",
141 derive(serde1::Serialize, serde1::Deserialize),
142 serde(crate = "serde1")
143)]
144pub enum DeviceKind {
145 Unknown = 0,
147 Generic = 14,
149 Ethernet = 1,
151 Wifi = 2,
153 Unused1 = 3,
155 Unused2 = 4,
157 Bt = 5,
159 OlpcMesh = 6,
161 Wimax = 7,
163 Modem = 8,
166 Infiniband = 9,
168 Bond = 10,
170 Vlan = 11,
172 Adsl = 12,
174 Bridge = 13,
176 Team = 15,
178 Tun = 16,
180 IpTunnel = 17,
182 Macvlan = 18,
184 Vxlan = 19,
186 Veth = 20,
188 Macsec = 21,
190 Dummy = 22,
192 Ppp = 23,
194 OvsInterface = 24,
196 OvsPort = 25,
198 OvsBridge = 26,
200 Wpan = 27,
202 SixLowPan = 28,
204 Wireguard = 29,
206 WifiP2p = 30,
208 Vrf = 31,
210}
211
212impl From<u32> for DeviceKind {
213 fn from(num: u32) -> Self {
214 if num > 31 {
215 Self::Unknown
216 } else {
217 unsafe { *(&num as *const u32 as *const Self) }
218 }
219 }
220}
221
222#[repr(u32)]
223#[derive(Debug, Clone, Copy, PartialEq, Eq)]
224#[cfg_attr(
225 feature = "serde",
226 derive(serde1::Serialize, serde1::Deserialize),
227 serde(crate = "serde1")
228)]
229pub enum DeviceState {
230 Unknown = 0,
232 Unmanaged = 10,
234 Unavailable = 20,
238 Disconnected = 30,
241 Prepare = 40,
246 Config = 50,
250 NeedAuth = 60,
254 IpConfig = 70,
257 IpCheck = 80,
262 Secondaries = 90,
265 Activated = 100,
267 Deactivating = 110,
271 Failed = 120,
274}
275
276impl From<u32> for DeviceState {
277 fn from(num: u32) -> Self {
278 if num > 120 || num % 10 != 0 {
279 Self::Unknown
280 } else {
281 unsafe { *(&num as *const u32 as *const Self) }
282 }
283 }
284}