use ethtool::EthtoolError;
use libc::{EEXIST, EPERM};
use netlink_packet_utils::DecodeError;
use serde::Serialize;
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum ErrorKind {
InvalidArgument,
NetlinkError,
NisporBug,
PermissionDeny,
}
impl std::fmt::Display for ErrorKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{self:?}")
}
}
#[derive(Debug, Clone, Serialize)]
#[non_exhaustive]
pub struct NisporError {
pub kind: ErrorKind,
pub msg: String,
}
impl NisporError {
pub(crate) fn bug(message: String) -> NisporError {
NisporError {
kind: ErrorKind::NisporBug,
msg: message,
}
}
pub(crate) fn permission_deny(message: String) -> NisporError {
NisporError {
kind: ErrorKind::PermissionDeny,
msg: message,
}
}
pub(crate) fn invalid_argument(message: String) -> NisporError {
NisporError {
kind: ErrorKind::InvalidArgument,
msg: message,
}
}
}
impl std::fmt::Display for NisporError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.msg)
}
}
impl std::error::Error for NisporError {
}
impl std::convert::From<rtnetlink::Error> for NisporError {
fn from(e: rtnetlink::Error) -> Self {
match e {
rtnetlink::Error::NetlinkError(netlink_err) => {
match netlink_err.raw_code().abs() {
EEXIST => NisporError::bug(format!(
"Got netlink EEXIST error: {netlink_err}"
)),
EPERM => {
NisporError::permission_deny(format!("{netlink_err}",))
}
_ => NisporError::bug(format!(
"Got netlink unknown error: code {}, msg: {}",
netlink_err.raw_code(),
netlink_err,
)),
}
}
_ => NisporError {
kind: ErrorKind::NetlinkError,
msg: e.to_string(),
},
}
}
}
impl std::convert::From<EthtoolError> for NisporError {
fn from(e: EthtoolError) -> Self {
NisporError {
kind: ErrorKind::NetlinkError,
msg: e.to_string(),
}
}
}
impl std::convert::From<std::ffi::FromBytesWithNulError> for NisporError {
fn from(e: std::ffi::FromBytesWithNulError) -> Self {
NisporError {
kind: ErrorKind::NisporBug,
msg: format!("FromBytesWithNulError: {e}"),
}
}
}
impl std::convert::From<std::str::Utf8Error> for NisporError {
fn from(e: std::str::Utf8Error) -> Self {
NisporError {
kind: ErrorKind::NisporBug,
msg: format!("Utf8Error: {e}"),
}
}
}
impl std::convert::From<DecodeError> for NisporError {
fn from(e: DecodeError) -> Self {
NisporError {
kind: ErrorKind::NetlinkError,
msg: e.to_string(),
}
}
}
impl std::convert::From<std::io::Error> for NisporError {
fn from(e: std::io::Error) -> Self {
NisporError {
kind: ErrorKind::NisporBug,
msg: e.to_string(),
}
}
}
impl std::convert::From<std::net::AddrParseError> for NisporError {
fn from(e: std::net::AddrParseError) -> Self {
NisporError {
kind: ErrorKind::InvalidArgument,
msg: e.to_string(),
}
}
}
impl std::convert::From<mptcp_pm::MptcpPathManagerError> for NisporError {
fn from(e: mptcp_pm::MptcpPathManagerError) -> Self {
NisporError {
kind: ErrorKind::NetlinkError,
msg: e.to_string(),
}
}
}