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.has_n_remaining(12)?;
54 data.advance(12);
55 let ip = data.read_ipv4_address()?;
56 ip.into()
57 }
58 Afi::Ipv6 => data.read_ipv6_address()?.into(),
59 Afi::LinkState => {
60 data.has_n_remaining(12)?;
63 data.advance(12);
64 std::net::Ipv4Addr::new(0, 0, 0, 0).into()
65 }
66 };
67
68 let local_port = data.read_u16()?;
69 let remote_port = data.read_u16()?;
70
71 data.has_n_remaining(19)?; let bgp1_length = u16::from_be_bytes([data[16], data[17]]) as usize;
74 data.has_n_remaining(bgp1_length)?;
75 let mut bgp1_data = data.split_to(bgp1_length);
76 let sent_open = parse_bgp_message(&mut bgp1_data, false, asn_len)?;
77
78 data.has_n_remaining(19)?; let bgp2_length = u16::from_be_bytes([data[16], data[17]]) as usize;
81 data.has_n_remaining(bgp2_length)?;
82 let mut bgp2_data = data.split_to(bgp2_length);
83 let received_open = parse_bgp_message(&mut bgp2_data, false, asn_len)?;
84
85 if let Some(BmpPeerType::LocalRib) = peer_type {
87 if let BgpMessage::Open(ref open_msg) = &sent_open {
89 let has_multiprotocol_capability = open_msg.opt_params.iter().any(|param| {
90 if let ParamValue::Capacities(caps) = ¶m.param_value {
91 caps.iter()
92 .any(|cap| cap.ty == BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4)
93 } else {
94 false
95 }
96 });
97 if !has_multiprotocol_capability {
98 warn!("RFC 9069: Local RIB peer up notification should include multiprotocol capabilities in fabricated OPEN messages (parsing Peer Up Notification)");
99 }
100 }
101 }
102
103 let mut tlvs = vec![];
104 let mut has_vr_table_name = false;
105
106 while data.remaining() >= 4 {
107 let info_type = PeerUpTlvType::try_from(data.read_u16()?)?;
108 let info_len = data.read_u16()?;
109 let info_value = data.read_n_bytes_to_string(info_len as usize)?;
110
111 if let Some(BmpPeerType::LocalRib) = peer_type {
113 if info_type == PeerUpTlvType::VrTableName {
114 has_vr_table_name = true;
115 if info_value.is_empty() || info_value.len() > 255 {
117 warn!(
118 "RFC 9069: VrTableName TLV length must be 1-255 bytes, found {} bytes (parsing Peer Up Notification)",
119 info_value.len()
120 );
121 }
122 }
123 }
124
125 tlvs.push(PeerUpNotificationTlv {
126 info_type,
127 info_len,
128 info_value,
129 })
130 }
131
132 if let Some(BmpPeerType::LocalRib) = peer_type {
134 if !has_vr_table_name {
135 warn!("RFC 9069: Local RIB peer up notification should include VrTableName TLV (parsing Peer Up Notification)");
136 }
137 }
138 Ok(PeerUpNotification {
139 local_addr,
140 local_port,
141 remote_port,
142 sent_open,
143 received_open,
144 tlvs,
145 })
146}
147
148#[cfg(test)]
149mod tests {
150 use super::*;
151 use crate::models::capabilities::{BgpCapabilityType, MultiprotocolExtensionsCapability};
152 use bytes::BytesMut;
153 use std::cell::RefCell;
154 use std::net::{IpAddr, Ipv4Addr};
155 use std::sync::{Arc, Mutex, Once};
156
157 thread_local! {
158 static WARNING_CAPTURE: RefCell<Option<Arc<Mutex<Vec<String>>>>> = const { RefCell::new(None) };
159 }
160
161 struct WarningCaptureGuard {
162 warnings: Arc<Mutex<Vec<String>>>,
163 }
164
165 impl WarningCaptureGuard {
166 fn warnings(&self) -> &Arc<Mutex<Vec<String>>> {
167 &self.warnings
168 }
169 }
170
171 impl Drop for WarningCaptureGuard {
172 fn drop(&mut self) {
173 clear_warning_logger();
174 }
175 }
176
177 #[test]
178 fn test_parse_peer_up_notification() {
179 let mut data = BytesMut::new();
180 data.extend_from_slice(&[
183 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x01,
184 0x01, 0x01,
185 ]);
186 data.extend_from_slice(&[0x1F, 0x40]); data.extend_from_slice(&[0x23, 0x28]); let bgp_open_message = crate::models::BgpMessage::Open(BgpOpenMessage {
190 version: 0,
191 asn: Default::default(),
192 hold_time: 0,
193 bgp_identifier: Ipv4Addr::new(0, 0, 0, 0),
194 extended_length: false,
195 opt_params: vec![],
196 });
197 let bgp_open_message_bytes = bgp_open_message.encode(AsnLength::Bits32);
198 data.extend_from_slice(&bgp_open_message_bytes);
199 data.extend_from_slice(&bgp_open_message_bytes);
200
201 data.extend_from_slice(&[0x00, 0x01]); data.extend_from_slice(&[0x00, 0x02]); data.extend_from_slice(&[0x00, 0x03]); let afi = Afi::Ipv4;
207 let asn_len = AsnLength::Bits32;
208
209 let result = parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, None);
210
211 match result {
212 Ok(peer_notification) => {
213 assert_eq!(
214 peer_notification.local_addr,
215 IpAddr::V4(std::net::Ipv4Addr::new(10, 1, 1, 1))
216 );
217 assert_eq!(peer_notification.local_port, 8000);
218 assert_eq!(peer_notification.remote_port, 9000);
219
220 let tlv = peer_notification.tlvs.first().unwrap();
222 assert_eq!(tlv.info_type, PeerUpTlvType::SysDescr);
223 assert_eq!(tlv.info_len, 2);
224 assert_eq!(tlv.info_value, "\u{0}\u{3}");
225 }
226 Err(_) => {
227 panic!("parse_peer_up_notification should return Ok");
228 }
229 }
230 }
231
232 fn setup_warning_logger() -> WarningCaptureGuard {
234 use log::{Level, Record};
235
236 static LOGGER_INIT: Once = Once::new();
237
238 struct TestLogger;
239
240 impl log::Log for TestLogger {
241 fn enabled(&self, metadata: &log::Metadata) -> bool {
242 metadata.level() <= Level::Warn
243 }
244
245 fn log(&self, record: &Record) {
246 if record.level() <= Level::Warn {
247 WARNING_CAPTURE.with(|capture| {
248 if let Some(warnings) = capture.borrow().as_ref() {
249 match warnings.lock() {
250 Ok(mut warnings) => warnings.push(record.args().to_string()),
251 Err(poisoned) => {
252 poisoned.into_inner().push(record.args().to_string());
253 }
254 }
255 }
256 });
257 }
258 }
259
260 fn flush(&self) {}
261 }
262
263 LOGGER_INIT.call_once(|| {
264 log::set_boxed_logger(Box::new(TestLogger)).unwrap();
265 log::set_max_level(log::LevelFilter::Warn);
266 });
267
268 let warnings = Arc::new(Mutex::new(Vec::new()));
269 WARNING_CAPTURE.with(|capture| {
270 *capture.borrow_mut() = Some(warnings.clone());
271 });
272 WarningCaptureGuard { warnings }
273 }
274
275 fn clear_warning_logger() {
276 WARNING_CAPTURE.with(|capture| {
277 *capture.borrow_mut() = None;
278 });
279 }
280
281 #[test]
287 fn test_parse_peer_up_notification_no_warnings() {
288 let warnings = setup_warning_logger();
289
290 let mut data = BytesMut::new();
295
296 data.extend_from_slice(&[
298 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
299 0x01, 0x01, 0x00, 0xB3, 0x00, 0xB3, ]);
303
304 let bgp1 = crate::models::BgpMessage::Open(BgpOpenMessage {
309 version: 4,
310 asn: crate::models::Asn::new_16bit(65001),
311 hold_time: 180,
312 bgp_identifier: Ipv4Addr::new(192, 168, 1, 1),
313 extended_length: false,
314 opt_params: vec![],
315 });
316 let bgp1_bytes = bgp1.encode(AsnLength::Bits32);
317
318 let bgp2 = crate::models::BgpMessage::Open(BgpOpenMessage {
320 version: 4,
321 asn: crate::models::Asn::new_16bit(65002),
322 hold_time: 90,
323 bgp_identifier: Ipv4Addr::new(192, 168, 1, 2),
324 extended_length: false,
325 opt_params: vec![],
326 });
327 let bgp2_bytes = bgp2.encode(AsnLength::Bits32);
328
329 data.extend_from_slice(&bgp1_bytes);
331 data.extend_from_slice(&bgp2_bytes);
332
333 data.extend_from_slice(&[
335 0x00, 0x00, 0x00, 0x08, ]);
338 data.extend_from_slice(b"TestNode");
339
340 let afi = Afi::Ipv4;
341 let asn_len = AsnLength::Bits32;
342
343 let result = parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, None);
344
345 assert!(result.is_ok(), "Parsing should succeed without warnings");
347
348 let peer_notification = result.unwrap();
349 assert_eq!(
350 peer_notification.local_addr,
351 IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1))
352 );
353 assert_eq!(peer_notification.local_port, 179);
354 assert_eq!(peer_notification.remote_port, 179);
355
356 if let crate::models::BgpMessage::Open(ref open1) = &peer_notification.sent_open {
358 assert_eq!(open1.asn, crate::models::Asn::new_16bit(65001));
359 } else {
360 panic!("sent_open should be an OPEN message");
361 }
362
363 if let crate::models::BgpMessage::Open(ref open2) = &peer_notification.received_open {
364 assert_eq!(open2.asn, crate::models::Asn::new_16bit(65002));
365 } else {
366 panic!("received_open should be an OPEN message");
367 }
368
369 assert_eq!(peer_notification.tlvs.len(), 1);
371 assert_eq!(peer_notification.tlvs[0].info_type, PeerUpTlvType::String);
372 assert_eq!(peer_notification.tlvs[0].info_value, "TestNode");
373
374 let captured_warnings = warnings.warnings().lock().unwrap();
376 assert!(
377 captured_warnings.is_empty(),
378 "Test should not produce warnings, but got: {:?}",
379 *captured_warnings
380 );
381 }
382
383 #[test]
384 fn test_parse_peer_up_insufficient_data_first_bgp() {
385 let mut data = BytesMut::new();
386
387 data.extend_from_slice(&[
389 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x01,
390 0x01, 0x01,
391 ]);
392 data.extend_from_slice(&[0x1F, 0x40]); data.extend_from_slice(&[0x23, 0x28]); data.extend_from_slice(&[
397 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
399 0x40, 0x01, ]);
402 let afi = Afi::Ipv4;
405 let asn_len = AsnLength::Bits32;
406 let result = parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, None);
407
408 assert!(
409 result.is_err(),
410 "Should fail with insufficient data for first BGP message"
411 );
412 }
413
414 #[test]
415 fn test_parse_peer_up_insufficient_data_second_bgp() {
416 let mut data = BytesMut::new();
417
418 data.extend_from_slice(&[
420 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x01,
421 0x01, 0x01,
422 ]);
423 data.extend_from_slice(&[0x1F, 0x40]); data.extend_from_slice(&[0x23, 0x28]); let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
428 version: 4,
429 asn: Default::default(),
430 hold_time: 180,
431 bgp_identifier: Ipv4Addr::new(0, 0, 0, 0),
432 extended_length: false,
433 opt_params: vec![],
434 });
435 let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
436 data.extend_from_slice(&bgp_bytes);
437
438 data.extend_from_slice(&[
440 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
442 0x30, ]);
445
446 let afi = Afi::Ipv4;
447 let asn_len = AsnLength::Bits32;
448 let result = parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, None);
449
450 assert!(
451 result.is_err(),
452 "Should fail with insufficient data for second BGP message"
453 );
454 }
455
456 #[test]
457 fn test_parse_peer_up_excess_data_in_tlvs() {
458 let mut data = BytesMut::new();
459
460 data.extend_from_slice(&[
462 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x01,
463 0x01, 0x01,
464 ]);
465 data.extend_from_slice(&[0x1F, 0x40]); data.extend_from_slice(&[0x23, 0x28]); let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
470 version: 4,
471 asn: Default::default(),
472 hold_time: 180,
473 bgp_identifier: Ipv4Addr::new(0, 0, 0, 0),
474 extended_length: false,
475 opt_params: vec![],
476 });
477 let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
478 data.extend_from_slice(&bgp_bytes);
479 data.extend_from_slice(&bgp_bytes);
480
481 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;
494 let asn_len = AsnLength::Bits32;
495 let result = parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, None);
496
497 assert!(result.is_ok(), "Should handle excess data gracefully");
499
500 let peer_notification = result.unwrap();
501 assert_eq!(peer_notification.tlvs.len(), 2); assert_eq!(peer_notification.tlvs[0].info_type, PeerUpTlvType::String);
503 assert_eq!(peer_notification.tlvs[0].info_value, "Test");
504 assert_eq!(peer_notification.tlvs[1].info_type, PeerUpTlvType::String);
505 assert_eq!(peer_notification.tlvs[1].info_value, "Router");
506 }
507
508 #[test]
509 fn test_local_rib_without_multiprotocol_capability() {
510 let mut data = BytesMut::new();
513
514 data.extend_from_slice(&[
516 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
517 0x01, 0x01, 0x00, 0xB3, 0x00, 0xB3, ]);
521
522 let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
524 version: 4,
525 asn: crate::models::Asn::new_32bit(65001),
526 hold_time: 180,
527 bgp_identifier: Ipv4Addr::new(192, 168, 1, 1),
528 extended_length: false,
529 opt_params: vec![], });
531 let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
532 data.extend_from_slice(&bgp_bytes);
533 data.extend_from_slice(&bgp_bytes);
534
535 let afi = Afi::Ipv4;
536 let asn_len = AsnLength::Bits32;
537 let peer_type = BmpPeerType::LocalRib;
538
539 let result =
540 parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
541
542 assert!(result.is_ok(), "Parsing should succeed");
543 }
545
546 #[test]
547 fn test_local_rib_with_multiprotocol_capability() {
548 let mut data = BytesMut::new();
551
552 data.extend_from_slice(&[
554 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
555 0x01, 0x01, 0x00, 0xB3, 0x00, 0xB3, ]);
559
560 let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
562 version: 4,
563 asn: crate::models::Asn::new_32bit(65001),
564 hold_time: 180,
565 bgp_identifier: Ipv4Addr::new(192, 168, 1, 1),
566 extended_length: false,
567 opt_params: vec![OptParam {
568 param_type: 2, param_len: 6,
570 param_value: ParamValue::Capacities(vec![Capability {
571 ty: BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4,
572 value: CapabilityValue::MultiprotocolExtensions(
573 MultiprotocolExtensionsCapability {
574 afi: Afi::Ipv4,
575 safi: Safi::Unicast,
576 },
577 ),
578 }]),
579 }],
580 });
581 let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
582 data.extend_from_slice(&bgp_bytes);
583 data.extend_from_slice(&bgp_bytes);
584
585 let afi = Afi::Ipv4;
586 let asn_len = AsnLength::Bits32;
587 let peer_type = BmpPeerType::LocalRib;
588
589 let result =
590 parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
591
592 assert!(result.is_ok(), "Parsing should succeed");
593 }
595
596 #[test]
597 fn test_local_rib_without_vr_table_name_tlv() {
598 let mut data = BytesMut::new();
601
602 data.extend_from_slice(&[
604 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
605 0x01, 0x01, 0x00, 0xB3, 0x00, 0xB3, ]);
609
610 let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
612 version: 4,
613 asn: crate::models::Asn::new_32bit(65001),
614 hold_time: 180,
615 bgp_identifier: Ipv4Addr::new(192, 168, 1, 1),
616 extended_length: false,
617 opt_params: vec![OptParam {
618 param_type: 2, param_len: 6,
620 param_value: ParamValue::Capacities(vec![Capability {
621 ty: BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4,
622 value: CapabilityValue::MultiprotocolExtensions(
623 MultiprotocolExtensionsCapability {
624 afi: Afi::Ipv4,
625 safi: Safi::Unicast,
626 },
627 ),
628 }]),
629 }],
630 });
631 let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
632 data.extend_from_slice(&bgp_bytes);
633 data.extend_from_slice(&bgp_bytes);
634
635 data.extend_from_slice(&[0x00, 0x00]); data.extend_from_slice(&[0x00, 0x04]); data.extend_from_slice(b"Test");
639
640 let afi = Afi::Ipv4;
641 let asn_len = AsnLength::Bits32;
642 let peer_type = BmpPeerType::LocalRib;
643
644 let result =
645 parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
646
647 assert!(result.is_ok(), "Parsing should succeed");
648 }
650
651 #[test]
652 fn test_local_rib_with_valid_vr_table_name_tlv() {
653 let mut data = BytesMut::new();
656
657 data.extend_from_slice(&[
659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
660 0x01, 0x01, 0x00, 0xB3, 0x00, 0xB3, ]);
664
665 let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
667 version: 4,
668 asn: crate::models::Asn::new_32bit(65001),
669 hold_time: 180,
670 bgp_identifier: Ipv4Addr::new(192, 168, 1, 1),
671 extended_length: false,
672 opt_params: vec![OptParam {
673 param_type: 2, param_len: 6,
675 param_value: ParamValue::Capacities(vec![Capability {
676 ty: BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4,
677 value: CapabilityValue::MultiprotocolExtensions(
678 MultiprotocolExtensionsCapability {
679 afi: Afi::Ipv4,
680 safi: Safi::Unicast,
681 },
682 ),
683 }]),
684 }],
685 });
686 let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
687 data.extend_from_slice(&bgp_bytes);
688 data.extend_from_slice(&bgp_bytes);
689
690 data.extend_from_slice(&[0x00, 0x03]); data.extend_from_slice(&[0x00, 0x08]); data.extend_from_slice(b"LocalRIB");
694
695 let afi = Afi::Ipv4;
696 let asn_len = AsnLength::Bits32;
697 let peer_type = BmpPeerType::LocalRib;
698
699 let result =
700 parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
701
702 assert!(result.is_ok(), "Parsing should succeed");
703
704 let peer_notification = result.unwrap();
705 assert_eq!(peer_notification.tlvs.len(), 1);
706 assert_eq!(
707 peer_notification.tlvs[0].info_type,
708 PeerUpTlvType::VrTableName
709 );
710 assert_eq!(peer_notification.tlvs[0].info_value, "LocalRIB");
711 }
713
714 #[test]
715 fn test_local_rib_with_empty_vr_table_name() {
716 let mut data = BytesMut::new();
719
720 data.extend_from_slice(&[
722 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
723 0x01, 0x01, 0x00, 0xB3, 0x00, 0xB3, ]);
727
728 let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
730 version: 4,
731 asn: crate::models::Asn::new_32bit(65001),
732 hold_time: 180,
733 bgp_identifier: Ipv4Addr::new(192, 168, 1, 1),
734 extended_length: false,
735 opt_params: vec![OptParam {
736 param_type: 2, param_len: 6,
738 param_value: ParamValue::Capacities(vec![Capability {
739 ty: BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4,
740 value: CapabilityValue::MultiprotocolExtensions(
741 MultiprotocolExtensionsCapability {
742 afi: Afi::Ipv4,
743 safi: Safi::Unicast,
744 },
745 ),
746 }]),
747 }],
748 });
749 let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
750 data.extend_from_slice(&bgp_bytes);
751 data.extend_from_slice(&bgp_bytes);
752
753 data.extend_from_slice(&[0x00, 0x03]); data.extend_from_slice(&[0x00, 0x00]); let afi = Afi::Ipv4;
758 let asn_len = AsnLength::Bits32;
759 let peer_type = BmpPeerType::LocalRib;
760
761 let result =
762 parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
763
764 assert!(result.is_ok(), "Parsing should succeed");
765 }
767
768 #[test]
769 fn test_local_rib_with_oversized_vr_table_name() {
770 let mut data = BytesMut::new();
773
774 data.extend_from_slice(&[
776 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
777 0x01, 0x01, 0x00, 0xB3, 0x00, 0xB3, ]);
781
782 let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
784 version: 4,
785 asn: crate::models::Asn::new_32bit(65001),
786 hold_time: 180,
787 bgp_identifier: Ipv4Addr::new(192, 168, 1, 1),
788 extended_length: false,
789 opt_params: vec![OptParam {
790 param_type: 2, param_len: 6,
792 param_value: ParamValue::Capacities(vec![Capability {
793 ty: BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4,
794 value: CapabilityValue::MultiprotocolExtensions(
795 MultiprotocolExtensionsCapability {
796 afi: Afi::Ipv4,
797 safi: Safi::Unicast,
798 },
799 ),
800 }]),
801 }],
802 });
803 let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
804 data.extend_from_slice(&bgp_bytes);
805 data.extend_from_slice(&bgp_bytes);
806
807 let oversized_name = "A".repeat(256);
809 data.extend_from_slice(&[0x00, 0x03]); data.extend_from_slice(&[0x01, 0x00]); data.extend_from_slice(oversized_name.as_bytes());
812
813 let afi = Afi::Ipv4;
814 let asn_len = AsnLength::Bits32;
815 let peer_type = BmpPeerType::LocalRib;
816
817 let result =
818 parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
819
820 assert!(result.is_ok(), "Parsing should succeed");
821 }
823
824 #[test]
825 fn test_non_local_rib_no_validation() {
826 let mut data = BytesMut::new();
828
829 data.extend_from_slice(&[
831 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
832 0x01, 0x01, 0x00, 0xB3, 0x00, 0xB3, ]);
836
837 let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
839 version: 4,
840 asn: crate::models::Asn::new_32bit(65001),
841 hold_time: 180,
842 bgp_identifier: Ipv4Addr::new(192, 168, 1, 1),
843 extended_length: false,
844 opt_params: vec![],
845 });
846 let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
847 data.extend_from_slice(&bgp_bytes);
848 data.extend_from_slice(&bgp_bytes);
849
850 let afi = Afi::Ipv4;
851 let asn_len = AsnLength::Bits32;
852 let peer_type = BmpPeerType::Global; let result =
855 parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
856
857 assert!(result.is_ok(), "Parsing should succeed");
858 }
860}