Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ip networks for interface #1218

Merged
merged 12 commits into from
Mar 8, 2024
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,5 @@ rusty-tags.vi
tags

**.o
simple
simple
.idea/
33 changes: 33 additions & 0 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ use std::collections::{HashMap, HashSet};
use std::convert::TryFrom;
use std::ffi::OsStr;
use std::fmt;
use std::fmt::Formatter;
use std::net::IpAddr;
use std::path::Path;
use std::str::FromStr;

Expand Down Expand Up @@ -2328,6 +2330,20 @@ impl NetworkData {
pub fn mac_address(&self) -> MacAddr {
self.inner.mac_address()
}

/// Returns the Ip Networks associated to current interface.
///
/// ```no_run
/// use sysinfo::Networks;
///
/// let mut networks = Networks::new_with_refreshed_list();
/// for (interface_name, network) in &networks {
/// println!("Ip Networks: {:?}", network.ip_networks());
/// }
/// ```
pub fn ip_networks(&self) -> &[IpNetwork] {
self.inner.ip_networks()
}
}

/// Struct containing a disk information.
Expand Down Expand Up @@ -3635,6 +3651,23 @@ impl fmt::Display for MacAddr {
}
}

/// Ip networks address for network interface.
///
/// It is returned by [`NetworkData::ip_networks`][crate::NetworkData::ip_networks].
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct IpNetwork {
/// The ip of the network interface
pub addr: IpAddr,
/// The netmask, prefix of the ipaddress
pub prefix: u8,
}

impl fmt::Display for IpNetwork {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}/{}", self.addr, self.prefix)
}
}

