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");
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",
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");
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::net::{IpAddr, Ipv4Addr};
154
155 #[test]
156 fn test_parse_peer_up_notification() {
157 let mut data = BytesMut::new();
158 data.extend_from_slice(&[
161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x01,
162 0x01, 0x01,
163 ]);
164 data.extend_from_slice(&[0x1F, 0x40]); data.extend_from_slice(&[0x23, 0x28]); let bgp_open_message = crate::models::BgpMessage::Open(BgpOpenMessage {
168 version: 0,
169 asn: Default::default(),
170 hold_time: 0,
171 sender_ip: Ipv4Addr::new(0, 0, 0, 0),
172 extended_length: false,
173 opt_params: vec![],
174 });
175 let bgp_open_message_bytes = bgp_open_message.encode(AsnLength::Bits32);
176 data.extend_from_slice(&bgp_open_message_bytes);
177 data.extend_from_slice(&bgp_open_message_bytes);
178
179 data.extend_from_slice(&[0x00, 0x01]); data.extend_from_slice(&[0x00, 0x02]); data.extend_from_slice(&[0x00, 0x03]); let afi = Afi::Ipv4;
185 let asn_len = AsnLength::Bits32;
186
187 let result = parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, None);
188
189 match result {
190 Ok(peer_notification) => {
191 assert_eq!(
192 peer_notification.local_addr,
193 IpAddr::V4(std::net::Ipv4Addr::new(10, 1, 1, 1))
194 );
195 assert_eq!(peer_notification.local_port, 8000);
196 assert_eq!(peer_notification.remote_port, 9000);
197
198 let tlv = peer_notification.tlvs.first().unwrap();
200 assert_eq!(tlv.info_type, PeerUpTlvType::SysDescr);
201 assert_eq!(tlv.info_len, 2);
202 assert_eq!(tlv.info_value, "\u{0}\u{3}");
203 }
204 Err(_) => {
205 panic!("parse_peer_up_notification should return Ok");
206 }
207 }
208 }
209
210 fn setup_warning_logger() -> std::sync::Arc<std::sync::Mutex<Vec<String>>> {
212 use log::{Level, Record};
213 use std::sync::{Arc, Mutex};
214
215 struct TestLogger(Arc<Mutex<Vec<String>>>);
216
217 impl log::Log for TestLogger {
218 fn enabled(&self, metadata: &log::Metadata) -> bool {
219 metadata.level() <= Level::Warn
220 }
221
222 fn log(&self, record: &Record) {
223 if record.level() <= Level::Warn {
224 self.0.lock().unwrap().push(record.args().to_string());
225 }
226 }
227
228 fn flush(&self) {}
229 }
230
231 let warnings = Arc::new(Mutex::new(Vec::new()));
232 let logger = TestLogger(warnings.clone());
233 let _ = log::set_boxed_logger(Box::new(logger));
234 log::set_max_level(log::LevelFilter::Warn);
235 warnings
236 }
237
238 #[test]
244 fn test_parse_peer_up_notification_no_warnings() {
245 let warnings = setup_warning_logger();
246
247 let mut data = BytesMut::new();
252
253 data.extend_from_slice(&[
255 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
256 0x01, 0x01, 0x00, 0xB3, 0x00, 0xB3, ]);
260
261 let bgp1 = crate::models::BgpMessage::Open(BgpOpenMessage {
266 version: 4,
267 asn: crate::models::Asn::new_16bit(65001),
268 hold_time: 180,
269 sender_ip: Ipv4Addr::new(192, 168, 1, 1),
270 extended_length: false,
271 opt_params: vec![],
272 });
273 let bgp1_bytes = bgp1.encode(AsnLength::Bits32);
274
275 let bgp2 = crate::models::BgpMessage::Open(BgpOpenMessage {
277 version: 4,
278 asn: crate::models::Asn::new_16bit(65002),
279 hold_time: 90,
280 sender_ip: Ipv4Addr::new(192, 168, 1, 2),
281 extended_length: false,
282 opt_params: vec![],
283 });
284 let bgp2_bytes = bgp2.encode(AsnLength::Bits32);
285
286 data.extend_from_slice(&bgp1_bytes);
288 data.extend_from_slice(&bgp2_bytes);
289
290 data.extend_from_slice(&[
292 0x00, 0x00, 0x00, 0x08, ]);
295 data.extend_from_slice(b"TestNode");
296
297 let afi = Afi::Ipv4;
298 let asn_len = AsnLength::Bits32;
299
300 let result = parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, None);
301
302 assert!(result.is_ok(), "Parsing should succeed without warnings");
304
305 let peer_notification = result.unwrap();
306 assert_eq!(
307 peer_notification.local_addr,
308 IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1))
309 );
310 assert_eq!(peer_notification.local_port, 179);
311 assert_eq!(peer_notification.remote_port, 179);
312
313 if let crate::models::BgpMessage::Open(ref open1) = &peer_notification.sent_open {
315 assert_eq!(open1.asn, crate::models::Asn::new_16bit(65001));
316 } else {
317 panic!("sent_open should be an OPEN message");
318 }
319
320 if let crate::models::BgpMessage::Open(ref open2) = &peer_notification.received_open {
321 assert_eq!(open2.asn, crate::models::Asn::new_16bit(65002));
322 } else {
323 panic!("received_open should be an OPEN message");
324 }
325
326 assert_eq!(peer_notification.tlvs.len(), 1);
328 assert_eq!(peer_notification.tlvs[0].info_type, PeerUpTlvType::String);
329 assert_eq!(peer_notification.tlvs[0].info_value, "TestNode");
330
331 let captured_warnings = warnings.lock().unwrap();
333 assert!(
334 captured_warnings.is_empty(),
335 "Test should not produce warnings, but got: {:?}",
336 *captured_warnings
337 );
338 }
339
340 #[test]
341 fn test_parse_peer_up_insufficient_data_first_bgp() {
342 let mut data = BytesMut::new();
343
344 data.extend_from_slice(&[
346 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x01,
347 0x01, 0x01,
348 ]);
349 data.extend_from_slice(&[0x1F, 0x40]); data.extend_from_slice(&[0x23, 0x28]); data.extend_from_slice(&[
354 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
356 0x40, 0x01, ]);
359 let afi = Afi::Ipv4;
362 let asn_len = AsnLength::Bits32;
363 let result = parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, None);
364
365 assert!(
366 result.is_err(),
367 "Should fail with insufficient data for first BGP message"
368 );
369 }
370
371 #[test]
372 fn test_parse_peer_up_insufficient_data_second_bgp() {
373 let mut data = BytesMut::new();
374
375 data.extend_from_slice(&[
377 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x01,
378 0x01, 0x01,
379 ]);
380 data.extend_from_slice(&[0x1F, 0x40]); data.extend_from_slice(&[0x23, 0x28]); let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
385 version: 4,
386 asn: Default::default(),
387 hold_time: 180,
388 sender_ip: Ipv4Addr::new(0, 0, 0, 0),
389 extended_length: false,
390 opt_params: vec![],
391 });
392 let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
393 data.extend_from_slice(&bgp_bytes);
394
395 data.extend_from_slice(&[
397 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
399 0x30, ]);
402
403 let afi = Afi::Ipv4;
404 let asn_len = AsnLength::Bits32;
405 let result = parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, None);
406
407 assert!(
408 result.is_err(),
409 "Should fail with insufficient data for second BGP message"
410 );
411 }
412
413 #[test]
414 fn test_parse_peer_up_excess_data_in_tlvs() {
415 let mut data = BytesMut::new();
416
417 data.extend_from_slice(&[
419 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x01,
420 0x01, 0x01,
421 ]);
422 data.extend_from_slice(&[0x1F, 0x40]); data.extend_from_slice(&[0x23, 0x28]); let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
427 version: 4,
428 asn: Default::default(),
429 hold_time: 180,
430 sender_ip: Ipv4Addr::new(0, 0, 0, 0),
431 extended_length: false,
432 opt_params: vec![],
433 });
434 let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
435 data.extend_from_slice(&bgp_bytes);
436 data.extend_from_slice(&bgp_bytes);
437
438 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;
451 let asn_len = AsnLength::Bits32;
452 let result = parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, None);
453
454 assert!(result.is_ok(), "Should handle excess data gracefully");
456
457 let peer_notification = result.unwrap();
458 assert_eq!(peer_notification.tlvs.len(), 2); assert_eq!(peer_notification.tlvs[0].info_type, PeerUpTlvType::String);
460 assert_eq!(peer_notification.tlvs[0].info_value, "Test");
461 assert_eq!(peer_notification.tlvs[1].info_type, PeerUpTlvType::String);
462 assert_eq!(peer_notification.tlvs[1].info_value, "Router");
463 }
464
465 #[test]
466 fn test_local_rib_without_multiprotocol_capability() {
467 let mut data = BytesMut::new();
470
471 data.extend_from_slice(&[
473 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
474 0x01, 0x01, 0x00, 0xB3, 0x00, 0xB3, ]);
478
479 let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
481 version: 4,
482 asn: crate::models::Asn::new_32bit(65001),
483 hold_time: 180,
484 sender_ip: Ipv4Addr::new(192, 168, 1, 1),
485 extended_length: false,
486 opt_params: vec![], });
488 let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
489 data.extend_from_slice(&bgp_bytes);
490 data.extend_from_slice(&bgp_bytes);
491
492 let afi = Afi::Ipv4;
493 let asn_len = AsnLength::Bits32;
494 let peer_type = BmpPeerType::LocalRib;
495
496 let result =
497 parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
498
499 assert!(result.is_ok(), "Parsing should succeed");
500 }
502
503 #[test]
504 fn test_local_rib_with_multiprotocol_capability() {
505 let mut data = BytesMut::new();
508
509 data.extend_from_slice(&[
511 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
512 0x01, 0x01, 0x00, 0xB3, 0x00, 0xB3, ]);
516
517 let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
519 version: 4,
520 asn: crate::models::Asn::new_32bit(65001),
521 hold_time: 180,
522 sender_ip: Ipv4Addr::new(192, 168, 1, 1),
523 extended_length: false,
524 opt_params: vec![OptParam {
525 param_type: 2, param_len: 6,
527 param_value: ParamValue::Capacities(vec![Capability {
528 ty: BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4,
529 value: CapabilityValue::MultiprotocolExtensions(
530 MultiprotocolExtensionsCapability {
531 afi: Afi::Ipv4,
532 safi: Safi::Unicast,
533 },
534 ),
535 }]),
536 }],
537 });
538 let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
539 data.extend_from_slice(&bgp_bytes);
540 data.extend_from_slice(&bgp_bytes);
541
542 let afi = Afi::Ipv4;
543 let asn_len = AsnLength::Bits32;
544 let peer_type = BmpPeerType::LocalRib;
545
546 let result =
547 parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
548
549 assert!(result.is_ok(), "Parsing should succeed");
550 }
552
553 #[test]
554 fn test_local_rib_without_vr_table_name_tlv() {
555 let mut data = BytesMut::new();
558
559 data.extend_from_slice(&[
561 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
562 0x01, 0x01, 0x00, 0xB3, 0x00, 0xB3, ]);
566
567 let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
569 version: 4,
570 asn: crate::models::Asn::new_32bit(65001),
571 hold_time: 180,
572 sender_ip: Ipv4Addr::new(192, 168, 1, 1),
573 extended_length: false,
574 opt_params: vec![OptParam {
575 param_type: 2, param_len: 6,
577 param_value: ParamValue::Capacities(vec![Capability {
578 ty: BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4,
579 value: CapabilityValue::MultiprotocolExtensions(
580 MultiprotocolExtensionsCapability {
581 afi: Afi::Ipv4,
582 safi: Safi::Unicast,
583 },
584 ),
585 }]),
586 }],
587 });
588 let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
589 data.extend_from_slice(&bgp_bytes);
590 data.extend_from_slice(&bgp_bytes);
591
592 data.extend_from_slice(&[0x00, 0x00]); data.extend_from_slice(&[0x00, 0x04]); data.extend_from_slice(b"Test");
596
597 let afi = Afi::Ipv4;
598 let asn_len = AsnLength::Bits32;
599 let peer_type = BmpPeerType::LocalRib;
600
601 let result =
602 parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
603
604 assert!(result.is_ok(), "Parsing should succeed");
605 }
607
608 #[test]
609 fn test_local_rib_with_valid_vr_table_name_tlv() {
610 let mut data = BytesMut::new();
613
614 data.extend_from_slice(&[
616 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
617 0x01, 0x01, 0x00, 0xB3, 0x00, 0xB3, ]);
621
622 let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
624 version: 4,
625 asn: crate::models::Asn::new_32bit(65001),
626 hold_time: 180,
627 sender_ip: Ipv4Addr::new(192, 168, 1, 1),
628 extended_length: false,
629 opt_params: vec![OptParam {
630 param_type: 2, param_len: 6,
632 param_value: ParamValue::Capacities(vec![Capability {
633 ty: BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4,
634 value: CapabilityValue::MultiprotocolExtensions(
635 MultiprotocolExtensionsCapability {
636 afi: Afi::Ipv4,
637 safi: Safi::Unicast,
638 },
639 ),
640 }]),
641 }],
642 });
643 let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
644 data.extend_from_slice(&bgp_bytes);
645 data.extend_from_slice(&bgp_bytes);
646
647 data.extend_from_slice(&[0x00, 0x03]); data.extend_from_slice(&[0x00, 0x08]); data.extend_from_slice(b"LocalRIB");
651
652 let afi = Afi::Ipv4;
653 let asn_len = AsnLength::Bits32;
654 let peer_type = BmpPeerType::LocalRib;
655
656 let result =
657 parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
658
659 assert!(result.is_ok(), "Parsing should succeed");
660
661 let peer_notification = result.unwrap();
662 assert_eq!(peer_notification.tlvs.len(), 1);
663 assert_eq!(
664 peer_notification.tlvs[0].info_type,
665 PeerUpTlvType::VrTableName
666 );
667 assert_eq!(peer_notification.tlvs[0].info_value, "LocalRIB");
668 }
670
671 #[test]
672 fn test_local_rib_with_empty_vr_table_name() {
673 let mut data = BytesMut::new();
676
677 data.extend_from_slice(&[
679 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
680 0x01, 0x01, 0x00, 0xB3, 0x00, 0xB3, ]);
684
685 let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
687 version: 4,
688 asn: crate::models::Asn::new_32bit(65001),
689 hold_time: 180,
690 sender_ip: Ipv4Addr::new(192, 168, 1, 1),
691 extended_length: false,
692 opt_params: vec![OptParam {
693 param_type: 2, param_len: 6,
695 param_value: ParamValue::Capacities(vec![Capability {
696 ty: BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4,
697 value: CapabilityValue::MultiprotocolExtensions(
698 MultiprotocolExtensionsCapability {
699 afi: Afi::Ipv4,
700 safi: Safi::Unicast,
701 },
702 ),
703 }]),
704 }],
705 });
706 let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
707 data.extend_from_slice(&bgp_bytes);
708 data.extend_from_slice(&bgp_bytes);
709
710 data.extend_from_slice(&[0x00, 0x03]); data.extend_from_slice(&[0x00, 0x00]); let afi = Afi::Ipv4;
715 let asn_len = AsnLength::Bits32;
716 let peer_type = BmpPeerType::LocalRib;
717
718 let result =
719 parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
720
721 assert!(result.is_ok(), "Parsing should succeed");
722 }
724
725 #[test]
726 fn test_local_rib_with_oversized_vr_table_name() {
727 let mut data = BytesMut::new();
730
731 data.extend_from_slice(&[
733 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
734 0x01, 0x01, 0x00, 0xB3, 0x00, 0xB3, ]);
738
739 let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
741 version: 4,
742 asn: crate::models::Asn::new_32bit(65001),
743 hold_time: 180,
744 sender_ip: Ipv4Addr::new(192, 168, 1, 1),
745 extended_length: false,
746 opt_params: vec![OptParam {
747 param_type: 2, param_len: 6,
749 param_value: ParamValue::Capacities(vec![Capability {
750 ty: BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4,
751 value: CapabilityValue::MultiprotocolExtensions(
752 MultiprotocolExtensionsCapability {
753 afi: Afi::Ipv4,
754 safi: Safi::Unicast,
755 },
756 ),
757 }]),
758 }],
759 });
760 let bgp_bytes = bgp_open.encode(AsnLength::Bits32);
761 data.extend_from_slice(&bgp_bytes);
762 data.extend_from_slice(&bgp_bytes);
763
764 let oversized_name = "A".repeat(256);
766 data.extend_from_slice(&[0x00, 0x03]); data.extend_from_slice(&[0x01, 0x00]); data.extend_from_slice(oversized_name.as_bytes());
769
770 let afi = Afi::Ipv4;
771 let asn_len = AsnLength::Bits32;
772 let peer_type = BmpPeerType::LocalRib;
773
774 let result =
775 parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
776
777 assert!(result.is_ok(), "Parsing should succeed");
778 }
780
781 #[test]
782 fn test_non_local_rib_no_validation() {
783 let mut data = BytesMut::new();
785
786 data.extend_from_slice(&[
788 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8,
789 0x01, 0x01, 0x00, 0xB3, 0x00, 0xB3, ]);
793
794 let bgp_open = crate::models::BgpMessage::Open(BgpOpenMessage {
796 version: 4,
797 asn: crate::models::Asn::new_32bit(65001),
798 hold_time: 180,
799 sender_ip: Ipv4Addr::new(192, 168, 1, 1),
800 extended_length: false,
801 opt_params: vec![],
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 afi = Afi::Ipv4;
808 let asn_len = AsnLength::Bits32;
809 let peer_type = BmpPeerType::Global; let result =
812 parse_peer_up_notification(&mut data.freeze(), &afi, &asn_len, Some(&peer_type));
813
814 assert!(result.is_ok(), "Parsing should succeed");
815 }
817}