powerline 0.1.0

Work-in-progress: Power-line communication library
Documentation
extern crate std;

use crate::{linux::*, unix::*, *};
use core::convert::TryInto;
use libc::{ifaddrs, sockaddr_ll};
use libc::{AF_PACKET, IFF_LOOPBACK, IFF_UP};
use std::borrow::ToOwned;
use std::ffi::{CStr, CString};
use std::io::{Error, Result};

pub struct LinuxInterface {
    name: CString,
    flags: i32,
    address: EtherAddr,
}
impl LinuxInterface {
    pub fn interfaces() -> Result<UnixInterfaceIter<LinuxInterface>> {
        UnixInterfaceIter::new()
    }
}
impl UnixInterface for LinuxInterface {
    fn new(ifaddr: &ifaddrs) -> Option<LinuxInterface> {
        unsafe {
            if ifaddr.ifa_addr.as_ref()?.sa_family != AF_PACKET as u16 {
                return None;
            }
            let sa = (ifaddr.ifa_addr as *const sockaddr_ll).as_ref().unwrap();
            let address = EtherAddr(sa.sll_addr[..6].try_into().unwrap());
            Some(LinuxInterface {
                name: CStr::from_ptr(ifaddr.ifa_name).to_owned(),
                flags: ifaddr.ifa_flags as i32,
                address,
            })
        }
    }
}
impl EtherInterface for LinuxInterface {
    type Error = Error;
    type Socket = LinuxRawSocket;
    fn open(&self, ethertype: EtherType) -> Result<LinuxRawSocket> {
        LinuxRawSocket::new(ethertype, &self.name)
    }
    fn name(&self) -> &str {
        self.name.to_str().unwrap_or("<INVALID>")
    }
    fn address(&self) -> EtherAddr {
        self.address
    }
    fn is_up(&self) -> bool {
        self.flags & IFF_UP != 0
    }
    fn is_loopback(&self) -> bool {
        self.flags & IFF_LOOPBACK != 0
    }
}
impl std::fmt::Debug for LinuxInterface {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        let status = if self.is_up() { "up" } else { "down" };
        write!(f, "{:?} - {} ({}", self.address(), self.name(), status)?;

        if self.is_loopback() {
            write!(f, " loopback")?;
        }
        write!(f, ")")?;
        Ok(())
    }
}