bgpkit_parser/parser/bmp/messages/
peer_up_notification.rs1use crate::bgp::parse_bgp_message;
2use crate::models::*;
3use crate::parser::bmp::error::ParserBmpError;
4use crate::parser::ReadUtils;
5use bytes::{Buf, Bytes};
6use num_enum::{IntoPrimitive, TryFromPrimitive};
7use std::net::IpAddr;
8
9#[derive(Debug, PartialEq, Clone)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct PeerUpNotification {
12 pub local_addr: IpAddr,
13 pub local_port: u16,
14 pub remote_port: u16,
15 pub sent_open: BgpMessage,
16 pub received_open: BgpMessage,
17 pub tlvs: Vec<PeerUpNotificationTlv>,
18}
19
20#[derive(Debug, TryFromPrimitive, IntoPrimitive, PartialEq, Clone, Copy)]
24#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
25#[repr(u16)]
26pub enum PeerUpTlvType {
27 String = 0,
28 SysDescr = 1,
29 SysName = 2,
30 VrTableName = 3,
31 AdminLabel = 4,
32}
33
34#[derive(Debug, PartialEq, Clone)]
35#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
36pub struct PeerUpNotificationTlv {
37 pub info_type: PeerUpTlvType,
38 pub info_len: u16,
39 pub info_value: String,
40}
41
42pub fn parse_peer_up_notification(
43 data: &mut Bytes,
44 afi: &Afi,
45 asn_len: &AsnLength,
46) -> Result<PeerUpNotification, ParserBmpError> {
47 let local_addr: IpAddr = match afi {
48 Afi::Ipv4 => {
49 data.advance(12);
50 let ip = data.read_ipv4_address()?;
51 ip.into()
52 }
53 Afi::Ipv6 => data.read_ipv6_address()?.into(),
54 };
55
56 let local_port = data.read_u16()?;
57 let remote_port = data.read_u16()?;
58
59 let sent_open = parse_bgp_message(data, false, asn_len)?;
60 let received_open = parse_bgp_message(data, false, asn_len)?;
61 let mut tlvs = vec![];
63 while data.remaining() >= 4 {
64 let info_type = PeerUpTlvType::try_from(data.read_u16()?)?;
65 let info_len = data.read_u16()?;
66 let info_value = data.read_n_bytes_to_string(info_len as usize)?;
67 tlvs.push(PeerUpNotificationTlv {
68 info_type,
69 info_len,
70 info_value,
71 })
72 }
73 Ok(PeerUpNotification {
74 local_addr,
75 local_port,
76 remote_port,
77 sent_open,
78 received_open,
79 tlvs,
80 })
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86 use bytes::BytesMut;
87 use std::net::{IpAddr, Ipv4Addr};
88
89 #[test]
90 fn test_parse_peer_up_notification() {
91 let mut data = BytesMut::new();
92 data.extend_from_slice(&[
95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x01,
96 0x01, 0x01,
97 ]);
98 data.extend_from_slice(&[0x1F, 0x40]); data.extend_from_slice(&[0x23, 0x28]); let bgp_open_message = crate::models::BgpMessage::Open(BgpOpenMessage {
102 version: 0,
103 asn: Default::default(),
104 hold_time: 0,
105 sender_ip: Ipv4Addr::new(0, 0, 0, 0),
106 extended_length: false,
107 opt_params: vec![],
108 });
109 let bgp_open_message_bytes = bgp_open_message.encode(false, AsnLength::Bits32);
110 data.extend_from_slice(&bgp_open_message_bytes);
111 data.extend_from_slice(&bgp_open_message_bytes);
112
113 data.extend_from_slice(&[0x00, 0x01]); data.extend_from_slice(&[0x00, 0x02]); data.extend_from_slice(&[0x00, 0x03]); let afi = Afi::Ipv4;
119 let asn_len = AsnLength::Bits32;
120
121 let result = parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len);
122
123 match result {
124 Ok(peer_notification) => {
125 assert_eq!(
126 peer_notification.local_addr,
127 IpAddr::V4(std::net::Ipv4Addr::new(10, 1, 1, 1))
128 );
129 assert_eq!(peer_notification.local_port, 8000);
130 assert_eq!(peer_notification.remote_port, 9000);
131
132 let tlv = peer_notification.tlvs.first().unwrap();
134 assert_eq!(tlv.info_type, PeerUpTlvType::SysDescr);
135 assert_eq!(tlv.info_len, 2);
136 assert_eq!(tlv.info_value, "\u{0}\u{3}");
137 }
138 Err(_) => {
139 panic!("parse_peer_up_notification should return Ok");
140 }
141 }
142 }
143}