netdev 0.41.0

Cross-platform library for enumerating network interfaces with metadata.
Documentation
use crate::interface::interface::Interface;

const SIOCGIFFLAGS: libc::c_ulong = 0xc0206911;

pub fn is_physical_interface(interface: &Interface) -> bool {
    interface.is_up() && interface.is_running() && !interface.is_tun() && !interface.is_loopback()
}

pub fn get_interface_flags(if_name: &str) -> std::io::Result<u32> {
    use libc::ifreq as IfReq;
    use libc::{AF_INET, SOCK_DGRAM, c_char, ioctl, socket};
    use std::mem;
    use std::os::unix::io::RawFd;
    use std::ptr;

    let sock: RawFd = unsafe { socket(AF_INET, SOCK_DGRAM, 0) };
    if sock < 0 {
        return Err(std::io::Error::last_os_error());
    }

    let mut ifr: IfReq = unsafe { mem::zeroed() };

    let ifname_c = std::ffi::CString::new(if_name).map_err(|_| std::io::ErrorKind::InvalidInput)?;
    let bytes = ifname_c.as_bytes_with_nul();

    if bytes.len() > ifr.ifr_name.len() {
        unsafe { libc::close(sock) };
        return Err(std::io::ErrorKind::InvalidInput.into());
    }

    unsafe {
        ptr::copy_nonoverlapping(
            bytes.as_ptr() as *const c_char,
            ifr.ifr_name.as_mut_ptr(),
            bytes.len(),
        );
    }

    let res = unsafe { ioctl(sock, SIOCGIFFLAGS, &mut ifr) };
    unsafe { libc::close(sock) };

    if res < 0 {
        Err(std::io::Error::last_os_error())
    } else {
        Ok(unsafe { ifr.ifr_ifru.ifru_flags as u32 })
    }
}