pub mod open;
pub mod update;
pub mod update_builder;
pub mod notification;
pub mod keepalive;
pub mod routerefresh;
use octseq::{Octets, Parser};
use crate::util::parser::ParseError;
use std::error::Error;
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
use std::io::Read;
use inetnum::addr::PrefixError;
use crate::typeenum;
use log::debug;
#[cfg(feature = "serde")]
use serde::{Serialize, Deserialize};
pub use open::OpenMessage;
pub use update::{PduParseInfo, SessionConfig, UpdateMessage};
pub use notification::NotificationMessage;
pub use keepalive::KeepaliveMessage;
pub use routerefresh::RouteRefreshMessage;
#[derive(Clone)]
pub enum Message<Octs: Octets> {
Open(OpenMessage<Octs>),
Update(UpdateMessage<Octs>),
Notification(NotificationMessage<Octs>),
Keepalive(KeepaliveMessage<Octs>),
RouteRefresh(RouteRefreshMessage<Octs>),
}
impl<Octs: Octets> AsRef<[u8]> for Message<Octs> {
fn as_ref(&self) -> &[u8] {
match self {
Message::Open(m) => m.as_ref(),
Message::Update(m) => m.as_ref(),
Message::Notification(m) => m.as_ref(),
Message::Keepalive(m) => m.as_ref(),
Message::RouteRefresh(m) => m.as_ref(),
}
}
}
impl<Octs: Octets> Message<Octs> {
fn octets(&self) -> &Octs {
match self {
Message::Open(m) => m.octets(),
Message::Update(m) => m.octets(),
Message::Notification(m) => m.octets(),
Message::Keepalive(m) => m.octets(),
Message::RouteRefresh(m) => m.octets(),
}
}
}
impl<Octs: Octets> Message<Octs> {
fn header(&self) -> Header<Octs::Range<'_>> {
Header::for_slice(self.octets().range(..19))
}
pub fn length(&self) -> u16 {
self.header().length()
}
pub fn msg_type(&self) -> MsgType {
self.header().msg_type()
}
}
typeenum!(
MsgType, u8,
{
1 => Open,
2 => Update,
3 => Notification,
4 => Keepalive,
5 => RouteRefresh, }
);
impl<Octs: Octets> Message<Octs> {
pub fn from_octets(octets: Octs, config: Option<&SessionConfig>)
-> Result<Message<Octs>, ParseError>
{
let mut parser = Parser::from_ref(&octets);
let msg_type;
{
let hdr = Header::parse(&mut parser)?;
parser.seek(0)?;
msg_type = hdr.msg_type();
}
match msg_type {
MsgType::Open =>
Ok(Message::Open(OpenMessage::from_octets(octets)?)),
MsgType::Update => {
let config = if let Some(c) = config {
c
} else {
return Err(ParseError::StateRequired)
};
Ok(Message::Update(
UpdateMessage::from_octets(octets, config)?
))
},
MsgType::Notification =>
Ok(Message::Notification(
NotificationMessage::from_octets(octets)?
)),
MsgType::Keepalive =>
Ok(Message::Keepalive(
KeepaliveMessage::from_octets(octets)?
)),
MsgType::RouteRefresh => {
debug!("Unimplemented BGP message type ROUTEREFRESH");
Err(ParseError::Unsupported)
}
MsgType::Unimplemented(t) => {
debug!("Unimplemented BGP message type {t}");
Err(ParseError::Unsupported)
}
}
}
}
pub fn read_message<'a, T: Read>(bytes: &mut T, buf: &'a mut [u8; 4096])
-> Result<Option<&'a [u8]>, &'a str>
{
if let Err(e) = bytes.read_exact(&mut buf[..18]) {
match e.kind() {
std::io::ErrorKind::UnexpectedEof => { return Ok(None) }
_ => return Err("io error")
}
}
let len = u16::from_be_bytes([buf[16], buf[17]]) as usize;
if len > 4096 {
println!("jumbo? (len: {len}) {:x?}", &buf[..20]);
}
let _ = bytes.read_exact(&mut buf[18..(len)]);
Ok(Some(&buf[..len]))
}
impl<Octs: Octets> TryFrom<Message<Octs>> for OpenMessage<Octs> {
type Error = MessageError;
fn try_from(msg: Message<Octs>) -> Result<Self, Self::Error> {
match msg {
Message::Open(u) => Ok(u),
_ => Err(MessageError::InvalidMsgType),
}
}
}
impl<Octs: Octets> TryFrom<Message<Octs>> for UpdateMessage<Octs> {
type Error = MessageError;
fn try_from(msg: Message<Octs>) -> Result<Self, Self::Error> {
match msg {
Message::Update(u) => Ok(u),
_ => Err(MessageError::InvalidMsgType),
}
}
}
impl<Octs: Octets> TryFrom<Message<Octs>> for NotificationMessage<Octs> {
type Error = MessageError;
fn try_from(msg: Message<Octs>) -> Result<Self, Self::Error> {
match msg {
Message::Notification(u) => Ok(u),
_ => Err(MessageError::InvalidMsgType),
}
}
}
#[derive(Clone, Copy, Default)]
pub struct Header<Octs>(Octs);
impl<Octs: AsMut<[u8]>> Header<Octs> {
pub fn set_type(&mut self, typ: MsgType) {
self.0.as_mut()[18] = typ.into();
}
pub fn set_length(&mut self, len: u16) {
self.0.as_mut()[16..=17].copy_from_slice( &(len.to_be_bytes()) );
}
}
impl<Octs: Octets> AsRef<[u8]> for Header<Octs> {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
impl Header<&mut [u8]> {
pub fn for_slice_mut(s: &mut [u8]) -> Header<&mut [u8]> {
Header(s)
}
}
impl<Octs: Octets> Header<Octs> {
pub fn new() -> Header<Vec<u8>> {
let mut buf = vec![0xff; 19]; buf[16] = 0; buf[17] = 0x13; buf[18] = 0; Header::<Vec<u8>>(buf)
}
pub fn for_slice(s: Octs) -> Self {
Header(s)
}
pub fn length(&self) -> u16 {
u16::from_be_bytes([self.0.as_ref()[16], self.0.as_ref()[17]])
}
pub fn msg_type(&self) -> MsgType {
match self.0.as_ref()[18] {
1 => MsgType::Open,
2 => MsgType::Update,
3 => MsgType::Notification,
4 => MsgType::Keepalive,
5 => MsgType::RouteRefresh,
u => MsgType::Unimplemented(u)
}
}
}
impl<Octs: Octets> Header<Octs> {
fn parse<'a, R>(parser: &mut Parser<'a, R>) -> Result<Self, ParseError>
where
R: Octets<Range<'a> = Octs>
{
let pos = parser.pos();
Marker::check(parser)?;
let _len = parser.parse_u16_be()?;
let _typ = parser.parse_u8()?;
parser.seek(pos)?;
let res = parser.parse_octets(19)?;
Ok(Header(res))
}
}
impl<Octs: Octets> Header<Octs> {
pub fn check(parser: &mut Parser<'_, Octs>) -> Result<(), ParseError> {
Marker::check(parser)?;
let len = parser.parse_u16_be()? as usize;
if len != parser.len() {
return Err(ParseError::form_error("invalid length"));
}
parser.advance(1)?;
Ok(())
}
}
struct Marker;
impl Marker {
fn check<R: Octets>(parser: &mut Parser<'_, R>)
-> Result<(), ParseError>
{
let mut buf = [0u8; 16];
parser.parse_buf(&mut buf)?;
if buf != [
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
] {
return Err(ParseError::form_error("invalid BGP marker"))
}
Ok(())
}
}
#[derive(Debug)]
pub enum MessageError {
IllegalNlris,
InvalidMsgType,
}
impl Display for MessageError {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
use MessageError::*;
match self {
IllegalNlris => write!(f, "illegal NLRIs"),
InvalidMsgType => write!(f, "invalid Message type"),
}
}
}
impl Error for MessageError { }
impl From<PrefixError> for ParseError {
fn from(_e: PrefixError) -> ParseError {
ParseError::form_error("failed to parse prefix")
}
}