/// Interacting with components.
///
/// ```no_run
Expand Down
50 changes: 47 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ cfg_if::cfg_if! {

pub use crate::common::{
get_current_pid, CGroupLimits, Component, Components, Cpu, CpuRefreshKind, Disk, DiskKind,
DiskUsage, Disks, Gid, Group, Groups, LoadAvg, MacAddr, MemoryRefreshKind, NetworkData,
Networks, Pid, Process, ProcessRefreshKind, ProcessStatus, RefreshKind, Signal, System,
ThreadKind, Uid, UpdateKind, User, Users,
DiskUsage, Disks, Gid, Group, Groups, IpNetwork, LoadAvg, MacAddr, MemoryRefreshKind,
NetworkData, Networks, Pid, Process, ProcessRefreshKind, ProcessStatus, RefreshKind, Signal,
System, ThreadKind, Uid, UpdateKind, User, Users,
};

pub(crate) use crate::common::GroupInner;
Expand Down Expand Up @@ -178,6 +178,7 @@ mod doctest {
#[cfg(test)]
mod test {
use crate::*;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

#[cfg(feature = "unknown-ci")]
#[test]
Expand Down Expand Up @@ -543,6 +544,49 @@ mod test {
assert!(!MacAddr([1, 2, 3, 4, 5, 6]).is_unspecified());
}

// Ensure that the `Display` and `Debug` traits are implemented on the `IpNetwork` struct
#[test]
fn check_display_impl_ip_network_ipv4() {
println!(
"{} {:?}",
IpNetwork {
addr: IpAddr::from(Ipv4Addr::new(1, 2, 3, 4)),
prefix: 3
},
IpNetwork {
addr: IpAddr::from(Ipv4Addr::new(255, 255, 255, 0)),
prefix: 21
}
);
}

#[test]
fn check_display_impl_ip_network_ipv6() {
println!(
"{} {:?}",
IpNetwork {
addr: IpAddr::from(Ipv6Addr::new(0xffff, 0xaabb, 00, 0, 0, 0x000c, 11, 21)),
prefix: 127
},
IpNetwork {
addr: IpAddr::from(Ipv6Addr::new(0xffcc, 0, 0, 0xffcc, 0, 0xffff, 0, 0xccaa)),
prefix: 120
}
)
}

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a test to ensure that supported platforms have at least one IP network for an interface. You can filter out using:

if !crate::IS_SUPPORTED_SYSTEM {
    return;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. Check added.

#[test]
fn check_ip_networks() {
if !IS_SUPPORTED_SYSTEM {
return;
}
let networks = Networks::new_with_refreshed_list();
if networks.iter().any(|(_, n)| !n.ip_networks().is_empty()) {
return;
}
panic!("Networks should have at least one IP network ");
}

// This test exists to ensure that the `TryFrom<usize>` and `FromStr` traits are implemented
// on `Uid`, `Gid` and `Pid`.
#[allow(clippy::unnecessary_fallible_conversions)]
Expand Down
10 changes: 8 additions & 2 deletions src/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@

use std::collections::HashMap;

use crate::network_helper::get_interface_address;
use crate::network_helper::{get_interface_address, get_interface_ip_networks};
use crate::NetworkData;

/// Interface addresses are OS-independent
pub(crate) fn refresh_networks_addresses(interfaces: &mut HashMap<String, NetworkData>) {
match get_interface_address() {
let interface_networks = unsafe { get_interface_ip_networks() };
for (interface_name, ip_networks) in interface_networks {
if let Some(interface) = interfaces.get_mut(&interface_name) {
interface.inner.ip_networks = ip_networks.into_iter().collect::<Vec<_>>();
}
}
match unsafe { get_interface_address() } {
Ok(ifa_iterator) => {
for (name, ifa) in ifa_iterator {
if let Some(interface) = interfaces.get_mut(&name) {
Expand Down
15 changes: 15 additions & 0 deletions src/serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ impl Serialize for crate::NetworkData {
&self.total_errors_on_transmitted(),
)?;
state.serialize_field("mac_address", &self.mac_address())?;
state.serialize_field("ip_networks", &self.ip_networks())?;

state.end()
}
Expand Down Expand Up @@ -413,3 +414,17 @@ impl Serialize for crate::MacAddr {
serializer.serialize_newtype_struct("MacAddr", &self.0)
}
}

impl Serialize for crate::IpNetwork {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_struct("IpNetwork", 2)?;

state.serialize_field("addr", &self.addr)?;
state.serialize_field("prefix", &self.prefix)?;

state.end()
}
}
11 changes: 5 additions & 6 deletions src/unix/apple/macos/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,11 +403,10 @@ unsafe fn get_exe_and_name_backup(
let tmp = String::from_utf8_unchecked(buffer);
let exe = PathBuf::from(tmp);
if process.name.is_empty() {
process.name = exe
.file_name()
exe.file_name()
.and_then(|x| x.to_str())
.unwrap_or("")
.to_owned();
.clone_into(&mut process.name);
}
if exe_needs_update {
process.exe = Some(exe);
Expand Down Expand Up @@ -540,11 +539,11 @@ unsafe fn get_process_infos(process: &mut ProcessInner, refresh_kind: ProcessRef

let (exe, proc_args) = get_exe(proc_args);
if process.name.is_empty() {
process.name = exe
.file_name()
exe.file_name()
.and_then(|x| x.to_str())
.unwrap_or("")
.to_owned();
.to_owned()
.clone_into(&mut process.name);
}

if refresh_kind.exe().needs_update(|| process.exe.is_none()) {
Expand Down
8 changes: 8 additions & 0 deletions src/unix/apple/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::ptr::null_mut;

use crate::common::MacAddr;
use crate::network::refresh_networks_addresses;
use crate::IpNetwork;
use crate::NetworkData;

macro_rules! old_and_new {
Expand Down Expand Up @@ -167,6 +168,7 @@ impl NetworksInner {
old_errors_out: errors_out,
updated: true,
mac_addr: MacAddr::UNSPECIFIED,
ip_networks: vec![],
},
});
}
Expand Down Expand Up @@ -194,6 +196,8 @@ pub(crate) struct NetworkDataInner {
updated: bool,
/// MAC address
pub(crate) mac_addr: MacAddr,
/// IP networks
pub(crate) ip_networks: Vec<IpNetwork>,
}

impl NetworkDataInner {
Expand Down Expand Up @@ -248,4 +252,8 @@ impl NetworkDataInner {
pub(crate) fn mac_address(&self) -> MacAddr {
self.mac_addr
}

pub(crate) fn ip_networks(&self) -> &[IpNetwork] {
&self.ip_networks
}
}
8 changes: 8 additions & 0 deletions src/unix/freebsd/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::mem::MaybeUninit;
use super::utils;
use crate::common::MacAddr;
use crate::network::refresh_networks_addresses;
use crate::IpNetwork;
use crate::NetworkData;

macro_rules! old_and_new {
Expand Down Expand Up @@ -115,6 +116,7 @@ impl NetworksInner {
old_ifi_oerrors: 0,
updated: true,
mac_addr: MacAddr::UNSPECIFIED,
ip_networks: vec![],
},
});
}
Expand Down Expand Up @@ -149,6 +151,8 @@ pub(crate) struct NetworkDataInner {
updated: bool,
/// MAC address
pub(crate) mac_addr: MacAddr,
/// IP networks
pub(crate) ip_networks: Vec<IpNetwork>,
}

impl NetworkDataInner {
Expand Down Expand Up @@ -203,4 +207,8 @@ impl NetworkDataInner {
pub(crate) fn mac_address(&self) -> MacAddr {
self.mac_addr
}

pub(crate) fn ip_networks(&self) -> &[IpNetwork] {
&self.ip_networks
}
}
2 changes: 1 addition & 1 deletion src/unix/freebsd/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ unsafe fn add_missing_proc_info(
// First, we try to retrieve the name from the command line.
let p = Path::new(&cmd[0]);
if let Some(name) = p.file_name().and_then(|s| s.to_str()) {
proc_inner.name = name.to_owned();
name.clone_into(&mut proc_inner.name);
}

if cmd_needs_update {
Expand Down
4 changes: 2 additions & 2 deletions src/unix/linux/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ impl CpusWrapper {
}
let mut parts = line.split(|x| *x == b' ').filter(|s| !s.is_empty());
if first {
self.global_cpu.inner.name =
to_str!(parts.next().unwrap_or(&[])).to_owned();
to_str!(parts.next().unwrap_or(&[]))
.clone_into(&mut self.global_cpu.inner.name);
} else {
parts.next();
}
Expand Down
8 changes: 7 additions & 1 deletion src/unix/linux/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::io::Read;
use std::path::Path;
use std::{fs::File, u8};

use crate::common::MacAddr;
use crate::common::{IpNetwork, MacAddr};
use crate::network::refresh_networks_addresses;
use crate::NetworkData;

Expand Down Expand Up @@ -95,6 +95,7 @@ fn refresh_networks_list_from_sysfs(
tx_errors,
old_tx_errors: tx_errors,
mac_addr: MacAddr::UNSPECIFIED,
ip_networks: vec![],
// rx_compressed,
// old_rx_compressed: rx_compressed,
// tx_compressed,
Expand Down Expand Up @@ -163,6 +164,7 @@ pub(crate) struct NetworkDataInner {
old_tx_errors: u64,
/// MAC address
pub(crate) mac_addr: MacAddr,
pub(crate) ip_networks: Vec<IpNetwork>,
// /// Indicates the number of compressed packets received by this
// /// network device. This value might only be relevant for interfaces
// /// that support packet compression (e.g: PPP).
Expand Down Expand Up @@ -271,6 +273,10 @@ impl NetworkDataInner {
pub(crate) fn mac_address(&self) -> MacAddr {
self.mac_addr
}

pub(crate) fn ip_networks(&self) -> &[IpNetwork] {
&self.ip_networks
}
}

#[cfg(test)]
Expand Down