1use crate::bgp::parse_bgp_message;
2use crate::models::capabilities::BgpCapabilityType;
3use crate::models::*;
4use crate::parser::bmp::error::ParserBmpError;
5use crate::parser::bmp::messages::BmpPeerType;
6use crate::parser::ReadUtils;
7use bytes::{Buf, Bytes};
8use log::warn;
9use num_enum::{IntoPrimitive, TryFromPrimitive};
10use std::net::IpAddr;
11
12#[derive(Debug, PartialEq, Clone)]
13#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
14pub struct PeerUpNotification {
15 pub local_addr: IpAddr,
16 pub local_port: u16,
17 pub remote_port: u16,
18 pub sent_open: BgpMessage,
19 pub received_open: BgpMessage,
20 pub tlvs: Vec<PeerUpNotificationTlv>,
21}
22
23#[derive(Debug, TryFromPrimitive, IntoPrimitive, PartialEq, Clone, Copy)]
27#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
28#[repr(u16)]
29pub enum PeerUpTlvType {
30 String = 0,
31 SysDescr = 1,
32 SysName = 2,
33 VrTableName = 3,
34 AdminLabel = 4,
35}
36
37#[derive(Debug, PartialEq, Clone)]
38#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
39pub struct PeerUpNotificationTlv {
40 pub info_type: PeerUpTlvType,
41 pub info_len: u16,
42 pub info_value: String,
43}
44
45pub fn parse_peer_up_notification(
46 data: &mut Bytes,
47 afi: &Afi,
48 asn_len: &AsnLength,
49 peer_type: Option<&BmpPeerType>,
50) -> Result<PeerUpNotification, ParserBmpError> {
51 let local_addr: IpAddr = match afi {
52 Afi::Ipv4 => {
53 data.advance(12);
54 let ip = data.read_ipv4_address()?;
55 ip.into()
56 }
57 Afi::Ipv6 => data.read_ipv6_address()?.into(),
58 Afi::LinkState => {
59 data.advance(12);
62 std::net::Ipv4Addr::new(0, 0, 0, 0).into()
63 }
64 };
65
66 let local_port = data.read_u16()?;
67 let remote_port = data.read_u16()?;
68
69 data.has_n_remaining(19)?; let bgp1_length = u16::from_be_bytes([data[16], data[17]]) as usize;
72 data.has_n_remaining(bgp1_length)?;
73 let mut bgp1_data = data.split_to(bgp1_length);
74 let sent_open = parse_bgp_message(&mut bgp1_data, false, asn_len)?;
75
76 data.has_n_remaining(19)?; let bgp2_length = u16::from_be_bytes([data[16], data[17]]) as usize;
79 data.has_n_remaining(bgp2_length)?;
80 let mut bgp2_data = data.split_to(bgp2_length);
81 let received_open = parse_bgp_message(&mut bgp2_data, false, asn_len)?;
82
83 if let Some(BmpPeerType::LocalRib) = peer_type {
85 if let BgpMessage::Open(ref open_msg) = &sent_open {
87 let has_multiprotocol_capability = open_msg.opt_params.iter().any(|param| {
88 if let ParamValue::Capacities(caps) = ¶m.param_value {
89 caps.iter()
90 .any(|cap| cap.ty == BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4)
91 } else {
92 false
93 }
94 });
95 if !has_multiprotocol_capability {
96 warn!("RFC 9069: Local RIB peer up notification should include multiprotocol capabilities in fabricated OPEN messages");
97 }
98 }
99 }
100
101 let mut tlvs = vec![];
102 let mut has_vr_table_name = false;
103
104 while data.remaining() >= 4 {
105 let info_type = PeerUpTlvType::try_from(data.read_u16()?)?;
106 let info_len = data.read_u16()?;
107 let info_value = data.read_n_bytes_to_string(info_len as usize)?;
108
109 if let Some(BmpPeerType::LocalRib) = peer_type {
111 if info_type == PeerUpTlvType::VrTableName {
112 has_vr_table_name = true;
113 if info_value.is_empty() || info_value.len() > 255 {
115 warn!(
116 "RFC 9069: VrTableName TLV length must be 1-255 bytes, found {} bytes",
117 info_value.len()
118 );
119 }
120 }
121 }
122
123 tlvs.push(PeerUpNotificationTlv {
124 info_type,
125 info_len,
126 info_value,
127 })
128 }
129
130 if let Some(BmpPeerType::LocalRib) = peer_type {
132 if !has_vr_table_name {
133 warn!("RFC 9069: Local RIB peer up notification should include VrTableName TLV");
134 }
135 }
136 Ok(PeerUpNotification {
137 local_addr,
138 local_port,
139 remote_port,
140 sent_open,
141 received_open,
142 tlvs,
143 })
144}
145
146#[cfg(test)]
147mod tests {
148 use super::*;
149 use crate::models::capabilities::{BgpCapabilityType, MultiprotocolExtensionsCapability};
150 use bytes::BytesMut;
151 use std::net::{IpAddr, Ipv4Addr};
152
153 #[test]
154 fn test_parse_peer_up_notification() {
155 let mut data = BytesMut::new();
156 data.extend_from_slice(&[
159 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x01,
160 0x01, 0x01,
161 ]);
162 data.extend_from_slice(&[0x1F, 0x40]); data.extend_from_slice(&[0x23, 0x28]); let bgp_open_message = crate::models::BgpMessage::Open(BgpOpenMessage {
166 version: 0,
167 asn: Default::default(),
168 hold_time: 0,
169 sender_ip: Ipv4Addr::new(0, 0, 0, 0),
170 extended_length: false,
171 opt_params: vec![],
172 });
173 let bgp_open_message_bytes = bgp_open_message.encode(AsnLength::Bits32);
174 data.extend_from_slice(&bgp_open_message_bytes);
175 data.extend_from_slice(&bgp_open_message_bytes);
176
177 data.extend_from_slice(&[0x00, 0x01]); data.extend_from_slice(&[0x00, 0x02]); data.extend_from_slice(&[0x00, 0x03]); let afi = Afi::Ipv4;
183 let asn_len = AsnLength::Bits32;
184
185 let result = parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, None);
186
187 match result {
188 Ok(peer_notification) => {
189 assert_eq!(
190 peer_notification.local_addr,
191 IpAddr::V4(std::net::Ipv4Addr::new(10, 1, 1, 1))
192 );
193 assert_eq!(peer_notification.local_port, 8000);
194 assert_eq!(peer_notification.remote_port, 9000);
195
196 let tlv = peer_notification.tlvs.first().unwrap();
198 assert_eq!(tlv.info_type, PeerUpTlvType::SysDescr);
199 assert_eq!(tlv.info_len, 2);
200 assert_eq!(tlv.info_value, "\u{0}\u{3}");
201 }
202 Err(_) => {
203 panic!("parse_peer_up_notification should return Ok");
204 }
205 }
206 }
207
208 fn setup_warning_logger() -> std::sync::Arc<std::sync::Mutex<Vec<String>>> {
210 use log::{Level, Record};
211 use std::sync::{Arc, Mutex};
212
213 struct TestLogger(Arc<Mutex<Vec<String>>>);
214
215 impl log::Log for TestLogger {
216 fn enabled(&self, metadata: &log::Metadata) -> bool {
217 metadata.level() <= Level::Warn
218 }
219
220 fn log(&self, record: &Record) {
221 if record.level() <= Level::Warn {
222 self.0.lock().unwrap().push(record.args().to_string());
223 }
224 }
225
226 fn flush(&self) {}
227 }
228
229 let warnings = Arc::new(Mutex::new(Vec::new()));
230 let logger = TestLogger(warnings.clone());
231 let _ = log::set_boxed_logger(Box::new(logger));
232 log::set_max_level(log::LevelFilter::Warn);
233 warnings
234 }
235
236 #[test]
242 fn test_parse_peer_up_notification_no_warnings() {
243 let warnings = setup_warning_logger();
244
245 let mut data = BytesMut::new();
250
251 data.extend_from_slice(&[
253 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
254 0x01, 0x01, 0x00, 0xB3, 0x00, 0xB3, ]);
258
259 let bgp1 = crate::models::BgpMessage::Open(BgpOpenMessage {
264 version: 4,
265 asn: crate::models::Asn::new_16bit(65001),
266 hold_time: 180,
267 sender_ip: Ipv4Addr::new(192, 168, 1, 1),
268 extended_length: false,
269 opt_params: vec![],
270 });
271 let bgp1_bytes = bgp1.encode(AsnLength::Bits32);
272
273 let bgp2 = crate::models::BgpMessage::Open(BgpOpenMessage {
275 version: 4,
276 asn: crate::models::Asn::new_16bit(65002),
277 hold_time: 90,
278 sender_ip: Ipv4Addr::new(192, 168, 1, 2),
279 extended_length: false,
280 opt_params: vec![],
281 });
282 let bgp2_bytes = bgp2.encode(AsnLength::Bits32);
283
284 data.extend_from_slice(&bgp1_bytes);
286 data.extend_from_slice(&bgp2_bytes);
287
288 data.extend_from_slice(&[
290 0x00, 0x00, 0x00, 0x08, ]);
293 data.extend_from_slice(b"TestNode");
294
295 let afi = Afi::Ipv4;
296 let asn_len = AsnLength::Bits32;
297
298 let result = parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, None);
299
300 assert!(result.is_ok(), "Parsing should succeed without warnings");
302
303 let peer_notification = result.unwrap();
304 assert_eq!(
305 peer_notification.local_addr,
306 IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1))
307 );
308 assert_eq!(peer_notification.local_port, 179);
309 assert_eq!(peer_notification.remote_port, 179);
310
311 if let crate::models::BgpMessage::Open(ref open1) = &peer_notification.sent_open {
313 assert_eq!(open1.asn, crate::models::Asn::new_16bit(65001));
314 } else {
315 panic!("sent_open should be an OPEN message");
316 }
317
318 if let crate::models::BgpMessage::Open(ref open2) = &peer_notification.received_open {
319 assert_eq!(open2.asn, crate::models::Asn::new_16bit(65002));
320 } else {
321 panic!("received_open should be an OPEN message");
322 }
323
324 assert_eq!(peer_notification.tlvs.len(), 1);
326 assert_eq!(peer_notification.tlvs[0].info_type, PeerUpTlvType::String);
327 assert_eq!(peer_notification.tlvs[0].info_value, "TestNode");
328
329 let captured_warnings = warnings.lock().unwrap();
331 assert!(
332 captured_warnings.is_empty(),
333 "Test should not produce warnings, but got: {:?}",
334 *captured_warnings
335 );
336 }
337
338 #[test]
339 fn test_parse_peer_up_insufficient_data_first_bgp() {
340 let mut data = BytesMut::new();
341
342 data.extend_from_slice(&[
344 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x01,
345 0x01, 0x01,
346 ]);
347 data.extend_from_slice(&[0x1F, 0x40]); data.extend_from_slice(&[0x23, 0x28]); data.extend_from_slice(&[
352 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
354 0x40, 0x01, ]);
357 let afi = Afi::Ipv4;
360 let asn_len = AsnLength::Bits32;
361 let result = parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, None);
362
363 assert!(
364 result.is_err(),
365 "Should fail with insufficient data for first BGP message"
366 );
367 }
368
369 #[test]
370 fn test_parse_peer_up_insufficient_data_second_bgp() {
371 let mut data = BytesMut::new();
372
373 data.extend_from_slice(&[
375 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x01,
376 0x01, 0x01,
377 ]);
378 data.extend_from_slice(&[0x1F, 0x40]); data.extend_from_slice(&[0x23, 0x28]); let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
383 version: 4,
384 asn: Default::default(),
385 hold_time: 180,
386 sender_ip: Ipv4Addr::new(0, 0, 0, 0),
387 extended_length: false,
388 opt_params: vec![],
389 });
390 let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
391 data.extend_from_slice(&bgp_bytes);
392
393 data.extend_from_slice(&[
395 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
397 0x30, ]);
400
401 let afi = Afi::Ipv4;
402 let asn_len = AsnLength::Bits32;
403 let result = parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, None);
404
405 assert!(
406 result.is_err(),
407 "Should fail with insufficient data for second BGP message"
408 );
409 }
410
411 #[test]
412 fn test_parse_peer_up_excess_data_in_tlvs() {
413 let mut data = BytesMut::new();
414
415 data.extend_from_slice(&[
417 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x01,
418 0x01, 0x01,
419 ]);
420 data.extend_from_slice(&[0x1F, 0x40]); data.extend_from_slice(&[0x23, 0x28]); let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
425 version: 4,
426 asn: Default::default(),
427 hold_time: 180,
428 sender_ip: Ipv4Addr::new(0, 0, 0, 0),
429 extended_length: false,
430 opt_params: vec![],
431 });
432 let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
433 data.extend_from_slice(&bgp_bytes);
434 data.extend_from_slice(&bgp_bytes);
435
436 data.extend_from_slice(&[0x00, 0x00]); data.extend_from_slice(&[0x00, 0x04]); data.extend_from_slice(b"Test"); data.extend_from_slice(&[0x00, 0x00]); data.extend_from_slice(&[0x00, 0x06]); data.extend_from_slice(b"Router"); data.extend_from_slice(&[0x00, 0x01, 0x02]); let afi = Afi::Ipv4;
449 let asn_len = AsnLength::Bits32;
450 let result = parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, None);
451
452 assert!(result.is_ok(), "Should handle excess data gracefully");
454
455 let peer_notification = result.unwrap();
456 assert_eq!(peer_notification.tlvs.len(), 2); assert_eq!(peer_notification.tlvs[0].info_type, PeerUpTlvType::String);
458 assert_eq!(peer_notification.tlvs[0].info_value, "Test");
459 assert_eq!(peer_notification.tlvs[1].info_type, PeerUpTlvType::String);
460 assert_eq!(peer_notification.tlvs[1].info_value, "Router");
461 }
462
463 #[test]
464 fn test_local_rib_without_multiprotocol_capability() {
465 let mut data = BytesMut::new();
468
469 data.extend_from_slice(&[
471 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
472 0x01, 0x01, 0x00, 0xB3, 0x00, 0xB3, ]);
476
477 let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
479 version: 4,
480 asn: crate::models::Asn::new_32bit(65001),
481 hold_time: 180,
482 sender_ip: Ipv4Addr::new(192, 168, 1, 1),
483 extended_length: false,
484 opt_params: vec![], });
486 let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
487 data.extend_from_slice(&bgp_bytes);
488 data.extend_from_slice(&bgp_bytes);
489
490 let afi = Afi::Ipv4;
491 let asn_len = AsnLength::Bits32;
492 let peer_type = BmpPeerType::LocalRib;
493
494 let result =
495 parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
496
497 assert!(result.is_ok(), "Parsing should succeed");
498 }
500
501 #[test]
502 fn test_local_rib_with_multiprotocol_capability() {
503 let mut data = BytesMut::new();
506
507 data.extend_from_slice(&[
509 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
510 0x01, 0x01, 0x00, 0xB3, 0x00, 0xB3, ]);
514
515 let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
517 version: 4,
518 asn: crate::models::Asn::new_32bit(65001),
519 hold_time: 180,
520 sender_ip: Ipv4Addr::new(192, 168, 1, 1),
521 extended_length: false,
522 opt_params: vec![OptParam {
523 param_type: 2, param_len: 6,
525 param_value: ParamValue::Capacities(vec![Capability {
526 ty: BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4,
527 value: CapabilityValue::MultiprotocolExtensions(
528 MultiprotocolExtensionsCapability {
529 afi: Afi::Ipv4,
530 safi: Safi::Unicast,
531 },
532 ),
533 }]),
534 }],
535 });
536 let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
537 data.extend_from_slice(&bgp_bytes);
538 data.extend_from_slice(&bgp_bytes);
539
540 let afi = Afi::Ipv4;
541 let asn_len = AsnLength::Bits32;
542 let peer_type = BmpPeerType::LocalRib;
543
544 let result =
545 parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
546
547 assert!(result.is_ok(), "Parsing should succeed");
548 }
550
551 #[test]
552 fn test_local_rib_without_vr_table_name_tlv() {
553 let mut data = BytesMut::new();
556
557 data.extend_from_slice(&[
559 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
560 0x01, 0x01, 0x00, 0xB3, 0x00, 0xB3, ]);
564
565 let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
567 version: 4,
568 asn: crate::models::Asn::new_32bit(65001),
569 hold_time: 180,
570 sender_ip: Ipv4Addr::new(192, 168, 1, 1),
571 extended_length: false,
572 opt_params: vec![OptParam {
573 param_type: 2, param_len: 6,
575 param_value: ParamValue::Capacities(vec![Capability {
576 ty: BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4,
577 value: CapabilityValue::MultiprotocolExtensions(
578 MultiprotocolExtensionsCapability {
579 afi: Afi::Ipv4,
580 safi: Safi::Unicast,
581 },
582 ),
583 }]),
584 }],
585 });
586 let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
587 data.extend_from_slice(&bgp_bytes);
588 data.extend_from_slice(&bgp_bytes);
589
590 data.extend_from_slice(&[0x00, 0x00]); data.extend_from_slice(&[0x00, 0x04]); data.extend_from_slice(b"Test");
594
595 let afi = Afi::Ipv4;
596 let asn_len = AsnLength::Bits32;
597 let peer_type = BmpPeerType::LocalRib;
598
599 let result =
600 parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
601
602 assert!(result.is_ok(), "Parsing should succeed");
603 }
605
606 #[test]
607 fn test_local_rib_with_valid_vr_table_name_tlv() {
608 let mut data = BytesMut::new();
611
612 data.extend_from_slice(&[
614 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
615 0x01, 0x01, 0x00, 0xB3, 0x00, 0xB3, ]);
619
620 let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
622 version: 4,
623 asn: crate::models::Asn::new_32bit(65001),
624 hold_time: 180,
625 sender_ip: Ipv4Addr::new(192, 168, 1, 1),
626 extended_length: false,
627 opt_params: vec![OptParam {
628 param_type: 2, param_len: 6,
630 param_value: ParamValue::Capacities(vec![Capability {
631 ty: BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4,
632 value: CapabilityValue::MultiprotocolExtensions(
633 MultiprotocolExtensionsCapability {
634 afi: Afi::Ipv4,
635 safi: Safi::Unicast,
636 },
637 ),
638 }]),
639 }],
640 });
641 let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
642 data.extend_from_slice(&bgp_bytes);
643 data.extend_from_slice(&bgp_bytes);
644
645 data.extend_from_slice(&[0x00, 0x03]); data.extend_from_slice(&[0x00, 0x08]); data.extend_from_slice(b"LocalRIB");
649
650 let afi = Afi::Ipv4;
651 let asn_len = AsnLength::Bits32;
652 let peer_type = BmpPeerType::LocalRib;
653
654 let result =
655 parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
656
657 assert!(result.is_ok(), "Parsing should succeed");
658
659 let peer_notification = result.unwrap();
660 assert_eq!(peer_notification.tlvs.len(), 1);
661 assert_eq!(
662 peer_notification.tlvs[0].info_type,
663 PeerUpTlvType::VrTableName
664 );
665 assert_eq!(peer_notification.tlvs[0].info_value, "LocalRIB");
666 }
668
669 #[test]
670 fn test_local_rib_with_empty_vr_table_name() {
671 let mut data = BytesMut::new();
674
675 data.extend_from_slice(&[
677 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
678 0x01, 0x01, 0x00, 0xB3, 0x00, 0xB3, ]);
682
683 let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
685 version: 4,
686 asn: crate::models::Asn::new_32bit(65001),
687 hold_time: 180,
688 sender_ip: Ipv4Addr::new(192, 168, 1, 1),
689 extended_length: false,
690 opt_params: vec![OptParam {
691 param_type: 2, param_len: 6,
693 param_value: ParamValue::Capacities(vec![Capability {
694 ty: BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4,
695 value: CapabilityValue::MultiprotocolExtensions(
696 MultiprotocolExtensionsCapability {
697 afi: Afi::Ipv4,
698 safi: Safi::Unicast,
699 },
700 ),
701 }]),
702 }],
703 });
704 let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
705 data.extend_from_slice(&bgp_bytes);
706 data.extend_from_slice(&bgp_bytes);
707
708 data.extend_from_slice(&[0x00, 0x03]); data.extend_from_slice(&[0x00, 0x00]); let afi = Afi::Ipv4;
713 let asn_len = AsnLength::Bits32;
714 let peer_type = BmpPeerType::LocalRib;
715
716 let result =
717 parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
718
719 assert!(result.is_ok(), "Parsing should succeed");
720 }
722
723 #[test]
724 fn test_local_rib_with_oversized_vr_table_name() {
725 let mut data = BytesMut::new();
728
729 data.extend_from_slice(&[
731 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
732 0x01, 0x01, 0x00, 0xB3, 0x00, 0xB3, ]);
736
737 let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
739 version: 4,
740 asn: crate::models::Asn::new_32bit(65001),
741 hold_time: 180,
742 sender_ip: Ipv4Addr::new(192, 168, 1, 1),
743 extended_length: false,
744 opt_params: vec![OptParam {
745 param_type: 2, param_len: 6,
747 param_value: ParamValue::Capacities(vec![Capability {
748 ty: BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4,
749 value: CapabilityValue::MultiprotocolExtensions(
750 MultiprotocolExtensionsCapability {
751 afi: Afi::Ipv4,
752 safi: Safi::Unicast,
753 },
754 ),
755 }]),
756 }],
757 });
758 let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
759 data.extend_from_slice(&bgp_bytes);
760 data.extend_from_slice(&bgp_bytes);
761
762 let oversized_name = "A".repeat(256);
764 data.extend_from_slice(&[0x00, 0x03]); data.extend_from_slice(&[0x01, 0x00]); data.extend_from_slice(oversized_name.as_bytes());
767
768 let afi = Afi::Ipv4;
769 let asn_len = AsnLength::Bits32;
770 let peer_type = BmpPeerType::LocalRib;
771
772 let result =
773 parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
774
775 assert!(result.is_ok(), "Parsing should succeed");
776 }
778
779 #[test]
780 fn test_non_local_rib_no_validation() {
781 let mut data = BytesMut::new();
783
784 data.extend_from_slice(&[
786 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
787 0x01, 0x01, 0x00, 0xB3, 0x00, 0xB3, ]);
791
792 let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
794 version: 4,
795 asn: crate::models::Asn::new_32bit(65001),
796 hold_time: 180,
797 sender_ip: Ipv4Addr::new(192, 168, 1, 1),
798 extended_length: false,
799 opt_params: vec![],
800 });
801 let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
802 data.extend_from_slice(&bgp_bytes);
803 data.extend_from_slice(&bgp_bytes);
804
805 let afi = Afi::Ipv4;
806 let asn_len = AsnLength::Bits32;
807 let peer_type = BmpPeerType::Global; let result =
810 parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
811
812 assert!(result.is_ok(), "Parsing should succeed");
813 }
815}