Skip to content

Commit

Permalink
implement bmp encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
yuyuyureka committed Jan 20, 2025
1 parent 9a49b03 commit 1d259df
Show file tree
Hide file tree
Showing 6 changed files with 212 additions and 1 deletion.
31 changes: 31 additions & 0 deletions src/bmp/bmputl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,23 @@ pub fn decode_bmp_addr_from(buf: &[u8]) -> Result<std::net::IpAddr, BgpError> {
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::insufficient_buffer_size());
}
match addr {
std::net::IpAddr::V4(v4) => {
for i in 0..12 {
buf[i] = 0;
}
encode_addrv4_to(v4, &mut buf[12..])?;
}
std::net::IpAddr::V6(v6) => {
encode_addrv6_to(v6, buf)?;
}
}
Ok(16)
}

/// peer header
#[derive(Debug, Clone)]
Expand Down Expand Up @@ -72,6 +89,20 @@ impl BmpMessagePeerHeader {
42,
))
}
pub fn encode_to(&self, buf: &mut [u8]) -> Result<usize, BgpError> {
if buf.len() < 42 {
return Err(BgpError::InsufficientBufferSize);
}
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> {
Expand Down
39 changes: 39 additions & 0 deletions src/bmp/msginit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,20 @@ impl BmpInfoVal {
ln + 4,
))
}
fn encode_to(&self, buf: &mut [u8]) -> Result<usize, BgpError> {
if buf.len() < 4 {
return Err(BgpError::insufficient_buffer_size());
};
let mut curpos = 0;
setn_u16(self.infotype, &mut buf[curpos..]);
curpos += 2;
let info = self.info.as_bytes();
setn_u16(info.len() as u16, &mut buf[curpos..]);
curpos += 2;
buf[curpos..curpos + info.len()].copy_from_slice(info);
curpos += info.len();
Ok(curpos)
}
}

