Files
ferrix/crates/packet/src/errors.rs
T

249 lines
6.2 KiB
Rust

use serde::{Deserialize, Serialize};
use strum::FromRepr;
use thiserror::Error;
#[derive(Debug, Error)]
#[error("Unknown BGP error code {code} subcode {subcode}")]
pub struct UnknownErrorCode {
pub code: u8,
pub subcode: u8,
}
#[derive(Debug, Clone, PartialEq, Eq, Error, Serialize, Deserialize)]
#[repr(u8)]
pub enum BgpError {
#[error("Message header error")]
MsgHeader(MsgHeaderSubcode) = 1,
#[error("Open message error")]
OpenMsg(OpenMsgSubcode) = 2,
#[error("Update message error")]
UpdateMsg(UpdateMsgSubcode) = 3,
#[error("Hold timer expired")]
HoldTimer = 4,
#[error("Finite state machine error")]
FsmError(FsmSubcode) = 5,
#[error("Cease")]
Cease(CeaseSubcode) = 6,
#[error("Route refresh message error")]
RouteRefresh(RouteRefreshSubcode) = 7,
#[error("Send hold timer expired")]
SendHoldTimer = 8,
}
impl BgpError {
pub fn from_code_subcode(code: u8, subcode: u8) -> Result<Self, UnknownErrorCode> {
let err = || UnknownErrorCode { code, subcode };
match code {
1 => Ok(Self::MsgHeader(
MsgHeaderSubcode::try_from(subcode).map_err(|_| err())?,
)),
2 => Ok(Self::OpenMsg(
OpenMsgSubcode::try_from(subcode).map_err(|_| err())?,
)),
3 => Ok(Self::UpdateMsg(
UpdateMsgSubcode::try_from(subcode).map_err(|_| err())?,
)),
4 => Ok(Self::HoldTimer),
5 => Ok(Self::FsmError(
FsmSubcode::try_from(subcode).map_err(|_| err())?,
)),
6 => Ok(Self::Cease(
CeaseSubcode::try_from(subcode).map_err(|_| err())?,
)),
7 => Ok(Self::RouteRefresh(
RouteRefreshSubcode::try_from(subcode).map_err(|_| err())?,
)),
8 => Ok(Self::SendHoldTimer),
_ => Err(err()),
}
}
pub fn code_subcode(&self) -> (u8, u8) {
match self {
Self::MsgHeader(s) => (1, *s as u8),
Self::OpenMsg(s) => (2, *s as u8),
Self::UpdateMsg(s) => (3, *s as u8),
Self::HoldTimer => (4, 0),
Self::FsmError(s) => (5, *s as u8),
Self::Cease(s) => (6, *s as u8),
Self::RouteRefresh(s) => (7, *s as u8),
Self::SendHoldTimer => (8, 0),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Error, Serialize, Deserialize, FromRepr)]
#[repr(u8)]
pub enum MsgHeaderSubcode {
#[error("Connection not synchronized")]
ConnNotSynchronized = 1,
#[error("Bad message length")]
BadMessageLength = 2,
#[error("Bad message type")]
BadMessageType = 3,
}
impl TryFrom<u8> for MsgHeaderSubcode {
type Error = ();
fn try_from(v: u8) -> Result<Self, ()> {
Self::from_repr(v).ok_or(())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Error, Serialize, Deserialize, FromRepr)]
#[repr(u8)]
pub enum OpenMsgSubcode {
#[error("Unsupported BGP version number")]
UnsupportedVersion = 1,
#[error("Bad peer AS number")]
BadPeerAs = 2,
#[error("Bad BGP identifier")]
BadBgpId = 3,
#[error("Unsupported optional parameter")]
UnsupportedOptionalParam = 4,
#[error("Unacceptable hold time")]
UnacceptableHoldTime = 6,
#[error("Unsupported capability")]
UnsupportedCapability = 7,
#[error("Role mismatch")]
RoleMismatch = 8,
}
impl TryFrom<u8> for OpenMsgSubcode {
type Error = ();
fn try_from(v: u8) -> Result<Self, ()> {
Self::from_repr(v).ok_or(())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Error, Serialize, Deserialize, FromRepr)]
#[repr(u8)]
pub enum UpdateMsgSubcode {
#[error("Malformed attribute list")]
MalformedAttrs = 1,
#[error("Unrecognized well known attribute")]
UnrecognizedWellKnownAttr = 2,
#[error("Missing well known attribute")]
MissingWellKnown = 3,
#[error("Attribute flags error")]
AttributeFlags = 4,
#[error("Attribute length error")]
AttributeLength = 5,
#[error("Invalid origin")]
InvalidOrigin = 6,
#[error("Invalid next hop")]
InvalidNextHop = 8,
#[error("Optional attribute error")]
OptionalAttribute = 9,
#[error("Invalid network field")]
InvalidNetworkField = 10,
#[error("Malformed AS path")]
MalformedAsPath = 11,
}
impl TryFrom<u8> for UpdateMsgSubcode {
type Error = ();
fn try_from(v: u8) -> Result<Self, ()> {
Self::from_repr(v).ok_or(())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Error, Serialize, Deserialize, FromRepr)]
#[repr(u8)]
pub enum FsmSubcode {
#[error("Received an unexpected message in OpenSent state")]
UnexpectedOpenSent = 1,
#[error("Received an unexpected message in OpenConfirm state")]
UnexpectedOpenConfirm = 2,
#[error("Received an unexpected message in Established state")]
UnexpectedEstablished = 3,
}
impl TryFrom<u8> for FsmSubcode {
type Error = ();
fn try_from(v: u8) -> Result<Self, ()> {
Self::from_repr(v).ok_or(())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Error, Serialize, Deserialize, FromRepr)]
#[repr(u8)]
pub enum CeaseSubcode {
#[error("Maximum number of prefixes reached")]
MaxPrefixes = 1,
#[error("Administrative shutdown")]
AdminShutdown = 2,
#[error("Peer deconfigured")]
PeerDeconf = 3,
#[error("Administrative reset")]
AdminReset = 4,
#[error("Connection rejected")]
ConnRejected = 5,
#[error("Configuration change")]
ConfChange = 6,
#[error("Connection collision resolution")]
ConnCollisionResolution = 7,
#[error("Out of resources")]
OutOfResources = 8,
#[error("Hard reset")]
HardReset = 9,
#[error("BFD down")]
BfdDown = 10,
}
impl TryFrom<u8> for CeaseSubcode {
type Error = ();
fn try_from(v: u8) -> Result<Self, ()> {
Self::from_repr(v).ok_or(())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Error, Serialize, Deserialize, FromRepr)]
#[repr(u8)]
pub enum RouteRefreshSubcode {
#[error("Invalid message length")]
InvalidLength = 1,
}
impl TryFrom<u8> for RouteRefreshSubcode {
type Error = ();
fn try_from(v: u8) -> Result<Self, ()> {
Self::from_repr(v).ok_or(())
}
}