1use crate::models::*;
2use bytes::{Buf, BufMut, Bytes, BytesMut};
3use std::convert::TryFrom;
4use std::net::Ipv4Addr;
5
6use crate::error::ParserError;
7use crate::models::capabilities::{
8 AddPathCapability, BgpCapabilityType, BgpExtendedMessageCapability, BgpRoleCapability,
9 ExtendedNextHopCapability, FourOctetAsCapability, GracefulRestartCapability,
10 MultiprotocolExtensionsCapability, RouteRefreshCapability,
11};
12use crate::models::error::BgpError;
13use crate::parser::bgp::attributes::parse_attributes;
14use crate::parser::{encode_nlri_prefixes, parse_nlri_list, ReadUtils};
15use log::warn;
16use zerocopy::big_endian::{U16, U32};
17use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
18
19#[derive(IntoBytes, FromBytes, KnownLayout, Immutable)]
21#[repr(C)]
22struct RawBgpOpenHeader {
23 version: u8,
24 asn: U16,
25 hold_time: U16,
26 bgp_identifier: U32,
27 opt_params_len: u8,
28}
29
30const _: () = assert!(size_of::<RawBgpOpenHeader>() == 10);
31
32pub fn parse_bgp_message(
51 data: &mut Bytes,
52 add_path: bool,
53 asn_len: &AsnLength,
54) -> Result<BgpMessage, ParserError> {
55 let total_size = data.len();
56 data.has_n_remaining(19)?;
57
58 let mut marker = [0u8; 16];
60 data.copy_to_slice(&mut marker);
61 if marker != [0xFF; 16] {
62 warn!("BGP message marker is not all 0xFF bytes (invalid per RFC 4271)");
65 }
66
67 let length = data.read_u16()?;
79
80 let max_length = 65535; if !(19..=max_length).contains(&length) {
88 return Err(ParserError::ParseError(format!(
89 "invalid BGP message length {length}"
90 )));
91 }
92
93 let length_usize = length as usize;
95 let bgp_msg_length = if length_usize > total_size {
96 total_size.saturating_sub(19)
97 } else {
98 length_usize.saturating_sub(19)
99 };
100
101 let msg_type: BgpMessageType = match BgpMessageType::try_from(data.read_u8()?) {
102 Ok(t) => t,
103 Err(_) => {
104 return Err(ParserError::ParseError(
105 "Unknown BGP Message Type".to_string(),
106 ))
107 }
108 };
109
110 match msg_type {
113 BgpMessageType::OPEN | BgpMessageType::KEEPALIVE => {
114 if length > 4096 {
115 return Err(ParserError::ParseError(format!(
116 "BGP {} message length {} exceeds maximum allowed 4096 bytes (RFC 8654)",
117 match msg_type {
118 BgpMessageType::OPEN => "OPEN",
119 BgpMessageType::KEEPALIVE => "KEEPALIVE",
120 _ => unreachable!(),
121 },
122 length
123 )));
124 }
125 }
126 BgpMessageType::UPDATE | BgpMessageType::NOTIFICATION => {
127 }
130 }
131
132 if data.remaining() != bgp_msg_length {
133 warn!(
134 "BGP message length {} does not match the actual length {} (parsing BGP message)",
135 bgp_msg_length,
136 data.remaining()
137 );
138 }
139 data.has_n_remaining(bgp_msg_length)?;
140 let mut msg_data = data.split_to(bgp_msg_length);
141
142 Ok(match msg_type {
143 BgpMessageType::OPEN => BgpMessage::Open(parse_bgp_open_message(&mut msg_data)?),
144 BgpMessageType::UPDATE => {
145 BgpMessage::Update(parse_bgp_update_message(msg_data, add_path, asn_len)?)
146 }
147 BgpMessageType::NOTIFICATION => {
148 BgpMessage::Notification(parse_bgp_notification_message(msg_data)?)
149 }
150 BgpMessageType::KEEPALIVE => BgpMessage::KeepAlive,
151 })
152}
153
154pub fn parse_bgp_notification_message(
161 mut input: Bytes,
162) -> Result<BgpNotificationMessage, ParserError> {
163 let error_code = input.read_u8()?;
164 let error_subcode = input.read_u8()?;
165
166 Ok(BgpNotificationMessage {
167 error: BgpError::new(error_code, error_subcode),
168 data: input.read_n_bytes(input.len())?,
169 })
170}
171
172impl BgpNotificationMessage {
173 pub fn encode(&self) -> Bytes {
174 let mut buf = BytesMut::new();
175 let (code, subcode) = self.error.get_codes();
176 buf.put_u8(code);
177 buf.put_u8(subcode);
178 buf.put_slice(&self.data);
179 buf.freeze()
180 }
181}
182
183pub fn parse_bgp_open_message(input: &mut Bytes) -> Result<BgpOpenMessage, ParserError> {
214 input.has_n_remaining(10)?;
215 let mut header_bytes = [0u8; 10];
216 input.copy_to_slice(&mut header_bytes);
217 let raw = RawBgpOpenHeader::ref_from_bytes(&header_bytes)
219 .expect("header_bytes is exactly 10 bytes with no alignment requirement");
220
221 let version = raw.version;
222 let asn = Asn::new_16bit(raw.asn.get());
223 let hold_time = raw.hold_time.get();
224 let bgp_identifier = Ipv4Addr::from(raw.bgp_identifier.get());
225 let mut opt_params_len: u16 = raw.opt_params_len as u16;
226
227 let mut extended_length = false;
228 let mut first = true;
229
230 let mut params: Vec<OptParam> = vec![];
231 while input.remaining() >= 2 {
232 let mut param_type = input.read_u8()?;
233 if first {
234 if opt_params_len == 0 && param_type == 255 {
235 return Err(ParserError::ParseError(
236 "RFC 9072 violation: Non-Extended Optional Parameters Length must not be 0 when using extended format".to_string()
237 ));
238 }
239 if opt_params_len != 0 && param_type == 255 {
241 extended_length = true;
263 opt_params_len = input.read_u16()?;
264 if opt_params_len == 0 {
265 break;
266 }
267 if input.remaining() != opt_params_len as usize {
269 warn!(
270 "BGP open message length {} does not match the actual length {} (parsing BGP OPEN message)",
271 opt_params_len,
272 input.remaining()
273 );
274 }
275
276 param_type = input.read_u8()?;
277 }
278 first = false;
279 }
280 let param_len = match extended_length {
283 true => input.read_u16()?,
284 false => input.read_u8()? as u16,
285 };
286
287 let param_value = match param_type {
291 2 => {
292 let mut capacities = vec![];
293
294 input.has_n_remaining(param_len as usize)?;
296 let mut param_data = input.split_to(param_len as usize);
297
298 while param_data.remaining() >= 2 {
299 let code = param_data.read_u8()?;
302 let len = param_data.read_u8()? as u16; let capability_data = param_data.read_n_bytes(len as usize)?;
305 let capability_type = BgpCapabilityType::from(code);
306
307 macro_rules! parse_capability {
309 ($parser:path, $variant:ident) => {
310 match $parser(Bytes::from(capability_data.clone())) {
311 Ok(parsed) => CapabilityValue::$variant(parsed),
312 Err(_) => CapabilityValue::Raw(capability_data),
313 }
314 };
315 }
316
317 let capability_value = match capability_type {
318 BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4 => {
319 parse_capability!(
320 MultiprotocolExtensionsCapability::parse,
321 MultiprotocolExtensions
322 )
323 }
324 BgpCapabilityType::ROUTE_REFRESH_CAPABILITY_FOR_BGP_4 => {
325 parse_capability!(RouteRefreshCapability::parse, RouteRefresh)
326 }
327 BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING => {
328 parse_capability!(ExtendedNextHopCapability::parse, ExtendedNextHop)
329 }
330 BgpCapabilityType::GRACEFUL_RESTART_CAPABILITY => {
331 parse_capability!(GracefulRestartCapability::parse, GracefulRestart)
332 }
333 BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY => {
334 parse_capability!(FourOctetAsCapability::parse, FourOctetAs)
335 }
336 BgpCapabilityType::ADD_PATH_CAPABILITY => {
337 parse_capability!(AddPathCapability::parse, AddPath)
338 }
339 BgpCapabilityType::BGP_ROLE => {
340 parse_capability!(BgpRoleCapability::parse, BgpRole)
341 }
342 BgpCapabilityType::BGP_EXTENDED_MESSAGE => {
343 parse_capability!(
344 BgpExtendedMessageCapability::parse,
345 BgpExtendedMessage
346 )
347 }
348 _ => CapabilityValue::Raw(capability_data),
349 };
350
351 capacities.push(Capability {
352 ty: capability_type,
353 value: capability_value,
354 });
355 }
356
357 ParamValue::Capacities(capacities)
358 }
359 _ => {
360 let bytes = input.read_n_bytes(param_len as usize)?;
362 ParamValue::Raw(bytes)
363 }
364 };
365 params.push(OptParam {
366 param_type,
367 param_len,
368 param_value,
369 });
370 }
371
372 Ok(BgpOpenMessage {
373 version,
374 asn,
375 hold_time,
376 bgp_identifier,
377 extended_length,
378 opt_params: params,
379 })
380}
381
382impl BgpOpenMessage {
383 pub fn encode(&self) -> Bytes {
384 let mut buf = BytesMut::new();
385 let raw_header = RawBgpOpenHeader {
386 version: self.version,
387 asn: U16::new(self.asn.into()),
388 hold_time: U16::new(self.hold_time),
389 bgp_identifier: U32::new(u32::from(self.bgp_identifier)),
390 opt_params_len: self.opt_params.len() as u8,
391 };
392 buf.extend_from_slice(raw_header.as_bytes());
393 for param in &self.opt_params {
394 buf.put_u8(param.param_type);
395 buf.put_u8(param.param_len as u8);
396 match ¶m.param_value {
397 ParamValue::Capacities(capacities) => {
398 for cap in capacities {
399 buf.put_u8(cap.ty.into());
400 let encoded_value = match &cap.value {
401 CapabilityValue::MultiprotocolExtensions(mp) => mp.encode(),
402 CapabilityValue::RouteRefresh(rr) => rr.encode(),
403 CapabilityValue::ExtendedNextHop(enh) => enh.encode(),
404 CapabilityValue::GracefulRestart(gr) => gr.encode(),
405 CapabilityValue::FourOctetAs(foa) => foa.encode(),
406 CapabilityValue::AddPath(ap) => ap.encode(),
407 CapabilityValue::BgpRole(br) => br.encode(),
408 CapabilityValue::BgpExtendedMessage(bem) => bem.encode(),
409 CapabilityValue::Raw(raw) => Bytes::from(raw.clone()),
410 };
411 buf.put_u8(encoded_value.len() as u8);
412 buf.extend(&encoded_value);
413 }
414 }
415 ParamValue::Raw(bytes) => {
416 buf.extend(bytes);
417 }
418 }
419 }
420 buf.freeze()
421 }
422}
423
424fn read_nlri(
426 mut input: Bytes,
427 afi: &Afi,
428 add_path: bool,
429) -> Result<Vec<NetworkPrefix>, ParserError> {
430 let length = input.len();
431 if length == 0 {
432 return Ok(vec![]);
433 }
434 if length == 1 {
435 warn!("seeing strange one-byte NLRI field (parsing NLRI in BGP UPDATE message)");
437 input.advance(1); return Ok(vec![]);
439 }
440
441 parse_nlri_list(input, add_path, afi)
442}
443
444pub fn parse_bgp_update_message(
448 mut input: Bytes,
449 add_path: bool,
450 asn_len: &AsnLength,
451) -> Result<BgpUpdateMessage, ParserError> {
452 let afi = Afi::Ipv4;
454
455 let withdrawn_bytes_length_raw = input.read_u16()?;
457 let withdrawn_bytes_length = withdrawn_bytes_length_raw as usize;
458 input.has_n_remaining(withdrawn_bytes_length)?;
459 let withdrawn_bytes = input.split_to(withdrawn_bytes_length);
460 let withdrawn_prefixes = read_nlri(withdrawn_bytes, &afi, add_path)?;
461
462 let attribute_length_raw = input.read_u16()?;
464 let attribute_length = attribute_length_raw as usize;
468
469 input.has_n_remaining(attribute_length)?;
470 let attr_data_slice = input.split_to(attribute_length);
471 let attributes = parse_attributes(attr_data_slice, asn_len, add_path, None, None, None)?;
472
473 let announced_prefixes = read_nlri(input, &afi, add_path)?;
476
477 Ok(BgpUpdateMessage {
478 withdrawn_prefixes,
479 attributes,
480 announced_prefixes,
481 })
482}
483
484impl BgpUpdateMessage {
485 pub fn encode(&self, asn_len: AsnLength) -> Bytes {
486 let mut bytes = BytesMut::new();
487
488 let withdrawn_bytes = encode_nlri_prefixes(&self.withdrawn_prefixes);
490 bytes.put_u16(withdrawn_bytes.len() as u16);
491 bytes.put_slice(&withdrawn_bytes);
492
493 let attr_bytes = self.attributes.encode(asn_len);
495
496 bytes.put_u16(attr_bytes.len() as u16);
497 bytes.put_slice(&attr_bytes);
498
499 bytes.extend(encode_nlri_prefixes(&self.announced_prefixes));
500 bytes.freeze()
501 }
502
503 pub fn is_end_of_rib(&self) -> bool {
508 if !self.announced_prefixes.is_empty() || !self.withdrawn_prefixes.is_empty() {
513 return false;
517 }
518
519 if self.attributes.inner.is_empty() {
520 return true;
523 }
524
525 if self.attributes.inner.len() > 1 {
528 return false;
530 }
531
532 if let AttributeValue::MpUnreachNlri(nlri) = &self.attributes.inner.first().unwrap().value {
534 if nlri.prefixes.is_empty() {
535 return true;
538 }
539 }
540
541 false
543 }
544}
545
546impl BgpMessage {
547 const MARKER: [u8; 16] = [0xFF; 16];
549
550 pub fn encode(&self, asn_len: AsnLength) -> Bytes {
551 let mut bytes = BytesMut::new();
552 bytes.put_slice(&Self::MARKER);
554
555 let (msg_type, msg_bytes) = match self {
556 BgpMessage::Open(msg) => (BgpMessageType::OPEN, msg.encode()),
557 BgpMessage::Update(msg) => (BgpMessageType::UPDATE, msg.encode(asn_len)),
558 BgpMessage::Notification(msg) => (BgpMessageType::NOTIFICATION, msg.encode()),
559 BgpMessage::KeepAlive => (BgpMessageType::KEEPALIVE, Bytes::new()),
560 };
561
562 bytes.put_u16(msg_bytes.len() as u16 + 16 + 2 + 1);
564 bytes.put_u8(msg_type as u8);
565 bytes.put_slice(&msg_bytes);
566 bytes.freeze()
567 }
568}
569
570impl From<&BgpElem> for BgpUpdateMessage {
571 fn from(elem: &BgpElem) -> Self {
572 BgpUpdateMessage {
573 withdrawn_prefixes: vec![],
574 attributes: Attributes::from(elem),
575 announced_prefixes: vec![],
576 }
577 }
578}
579
580impl From<BgpUpdateMessage> for BgpMessage {
581 fn from(value: BgpUpdateMessage) -> Self {
582 BgpMessage::Update(value)
583 }
584}
585
586#[cfg(test)]
587mod tests {
588 use super::*;
589 use std::net::Ipv4Addr;
590 use std::str::FromStr;
591
592 #[test]
593 fn test_end_of_rib() {
594 let attrs = Attributes::default();
596 let msg = BgpUpdateMessage {
597 withdrawn_prefixes: vec![],
598 attributes: attrs,
599 announced_prefixes: vec![],
600 };
601 assert!(msg.is_end_of_rib());
602
603 let attrs = Attributes::from_iter(vec![AttributeValue::MpUnreachNlri(Nlri {
605 afi: Afi::Ipv4,
606 safi: Safi::Unicast,
607 next_hop: None,
608 prefixes: vec![],
609 link_state_nlris: None,
610 flowspec_nlris: None,
611 })]);
612 let msg = BgpUpdateMessage {
613 withdrawn_prefixes: vec![],
614 attributes: attrs,
615 announced_prefixes: vec![],
616 };
617 assert!(msg.is_end_of_rib());
618
619 let prefix = NetworkPrefix::from_str("192.168.1.0/24").unwrap();
621 let attrs = Attributes::default();
622 let msg = BgpUpdateMessage {
623 withdrawn_prefixes: vec![],
624 attributes: attrs,
625 announced_prefixes: vec![prefix],
626 };
627 assert!(!msg.is_end_of_rib());
628
629 let prefix = NetworkPrefix::from_str("192.168.1.0/24").unwrap();
631 let attrs = Attributes::default();
632 let msg = BgpUpdateMessage {
633 withdrawn_prefixes: vec![prefix],
634 attributes: attrs,
635 announced_prefixes: vec![],
636 };
637 assert!(!msg.is_end_of_rib());
638
639 let attrs = Attributes::from_iter(vec![AttributeValue::MpReachNlri(Nlri {
641 afi: Afi::Ipv4,
642 safi: Safi::Unicast,
643 next_hop: None,
644 prefixes: vec![],
645 link_state_nlris: None,
646 flowspec_nlris: None,
647 })]);
648 let msg = BgpUpdateMessage {
649 withdrawn_prefixes: vec![],
650 attributes: attrs,
651 announced_prefixes: vec![],
652 };
653 assert!(!msg.is_end_of_rib());
654
655 let attrs = Attributes::from_iter(vec![AttributeValue::MpReachNlri(Nlri {
657 afi: Afi::Ipv4,
658 safi: Safi::Unicast,
659 next_hop: None,
660 prefixes: vec![prefix],
661 link_state_nlris: None,
662 flowspec_nlris: None,
663 })]);
664 let msg = BgpUpdateMessage {
665 withdrawn_prefixes: vec![],
666 attributes: attrs,
667 announced_prefixes: vec![],
668 };
669 assert!(!msg.is_end_of_rib());
670
671 let attrs = Attributes::from_iter(vec![AttributeValue::MpUnreachNlri(Nlri {
673 afi: Afi::Ipv4,
674 safi: Safi::Unicast,
675 next_hop: None,
676 prefixes: vec![prefix],
677 link_state_nlris: None,
678 flowspec_nlris: None,
679 })]);
680 let msg = BgpUpdateMessage {
681 withdrawn_prefixes: vec![],
682 attributes: attrs,
683 announced_prefixes: vec![],
684 };
685 assert!(!msg.is_end_of_rib());
686
687 let attrs = Attributes::from_iter(vec![
689 AttributeValue::MpUnreachNlri(Nlri {
690 afi: Afi::Ipv4,
691 safi: Safi::Unicast,
692 next_hop: None,
693 prefixes: vec![],
694 link_state_nlris: None,
695 flowspec_nlris: None,
696 }),
697 AttributeValue::AtomicAggregate,
698 ]);
699 let msg = BgpUpdateMessage {
700 withdrawn_prefixes: vec![],
701 attributes: attrs,
702 announced_prefixes: vec![],
703 };
704 assert!(!msg.is_end_of_rib());
705 }
706
707 #[test]
708 fn test_invlaid_length() {
709 let bytes = Bytes::from_static(&[
710 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, ]);
717 let mut data = bytes.clone();
718 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_err());
719
720 let bytes = Bytes::from_static(&[
721 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x05, ]);
728 let mut data = bytes.clone();
729 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_err());
730 }
731
732 #[test]
733 fn test_invlaid_type() {
734 let bytes = Bytes::from_static(&[
735 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x28, 0x05, ]);
742 let mut data = bytes.clone();
743 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_err());
744 }
745
746 #[test]
747 fn test_bgp_message_length_underflow_protection() {
748 for len in [0u16, 1, 18] {
751 let bytes = Bytes::from(vec![
752 0xFF,
753 0xFF,
754 0xFF,
755 0xFF, 0xFF,
757 0xFF,
758 0xFF,
759 0xFF, 0xFF,
761 0xFF,
762 0xFF,
763 0xFF, 0xFF,
765 0xFF,
766 0xFF,
767 0xFF, (len >> 8) as u8,
769 (len & 0xFF) as u8, 0x01, ]);
772 let mut data = bytes.clone();
773 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
774 assert!(
775 result.is_err(),
776 "Length {} should be rejected as invalid",
777 len
778 );
779 }
780 }
781
782 #[test]
783 fn test_bgp_marker_encoding_rfc4271() {
784 let msg = BgpMessage::KeepAlive;
786 let encoded = msg.encode(AsnLength::Bits16);
787
788 assert_eq!(
790 &encoded[..16],
791 &[0xFF; 16],
792 "BGP marker should be all 0xFF bytes"
793 );
794 }
795
796 #[test]
797 fn test_bgp_marker_validation() {
798 let valid_bytes = Bytes::from(vec![
800 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x13, 0x04, ]);
807 let mut data = valid_bytes.clone();
808 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
809 assert!(result.is_ok(), "Valid marker should parse successfully");
810
811 let invalid_bytes = Bytes::from(vec![
814 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x04, ]);
821 let mut data = invalid_bytes.clone();
822 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
824 assert!(
825 result.is_ok(),
826 "Invalid marker should still parse (with warning)"
827 );
828 }
829
830 #[test]
831 fn test_attribute_length_overflow_protection() {
832 let update_bytes = Bytes::from(vec![
837 0x00, 0x00, 0xFF,
839 0xFF, ]);
842
843 let result = parse_bgp_update_message(update_bytes, false, &AsnLength::Bits16);
844 assert!(
845 result.is_err(),
846 "Should fail when attribute_length exceeds available data"
847 );
848 assert!(
849 matches!(result, Err(ParserError::TruncatedMsg(_))),
850 "Should fail with TruncatedMsg error"
851 );
852
853 let valid_update = Bytes::from(vec![
855 0x00, 0x00, 0x00,
857 0x00, ]);
860 let result = parse_bgp_update_message(valid_update, false, &AsnLength::Bits16);
861 assert!(result.is_ok(), "Should parse valid empty UPDATE");
862 }
863
864 #[test]
865 fn test_parse_bgp_notification_message() {
866 let bytes = Bytes::from_static(&[
867 0x01, 0x02, 0x00, 0x00, ]);
871 let msg = parse_bgp_notification_message(bytes).unwrap();
872 matches!(
873 msg.error,
874 BgpError::MessageHeaderError(MessageHeaderError::BAD_MESSAGE_LENGTH)
875 );
876 assert_eq!(msg.data, Bytes::from_static(&[0x00, 0x00]));
877 }
878
879 #[test]
880 fn test_encode_bgp_notification_messsage() {
881 let msg = BgpNotificationMessage {
882 error: BgpError::MessageHeaderError(MessageHeaderError::BAD_MESSAGE_LENGTH),
883 data: vec![0x00, 0x00],
884 };
885 let bytes = msg.encode();
886 assert_eq!(bytes, Bytes::from_static(&[0x01, 0x02, 0x00, 0x00]));
887 }
888
889 #[test]
890 fn test_parse_bgp_open_message() {
891 let bytes = Bytes::from_static(&[
892 0x04, 0x00, 0x01, 0x00, 0xb4, 0xc0, 0x00, 0x02, 0x01, 0x00, ]);
898 let msg = parse_bgp_open_message(&mut bytes.clone()).unwrap();
899 assert_eq!(msg.version, 4);
900 assert_eq!(msg.asn, Asn::new_16bit(1));
901 assert_eq!(msg.hold_time, 180);
902 assert_eq!(msg.bgp_identifier, Ipv4Addr::new(192, 0, 2, 1));
903 assert!(!msg.extended_length);
904 assert_eq!(msg.opt_params.len(), 0);
905 }
906
907 #[test]
908 fn test_encode_bgp_open_message() {
909 let msg = BgpOpenMessage {
910 version: 4,
911 asn: Asn::new_16bit(1),
912 hold_time: 180,
913 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
914 extended_length: false,
915 opt_params: vec![],
916 };
917 let bytes = msg.encode();
918 assert_eq!(
919 bytes,
920 Bytes::from_static(&[
921 0x04, 0x00, 0x01, 0x00, 0xb4, 0xc0, 0x00, 0x02, 0x01, 0x00, ])
927 );
928 }
929
930 #[test]
931 fn test_encode_bgp_notification_message() {
932 let bgp_message = BgpMessage::Notification(BgpNotificationMessage {
933 error: BgpError::MessageHeaderError(MessageHeaderError::BAD_MESSAGE_LENGTH),
934 data: vec![0x00, 0x00],
935 });
936 let bytes = bgp_message.encode(AsnLength::Bits16);
937 assert_eq!(
939 bytes,
940 Bytes::from_static(&[
941 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x17, 0x03, 0x01, 0x02, 0x00, 0x00 ])
948 );
949 }
950
951 #[test]
952 fn test_bgp_message_from_bgp_update_message() {
953 let msg = BgpMessage::from(BgpUpdateMessage::default());
954 assert!(matches!(msg, BgpMessage::Update(_)));
955 }
956
957 #[test]
958 fn test_parse_bgp_open_message_with_extended_next_hop_capability() {
959 use crate::models::{Afi, Safi};
960
961 let bytes = Bytes::from(vec![
967 0x04, 0xfd, 0xe9, 0x00, 0xb4, 0xc0, 0x00, 0x02, 0x01, 0x10, 0x02, 0x0e, 0x05, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x80, 0x00, 0x02, ]);
983
984 let msg = parse_bgp_open_message(&mut bytes.clone()).unwrap();
985 assert_eq!(msg.version, 4);
986 assert_eq!(msg.asn, Asn::new_16bit(65001));
987 assert_eq!(msg.hold_time, 180);
988 assert_eq!(msg.bgp_identifier, Ipv4Addr::new(192, 0, 2, 1));
989 assert!(!msg.extended_length);
990 assert_eq!(msg.opt_params.len(), 1);
991
992 if let ParamValue::Capacities(cap) = &msg.opt_params[0].param_value {
994 assert_eq!(cap[0].ty, BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING);
995
996 if let CapabilityValue::ExtendedNextHop(enh_cap) = &cap[0].value {
997 assert_eq!(enh_cap.entries.len(), 2);
998
999 let entry1 = &enh_cap.entries[0];
1001 assert_eq!(entry1.nlri_afi, Afi::Ipv4);
1002 assert_eq!(entry1.nlri_safi, Safi::Unicast);
1003 assert_eq!(entry1.nexthop_afi, Afi::Ipv6);
1004
1005 let entry2 = &enh_cap.entries[1];
1007 assert_eq!(entry2.nlri_afi, Afi::Ipv4);
1008 assert_eq!(entry2.nlri_safi, Safi::MplsVpn);
1009 assert_eq!(entry2.nexthop_afi, Afi::Ipv6);
1010
1011 assert!(enh_cap.supports(Afi::Ipv4, Safi::Unicast, Afi::Ipv6));
1013 assert!(enh_cap.supports(Afi::Ipv4, Safi::MplsVpn, Afi::Ipv6));
1014 assert!(!enh_cap.supports(Afi::Ipv4, Safi::Multicast, Afi::Ipv6));
1015 } else {
1016 panic!("Expected ExtendedNextHop capability value");
1017 }
1018 } else {
1019 panic!("Expected capability parameter");
1020 }
1021 }
1022
1023 #[test]
1024 fn test_rfc8654_extended_message_length_validation() {
1025 let bytes = Bytes::from_static(&[
1027 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x00, 0x00,
1035 0x00, ]);
1038 let mut data = bytes.clone();
1039 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_ok());
1041
1042 let bytes = Bytes::from_static(&[
1044 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x01, ]);
1051 let mut data = bytes.clone();
1052 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1053 assert!(result.is_err());
1054 if let Err(ParserError::ParseError(msg)) = result {
1055 assert!(msg.contains("BGP OPEN message length"));
1056 assert!(msg.contains("4096 bytes"));
1057 }
1058
1059 let bytes = Bytes::from_static(&[
1061 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x04, ]);
1068 let mut data = bytes.clone();
1069 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1070 assert!(result.is_err());
1071 if let Err(ParserError::ParseError(msg)) = result {
1072 assert!(msg.contains("BGP KEEPALIVE message length"));
1073 assert!(msg.contains("4096 bytes"));
1074 }
1075
1076 let bytes = Bytes::from_static(&[
1078 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x02, ]);
1085 let mut data = bytes.clone();
1086 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1088 if let Err(ParserError::ParseError(msg)) = result {
1089 assert!(!msg.contains("invalid BGP message length"));
1091 }
1092 }
1093
1094 #[test]
1095 fn test_bgp_extended_message_capability_parsing() {
1096 use crate::models::CapabilityValue;
1097
1098 let bytes = Bytes::from(vec![
1100 0x04, 0x00, 0x01, 0x00, 0xb4, 0xc0, 0x00, 0x02, 0x01, 0x04, 0x02, 0x02, 0x06, 0x00, ]);
1110
1111 let msg = parse_bgp_open_message(&mut bytes.clone()).unwrap();
1112 assert_eq!(msg.version, 4);
1113 assert_eq!(msg.asn, Asn::new_16bit(1));
1114 assert_eq!(msg.opt_params.len(), 1);
1115
1116 if let ParamValue::Capacities(cap) = &msg.opt_params[0].param_value {
1118 assert_eq!(cap[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1119 if let CapabilityValue::BgpExtendedMessage(_) = &cap[0].value {
1120 } else {
1122 panic!("Expected BgpExtendedMessage capability value");
1123 }
1124 } else {
1125 panic!("Expected capability parameter");
1126 }
1127 }
1128
1129 #[test]
1130 fn test_rfc8654_edge_cases() {
1131 let bytes = Bytes::from_static(&[
1133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x03, 0x06, 0x00, ]);
1143 let mut data = bytes.clone();
1144 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1146 if let Err(ParserError::ParseError(msg)) = result {
1148 assert!(!msg.contains("invalid BGP message length"));
1149 assert!(!msg.contains("exceeds maximum allowed 4096 bytes"));
1150 }
1151
1152 let open_data = vec![
1154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, ];
1161 let bytes = Bytes::from(open_data);
1162 let mut data = bytes.clone();
1163 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1164 if let Err(ParserError::ParseError(msg)) = result {
1166 assert!(!msg.contains("exceeds maximum allowed 4096 bytes"));
1167 }
1168
1169 let bytes = Bytes::from_static(&[
1171 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x02, ]);
1178 let mut data = bytes.clone();
1179 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1180 if let Err(ParserError::ParseError(msg)) = result {
1182 assert!(!msg.contains("invalid BGP message length"));
1183 }
1184 }
1185
1186 #[test]
1187 fn test_rfc8654_capability_encoding_path() {
1188 use crate::models::capabilities::BgpExtendedMessageCapability;
1189
1190 let capability_value =
1193 CapabilityValue::BgpExtendedMessage(BgpExtendedMessageCapability::new());
1194 let capability = Capability {
1195 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1196 value: capability_value,
1197 };
1198
1199 let opt_param = OptParam {
1200 param_type: 2, param_len: 2,
1202 param_value: ParamValue::Capacities(vec![capability]),
1203 };
1204
1205 let msg = BgpOpenMessage {
1206 version: 4,
1207 asn: Asn::new_16bit(65001),
1208 hold_time: 180,
1209 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
1210 extended_length: false,
1211 opt_params: vec![opt_param],
1212 };
1213
1214 let encoded = msg.encode();
1216 assert!(!encoded.is_empty());
1217
1218 let parsed = parse_bgp_open_message(&mut encoded.clone()).unwrap();
1220 assert_eq!(parsed.opt_params.len(), 1);
1221 if let ParamValue::Capacities(cap) = &parsed.opt_params[0].param_value {
1222 assert_eq!(cap[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1223 }
1224 }
1225
1226 #[test]
1227 fn test_rfc8654_error_message_formatting() {
1228 let bytes = Bytes::from_static(&[
1233 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x01, ]);
1240 let mut data = bytes.clone();
1241 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1242 assert!(result.is_err());
1243 if let Err(ParserError::ParseError(msg)) = result {
1244 assert!(msg.contains("BGP OPEN message length"));
1245 assert!(msg.contains("exceeds maximum allowed 4096 bytes"));
1246 }
1247
1248 let bytes = Bytes::from_static(&[
1250 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x04, ]);
1257 let mut data = bytes.clone();
1258 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1259 assert!(result.is_err());
1260 if let Err(ParserError::ParseError(msg)) = result {
1261 assert!(msg.contains("BGP KEEPALIVE message length"));
1262 assert!(msg.contains("exceeds maximum allowed 4096 bytes"));
1263 }
1264 }
1265
1266 #[test]
1267 fn test_encode_bgp_open_message_with_extended_message_capability() {
1268 use crate::models::capabilities::BgpExtendedMessageCapability;
1269
1270 let extended_msg_capability = BgpExtendedMessageCapability::new();
1272
1273 let msg = BgpOpenMessage {
1274 version: 4,
1275 asn: Asn::new_16bit(65001),
1276 hold_time: 180,
1277 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
1278 extended_length: false,
1279 opt_params: vec![OptParam {
1280 param_type: 2, param_len: 2, param_value: ParamValue::Capacities(vec![Capability {
1283 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1284 value: CapabilityValue::BgpExtendedMessage(extended_msg_capability),
1285 }]),
1286 }],
1287 };
1288
1289 let encoded = msg.encode();
1290
1291 let parsed = parse_bgp_open_message(&mut encoded.clone()).unwrap();
1293 assert_eq!(parsed.version, msg.version);
1294 assert_eq!(parsed.asn, msg.asn);
1295 assert_eq!(parsed.hold_time, msg.hold_time);
1296 assert_eq!(parsed.bgp_identifier, msg.bgp_identifier);
1297 assert_eq!(parsed.opt_params.len(), 1);
1298
1299 if let ParamValue::Capacities(cap) = &parsed.opt_params[0].param_value {
1301 assert_eq!(cap[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1302 if let CapabilityValue::BgpExtendedMessage(_) = &cap[0].value {
1303 } else {
1305 panic!("Expected BgpExtendedMessage capability value after round trip");
1306 }
1307 } else {
1308 panic!("Expected capability parameter after round trip");
1309 }
1310 }
1311
1312 #[test]
1313 fn test_encode_bgp_open_message_with_extended_next_hop_capability() {
1314 use crate::models::capabilities::{ExtendedNextHopCapability, ExtendedNextHopEntry};
1315 use crate::models::{Afi, Safi};
1316
1317 let entries = vec![
1319 ExtendedNextHopEntry {
1320 nlri_afi: Afi::Ipv4,
1321 nlri_safi: Safi::Unicast,
1322 nexthop_afi: Afi::Ipv6,
1323 },
1324 ExtendedNextHopEntry {
1325 nlri_afi: Afi::Ipv4,
1326 nlri_safi: Safi::MplsVpn,
1327 nexthop_afi: Afi::Ipv6,
1328 },
1329 ];
1330 let enh_capability = ExtendedNextHopCapability::new(entries);
1331
1332 let msg = BgpOpenMessage {
1333 version: 4,
1334 asn: Asn::new_16bit(65001),
1335 hold_time: 180,
1336 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
1337 extended_length: false,
1338 opt_params: vec![OptParam {
1339 param_type: 2, param_len: 14, param_value: ParamValue::Capacities(vec![Capability {
1342 ty: BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING,
1343 value: CapabilityValue::ExtendedNextHop(enh_capability),
1344 }]),
1345 }],
1346 };
1347
1348 let encoded = msg.encode();
1349
1350 let parsed = parse_bgp_open_message(&mut encoded.clone()).unwrap();
1352 assert_eq!(parsed.version, msg.version);
1353 assert_eq!(parsed.asn, msg.asn);
1354 assert_eq!(parsed.hold_time, msg.hold_time);
1355 assert_eq!(parsed.bgp_identifier, msg.bgp_identifier);
1356 assert_eq!(parsed.extended_length, msg.extended_length);
1357 assert_eq!(parsed.opt_params.len(), 1);
1358
1359 if let ParamValue::Capacities(cap) = &parsed.opt_params[0].param_value {
1361 assert_eq!(cap[0].ty, BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING);
1362 if let CapabilityValue::ExtendedNextHop(enh_cap) = &cap[0].value {
1363 assert_eq!(enh_cap.entries.len(), 2);
1364 assert!(enh_cap.supports(Afi::Ipv4, Safi::Unicast, Afi::Ipv6));
1365 assert!(enh_cap.supports(Afi::Ipv4, Safi::MplsVpn, Afi::Ipv6));
1366 } else {
1367 panic!("Expected ExtendedNextHop capability value after round trip");
1368 }
1369 } else {
1370 panic!("Expected capability parameter after round trip");
1371 }
1372 }
1373
1374 #[test]
1375 fn test_parse_bgp_open_message_with_multiple_capabilities() {
1376 let extended_msg_cap = Capability {
1381 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1382 value: CapabilityValue::BgpExtendedMessage(BgpExtendedMessageCapability {}),
1383 };
1384
1385 let route_refresh_cap = Capability {
1386 ty: BgpCapabilityType::ROUTE_REFRESH_CAPABILITY_FOR_BGP_4,
1387 value: CapabilityValue::RouteRefresh(RouteRefreshCapability {}),
1388 };
1389
1390 let four_octet_as_cap = Capability {
1391 ty: BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY,
1392 value: CapabilityValue::FourOctetAs(FourOctetAsCapability { asn: 65536 }),
1393 };
1394
1395 let msg = BgpOpenMessage {
1397 version: 4,
1398 asn: Asn::new_32bit(65000),
1399 hold_time: 180,
1400 bgp_identifier: "10.0.0.1".parse().unwrap(),
1401 extended_length: false,
1402 opt_params: vec![OptParam {
1403 param_type: 2, param_len: 10, param_value: ParamValue::Capacities(vec![
1406 extended_msg_cap,
1407 route_refresh_cap,
1408 four_octet_as_cap,
1409 ]),
1410 }],
1411 };
1412
1413 let encoded = msg.encode();
1415
1416 let mut encoded_bytes = encoded.clone();
1418 let parsed = parse_bgp_open_message(&mut encoded_bytes).unwrap();
1419
1420 assert_eq!(parsed.version, 4);
1422 assert_eq!(parsed.asn, Asn::new_32bit(65000));
1423 assert_eq!(parsed.hold_time, 180);
1424 assert_eq!(
1425 parsed.bgp_identifier,
1426 "10.0.0.1".parse::<std::net::Ipv4Addr>().unwrap()
1427 );
1428 assert_eq!(parsed.opt_params.len(), 1);
1429
1430 if let ParamValue::Capacities(caps) = &parsed.opt_params[0].param_value {
1432 assert_eq!(caps.len(), 3, "Should have 3 capabilities");
1433
1434 assert_eq!(caps[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1436 assert!(matches!(
1437 caps[0].value,
1438 CapabilityValue::BgpExtendedMessage(_)
1439 ));
1440
1441 assert_eq!(
1443 caps[1].ty,
1444 BgpCapabilityType::ROUTE_REFRESH_CAPABILITY_FOR_BGP_4
1445 );
1446 assert!(matches!(caps[1].value, CapabilityValue::RouteRefresh(_)));
1447
1448 assert_eq!(
1450 caps[2].ty,
1451 BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY
1452 );
1453 if let CapabilityValue::FourOctetAs(foa) = &caps[2].value {
1454 assert_eq!(foa.asn, 65536);
1455 } else {
1456 panic!("Expected FourOctetAs capability value");
1457 }
1458 } else {
1459 panic!("Expected Capacities parameter");
1460 }
1461 }
1462
1463 #[test]
1464 fn test_parse_bgp_open_message_with_multiple_capability_parameters() {
1465 let msg = BgpOpenMessage {
1469 version: 4,
1470 asn: Asn::new_32bit(65001),
1471 hold_time: 90,
1472 bgp_identifier: "192.168.1.1".parse().unwrap(),
1473 extended_length: false,
1474 opt_params: vec![
1475 OptParam {
1476 param_type: 2, param_len: 2,
1478 param_value: ParamValue::Capacities(vec![Capability {
1479 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1480 value: CapabilityValue::BgpExtendedMessage(BgpExtendedMessageCapability {}),
1481 }]),
1482 },
1483 OptParam {
1484 param_type: 2, param_len: 6,
1486 param_value: ParamValue::Capacities(vec![Capability {
1487 ty: BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY,
1488 value: CapabilityValue::FourOctetAs(FourOctetAsCapability {
1489 asn: 4200000000,
1490 }),
1491 }]),
1492 },
1493 ],
1494 };
1495
1496 let encoded = msg.encode();
1498 let mut encoded_bytes = encoded.clone();
1499 let parsed = parse_bgp_open_message(&mut encoded_bytes).unwrap();
1500
1501 assert_eq!(parsed.opt_params.len(), 2);
1503
1504 if let ParamValue::Capacities(caps) = &parsed.opt_params[0].param_value {
1506 assert_eq!(caps.len(), 1);
1507 assert_eq!(caps[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1508 } else {
1509 panic!("Expected Capacities in first parameter");
1510 }
1511
1512 if let ParamValue::Capacities(caps) = &parsed.opt_params[1].param_value {
1514 assert_eq!(caps.len(), 1);
1515 assert_eq!(
1516 caps[0].ty,
1517 BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY
1518 );
1519 if let CapabilityValue::FourOctetAs(foa) = &caps[0].value {
1520 assert_eq!(foa.asn, 4200000000);
1521 }
1522 } else {
1523 panic!("Expected Capacities in second parameter");
1524 }
1525 }
1526}