use super::NmIfaceType;
#[cfg(feature = "query_apply")]
use super::{
ErrorKind, NmError,
connection::nm_con_get_from_obj_path,
dbus::{NM_DBUS_INTERFACE_AC, NM_DBUS_INTERFACE_ROOT, obj_path_to_string},
query_apply::device::nm_dev_from_obj_path,
};
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct NmActiveConnection {
pub uuid: String,
pub iface_type: NmIfaceType,
pub iface_name: String,
pub state: u32,
pub state_flags: u32,
pub dev_obj_path: Option<String>,
}
#[cfg_attr(not(feature = "query_apply"), allow(dead_code))]
impl NmActiveConnection {
pub const STATE_FLAG_EXTERNAL: u32 = 0x80;
pub const STATE_ACTIVATED: u32 = 2;
}
#[cfg(feature = "query_apply")]
async fn nm_ac_obj_path_state_flags_get(
dbus_conn: &zbus::Connection,
obj_path: &str,
) -> Result<u32, NmError> {
let proxy = zbus::Proxy::new(
dbus_conn,
NM_DBUS_INTERFACE_ROOT,
obj_path,
NM_DBUS_INTERFACE_AC,
)
.await?;
match proxy.get_property::<u32>("StateFlags").await {
Ok(uuid) => Ok(uuid),
Err(e) => Err(NmError::new(
ErrorKind::Bug,
format!(
"Failed to retrieve StateFlags of active connection \
{obj_path}: {e}"
),
)),
}
}
#[cfg(feature = "query_apply")]
pub(crate) async fn nm_ac_obj_path_uuid_get(
dbus_conn: &zbus::Connection,
obj_path: &str,
) -> Result<String, NmError> {
let proxy = zbus::Proxy::new(
dbus_conn,
NM_DBUS_INTERFACE_ROOT,
obj_path,
NM_DBUS_INTERFACE_AC,
)
.await?;
match proxy.get_property::<String>("Uuid").await {
Ok(uuid) => Ok(uuid),
Err(e) => Err(NmError::new(
ErrorKind::Bug,
format!(
"Failed to retrieve UUID of active connection {obj_path}: {e}"
),
)),
}
}
#[cfg(feature = "query_apply")]
async fn nm_ac_obj_path_nm_con_obj_path_get(
dbus_conn: &zbus::Connection,
obj_path: &str,
) -> Result<String, NmError> {
let proxy = zbus::Proxy::new(
dbus_conn,
NM_DBUS_INTERFACE_ROOT,
obj_path,
NM_DBUS_INTERFACE_AC,
)
.await?;
match proxy
.get_property::<zvariant::OwnedObjectPath>("Connection")
.await
{
Ok(p) => Ok(obj_path_to_string(p)),
Err(_) => Ok("".to_string()),
}
}
#[cfg(feature = "query_apply")]
pub(crate) async fn get_nm_ac_by_obj_path(
connection: &zbus::Connection,
obj_path: &str,
) -> Result<Option<NmActiveConnection>, NmError> {
let nm_conn_obj_path =
nm_ac_obj_path_nm_con_obj_path_get(connection, obj_path).await?;
if (!nm_conn_obj_path.is_empty()) && nm_conn_obj_path != "/" {
let nm_conn =
nm_con_get_from_obj_path(connection, &nm_conn_obj_path).await?;
let nm_dev_obj_path =
nm_ac_obj_path_nm_dev_obj_path_get(connection, obj_path).await?;
let iface_name = match nm_conn.iface_name() {
Some(i) => i.to_string(),
None => {
if let Some(nm_dev_obj_path) = nm_dev_obj_path.as_ref() {
nm_dev_from_obj_path(connection, nm_dev_obj_path)
.await?
.name
} else {
String::new()
}
}
};
let iface_type = nm_conn.iface_type().cloned().unwrap_or_default();
Ok(Some(NmActiveConnection {
uuid: nm_ac_obj_path_uuid_get(connection, obj_path).await?,
iface_name,
iface_type,
state: nm_ac_obj_path_state_get(connection, obj_path).await?,
state_flags: nm_ac_obj_path_state_flags_get(connection, obj_path)
.await?,
dev_obj_path: nm_dev_obj_path,
}))
} else {
Ok(None)
}
}
#[cfg(feature = "query_apply")]
async fn nm_ac_obj_path_nm_dev_obj_path_get(
dbus_conn: &zbus::Connection,
obj_path: &str,
) -> Result<Option<String>, NmError> {
let proxy = zbus::Proxy::new(
dbus_conn,
NM_DBUS_INTERFACE_ROOT,
obj_path,
NM_DBUS_INTERFACE_AC,
)
.await?;
match proxy
.get_property::<Vec<zvariant::OwnedObjectPath>>("Devices")
.await
{
Ok(mut p) => Ok(p.pop().map(obj_path_to_string)),
Err(_) => Ok(None),
}
}
#[cfg(feature = "query_apply")]
async fn nm_ac_obj_path_state_get(
dbus_conn: &zbus::Connection,
obj_path: &str,
) -> Result<u32, NmError> {
let proxy = zbus::Proxy::new(
dbus_conn,
NM_DBUS_INTERFACE_ROOT,
obj_path,
NM_DBUS_INTERFACE_AC,
)
.await?;
match proxy.get_property::<u32>("State").await {
Ok(uuid) => Ok(uuid),
Err(e) => Err(NmError::new(
ErrorKind::Bug,
format!(
"Failed to retrieve State of active connection {obj_path}: {e}"
),
)),
}
}