use crate::prelude::*;
#[cfg(feature = "serialization")]
use serde::{Deserialize, Serialize};
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg(feature = "serialization")]
#[derive(Serialize, Deserialize)]
pub struct BgpMPUpdates {
pub nexthop: BgpAddr,
pub addrs: BgpAddrs,
}
impl BgpMPUpdates {
pub fn s4vpnv4u(nhop: BgpIPv4RD, nlri: Vec<Labeled<WithRd<BgpAddrV4>>>) -> BgpMPUpdates {
BgpMPUpdates {
nexthop: BgpAddr::V4RD(nhop),
addrs: BgpAddrs::VPNV4U(nlri),
}
}
pub fn s4vpnv4m(nhop: BgpIPv4RD, nlri: Vec<Labeled<WithRd<BgpAddrV4>>>) -> BgpMPUpdates {
BgpMPUpdates {
nexthop: BgpAddr::V4RD(nhop),
addrs: BgpAddrs::VPNV4M(nlri),
}
}
pub fn s4ip4lu(nhop: std::net::Ipv4Addr, nlri: Vec<Labeled<BgpAddrV4>>) -> BgpMPUpdates {
BgpMPUpdates {
nexthop: BgpAddr::V4(nhop),
addrs: BgpAddrs::IPV4LU(nlri),
}
}
pub fn s4ip6lu(nhop: std::net::Ipv4Addr, nlri: Vec<Labeled<BgpAddrV6>>) -> BgpMPUpdates {
BgpMPUpdates {
nexthop: BgpAddr::V4(nhop),
addrs: BgpAddrs::IPV6LU(nlri),
}
}
pub fn s4vpnv6u(nhop: BgpIPv4RD, nlri: Vec<Labeled<WithRd<BgpAddrV6>>>) -> BgpMPUpdates {
BgpMPUpdates {
nexthop: BgpAddr::V4RD(nhop),
addrs: BgpAddrs::VPNV6U(nlri),
}
}
pub fn s4vpnv6m(nhop: BgpIPv4RD, nlri: Vec<Labeled<WithRd<BgpAddrV6>>>) -> BgpMPUpdates {
BgpMPUpdates {
nexthop: BgpAddr::V4RD(nhop),
addrs: BgpAddrs::VPNV6M(nlri),
}
}
pub fn decode_from(peer: &BgpSessionParams, buf: &[u8]) -> Result<BgpMPUpdates, BgpError> {
let afi = getn_u16(buf);
let safi = buf[2];
let mut curpos: usize = 4;
let nh: BgpAddr;
let nhlen = buf[3] as usize;
match afi {
1 => {
match safi {
1 | 2 | 4 | 5 | 66 | 133 => {
nh = if nhlen == 0 {
BgpAddr::None
} else {
BgpAddr::V4(decode_addrv4_from(&buf[curpos..(curpos + nhlen)])?)
};
curpos += nhlen;
}
128 | 129 | 134 => {
let r = BgpIPv4RD::decode_from(peer.peer_mode, &buf[curpos..])?;
nh = BgpAddr::V4RD(r.0);
curpos += r.1;
}
n => {
log::trace!("AFI/SAFI {}/{} {:?}", afi, safi, &buf[curpos..]);
return Err(BgpError::from_string(format!(
"Unknown safi for ipv4 code {:?}",
n
)));
}
}
}
2 => {
match safi {
1 | 2 | 4 | 66 | 133 => {
nh = if nhlen == 0 {
BgpAddr::None
} else {
BgpAddr::V6(decode_addrv6_from(&buf[curpos..(curpos + nhlen)])?)
};
curpos += nhlen;
}
128 | 129 | 134 => {
let r = BgpIPv6RD::decode_from(peer.peer_mode, &buf[curpos..])?;
nh = BgpAddr::V6RD(r.0);
curpos += r.1;
}
n => {
return Err(BgpError::from_string(format!(
"Unknown safi for ipv6: {:?}",
n
)))
}
}
}
25 => {
match safi {
65 | 70 => {
nh = BgpAddr::V4(decode_addrv4_from(&buf[curpos..])?);
curpos += nhlen;
}
n => {
return Err(BgpError::from_string(format!(
"Unknown safi for l2: {:?}",
n
)))
}
}
}
n => return Err(BgpError::from_string(format!("Unknown afi code {:?}", n))),
}
let snpa_count = buf[curpos];
curpos += 1;
for _ in 0..snpa_count {
let snpa_len = buf[curpos] as usize;
curpos += 1 + snpa_len;
}
let ap = BgpAddrs::decode_from(peer, afi, safi, &buf[curpos..])?;
Ok(BgpMPUpdates {
nexthop: nh,
addrs: ap.0,
})
}
}
impl std::fmt::Debug for BgpMPUpdates {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("BgpMPUpdates")
.field("nexthop", &self.nexthop)
.field("addrs", &self.addrs)
.finish()
}
}
impl std::fmt::Display for BgpMPUpdates {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "BgpMPUpdates ({:?} {:?})", self.nexthop, self.addrs)
}
}
impl BgpAttr for BgpMPUpdates {
fn attr(&self) -> BgpAttrParams {
BgpAttrParams {
typecode: 14,
flags: 144,
}
}
fn encode_to(&self, peer: &BgpSessionParams, buf: &mut [u8]) -> Result<usize, BgpError> {
let afisafi = self.addrs.get_afi_safi();
setn_u16(afisafi.0, &mut buf[..2]);
buf[2] = afisafi.1;
let mut curpos: usize = 4;
let nhl = match &self.nexthop {
BgpAddr::None => 0,
BgpAddr::V4(a) => encode_addrv4_to(a, &mut buf[curpos..])?,
BgpAddr::V6(a) => encode_addrv6_to(a, &mut buf[curpos..])?,
BgpAddr::V4RD(a) => a.encode_to(peer.peer_mode, &mut buf[curpos..])?,
BgpAddr::V6RD(a) => a.encode_to(peer.peer_mode, &mut buf[curpos..])?,
_ => return Err(BgpError::static_str("Invalid nexthop kind")),
};
buf[3] = nhl as u8;
curpos += nhl;
buf[curpos] = 0; curpos += 1;
let ps = self.addrs.encode_to(peer, &mut buf[curpos..])?;
curpos += ps;
Ok(curpos)
}
}
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg(feature = "serialization")]
#[derive(Serialize, Deserialize)]
pub struct BgpMPWithdraws {
pub addrs: BgpAddrs,
}
impl BgpMPWithdraws {
pub fn decode_from(peer: &BgpSessionParams, buf: &[u8]) -> Result<BgpMPWithdraws, BgpError> {
let afi = getn_u16(buf);
let safi = buf[2];
let a = BgpAddrs::decode_from(peer, afi, safi, &buf[3..])?;
Ok(BgpMPWithdraws { addrs: a.0 })
}
}
impl std::fmt::Debug for BgpMPWithdraws {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("BgpMPWithdraws")
.field("addrs", &self.addrs)
.finish()
}
}
impl std::fmt::Display for BgpMPWithdraws {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "BgpMPWithdraws ({:?})", self.addrs)
}
}
impl BgpAttr for BgpMPWithdraws {
fn attr(&self) -> BgpAttrParams {
BgpAttrParams {
typecode: 15,
flags: 144,
}
}
fn encode_to(&self, peer: &BgpSessionParams, buf: &mut [u8]) -> Result<usize, BgpError> {
let afisafi = self.addrs.get_afi_safi();
setn_u16(afisafi.0, &mut buf[..2]);
buf[2] = afisafi.1;
let mut curpos: usize = 3;
let ps = self.addrs.encode_to(peer, &mut buf[curpos..])?;
curpos += ps;
Ok(curpos)
}
}