use crate::afi::*;
use crate::*;
use std::cmp::Ordering;
pub fn decode_bmp_addr_from(buf: &[u8]) -> Result<std::net::IpAddr, BgpError> {
if buf.len() < 16 {
return Err(BgpError::InsufficientBufferSize(file!(), line!()));
}
if buf[0] == 0
&& buf[1] == 0
&& buf[2] == 0
&& buf[3] == 0
&& buf[4] == 0
&& buf[5] == 0
&& buf[6] == 0
&& buf[7] == 0
&& buf[8] == 0
&& buf[9] == 0
&& buf[10] == 0
&& buf[11] == 0
{
Ok(std::net::IpAddr::V4(decode_addrv4_from(&buf[12..])?))
} else {
Ok(std::net::IpAddr::V6(decode_addrv6_from(buf)?))
}
}
pub fn encode_bmp_addr_to(addr: &std::net::IpAddr, buf: &mut [u8]) -> Result<usize, BgpError> {
if buf.len() < 16 {
return Err(BgpError::InsufficientBufferSize(file!(), line!()));
}
match addr {
std::net::IpAddr::V4(v4) => {
for byte in buf.iter_mut() {
*byte = 0;
}
encode_addrv4_to(v4, &mut buf[12..])?;
}
std::net::IpAddr::V6(v6) => {
encode_addrv6_to(v6, buf)?;
}
}
Ok(16)
}
#[derive(Debug, Clone)]
pub struct BmpMessagePeerHeader {
pub peertype: u8,
pub flags: u8,
pub peerdistinguisher: BgpRD,
pub peeraddress: std::net::IpAddr,
pub asnum: u32,
pub routerid: std::net::Ipv4Addr,
pub timestamp: u64,
}
impl BmpMessagePeerHeader {
pub fn decode_from(buf: &[u8]) -> Result<(BmpMessagePeerHeader, usize), BgpError> {
if buf.len() < 42 {
return Err(BgpError::InsufficientBufferSize(file!(), line!()));
}
Ok((
BmpMessagePeerHeader {
peertype: buf[0],
flags: buf[1],
peerdistinguisher: BgpRD::decode_from(BgpTransportMode::IPv4, &buf[2..])?.0,
peeraddress: decode_bmp_addr_from(&buf[10..])?,
asnum: getn_u32(&buf[26..]),
routerid: decode_addrv4_from(&buf[30..])?,
timestamp: getn_u64(&buf[34..]),
},
42,
))
}
pub fn encode_to(&self, buf: &mut [u8]) -> Result<usize, BgpError> {
if buf.len() < 42 {
return Err(BgpError::InsufficientBufferSize(file!(), line!()));
}
buf[0] = self.peertype;
buf[1] = self.flags;
self.peerdistinguisher
.encode_to(BgpTransportMode::IPv4, &mut buf[2..])?;
encode_bmp_addr_to(&self.peeraddress, &mut buf[10..])?;
setn_u32(self.asnum, &mut buf[26..]);
encode_addrv4_to(&self.routerid, &mut buf[30..])?;
setn_u64(self.timestamp, &mut buf[34..]);
Ok(42)
}
}
impl PartialOrd for BmpMessagePeerHeader {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
if let Some(pc) = self.peertype.partial_cmp(&other.peertype) {
match pc {
Ordering::Less => return Some(Ordering::Less),
Ordering::Greater => return Some(Ordering::Greater),
Ordering::Equal => {}
}
};
if let Some(pc) = self.flags.partial_cmp(&other.flags) {
match pc {
Ordering::Less => return Some(Ordering::Less),
Ordering::Greater => return Some(Ordering::Greater),
Ordering::Equal => {}
}
};
if let Some(pc) = self.peerdistinguisher.partial_cmp(&other.peerdistinguisher) {
match pc {
Ordering::Less => return Some(Ordering::Less),
Ordering::Greater => return Some(Ordering::Greater),
Ordering::Equal => {}
}
};
if let Some(pc) = self.peeraddress.partial_cmp(&other.peeraddress) {
match pc {
Ordering::Less => return Some(Ordering::Less),
Ordering::Greater => return Some(Ordering::Greater),
Ordering::Equal => {}
}
};
if let Some(pc) = self.asnum.partial_cmp(&other.asnum) {
match pc {
Ordering::Less => return Some(Ordering::Less),
Ordering::Greater => return Some(Ordering::Greater),
Ordering::Equal => {}
}
};
self.routerid.partial_cmp(&other.routerid)
}
}
impl Ord for BmpMessagePeerHeader {
fn cmp(&self, other: &Self) -> Ordering {
match self.peertype.cmp(&other.peertype) {
Ordering::Equal => {}
x => return x,
};
match self.flags.cmp(&other.flags) {
Ordering::Equal => {}
x => return x,
};
match self.peerdistinguisher.cmp(&other.peerdistinguisher) {
Ordering::Equal => {}
x => return x,
};
match self.peeraddress.cmp(&other.peeraddress) {
Ordering::Equal => {}
x => return x,
};
match self.asnum.cmp(&other.asnum) {
Ordering::Equal => {}
x => return x,
};
self.routerid.cmp(&other.routerid)
}
}
impl PartialEq for BmpMessagePeerHeader {
fn eq(&self, other: &Self) -> bool {
self.peertype == other.peertype
&& self.flags == other.flags
&& self.peerdistinguisher == other.peerdistinguisher
&& self.peeraddress == other.peeraddress
&& self.asnum == other.asnum
&& self.routerid == other.routerid
}
}
impl Eq for BmpMessagePeerHeader {}
impl From<&BmpMessagePeerHeader> for BgpSessionParams {
#[inline]
fn from(bmph: &BmpMessagePeerHeader) -> BgpSessionParams {
BgpSessionParams::new(
bmph.asnum,
0,
bmph.peeraddress.into(),
bmph.routerid,
Vec::new(),
)
}
}