bgpkit_parser/parser/bmp/
mod.rs

1/*!
2Provides parsing for BMP and OpenBMP binary-formatted messages.
3*/
4use crate::parser::bmp::error::ParserBmpError;
5use crate::parser::bmp::messages::*;
6pub use crate::parser::bmp::openbmp::parse_openbmp_header;
7use crate::utils::ReadUtils;
8use bytes::Bytes;
9
10pub mod error;
11pub mod messages;
12pub mod openbmp;
13
14/// Parse OpenBMP `raw_bmp` message.
15///
16/// An OpenBMP `raw_bmp` message contains a [OpenBmpHeader][OpenBmpHeader] and a [BmpMessage].
17///
18/// [OpenBmpHeader]: crate::parser::bmp::openbmp::OpenBmpHeader
19pub fn parse_openbmp_msg(mut data: Bytes) -> Result<BmpMessage, ParserBmpError> {
20    let _header = parse_openbmp_header(&mut data)?;
21    parse_bmp_msg(&mut data)
22}
23
24/// Parse a BMP message.
25pub fn parse_bmp_msg(data: &mut Bytes) -> Result<BmpMessage, ParserBmpError> {
26    let common_header = parse_bmp_common_header(data)?;
27
28    let msg_len = common_header.msg_len as usize;
29    if msg_len < 6 {
30        return Err(ParserBmpError::CorruptedBmpMessage);
31    }
32    let content_length = msg_len - 6;
33    data.has_n_remaining(content_length)?;
34    let mut content = data.split_to(content_length);
35
36    match &common_header.msg_type {
37        BmpMsgType::RouteMonitoring => {
38            let per_peer_header = parse_per_peer_header(&mut content)?;
39            let msg = parse_route_monitoring(
40                &mut content,
41                &per_peer_header.asn_length(),
42                Some(&per_peer_header.peer_type),
43            )?;
44            Ok(BmpMessage {
45                common_header,
46                per_peer_header: Some(per_peer_header),
47                message_body: BmpMessageBody::RouteMonitoring(msg),
48            })
49        }
50        BmpMsgType::RouteMirroringMessage => {
51            let per_peer_header = parse_per_peer_header(&mut content)?;
52            let msg = parse_route_mirroring(
53                &mut content,
54                &per_peer_header.asn_length(),
55                Some(&per_peer_header.peer_type),
56            )?;
57            Ok(BmpMessage {
58                common_header,
59                per_peer_header: Some(per_peer_header),
60                message_body: BmpMessageBody::RouteMirroring(msg),
61            })
62        }
63        BmpMsgType::StatisticsReport => {
64            let per_peer_header = parse_per_peer_header(&mut content)?;
65            let msg = parse_stats_report(&mut content)?;
66            Ok(BmpMessage {
67                common_header,
68                per_peer_header: Some(per_peer_header),
69                message_body: BmpMessageBody::StatsReport(msg),
70            })
71        }
72        BmpMsgType::PeerDownNotification => {
73            let per_peer_header = parse_per_peer_header(&mut content)?;
74            let msg = parse_peer_down_notification(&mut content)?;
75            Ok(BmpMessage {
76                common_header,
77                per_peer_header: Some(per_peer_header),
78                message_body: BmpMessageBody::PeerDownNotification(msg),
79            })
80        }
81        BmpMsgType::PeerUpNotification => {
82            let per_peer_header = parse_per_peer_header(&mut content)?;
83            let msg = parse_peer_up_notification(
84                &mut content,
85                &per_peer_header.afi(),
86                &per_peer_header.asn_length(),
87                Some(&per_peer_header.peer_type),
88            )?;
89            Ok(BmpMessage {
90                common_header,
91                per_peer_header: Some(per_peer_header),
92                message_body: BmpMessageBody::PeerUpNotification(msg),
93            })
94        }
95        BmpMsgType::InitiationMessage => {
96            let msg = parse_initiation_message(&mut content)?;
97            Ok(BmpMessage {
98                common_header,
99                per_peer_header: None,
100                message_body: BmpMessageBody::InitiationMessage(msg),
101            })
102        }
103        BmpMsgType::TerminationMessage => {
104            let msg = parse_termination_message(&mut content)?;
105            Ok(BmpMessage {
106                common_header,
107                per_peer_header: None,
108                message_body: BmpMessageBody::TerminationMessage(msg),
109            })
110        }
111    }
112}
113
114#[cfg(test)]
115#[allow(unused_variables)]
116mod tests {
117    use super::*;
118    use crate::parser::bmp::openbmp::parse_openbmp_header;
119
120    #[test]
121    fn test_peer_down_notification() {
122        let input = "4f424d500107006400000033800c6184b9c2000c602cbf4f072f3ae149d23486024bc3dadfc4000a69732d63632d626d7031c677060bdd020a9e92be000200de2e3180df3369000000000000000000000000000c726f7574652d76696577733500000001030000003302000000000000000000000000000000000000000000003fda060e00000da30000000061523c36000c0e1c0200000a";
123        let decoded = hex::decode(input).unwrap();
124        let mut data = Bytes::from(decoded);
125        let _header = parse_openbmp_header(&mut data).unwrap();
126        let _msg = parse_bmp_msg(&mut data).unwrap();
127    }
128
129    #[test]
130    fn test_route_monitoring() {
131        let input = "4f424d500107005c000000b0800c618881530002f643fef880938d19e9d632c815d1e95a87e1000a69732d61682d626d7031eb4de4e596b282c6a995b067df4abc8cc342f19200000000000000000000000000046c696e780000000103000000b00000c00000000000000000200107f800040000000000001aae000400001aae5474800e02dddf5d00000000ffffffffffffffffffffffffffffffff00800200000069400101005002001602050000192f00001aae0000232a000328eb00032caec008181aae42681aae44581aae464f1aae59d91aae866543000000900e002c00020120200107f800040000000000001aae0004fe8000000000000082711ffffe7f29f100302a0fca8000010a";
132        let decoded = hex::decode(input).unwrap();
133        let mut data = Bytes::from(decoded);
134        let _header = parse_openbmp_header(&mut data).unwrap();
135        let _msg = parse_bmp_msg(&mut data).unwrap();
136    }
137
138    #[test]
139    fn parse_peer_up_notification() {}
140}