Skip to content

Commit

Permalink
Merge pull request #1004 from GuillaumeGomez/network-interfaces
Browse files Browse the repository at this point in the history
Improve code to retrieve network interfaces
  • Loading branch information
GuillaumeGomez committed Jul 3, 2023
2 parents e3c9764 + 2628c61 commit 84da136
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 23 deletions.
13 changes: 9 additions & 4 deletions src/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,16 @@ use crate::NetworkData;

/// Interface addresses are OS-independent
pub(crate) fn refresh_networks_addresses(interfaces: &mut HashMap<String, NetworkData>) {
if let Ok(ifa_iterator) = get_interface_address() {
for (name, ifa) in ifa_iterator {
if let Some(interface) = interfaces.get_mut(&name) {
interface.mac_addr = ifa;
match get_interface_address() {
Ok(ifa_iterator) => {
for (name, ifa) in ifa_iterator {
if let Some(interface) = interfaces.get_mut(&name) {
interface.mac_addr = ifa;
}
}
}
Err(_e) => {
sysinfo_debug!("refresh_networks_addresses failed: {:?}", _e);
}
}
}
50 changes: 32 additions & 18 deletions src/network_helper_win.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ use winapi::um::iptypes::{

use crate::common::MacAddr;

// Need a function to convert u16 pointer into String
// https://stackoverflow.com/a/48587463/8706476
unsafe fn u16_ptr_to_string(ptr: *const u16) -> OsString {
let len = (0..).take_while(|&i| *ptr.offset(i) != 0).count();
let slice = std::slice::from_raw_parts(ptr, len);

OsString::from_wide(slice)
}

/// this iterator yields an interface name and address
pub(crate) struct InterfaceAddressIterator {
/// The first item in the linked list
Expand All @@ -21,13 +30,26 @@ pub(crate) struct InterfaceAddressIterator {
adapter: PIP_ADAPTER_ADDRESSES,
}

// Need a function to convert u16 pointer into String
// https://stackoverflow.com/a/48587463/8706476
unsafe fn u16_ptr_to_string(ptr: *const u16) -> OsString {
let len = (0..).take_while(|&i| *ptr.offset(i) != 0).count();
let slice = std::slice::from_raw_parts(ptr, len);

OsString::from_wide(slice)
impl InterfaceAddressIterator {
fn new() -> Self {
Self {
buf: null_mut(),
adapter: null_mut(),
}
}
unsafe fn realloc(mut self, size: libc::size_t) -> Result<Self, String> {
let new_buf = libc::realloc(self.buf as _, size) as PIP_ADAPTER_ADDRESSES;
if new_buf.is_null() {
// insufficient memory available
// https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/malloc?view=msvc-170#return-value
// malloc is not documented to set the last-error code
Err("failed to allocate memory for IP_ADAPTER_ADDRESSES".to_string())
} else {
self.buf = new_buf;
self.adapter = new_buf;
Ok(self)
}
}
}

impl Iterator for InterfaceAddressIterator {
Expand Down Expand Up @@ -67,25 +89,17 @@ pub(crate) fn get_interface_address() -> Result<InterfaceAddressIterator, String
// A 15k buffer is recommended
let mut size: u32 = 15 * 1024;
let mut ret = ERROR_SUCCESS;
let mut iterator = InterfaceAddressIterator::new();

// https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getadaptersaddresses#examples
// Try to retrieve adapter information up to 3 times
for _ in 0..3 {
let buf = libc::malloc(size as _) as PIP_ADAPTER_ADDRESSES;
// free memory on drop
let iterator = InterfaceAddressIterator { buf, adapter: buf };
if buf.is_null() {
// insufficient memory available
// https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/malloc?view=msvc-170#return-value
// malloc is not documented to set the last-error code
return Err("failed to allocate memory for IP_ADAPTER_ADDRESSES".to_string());
}

iterator = iterator.realloc(size as _)?;
ret = GetAdaptersAddresses(
AF_UNSPEC as u32,
GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_DNS_SERVER,
null_mut(),
buf,
iterator.buf,
&mut size,
);
if ret == ERROR_SUCCESS {
Expand Down
2 changes: 1 addition & 1 deletion src/windows/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub(crate) unsafe fn to_str(p: LPWSTR) -> String {
fn utf16_str<S: AsRef<OsStr> + ?Sized>(text: &S) -> Vec<u16> {
OsStr::new(text)
.encode_wide()
.chain(Some(0).into_iter())
.chain(Some(0))
.collect::<Vec<_>>()
}

Expand Down

0 comments on commit 84da136

Please sign in to comment.