Skip to content

Commit

Permalink
Add mac assigning to base connection
Browse files Browse the repository at this point in the history
  • Loading branch information
jcronenberg committed Nov 30, 2023
1 parent 5e7a449 commit c960eac
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 3 deletions.
13 changes: 13 additions & 0 deletions rust/agama-dbus-server/src/network/dbus/interfaces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,19 @@ impl Connection {
connection.set_interface(name);
self.update_connection(connection).await
}

/// Custom mac-address
#[dbus_interface(property)]
pub async fn mac_address(&self) -> String {
self.get_connection().await.mac_address().to_string()
}

#[dbus_interface(property)]
pub async fn set_mac_address(&mut self, mac_address: &str) -> zbus::fdo::Result<()> {
let mut connection = self.get_connection().await;
connection.set_mac_address(mac_address);
self.update_connection(connection).await
}
}

/// D-Bus interface for Match settings
Expand Down
13 changes: 13 additions & 0 deletions rust/agama-dbus-server/src/network/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,12 +306,25 @@ impl Connection {
pub fn is_loopback(&self) -> bool {
matches!(self, Connection::Loopback(_))
}

pub fn mac_address(&self) -> &str {
&self.base().mac_address
}

pub fn set_mac_address(&mut self, mac_address: &str) {
self.base_mut().mac_address = mac_address.to_string();
}

pub fn is_ethernet(&self) -> bool {
matches!(self, Connection::Loopback(_)) || matches!(self, Connection::Ethernet(_))
}
}

