use crate::sockaddr;
use libc::{freeifaddrs, getifaddrs, ifaddrs};
use std::net::IpAddr;
use std::{io, mem};
pub fn do_broadcast(ifaddr: &ifaddrs) -> Option<IpAddr> {
#[cfg(any(
target_os = "linux",
target_os = "android",
target_os = "l4re",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "hurd",
target_os = "nacl",
))]
let sockaddr = ifaddr.ifa_ifu;
#[cfg(not(any(
target_os = "linux",
target_os = "android",
target_os = "l4re",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "hurd",
target_os = "nacl",
)))]
let sockaddr = ifaddr.ifa_dstaddr;
sockaddr::to_ipaddr(sockaddr)
}
pub struct IfAddrs {
inner: *mut ifaddrs,
}
impl IfAddrs {
#[allow(unsafe_code, clippy::new_ret_no_self)]
pub fn new() -> io::Result<Self> {
let mut ifaddrs = mem::MaybeUninit::uninit();
unsafe {
if -1 == getifaddrs(ifaddrs.as_mut_ptr()) {
return Err(io::Error::last_os_error());
}
Ok(Self {
inner: ifaddrs.assume_init(),
})
}
}
pub fn iter(&self) -> IfAddrsIterator {
IfAddrsIterator { next: self.inner }
}
}
impl Drop for IfAddrs {
#[allow(unsafe_code)]
fn drop(&mut self) {
unsafe {
freeifaddrs(self.inner);
}
}
}
pub struct IfAddrsIterator {
next: *mut ifaddrs,
}
impl Iterator for IfAddrsIterator {
type Item = ifaddrs;
#[allow(unsafe_code)]
fn next(&mut self) -> Option<Self::Item> {
if self.next.is_null() {
return None;
};
Some(unsafe {
let result = *self.next;
self.next = (*self.next).ifa_next;
result
})
}
}