--- /dev/null
+/// Errors in netwatcher or in one of the underlying platform integratinos.
+#[derive(Debug, Clone, PartialEq, Eq)]
+#[non_exhaustive]
+pub enum Error {
+ CreateSocket(String),
+ Bind(String),
+ CreatePipe(String),
+ Getifaddrs(String),
+ GetInterfaceName(String),
+ FormatMacAddress,
+ UnexpectedWindowsResult(u32),
+ AddressNotAssociated,
+ InvalidParameter,
+ NotEnoughMemory,
+ InvalidHandle,
+}
+
+impl std::fmt::Display for Error {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{:?}", self)
+ }
+}
+
+impl std::error::Error for Error {}
ops::Sub,
};
-use nix::errno::Errno;
+mod error;
#[cfg_attr(windows, path = "list_win.rs")]
#[cfg_attr(unix, path = "list_unix.rs")]
type IfIndex = u32;
+pub use error::Error;
+
/// Information about one network interface at a point in time.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Interface {
pub addrs_removed: Vec<IpAddr>,
}
-/// Errors in netwatcher or in one of the underlying platform integratinos.
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum Error {
- CreateSocket(Errno),
- Bind(Errno),
- CreatePipe(Errno),
- Getifaddrs(Errno),
- GetInterfaceName(Errno),
- FormatMacAddress,
- Internal,
-}
-
#[derive(Default, PartialEq, Eq)]
struct List(HashMap<IfIndex, Interface>);
}
pub(crate) fn list_interfaces() -> Result<List, Error> {
- let addrs = getifaddrs().map_err(|e| Error::Getifaddrs(e))?;
+ let addrs = getifaddrs().map_err(|e| Error::Getifaddrs(e.to_string()))?;
let mut candidates = HashMap::new();
for addr in addrs {
- let index =
- if_nametoindex(addr.interface_name.as_str()).map_err(|e| Error::GetInterfaceName(e))?;
+ let index = if_nametoindex(addr.interface_name.as_str())
+ .map_err(|e| Error::GetInterfaceName(e.to_string()))?;
let candidate = candidates
.entry(addr.interface_name.clone())
.or_insert_with(|| CandidateInterface {
);
match WIN32_ERROR(res) {
ERROR_SUCCESS => break,
- ERROR_ADDRESS_NOT_ASSOCIATED => return Err(Error::Internal),
+ ERROR_ADDRESS_NOT_ASSOCIATED => return Err(Error::AddressNotAssociated),
ERROR_BUFFER_OVERFLOW => {
buf.resize(sizepointer as usize, 0);
continue;
}
- ERROR_INVALID_PARAMETER => return Err(Error::Internal),
- ERROR_NOT_ENOUGH_MEMORY => return Err(Error::Internal),
+ ERROR_INVALID_PARAMETER => return Err(Error::InvalidParameter),
+ ERROR_NOT_ENOUGH_MEMORY => return Err(Error::NotEnoughMemory),
ERROR_NO_DATA => return Ok(List(HashMap::new())), // there aren't any
- _ => return Err(Error::Internal), // TODO: Use FormatMessage to get a string
+ _ => return Err(Error::UnexpectedWindowsResult(res)),
}
}
let mut hw_addr = String::with_capacity(adapter.PhysicalAddressLength as usize * 3);
for i in 0..adapter.PhysicalAddressLength as usize {
if i != 0 {
- write!(hw_addr, ":").map_err(|_| Error::Internal)?;
+ write!(hw_addr, ":").map_err(|_| Error::FormatMacAddress)?;
}
write!(hw_addr, "{:02X}", adapter.PhysicalAddress[i])
- .map_err(|_| Error::Internal)?;
+ .map_err(|_| Error::FormatMacAddress)?;
}
let mut ips = vec![];
let mut unicast_ptr = adapter.FirstUnicastAddress;
SockFlag::empty(),
Some(SockProtocol::NetlinkRoute),
)
- .map_err(|e| Error::CreateSocket(e))?;
- // TODO: set nonblocking
+ .map_err(|e| Error::CreateSocket(e.to_string()))?;
+ sockfd.set_nonblocking(true);
let sa_nl = NetlinkAddr::new(
0,
(RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR) as u32,
);
- bind(sockfd.as_raw_fd(), &sa_nl).map_err(|e| Error::Bind(e))?;
- let (pipe_rd, pipe_wr) = pipe().map_err(|e| Error::CreatePipe(e))?;
+ bind(sockfd.as_raw_fd(), &sa_nl).map_err(|e| Error::Bind(e.to_string()))?;
+ let (pipe_rd, pipe_wr) = pipe().map_err(|e| Error::CreatePipe(e.to_string()))?;
let mut prev_list = List::default();
let mut handle_update = move |new_list: List| {