1use super::{decode_buffer, serialize_error, serialize_success};
17use crate::protocol_handler::{DecodeOutcome, ProtocolHandler};
18use bytes::BytesMut;
19use netgauze_bmp_pkt::BmpMessage;
20use netgauze_bmp_pkt::codec::{BmpCodec, BmpCodecDecoderError};
21use netgauze_pcap_reader::TransportProtocol;
22use std::collections::HashMap;
23use std::io;
24use std::net::IpAddr;
25
26pub struct BmpProtocolHandler {
27 ports: Vec<u16>,
28}
29
30impl BmpProtocolHandler {
31 pub fn new(ports: Vec<u16>) -> Self {
32 BmpProtocolHandler { ports }
33 }
34}
35
36impl ProtocolHandler<BmpMessage, BmpCodec, BmpCodecDecoderError> for BmpProtocolHandler {
37 fn decode(
38 &self,
39 flow_key: (IpAddr, u16, IpAddr, u16),
40 protocol: TransportProtocol,
41 packet_data: &[u8],
42 exporter_peers: &mut HashMap<(IpAddr, u16, IpAddr, u16), (BmpCodec, BytesMut)>,
43 ) -> Option<Vec<DecodeOutcome<BmpMessage, BmpCodecDecoderError>>> {
44 let dst_port: u16 = flow_key.3;
45
46 if protocol == TransportProtocol::TCP && self.ports.contains(&dst_port) {
47 let (codec, buffer) = exporter_peers
48 .entry(flow_key)
49 .or_insert((BmpCodec::default(), BytesMut::new()));
50 buffer.extend_from_slice(packet_data);
51
52 let mut results = Vec::new();
53 decode_buffer(buffer, codec, flow_key, &mut results);
54 if !results.is_empty() {
55 return Some(results);
56 }
57 }
58 None
59 }
60
61 fn serialize(
62 &self,
63 decode_outcome: DecodeOutcome<BmpMessage, BmpCodecDecoderError>,
64 ) -> io::Result<serde_json::Value> {
65 match decode_outcome {
66 DecodeOutcome::Success(m) => {
67 let (flow_key, bmp_message) = m;
68 serialize_success(flow_key, bmp_message)
69 }
70 DecodeOutcome::Error(m) => serialize_error(m),
71 }
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78 use netgauze_bmp_pkt::v3::{BmpMessageValue, InitiationInformation, InitiationMessage};
79 use netgauze_bmp_pkt::wire::deserializer::BmpMessageParsingError;
80 use serde_json::json;
81 use std::net::Ipv4Addr;
82
83 #[test]
84 fn test_bmp_handler_decode_success() {
85 let handler = BmpProtocolHandler::new(vec![1790]);
86 let flow_key = (
87 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
88 12345,
89 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
90 1790,
91 );
92 let packet_data = [
94 0x03, 0x00, 0x00, 0x00, 0x6c, 0x04, 0x00, 0x01, 0x00, 0x5b, 0x43, 0x69, 0x73, 0x63,
95 0x6f, 0x20, 0x49, 0x4f, 0x53, 0x20, 0x58, 0x52, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77,
96 0x61, 0x72, 0x65, 0x2c, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x35,
97 0x2e, 0x32, 0x2e, 0x32, 0x2e, 0x32, 0x31, 0x49, 0x5b, 0x44, 0x65, 0x66, 0x61, 0x75,
98 0x6c, 0x74, 0x5d, 0x0a, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20,
99 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x31, 0x34, 0x20, 0x62, 0x79, 0x20, 0x43, 0x69,
100 0x73, 0x63, 0x6f, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x2c, 0x20, 0x49,
101 0x6e, 0x63, 0x2e, 0x00, 0x02, 0x00, 0x03, 0x78, 0x72, 0x33,
102 ];
103
104 let mut exporter_peers = HashMap::new();
105
106 let result = handler.decode(
107 flow_key,
108 TransportProtocol::TCP,
109 &packet_data,
110 &mut exporter_peers,
111 );
112
113 assert_eq!(
114 result,
115 Some(vec![DecodeOutcome::Success((
116 flow_key,
117 BmpMessage::V3(BmpMessageValue::Initiation(InitiationMessage::new(vec![
118 InitiationInformation::SystemDescription(
119 "Cisco IOS XR Software, Version 5.2.2.21I[Default]\nCopyright (c) 2014 by Cisco Systems, Inc.".to_string()
120 ),
121 InitiationInformation::SystemName("xr3".to_string())
122 ])))
123 ))]),
124 );
125 assert!(exporter_peers.get(&flow_key).unwrap().1.is_empty());
127 }
128
129 #[test]
130 fn test_bmp_handler_decode_fragmented_success() {
131 let handler = BmpProtocolHandler::new(vec![1790]);
132 let flow_key = (
133 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
134 12345,
135 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
136 1790,
137 );
138 let packet_data1 = [
139 0x03, 0x00, 0x00, 0x00, 0x6c, 0x04, 0x00, 0x01, 0x00, 0x5b, 0x43, 0x69, 0x73, 0x63,
140 0x6f, 0x20,
141 ];
142 let packet_data2 = [
143 0x49, 0x4f, 0x53, 0x20, 0x58, 0x52, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72,
144 0x65, 0x2c, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x35, 0x2e, 0x32,
145 0x2e, 0x32, 0x2e, 0x32, 0x31, 0x49, 0x5b, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74,
146 0x5d, 0x0a, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x63,
147 0x29, 0x20, 0x32, 0x30, 0x31, 0x34, 0x20, 0x62, 0x79, 0x20, 0x43, 0x69, 0x73, 0x63,
148 0x6f, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x2c, 0x20, 0x49, 0x6e, 0x63,
149 0x2e, 0x00, 0x02, 0x00, 0x03, 0x78, 0x72, 0x33,
150 ];
151 let mut exporter_peers = HashMap::new();
152
153 let result1 = handler.decode(
154 flow_key,
155 TransportProtocol::TCP,
156 &packet_data1,
157 &mut exporter_peers,
158 );
159 assert!(result1.is_none());
160 assert!(!exporter_peers.get(&flow_key).unwrap().1.is_empty());
162
163 let result2 = handler.decode(
164 flow_key,
165 TransportProtocol::TCP,
166 &packet_data2,
167 &mut exporter_peers,
168 );
169
170 assert_eq!(
171 result2,
172 Some(vec![DecodeOutcome::Success((
173 flow_key,
174 BmpMessage::V3(BmpMessageValue::Initiation(InitiationMessage::new(vec![
175 InitiationInformation::SystemDescription(
176 "Cisco IOS XR Software, Version 5.2.2.21I[Default]\nCopyright (c) 2014 by Cisco Systems, Inc.".to_string()
177 ),
178 InitiationInformation::SystemName("xr3".to_string())
179 ])))
180 ))]),
181 );
182 assert!(exporter_peers.get(&flow_key).unwrap().1.is_empty());
184 }
185
186 #[test]
187 fn test_bmp_decode_multiple_messages_success() {
188 let handler = BmpProtocolHandler::new(vec![1790]);
189 let flow_key = (
190 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
191 12345,
192 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
193 1790,
194 );
195 let packet_data = [
197 0x03, 0x00, 0x00, 0x00, 0x6c, 0x04, 0x00, 0x01, 0x00, 0x5b, 0x43, 0x69, 0x73, 0x63,
198 0x6f, 0x20, 0x49, 0x4f, 0x53, 0x20, 0x58, 0x52, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77,
199 0x61, 0x72, 0x65, 0x2c, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x35,
200 0x2e, 0x32, 0x2e, 0x32, 0x2e, 0x32, 0x31, 0x49, 0x5b, 0x44, 0x65, 0x66, 0x61, 0x75,
201 0x6c, 0x74, 0x5d, 0x0a, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20,
202 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x31, 0x34, 0x20, 0x62, 0x79, 0x20, 0x43, 0x69,
203 0x73, 0x63, 0x6f, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x2c, 0x20, 0x49,
204 0x6e, 0x63, 0x2e, 0x00, 0x02, 0x00, 0x03, 0x78, 0x72, 0x33, 0x03, 0x00, 0x00, 0x00,
205 0x6c, 0x04, 0x00, 0x01, 0x00, 0x5b, 0x43, 0x69, 0x73, 0x63, 0x6f, 0x20, 0x49, 0x4f,
206 0x53, 0x20, 0x58, 0x52, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x2c,
207 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x35, 0x2e, 0x32, 0x2e, 0x32,
208 0x2e, 0x32, 0x31, 0x49, 0x5b, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5d, 0x0a,
209 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20,
210 0x32, 0x30, 0x31, 0x34, 0x20, 0x62, 0x79, 0x20, 0x43, 0x69, 0x73, 0x63, 0x6f, 0x20,
211 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x00,
212 0x02, 0x00, 0x03, 0x78, 0x72, 0x33,
213 ];
214
215 let mut exporter_peers = HashMap::new();
216
217 let result = handler.decode(
218 flow_key,
219 TransportProtocol::TCP,
220 &packet_data,
221 &mut exporter_peers,
222 );
223
224 let expected_initiation = InitiationMessage::new(vec![
225 InitiationInformation::SystemDescription(
226 "Cisco IOS XR Software, Version 5.2.2.21I[Default]\nCopyright (c) 2014 by Cisco Systems, Inc.".to_string()
227 ),
228 InitiationInformation::SystemName("xr3".to_string())
229 ]);
230
231 assert_eq!(
232 result,
233 Some(vec![
234 DecodeOutcome::Success((
235 flow_key,
236 BmpMessage::V3(BmpMessageValue::Initiation(expected_initiation.clone()))
237 )),
238 DecodeOutcome::Success((
239 flow_key,
240 BmpMessage::V3(BmpMessageValue::Initiation(expected_initiation))
241 ))
242 ]),
243 );
244 assert!(exporter_peers.get(&flow_key).unwrap().1.is_empty());
246 }
247
248 #[test]
249 fn test_bmp_handler_decode_failure() {
250 let handler = BmpProtocolHandler::new(vec![1790]);
251 let flow_key = (
252 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
253 12345,
254 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
255 1790,
256 );
257 let packet_data = [
259 0x01, 0x00, 0x00, 0x00, 0x6c, 0x04, 0x00, 0x01, 0x00, 0x5b, 0x43, 0x69, 0x73, 0x63,
260 0x6f, 0x20, 0x49, 0x4f, 0x53, 0x20, 0x58, 0x52, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72,
262 0x65, 0x2c, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x35, 0x2e, 0x32,
263 0x2e, 0x32, 0x2e, 0x32, 0x31, 0x49, 0x5b, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74,
264 0x5d, 0x0a, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x63,
265 0x29, 0x20, 0x32, 0x30, 0x31, 0x34, 0x20, 0x62, 0x79, 0x20, 0x43, 0x69, 0x73, 0x63,
266 0x6f, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x2c, 0x20, 0x49, 0x6e, 0x63,
267 0x2e, 0x00, 0x02, 0x00, 0x03, 0x78, 0x72, 0x33,
268 ];
269 let mut exporter_peers = HashMap::new();
270
271 let result = handler.decode(
272 flow_key,
273 TransportProtocol::TCP,
274 &packet_data,
275 &mut exporter_peers,
276 );
277
278 assert_eq!(
279 result,
280 Some(vec![DecodeOutcome::Error(
281 BmpCodecDecoderError::BmpMessageParsingError(
282 BmpMessageParsingError::UndefinedBmpVersion(
283 netgauze_bmp_pkt::iana::UndefinedBmpVersion(1)
284 )
285 )
286 )]),
287 );
288 assert!(exporter_peers.get(&flow_key).unwrap().1.is_empty());
290 }
291
292 #[test]
293 fn test_bmp_handler_decode_ignore_wrong_port() {
294 let handler = BmpProtocolHandler::new(vec![1790]);
295 let flow_key = (
296 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
297 12345,
298 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
299 123,
300 );
301 let packet_data = [0xff; 0xff];
302 let mut exporter_peers = HashMap::new();
303
304 let result = handler.decode(
305 flow_key,
306 TransportProtocol::TCP,
307 &packet_data,
308 &mut exporter_peers,
309 );
310
311 assert!(result.is_none());
312 }
313
314 #[test]
315 fn test_bmp_handler_decode_ignore_wrong_protocol() {
316 let handler = BmpProtocolHandler::new(vec![1790]);
317 let flow_key = (
318 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
319 12345,
320 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
321 1790,
322 );
323 let packet_data = [0xff; 0xff];
324 let mut exporter_peers = HashMap::new();
325
326 let result = handler.decode(
327 flow_key,
328 TransportProtocol::UDP,
329 &packet_data,
330 &mut exporter_peers,
331 );
332
333 assert!(result.is_none());
334 }
335
336 #[test]
337 fn test_bmp_handler_serialize_success() {
338 let handler = BmpProtocolHandler::new(vec![1790]);
339 let flow_key = (
340 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
341 12345,
342 IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
343 1790,
344 );
345 let bmp_message =
346 BmpMessage::V3(BmpMessageValue::Initiation(InitiationMessage::new(vec![])));
347 let outcome = DecodeOutcome::Success((flow_key, bmp_message));
348 let result = handler.serialize(outcome);
349 assert!(result.is_ok());
350 let json = result.unwrap();
351 let expected = json!({
352 "source_address": "10.0.0.1:12345",
353 "destination_address": "10.0.0.2:1790",
354 "info": {
355 "V3": {
356 "Initiation": {
357 "information": []
358 }
359 }
360 }
361 });
362 assert_eq!(json, expected);
363 }
364
365 #[test]
366 fn test_bmp_handler_serialize_error() {
367 let handler = BmpProtocolHandler::new(vec![1790]);
368 let error = BmpCodecDecoderError::BmpMessageParsingError(
369 BmpMessageParsingError::InvalidBmpLength(10),
370 );
371 let outcome = DecodeOutcome::Error(error);
372 let result = handler.serialize(outcome);
373 assert!(result.is_ok());
374 let json = result.unwrap();
375 let expected = json!({
376 "BmpMessageParsingError": {
377 "InvalidBmpLength": 10
378 }
379 });
380 assert_eq!(json, expected);
381 }
382}