From 0b234244054c32dcb89402638923ee7b3a6bb300 Mon Sep 17 00:00:00 2001 From: Andrey Dyldin Date: Thu, 4 Mar 2021 14:10:54 +0200 Subject: [PATCH] net: read mac on open --- examples/netinfo.rs | 7 +---- src/net/mod.rs | 69 ++++++++++++++++++++++++++++----------------- 2 files changed, 44 insertions(+), 32 deletions(-) diff --git a/examples/netinfo.rs b/examples/netinfo.rs index 4ff9dfe..c5ca3a1 100644 --- a/examples/netinfo.rs +++ b/examples/netinfo.rs @@ -22,12 +22,7 @@ fn check_net(path: &Path) -> Result<()> { dev.add_if(&mut info)?; println!("Interface: {}", dev.get_name()); - - let mac = match dev.get_mac() { - Ok(v) => v, - Err(e) => e.to_string(), - }; - println!("MAC: {}", mac); + println!("MAC: {}", dev.get_mac()); dev.remove_if(&info)?; diff --git a/src/net/mod.rs b/src/net/mod.rs index d5dcdaa..c6f28e4 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -48,6 +48,9 @@ use { }; +pub const EMPTY_MAC: &str = "00:00:00:00:00:00"; + + /// A reference to the network device #[derive(Debug)] pub struct NetDevice { @@ -55,6 +58,9 @@ pub struct NetDevice { /// Interface name name: String, + + /// MAC address + mac: String, } @@ -64,6 +70,38 @@ impl AsRawFd for NetDevice { } +fn read_interface_name(file: &T) -> Result { + let s = fstat(file.as_raw_fd())?; + + let path = format!("/sys/dev/char/{}:{}", major(s.st_rdev), minor(s.st_rdev)); + let name = readlink(path.as_str())? + .to_str() + .unwrap_or_default() + .rsplit('/') + .next() + .unwrap_or_default() + .split(".net") + .collect::>() + .join("_"); + + Ok(name) +} + + +fn read_mac_address(name: &str) -> Result { + ensure!(name.starts_with("dvb"), "incorrect interface name"); + + let len = 2 * 6 + 5; + + let mut mac = String::with_capacity(len); + let path = format!("/sys/class/net/{}/address", name); + let file = File::open(&path)?; + file.take(len as u64).read_to_string(&mut mac)?; + + Ok(mac) +} + + impl NetDevice { /// Attempts to open a network device in read-write mode pub fn open>(path: P) -> Result { @@ -74,25 +112,13 @@ impl NetDevice { .open(path) .context("NET: open")?; - let s = fstat(file.as_raw_fd())?; - let sys_path = format!( - "/sys/dev/char/{}:{}", - major(s.st_rdev), - minor(s.st_rdev) - ); - let name = readlink(sys_path.as_str())? - .to_str() - .unwrap_or_default() - .rsplit('/') - .next() - .unwrap_or_default() - .split(".net") - .collect::>() - .join("_"); + let name = read_interface_name(&file).context("NET: read interface name")?; + let mac = read_mac_address(&name).unwrap_or_else(|_| EMPTY_MAC.to_owned()); let net = NetDevice { file, name, + mac, }; Ok(net) @@ -102,17 +128,8 @@ impl NetDevice { /// and `{1}` is a device number pub fn get_name(&self) -> &str { self.name.as_str() } - /// Reads and returns interface MAC address - pub fn get_mac(&self) -> Result { - let path = format!("/sys/class/net/{}/address", self.get_name()); - - let len = 2 * 6 + 5; - let file = File::open(&path)?; - let mut result = String::with_capacity(len); - file.take(2 * 6 + 5).read_to_string(&mut result)?; - - Ok(result) - } + /// Returns interface MAC address + pub fn get_mac(&self) -> &str { self.mac.as_str() } /// Creates a new network interface pub fn add_if(&self, data: &mut DvbNetIf) -> Result<()> {