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(crate) fn read_and_validate_bgp_marker(data: &mut Bytes) -> Result<(), ParserError> {
33 data.has_n_remaining(16)?;
34
35 let mut marker = [0u8; 16];
36 data.copy_to_slice(&mut marker);
37 if marker != [0xFF; 16] {
38 warn!("BGP message marker is not all 0xFF bytes (invalid per RFC 4271)");
39 }
40
41 Ok(())
42}
43
44pub fn parse_bgp_message(
63 data: &mut Bytes,
64 add_path: bool,
65 asn_len: &AsnLength,
66) -> Result<BgpMessage, ParserError> {
67 let total_size = data.len();
68 data.has_n_remaining(19)?;
69 read_and_validate_bgp_marker(data)?;
70
71 let length = data.read_u16()?;
83
84 let max_length = 65535; if !(19..=max_length).contains(&length) {
92 return Err(ParserError::ParseError(format!(
93 "invalid BGP message length {length}"
94 )));
95 }
96
97 let length_usize = length as usize;
99 let bgp_msg_length = if length_usize > total_size {
100 total_size.saturating_sub(19)
101 } else {
102 length_usize.saturating_sub(19)
103 };
104
105 let msg_type: BgpMessageType = match BgpMessageType::try_from(data.read_u8()?) {
106 Ok(t) => t,
107 Err(_) => {
108 return Err(ParserError::ParseError(
109 "Unknown BGP Message Type".to_string(),
110 ))
111 }
112 };
113
114 match msg_type {
117 BgpMessageType::OPEN | BgpMessageType::KEEPALIVE => {
118 if length > 4096 {
119 return Err(ParserError::ParseError(format!(
120 "BGP {} message length {} exceeds maximum allowed 4096 bytes (RFC 8654)",
121 match msg_type {
122 BgpMessageType::OPEN => "OPEN",
123 BgpMessageType::KEEPALIVE => "KEEPALIVE",
124 _ => unreachable!(),
125 },
126 length
127 )));
128 }
129 }
130 BgpMessageType::UPDATE | BgpMessageType::NOTIFICATION => {
131 }
134 }
135
136 if data.remaining() != bgp_msg_length {
137 warn!(
138 "BGP message length {} does not match the actual length {} (parsing BGP message)",
139 bgp_msg_length,
140 data.remaining()
141 );
142 }
143 data.has_n_remaining(bgp_msg_length)?;
144 let mut msg_data = data.split_to(bgp_msg_length);
145
146 Ok(match msg_type {
147 BgpMessageType::OPEN => BgpMessage::Open(parse_bgp_open_message(&mut msg_data)?),
148 BgpMessageType::UPDATE => {
149 BgpMessage::Update(parse_bgp_update_message(msg_data, add_path, asn_len)?)
150 }
151 BgpMessageType::NOTIFICATION => {
152 BgpMessage::Notification(parse_bgp_notification_message(msg_data)?)
153 }
154 BgpMessageType::KEEPALIVE => BgpMessage::KeepAlive,
155 })
156}
157
158pub fn parse_bgp_notification_message(
165 mut input: Bytes,
166) -> Result<BgpNotificationMessage, ParserError> {
167 let error_code = input.read_u8()?;
168 let error_subcode = input.read_u8()?;
169
170 Ok(BgpNotificationMessage {
171 error: BgpError::new(error_code, error_subcode),
172 data: input.read_n_bytes(input.len())?,
173 })
174}
175
176impl BgpNotificationMessage {
177 pub fn encode(&self) -> Bytes {
178 let mut buf = BytesMut::new();
179 let (code, subcode) = self.error.get_codes();
180 buf.put_u8(code);
181 buf.put_u8(subcode);
182 buf.put_slice(&self.data);
183 buf.freeze()
184 }
185}
186
187pub fn parse_bgp_open_message(input: &mut Bytes) -> Result<BgpOpenMessage, ParserError> {
218 input.has_n_remaining(10)?;
219 let mut header_bytes = [0u8; 10];
220 input.copy_to_slice(&mut header_bytes);
221 let raw = RawBgpOpenHeader::ref_from_bytes(&header_bytes)
223 .expect("header_bytes is exactly 10 bytes with no alignment requirement");
224
225 let version = raw.version;
226 let asn = Asn::new_16bit(raw.asn.get());
227 let hold_time = raw.hold_time.get();
228 let bgp_identifier = Ipv4Addr::from(raw.bgp_identifier.get());
229 let mut opt_params_len: u16 = raw.opt_params_len as u16;
230
231 let mut extended_length = false;
232 let mut first = true;
233
234 let mut params: Vec<OptParam> = vec![];
235 while input.remaining() >= 2 {
236 let mut param_type = input.read_u8()?;
237 if first {
238 if opt_params_len == 0 && param_type == 255 {
239 return Err(ParserError::ParseError(
240 "RFC 9072 violation: Non-Extended Optional Parameters Length must not be 0 when using extended format".to_string()
241 ));
242 }
243 if opt_params_len != 0 && param_type == 255 {
245 extended_length = true;
267 opt_params_len = input.read_u16()?;
268 if opt_params_len == 0 {
269 break;
270 }
271 if input.remaining() != opt_params_len as usize {
273 warn!(
274 "BGP open message length {} does not match the actual length {} (parsing BGP OPEN message)",
275 opt_params_len,
276 input.remaining()
277 );
278 }
279
280 param_type = input.read_u8()?;
281 }
282 first = false;
283 }
284 let param_len = match extended_length {
287 true => input.read_u16()?,
288 false => input.read_u8()? as u16,
289 };
290
291 let param_value = match param_type {
295 2 => {
296 let mut capacities = vec![];
297
298 input.has_n_remaining(param_len as usize)?;
300 let mut param_data = input.split_to(param_len as usize);
301
302 while param_data.remaining() >= 2 {
303 let code = param_data.read_u8()?;
306 let len = param_data.read_u8()? as u16; let capability_data = param_data.read_n_bytes(len as usize)?;
309 let capability_type = BgpCapabilityType::from(code);
310
311 macro_rules! parse_capability {
313 ($parser:path, $variant:ident) => {
314 match $parser(Bytes::from(capability_data.clone())) {
315 Ok(parsed) => CapabilityValue::$variant(parsed),
316 Err(_) => CapabilityValue::Raw(capability_data),
317 }
318 };
319 }
320
321 let capability_value = match capability_type {
322 BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4 => {
323 parse_capability!(
324 MultiprotocolExtensionsCapability::parse,
325 MultiprotocolExtensions
326 )
327 }
328 BgpCapabilityType::ROUTE_REFRESH_CAPABILITY_FOR_BGP_4 => {
329 parse_capability!(RouteRefreshCapability::parse, RouteRefresh)
330 }
331 BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING => {
332 parse_capability!(ExtendedNextHopCapability::parse, ExtendedNextHop)
333 }
334 BgpCapabilityType::GRACEFUL_RESTART_CAPABILITY => {
335 parse_capability!(GracefulRestartCapability::parse, GracefulRestart)
336 }
337 BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY => {
338 parse_capability!(FourOctetAsCapability::parse, FourOctetAs)
339 }
340 BgpCapabilityType::ADD_PATH_CAPABILITY => {
341 parse_capability!(AddPathCapability::parse, AddPath)
342 }
343 BgpCapabilityType::BGP_ROLE => {
344 parse_capability!(BgpRoleCapability::parse, BgpRole)
345 }
346 BgpCapabilityType::BGP_EXTENDED_MESSAGE => {
347 parse_capability!(
348 BgpExtendedMessageCapability::parse,
349 BgpExtendedMessage
350 )
351 }
352 _ => CapabilityValue::Raw(capability_data),
353 };
354
355 capacities.push(Capability {
356 ty: capability_type,
357 value: capability_value,
358 });
359 }
360
361 ParamValue::Capacities(capacities)
362 }
363 _ => {
364 let bytes = input.read_n_bytes(param_len as usize)?;
366 ParamValue::Raw(bytes)
367 }
368 };
369 params.push(OptParam {
370 param_type,
371 param_len,
372 param_value,
373 });
374 }
375
376 Ok(BgpOpenMessage {
377 version,
378 asn,
379 hold_time,
380 bgp_identifier,
381 extended_length,
382 opt_params: params,
383 })
384}
385
386impl BgpOpenMessage {
387 pub fn encode(&self) -> Bytes {
388 let mut buf = BytesMut::new();
389 let raw_header = RawBgpOpenHeader {
390 version: self.version,
391 asn: U16::new(self.asn.into()),
392 hold_time: U16::new(self.hold_time),
393 bgp_identifier: U32::new(u32::from(self.bgp_identifier)),
394 opt_params_len: self.opt_params.len() as u8,
395 };
396 buf.extend_from_slice(raw_header.as_bytes());
397 for param in &self.opt_params {
398 buf.put_u8(param.param_type);
399 buf.put_u8(param.param_len as u8);
400 match ¶m.param_value {
401 ParamValue::Capacities(capacities) => {
402 for cap in capacities {
403 buf.put_u8(cap.ty.into());
404 let encoded_value = match &cap.value {
405 CapabilityValue::MultiprotocolExtensions(mp) => mp.encode(),
406 CapabilityValue::RouteRefresh(rr) => rr.encode(),
407 CapabilityValue::ExtendedNextHop(enh) => enh.encode(),
408 CapabilityValue::GracefulRestart(gr) => gr.encode(),
409 CapabilityValue::FourOctetAs(foa) => foa.encode(),
410 CapabilityValue::AddPath(ap) => ap.encode(),
411 CapabilityValue::BgpRole(br) => br.encode(),
412 CapabilityValue::BgpExtendedMessage(bem) => bem.encode(),
413 CapabilityValue::Raw(raw) => Bytes::from(raw.clone()),
414 };
415 buf.put_u8(encoded_value.len() as u8);
416 buf.extend(&encoded_value);
417 }
418 }
419 ParamValue::Raw(bytes) => {
420 buf.extend(bytes);
421 }
422 }
423 }
424 buf.freeze()
425 }
426}
427
428fn read_nlri(
430 mut input: Bytes,
431 afi: &Afi,
432 add_path: bool,
433) -> Result<Vec<NetworkPrefix>, ParserError> {
434 let length = input.len();
435 if length == 0 {
436 return Ok(vec![]);
437 }
438 if length == 1 {
439 warn!("seeing strange one-byte NLRI field (parsing NLRI in BGP UPDATE message)");
441 input.advance(1); return Ok(vec![]);
443 }
444
445 parse_nlri_list(input, add_path, afi)
446}
447
448pub fn parse_bgp_update_message(
452 mut input: Bytes,
453 add_path: bool,
454 asn_len: &AsnLength,
455) -> Result<BgpUpdateMessage, ParserError> {
456 let afi = Afi::Ipv4;
458
459 let withdrawn_bytes_length_raw = input.read_u16()?;
461 let withdrawn_bytes_length = withdrawn_bytes_length_raw as usize;
462 input.has_n_remaining(withdrawn_bytes_length)?;
463 let withdrawn_bytes = input.split_to(withdrawn_bytes_length);
464 let withdrawn_prefixes = read_nlri(withdrawn_bytes, &afi, add_path)?;
465
466 let attribute_length_raw = input.read_u16()?;
468 let attribute_length = attribute_length_raw as usize;
472
473 input.has_n_remaining(attribute_length)?;
474 let attr_data_slice = input.split_to(attribute_length);
475 let mut attributes = parse_attributes(attr_data_slice, asn_len, add_path, None, None, None)?;
476
477 let announced_prefixes = read_nlri(input, &afi, add_path)?;
480
481 let is_announcement =
483 !announced_prefixes.is_empty() || attributes.has_attr(AttrType::MP_REACHABLE_NLRI);
484 let has_standard_nlri = !announced_prefixes.is_empty();
485 attributes.check_mandatory_attributes(is_announcement, has_standard_nlri);
486
487 Ok(BgpUpdateMessage {
488 withdrawn_prefixes,
489 attributes,
490 announced_prefixes,
491 })
492}
493
494impl BgpUpdateMessage {
495 pub fn encode(&self, asn_len: AsnLength) -> Bytes {
496 let mut bytes = BytesMut::new();
497
498 let withdrawn_bytes = encode_nlri_prefixes(&self.withdrawn_prefixes);
500 bytes.put_u16(withdrawn_bytes.len() as u16);
501 bytes.put_slice(&withdrawn_bytes);
502
503 let attr_bytes = self.attributes.encode(asn_len);
505
506 bytes.put_u16(attr_bytes.len() as u16);
507 bytes.put_slice(&attr_bytes);
508
509 bytes.extend(encode_nlri_prefixes(&self.announced_prefixes));
510 bytes.freeze()
511 }
512
513 pub fn is_end_of_rib(&self) -> bool {
518 if !self.announced_prefixes.is_empty() || !self.withdrawn_prefixes.is_empty() {
523 return false;
527 }
528
529 if self.attributes.inner.is_empty() {
530 return true;
533 }
534
535 if self.attributes.inner.len() > 1 {
538 return false;
540 }
541
542 if let AttributeValue::MpUnreachNlri(nlri) = &self.attributes.inner.first().unwrap().value {
544 if nlri.prefixes.is_empty() {
545 return true;
548 }
549 }
550
551 false
553 }
554}
555
556impl BgpMessage {
557 const MARKER: [u8; 16] = [0xFF; 16];
559
560 pub fn encode(&self, asn_len: AsnLength) -> Bytes {
561 let mut bytes = BytesMut::new();
562 bytes.put_slice(&Self::MARKER);
564
565 let (msg_type, msg_bytes) = match self {
566 BgpMessage::Open(msg) => (BgpMessageType::OPEN, msg.encode()),
567 BgpMessage::Update(msg) => (BgpMessageType::UPDATE, msg.encode(asn_len)),
568 BgpMessage::Notification(msg) => (BgpMessageType::NOTIFICATION, msg.encode()),
569 BgpMessage::KeepAlive => (BgpMessageType::KEEPALIVE, Bytes::new()),
570 };
571
572 bytes.put_u16(msg_bytes.len() as u16 + 16 + 2 + 1);
574 bytes.put_u8(msg_type as u8);
575 bytes.put_slice(&msg_bytes);
576 bytes.freeze()
577 }
578}
579
580impl From<&BgpElem> for BgpUpdateMessage {
581 fn from(elem: &BgpElem) -> Self {
582 BgpUpdateMessage {
583 withdrawn_prefixes: vec![],
584 attributes: Attributes::from(elem),
585 announced_prefixes: vec![],
586 }
587 }
588}
589
590impl From<BgpUpdateMessage> for BgpMessage {
591 fn from(value: BgpUpdateMessage) -> Self {
592 BgpMessage::Update(value)
593 }
594}
595
596#[cfg(test)]
597mod tests {
598 use super::*;
599 use std::net::Ipv4Addr;
600 use std::str::FromStr;
601
602 #[test]
603 fn test_end_of_rib() {
604 let attrs = Attributes::default();
606 let msg = BgpUpdateMessage {
607 withdrawn_prefixes: vec![],
608 attributes: attrs,
609 announced_prefixes: vec![],
610 };
611 assert!(msg.is_end_of_rib());
612
613 let attrs = Attributes::from_iter(vec![AttributeValue::MpUnreachNlri(Nlri {
615 afi: Afi::Ipv4,
616 safi: Safi::Unicast,
617 next_hop: None,
618 prefixes: vec![],
619 labeled_prefixes: None,
620 link_state_nlris: None,
621 flowspec_nlris: None,
622 })]);
623 let msg = BgpUpdateMessage {
624 withdrawn_prefixes: vec![],
625 attributes: attrs,
626 announced_prefixes: vec![],
627 };
628 assert!(msg.is_end_of_rib());
629
630 let prefix = NetworkPrefix::from_str("192.168.1.0/24").unwrap();
632 let attrs = Attributes::default();
633 let msg = BgpUpdateMessage {
634 withdrawn_prefixes: vec![],
635 attributes: attrs,
636 announced_prefixes: vec![prefix],
637 };
638 assert!(!msg.is_end_of_rib());
639
640 let prefix = NetworkPrefix::from_str("192.168.1.0/24").unwrap();
642 let attrs = Attributes::default();
643 let msg = BgpUpdateMessage {
644 withdrawn_prefixes: vec![prefix],
645 attributes: attrs,
646 announced_prefixes: vec![],
647 };
648 assert!(!msg.is_end_of_rib());
649
650 let attrs = Attributes::from_iter(vec![AttributeValue::MpReachNlri(Nlri {
652 afi: Afi::Ipv4,
653 safi: Safi::Unicast,
654 next_hop: None,
655 prefixes: vec![],
656 labeled_prefixes: None,
657 link_state_nlris: None,
658 flowspec_nlris: None,
659 })]);
660 let msg = BgpUpdateMessage {
661 withdrawn_prefixes: vec![],
662 attributes: attrs,
663 announced_prefixes: vec![],
664 };
665 assert!(!msg.is_end_of_rib());
666
667 let attrs = Attributes::from_iter(vec![AttributeValue::MpReachNlri(Nlri {
669 afi: Afi::Ipv4,
670 safi: Safi::Unicast,
671 next_hop: None,
672 prefixes: vec![prefix],
673 labeled_prefixes: None,
674 link_state_nlris: None,
675 flowspec_nlris: None,
676 })]);
677 let msg = BgpUpdateMessage {
678 withdrawn_prefixes: vec![],
679 attributes: attrs,
680 announced_prefixes: vec![],
681 };
682 assert!(!msg.is_end_of_rib());
683
684 let attrs = Attributes::from_iter(vec![AttributeValue::MpUnreachNlri(Nlri {
686 afi: Afi::Ipv4,
687 safi: Safi::Unicast,
688 next_hop: None,
689 prefixes: vec![prefix],
690 labeled_prefixes: None,
691 link_state_nlris: None,
692 flowspec_nlris: None,
693 })]);
694 let msg = BgpUpdateMessage {
695 withdrawn_prefixes: vec![],
696 attributes: attrs,
697 announced_prefixes: vec![],
698 };
699 assert!(!msg.is_end_of_rib());
700
701 let attrs = Attributes::from_iter(vec![
703 AttributeValue::MpUnreachNlri(Nlri {
704 afi: Afi::Ipv4,
705 safi: Safi::Unicast,
706 next_hop: None,
707 prefixes: vec![],
708 labeled_prefixes: None,
709 link_state_nlris: None,
710 flowspec_nlris: None,
711 }),
712 AttributeValue::AtomicAggregate,
713 ]);
714 let msg = BgpUpdateMessage {
715 withdrawn_prefixes: vec![],
716 attributes: attrs,
717 announced_prefixes: vec![],
718 };
719 assert!(!msg.is_end_of_rib());
720 }
721
722 #[test]
723 fn test_invlaid_length() {
724 let bytes = Bytes::from_static(&[
725 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, ]);
732 let mut data = bytes.clone();
733 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_err());
734
735 let bytes = Bytes::from_static(&[
736 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x05, ]);
743 let mut data = bytes.clone();
744 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_err());
745 }
746
747 #[test]
748 fn test_invlaid_type() {
749 let bytes = Bytes::from_static(&[
750 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x28, 0x05, ]);
757 let mut data = bytes.clone();
758 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_err());
759 }
760
761 #[test]
762 fn test_bgp_message_length_underflow_protection() {
763 for len in [0u16, 1, 18] {
766 let bytes = Bytes::from(vec![
767 0xFF,
768 0xFF,
769 0xFF,
770 0xFF, 0xFF,
772 0xFF,
773 0xFF,
774 0xFF, 0xFF,
776 0xFF,
777 0xFF,
778 0xFF, 0xFF,
780 0xFF,
781 0xFF,
782 0xFF, (len >> 8) as u8,
784 (len & 0xFF) as u8, 0x01, ]);
787 let mut data = bytes.clone();
788 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
789 assert!(
790 result.is_err(),
791 "Length {} should be rejected as invalid",
792 len
793 );
794 }
795 }
796
797 #[test]
798 fn test_bgp_marker_encoding_rfc4271() {
799 let msg = BgpMessage::KeepAlive;
801 let encoded = msg.encode(AsnLength::Bits16);
802
803 assert_eq!(
805 &encoded[..16],
806 &[0xFF; 16],
807 "BGP marker should be all 0xFF bytes"
808 );
809 }
810
811 #[test]
812 fn test_bgp_marker_validation() {
813 let valid_bytes = Bytes::from(vec![
815 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x13, 0x04, ]);
822 let mut data = valid_bytes.clone();
823 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
824 assert!(result.is_ok(), "Valid marker should parse successfully");
825
826 let invalid_bytes = Bytes::from(vec![
829 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x04, ]);
836 let mut data = invalid_bytes.clone();
837 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
839 assert!(
840 result.is_ok(),
841 "Invalid marker should still parse (with warning)"
842 );
843 }
844
845 #[test]
846 fn test_attribute_length_overflow_protection() {
847 let update_bytes = Bytes::from(vec![
852 0x00, 0x00, 0xFF,
854 0xFF, ]);
857
858 let result = parse_bgp_update_message(update_bytes, false, &AsnLength::Bits16);
859 assert!(
860 result.is_err(),
861 "Should fail when attribute_length exceeds available data"
862 );
863 assert!(
864 matches!(result, Err(ParserError::TruncatedMsg(_))),
865 "Should fail with TruncatedMsg error"
866 );
867
868 let valid_update = Bytes::from(vec![
870 0x00, 0x00, 0x00,
872 0x00, ]);
875 let result = parse_bgp_update_message(valid_update, false, &AsnLength::Bits16);
876 assert!(result.is_ok(), "Should parse valid empty UPDATE");
877 }
878
879 #[test]
880 fn test_parse_bgp_notification_message() {
881 let bytes = Bytes::from_static(&[
882 0x01, 0x02, 0x00, 0x00, ]);
886 let msg = parse_bgp_notification_message(bytes).unwrap();
887 matches!(
888 msg.error,
889 BgpError::MessageHeaderError(MessageHeaderError::BAD_MESSAGE_LENGTH)
890 );
891 assert_eq!(msg.data, Bytes::from_static(&[0x00, 0x00]));
892 }
893
894 #[test]
895 fn test_encode_bgp_notification_messsage() {
896 let msg = BgpNotificationMessage {
897 error: BgpError::MessageHeaderError(MessageHeaderError::BAD_MESSAGE_LENGTH),
898 data: vec![0x00, 0x00],
899 };
900 let bytes = msg.encode();
901 assert_eq!(bytes, Bytes::from_static(&[0x01, 0x02, 0x00, 0x00]));
902 }
903
904 #[test]
905 fn test_parse_bgp_open_message() {
906 let bytes = Bytes::from_static(&[
907 0x04, 0x00, 0x01, 0x00, 0xb4, 0xc0, 0x00, 0x02, 0x01, 0x00, ]);
913 let msg = parse_bgp_open_message(&mut bytes.clone()).unwrap();
914 assert_eq!(msg.version, 4);
915 assert_eq!(msg.asn, Asn::new_16bit(1));
916 assert_eq!(msg.hold_time, 180);
917 assert_eq!(msg.bgp_identifier, Ipv4Addr::new(192, 0, 2, 1));
918 assert!(!msg.extended_length);
919 assert_eq!(msg.opt_params.len(), 0);
920 }
921
922 #[test]
923 fn test_encode_bgp_open_message() {
924 let msg = BgpOpenMessage {
925 version: 4,
926 asn: Asn::new_16bit(1),
927 hold_time: 180,
928 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
929 extended_length: false,
930 opt_params: vec![],
931 };
932 let bytes = msg.encode();
933 assert_eq!(
934 bytes,
935 Bytes::from_static(&[
936 0x04, 0x00, 0x01, 0x00, 0xb4, 0xc0, 0x00, 0x02, 0x01, 0x00, ])
942 );
943 }
944
945 #[test]
946 fn test_encode_bgp_notification_message() {
947 let bgp_message = BgpMessage::Notification(BgpNotificationMessage {
948 error: BgpError::MessageHeaderError(MessageHeaderError::BAD_MESSAGE_LENGTH),
949 data: vec![0x00, 0x00],
950 });
951 let bytes = bgp_message.encode(AsnLength::Bits16);
952 assert_eq!(
954 bytes,
955 Bytes::from_static(&[
956 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x17, 0x03, 0x01, 0x02, 0x00, 0x00 ])
963 );
964 }
965
966 #[test]
967 fn test_bgp_message_from_bgp_update_message() {
968 let msg = BgpMessage::from(BgpUpdateMessage::default());
969 assert!(matches!(msg, BgpMessage::Update(_)));
970 }
971
972 #[test]
973 fn test_parse_bgp_open_message_with_extended_next_hop_capability() {
974 use crate::models::{Afi, Safi};
975
976 let bytes = Bytes::from(vec![
982 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, ]);
998
999 let msg = parse_bgp_open_message(&mut bytes.clone()).unwrap();
1000 assert_eq!(msg.version, 4);
1001 assert_eq!(msg.asn, Asn::new_16bit(65001));
1002 assert_eq!(msg.hold_time, 180);
1003 assert_eq!(msg.bgp_identifier, Ipv4Addr::new(192, 0, 2, 1));
1004 assert!(!msg.extended_length);
1005 assert_eq!(msg.opt_params.len(), 1);
1006
1007 if let ParamValue::Capacities(cap) = &msg.opt_params[0].param_value {
1009 assert_eq!(cap[0].ty, BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING);
1010
1011 if let CapabilityValue::ExtendedNextHop(enh_cap) = &cap[0].value {
1012 assert_eq!(enh_cap.entries.len(), 2);
1013
1014 let entry1 = &enh_cap.entries[0];
1016 assert_eq!(entry1.nlri_afi, Afi::Ipv4);
1017 assert_eq!(entry1.nlri_safi, Safi::Unicast);
1018 assert_eq!(entry1.nexthop_afi, Afi::Ipv6);
1019
1020 let entry2 = &enh_cap.entries[1];
1022 assert_eq!(entry2.nlri_afi, Afi::Ipv4);
1023 assert_eq!(entry2.nlri_safi, Safi::MplsVpn);
1024 assert_eq!(entry2.nexthop_afi, Afi::Ipv6);
1025
1026 assert!(enh_cap.supports(Afi::Ipv4, Safi::Unicast, Afi::Ipv6));
1028 assert!(enh_cap.supports(Afi::Ipv4, Safi::MplsVpn, Afi::Ipv6));
1029 assert!(!enh_cap.supports(Afi::Ipv4, Safi::Multicast, Afi::Ipv6));
1030 } else {
1031 panic!("Expected ExtendedNextHop capability value");
1032 }
1033 } else {
1034 panic!("Expected capability parameter");
1035 }
1036 }
1037
1038 #[test]
1039 fn test_rfc8654_extended_message_length_validation() {
1040 let bytes = Bytes::from_static(&[
1042 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x00, 0x00,
1050 0x00, ]);
1053 let mut data = bytes.clone();
1054 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_ok());
1056
1057 let bytes = Bytes::from_static(&[
1059 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x01, ]);
1066 let mut data = bytes.clone();
1067 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1068 assert!(result.is_err());
1069 if let Err(ParserError::ParseError(msg)) = result {
1070 assert!(msg.contains("BGP OPEN message length"));
1071 assert!(msg.contains("4096 bytes"));
1072 }
1073
1074 let bytes = Bytes::from_static(&[
1076 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x04, ]);
1083 let mut data = bytes.clone();
1084 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1085 assert!(result.is_err());
1086 if let Err(ParserError::ParseError(msg)) = result {
1087 assert!(msg.contains("BGP KEEPALIVE message length"));
1088 assert!(msg.contains("4096 bytes"));
1089 }
1090
1091 let bytes = Bytes::from_static(&[
1093 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x02, ]);
1100 let mut data = bytes.clone();
1101 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1103 if let Err(ParserError::ParseError(msg)) = result {
1104 assert!(!msg.contains("invalid BGP message length"));
1106 }
1107 }
1108
1109 #[test]
1110 fn test_bgp_extended_message_capability_parsing() {
1111 use crate::models::CapabilityValue;
1112
1113 let bytes = Bytes::from(vec![
1115 0x04, 0x00, 0x01, 0x00, 0xb4, 0xc0, 0x00, 0x02, 0x01, 0x04, 0x02, 0x02, 0x06, 0x00, ]);
1125
1126 let msg = parse_bgp_open_message(&mut bytes.clone()).unwrap();
1127 assert_eq!(msg.version, 4);
1128 assert_eq!(msg.asn, Asn::new_16bit(1));
1129 assert_eq!(msg.opt_params.len(), 1);
1130
1131 if let ParamValue::Capacities(cap) = &msg.opt_params[0].param_value {
1133 assert_eq!(cap[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1134 if let CapabilityValue::BgpExtendedMessage(_) = &cap[0].value {
1135 } else {
1137 panic!("Expected BgpExtendedMessage capability value");
1138 }
1139 } else {
1140 panic!("Expected capability parameter");
1141 }
1142 }
1143
1144 #[test]
1145 fn test_rfc8654_edge_cases() {
1146 let bytes = Bytes::from_static(&[
1148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x03, 0x06, 0x00, ]);
1158 let mut data = bytes.clone();
1159 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1161 if let Err(ParserError::ParseError(msg)) = result {
1163 assert!(!msg.contains("invalid BGP message length"));
1164 assert!(!msg.contains("exceeds maximum allowed 4096 bytes"));
1165 }
1166
1167 let open_data = vec![
1169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, ];
1176 let bytes = Bytes::from(open_data);
1177 let mut data = bytes.clone();
1178 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1179 if let Err(ParserError::ParseError(msg)) = result {
1181 assert!(!msg.contains("exceeds maximum allowed 4096 bytes"));
1182 }
1183
1184 let bytes = Bytes::from_static(&[
1186 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x02, ]);
1193 let mut data = bytes.clone();
1194 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1195 if let Err(ParserError::ParseError(msg)) = result {
1197 assert!(!msg.contains("invalid BGP message length"));
1198 }
1199 }
1200
1201 #[test]
1202 fn test_rfc8654_capability_encoding_path() {
1203 use crate::models::capabilities::BgpExtendedMessageCapability;
1204
1205 let capability_value =
1208 CapabilityValue::BgpExtendedMessage(BgpExtendedMessageCapability::new());
1209 let capability = Capability {
1210 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1211 value: capability_value,
1212 };
1213
1214 let opt_param = OptParam {
1215 param_type: 2, param_len: 2,
1217 param_value: ParamValue::Capacities(vec![capability]),
1218 };
1219
1220 let msg = BgpOpenMessage {
1221 version: 4,
1222 asn: Asn::new_16bit(65001),
1223 hold_time: 180,
1224 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
1225 extended_length: false,
1226 opt_params: vec![opt_param],
1227 };
1228
1229 let encoded = msg.encode();
1231 assert!(!encoded.is_empty());
1232
1233 let parsed = parse_bgp_open_message(&mut encoded.clone()).unwrap();
1235 assert_eq!(parsed.opt_params.len(), 1);
1236 if let ParamValue::Capacities(cap) = &parsed.opt_params[0].param_value {
1237 assert_eq!(cap[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1238 }
1239 }
1240
1241 #[test]
1242 fn test_rfc8654_error_message_formatting() {
1243 let bytes = Bytes::from_static(&[
1248 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x01, ]);
1255 let mut data = bytes.clone();
1256 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1257 assert!(result.is_err());
1258 if let Err(ParserError::ParseError(msg)) = result {
1259 assert!(msg.contains("BGP OPEN message length"));
1260 assert!(msg.contains("exceeds maximum allowed 4096 bytes"));
1261 }
1262
1263 let bytes = Bytes::from_static(&[
1265 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x04, ]);
1272 let mut data = bytes.clone();
1273 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1274 assert!(result.is_err());
1275 if let Err(ParserError::ParseError(msg)) = result {
1276 assert!(msg.contains("BGP KEEPALIVE message length"));
1277 assert!(msg.contains("exceeds maximum allowed 4096 bytes"));
1278 }
1279 }
1280
1281 #[test]
1282 fn test_encode_bgp_open_message_with_extended_message_capability() {
1283 use crate::models::capabilities::BgpExtendedMessageCapability;
1284
1285 let extended_msg_capability = BgpExtendedMessageCapability::new();
1287
1288 let msg = BgpOpenMessage {
1289 version: 4,
1290 asn: Asn::new_16bit(65001),
1291 hold_time: 180,
1292 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
1293 extended_length: false,
1294 opt_params: vec![OptParam {
1295 param_type: 2, param_len: 2, param_value: ParamValue::Capacities(vec![Capability {
1298 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1299 value: CapabilityValue::BgpExtendedMessage(extended_msg_capability),
1300 }]),
1301 }],
1302 };
1303
1304 let encoded = msg.encode();
1305
1306 let parsed = parse_bgp_open_message(&mut encoded.clone()).unwrap();
1308 assert_eq!(parsed.version, msg.version);
1309 assert_eq!(parsed.asn, msg.asn);
1310 assert_eq!(parsed.hold_time, msg.hold_time);
1311 assert_eq!(parsed.bgp_identifier, msg.bgp_identifier);
1312 assert_eq!(parsed.opt_params.len(), 1);
1313
1314 if let ParamValue::Capacities(cap) = &parsed.opt_params[0].param_value {
1316 assert_eq!(cap[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1317 if let CapabilityValue::BgpExtendedMessage(_) = &cap[0].value {
1318 } else {
1320 panic!("Expected BgpExtendedMessage capability value after round trip");
1321 }
1322 } else {
1323 panic!("Expected capability parameter after round trip");
1324 }
1325 }
1326
1327 #[test]
1328 fn test_encode_bgp_open_message_with_extended_next_hop_capability() {
1329 use crate::models::capabilities::{ExtendedNextHopCapability, ExtendedNextHopEntry};
1330 use crate::models::{Afi, Safi};
1331
1332 let entries = vec![
1334 ExtendedNextHopEntry {
1335 nlri_afi: Afi::Ipv4,
1336 nlri_safi: Safi::Unicast,
1337 nexthop_afi: Afi::Ipv6,
1338 },
1339 ExtendedNextHopEntry {
1340 nlri_afi: Afi::Ipv4,
1341 nlri_safi: Safi::MplsVpn,
1342 nexthop_afi: Afi::Ipv6,
1343 },
1344 ];
1345 let enh_capability = ExtendedNextHopCapability::new(entries);
1346
1347 let msg = BgpOpenMessage {
1348 version: 4,
1349 asn: Asn::new_16bit(65001),
1350 hold_time: 180,
1351 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
1352 extended_length: false,
1353 opt_params: vec![OptParam {
1354 param_type: 2, param_len: 14, param_value: ParamValue::Capacities(vec![Capability {
1357 ty: BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING,
1358 value: CapabilityValue::ExtendedNextHop(enh_capability),
1359 }]),
1360 }],
1361 };
1362
1363 let encoded = msg.encode();
1364
1365 let parsed = parse_bgp_open_message(&mut encoded.clone()).unwrap();
1367 assert_eq!(parsed.version, msg.version);
1368 assert_eq!(parsed.asn, msg.asn);
1369 assert_eq!(parsed.hold_time, msg.hold_time);
1370 assert_eq!(parsed.bgp_identifier, msg.bgp_identifier);
1371 assert_eq!(parsed.extended_length, msg.extended_length);
1372 assert_eq!(parsed.opt_params.len(), 1);
1373
1374 if let ParamValue::Capacities(cap) = &parsed.opt_params[0].param_value {
1376 assert_eq!(cap[0].ty, BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING);
1377 if let CapabilityValue::ExtendedNextHop(enh_cap) = &cap[0].value {
1378 assert_eq!(enh_cap.entries.len(), 2);
1379 assert!(enh_cap.supports(Afi::Ipv4, Safi::Unicast, Afi::Ipv6));
1380 assert!(enh_cap.supports(Afi::Ipv4, Safi::MplsVpn, Afi::Ipv6));
1381 } else {
1382 panic!("Expected ExtendedNextHop capability value after round trip");
1383 }
1384 } else {
1385 panic!("Expected capability parameter after round trip");
1386 }
1387 }
1388
1389 #[test]
1390 fn test_parse_bgp_open_message_with_multiple_capabilities() {
1391 let extended_msg_cap = Capability {
1396 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1397 value: CapabilityValue::BgpExtendedMessage(BgpExtendedMessageCapability {}),
1398 };
1399
1400 let route_refresh_cap = Capability {
1401 ty: BgpCapabilityType::ROUTE_REFRESH_CAPABILITY_FOR_BGP_4,
1402 value: CapabilityValue::RouteRefresh(RouteRefreshCapability {}),
1403 };
1404
1405 let four_octet_as_cap = Capability {
1406 ty: BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY,
1407 value: CapabilityValue::FourOctetAs(FourOctetAsCapability { asn: 65536 }),
1408 };
1409
1410 let msg = BgpOpenMessage {
1412 version: 4,
1413 asn: Asn::new_32bit(65000),
1414 hold_time: 180,
1415 bgp_identifier: "10.0.0.1".parse().unwrap(),
1416 extended_length: false,
1417 opt_params: vec![OptParam {
1418 param_type: 2, param_len: 10, param_value: ParamValue::Capacities(vec![
1421 extended_msg_cap,
1422 route_refresh_cap,
1423 four_octet_as_cap,
1424 ]),
1425 }],
1426 };
1427
1428 let encoded = msg.encode();
1430
1431 let mut encoded_bytes = encoded.clone();
1433 let parsed = parse_bgp_open_message(&mut encoded_bytes).unwrap();
1434
1435 assert_eq!(parsed.version, 4);
1437 assert_eq!(parsed.asn, Asn::new_32bit(65000));
1438 assert_eq!(parsed.hold_time, 180);
1439 assert_eq!(
1440 parsed.bgp_identifier,
1441 "10.0.0.1".parse::<std::net::Ipv4Addr>().unwrap()
1442 );
1443 assert_eq!(parsed.opt_params.len(), 1);
1444
1445 if let ParamValue::Capacities(caps) = &parsed.opt_params[0].param_value {
1447 assert_eq!(caps.len(), 3, "Should have 3 capabilities");
1448
1449 assert_eq!(caps[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1451 assert!(matches!(
1452 caps[0].value,
1453 CapabilityValue::BgpExtendedMessage(_)
1454 ));
1455
1456 assert_eq!(
1458 caps[1].ty,
1459 BgpCapabilityType::ROUTE_REFRESH_CAPABILITY_FOR_BGP_4
1460 );
1461 assert!(matches!(caps[1].value, CapabilityValue::RouteRefresh(_)));
1462
1463 assert_eq!(
1465 caps[2].ty,
1466 BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY
1467 );
1468 if let CapabilityValue::FourOctetAs(foa) = &caps[2].value {
1469 assert_eq!(foa.asn, 65536);
1470 } else {
1471 panic!("Expected FourOctetAs capability value");
1472 }
1473 } else {
1474 panic!("Expected Capacities parameter");
1475 }
1476 }
1477
1478 #[test]
1479 fn test_parse_bgp_open_message_with_multiple_capability_parameters() {
1480 let msg = BgpOpenMessage {
1484 version: 4,
1485 asn: Asn::new_32bit(65001),
1486 hold_time: 90,
1487 bgp_identifier: "192.168.1.1".parse().unwrap(),
1488 extended_length: false,
1489 opt_params: vec![
1490 OptParam {
1491 param_type: 2, param_len: 2,
1493 param_value: ParamValue::Capacities(vec![Capability {
1494 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1495 value: CapabilityValue::BgpExtendedMessage(BgpExtendedMessageCapability {}),
1496 }]),
1497 },
1498 OptParam {
1499 param_type: 2, param_len: 6,
1501 param_value: ParamValue::Capacities(vec![Capability {
1502 ty: BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY,
1503 value: CapabilityValue::FourOctetAs(FourOctetAsCapability {
1504 asn: 4200000000,
1505 }),
1506 }]),
1507 },
1508 ],
1509 };
1510
1511 let encoded = msg.encode();
1513 let mut encoded_bytes = encoded.clone();
1514 let parsed = parse_bgp_open_message(&mut encoded_bytes).unwrap();
1515
1516 assert_eq!(parsed.opt_params.len(), 2);
1518
1519 if let ParamValue::Capacities(caps) = &parsed.opt_params[0].param_value {
1521 assert_eq!(caps.len(), 1);
1522 assert_eq!(caps[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1523 } else {
1524 panic!("Expected Capacities in first parameter");
1525 }
1526
1527 if let ParamValue::Capacities(caps) = &parsed.opt_params[1].param_value {
1529 assert_eq!(caps.len(), 1);
1530 assert_eq!(
1531 caps[0].ty,
1532 BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY
1533 );
1534 if let CapabilityValue::FourOctetAs(foa) = &caps[0].value {
1535 assert_eq!(foa.asn, 4200000000);
1536 }
1537 } else {
1538 panic!("Expected Capacities in second parameter");
1539 }
1540 }
1541}