#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("socket creation failed")]
Socket(#[source] std::io::Error),
#[error("mmap failed")]
Mmap(#[source] std::io::Error),
#[error("invalid configuration: {0}")]
Config(String),
#[error("interface not found: {0}")]
InterfaceNotFound(String),
#[error("bind failed")]
Bind(#[source] std::io::Error),
#[error("setsockopt({option}) failed")]
SockOpt {
option: &'static str,
#[source]
source: std::io::Error,
},
#[error("insufficient privileges (need CAP_NET_RAW)")]
PermissionDenied,
#[error(transparent)]
Io(#[from] std::io::Error),
#[cfg(feature = "xdp-loader")]
#[error("XDP loader: {0}")]
Loader(String),
#[error("BPF filter: {0}")]
Bpf(#[from] crate::config::BuildError),
}
pub type Result<T> = std::result::Result<T, Error>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn error_is_send_sync() {
fn assert_send_sync<T: Send + Sync>() {}
assert_send_sync::<Error>();
}
#[test]
fn from_io_error() {
let io_err = std::io::Error::other("test");
let err: Error = io_err.into();
assert!(matches!(err, Error::Io(_)));
}
#[test]
fn display_variants() {
let e = Error::Config("bad block_size".into());
assert_eq!(e.to_string(), "invalid configuration: bad block_size");
let e = Error::InterfaceNotFound("eth99".into());
assert_eq!(e.to_string(), "interface not found: eth99");
let e = Error::PermissionDenied;
assert!(e.to_string().contains("CAP_NET_RAW"));
let io_err = std::io::Error::other("fail");
let e = Error::SockOpt {
option: "PACKET_VERSION",
source: io_err,
};
assert!(e.to_string().contains("PACKET_VERSION"));
}
}