/// BMP init message
Expand Down Expand Up @@ -72,6 +86,31 @@ impl BmpMessageInitiation {
}
Ok((ret, pos))
}
pub fn encode_to(&self, buf: &mut [u8]) -> Result<usize, BgpError> {
let mut curpos: usize = 0;
if let Some(str0) = &self.str0 {
curpos += (BmpInfoVal {
infotype: 0,
info: str0.clone(),
})
.encode_to(&mut buf[curpos..])?;
}
if let Some(sys_descr) = &self.sys_descr {
curpos += (BmpInfoVal {
infotype: 0,
info: sys_descr.clone(),
})
.encode_to(&mut buf[curpos..])?;
}
if let Some(sys_name) = &self.sys_name {
curpos += (BmpInfoVal {
infotype: 0,
info: sys_name.to_string(),
})
.encode_to(&mut buf[curpos..])?;
}
Ok(curpos)
}
}
impl Default for BmpMessageInitiation {
fn default() -> Self {
Expand Down
86 changes: 86 additions & 0 deletions src/bmp/msgpeer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,34 @@ impl BmpMessagePeerUp {
pos += msgt.1;
Ok((ret, pos))
}
pub fn encode_to(&self, buf: &mut [u8]) -> Result<usize, BgpError> {
if buf.len() < 62 {
return Err(BgpError::InsufficientBufferSize);
}
let mut curpos: usize = 0;
curpos += self.peer.encode_to(buf)?;

encode_bmp_addr_to(&self.localaddress, &mut buf[curpos..])?;
curpos += 16;
setn_u16(self.localport, &mut buf[curpos..]);
curpos += 2;
setn_u16(self.remoteport, &mut buf[curpos..]);
curpos += 2;

let sesspars: &BgpSessionParams = &(&self.peer).into();

let messagelen = self.msg1.encode_to(sesspars, &mut buf[curpos + 19..])?;
let blen =
sesspars.prepare_message_buf(&mut buf[curpos..], BgpMessageType::Open, messagelen)?;
curpos += blen;

let messagelen = self.msg2.encode_to(sesspars, &mut buf[curpos + 19..])?;
let blen =
sesspars.prepare_message_buf(&mut buf[curpos..], BgpMessageType::Open, messagelen)?;
curpos += blen;

Ok(curpos)
}
}

impl BmpMessagePeerDown {
Expand Down Expand Up @@ -122,4 +150,62 @@ impl BmpMessagePeerDown {
};
Ok((BmpMessagePeerDown { peer: pm.0, reason }, pos))
}
pub fn encode_to(&self, buf: &mut [u8]) -> Result<usize, BgpError> {
if buf.len() < 43 {
return Err(BgpError::InsufficientBufferSize);
}
let mut curpos: usize = 0;
curpos += self.peer.encode_to(buf)?;

match &self.reason {
BmpMessagePeerDownReason::AdministrativelyClosed(msg) => {
buf[curpos] = 1;
curpos += 1;

if buf.len() - curpos < 19 {
return Err(BgpError::InsufficientBufferSize);
}

let sesspars: &BgpSessionParams = &(&self.peer).into();
let messagelen = msg.encode_to(sesspars, &mut buf[curpos + 19..])?;
let blen =
sesspars.prepare_message_buf(&mut buf[curpos..], BgpMessageType::Notification, messagelen)?;
curpos += blen;
}
BmpMessagePeerDownReason::LocalSystemState(state) => {
buf[curpos] = 2;
curpos += 1;

if buf.len() - curpos < 2 {
return Err(BgpError::InsufficientBufferSize);
}
setn_u16(*state, &mut buf[curpos..]);
curpos += 2;
}
BmpMessagePeerDownReason::RemoteNotification(msg) => {
buf[curpos] = 3;
curpos += 1;

if buf.len() - curpos < 19 {
return Err(BgpError::InsufficientBufferSize);
}

let sesspars: &BgpSessionParams = &(&self.peer).into();
let messagelen = msg.encode_to(sesspars, &mut buf[curpos + 19..])?;
let blen =
sesspars.prepare_message_buf(&mut buf[curpos..], BgpMessageType::Notification, messagelen)?;
curpos += blen;
}
BmpMessagePeerDownReason::Remote => {
buf[curpos] = 4;
curpos += 1;
}
BmpMessagePeerDownReason::BmpDisabled => {
buf[curpos] = 5;
curpos += 1;
}
}

Ok(curpos)
}
}
15 changes: 15 additions & 0 deletions src/bmp/msgrmon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,19 @@ impl BmpMessageRouteMonitoring {
pos,
))
}
pub fn encode_to(&self, buf: &mut [u8]) -> Result<usize, BgpError> {
let mut curpos: usize = 0;
if buf.len() < 62 {
return Err(BgpError::InsufficientBufferSize);
}
curpos += self.peer.encode_to(buf)?; // BmpMessagePeerHeader
let sesspars: &BgpSessionParams = &(&self.peer).into();

let messagelen = self.update.encode_to(sesspars, &mut buf[curpos + 19..])?;
let blen =
sesspars.prepare_message_buf(&mut buf[curpos..], BgpMessageType::Update, messagelen)?;
curpos += blen;

Ok(curpos)
}
}
32 changes: 31 additions & 1 deletion src/bmp/msgterm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,13 @@ impl BmpMessageTermination {
pub fn decode_from(buf: &[u8]) -> Result<(BmpMessageTermination, usize), BgpError> {
let mut pos: usize = 0;
let mut ret: BmpMessageTermination = BmpMessageTermination::new();
while pos < buf.len() {
while buf.len() - pos >= 4 {
let infotype = getn_u16(&buf[pos..]);
let infolen = getn_u16(&buf[pos + 2..]) as usize;
pos += 4;
if buf.len() - pos < infolen {
return Err(BgpError::InsufficientBufferSize);
}
match infotype {
0 => ret.str0 = Some(core::str::from_utf8(&buf[pos..pos + infolen])?.to_string()),
1 => ret.reason = Some(getn_u16(&buf[pos..])),
Expand All @@ -42,6 +45,33 @@ impl BmpMessageTermination {
}
Ok((ret, pos))
}
pub fn encode_to(&self, buf: &mut [u8]) -> Result<usize, BgpError> {
let mut curpos: usize = 0;
if let Some(str0) = &self.str0 {
let str0 = str0.as_bytes();
if buf.len() - curpos < 4 + str0.len() {
return Err(BgpError::InsufficientBufferSize);
}
setn_u16(0, &mut buf[curpos..]);
curpos += 2;
setn_u16(str0.len() as u16, &mut buf[curpos..]);
curpos += 2;
buf[curpos..curpos + str0.len()].copy_from_slice(str0);
curpos += str0.len();
}
if let Some(reason) = self.reason {
if buf.len() - curpos < 6 {
return Err(BgpError::InsufficientBufferSize);
}
setn_u16(1, &mut buf[curpos..]);
curpos += 2;
setn_u16(2, &mut buf[curpos..]);
curpos += 2;
setn_u16(reason, &mut buf[curpos..]);
curpos += 2;
}
Ok(curpos)
}
}
impl Default for BmpMessageTermination {
fn default() -> Self {
Expand Down
10 changes: 10 additions & 0 deletions src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,16 @@ pub fn setn_u32(s: u32, a: &mut [u8]) {
pub fn getn_u64(a: &[u8]) -> u64 {
((getn_u32(a) as u64) << 32) | (getn_u32(&a[4..8]) as u64)
}
pub fn setn_u64(s: u64, a: &mut [u8]) {
a[0] = (s >> 56) as u8;
a[1] = ((s >> 48) & 0xff) as u8;
a[2] = ((s >> 40) & 0xff) as u8;
a[3] = ((s >> 32) & 0xff) as u8;
a[4] = ((s >> 24) & 0xff) as u8;
a[5] = ((s >> 16) & 0xff) as u8;
a[6] = ((s >> 8) & 0xff) as u8;
a[7] = (s & 0xff) as u8;
}
pub fn getn_u128(a: &[u8]) -> u128 {
((getn_u64(a) as u128) << 64) | (getn_u64(&a[8..16]) as u128)
}
Expand Down

0 comments on commit 1d259df

Please sign in to comment.