#[derive(Debug, Default, Clone)]
pub struct BaseConnection {
pub id: String,
pub uuid: Uuid,
pub mac_address: String,
pub ip_config: IpConfig,
pub status: Status,
pub interface: String,
Expand Down
68 changes: 65 additions & 3 deletions rust/agama-dbus-server/src/network/nm/dbus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,12 @@ pub fn connection_to_dbus(conn: &Connection) -> NestedHash {
result.insert("ipv6", ip_config_to_ipv6_dbus(conn.ip_config()));
result.insert("match", match_config_to_dbus(conn.match_config()));

if let Connection::Wireless(wireless) = conn {
connection_dbus.insert("type", "802-11-wireless".into());
if conn.is_ethernet() {
let ethernet_config =
HashMap::from([("assigned-mac-address", Value::new(conn.mac_address()))]);
result.insert(ETHERNET_KEY, ethernet_config);
} else if let Connection::Wireless(wireless) = conn {
connection_dbus.insert("type", WIRELESS_KEY.into());
let wireless_dbus = wireless_config_to_dbus(wireless);
for (k, v) in wireless_dbus {
result.insert(k, v);
Expand Down Expand Up @@ -218,6 +222,10 @@ fn wireless_config_to_dbus(conn: &WirelessConnection) -> NestedHash {
let wireless: HashMap<&str, zvariant::Value> = HashMap::from([
("mode", Value::new(config.mode.to_string())),
("ssid", Value::new(config.ssid.to_vec())),
(
"assigned-mac-address",
Value::new(conn.base.mac_address.clone()),
),
]);

let mut security: HashMap<&str, zvariant::Value> =
Expand Down Expand Up @@ -291,6 +299,20 @@ fn base_connection_from_dbus(conn: &OwnedNestedHash) -> Option<BaseConnection> {
base_connection.match_config = match_config_from_dbus(match_config)?;
}

if let Some(ethernet_config) = conn.get(ETHERNET_KEY) {
if let Some(mac_address) = ethernet_config.get("assigned-mac-address") {
base_connection.mac_address = mac_address.downcast_ref::<str>()?.to_string();
} else {
base_connection.mac_address = "".to_string();
}
} else if let Some(wireless_config) = conn.get(WIRELESS_KEY) {
if let Some(mac_address) = wireless_config.get("assigned-mac-address") {
base_connection.mac_address = mac_address.downcast_ref::<str>()?.to_string();
} else {
base_connection.mac_address = "".to_string();
}
}

base_connection.ip_config = ip_config_from_dbus(&conn)?;

Some(base_connection)
Expand Down Expand Up @@ -585,6 +607,8 @@ mod test {
let match_config = connection.match_config();
assert_eq!(match_config.kernel, vec!["pci-0000:00:19.0"]);

assert_eq!(connection.mac_address(), "12:34:56:78:9A:BC");

assert_eq!(
ip_config.addresses,
vec![
Expand Down Expand Up @@ -640,6 +664,10 @@ mod test {
"ssid".to_string(),
Value::new("agama".as_bytes()).to_owned(),
),
(
"assigned-mac-address".to_string(),
Value::new("13:45:67:89:AB:CD").to_owned(),
),
]);

let security_section =
Expand All @@ -652,6 +680,10 @@ mod test {
]);

let connection = connection_from_dbus(dbus_conn).unwrap();
assert_eq!(
connection.base().mac_address,
"13:45:67:89:AB:CD".to_string()
);
assert!(matches!(connection, Connection::Wireless(_)));
if let Connection::Wireless(connection) = connection {
assert_eq!(connection.wireless.ssid, SSID(vec![97, 103, 97, 109, 97]));
Expand Down Expand Up @@ -679,6 +711,12 @@ mod test {
let wireless = wireless_dbus.get("802-11-wireless").unwrap();
let mode: &str = wireless.get("mode").unwrap().downcast_ref().unwrap();
assert_eq!(mode, "infrastructure");
let mac_address: &str = wireless
.get("assigned-mac-address")
.unwrap()
.downcast_ref()
.unwrap();
assert_eq!(mac_address, "FD:CB:A9:87:65:43");

let ssid: &zvariant::Array = wireless.get("ssid").unwrap().downcast_ref().unwrap();
let ssid: Vec<u8> = ssid
Expand Down Expand Up @@ -804,19 +842,33 @@ mod test {
Value::new("eth0".to_string()).to_owned(),
),
]);
let ethernet = HashMap::from([(
"assigned-mac-address".to_string(),
Value::new("12:34:56:78:9A:BC".to_string()).to_owned(),
)]);
original.insert("connection".to_string(), connection);
original.insert(ETHERNET_KEY.to_string(), ethernet);

let mut updated = Connection::Ethernet(EthernetConnection::default());
updated.set_interface("");
updated.set_mac_address("");
let updated = connection_to_dbus(&updated);

let merged = merge_dbus_connections(&original, &updated);
let connection = merged.get("connection").unwrap();
assert_eq!(connection.get("interface-name"), None);
let ethernet = merged.get(ETHERNET_KEY).unwrap();
assert_eq!(ethernet.get("assigned-mac-address"), Some(&Value::from("")));
}

fn build_ethernet_section_from_dbus() -> HashMap<String, OwnedValue> {
HashMap::from([("auto-negotiate".to_string(), true.into())])
HashMap::from([
("auto-negotiate".to_string(), true.into()),
(
"assigned-mac-address".to_string(),
Value::new("12:34:56:78:9A:BC").to_owned(),
),
])
}

fn build_base_connection() -> BaseConnection {
Expand All @@ -840,9 +892,11 @@ mod test {
}]),
..Default::default()
};
let mac_address = "FD:CB:A9:87:65:43".to_string();
BaseConnection {
id: "agama".to_string(),
ip_config,
mac_address,
..Default::default()
}
}
Expand All @@ -859,6 +913,14 @@ mod test {
let id: &str = connection_dbus.get("id").unwrap().downcast_ref().unwrap();
assert_eq!(id, "agama");

let ethernet_connection = conn_dbus.get(ETHERNET_KEY).unwrap();
let mac_address: &str = ethernet_connection
.get("assigned-mac-address")
.unwrap()
.downcast_ref()
.unwrap();
assert_eq!(mac_address, "FD:CB:A9:87:65:43");

let ipv4_dbus = conn_dbus.get("ipv4").unwrap();
let gateway4: &str = ipv4_dbus.get("gateway").unwrap().downcast_ref().unwrap();
assert_eq!(gateway4, "192.168.0.1");
Expand Down
2 changes: 2 additions & 0 deletions rust/agama-dbus-server/tests/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ async fn test_add_connection() -> Result<(), Box<dyn Error>> {
let addresses: Vec<IpInet> = vec!["192.168.0.2/24".parse()?, "::ffff:c0a8:7ac7/64".parse()?];
let wlan0 = settings::NetworkConnection {
id: "wlan0".to_string(),
mac_address: Some("FD:CB:A9:87:65:43".to_string()),
method4: Some("auto".to_string()),
method6: Some("disabled".to_string()),
addresses: addresses.clone(),
Expand All @@ -80,6 +81,7 @@ async fn test_add_connection() -> Result<(), Box<dyn Error>> {

let conn = conns.first().unwrap();
assert_eq!(conn.id, "wlan0");
assert_eq!(conn.mac_address, Some("FD:CB:A9:87:65:43".to_string()));
assert_eq!(conn.device_type(), DeviceType::Wireless);
assert_eq!(&conn.addresses, &addresses);
let method4 = conn.method4.as_ref().unwrap();
Expand Down
4 changes: 4 additions & 0 deletions rust/agama-lib/share/profile.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
"description": "The name of the network interface bound to this connection",
"type": "string"
},
"mac-address": {
"description": "Custom mac-address (can also be 'preserve', 'permanent', 'random' or 'stable')",
"type": "string"
},
"method4": {
"description": "IPv4 configuration method (e.g., 'auto')",
"type": "string",
Expand Down
12 changes: 12 additions & 0 deletions rust/agama-lib/src/network/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ impl<'a> NetworkClient<'a> {
"" => None,
value => Some(value.to_string()),
};
let mac_address = match connection_proxy.mac_address().await?.as_str() {
"" => None,
value => Some(value.to_string()),
};

let ip_proxy = IPProxy::builder(&self.connection)
.path(path)?
Expand All @@ -91,6 +95,7 @@ impl<'a> NetworkClient<'a> {
addresses,
nameservers,
interface,
mac_address,
..Default::default()
})
}
Expand Down Expand Up @@ -189,6 +194,13 @@ impl<'a> NetworkClient<'a> {
let interface = conn.interface.as_deref().unwrap_or("");
proxy.set_interface(interface).await?;

let mac_address = if let Some(mac_address) = &conn.mac_address {
mac_address
} else {
""
};
proxy.set_mac_address(mac_address).await?;

self.update_ip_settings(path, conn).await?;

if let Some(ref wireless) = conn.wireless {
Expand Down
4 changes: 4 additions & 0 deletions rust/agama-lib/src/network/proxies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ trait Connection {
fn interface(&self) -> zbus::Result<String>;
#[dbus_proxy(property)]
fn set_interface(&self, interface: &str) -> zbus::Result<()>;
#[dbus_proxy(property)]
fn mac_address(&self) -> zbus::Result<String>;
#[dbus_proxy(property)]
fn set_mac_address(&self, mac_address: &str) -> zbus::Result<()>;
}

#[dbus_proxy(
Expand Down
2 changes: 2 additions & 0 deletions rust/agama-lib/src/network/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ pub struct NetworkConnection {
pub interface: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub match_settings: Option<MatchSettings>,
#[serde(rename = "mac-address", skip_serializing_if = "Option::is_none")]
pub mac_address: Option<String>,
}

impl NetworkConnection {
Expand Down

0 comments on commit c960eac

Please sign in to comment.