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!("only OPEN and KEEPALIVE take this length check"),
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 attributes.check_domain_path_with_classic_nlri(has_standard_nlri);
637
638 if let Some(w) = withdrawn_nlri_error {
640 attributes.add_validation_warning(w);
641 }
642 if let Some(w) = announced_nlri_error {
643 attributes.add_validation_warning(w);
644 }
645
646 Ok(BgpUpdateMessage {
647 withdrawn_prefixes,
648 attributes,
649 announced_prefixes,
650 })
651}
652
653impl BgpUpdateMessage {
654 pub fn encode(&self, asn_len: AsnLength) -> Result<Bytes, EncodingError> {
655 let mut bytes = BytesMut::new();
656
657 let withdrawn_bytes = encode_nlri_prefixes(&self.withdrawn_prefixes);
659 put_u16_len_slice(
660 &mut bytes,
661 "BGP UPDATE withdrawn routes length",
662 &withdrawn_bytes,
663 )?;
664
665 with_u16_len(&mut bytes, "BGP UPDATE total path attribute length", |b| {
667 self.attributes.encode_to(asn_len, b)
668 })?;
669
670 bytes.extend(encode_nlri_prefixes(&self.announced_prefixes));
671 Ok(bytes.freeze())
672 }
673
674 pub fn is_end_of_rib(&self) -> bool {
679 if !self.announced_prefixes.is_empty() || !self.withdrawn_prefixes.is_empty() {
684 return false;
688 }
689
690 if self.attributes.inner.is_empty() {
691 return true;
694 }
695
696 if self.attributes.inner.len() > 1 {
699 return false;
701 }
702
703 if let AttributeValue::MpUnreachNlri(nlri) = &self.attributes.inner.first().unwrap().value {
705 if nlri.prefixes.is_empty() {
706 return true;
709 }
710 }
711
712 false
714 }
715}
716
717impl BgpMessage {
718 const MARKER: [u8; 16] = [0xFF; 16];
720
721 pub fn encode(&self, asn_len: AsnLength) -> Result<Bytes, EncodingError> {
722 let mut bytes = BytesMut::new();
723 bytes.put_slice(&Self::MARKER);
725
726 let (msg_type, msg_bytes) = match self {
727 BgpMessage::Open(msg) => (BgpMessageType::OPEN, msg.encode()?),
728 BgpMessage::Update(msg) => (BgpMessageType::UPDATE, msg.encode(asn_len)?),
729 BgpMessage::Notification(msg) => (BgpMessageType::NOTIFICATION, msg.encode()),
730 BgpMessage::KeepAlive => (BgpMessageType::KEEPALIVE, Bytes::new()),
731 BgpMessage::RouteRefresh(msg) => (BgpMessageType::ROUTE_REFRESH, msg.encode()),
732 };
733
734 let total_len = msg_bytes.len() + 16 + 2 + 1;
736 check_max("BGP message total length", total_len, u16::MAX as usize)?;
737 bytes.put_u16(total_len as u16);
738 bytes.put_u8(msg_type as u8);
739 bytes.put_slice(&msg_bytes);
740 Ok(bytes.freeze())
741 }
742}
743
744impl From<&BgpElem> for BgpUpdateMessage {
745 fn from(elem: &BgpElem) -> Self {
746 BgpUpdateMessage {
747 withdrawn_prefixes: vec![],
748 attributes: Attributes::from(elem),
749 announced_prefixes: vec![],
750 }
751 }
752}
753
754impl From<BgpUpdateMessage> for BgpMessage {
755 fn from(value: BgpUpdateMessage) -> Self {
756 BgpMessage::Update(value)
757 }
758}
759
760#[cfg(test)]
761mod tests {
762 use super::*;
763 use std::net::Ipv4Addr;
764 use std::str::FromStr;
765
766 #[test]
767 fn test_end_of_rib() {
768 let attrs = Attributes::default();
770 let msg = BgpUpdateMessage {
771 withdrawn_prefixes: vec![],
772 attributes: attrs,
773 announced_prefixes: vec![],
774 };
775 assert!(msg.is_end_of_rib());
776
777 let attrs = Attributes::from_iter(vec![AttributeValue::MpUnreachNlri(Nlri {
779 afi: Afi::Ipv4,
780 safi: Safi::Unicast,
781 next_hop: None,
782 prefixes: vec![],
783 labeled_prefixes: None,
784 link_state_nlris: None,
785 flowspec_nlris: None,
786 })]);
787 let msg = BgpUpdateMessage {
788 withdrawn_prefixes: vec![],
789 attributes: attrs,
790 announced_prefixes: vec![],
791 };
792 assert!(msg.is_end_of_rib());
793
794 let prefix = NetworkPrefix::from_str("192.168.1.0/24").unwrap();
796 let attrs = Attributes::default();
797 let msg = BgpUpdateMessage {
798 withdrawn_prefixes: vec![],
799 attributes: attrs,
800 announced_prefixes: vec![prefix],
801 };
802 assert!(!msg.is_end_of_rib());
803
804 let prefix = NetworkPrefix::from_str("192.168.1.0/24").unwrap();
806 let attrs = Attributes::default();
807 let msg = BgpUpdateMessage {
808 withdrawn_prefixes: vec![prefix],
809 attributes: attrs,
810 announced_prefixes: vec![],
811 };
812 assert!(!msg.is_end_of_rib());
813
814 let attrs = Attributes::from_iter(vec![AttributeValue::MpReachNlri(Nlri {
816 afi: Afi::Ipv4,
817 safi: Safi::Unicast,
818 next_hop: None,
819 prefixes: vec![],
820 labeled_prefixes: None,
821 link_state_nlris: None,
822 flowspec_nlris: None,
823 })]);
824 let msg = BgpUpdateMessage {
825 withdrawn_prefixes: vec![],
826 attributes: attrs,
827 announced_prefixes: vec![],
828 };
829 assert!(!msg.is_end_of_rib());
830
831 let attrs = Attributes::from_iter(vec![AttributeValue::MpReachNlri(Nlri {
833 afi: Afi::Ipv4,
834 safi: Safi::Unicast,
835 next_hop: None,
836 prefixes: vec![prefix],
837 labeled_prefixes: None,
838 link_state_nlris: None,
839 flowspec_nlris: None,
840 })]);
841 let msg = BgpUpdateMessage {
842 withdrawn_prefixes: vec![],
843 attributes: attrs,
844 announced_prefixes: vec![],
845 };
846 assert!(!msg.is_end_of_rib());
847
848 let attrs = Attributes::from_iter(vec![AttributeValue::MpUnreachNlri(Nlri {
850 afi: Afi::Ipv4,
851 safi: Safi::Unicast,
852 next_hop: None,
853 prefixes: vec![prefix],
854 labeled_prefixes: None,
855 link_state_nlris: None,
856 flowspec_nlris: None,
857 })]);
858 let msg = BgpUpdateMessage {
859 withdrawn_prefixes: vec![],
860 attributes: attrs,
861 announced_prefixes: vec![],
862 };
863 assert!(!msg.is_end_of_rib());
864
865 let attrs = Attributes::from_iter(vec![
867 AttributeValue::MpUnreachNlri(Nlri {
868 afi: Afi::Ipv4,
869 safi: Safi::Unicast,
870 next_hop: None,
871 prefixes: vec![],
872 labeled_prefixes: None,
873 link_state_nlris: None,
874 flowspec_nlris: None,
875 }),
876 AttributeValue::AtomicAggregate,
877 ]);
878 let msg = BgpUpdateMessage {
879 withdrawn_prefixes: vec![],
880 attributes: attrs,
881 announced_prefixes: vec![],
882 };
883 assert!(!msg.is_end_of_rib());
884 }
885
886 #[test]
887 fn test_invalid_length() {
888 let bytes = Bytes::from_static(&[
889 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, ]);
896 let mut data = bytes.clone();
897 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_err());
898
899 let bytes = Bytes::from_static(&[
900 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x05, ]);
907 let mut data = bytes.clone();
908 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_err());
909 }
910
911 #[test]
912 fn test_invalid_type() {
913 let bytes = Bytes::from_static(&[
914 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x28, 0x06, ]);
921 let mut data = bytes.clone();
922 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_err());
923 }
924
925 #[test]
926 fn test_parse_bgp_route_refresh_message() {
927 let bytes = Bytes::from_static(&[
930 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x17, 0x05, 0x00, 0x01, 0x00, 0x01, ]);
940 let mut data = bytes.clone();
941 let msg = parse_bgp_message(&mut data, false, &AsnLength::Bits32).unwrap();
942 let refresh = match &msg {
943 BgpMessage::RouteRefresh(refresh) => refresh,
944 _ => panic!("expected RouteRefresh, got {msg:?}"),
945 };
946 assert_eq!(msg.msg_type(), BgpMessageType::ROUTE_REFRESH);
947 assert_eq!(refresh.afi, 1);
948 assert_eq!(refresh.subtype, 0);
949 assert_eq!(refresh.safi, 1);
950 assert!(refresh.data.is_empty());
951 assert_eq!(refresh.afi(), Some(Afi::Ipv4));
952 assert_eq!(refresh.safi(), Some(Safi::Unicast));
953
954 let encoded = msg.encode(AsnLength::Bits32).unwrap();
956 assert_eq!(encoded, bytes);
957 }
958
959 #[test]
960 fn test_parse_bgp_route_refresh_message_with_orf_data() {
961 let bytes = Bytes::from_static(&[
964 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, ]);
975 let mut data = bytes.clone();
976 let msg = parse_bgp_message(&mut data, false, &AsnLength::Bits32).unwrap();
977 let refresh = match &msg {
978 BgpMessage::RouteRefresh(refresh) => refresh,
979 _ => panic!("expected RouteRefresh, got {msg:?}"),
980 };
981 assert_eq!(refresh.afi, 25);
982 assert_eq!(refresh.subtype, 1);
983 assert_eq!(refresh.safi, 65);
984 assert_eq!(refresh.data, vec![0xDE, 0xAD, 0xBE]);
985 assert_eq!(refresh.afi(), None);
986 assert_eq!(refresh.safi(), None);
987
988 let encoded = msg.encode(AsnLength::Bits32).unwrap();
989 assert_eq!(encoded, bytes);
990 }
991
992 #[test]
993 fn test_parse_bgp_route_refresh_message_unknown_subtype() {
994 let bytes = Bytes::from_static(&[
998 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x17, 0x05, 0x00, 0x01, 0x03, 0x01, ]);
1008 let mut data = bytes.clone();
1009 let msg = parse_bgp_message(&mut data, false, &AsnLength::Bits32).unwrap();
1010 let refresh = match &msg {
1011 BgpMessage::RouteRefresh(refresh) => refresh,
1012 _ => panic!("expected RouteRefresh, got {msg:?}"),
1013 };
1014 assert_eq!(refresh.afi, 1);
1015 assert_eq!(refresh.subtype, 3);
1016 assert_eq!(refresh.safi, 1);
1017 assert!(refresh.data.is_empty());
1018
1019 let encoded = msg.encode(AsnLength::Bits32).unwrap();
1020 assert_eq!(encoded, bytes);
1021 }
1022
1023 #[test]
1024 fn test_parse_bgp_route_refresh_message_truncated() {
1025 let bytes = Bytes::from_static(&[
1027 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x15, 0x05, 0x00, 0x01, ]);
1035 let mut data = bytes.clone();
1036 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits32).is_err());
1037 }
1038
1039 #[test]
1040 fn test_bgp_message_length_underflow_protection() {
1041 for len in [0u16, 1, 18] {
1044 let bytes = Bytes::from(vec![
1045 0xFF,
1046 0xFF,
1047 0xFF,
1048 0xFF, 0xFF,
1050 0xFF,
1051 0xFF,
1052 0xFF, 0xFF,
1054 0xFF,
1055 0xFF,
1056 0xFF, 0xFF,
1058 0xFF,
1059 0xFF,
1060 0xFF, (len >> 8) as u8,
1062 (len & 0xFF) as u8, 0x01, ]);
1065 let mut data = bytes.clone();
1066 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1067 assert!(
1068 result.is_err(),
1069 "Length {} should be rejected as invalid",
1070 len
1071 );
1072 }
1073 }
1074
1075 #[test]
1076 fn test_bgp_marker_encoding_rfc4271() {
1077 let msg = BgpMessage::KeepAlive;
1079 let encoded = msg.encode(AsnLength::Bits16).unwrap();
1080
1081 assert_eq!(
1083 &encoded[..16],
1084 &[0xFF; 16],
1085 "BGP marker should be all 0xFF bytes"
1086 );
1087 }
1088
1089 #[test]
1090 fn test_bgp_marker_validation() {
1091 let valid_bytes = Bytes::from(vec![
1093 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x13, 0x04, ]);
1100 let mut data = valid_bytes.clone();
1101 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1102 assert!(result.is_ok(), "Valid marker should parse successfully");
1103
1104 let invalid_bytes = Bytes::from(vec![
1107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x04, ]);
1114 let mut data = invalid_bytes.clone();
1115 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1117 assert!(
1118 result.is_ok(),
1119 "Invalid marker should still parse (with warning)"
1120 );
1121 }
1122
1123 #[test]
1124 fn test_attribute_length_overflow_protection() {
1125 let update_bytes = Bytes::from(vec![
1130 0x00, 0x00, 0xFF,
1132 0xFF, ]);
1135
1136 let result = parse_bgp_update_message(update_bytes, false, &AsnLength::Bits16);
1137 assert!(
1138 result.is_err(),
1139 "Should fail when attribute_length exceeds available data"
1140 );
1141 assert!(
1142 matches!(result, Err(ParserError::TruncatedMsg(_))),
1143 "Should fail with TruncatedMsg error"
1144 );
1145
1146 let valid_update = Bytes::from(vec![
1148 0x00, 0x00, 0x00,
1150 0x00, ]);
1153 let result = parse_bgp_update_message(valid_update, false, &AsnLength::Bits16);
1154 assert!(result.is_ok(), "Should parse valid empty UPDATE");
1155 }
1156
1157 #[test]
1158 fn test_parse_bgp_notification_message() {
1159 let bytes = Bytes::from_static(&[
1160 0x01, 0x02, 0x00, 0x00, ]);
1164 let msg = parse_bgp_notification_message(bytes).unwrap();
1165 matches!(
1166 msg.error,
1167 BgpError::MessageHeaderError(MessageHeaderError::BAD_MESSAGE_LENGTH)
1168 );
1169 assert_eq!(msg.data, Bytes::from_static(&[0x00, 0x00]));
1170 }
1171
1172 #[test]
1173 fn test_encode_bgp_notification_messsage() {
1174 let msg = BgpNotificationMessage {
1175 error: BgpError::MessageHeaderError(MessageHeaderError::BAD_MESSAGE_LENGTH),
1176 data: vec![0x00, 0x00],
1177 };
1178 let bytes = msg.encode();
1179 assert_eq!(bytes, Bytes::from_static(&[0x01, 0x02, 0x00, 0x00]));
1180 }
1181
1182 #[test]
1183 fn test_parse_bgp_open_message() {
1184 let bytes = Bytes::from_static(&[
1185 0x04, 0x00, 0x01, 0x00, 0xb4, 0xc0, 0x00, 0x02, 0x01, 0x00, ]);
1191 let msg = parse_bgp_open_message(&mut bytes.clone()).unwrap();
1192 assert_eq!(msg.version, 4);
1193 assert_eq!(msg.asn, Asn::new_16bit(1));
1194 assert_eq!(msg.hold_time, 180);
1195 assert_eq!(msg.bgp_identifier, Ipv4Addr::new(192, 0, 2, 1));
1196 assert!(!msg.extended_length);
1197 assert_eq!(msg.opt_params.len(), 0);
1198 }
1199
1200 #[test]
1201 fn test_encode_bgp_open_message() {
1202 let msg = BgpOpenMessage {
1203 version: 4,
1204 asn: Asn::new_16bit(1),
1205 hold_time: 180,
1206 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
1207 extended_length: false,
1208 opt_params: vec![],
1209 };
1210 let bytes = msg.encode().unwrap();
1211 assert_eq!(
1212 bytes,
1213 Bytes::from_static(&[
1214 0x04, 0x00, 0x01, 0x00, 0xb4, 0xc0, 0x00, 0x02, 0x01, 0x00, ])
1220 );
1221 }
1222
1223 #[test]
1224 fn test_bgp_open_wire_fixtures_round_trip_byte_identically() {
1225 let fixtures = [
1227 (
1228 "no optional parameters",
1229 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF001D01",
1230 "048826005A02380BFE00",
1231 0x00,
1232 ),
1233 (
1234 "two capability parameters",
1235 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF002501",
1236 "045BA0005A66433801080202800002020200",
1237 0x08,
1238 ),
1239 (
1240 "five capability parameters",
1241 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003901",
1242 "04947100B4CBD0B16E1C02060104000200010202800002020200020246000206410400009471",
1243 0x1C,
1244 ),
1245 (
1246 "one 22-byte capability parameter",
1247 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003501",
1248 "045BA000F05D9FBB0118021601040001000102004002007841040003215C46004700",
1249 0x18,
1250 ),
1251 (
1252 "one 26-byte capability parameter",
1253 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003901",
1254 "045BA0012CB901A6321C021A0104000100010200400600780001010041040003167D46004700",
1255 0x1C,
1256 ),
1257 ];
1258
1259 for (name, header, body, expected_opt_params_len) in fixtures {
1260 let wire = Bytes::from(hex::decode(format!("{header}{body}")).unwrap());
1261 assert_eq!(wire[28], expected_opt_params_len, "{name}");
1262
1263 let mut input = wire.clone();
1264 let parsed =
1265 parse_bgp_message(&mut input, false, &AsnLength::Bits16).unwrap_or_else(|error| {
1266 panic!("failed to parse {name}: {error}");
1267 });
1268 let encoded = parsed.encode(AsnLength::Bits16).unwrap();
1269
1270 assert_eq!(encoded, wire, "{name}");
1271 }
1272 }
1273
1274 #[test]
1275 fn test_bgp_open_encoding_recomputes_parameter_lengths() {
1276 let msg = BgpOpenMessage {
1277 version: 4,
1278 asn: Asn::new_16bit(64512),
1279 hold_time: 90,
1280 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
1281 extended_length: false,
1282 opt_params: vec![OptParam {
1283 param_type: 254,
1284 param_value: ParamValue::Raw(vec![0xAA, 0xBB, 0xCC]),
1285 }],
1286 };
1287
1288 let encoded = msg.encode().unwrap();
1289
1290 assert_eq!(encoded[9], 5);
1291 assert_eq!(&encoded[10..], &[254, 3, 0xAA, 0xBB, 0xCC]);
1292 let parsed = parse_bgp_open_message(&mut encoded.clone()).unwrap();
1293 assert_eq!(parsed.encode().unwrap(), encoded);
1294 }
1295
1296 #[test]
1297 fn test_bgp_open_encoding_rejects_oversized_add_path_capability() {
1298 use crate::models::capabilities::{AddPathAddressFamily, AddPathSendReceive};
1299
1300 let address_family = AddPathAddressFamily {
1301 afi: Afi::Ipv4,
1302 safi: Safi::Unicast,
1303 send_receive: AddPathSendReceive::SendReceive,
1304 };
1305 let msg = BgpOpenMessage {
1306 version: 4,
1307 asn: Asn::new_16bit(64512),
1308 hold_time: 90,
1309 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
1310 extended_length: false,
1311 opt_params: vec![OptParam {
1312 param_type: 2,
1313 param_value: ParamValue::Capacities(vec![Capability {
1314 ty: BgpCapabilityType::ADD_PATH_CAPABILITY,
1315 value: CapabilityValue::AddPath(AddPathCapability::new(vec![
1316 address_family;
1317 64
1318 ])),
1319 }]),
1320 }],
1321 };
1322
1323 let err = msg.encode().unwrap_err();
1324 assert_eq!(
1325 err,
1326 EncodingError::ValueTooLarge {
1327 field: "BGP capability value length",
1328 actual: 256,
1329 max: 255
1330 }
1331 );
1332 }
1333
1334 #[test]
1335 fn test_bgp_open_forced_extended_parameter_encoding() {
1336 let msg = BgpOpenMessage {
1337 version: 4,
1338 asn: Asn::new_16bit(64512),
1339 hold_time: 90,
1340 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
1341 extended_length: true,
1342 opt_params: vec![OptParam {
1343 param_type: 254,
1344 param_value: ParamValue::Raw(vec![0xAA, 0xBB]),
1345 }],
1346 };
1347
1348 let encoded = msg.encode().unwrap();
1349
1350 assert_eq!(
1351 &encoded[9..],
1352 &[0xFF, 0xFF, 0x00, 0x05, 254, 0x00, 0x02, 0xAA, 0xBB]
1353 );
1354 let parsed = parse_bgp_open_message(&mut encoded.clone()).unwrap();
1355 assert!(parsed.extended_length);
1356 assert_eq!(parsed.encode().unwrap(), encoded);
1357 }
1358
1359 #[test]
1360 fn test_bgp_open_automatically_uses_extended_parameter_encoding() {
1361 let msg = BgpOpenMessage {
1362 version: 4,
1363 asn: Asn::new_16bit(64512),
1364 hold_time: 90,
1365 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
1366 extended_length: false,
1367 opt_params: vec![OptParam {
1368 param_type: 254,
1369 param_value: ParamValue::Raw(vec![0xAA; 256]),
1370 }],
1371 };
1372
1373 let encoded = msg.encode().unwrap();
1374
1375 assert_eq!(encoded.len(), 272);
1376 assert_eq!(&encoded[9..16], &[0xFF, 0xFF, 0x01, 0x03, 254, 0x01, 0x00]);
1377 let parsed = parse_bgp_open_message(&mut encoded.clone()).unwrap();
1378 assert!(parsed.extended_length);
1379 assert_eq!(parsed.encode().unwrap(), encoded);
1380 }
1381
1382 #[test]
1383 fn test_encode_bgp_notification_message() {
1384 let bgp_message = BgpMessage::Notification(BgpNotificationMessage {
1385 error: BgpError::MessageHeaderError(MessageHeaderError::BAD_MESSAGE_LENGTH),
1386 data: vec![0x00, 0x00],
1387 });
1388 let bytes = bgp_message.encode(AsnLength::Bits16).unwrap();
1389 assert_eq!(
1391 bytes,
1392 Bytes::from_static(&[
1393 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x17, 0x03, 0x01, 0x02, 0x00, 0x00 ])
1400 );
1401 }
1402
1403 #[test]
1404 fn test_bgp_message_from_bgp_update_message() {
1405 let msg = BgpMessage::from(BgpUpdateMessage::default());
1406 assert!(matches!(msg, BgpMessage::Update(_)));
1407 }
1408
1409 #[test]
1410 fn test_parse_bgp_open_message_with_extended_next_hop_capability() {
1411 use crate::models::{Afi, Safi};
1412
1413 let bytes = Bytes::from(vec![
1419 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, ]);
1435
1436 let msg = parse_bgp_open_message(&mut bytes.clone()).unwrap();
1437 assert_eq!(msg.version, 4);
1438 assert_eq!(msg.asn, Asn::new_16bit(65001));
1439 assert_eq!(msg.hold_time, 180);
1440 assert_eq!(msg.bgp_identifier, Ipv4Addr::new(192, 0, 2, 1));
1441 assert!(!msg.extended_length);
1442 assert_eq!(msg.opt_params.len(), 1);
1443
1444 if let ParamValue::Capacities(cap) = &msg.opt_params[0].param_value {
1446 assert_eq!(cap[0].ty, BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING);
1447
1448 if let CapabilityValue::ExtendedNextHop(enh_cap) = &cap[0].value {
1449 assert_eq!(enh_cap.entries.len(), 2);
1450
1451 let entry1 = &enh_cap.entries[0];
1453 assert_eq!(entry1.nlri_afi, Afi::Ipv4);
1454 assert_eq!(entry1.nlri_safi, Safi::Unicast);
1455 assert_eq!(entry1.nexthop_afi, Afi::Ipv6);
1456
1457 let entry2 = &enh_cap.entries[1];
1459 assert_eq!(entry2.nlri_afi, Afi::Ipv4);
1460 assert_eq!(entry2.nlri_safi, Safi::MplsVpn);
1461 assert_eq!(entry2.nexthop_afi, Afi::Ipv6);
1462
1463 assert!(enh_cap.supports(Afi::Ipv4, Safi::Unicast, Afi::Ipv6));
1465 assert!(enh_cap.supports(Afi::Ipv4, Safi::MplsVpn, Afi::Ipv6));
1466 assert!(!enh_cap.supports(Afi::Ipv4, Safi::Multicast, Afi::Ipv6));
1467 } else {
1468 panic!("Expected ExtendedNextHop capability value");
1469 }
1470 } else {
1471 panic!("Expected capability parameter");
1472 }
1473 }
1474
1475 #[test]
1476 fn test_rfc8654_extended_message_length_validation() {
1477 let bytes = Bytes::from_static(&[
1479 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x00, 0x00,
1487 0x00, ]);
1490 let mut data = bytes.clone();
1491 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_ok());
1493
1494 let bytes = Bytes::from_static(&[
1496 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x01, ]);
1503 let mut data = bytes.clone();
1504 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1505 assert!(result.is_err());
1506 if let Err(ParserError::ParseError(msg)) = result {
1507 assert!(msg.contains("BGP OPEN message length"));
1508 assert!(msg.contains("4096 bytes"));
1509 }
1510
1511 let bytes = Bytes::from_static(&[
1513 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x04, ]);
1520 let mut data = bytes.clone();
1521 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1522 assert!(result.is_err());
1523 if let Err(ParserError::ParseError(msg)) = result {
1524 assert!(msg.contains("BGP KEEPALIVE message length"));
1525 assert!(msg.contains("4096 bytes"));
1526 }
1527
1528 let bytes = Bytes::from_static(&[
1530 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x02, ]);
1537 let mut data = bytes.clone();
1538 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1540 if let Err(ParserError::ParseError(msg)) = result {
1541 assert!(!msg.contains("invalid BGP message length"));
1543 }
1544 }
1545
1546 #[test]
1547 fn test_bgp_extended_message_capability_parsing() {
1548 use crate::models::CapabilityValue;
1549
1550 let bytes = Bytes::from(vec![
1552 0x04, 0x00, 0x01, 0x00, 0xb4, 0xc0, 0x00, 0x02, 0x01, 0x04, 0x02, 0x02, 0x06, 0x00, ]);
1562
1563 let msg = parse_bgp_open_message(&mut bytes.clone()).unwrap();
1564 assert_eq!(msg.version, 4);
1565 assert_eq!(msg.asn, Asn::new_16bit(1));
1566 assert_eq!(msg.opt_params.len(), 1);
1567
1568 if let ParamValue::Capacities(cap) = &msg.opt_params[0].param_value {
1570 assert_eq!(cap[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1571 if let CapabilityValue::BgpExtendedMessage(_) = &cap[0].value {
1572 } else {
1574 panic!("Expected BgpExtendedMessage capability value");
1575 }
1576 } else {
1577 panic!("Expected capability parameter");
1578 }
1579 }
1580
1581 #[test]
1582 fn test_rfc8654_edge_cases() {
1583 let bytes = Bytes::from_static(&[
1585 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x03, 0x06, 0x00, ]);
1595 let mut data = bytes.clone();
1596 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1598 if let Err(ParserError::ParseError(msg)) = result {
1600 assert!(!msg.contains("invalid BGP message length"));
1601 assert!(!msg.contains("exceeds maximum allowed 4096 bytes"));
1602 }
1603
1604 let open_data = vec![
1606 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, ];
1613 let bytes = Bytes::from(open_data);
1614 let mut data = bytes.clone();
1615 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1616 if let Err(ParserError::ParseError(msg)) = result {
1618 assert!(!msg.contains("exceeds maximum allowed 4096 bytes"));
1619 }
1620
1621 let bytes = Bytes::from_static(&[
1623 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x02, ]);
1630 let mut data = bytes.clone();
1631 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1632 if let Err(ParserError::ParseError(msg)) = result {
1634 assert!(!msg.contains("invalid BGP message length"));
1635 }
1636 }
1637
1638 #[test]
1639 fn test_rfc8654_capability_encoding_path() {
1640 use crate::models::capabilities::BgpExtendedMessageCapability;
1641
1642 let capability_value =
1645 CapabilityValue::BgpExtendedMessage(BgpExtendedMessageCapability::new());
1646 let capability = Capability {
1647 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1648 value: capability_value,
1649 };
1650
1651 let opt_param = OptParam {
1652 param_type: 2, param_value: ParamValue::Capacities(vec![capability]),
1654 };
1655
1656 let msg = BgpOpenMessage {
1657 version: 4,
1658 asn: Asn::new_16bit(65001),
1659 hold_time: 180,
1660 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
1661 extended_length: false,
1662 opt_params: vec![opt_param],
1663 };
1664
1665 let encoded = msg.encode().unwrap();
1667 assert!(!encoded.is_empty());
1668
1669 let parsed = parse_bgp_open_message(&mut encoded.clone()).unwrap();
1671 assert_eq!(parsed.opt_params.len(), 1);
1672 if let ParamValue::Capacities(cap) = &parsed.opt_params[0].param_value {
1673 assert_eq!(cap[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1674 }
1675 }
1676
1677 #[test]
1678 fn test_rfc8654_error_message_formatting() {
1679 let bytes = Bytes::from_static(&[
1684 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x01, ]);
1691 let mut data = bytes.clone();
1692 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1693 assert!(result.is_err());
1694 if let Err(ParserError::ParseError(msg)) = result {
1695 assert!(msg.contains("BGP OPEN message length"));
1696 assert!(msg.contains("exceeds maximum allowed 4096 bytes"));
1697 }
1698
1699 let bytes = Bytes::from_static(&[
1701 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x04, ]);
1708 let mut data = bytes.clone();
1709 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1710 assert!(result.is_err());
1711 if let Err(ParserError::ParseError(msg)) = result {
1712 assert!(msg.contains("BGP KEEPALIVE message length"));
1713 assert!(msg.contains("exceeds maximum allowed 4096 bytes"));
1714 }
1715 }
1716
1717 #[test]
1718 fn test_encode_bgp_open_message_with_extended_message_capability() {
1719 use crate::models::capabilities::BgpExtendedMessageCapability;
1720
1721 let extended_msg_capability = BgpExtendedMessageCapability::new();
1723
1724 let msg = BgpOpenMessage {
1725 version: 4,
1726 asn: Asn::new_16bit(65001),
1727 hold_time: 180,
1728 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
1729 extended_length: false,
1730 opt_params: vec![OptParam {
1731 param_type: 2, param_value: ParamValue::Capacities(vec![Capability {
1733 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1734 value: CapabilityValue::BgpExtendedMessage(extended_msg_capability),
1735 }]),
1736 }],
1737 };
1738
1739 let encoded = msg.encode().unwrap();
1740
1741 let parsed = parse_bgp_open_message(&mut encoded.clone()).unwrap();
1743 assert_eq!(parsed.version, msg.version);
1744 assert_eq!(parsed.asn, msg.asn);
1745 assert_eq!(parsed.hold_time, msg.hold_time);
1746 assert_eq!(parsed.bgp_identifier, msg.bgp_identifier);
1747 assert_eq!(parsed.opt_params.len(), 1);
1748
1749 if let ParamValue::Capacities(cap) = &parsed.opt_params[0].param_value {
1751 assert_eq!(cap[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1752 if let CapabilityValue::BgpExtendedMessage(_) = &cap[0].value {
1753 } else {
1755 panic!("Expected BgpExtendedMessage capability value after round trip");
1756 }
1757 } else {
1758 panic!("Expected capability parameter after round trip");
1759 }
1760 }
1761
1762 #[test]
1763 fn test_encode_bgp_open_message_with_extended_next_hop_capability() {
1764 use crate::models::capabilities::{ExtendedNextHopCapability, ExtendedNextHopEntry};
1765 use crate::models::{Afi, Safi};
1766
1767 let entries = vec![
1769 ExtendedNextHopEntry {
1770 nlri_afi: Afi::Ipv4,
1771 nlri_safi: Safi::Unicast,
1772 nexthop_afi: Afi::Ipv6,
1773 },
1774 ExtendedNextHopEntry {
1775 nlri_afi: Afi::Ipv4,
1776 nlri_safi: Safi::MplsVpn,
1777 nexthop_afi: Afi::Ipv6,
1778 },
1779 ];
1780 let enh_capability = ExtendedNextHopCapability::new(entries);
1781
1782 let msg = BgpOpenMessage {
1783 version: 4,
1784 asn: Asn::new_16bit(65001),
1785 hold_time: 180,
1786 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
1787 extended_length: false,
1788 opt_params: vec![OptParam {
1789 param_type: 2, param_value: ParamValue::Capacities(vec![Capability {
1791 ty: BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING,
1792 value: CapabilityValue::ExtendedNextHop(enh_capability),
1793 }]),
1794 }],
1795 };
1796
1797 let encoded = msg.encode().unwrap();
1798
1799 let parsed = parse_bgp_open_message(&mut encoded.clone()).unwrap();
1801 assert_eq!(parsed.version, msg.version);
1802 assert_eq!(parsed.asn, msg.asn);
1803 assert_eq!(parsed.hold_time, msg.hold_time);
1804 assert_eq!(parsed.bgp_identifier, msg.bgp_identifier);
1805 assert_eq!(parsed.extended_length, msg.extended_length);
1806 assert_eq!(parsed.opt_params.len(), 1);
1807
1808 if let ParamValue::Capacities(cap) = &parsed.opt_params[0].param_value {
1810 assert_eq!(cap[0].ty, BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING);
1811 if let CapabilityValue::ExtendedNextHop(enh_cap) = &cap[0].value {
1812 assert_eq!(enh_cap.entries.len(), 2);
1813 assert!(enh_cap.supports(Afi::Ipv4, Safi::Unicast, Afi::Ipv6));
1814 assert!(enh_cap.supports(Afi::Ipv4, Safi::MplsVpn, Afi::Ipv6));
1815 } else {
1816 panic!("Expected ExtendedNextHop capability value after round trip");
1817 }
1818 } else {
1819 panic!("Expected capability parameter after round trip");
1820 }
1821 }
1822
1823 #[test]
1824 fn test_parse_bgp_open_message_with_multiple_capabilities() {
1825 let extended_msg_cap = Capability {
1830 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1831 value: CapabilityValue::BgpExtendedMessage(BgpExtendedMessageCapability {}),
1832 };
1833
1834 let route_refresh_cap = Capability {
1835 ty: BgpCapabilityType::ROUTE_REFRESH_CAPABILITY_FOR_BGP_4,
1836 value: CapabilityValue::RouteRefresh(RouteRefreshCapability {}),
1837 };
1838
1839 let four_octet_as_cap = Capability {
1840 ty: BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY,
1841 value: CapabilityValue::FourOctetAs(FourOctetAsCapability { asn: 65536 }),
1842 };
1843
1844 let msg = BgpOpenMessage {
1846 version: 4,
1847 asn: Asn::new_32bit(65000),
1848 hold_time: 180,
1849 bgp_identifier: "10.0.0.1".parse().unwrap(),
1850 extended_length: false,
1851 opt_params: vec![OptParam {
1852 param_type: 2, param_value: ParamValue::Capacities(vec![
1854 extended_msg_cap,
1855 route_refresh_cap,
1856 four_octet_as_cap,
1857 ]),
1858 }],
1859 };
1860
1861 let encoded = msg.encode().unwrap();
1863
1864 let mut encoded_bytes = encoded.clone();
1866 let parsed = parse_bgp_open_message(&mut encoded_bytes).unwrap();
1867
1868 assert_eq!(parsed.version, 4);
1870 assert_eq!(parsed.asn, Asn::new_32bit(65000));
1871 assert_eq!(parsed.hold_time, 180);
1872 assert_eq!(
1873 parsed.bgp_identifier,
1874 "10.0.0.1".parse::<std::net::Ipv4Addr>().unwrap()
1875 );
1876 assert_eq!(parsed.opt_params.len(), 1);
1877
1878 if let ParamValue::Capacities(caps) = &parsed.opt_params[0].param_value {
1880 assert_eq!(caps.len(), 3, "Should have 3 capabilities");
1881
1882 assert_eq!(caps[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1884 assert!(matches!(
1885 caps[0].value,
1886 CapabilityValue::BgpExtendedMessage(_)
1887 ));
1888
1889 assert_eq!(
1891 caps[1].ty,
1892 BgpCapabilityType::ROUTE_REFRESH_CAPABILITY_FOR_BGP_4
1893 );
1894 assert!(matches!(caps[1].value, CapabilityValue::RouteRefresh(_)));
1895
1896 assert_eq!(
1898 caps[2].ty,
1899 BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY
1900 );
1901 if let CapabilityValue::FourOctetAs(foa) = &caps[2].value {
1902 assert_eq!(foa.asn, 65536);
1903 } else {
1904 panic!("Expected FourOctetAs capability value");
1905 }
1906 } else {
1907 panic!("Expected Capacities parameter");
1908 }
1909 }
1910
1911 #[test]
1912 fn test_parse_bgp_open_message_with_multiple_capability_parameters() {
1913 let msg = BgpOpenMessage {
1917 version: 4,
1918 asn: Asn::new_32bit(65001),
1919 hold_time: 90,
1920 bgp_identifier: "192.168.1.1".parse().unwrap(),
1921 extended_length: false,
1922 opt_params: vec![
1923 OptParam {
1924 param_type: 2, param_value: ParamValue::Capacities(vec![Capability {
1926 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1927 value: CapabilityValue::BgpExtendedMessage(BgpExtendedMessageCapability {}),
1928 }]),
1929 },
1930 OptParam {
1931 param_type: 2, param_value: ParamValue::Capacities(vec![Capability {
1933 ty: BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY,
1934 value: CapabilityValue::FourOctetAs(FourOctetAsCapability {
1935 asn: 4200000000,
1936 }),
1937 }]),
1938 },
1939 ],
1940 };
1941
1942 let encoded = msg.encode().unwrap();
1944 let mut encoded_bytes = encoded.clone();
1945 let parsed = parse_bgp_open_message(&mut encoded_bytes).unwrap();
1946
1947 assert_eq!(parsed.opt_params.len(), 2);
1949
1950 if let ParamValue::Capacities(caps) = &parsed.opt_params[0].param_value {
1952 assert_eq!(caps.len(), 1);
1953 assert_eq!(caps[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1954 } else {
1955 panic!("Expected Capacities in first parameter");
1956 }
1957
1958 if let ParamValue::Capacities(caps) = &parsed.opt_params[1].param_value {
1960 assert_eq!(caps.len(), 1);
1961 assert_eq!(
1962 caps[0].ty,
1963 BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY
1964 );
1965 if let CapabilityValue::FourOctetAs(foa) = &caps[0].value {
1966 assert_eq!(foa.asn, 4200000000);
1967 }
1968 } else {
1969 panic!("Expected Capacities in second parameter");
1970 }
1971 }
1972}