1use crate::models::*;
2use bytes::{Buf, BufMut, Bytes, BytesMut};
3use std::convert::TryFrom;
4use std::net::Ipv4Addr;
5
6use crate::encoder::sink::{put_u16_len_slice, put_u8_len_slice, with_u16_len};
7use crate::error::{check_max, BgpValidationWarning, EncodingError, ParserError};
8use crate::models::capabilities::{
9 AddPathCapability, BgpCapabilityType, BgpExtendedMessageCapability, BgpRoleCapability,
10 ExtendedNextHopCapability, FourOctetAsCapability, GracefulRestartCapability,
11 MultiprotocolExtensionsCapability, RouteRefreshCapability,
12};
13use crate::models::error::BgpError;
14use crate::parser::bgp::attributes::parse_attributes;
15use crate::parser::{encode_nlri_prefixes, parse_nlri_list, ReadUtils};
16use log::warn;
17use zerocopy::big_endian::{U16, U32};
18use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
19
20#[derive(IntoBytes, FromBytes, KnownLayout, Immutable)]
22#[repr(C)]
23struct RawBgpOpenHeader {
24 version: u8,
25 asn: U16,
26 hold_time: U16,
27 bgp_identifier: U32,
28 opt_params_len: u8,
29}
30
31const _: () = assert!(size_of::<RawBgpOpenHeader>() == 10);
32
33#[derive(IntoBytes, FromBytes, KnownLayout, Immutable)]
36#[repr(C)]
37struct RawRouteRefreshHeader {
38 afi: U16,
39 subtype: u8,
40 safi: u8,
41}
42
43const _: () = assert!(size_of::<RawRouteRefreshHeader>() == 4);
44
45pub(crate) fn read_and_validate_bgp_marker(data: &mut Bytes) -> Result<(), ParserError> {
46 data.has_n_remaining(16)?;
47
48 let mut marker = [0u8; 16];
49 data.copy_to_slice(&mut marker);
50 if marker != [0xFF; 16] {
51 warn!("BGP message marker is not all 0xFF bytes (invalid per RFC 4271)");
52 }
53
54 Ok(())
55}
56
57pub fn parse_bgp_message(
76 data: &mut Bytes,
77 add_path: bool,
78 asn_len: &AsnLength,
79) -> Result<BgpMessage, ParserError> {
80 let total_size = data.len();
81 data.has_n_remaining(19)?;
82 read_and_validate_bgp_marker(data)?;
83
84 let length = data.read_u16()?;
96
97 let max_length = 65535; if !(19..=max_length).contains(&length) {
105 return Err(ParserError::ParseError(format!(
106 "invalid BGP message length {length}"
107 )));
108 }
109
110 let length_usize = length as usize;
112 let bgp_msg_length = if length_usize > total_size {
113 total_size.saturating_sub(19)
114 } else {
115 length_usize.saturating_sub(19)
116 };
117
118 let msg_type: BgpMessageType = match BgpMessageType::try_from(data.read_u8()?) {
119 Ok(t) => t,
120 Err(_) => {
121 return Err(ParserError::ParseError(
122 "Unknown BGP Message Type".to_string(),
123 ))
124 }
125 };
126
127 match msg_type {
130 BgpMessageType::OPEN | BgpMessageType::KEEPALIVE => {
131 if length > 4096 {
132 return Err(ParserError::ParseError(format!(
133 "BGP {} message length {} exceeds maximum allowed 4096 bytes (RFC 8654)",
134 match msg_type {
135 BgpMessageType::OPEN => "OPEN",
136 BgpMessageType::KEEPALIVE => "KEEPALIVE",
137 _ => unreachable!(),
138 },
139 length
140 )));
141 }
142 }
143 BgpMessageType::UPDATE | BgpMessageType::NOTIFICATION | BgpMessageType::ROUTE_REFRESH => {
144 }
147 }
148
149 if data.remaining() != bgp_msg_length {
150 warn!(
151 "BGP message length {} does not match the actual length {} (parsing BGP message)",
152 bgp_msg_length,
153 data.remaining()
154 );
155 }
156 data.has_n_remaining(bgp_msg_length)?;
157 let mut msg_data = data.split_to(bgp_msg_length);
158
159 Ok(match msg_type {
160 BgpMessageType::OPEN => BgpMessage::Open(parse_bgp_open_message(&mut msg_data)?),
161 BgpMessageType::UPDATE => {
162 BgpMessage::Update(parse_bgp_update_message(msg_data, add_path, asn_len)?)
163 }
164 BgpMessageType::NOTIFICATION => {
165 BgpMessage::Notification(parse_bgp_notification_message(msg_data)?)
166 }
167 BgpMessageType::KEEPALIVE => BgpMessage::KeepAlive,
168 BgpMessageType::ROUTE_REFRESH => {
169 BgpMessage::RouteRefresh(parse_bgp_route_refresh_message(&mut msg_data)?)
170 }
171 })
172}
173
174pub fn parse_bgp_route_refresh_message(
180 input: &mut Bytes,
181) -> Result<BgpRouteRefreshMessage, ParserError> {
182 input.has_n_remaining(4)?;
183 let mut header_bytes = [0u8; 4];
184 input.copy_to_slice(&mut header_bytes);
185 let raw = RawRouteRefreshHeader::ref_from_bytes(&header_bytes)
187 .expect("header_bytes is exactly 4 bytes with no alignment requirement");
188
189 Ok(BgpRouteRefreshMessage {
190 afi: raw.afi.get(),
191 subtype: raw.subtype,
192 safi: raw.safi,
193 data: input.split_to(input.remaining()).to_vec(),
194 })
195}
196
197impl BgpRouteRefreshMessage {
198 pub fn encode(&self) -> Bytes {
199 let raw = RawRouteRefreshHeader {
200 afi: U16::new(self.afi),
201 subtype: self.subtype,
202 safi: self.safi,
203 };
204 let mut bytes = BytesMut::with_capacity(4 + self.data.len());
205 bytes.put_slice(raw.as_bytes());
206 bytes.put_slice(&self.data);
207 bytes.freeze()
208 }
209}
210
211pub fn parse_bgp_notification_message(
218 mut input: Bytes,
219) -> Result<BgpNotificationMessage, ParserError> {
220 let error_code = input.read_u8()?;
221 let error_subcode = input.read_u8()?;
222
223 Ok(BgpNotificationMessage {
224 error: BgpError::new(error_code, error_subcode),
225 data: input.read_n_bytes(input.len())?,
226 })
227}
228
229impl BgpNotificationMessage {
230 pub fn encode(&self) -> Bytes {
231 let mut buf = BytesMut::new();
232 let (code, subcode) = self.error.get_codes();
233 buf.put_u8(code);
234 buf.put_u8(subcode);
235 buf.put_slice(&self.data);
236 buf.freeze()
237 }
238}
239
240pub fn parse_bgp_open_message(input: &mut Bytes) -> Result<BgpOpenMessage, ParserError> {
271 input.has_n_remaining(10)?;
272 let mut header_bytes = [0u8; 10];
273 input.copy_to_slice(&mut header_bytes);
274 let raw = RawBgpOpenHeader::ref_from_bytes(&header_bytes)
276 .expect("header_bytes is exactly 10 bytes with no alignment requirement");
277
278 let version = raw.version;
279 let asn = Asn::new_16bit(raw.asn.get());
280 let hold_time = raw.hold_time.get();
281 let bgp_identifier = Ipv4Addr::from(raw.bgp_identifier.get());
282 let mut opt_params_len: u16 = raw.opt_params_len as u16;
283
284 let mut extended_length = false;
285 let mut first = true;
286
287 let mut params: Vec<OptParam> = vec![];
288 while input.remaining() >= 2 {
289 let mut param_type = input.read_u8()?;
290 if first {
291 if opt_params_len == 0 && param_type == 255 {
292 return Err(ParserError::ParseError(
293 "RFC 9072 violation: Non-Extended Optional Parameters Length must not be 0 when using extended format".to_string()
294 ));
295 }
296 if opt_params_len != 0 && param_type == 255 {
298 extended_length = true;
320 opt_params_len = input.read_u16()?;
321 if opt_params_len == 0 {
322 break;
323 }
324 if input.remaining() != opt_params_len as usize {
326 warn!(
327 "BGP open message length {} does not match the actual length {} (parsing BGP OPEN message)",
328 opt_params_len,
329 input.remaining()
330 );
331 }
332
333 param_type = input.read_u8()?;
334 }
335 first = false;
336 }
337 let param_len = match extended_length {
340 true => input.read_u16()?,
341 false => input.read_u8()? as u16,
342 };
343
344 let param_value = match param_type {
348 2 => {
349 let mut capacities = vec![];
350
351 input.has_n_remaining(param_len as usize)?;
353 let mut param_data = input.split_to(param_len as usize);
354
355 while param_data.remaining() >= 2 {
356 let code = param_data.read_u8()?;
359 let len = param_data.read_u8()? as u16; let capability_data = param_data.read_n_bytes(len as usize)?;
362 let capability_type = BgpCapabilityType::from(code);
363
364 macro_rules! parse_capability {
366 ($parser:path, $variant:ident) => {
367 match $parser(Bytes::from(capability_data.clone())) {
368 Ok(parsed) => CapabilityValue::$variant(parsed),
369 Err(_) => CapabilityValue::Raw(capability_data),
370 }
371 };
372 }
373
374 let capability_value = match capability_type {
375 BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4 => {
376 parse_capability!(
377 MultiprotocolExtensionsCapability::parse,
378 MultiprotocolExtensions
379 )
380 }
381 BgpCapabilityType::ROUTE_REFRESH_CAPABILITY_FOR_BGP_4 => {
382 parse_capability!(RouteRefreshCapability::parse, RouteRefresh)
383 }
384 BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING => {
385 parse_capability!(ExtendedNextHopCapability::parse, ExtendedNextHop)
386 }
387 BgpCapabilityType::GRACEFUL_RESTART_CAPABILITY => {
388 parse_capability!(GracefulRestartCapability::parse, GracefulRestart)
389 }
390 BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY => {
391 parse_capability!(FourOctetAsCapability::parse, FourOctetAs)
392 }
393 BgpCapabilityType::ADD_PATH_CAPABILITY => {
394 parse_capability!(AddPathCapability::parse, AddPath)
395 }
396 BgpCapabilityType::BGP_ROLE => {
397 parse_capability!(BgpRoleCapability::parse, BgpRole)
398 }
399 BgpCapabilityType::BGP_EXTENDED_MESSAGE => {
400 parse_capability!(
401 BgpExtendedMessageCapability::parse,
402 BgpExtendedMessage
403 )
404 }
405 _ => CapabilityValue::Raw(capability_data),
406 };
407
408 capacities.push(Capability {
409 ty: capability_type,
410 value: capability_value,
411 });
412 }
413
414 ParamValue::Capacities(capacities)
415 }
416 _ => {
417 let bytes = input.read_n_bytes(param_len as usize)?;
419 ParamValue::Raw(bytes)
420 }
421 };
422 params.push(OptParam {
423 param_type,
424 param_value,
425 });
426 }
427
428 Ok(BgpOpenMessage {
429 version,
430 asn,
431 hold_time,
432 bgp_identifier,
433 extended_length,
434 opt_params: params,
435 })
436}
437
438fn encode_bgp_open_param_value(param: &OptParam) -> Result<Bytes, EncodingError> {
439 let mut buf = BytesMut::new();
440 match ¶m.param_value {
441 ParamValue::Capacities(capacities) => {
442 for cap in capacities {
443 buf.put_u8(cap.ty.into());
444 let encoded_value = match &cap.value {
445 CapabilityValue::MultiprotocolExtensions(mp) => mp.encode(),
446 CapabilityValue::RouteRefresh(rr) => rr.encode(),
447 CapabilityValue::ExtendedNextHop(enh) => enh.encode(),
448 CapabilityValue::GracefulRestart(gr) => gr.encode(),
449 CapabilityValue::FourOctetAs(foa) => foa.encode(),
450 CapabilityValue::AddPath(ap) => ap.encode(),
451 CapabilityValue::BgpRole(br) => br.encode(),
452 CapabilityValue::BgpExtendedMessage(bem) => bem.encode(),
453 CapabilityValue::Raw(raw) => Bytes::from(raw.clone()),
454 };
455 put_u8_len_slice(&mut buf, "BGP capability value length", &encoded_value)?;
456 }
457 }
458 ParamValue::Raw(bytes) => buf.put_slice(bytes),
459 }
460 Ok(buf.freeze())
461}
462
463impl BgpOpenMessage {
464 pub fn encode(&self) -> Result<Bytes, EncodingError> {
465 let encoded_params: Vec<(u8, Bytes)> = self
466 .opt_params
467 .iter()
468 .map(|param| {
469 if param.param_type == u8::MAX {
473 return Err(EncodingError::unencodable(
474 "BGP OPEN optional parameter type",
475 "type 255 is reserved by RFC 9072 as the extended-length marker",
476 ));
477 }
478 Ok((param.param_type, encode_bgp_open_param_value(param)?))
479 })
480 .collect::<Result<_, _>>()?;
481
482 let values_len: usize = encoded_params.iter().map(|(_, value)| value.len()).sum();
483 let non_extended_params_len = 2 * encoded_params.len() + values_len;
487 let use_extended_length =
488 self.extended_length || non_extended_params_len > u8::MAX as usize;
489 let per_param_header = if use_extended_length { 3 } else { 2 };
490 let encoded_params_len = per_param_header * encoded_params.len() + values_len;
491
492 let mut buf = BytesMut::with_capacity(
493 size_of::<RawBgpOpenHeader>()
494 + encoded_params_len
495 + if use_extended_length { 3 } else { 0 },
496 );
497 let raw_header = RawBgpOpenHeader {
498 version: self.version,
499 asn: U16::new(self.asn.into()),
500 hold_time: U16::new(self.hold_time),
501 bgp_identifier: U32::new(u32::from(self.bgp_identifier)),
502 opt_params_len: if use_extended_length {
503 u8::MAX
504 } else {
505 encoded_params_len as u8
506 },
507 };
508 buf.extend_from_slice(raw_header.as_bytes());
509
510 if use_extended_length {
511 check_max(
514 "BGP OPEN extended optional parameters total length",
515 encoded_params_len,
516 u16::MAX as usize,
517 )?;
518 buf.put_u8(u8::MAX);
519 buf.put_u16(encoded_params_len as u16);
520 }
521
522 for (param_type, value) in encoded_params {
523 buf.put_u8(param_type);
524 if use_extended_length {
525 debug_assert!(value.len() <= u16::MAX as usize);
528 buf.put_u16(value.len() as u16);
529 } else {
530 buf.put_u8(value.len() as u8);
533 }
534 buf.put_slice(&value);
535 }
536 Ok(buf.freeze())
537 }
538}
539
540fn read_nlri(input: Bytes, afi: &Afi, add_path: bool) -> Result<Vec<NetworkPrefix>, ParserError> {
546 let length = input.len();
547 if length == 0 {
548 return Ok(vec![]);
549 }
550 if length == 1 && input[0] != 0 {
551 warn!("seeing strange one-byte NLRI field (parsing NLRI in BGP UPDATE message)");
554 return Err(ParserError::ParseError(
555 "one-byte NLRI field with non-zero value is not a valid encoding".to_string(),
556 ));
557 }
558
559 parse_nlri_list(input, add_path, afi)
560}
561
562pub fn parse_bgp_update_message(
572 mut input: Bytes,
573 add_path: bool,
574 asn_len: &AsnLength,
575) -> Result<BgpUpdateMessage, ParserError> {
576 let afi = Afi::Ipv4;
578
579 let withdrawn_bytes_length_raw = input.read_u16()?;
581 let withdrawn_bytes_length = withdrawn_bytes_length_raw as usize;
582 input.has_n_remaining(withdrawn_bytes_length)?;
583 let withdrawn_bytes = input.split_to(withdrawn_bytes_length);
584 let (withdrawn_prefixes, withdrawn_nlri_error) =
585 match read_nlri(withdrawn_bytes.clone(), &afi, add_path) {
586 Ok(pfxs) => (pfxs, None),
587 Err(e) => (
588 Vec::new(),
589 Some(BgpValidationWarning::MalformedNlri {
590 nlri_type: "withdrawn",
591 reason: e.to_string(),
592 raw_bytes: withdrawn_bytes.to_vec(),
593 }),
594 ),
595 };
596
597 let attribute_length_raw = input.read_u16()?;
599 let attribute_length = attribute_length_raw as usize;
603
604 input.has_n_remaining(attribute_length)?;
605 let attr_data_slice = input.split_to(attribute_length);
606 let mut attributes = parse_attributes(attr_data_slice, asn_len, add_path, None, None, None)?;
607
608 let announced_bytes_present = !input.is_empty();
611 let (announced_prefixes, announced_nlri_error) = match read_nlri(input.clone(), &afi, add_path)
612 {
613 Ok(pfxs) => (pfxs, None),
614 Err(e) => (
615 Vec::new(),
616 Some(BgpValidationWarning::MalformedNlri {
617 nlri_type: "announced",
618 reason: e.to_string(),
619 raw_bytes: input.to_vec(),
620 }),
621 ),
622 };
623
624 let is_announcement =
630 announced_bytes_present || attributes.has_attr(AttrType::MP_REACHABLE_NLRI);
631 let has_standard_nlri = announced_bytes_present;
632 attributes.check_mandatory_attributes(is_announcement, has_standard_nlri);
633
634 if let Some(w) = withdrawn_nlri_error {
636 attributes.add_validation_warning(w);
637 }
638 if let Some(w) = announced_nlri_error {
639 attributes.add_validation_warning(w);
640 }
641
642 Ok(BgpUpdateMessage {
643 withdrawn_prefixes,
644 attributes,
645 announced_prefixes,
646 })
647}
648
649impl BgpUpdateMessage {
650 pub fn encode(&self, asn_len: AsnLength) -> Result<Bytes, EncodingError> {
651 let mut bytes = BytesMut::new();
652
653 let withdrawn_bytes = encode_nlri_prefixes(&self.withdrawn_prefixes);
655 put_u16_len_slice(
656 &mut bytes,
657 "BGP UPDATE withdrawn routes length",
658 &withdrawn_bytes,
659 )?;
660
661 with_u16_len(&mut bytes, "BGP UPDATE total path attribute length", |b| {
663 self.attributes.encode_to(asn_len, b)
664 })?;
665
666 bytes.extend(encode_nlri_prefixes(&self.announced_prefixes));
667 Ok(bytes.freeze())
668 }
669
670 pub fn is_end_of_rib(&self) -> bool {
675 if !self.announced_prefixes.is_empty() || !self.withdrawn_prefixes.is_empty() {
680 return false;
684 }
685
686 if self.attributes.inner.is_empty() {
687 return true;
690 }
691
692 if self.attributes.inner.len() > 1 {
695 return false;
697 }
698
699 if let AttributeValue::MpUnreachNlri(nlri) = &self.attributes.inner.first().unwrap().value {
701 if nlri.prefixes.is_empty() {
702 return true;
705 }
706 }
707
708 false
710 }
711}
712
713impl BgpMessage {
714 const MARKER: [u8; 16] = [0xFF; 16];
716
717 pub fn encode(&self, asn_len: AsnLength) -> Result<Bytes, EncodingError> {
718 let mut bytes = BytesMut::new();
719 bytes.put_slice(&Self::MARKER);
721
722 let (msg_type, msg_bytes) = match self {
723 BgpMessage::Open(msg) => (BgpMessageType::OPEN, msg.encode()?),
724 BgpMessage::Update(msg) => (BgpMessageType::UPDATE, msg.encode(asn_len)?),
725 BgpMessage::Notification(msg) => (BgpMessageType::NOTIFICATION, msg.encode()),
726 BgpMessage::KeepAlive => (BgpMessageType::KEEPALIVE, Bytes::new()),
727 BgpMessage::RouteRefresh(msg) => (BgpMessageType::ROUTE_REFRESH, msg.encode()),
728 };
729
730 let total_len = msg_bytes.len() + 16 + 2 + 1;
732 check_max("BGP message total length", total_len, u16::MAX as usize)?;
733 bytes.put_u16(total_len as u16);
734 bytes.put_u8(msg_type as u8);
735 bytes.put_slice(&msg_bytes);
736 Ok(bytes.freeze())
737 }
738}
739
740impl From<&BgpElem> for BgpUpdateMessage {
741 fn from(elem: &BgpElem) -> Self {
742 BgpUpdateMessage {
743 withdrawn_prefixes: vec![],
744 attributes: Attributes::from(elem),
745 announced_prefixes: vec![],
746 }
747 }
748}
749
750impl From<BgpUpdateMessage> for BgpMessage {
751 fn from(value: BgpUpdateMessage) -> Self {
752 BgpMessage::Update(value)
753 }
754}
755
756#[cfg(test)]
757mod tests {
758 use super::*;
759 use std::net::Ipv4Addr;
760 use std::str::FromStr;
761
762 #[test]
763 fn test_end_of_rib() {
764 let attrs = Attributes::default();
766 let msg = BgpUpdateMessage {
767 withdrawn_prefixes: vec![],
768 attributes: attrs,
769 announced_prefixes: vec![],
770 };
771 assert!(msg.is_end_of_rib());
772
773 let attrs = Attributes::from_iter(vec![AttributeValue::MpUnreachNlri(Nlri {
775 afi: Afi::Ipv4,
776 safi: Safi::Unicast,
777 next_hop: None,
778 prefixes: vec![],
779 labeled_prefixes: None,
780 link_state_nlris: None,
781 flowspec_nlris: None,
782 })]);
783 let msg = BgpUpdateMessage {
784 withdrawn_prefixes: vec![],
785 attributes: attrs,
786 announced_prefixes: vec![],
787 };
788 assert!(msg.is_end_of_rib());
789
790 let prefix = NetworkPrefix::from_str("192.168.1.0/24").unwrap();
792 let attrs = Attributes::default();
793 let msg = BgpUpdateMessage {
794 withdrawn_prefixes: vec![],
795 attributes: attrs,
796 announced_prefixes: vec![prefix],
797 };
798 assert!(!msg.is_end_of_rib());
799
800 let prefix = NetworkPrefix::from_str("192.168.1.0/24").unwrap();
802 let attrs = Attributes::default();
803 let msg = BgpUpdateMessage {
804 withdrawn_prefixes: vec![prefix],
805 attributes: attrs,
806 announced_prefixes: vec![],
807 };
808 assert!(!msg.is_end_of_rib());
809
810 let attrs = Attributes::from_iter(vec![AttributeValue::MpReachNlri(Nlri {
812 afi: Afi::Ipv4,
813 safi: Safi::Unicast,
814 next_hop: None,
815 prefixes: vec![],
816 labeled_prefixes: None,
817 link_state_nlris: None,
818 flowspec_nlris: None,
819 })]);
820 let msg = BgpUpdateMessage {
821 withdrawn_prefixes: vec![],
822 attributes: attrs,
823 announced_prefixes: vec![],
824 };
825 assert!(!msg.is_end_of_rib());
826
827 let attrs = Attributes::from_iter(vec![AttributeValue::MpReachNlri(Nlri {
829 afi: Afi::Ipv4,
830 safi: Safi::Unicast,
831 next_hop: None,
832 prefixes: vec![prefix],
833 labeled_prefixes: None,
834 link_state_nlris: None,
835 flowspec_nlris: None,
836 })]);
837 let msg = BgpUpdateMessage {
838 withdrawn_prefixes: vec![],
839 attributes: attrs,
840 announced_prefixes: vec![],
841 };
842 assert!(!msg.is_end_of_rib());
843
844 let attrs = Attributes::from_iter(vec![AttributeValue::MpUnreachNlri(Nlri {
846 afi: Afi::Ipv4,
847 safi: Safi::Unicast,
848 next_hop: None,
849 prefixes: vec![prefix],
850 labeled_prefixes: None,
851 link_state_nlris: None,
852 flowspec_nlris: None,
853 })]);
854 let msg = BgpUpdateMessage {
855 withdrawn_prefixes: vec![],
856 attributes: attrs,
857 announced_prefixes: vec![],
858 };
859 assert!(!msg.is_end_of_rib());
860
861 let attrs = Attributes::from_iter(vec![
863 AttributeValue::MpUnreachNlri(Nlri {
864 afi: Afi::Ipv4,
865 safi: Safi::Unicast,
866 next_hop: None,
867 prefixes: vec![],
868 labeled_prefixes: None,
869 link_state_nlris: None,
870 flowspec_nlris: None,
871 }),
872 AttributeValue::AtomicAggregate,
873 ]);
874 let msg = BgpUpdateMessage {
875 withdrawn_prefixes: vec![],
876 attributes: attrs,
877 announced_prefixes: vec![],
878 };
879 assert!(!msg.is_end_of_rib());
880 }
881
882 #[test]
883 fn test_invalid_length() {
884 let bytes = Bytes::from_static(&[
885 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, ]);
892 let mut data = bytes.clone();
893 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_err());
894
895 let bytes = Bytes::from_static(&[
896 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x05, ]);
903 let mut data = bytes.clone();
904 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_err());
905 }
906
907 #[test]
908 fn test_invalid_type() {
909 let bytes = Bytes::from_static(&[
910 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x28, 0x06, ]);
917 let mut data = bytes.clone();
918 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_err());
919 }
920
921 #[test]
922 fn test_parse_bgp_route_refresh_message() {
923 let bytes = Bytes::from_static(&[
926 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x17, 0x05, 0x00, 0x01, 0x00, 0x01, ]);
936 let mut data = bytes.clone();
937 let msg = parse_bgp_message(&mut data, false, &AsnLength::Bits32).unwrap();
938 let refresh = match &msg {
939 BgpMessage::RouteRefresh(refresh) => refresh,
940 _ => panic!("expected RouteRefresh, got {msg:?}"),
941 };
942 assert_eq!(msg.msg_type(), BgpMessageType::ROUTE_REFRESH);
943 assert_eq!(refresh.afi, 1);
944 assert_eq!(refresh.subtype, 0);
945 assert_eq!(refresh.safi, 1);
946 assert!(refresh.data.is_empty());
947 assert_eq!(refresh.afi(), Some(Afi::Ipv4));
948 assert_eq!(refresh.safi(), Some(Safi::Unicast));
949
950 let encoded = msg.encode(AsnLength::Bits32).unwrap();
952 assert_eq!(encoded, bytes);
953 }
954
955 #[test]
956 fn test_parse_bgp_route_refresh_message_with_orf_data() {
957 let bytes = Bytes::from_static(&[
960 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x1A, 0x05, 0x00, 0x19, 0x01, 0x41, 0xDE, 0xAD, 0xBE, ]);
971 let mut data = bytes.clone();
972 let msg = parse_bgp_message(&mut data, false, &AsnLength::Bits32).unwrap();
973 let refresh = match &msg {
974 BgpMessage::RouteRefresh(refresh) => refresh,
975 _ => panic!("expected RouteRefresh, got {msg:?}"),
976 };
977 assert_eq!(refresh.afi, 25);
978 assert_eq!(refresh.subtype, 1);
979 assert_eq!(refresh.safi, 65);
980 assert_eq!(refresh.data, vec![0xDE, 0xAD, 0xBE]);
981 assert_eq!(refresh.afi(), None);
982 assert_eq!(refresh.safi(), None);
983
984 let encoded = msg.encode(AsnLength::Bits32).unwrap();
985 assert_eq!(encoded, bytes);
986 }
987
988 #[test]
989 fn test_parse_bgp_route_refresh_message_unknown_subtype() {
990 let bytes = Bytes::from_static(&[
994 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x17, 0x05, 0x00, 0x01, 0x03, 0x01, ]);
1004 let mut data = bytes.clone();
1005 let msg = parse_bgp_message(&mut data, false, &AsnLength::Bits32).unwrap();
1006 let refresh = match &msg {
1007 BgpMessage::RouteRefresh(refresh) => refresh,
1008 _ => panic!("expected RouteRefresh, got {msg:?}"),
1009 };
1010 assert_eq!(refresh.afi, 1);
1011 assert_eq!(refresh.subtype, 3);
1012 assert_eq!(refresh.safi, 1);
1013 assert!(refresh.data.is_empty());
1014
1015 let encoded = msg.encode(AsnLength::Bits32).unwrap();
1016 assert_eq!(encoded, bytes);
1017 }
1018
1019 #[test]
1020 fn test_parse_bgp_route_refresh_message_truncated() {
1021 let bytes = Bytes::from_static(&[
1023 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x15, 0x05, 0x00, 0x01, ]);
1031 let mut data = bytes.clone();
1032 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits32).is_err());
1033 }
1034
1035 #[test]
1036 fn test_bgp_message_length_underflow_protection() {
1037 for len in [0u16, 1, 18] {
1040 let bytes = Bytes::from(vec![
1041 0xFF,
1042 0xFF,
1043 0xFF,
1044 0xFF, 0xFF,
1046 0xFF,
1047 0xFF,
1048 0xFF, 0xFF,
1050 0xFF,
1051 0xFF,
1052 0xFF, 0xFF,
1054 0xFF,
1055 0xFF,
1056 0xFF, (len >> 8) as u8,
1058 (len & 0xFF) as u8, 0x01, ]);
1061 let mut data = bytes.clone();
1062 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1063 assert!(
1064 result.is_err(),
1065 "Length {} should be rejected as invalid",
1066 len
1067 );
1068 }
1069 }
1070
1071 #[test]
1072 fn test_bgp_marker_encoding_rfc4271() {
1073 let msg = BgpMessage::KeepAlive;
1075 let encoded = msg.encode(AsnLength::Bits16).unwrap();
1076
1077 assert_eq!(
1079 &encoded[..16],
1080 &[0xFF; 16],
1081 "BGP marker should be all 0xFF bytes"
1082 );
1083 }
1084
1085 #[test]
1086 fn test_bgp_marker_validation() {
1087 let valid_bytes = Bytes::from(vec![
1089 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x13, 0x04, ]);
1096 let mut data = valid_bytes.clone();
1097 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1098 assert!(result.is_ok(), "Valid marker should parse successfully");
1099
1100 let invalid_bytes = Bytes::from(vec![
1103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x04, ]);
1110 let mut data = invalid_bytes.clone();
1111 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1113 assert!(
1114 result.is_ok(),
1115 "Invalid marker should still parse (with warning)"
1116 );
1117 }
1118
1119 #[test]
1120 fn test_attribute_length_overflow_protection() {
1121 let update_bytes = Bytes::from(vec![
1126 0x00, 0x00, 0xFF,
1128 0xFF, ]);
1131
1132 let result = parse_bgp_update_message(update_bytes, false, &AsnLength::Bits16);
1133 assert!(
1134 result.is_err(),
1135 "Should fail when attribute_length exceeds available data"
1136 );
1137 assert!(
1138 matches!(result, Err(ParserError::TruncatedMsg(_))),
1139 "Should fail with TruncatedMsg error"
1140 );
1141
1142 let valid_update = Bytes::from(vec![
1144 0x00, 0x00, 0x00,
1146 0x00, ]);
1149 let result = parse_bgp_update_message(valid_update, false, &AsnLength::Bits16);
1150 assert!(result.is_ok(), "Should parse valid empty UPDATE");
1151 }
1152
1153 #[test]
1154 fn test_parse_bgp_notification_message() {
1155 let bytes = Bytes::from_static(&[
1156 0x01, 0x02, 0x00, 0x00, ]);
1160 let msg = parse_bgp_notification_message(bytes).unwrap();
1161 matches!(
1162 msg.error,
1163 BgpError::MessageHeaderError(MessageHeaderError::BAD_MESSAGE_LENGTH)
1164 );
1165 assert_eq!(msg.data, Bytes::from_static(&[0x00, 0x00]));
1166 }
1167
1168 #[test]
1169 fn test_encode_bgp_notification_messsage() {
1170 let msg = BgpNotificationMessage {
1171 error: BgpError::MessageHeaderError(MessageHeaderError::BAD_MESSAGE_LENGTH),
1172 data: vec![0x00, 0x00],
1173 };
1174 let bytes = msg.encode();
1175 assert_eq!(bytes, Bytes::from_static(&[0x01, 0x02, 0x00, 0x00]));
1176 }
1177
1178 #[test]
1179 fn test_parse_bgp_open_message() {
1180 let bytes = Bytes::from_static(&[
1181 0x04, 0x00, 0x01, 0x00, 0xb4, 0xc0, 0x00, 0x02, 0x01, 0x00, ]);
1187 let msg = parse_bgp_open_message(&mut bytes.clone()).unwrap();
1188 assert_eq!(msg.version, 4);
1189 assert_eq!(msg.asn, Asn::new_16bit(1));
1190 assert_eq!(msg.hold_time, 180);
1191 assert_eq!(msg.bgp_identifier, Ipv4Addr::new(192, 0, 2, 1));
1192 assert!(!msg.extended_length);
1193 assert_eq!(msg.opt_params.len(), 0);
1194 }
1195
1196 #[test]
1197 fn test_encode_bgp_open_message() {
1198 let msg = BgpOpenMessage {
1199 version: 4,
1200 asn: Asn::new_16bit(1),
1201 hold_time: 180,
1202 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
1203 extended_length: false,
1204 opt_params: vec![],
1205 };
1206 let bytes = msg.encode().unwrap();
1207 assert_eq!(
1208 bytes,
1209 Bytes::from_static(&[
1210 0x04, 0x00, 0x01, 0x00, 0xb4, 0xc0, 0x00, 0x02, 0x01, 0x00, ])
1216 );
1217 }
1218
1219 #[test]
1220 fn test_bgp_open_wire_fixtures_round_trip_byte_identically() {
1221 let fixtures = [
1223 (
1224 "no optional parameters",
1225 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF001D01",
1226 "048826005A02380BFE00",
1227 0x00,
1228 ),
1229 (
1230 "two capability parameters",
1231 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF002501",
1232 "045BA0005A66433801080202800002020200",
1233 0x08,
1234 ),
1235 (
1236 "five capability parameters",
1237 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003901",
1238 "04947100B4CBD0B16E1C02060104000200010202800002020200020246000206410400009471",
1239 0x1C,
1240 ),
1241 (
1242 "one 22-byte capability parameter",
1243 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003501",
1244 "045BA000F05D9FBB0118021601040001000102004002007841040003215C46004700",
1245 0x18,
1246 ),
1247 (
1248 "one 26-byte capability parameter",
1249 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003901",
1250 "045BA0012CB901A6321C021A0104000100010200400600780001010041040003167D46004700",
1251 0x1C,
1252 ),
1253 ];
1254
1255 for (name, header, body, expected_opt_params_len) in fixtures {
1256 let wire = Bytes::from(hex::decode(format!("{header}{body}")).unwrap());
1257 assert_eq!(wire[28], expected_opt_params_len, "{name}");
1258
1259 let mut input = wire.clone();
1260 let parsed =
1261 parse_bgp_message(&mut input, false, &AsnLength::Bits16).unwrap_or_else(|error| {
1262 panic!("failed to parse {name}: {error}");
1263 });
1264 let encoded = parsed.encode(AsnLength::Bits16).unwrap();
1265
1266 assert_eq!(encoded, wire, "{name}");
1267 }
1268 }
1269
1270 #[test]
1271 fn test_bgp_open_encoding_recomputes_parameter_lengths() {
1272 let msg = BgpOpenMessage {
1273 version: 4,
1274 asn: Asn::new_16bit(64512),
1275 hold_time: 90,
1276 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
1277 extended_length: false,
1278 opt_params: vec![OptParam {
1279 param_type: 254,
1280 param_value: ParamValue::Raw(vec![0xAA, 0xBB, 0xCC]),
1281 }],
1282 };
1283
1284 let encoded = msg.encode().unwrap();
1285
1286 assert_eq!(encoded[9], 5);
1287 assert_eq!(&encoded[10..], &[254, 3, 0xAA, 0xBB, 0xCC]);
1288 let parsed = parse_bgp_open_message(&mut encoded.clone()).unwrap();
1289 assert_eq!(parsed.encode().unwrap(), encoded);
1290 }
1291
1292 #[test]
1293 fn test_bgp_open_encoding_rejects_oversized_add_path_capability() {
1294 use crate::models::capabilities::{AddPathAddressFamily, AddPathSendReceive};
1295
1296 let address_family = AddPathAddressFamily {
1297 afi: Afi::Ipv4,
1298 safi: Safi::Unicast,
1299 send_receive: AddPathSendReceive::SendReceive,
1300 };
1301 let msg = BgpOpenMessage {
1302 version: 4,
1303 asn: Asn::new_16bit(64512),
1304 hold_time: 90,
1305 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
1306 extended_length: false,
1307 opt_params: vec![OptParam {
1308 param_type: 2,
1309 param_value: ParamValue::Capacities(vec![Capability {
1310 ty: BgpCapabilityType::ADD_PATH_CAPABILITY,
1311 value: CapabilityValue::AddPath(AddPathCapability::new(vec![
1312 address_family;
1313 64
1314 ])),
1315 }]),
1316 }],
1317 };
1318
1319 let err = msg.encode().unwrap_err();
1320 assert_eq!(
1321 err,
1322 EncodingError::ValueTooLarge {
1323 field: "BGP capability value length",
1324 actual: 256,
1325 max: 255
1326 }
1327 );
1328 }
1329
1330 #[test]
1331 fn test_bgp_open_forced_extended_parameter_encoding() {
1332 let msg = BgpOpenMessage {
1333 version: 4,
1334 asn: Asn::new_16bit(64512),
1335 hold_time: 90,
1336 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
1337 extended_length: true,
1338 opt_params: vec![OptParam {
1339 param_type: 254,
1340 param_value: ParamValue::Raw(vec![0xAA, 0xBB]),
1341 }],
1342 };
1343
1344 let encoded = msg.encode().unwrap();
1345
1346 assert_eq!(
1347 &encoded[9..],
1348 &[0xFF, 0xFF, 0x00, 0x05, 254, 0x00, 0x02, 0xAA, 0xBB]
1349 );
1350 let parsed = parse_bgp_open_message(&mut encoded.clone()).unwrap();
1351 assert!(parsed.extended_length);
1352 assert_eq!(parsed.encode().unwrap(), encoded);
1353 }
1354
1355 #[test]
1356 fn test_bgp_open_automatically_uses_extended_parameter_encoding() {
1357 let msg = BgpOpenMessage {
1358 version: 4,
1359 asn: Asn::new_16bit(64512),
1360 hold_time: 90,
1361 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
1362 extended_length: false,
1363 opt_params: vec![OptParam {
1364 param_type: 254,
1365 param_value: ParamValue::Raw(vec![0xAA; 256]),
1366 }],
1367 };
1368
1369 let encoded = msg.encode().unwrap();
1370
1371 assert_eq!(encoded.len(), 272);
1372 assert_eq!(&encoded[9..16], &[0xFF, 0xFF, 0x01, 0x03, 254, 0x01, 0x00]);
1373 let parsed = parse_bgp_open_message(&mut encoded.clone()).unwrap();
1374 assert!(parsed.extended_length);
1375 assert_eq!(parsed.encode().unwrap(), encoded);
1376 }
1377
1378 #[test]
1379 fn test_encode_bgp_notification_message() {
1380 let bgp_message = BgpMessage::Notification(BgpNotificationMessage {
1381 error: BgpError::MessageHeaderError(MessageHeaderError::BAD_MESSAGE_LENGTH),
1382 data: vec![0x00, 0x00],
1383 });
1384 let bytes = bgp_message.encode(AsnLength::Bits16).unwrap();
1385 assert_eq!(
1387 bytes,
1388 Bytes::from_static(&[
1389 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x17, 0x03, 0x01, 0x02, 0x00, 0x00 ])
1396 );
1397 }
1398
1399 #[test]
1400 fn test_bgp_message_from_bgp_update_message() {
1401 let msg = BgpMessage::from(BgpUpdateMessage::default());
1402 assert!(matches!(msg, BgpMessage::Update(_)));
1403 }
1404
1405 #[test]
1406 fn test_parse_bgp_open_message_with_extended_next_hop_capability() {
1407 use crate::models::{Afi, Safi};
1408
1409 let bytes = Bytes::from(vec![
1415 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, ]);
1431
1432 let msg = parse_bgp_open_message(&mut bytes.clone()).unwrap();
1433 assert_eq!(msg.version, 4);
1434 assert_eq!(msg.asn, Asn::new_16bit(65001));
1435 assert_eq!(msg.hold_time, 180);
1436 assert_eq!(msg.bgp_identifier, Ipv4Addr::new(192, 0, 2, 1));
1437 assert!(!msg.extended_length);
1438 assert_eq!(msg.opt_params.len(), 1);
1439
1440 if let ParamValue::Capacities(cap) = &msg.opt_params[0].param_value {
1442 assert_eq!(cap[0].ty, BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING);
1443
1444 if let CapabilityValue::ExtendedNextHop(enh_cap) = &cap[0].value {
1445 assert_eq!(enh_cap.entries.len(), 2);
1446
1447 let entry1 = &enh_cap.entries[0];
1449 assert_eq!(entry1.nlri_afi, Afi::Ipv4);
1450 assert_eq!(entry1.nlri_safi, Safi::Unicast);
1451 assert_eq!(entry1.nexthop_afi, Afi::Ipv6);
1452
1453 let entry2 = &enh_cap.entries[1];
1455 assert_eq!(entry2.nlri_afi, Afi::Ipv4);
1456 assert_eq!(entry2.nlri_safi, Safi::MplsVpn);
1457 assert_eq!(entry2.nexthop_afi, Afi::Ipv6);
1458
1459 assert!(enh_cap.supports(Afi::Ipv4, Safi::Unicast, Afi::Ipv6));
1461 assert!(enh_cap.supports(Afi::Ipv4, Safi::MplsVpn, Afi::Ipv6));
1462 assert!(!enh_cap.supports(Afi::Ipv4, Safi::Multicast, Afi::Ipv6));
1463 } else {
1464 panic!("Expected ExtendedNextHop capability value");
1465 }
1466 } else {
1467 panic!("Expected capability parameter");
1468 }
1469 }
1470
1471 #[test]
1472 fn test_rfc8654_extended_message_length_validation() {
1473 let bytes = Bytes::from_static(&[
1475 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x00, 0x00,
1483 0x00, ]);
1486 let mut data = bytes.clone();
1487 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_ok());
1489
1490 let bytes = Bytes::from_static(&[
1492 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x01, ]);
1499 let mut data = bytes.clone();
1500 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1501 assert!(result.is_err());
1502 if let Err(ParserError::ParseError(msg)) = result {
1503 assert!(msg.contains("BGP OPEN message length"));
1504 assert!(msg.contains("4096 bytes"));
1505 }
1506
1507 let bytes = Bytes::from_static(&[
1509 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x04, ]);
1516 let mut data = bytes.clone();
1517 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1518 assert!(result.is_err());
1519 if let Err(ParserError::ParseError(msg)) = result {
1520 assert!(msg.contains("BGP KEEPALIVE message length"));
1521 assert!(msg.contains("4096 bytes"));
1522 }
1523
1524 let bytes = Bytes::from_static(&[
1526 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x02, ]);
1533 let mut data = bytes.clone();
1534 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1536 if let Err(ParserError::ParseError(msg)) = result {
1537 assert!(!msg.contains("invalid BGP message length"));
1539 }
1540 }
1541
1542 #[test]
1543 fn test_bgp_extended_message_capability_parsing() {
1544 use crate::models::CapabilityValue;
1545
1546 let bytes = Bytes::from(vec![
1548 0x04, 0x00, 0x01, 0x00, 0xb4, 0xc0, 0x00, 0x02, 0x01, 0x04, 0x02, 0x02, 0x06, 0x00, ]);
1558
1559 let msg = parse_bgp_open_message(&mut bytes.clone()).unwrap();
1560 assert_eq!(msg.version, 4);
1561 assert_eq!(msg.asn, Asn::new_16bit(1));
1562 assert_eq!(msg.opt_params.len(), 1);
1563
1564 if let ParamValue::Capacities(cap) = &msg.opt_params[0].param_value {
1566 assert_eq!(cap[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1567 if let CapabilityValue::BgpExtendedMessage(_) = &cap[0].value {
1568 } else {
1570 panic!("Expected BgpExtendedMessage capability value");
1571 }
1572 } else {
1573 panic!("Expected capability parameter");
1574 }
1575 }
1576
1577 #[test]
1578 fn test_rfc8654_edge_cases() {
1579 let bytes = Bytes::from_static(&[
1581 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x03, 0x06, 0x00, ]);
1591 let mut data = bytes.clone();
1592 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1594 if let Err(ParserError::ParseError(msg)) = result {
1596 assert!(!msg.contains("invalid BGP message length"));
1597 assert!(!msg.contains("exceeds maximum allowed 4096 bytes"));
1598 }
1599
1600 let open_data = vec![
1602 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, ];
1609 let bytes = Bytes::from(open_data);
1610 let mut data = bytes.clone();
1611 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1612 if let Err(ParserError::ParseError(msg)) = result {
1614 assert!(!msg.contains("exceeds maximum allowed 4096 bytes"));
1615 }
1616
1617 let bytes = Bytes::from_static(&[
1619 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x02, ]);
1626 let mut data = bytes.clone();
1627 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1628 if let Err(ParserError::ParseError(msg)) = result {
1630 assert!(!msg.contains("invalid BGP message length"));
1631 }
1632 }
1633
1634 #[test]
1635 fn test_rfc8654_capability_encoding_path() {
1636 use crate::models::capabilities::BgpExtendedMessageCapability;
1637
1638 let capability_value =
1641 CapabilityValue::BgpExtendedMessage(BgpExtendedMessageCapability::new());
1642 let capability = Capability {
1643 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1644 value: capability_value,
1645 };
1646
1647 let opt_param = OptParam {
1648 param_type: 2, param_value: ParamValue::Capacities(vec![capability]),
1650 };
1651
1652 let msg = BgpOpenMessage {
1653 version: 4,
1654 asn: Asn::new_16bit(65001),
1655 hold_time: 180,
1656 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
1657 extended_length: false,
1658 opt_params: vec![opt_param],
1659 };
1660
1661 let encoded = msg.encode().unwrap();
1663 assert!(!encoded.is_empty());
1664
1665 let parsed = parse_bgp_open_message(&mut encoded.clone()).unwrap();
1667 assert_eq!(parsed.opt_params.len(), 1);
1668 if let ParamValue::Capacities(cap) = &parsed.opt_params[0].param_value {
1669 assert_eq!(cap[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1670 }
1671 }
1672
1673 #[test]
1674 fn test_rfc8654_error_message_formatting() {
1675 let bytes = Bytes::from_static(&[
1680 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x01, ]);
1687 let mut data = bytes.clone();
1688 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1689 assert!(result.is_err());
1690 if let Err(ParserError::ParseError(msg)) = result {
1691 assert!(msg.contains("BGP OPEN message length"));
1692 assert!(msg.contains("exceeds maximum allowed 4096 bytes"));
1693 }
1694
1695 let bytes = Bytes::from_static(&[
1697 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x04, ]);
1704 let mut data = bytes.clone();
1705 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1706 assert!(result.is_err());
1707 if let Err(ParserError::ParseError(msg)) = result {
1708 assert!(msg.contains("BGP KEEPALIVE message length"));
1709 assert!(msg.contains("exceeds maximum allowed 4096 bytes"));
1710 }
1711 }
1712
1713 #[test]
1714 fn test_encode_bgp_open_message_with_extended_message_capability() {
1715 use crate::models::capabilities::BgpExtendedMessageCapability;
1716
1717 let extended_msg_capability = BgpExtendedMessageCapability::new();
1719
1720 let msg = BgpOpenMessage {
1721 version: 4,
1722 asn: Asn::new_16bit(65001),
1723 hold_time: 180,
1724 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
1725 extended_length: false,
1726 opt_params: vec![OptParam {
1727 param_type: 2, param_value: ParamValue::Capacities(vec![Capability {
1729 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1730 value: CapabilityValue::BgpExtendedMessage(extended_msg_capability),
1731 }]),
1732 }],
1733 };
1734
1735 let encoded = msg.encode().unwrap();
1736
1737 let parsed = parse_bgp_open_message(&mut encoded.clone()).unwrap();
1739 assert_eq!(parsed.version, msg.version);
1740 assert_eq!(parsed.asn, msg.asn);
1741 assert_eq!(parsed.hold_time, msg.hold_time);
1742 assert_eq!(parsed.bgp_identifier, msg.bgp_identifier);
1743 assert_eq!(parsed.opt_params.len(), 1);
1744
1745 if let ParamValue::Capacities(cap) = &parsed.opt_params[0].param_value {
1747 assert_eq!(cap[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1748 if let CapabilityValue::BgpExtendedMessage(_) = &cap[0].value {
1749 } else {
1751 panic!("Expected BgpExtendedMessage capability value after round trip");
1752 }
1753 } else {
1754 panic!("Expected capability parameter after round trip");
1755 }
1756 }
1757
1758 #[test]
1759 fn test_encode_bgp_open_message_with_extended_next_hop_capability() {
1760 use crate::models::capabilities::{ExtendedNextHopCapability, ExtendedNextHopEntry};
1761 use crate::models::{Afi, Safi};
1762
1763 let entries = vec![
1765 ExtendedNextHopEntry {
1766 nlri_afi: Afi::Ipv4,
1767 nlri_safi: Safi::Unicast,
1768 nexthop_afi: Afi::Ipv6,
1769 },
1770 ExtendedNextHopEntry {
1771 nlri_afi: Afi::Ipv4,
1772 nlri_safi: Safi::MplsVpn,
1773 nexthop_afi: Afi::Ipv6,
1774 },
1775 ];
1776 let enh_capability = ExtendedNextHopCapability::new(entries);
1777
1778 let msg = BgpOpenMessage {
1779 version: 4,
1780 asn: Asn::new_16bit(65001),
1781 hold_time: 180,
1782 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
1783 extended_length: false,
1784 opt_params: vec![OptParam {
1785 param_type: 2, param_value: ParamValue::Capacities(vec![Capability {
1787 ty: BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING,
1788 value: CapabilityValue::ExtendedNextHop(enh_capability),
1789 }]),
1790 }],
1791 };
1792
1793 let encoded = msg.encode().unwrap();
1794
1795 let parsed = parse_bgp_open_message(&mut encoded.clone()).unwrap();
1797 assert_eq!(parsed.version, msg.version);
1798 assert_eq!(parsed.asn, msg.asn);
1799 assert_eq!(parsed.hold_time, msg.hold_time);
1800 assert_eq!(parsed.bgp_identifier, msg.bgp_identifier);
1801 assert_eq!(parsed.extended_length, msg.extended_length);
1802 assert_eq!(parsed.opt_params.len(), 1);
1803
1804 if let ParamValue::Capacities(cap) = &parsed.opt_params[0].param_value {
1806 assert_eq!(cap[0].ty, BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING);
1807 if let CapabilityValue::ExtendedNextHop(enh_cap) = &cap[0].value {
1808 assert_eq!(enh_cap.entries.len(), 2);
1809 assert!(enh_cap.supports(Afi::Ipv4, Safi::Unicast, Afi::Ipv6));
1810 assert!(enh_cap.supports(Afi::Ipv4, Safi::MplsVpn, Afi::Ipv6));
1811 } else {
1812 panic!("Expected ExtendedNextHop capability value after round trip");
1813 }
1814 } else {
1815 panic!("Expected capability parameter after round trip");
1816 }
1817 }
1818
1819 #[test]
1820 fn test_parse_bgp_open_message_with_multiple_capabilities() {
1821 let extended_msg_cap = Capability {
1826 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1827 value: CapabilityValue::BgpExtendedMessage(BgpExtendedMessageCapability {}),
1828 };
1829
1830 let route_refresh_cap = Capability {
1831 ty: BgpCapabilityType::ROUTE_REFRESH_CAPABILITY_FOR_BGP_4,
1832 value: CapabilityValue::RouteRefresh(RouteRefreshCapability {}),
1833 };
1834
1835 let four_octet_as_cap = Capability {
1836 ty: BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY,
1837 value: CapabilityValue::FourOctetAs(FourOctetAsCapability { asn: 65536 }),
1838 };
1839
1840 let msg = BgpOpenMessage {
1842 version: 4,
1843 asn: Asn::new_32bit(65000),
1844 hold_time: 180,
1845 bgp_identifier: "10.0.0.1".parse().unwrap(),
1846 extended_length: false,
1847 opt_params: vec![OptParam {
1848 param_type: 2, param_value: ParamValue::Capacities(vec![
1850 extended_msg_cap,
1851 route_refresh_cap,
1852 four_octet_as_cap,
1853 ]),
1854 }],
1855 };
1856
1857 let encoded = msg.encode().unwrap();
1859
1860 let mut encoded_bytes = encoded.clone();
1862 let parsed = parse_bgp_open_message(&mut encoded_bytes).unwrap();
1863
1864 assert_eq!(parsed.version, 4);
1866 assert_eq!(parsed.asn, Asn::new_32bit(65000));
1867 assert_eq!(parsed.hold_time, 180);
1868 assert_eq!(
1869 parsed.bgp_identifier,
1870 "10.0.0.1".parse::<std::net::Ipv4Addr>().unwrap()
1871 );
1872 assert_eq!(parsed.opt_params.len(), 1);
1873
1874 if let ParamValue::Capacities(caps) = &parsed.opt_params[0].param_value {
1876 assert_eq!(caps.len(), 3, "Should have 3 capabilities");
1877
1878 assert_eq!(caps[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1880 assert!(matches!(
1881 caps[0].value,
1882 CapabilityValue::BgpExtendedMessage(_)
1883 ));
1884
1885 assert_eq!(
1887 caps[1].ty,
1888 BgpCapabilityType::ROUTE_REFRESH_CAPABILITY_FOR_BGP_4
1889 );
1890 assert!(matches!(caps[1].value, CapabilityValue::RouteRefresh(_)));
1891
1892 assert_eq!(
1894 caps[2].ty,
1895 BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY
1896 );
1897 if let CapabilityValue::FourOctetAs(foa) = &caps[2].value {
1898 assert_eq!(foa.asn, 65536);
1899 } else {
1900 panic!("Expected FourOctetAs capability value");
1901 }
1902 } else {
1903 panic!("Expected Capacities parameter");
1904 }
1905 }
1906
1907 #[test]
1908 fn test_parse_bgp_open_message_with_multiple_capability_parameters() {
1909 let msg = BgpOpenMessage {
1913 version: 4,
1914 asn: Asn::new_32bit(65001),
1915 hold_time: 90,
1916 bgp_identifier: "192.168.1.1".parse().unwrap(),
1917 extended_length: false,
1918 opt_params: vec![
1919 OptParam {
1920 param_type: 2, param_value: ParamValue::Capacities(vec![Capability {
1922 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1923 value: CapabilityValue::BgpExtendedMessage(BgpExtendedMessageCapability {}),
1924 }]),
1925 },
1926 OptParam {
1927 param_type: 2, param_value: ParamValue::Capacities(vec![Capability {
1929 ty: BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY,
1930 value: CapabilityValue::FourOctetAs(FourOctetAsCapability {
1931 asn: 4200000000,
1932 }),
1933 }]),
1934 },
1935 ],
1936 };
1937
1938 let encoded = msg.encode().unwrap();
1940 let mut encoded_bytes = encoded.clone();
1941 let parsed = parse_bgp_open_message(&mut encoded_bytes).unwrap();
1942
1943 assert_eq!(parsed.opt_params.len(), 2);
1945
1946 if let ParamValue::Capacities(caps) = &parsed.opt_params[0].param_value {
1948 assert_eq!(caps.len(), 1);
1949 assert_eq!(caps[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1950 } else {
1951 panic!("Expected Capacities in first parameter");
1952 }
1953
1954 if let ParamValue::Capacities(caps) = &parsed.opt_params[1].param_value {
1956 assert_eq!(caps.len(), 1);
1957 assert_eq!(
1958 caps[0].ty,
1959 BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY
1960 );
1961 if let CapabilityValue::FourOctetAs(foa) = &caps[0].value {
1962 assert_eq!(foa.asn, 4200000000);
1963 }
1964 } else {
1965 panic!("Expected Capacities in second parameter");
1966 }
1967 }
1968}