diff --git a/Cargo.toml b/Cargo.toml index bf905a4..cc7f307 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ tokio-timer = "0.1" bitflags = "1.0" ascii = "0.8" log = "0.3" +bitintr = "0.2.0" [dependencies.error-chain] version = "0.11" diff --git a/src/connection.rs b/src/connection.rs index b4df188..d9b3377 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -284,6 +284,44 @@ where Ok((connection, state)) } +pub fn set_ethernet_address( + dbus_manager: &Rc, + device_path: &str, + interface: &str, + address: Ipv4Addr, + address_netmask_bit_count: u8, + gateway: Ipv4Addr, + dns_addr_1: Ipv4Addr, + dns_addr_2: Ipv4Addr, + dns_search: &str, + method: &str, + connection_name: &str, +) -> Result<(Connection, ConnectionState)> +{ + let (path, _) = dbus_manager.set_ethernet_address( + device_path, + interface, + address, + address_netmask_bit_count, + gateway, + dns_addr_1, + dns_addr_2, + dns_search, + method, + connection_name, + )?; + + let connection = Connection::init(dbus_manager, &path)?; + + let state = wait( + &connection, + &ConnectionState::Activated, + dbus_manager.method_timeout(), + )?; + + Ok((connection, state)) +} + fn get_connection_active_path( dbus_manager: &DBusNetworkManager, connection_path: &str, diff --git a/src/dbus_nm.rs b/src/dbus_nm.rs index a89bf5b..189f895 100644 --- a/src/dbus_nm.rs +++ b/src/dbus_nm.rs @@ -6,6 +6,8 @@ use dbus::arg::{Array, Dict, Iter, RefArg, Variant}; use ascii::AsciiStr; +use bitintr::Rev; + use errors::*; use dbus_api::{extract, path_to_string, DBusApi, VariantTo, variant_iter_to_vec_u8}; use manager::{Connectivity, NetworkManagerState}; @@ -347,6 +349,62 @@ impl DBusNetworkManager { )) } + pub fn set_ethernet_address( + &self, + device_path: &str, + interface: &str, + address: Ipv4Addr, + address_netmask_bit_count: u8, + gateway: Ipv4Addr, + dns_addr_1: Ipv4Addr, + dns_addr_2: Ipv4Addr, + dns_search: &str, + method: &str, + connection_name: &str, + ) -> Result<(String, String)> + { + let mut connection: VariantMap = HashMap::new(); + add_str(&mut connection, "id", connection_name); + add_str(&mut connection, "interface-name", interface); + add_str(&mut connection, "type", "802-3-ethernet"); + + let mut ipv4: VariantMap = HashMap::new(); + add_str(&mut ipv4, "method", method); + + if(method == "manual"){ + add_str(&mut ipv4, "gateway", format!("{}", gateway)); + let mut addr_map: VariantMap = HashMap::new(); + let prefix = address_netmask_bit_count as u32; + add_str(&mut addr_map, "address", format!("{}", address)); + add_val(&mut addr_map, "prefix", prefix); + add_val(&mut ipv4, "address-data", vec![addr_map]); + } + add_val(&mut ipv4, "dns", vec![u32::from(dns_addr_1).rev(), u32::from(dns_addr_2).rev()]); + add_val(&mut ipv4, "dns-search", vec![dns_search.to_string()]); + + let mut settings: HashMap = HashMap::new(); + settings.insert("connection".to_string(), connection); + settings.insert("ipv4".to_string(), ipv4); + + let response = self.dbus.call_with_args( + NM_SERVICE_PATH, + NM_SERVICE_INTERFACE, + "AddAndActivateConnection", + &[ + &settings as &RefArg, + &Path::new(device_path)? as &RefArg, + &Path::new("/")? as &RefArg, + ], + )?; + + let (conn_path, active_connection): (Path, Path) = self.dbus.extract_two(&response)?; + + Ok(( + path_to_string(&conn_path)?, + path_to_string(&active_connection)?, + )) + } + pub fn get_devices(&self) -> Result> { self.dbus .property(NM_SERVICE_PATH, NM_SERVICE_INTERFACE, "Devices") diff --git a/src/device.rs b/src/device.rs index bd7f22b..d0972d1 100644 --- a/src/device.rs +++ b/src/device.rs @@ -5,6 +5,7 @@ use errors::*; use dbus_nm::DBusNetworkManager; use wifi::{new_wifi_device, WiFiDevice}; +use ethernet::{new_ethernet_device, EthernetDevice}; #[derive(Clone)] pub struct Device { @@ -48,6 +49,14 @@ impl Device { } } + pub fn as_ethernet_device(&self) -> Option { + if self.device_type == DeviceType::Ethernet { + Some(new_ethernet_device(&self.dbus_manager, self)) + } else { + None + } + } + /// Connects a Network Manager device. /// /// Examples diff --git a/src/ethernet.rs b/src/ethernet.rs new file mode 100644 index 0000000..6f6ad85 --- /dev/null +++ b/src/ethernet.rs @@ -0,0 +1,52 @@ +use std::rc::Rc; +use std::net::Ipv4Addr; + +use errors::*; +use dbus_nm::DBusNetworkManager; + +use connection::{Connection, ConnectionState, set_ethernet_address}; +use device::{Device, PathGetter}; + +pub struct EthernetDevice<'a> { + dbus_manager: Rc, + device: &'a Device, +} + +impl<'a> EthernetDevice<'a> { + pub fn set_ethernet_address( + &self, + address: Ipv4Addr, + address_netmask_bit_count: u8, + gateway: Ipv4Addr, + dns_addr_1: Ipv4Addr, + dns_addr_2: Ipv4Addr, + dns_search: &str, + method: &str, + connection_name: &str, + ) -> Result<(Connection, ConnectionState)> + { + set_ethernet_address( + &self.dbus_manager, + self.device.path(), + self.device.interface(), + address, + address_netmask_bit_count, + gateway, + dns_addr_1, + dns_addr_2, + dns_search, + method, + connection_name, + ) + } +} + +pub fn new_ethernet_device<'a>( + dbus_manager: &Rc, + device: &'a Device, +) -> EthernetDevice<'a> { + EthernetDevice { + dbus_manager: Rc::clone(dbus_manager), + device: device, + } +} diff --git a/src/lib.rs b/src/lib.rs index a8eeb9b..5ef0a2e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,8 @@ extern crate dbus; extern crate ascii; +extern crate bitintr; + pub mod errors; mod dbus_nm; @@ -25,6 +27,7 @@ mod service; mod connection; mod device; mod wifi; +mod ethernet; mod ssid; pub use manager::{Connectivity, NetworkManager};