Skip to main content

netgauze_pcap_decoder/handlers/
bgp.rs

1// Copyright (C) 2025-present The NetGauze Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//    http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12// implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use super::{decode_buffer, serialize_error, serialize_success};
17use crate::protocol_handler::{DecodeOutcome, ProtocolHandler};
18use bytes::BytesMut;
19use netgauze_bgp_pkt::BgpMessage;
20use netgauze_bgp_pkt::codec::{BgpCodec, BgpCodecDecoderError};
21use netgauze_bgp_pkt::wire::deserializer::{BgpParsingContext, BgpParsingIgnoredErrors};
22use netgauze_pcap_reader::TransportProtocol;
23use std::collections::HashMap;
24use std::io;
25use std::net::IpAddr;
26
27pub struct BgpProtocolHandler {
28    ports: Vec<u16>,
29}
30
31impl BgpProtocolHandler {
32    pub fn new(ports: Vec<u16>) -> Self {
33        BgpProtocolHandler { ports }
34    }
35}
36
37impl ProtocolHandler<(BgpMessage, BgpParsingIgnoredErrors), BgpCodec, BgpCodecDecoderError>
38    for BgpProtocolHandler
39{
40    fn decode(
41        &self,
42        flow_key: (IpAddr, u16, IpAddr, u16),
43        protocol: TransportProtocol,
44        packet_data: &[u8],
45        exporter_peers: &mut HashMap<(IpAddr, u16, IpAddr, u16), (BgpCodec, BytesMut)>,
46    ) -> Option<Vec<DecodeOutcome<(BgpMessage, BgpParsingIgnoredErrors), BgpCodecDecoderError>>>
47    {
48        let dst_port: u16 = flow_key.3;
49
50        if protocol == TransportProtocol::TCP && self.ports.contains(&dst_port) {
51            let (codec, buffer) = exporter_peers.entry(flow_key).or_insert((
52                BgpCodec::new_from_ctx(
53                    true,
54                    BgpParsingContext::new(
55                        true,
56                        HashMap::new(),
57                        HashMap::new(),
58                        true,
59                        true,
60                        true,
61                        true,
62                    ),
63                ),
64                BytesMut::new(),
65            ));
66            buffer.extend_from_slice(packet_data);
67
68            let mut results = Vec::new();
69            decode_buffer(buffer, codec, flow_key, &mut results);
70            if !results.is_empty() {
71                return Some(results);
72            }
73        }
74        None
75    }
76
77    fn serialize(
78        &self,
79        decode_outcome: DecodeOutcome<(BgpMessage, BgpParsingIgnoredErrors), BgpCodecDecoderError>,
80    ) -> io::Result<serde_json::Value> {
81        match decode_outcome {
82            DecodeOutcome::Success(m) => {
83                let (flow_key, (bgp_message, bgp_parsing_error)) = m;
84                if !bgp_parsing_error.eq(&BgpParsingIgnoredErrors::default()) {
85                    // the bgp message was parsed with some ignored errors, we will not serialize it
86                    // we will report that some ignored errors were found and that this behavior
87                    // by the CLI tool is not expected
88                    return Ok(serde_json::Value::String("Encountered BGP parsing errors that were ignored during the decoding of the bgp message, this behaviour is not expected, please file a bug report to the developers".to_string()));
89                }
90                serialize_success(flow_key, bgp_message)
91            }
92            DecodeOutcome::Error(m) => serialize_error(m),
93        }
94    }
95}
96
97#[cfg(test)]
98mod tests {
99    use super::*;
100    use netgauze_bgp_pkt::open::BgpOpenMessage;
101    use netgauze_bgp_pkt::path_attribute::UndefinedOrigin;
102    use netgauze_bgp_pkt::wire::deserializer::BgpMessageParsingError;
103    use netgauze_bgp_pkt::wire::deserializer::path_attribute::{
104        OriginParsingError, PathAttributeParsingError,
105    };
106    use netgauze_bgp_pkt::wire::deserializer::update::BgpUpdateMessageParsingError;
107    use serde_json::json;
108    use std::net::Ipv4Addr;
109
110    #[test]
111    fn test_bgp_handler_decode_success() {
112        let handler = BgpProtocolHandler::new(vec![179]);
113        let flow_key = (
114            IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
115            12345,
116            IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
117            179,
118        );
119        // A simple BGP OPEN message
120        let packet_data = [
121            0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
122            0xff, 0xff, 0x00, 0x1d, 0x01, 0x04, 0x00, 0x01, 0x00, 0xb4, 0x01, 0x02, 0x03, 0x04,
123            0x00,
124        ];
125        let mut exporter_peers = HashMap::new();
126
127        let result = handler.decode(
128            flow_key,
129            TransportProtocol::TCP,
130            &packet_data,
131            &mut exporter_peers,
132        );
133
134        assert_eq!(
135            result,
136            Some(vec![DecodeOutcome::Success((
137                flow_key,
138                (
139                    BgpMessage::Open(BgpOpenMessage::new(
140                        1,
141                        180,
142                        Ipv4Addr::new(1, 2, 3, 4),
143                        vec![],
144                    )),
145                    BgpParsingIgnoredErrors::default()
146                )
147            ))]),
148        );
149        // Now we should have an empty buffer for this flow key
150        assert!(exporter_peers.get(&flow_key).unwrap().1.is_empty());
151    }
152
153    #[test]
154    fn test_bgp_handler_decode_fragmented_success() {
155        let handler = BgpProtocolHandler::new(vec![179]);
156        let flow_key = (
157            IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
158            12345,
159            IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
160            179,
161        );
162        // A simple BGP OPEN message, split into two
163        let packet_data1 = &[
164            0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
165            0xff, 0xff, 0x00, 0x1d, 0x01,
166        ];
167        let packet_data2 = &[0x04, 0x00, 0x01, 0x00, 0xb4, 0x01, 0x02, 0x03, 0x04, 0x00];
168        let mut exporter_peers = HashMap::new();
169
170        // First packet is fragmented
171        let result1 = handler.decode(
172            flow_key,
173            TransportProtocol::TCP,
174            packet_data1,
175            &mut exporter_peers,
176        );
177        assert!(result1.is_none());
178        // The buffer for this flow key should now contain the first part, so not empty
179        assert!(!exporter_peers.get(&flow_key).unwrap().1.is_empty());
180
181        // Second packet completes it
182        let result2 = handler.decode(
183            flow_key,
184            TransportProtocol::TCP,
185            packet_data2,
186            &mut exporter_peers,
187        );
188
189        assert_eq!(
190            result2,
191            Some(vec![DecodeOutcome::Success((
192                flow_key,
193                (
194                    BgpMessage::Open(BgpOpenMessage::new(
195                        1,
196                        180,
197                        Ipv4Addr::new(1, 2, 3, 4),
198                        vec![],
199                    )),
200                    BgpParsingIgnoredErrors::default()
201                )
202            ))]),
203        );
204        // Now we should have an empty buffer for this flow key
205        assert!(exporter_peers.get(&flow_key).unwrap().1.is_empty());
206    }
207
208    #[test]
209    fn test_bgp_handler_decode_multiple_messages_success() {
210        let handler = BgpProtocolHandler::new(vec![179]);
211        let flow_key = (
212            IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
213            12345,
214            IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
215            179,
216        );
217        // Two simple BGP OPEN messages
218        let packet_data = [
219            0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
220            0xff, 0xff, 0x00, 0x1d, 0x01, 0x04, 0x00, 0x01, 0x00, 0xb4, 0x01, 0x02, 0x03, 0x04,
221            0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
222            0xff, 0xff, 0xff, 0x00, 0x1d, 0x01, 0x04, 0x00, 0x01, 0x00, 0xb4, 0x05, 0x06, 0x07,
223            0x08, 0x00,
224        ];
225        let mut exporter_peers = HashMap::new();
226
227        let result = handler.decode(
228            flow_key,
229            TransportProtocol::TCP,
230            &packet_data,
231            &mut exporter_peers,
232        );
233
234        assert_eq!(
235            result,
236            Some(vec![
237                DecodeOutcome::Success((
238                    flow_key,
239                    (
240                        BgpMessage::Open(BgpOpenMessage::new(
241                            1,
242                            180,
243                            Ipv4Addr::new(1, 2, 3, 4),
244                            vec![],
245                        )),
246                        BgpParsingIgnoredErrors::default()
247                    )
248                )),
249                DecodeOutcome::Success((
250                    flow_key,
251                    (
252                        BgpMessage::Open(BgpOpenMessage::new(
253                            1,
254                            180,
255                            Ipv4Addr::new(5, 6, 7, 8),
256                            vec![],
257                        )),
258                        BgpParsingIgnoredErrors::default()
259                    )
260                ))
261            ]),
262        );
263        // Now we should have an empty buffer for this flow key
264        assert!(exporter_peers.get(&flow_key).unwrap().1.is_empty());
265    }
266
267    #[test]
268    fn test_bgp_handler_decode_message_with_errors_that_should_not_be_ignored() {
269        let handler = BgpProtocolHandler::new(vec![179]);
270        let flow_key = (
271            IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
272            12345,
273            IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
274            179,
275        );
276        // The packet data contains a BGP message with some errors that can potentially
277        // be ignored
278        let packet_data = [
279            0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
280            0xff, 0xff, 0x00, 0x59, 0x02, 0x00, 0x00, 0x00, 0x30, 0x40, 0x01, 0x01,
281            0x0ff, // Undefined origin type = 0xff
282            0x40, 0x02, 0x06, 0x02, 0xff, 0x00, 0x00, 0xfb, 0xff, // Segment count is 0xff
283            0x40, 0x03, 0xff, 0x0a, 0x00, 0x0e,
284            0x01, // Next hop size is 0xff, rather than 0x04
285            0x80, 0x04, 0xff, 0x00, 0x00, 0x00, 0x00, // MED length is 0xff, rather than 0x04
286            0x40, 0x05, 0xff, 0x00, 0x00, 0x00,
287            0x64, // LOCAL PREF length is 0xff, rather than 0x04
288            0x80, 0x0a, 0x04, 0x0a, 0x00, 0x22, 0x04, 0x80, 0x09, 0x04, 0x0a, 0x00, 0x0f, 0x01,
289            0x00, 0x00, 0x00, 0x01, 0x20, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x01, 0x20,
290            0xc0, 0xa8, 0x01, 0x05,
291        ];
292        let mut exporter_peers = HashMap::new();
293
294        let result = handler.decode(
295            flow_key,
296            TransportProtocol::TCP,
297            &packet_data,
298            &mut exporter_peers,
299        );
300
301        // Expecting an error due to the first byte being different
302        assert_eq!(
303            result,
304            Some(vec![DecodeOutcome::Error(
305                BgpCodecDecoderError::BgpMessageParsingError(
306                    BgpMessageParsingError::BgpUpdateMessageParsingError(
307                        BgpUpdateMessageParsingError::PathAttributeError(
308                            PathAttributeParsingError::OriginError(
309                                OriginParsingError::UndefinedOrigin(UndefinedOrigin(255))
310                            )
311                        )
312                    )
313                )
314            )]),
315        );
316        // now we should have an empty buffer for this flow key
317        assert!(exporter_peers.get(&flow_key).unwrap().1.is_empty());
318    }
319    #[test]
320    fn test_bgp_handler_decode_failure() {
321        let handler = BgpProtocolHandler::new(vec![179]);
322        let flow_key = (
323            IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
324            12345,
325            IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
326            179,
327        );
328        // A simple BGP OPEN message
329        let packet_data = [
330            0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
331            0xff, // first byte differs
332            0xff, 0xff, 0x00, 0x1d, 0x01, 0x04, 0x00, 0x01, 0x00, 0xb4, 0x01, 0x02, 0x03, 0x04,
333            0x00,
334        ];
335        let mut exporter_peers = HashMap::new();
336
337        let result = handler.decode(
338            flow_key,
339            TransportProtocol::TCP,
340            &packet_data,
341            &mut exporter_peers,
342        );
343
344        assert!(result.is_some());
345        // expecting an error due to the first byte being different
346        assert_eq!(
347            result,
348            Some(vec![DecodeOutcome::Error(
349                BgpCodecDecoderError::BgpMessageParsingError(
350                    BgpMessageParsingError::ConnectionNotSynchronized(
351                        1329227995784915872903807060280344575
352                    )
353                )
354            )]),
355        );
356        // Now we should have an empty buffer for this flow key
357        assert!(exporter_peers.get(&flow_key).unwrap().1.is_empty());
358    }
359
360    #[test]
361    fn test_bgp_handler_decode_ignore_wrong_port() {
362        let handler = BgpProtocolHandler::new(vec![179]);
363        let flow_key = (
364            IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
365            12345,
366            IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
367            180, // Wrong port
368        );
369        let packet_data = [0xff; 20];
370        let mut exporter_peers = HashMap::new();
371
372        let result = handler.decode(
373            flow_key,
374            TransportProtocol::TCP,
375            &packet_data,
376            &mut exporter_peers,
377        );
378
379        assert!(result.is_none());
380    }
381
382    #[test]
383    fn test_bgp_handler_decode_ignore_wrong_protocol() {
384        let handler = BgpProtocolHandler::new(vec![179]);
385        let flow_key = (
386            IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
387            12345,
388            IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
389            179,
390        );
391        let packet_data = [0xff; 20];
392        let mut exporter_peers = HashMap::new();
393
394        let result = handler.decode(
395            flow_key,
396            TransportProtocol::UDP, // Wrong protocol
397            &packet_data,
398            &mut exporter_peers,
399        );
400
401        assert!(result.is_none());
402    }
403
404    #[test]
405    fn test_bgp_handler_serialize_success() {
406        let handler = BgpProtocolHandler::new(vec![179]);
407        let flow_key = (
408            IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)),
409            12345,
410            IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)),
411            179,
412        );
413        let open_message = BgpMessage::Open(BgpOpenMessage::new(
414            1,
415            180,
416            Ipv4Addr::new(1, 1, 1, 1),
417            vec![],
418        ));
419        let outcome =
420            DecodeOutcome::Success((flow_key, (open_message, BgpParsingIgnoredErrors::default())));
421
422        let result = handler.serialize(outcome);
423        assert!(result.is_ok());
424        let json = result.unwrap();
425        let expected = json!({
426          "source_address": "10.0.0.1:12345",
427          "destination_address": "10.0.0.2:179",
428          "info": {
429            "Open": {
430              "version": 4,
431              "my_as": 1,
432              "hold_time": 180,
433              "bgp_id": "1.1.1.1",
434              "params": []
435            }
436          }
437        });
438        assert_eq!(json, expected);
439    }
440
441    #[test]
442    fn test_bgp_handler_serialize_error() {
443        let handler = BgpProtocolHandler::new(vec![179]);
444        let error = BgpCodecDecoderError::BgpMessageParsingError(
445            BgpMessageParsingError::BadMessageLength(10),
446        );
447        let outcome = DecodeOutcome::Error(error);
448
449        let result = handler.serialize(outcome);
450        assert!(result.is_ok());
451        let json = result.unwrap();
452        let expected = json!({
453            "BgpMessageParsingError": {
454                "BadMessageLength": 10
455            }
456        });
457        assert_eq!(json, expected);
458    }
459}