1use crate::models::*;
2use bytes::{Buf, BufMut, Bytes, BytesMut};
3use std::convert::TryFrom;
4use std::net::Ipv4Addr;
5
6use crate::error::{BgpValidationWarning, ParserError};
7use crate::models::capabilities::{
8 AddPathCapability, BgpCapabilityType, BgpExtendedMessageCapability, BgpRoleCapability,
9 ExtendedNextHopCapability, FourOctetAsCapability, GracefulRestartCapability,
10 MultiprotocolExtensionsCapability, RouteRefreshCapability,
11};
12use crate::models::error::BgpError;
13use crate::parser::bgp::attributes::parse_attributes;
14use crate::parser::{encode_nlri_prefixes, parse_nlri_list, ReadUtils};
15use log::warn;
16use zerocopy::big_endian::{U16, U32};
17use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
18
19#[derive(IntoBytes, FromBytes, KnownLayout, Immutable)]
21#[repr(C)]
22struct RawBgpOpenHeader {
23 version: u8,
24 asn: U16,
25 hold_time: U16,
26 bgp_identifier: U32,
27 opt_params_len: u8,
28}
29
30const _: () = assert!(size_of::<RawBgpOpenHeader>() == 10);
31
32pub(crate) fn read_and_validate_bgp_marker(data: &mut Bytes) -> Result<(), ParserError> {
33 data.has_n_remaining(16)?;
34
35 let mut marker = [0u8; 16];
36 data.copy_to_slice(&mut marker);
37 if marker != [0xFF; 16] {
38 warn!("BGP message marker is not all 0xFF bytes (invalid per RFC 4271)");
39 }
40
41 Ok(())
42}
43
44pub fn parse_bgp_message(
63 data: &mut Bytes,
64 add_path: bool,
65 asn_len: &AsnLength,
66) -> Result<BgpMessage, ParserError> {
67 let total_size = data.len();
68 data.has_n_remaining(19)?;
69 read_and_validate_bgp_marker(data)?;
70
71 let length = data.read_u16()?;
83
84 let max_length = 65535; if !(19..=max_length).contains(&length) {
92 return Err(ParserError::ParseError(format!(
93 "invalid BGP message length {length}"
94 )));
95 }
96
97 let length_usize = length as usize;
99 let bgp_msg_length = if length_usize > total_size {
100 total_size.saturating_sub(19)
101 } else {
102 length_usize.saturating_sub(19)
103 };
104
105 let msg_type: BgpMessageType = match BgpMessageType::try_from(data.read_u8()?) {
106 Ok(t) => t,
107 Err(_) => {
108 return Err(ParserError::ParseError(
109 "Unknown BGP Message Type".to_string(),
110 ))
111 }
112 };
113
114 match msg_type {
117 BgpMessageType::OPEN | BgpMessageType::KEEPALIVE => {
118 if length > 4096 {
119 return Err(ParserError::ParseError(format!(
120 "BGP {} message length {} exceeds maximum allowed 4096 bytes (RFC 8654)",
121 match msg_type {
122 BgpMessageType::OPEN => "OPEN",
123 BgpMessageType::KEEPALIVE => "KEEPALIVE",
124 _ => unreachable!(),
125 },
126 length
127 )));
128 }
129 }
130 BgpMessageType::UPDATE | BgpMessageType::NOTIFICATION => {
131 }
134 }
135
136 if data.remaining() != bgp_msg_length {
137 warn!(
138 "BGP message length {} does not match the actual length {} (parsing BGP message)",
139 bgp_msg_length,
140 data.remaining()
141 );
142 }
143 data.has_n_remaining(bgp_msg_length)?;
144 let mut msg_data = data.split_to(bgp_msg_length);
145
146 Ok(match msg_type {
147 BgpMessageType::OPEN => BgpMessage::Open(parse_bgp_open_message(&mut msg_data)?),
148 BgpMessageType::UPDATE => {
149 BgpMessage::Update(parse_bgp_update_message(msg_data, add_path, asn_len)?)
150 }
151 BgpMessageType::NOTIFICATION => {
152 BgpMessage::Notification(parse_bgp_notification_message(msg_data)?)
153 }
154 BgpMessageType::KEEPALIVE => BgpMessage::KeepAlive,
155 })
156}
157
158pub fn parse_bgp_notification_message(
165 mut input: Bytes,
166) -> Result<BgpNotificationMessage, ParserError> {
167 let error_code = input.read_u8()?;
168 let error_subcode = input.read_u8()?;
169
170 Ok(BgpNotificationMessage {
171 error: BgpError::new(error_code, error_subcode),
172 data: input.read_n_bytes(input.len())?,
173 })
174}
175
176impl BgpNotificationMessage {
177 pub fn encode(&self) -> Bytes {
178 let mut buf = BytesMut::new();
179 let (code, subcode) = self.error.get_codes();
180 buf.put_u8(code);
181 buf.put_u8(subcode);
182 buf.put_slice(&self.data);
183 buf.freeze()
184 }
185}
186
187pub fn parse_bgp_open_message(input: &mut Bytes) -> Result<BgpOpenMessage, ParserError> {
218 input.has_n_remaining(10)?;
219 let mut header_bytes = [0u8; 10];
220 input.copy_to_slice(&mut header_bytes);
221 let raw = RawBgpOpenHeader::ref_from_bytes(&header_bytes)
223 .expect("header_bytes is exactly 10 bytes with no alignment requirement");
224
225 let version = raw.version;
226 let asn = Asn::new_16bit(raw.asn.get());
227 let hold_time = raw.hold_time.get();
228 let bgp_identifier = Ipv4Addr::from(raw.bgp_identifier.get());
229 let mut opt_params_len: u16 = raw.opt_params_len as u16;
230
231 let mut extended_length = false;
232 let mut first = true;
233
234 let mut params: Vec<OptParam> = vec![];
235 while input.remaining() >= 2 {
236 let mut param_type = input.read_u8()?;
237 if first {
238 if opt_params_len == 0 && param_type == 255 {
239 return Err(ParserError::ParseError(
240 "RFC 9072 violation: Non-Extended Optional Parameters Length must not be 0 when using extended format".to_string()
241 ));
242 }
243 if opt_params_len != 0 && param_type == 255 {
245 extended_length = true;
267 opt_params_len = input.read_u16()?;
268 if opt_params_len == 0 {
269 break;
270 }
271 if input.remaining() != opt_params_len as usize {
273 warn!(
274 "BGP open message length {} does not match the actual length {} (parsing BGP OPEN message)",
275 opt_params_len,
276 input.remaining()
277 );
278 }
279
280 param_type = input.read_u8()?;
281 }
282 first = false;
283 }
284 let param_len = match extended_length {
287 true => input.read_u16()?,
288 false => input.read_u8()? as u16,
289 };
290
291 let param_value = match param_type {
295 2 => {
296 let mut capacities = vec![];
297
298 input.has_n_remaining(param_len as usize)?;
300 let mut param_data = input.split_to(param_len as usize);
301
302 while param_data.remaining() >= 2 {
303 let code = param_data.read_u8()?;
306 let len = param_data.read_u8()? as u16; let capability_data = param_data.read_n_bytes(len as usize)?;
309 let capability_type = BgpCapabilityType::from(code);
310
311 macro_rules! parse_capability {
313 ($parser:path, $variant:ident) => {
314 match $parser(Bytes::from(capability_data.clone())) {
315 Ok(parsed) => CapabilityValue::$variant(parsed),
316 Err(_) => CapabilityValue::Raw(capability_data),
317 }
318 };
319 }
320
321 let capability_value = match capability_type {
322 BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4 => {
323 parse_capability!(
324 MultiprotocolExtensionsCapability::parse,
325 MultiprotocolExtensions
326 )
327 }
328 BgpCapabilityType::ROUTE_REFRESH_CAPABILITY_FOR_BGP_4 => {
329 parse_capability!(RouteRefreshCapability::parse, RouteRefresh)
330 }
331 BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING => {
332 parse_capability!(ExtendedNextHopCapability::parse, ExtendedNextHop)
333 }
334 BgpCapabilityType::GRACEFUL_RESTART_CAPABILITY => {
335 parse_capability!(GracefulRestartCapability::parse, GracefulRestart)
336 }
337 BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY => {
338 parse_capability!(FourOctetAsCapability::parse, FourOctetAs)
339 }
340 BgpCapabilityType::ADD_PATH_CAPABILITY => {
341 parse_capability!(AddPathCapability::parse, AddPath)
342 }
343 BgpCapabilityType::BGP_ROLE => {
344 parse_capability!(BgpRoleCapability::parse, BgpRole)
345 }
346 BgpCapabilityType::BGP_EXTENDED_MESSAGE => {
347 parse_capability!(
348 BgpExtendedMessageCapability::parse,
349 BgpExtendedMessage
350 )
351 }
352 _ => CapabilityValue::Raw(capability_data),
353 };
354
355 capacities.push(Capability {
356 ty: capability_type,
357 value: capability_value,
358 });
359 }
360
361 ParamValue::Capacities(capacities)
362 }
363 _ => {
364 let bytes = input.read_n_bytes(param_len as usize)?;
366 ParamValue::Raw(bytes)
367 }
368 };
369 params.push(OptParam {
370 param_type,
371 param_len,
372 param_value,
373 });
374 }
375
376 Ok(BgpOpenMessage {
377 version,
378 asn,
379 hold_time,
380 bgp_identifier,
381 extended_length,
382 opt_params: params,
383 })
384}
385
386impl BgpOpenMessage {
387 pub fn encode(&self) -> Bytes {
388 let mut buf = BytesMut::new();
389 let raw_header = RawBgpOpenHeader {
390 version: self.version,
391 asn: U16::new(self.asn.into()),
392 hold_time: U16::new(self.hold_time),
393 bgp_identifier: U32::new(u32::from(self.bgp_identifier)),
394 opt_params_len: self.opt_params.len() as u8,
395 };
396 buf.extend_from_slice(raw_header.as_bytes());
397 for param in &self.opt_params {
398 buf.put_u8(param.param_type);
399 buf.put_u8(param.param_len as u8);
400 match ¶m.param_value {
401 ParamValue::Capacities(capacities) => {
402 for cap in capacities {
403 buf.put_u8(cap.ty.into());
404 let encoded_value = match &cap.value {
405 CapabilityValue::MultiprotocolExtensions(mp) => mp.encode(),
406 CapabilityValue::RouteRefresh(rr) => rr.encode(),
407 CapabilityValue::ExtendedNextHop(enh) => enh.encode(),
408 CapabilityValue::GracefulRestart(gr) => gr.encode(),
409 CapabilityValue::FourOctetAs(foa) => foa.encode(),
410 CapabilityValue::AddPath(ap) => ap.encode(),
411 CapabilityValue::BgpRole(br) => br.encode(),
412 CapabilityValue::BgpExtendedMessage(bem) => bem.encode(),
413 CapabilityValue::Raw(raw) => Bytes::from(raw.clone()),
414 };
415 buf.put_u8(encoded_value.len() as u8);
416 buf.extend(&encoded_value);
417 }
418 }
419 ParamValue::Raw(bytes) => {
420 buf.extend(bytes);
421 }
422 }
423 }
424 buf.freeze()
425 }
426}
427
428fn read_nlri(input: Bytes, afi: &Afi, add_path: bool) -> Result<Vec<NetworkPrefix>, ParserError> {
434 let length = input.len();
435 if length == 0 {
436 return Ok(vec![]);
437 }
438 if length == 1 && input[0] != 0 {
439 warn!("seeing strange one-byte NLRI field (parsing NLRI in BGP UPDATE message)");
442 return Err(ParserError::ParseError(
443 "one-byte NLRI field with non-zero value is not a valid encoding".to_string(),
444 ));
445 }
446
447 parse_nlri_list(input, add_path, afi)
448}
449
450pub fn parse_bgp_update_message(
460 mut input: Bytes,
461 add_path: bool,
462 asn_len: &AsnLength,
463) -> Result<BgpUpdateMessage, ParserError> {
464 let afi = Afi::Ipv4;
466
467 let withdrawn_bytes_length_raw = input.read_u16()?;
469 let withdrawn_bytes_length = withdrawn_bytes_length_raw as usize;
470 input.has_n_remaining(withdrawn_bytes_length)?;
471 let withdrawn_bytes = input.split_to(withdrawn_bytes_length);
472 let (withdrawn_prefixes, withdrawn_nlri_error) =
473 match read_nlri(withdrawn_bytes.clone(), &afi, add_path) {
474 Ok(pfxs) => (pfxs, None),
475 Err(e) => (
476 Vec::new(),
477 Some(BgpValidationWarning::MalformedNlri {
478 nlri_type: "withdrawn",
479 reason: e.to_string(),
480 raw_bytes: withdrawn_bytes.to_vec(),
481 }),
482 ),
483 };
484
485 let attribute_length_raw = input.read_u16()?;
487 let attribute_length = attribute_length_raw as usize;
491
492 input.has_n_remaining(attribute_length)?;
493 let attr_data_slice = input.split_to(attribute_length);
494 let mut attributes = parse_attributes(attr_data_slice, asn_len, add_path, None, None, None)?;
495
496 let announced_bytes_present = !input.is_empty();
499 let (announced_prefixes, announced_nlri_error) = match read_nlri(input.clone(), &afi, add_path)
500 {
501 Ok(pfxs) => (pfxs, None),
502 Err(e) => (
503 Vec::new(),
504 Some(BgpValidationWarning::MalformedNlri {
505 nlri_type: "announced",
506 reason: e.to_string(),
507 raw_bytes: input.to_vec(),
508 }),
509 ),
510 };
511
512 let is_announcement =
518 announced_bytes_present || attributes.has_attr(AttrType::MP_REACHABLE_NLRI);
519 let has_standard_nlri = announced_bytes_present;
520 attributes.check_mandatory_attributes(is_announcement, has_standard_nlri);
521
522 if let Some(w) = withdrawn_nlri_error {
524 attributes.add_validation_warning(w);
525 }
526 if let Some(w) = announced_nlri_error {
527 attributes.add_validation_warning(w);
528 }
529
530 Ok(BgpUpdateMessage {
531 withdrawn_prefixes,
532 attributes,
533 announced_prefixes,
534 })
535}
536
537impl BgpUpdateMessage {
538 pub fn encode(&self, asn_len: AsnLength) -> Bytes {
539 let mut bytes = BytesMut::new();
540
541 let withdrawn_bytes = encode_nlri_prefixes(&self.withdrawn_prefixes);
543 bytes.put_u16(withdrawn_bytes.len() as u16);
544 bytes.put_slice(&withdrawn_bytes);
545
546 let attr_bytes = self.attributes.encode(asn_len);
548
549 bytes.put_u16(attr_bytes.len() as u16);
550 bytes.put_slice(&attr_bytes);
551
552 bytes.extend(encode_nlri_prefixes(&self.announced_prefixes));
553 bytes.freeze()
554 }
555
556 pub fn is_end_of_rib(&self) -> bool {
561 if !self.announced_prefixes.is_empty() || !self.withdrawn_prefixes.is_empty() {
566 return false;
570 }
571
572 if self.attributes.inner.is_empty() {
573 return true;
576 }
577
578 if self.attributes.inner.len() > 1 {
581 return false;
583 }
584
585 if let AttributeValue::MpUnreachNlri(nlri) = &self.attributes.inner.first().unwrap().value {
587 if nlri.prefixes.is_empty() {
588 return true;
591 }
592 }
593
594 false
596 }
597}
598
599impl BgpMessage {
600 const MARKER: [u8; 16] = [0xFF; 16];
602
603 pub fn encode(&self, asn_len: AsnLength) -> Bytes {
604 let mut bytes = BytesMut::new();
605 bytes.put_slice(&Self::MARKER);
607
608 let (msg_type, msg_bytes) = match self {
609 BgpMessage::Open(msg) => (BgpMessageType::OPEN, msg.encode()),
610 BgpMessage::Update(msg) => (BgpMessageType::UPDATE, msg.encode(asn_len)),
611 BgpMessage::Notification(msg) => (BgpMessageType::NOTIFICATION, msg.encode()),
612 BgpMessage::KeepAlive => (BgpMessageType::KEEPALIVE, Bytes::new()),
613 };
614
615 bytes.put_u16(msg_bytes.len() as u16 + 16 + 2 + 1);
617 bytes.put_u8(msg_type as u8);
618 bytes.put_slice(&msg_bytes);
619 bytes.freeze()
620 }
621}
622
623impl From<&BgpElem> for BgpUpdateMessage {
624 fn from(elem: &BgpElem) -> Self {
625 BgpUpdateMessage {
626 withdrawn_prefixes: vec![],
627 attributes: Attributes::from(elem),
628 announced_prefixes: vec![],
629 }
630 }
631}
632
633impl From<BgpUpdateMessage> for BgpMessage {
634 fn from(value: BgpUpdateMessage) -> Self {
635 BgpMessage::Update(value)
636 }
637}
638
639#[cfg(test)]
640mod tests {
641 use super::*;
642 use std::net::Ipv4Addr;
643 use std::str::FromStr;
644
645 #[test]
646 fn test_end_of_rib() {
647 let attrs = Attributes::default();
649 let msg = BgpUpdateMessage {
650 withdrawn_prefixes: vec![],
651 attributes: attrs,
652 announced_prefixes: vec![],
653 };
654 assert!(msg.is_end_of_rib());
655
656 let attrs = Attributes::from_iter(vec![AttributeValue::MpUnreachNlri(Nlri {
658 afi: Afi::Ipv4,
659 safi: Safi::Unicast,
660 next_hop: None,
661 prefixes: vec![],
662 labeled_prefixes: None,
663 link_state_nlris: None,
664 flowspec_nlris: None,
665 })]);
666 let msg = BgpUpdateMessage {
667 withdrawn_prefixes: vec![],
668 attributes: attrs,
669 announced_prefixes: vec![],
670 };
671 assert!(msg.is_end_of_rib());
672
673 let prefix = NetworkPrefix::from_str("192.168.1.0/24").unwrap();
675 let attrs = Attributes::default();
676 let msg = BgpUpdateMessage {
677 withdrawn_prefixes: vec![],
678 attributes: attrs,
679 announced_prefixes: vec![prefix],
680 };
681 assert!(!msg.is_end_of_rib());
682
683 let prefix = NetworkPrefix::from_str("192.168.1.0/24").unwrap();
685 let attrs = Attributes::default();
686 let msg = BgpUpdateMessage {
687 withdrawn_prefixes: vec![prefix],
688 attributes: attrs,
689 announced_prefixes: vec![],
690 };
691 assert!(!msg.is_end_of_rib());
692
693 let attrs = Attributes::from_iter(vec![AttributeValue::MpReachNlri(Nlri {
695 afi: Afi::Ipv4,
696 safi: Safi::Unicast,
697 next_hop: None,
698 prefixes: vec![],
699 labeled_prefixes: None,
700 link_state_nlris: None,
701 flowspec_nlris: None,
702 })]);
703 let msg = BgpUpdateMessage {
704 withdrawn_prefixes: vec![],
705 attributes: attrs,
706 announced_prefixes: vec![],
707 };
708 assert!(!msg.is_end_of_rib());
709
710 let attrs = Attributes::from_iter(vec![AttributeValue::MpReachNlri(Nlri {
712 afi: Afi::Ipv4,
713 safi: Safi::Unicast,
714 next_hop: None,
715 prefixes: vec![prefix],
716 labeled_prefixes: None,
717 link_state_nlris: None,
718 flowspec_nlris: None,
719 })]);
720 let msg = BgpUpdateMessage {
721 withdrawn_prefixes: vec![],
722 attributes: attrs,
723 announced_prefixes: vec![],
724 };
725 assert!(!msg.is_end_of_rib());
726
727 let attrs = Attributes::from_iter(vec![AttributeValue::MpUnreachNlri(Nlri {
729 afi: Afi::Ipv4,
730 safi: Safi::Unicast,
731 next_hop: None,
732 prefixes: vec![prefix],
733 labeled_prefixes: None,
734 link_state_nlris: None,
735 flowspec_nlris: None,
736 })]);
737 let msg = BgpUpdateMessage {
738 withdrawn_prefixes: vec![],
739 attributes: attrs,
740 announced_prefixes: vec![],
741 };
742 assert!(!msg.is_end_of_rib());
743
744 let attrs = Attributes::from_iter(vec![
746 AttributeValue::MpUnreachNlri(Nlri {
747 afi: Afi::Ipv4,
748 safi: Safi::Unicast,
749 next_hop: None,
750 prefixes: vec![],
751 labeled_prefixes: None,
752 link_state_nlris: None,
753 flowspec_nlris: None,
754 }),
755 AttributeValue::AtomicAggregate,
756 ]);
757 let msg = BgpUpdateMessage {
758 withdrawn_prefixes: vec![],
759 attributes: attrs,
760 announced_prefixes: vec![],
761 };
762 assert!(!msg.is_end_of_rib());
763 }
764
765 #[test]
766 fn test_invlaid_length() {
767 let bytes = Bytes::from_static(&[
768 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, ]);
775 let mut data = bytes.clone();
776 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_err());
777
778 let bytes = Bytes::from_static(&[
779 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x05, ]);
786 let mut data = bytes.clone();
787 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_err());
788 }
789
790 #[test]
791 fn test_invlaid_type() {
792 let bytes = Bytes::from_static(&[
793 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x28, 0x05, ]);
800 let mut data = bytes.clone();
801 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_err());
802 }
803
804 #[test]
805 fn test_bgp_message_length_underflow_protection() {
806 for len in [0u16, 1, 18] {
809 let bytes = Bytes::from(vec![
810 0xFF,
811 0xFF,
812 0xFF,
813 0xFF, 0xFF,
815 0xFF,
816 0xFF,
817 0xFF, 0xFF,
819 0xFF,
820 0xFF,
821 0xFF, 0xFF,
823 0xFF,
824 0xFF,
825 0xFF, (len >> 8) as u8,
827 (len & 0xFF) as u8, 0x01, ]);
830 let mut data = bytes.clone();
831 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
832 assert!(
833 result.is_err(),
834 "Length {} should be rejected as invalid",
835 len
836 );
837 }
838 }
839
840 #[test]
841 fn test_bgp_marker_encoding_rfc4271() {
842 let msg = BgpMessage::KeepAlive;
844 let encoded = msg.encode(AsnLength::Bits16);
845
846 assert_eq!(
848 &encoded[..16],
849 &[0xFF; 16],
850 "BGP marker should be all 0xFF bytes"
851 );
852 }
853
854 #[test]
855 fn test_bgp_marker_validation() {
856 let valid_bytes = Bytes::from(vec![
858 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x13, 0x04, ]);
865 let mut data = valid_bytes.clone();
866 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
867 assert!(result.is_ok(), "Valid marker should parse successfully");
868
869 let invalid_bytes = Bytes::from(vec![
872 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x04, ]);
879 let mut data = invalid_bytes.clone();
880 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
882 assert!(
883 result.is_ok(),
884 "Invalid marker should still parse (with warning)"
885 );
886 }
887
888 #[test]
889 fn test_attribute_length_overflow_protection() {
890 let update_bytes = Bytes::from(vec![
895 0x00, 0x00, 0xFF,
897 0xFF, ]);
900
901 let result = parse_bgp_update_message(update_bytes, false, &AsnLength::Bits16);
902 assert!(
903 result.is_err(),
904 "Should fail when attribute_length exceeds available data"
905 );
906 assert!(
907 matches!(result, Err(ParserError::TruncatedMsg(_))),
908 "Should fail with TruncatedMsg error"
909 );
910
911 let valid_update = Bytes::from(vec![
913 0x00, 0x00, 0x00,
915 0x00, ]);
918 let result = parse_bgp_update_message(valid_update, false, &AsnLength::Bits16);
919 assert!(result.is_ok(), "Should parse valid empty UPDATE");
920 }
921
922 #[test]
923 fn test_parse_bgp_notification_message() {
924 let bytes = Bytes::from_static(&[
925 0x01, 0x02, 0x00, 0x00, ]);
929 let msg = parse_bgp_notification_message(bytes).unwrap();
930 matches!(
931 msg.error,
932 BgpError::MessageHeaderError(MessageHeaderError::BAD_MESSAGE_LENGTH)
933 );
934 assert_eq!(msg.data, Bytes::from_static(&[0x00, 0x00]));
935 }
936
937 #[test]
938 fn test_encode_bgp_notification_messsage() {
939 let msg = BgpNotificationMessage {
940 error: BgpError::MessageHeaderError(MessageHeaderError::BAD_MESSAGE_LENGTH),
941 data: vec![0x00, 0x00],
942 };
943 let bytes = msg.encode();
944 assert_eq!(bytes, Bytes::from_static(&[0x01, 0x02, 0x00, 0x00]));
945 }
946
947 #[test]
948 fn test_parse_bgp_open_message() {
949 let bytes = Bytes::from_static(&[
950 0x04, 0x00, 0x01, 0x00, 0xb4, 0xc0, 0x00, 0x02, 0x01, 0x00, ]);
956 let msg = parse_bgp_open_message(&mut bytes.clone()).unwrap();
957 assert_eq!(msg.version, 4);
958 assert_eq!(msg.asn, Asn::new_16bit(1));
959 assert_eq!(msg.hold_time, 180);
960 assert_eq!(msg.bgp_identifier, Ipv4Addr::new(192, 0, 2, 1));
961 assert!(!msg.extended_length);
962 assert_eq!(msg.opt_params.len(), 0);
963 }
964
965 #[test]
966 fn test_encode_bgp_open_message() {
967 let msg = BgpOpenMessage {
968 version: 4,
969 asn: Asn::new_16bit(1),
970 hold_time: 180,
971 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
972 extended_length: false,
973 opt_params: vec![],
974 };
975 let bytes = msg.encode();
976 assert_eq!(
977 bytes,
978 Bytes::from_static(&[
979 0x04, 0x00, 0x01, 0x00, 0xb4, 0xc0, 0x00, 0x02, 0x01, 0x00, ])
985 );
986 }
987
988 #[test]
989 fn test_encode_bgp_notification_message() {
990 let bgp_message = BgpMessage::Notification(BgpNotificationMessage {
991 error: BgpError::MessageHeaderError(MessageHeaderError::BAD_MESSAGE_LENGTH),
992 data: vec![0x00, 0x00],
993 });
994 let bytes = bgp_message.encode(AsnLength::Bits16);
995 assert_eq!(
997 bytes,
998 Bytes::from_static(&[
999 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x17, 0x03, 0x01, 0x02, 0x00, 0x00 ])
1006 );
1007 }
1008
1009 #[test]
1010 fn test_bgp_message_from_bgp_update_message() {
1011 let msg = BgpMessage::from(BgpUpdateMessage::default());
1012 assert!(matches!(msg, BgpMessage::Update(_)));
1013 }
1014
1015 #[test]
1016 fn test_parse_bgp_open_message_with_extended_next_hop_capability() {
1017 use crate::models::{Afi, Safi};
1018
1019 let bytes = Bytes::from(vec![
1025 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, ]);
1041
1042 let msg = parse_bgp_open_message(&mut bytes.clone()).unwrap();
1043 assert_eq!(msg.version, 4);
1044 assert_eq!(msg.asn, Asn::new_16bit(65001));
1045 assert_eq!(msg.hold_time, 180);
1046 assert_eq!(msg.bgp_identifier, Ipv4Addr::new(192, 0, 2, 1));
1047 assert!(!msg.extended_length);
1048 assert_eq!(msg.opt_params.len(), 1);
1049
1050 if let ParamValue::Capacities(cap) = &msg.opt_params[0].param_value {
1052 assert_eq!(cap[0].ty, BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING);
1053
1054 if let CapabilityValue::ExtendedNextHop(enh_cap) = &cap[0].value {
1055 assert_eq!(enh_cap.entries.len(), 2);
1056
1057 let entry1 = &enh_cap.entries[0];
1059 assert_eq!(entry1.nlri_afi, Afi::Ipv4);
1060 assert_eq!(entry1.nlri_safi, Safi::Unicast);
1061 assert_eq!(entry1.nexthop_afi, Afi::Ipv6);
1062
1063 let entry2 = &enh_cap.entries[1];
1065 assert_eq!(entry2.nlri_afi, Afi::Ipv4);
1066 assert_eq!(entry2.nlri_safi, Safi::MplsVpn);
1067 assert_eq!(entry2.nexthop_afi, Afi::Ipv6);
1068
1069 assert!(enh_cap.supports(Afi::Ipv4, Safi::Unicast, Afi::Ipv6));
1071 assert!(enh_cap.supports(Afi::Ipv4, Safi::MplsVpn, Afi::Ipv6));
1072 assert!(!enh_cap.supports(Afi::Ipv4, Safi::Multicast, Afi::Ipv6));
1073 } else {
1074 panic!("Expected ExtendedNextHop capability value");
1075 }
1076 } else {
1077 panic!("Expected capability parameter");
1078 }
1079 }
1080
1081 #[test]
1082 fn test_rfc8654_extended_message_length_validation() {
1083 let bytes = Bytes::from_static(&[
1085 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x00, 0x00,
1093 0x00, ]);
1096 let mut data = bytes.clone();
1097 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_ok());
1099
1100 let bytes = Bytes::from_static(&[
1102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x01, ]);
1109 let mut data = bytes.clone();
1110 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1111 assert!(result.is_err());
1112 if let Err(ParserError::ParseError(msg)) = result {
1113 assert!(msg.contains("BGP OPEN message length"));
1114 assert!(msg.contains("4096 bytes"));
1115 }
1116
1117 let bytes = Bytes::from_static(&[
1119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x04, ]);
1126 let mut data = bytes.clone();
1127 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1128 assert!(result.is_err());
1129 if let Err(ParserError::ParseError(msg)) = result {
1130 assert!(msg.contains("BGP KEEPALIVE message length"));
1131 assert!(msg.contains("4096 bytes"));
1132 }
1133
1134 let bytes = Bytes::from_static(&[
1136 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x02, ]);
1143 let mut data = bytes.clone();
1144 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1146 if let Err(ParserError::ParseError(msg)) = result {
1147 assert!(!msg.contains("invalid BGP message length"));
1149 }
1150 }
1151
1152 #[test]
1153 fn test_bgp_extended_message_capability_parsing() {
1154 use crate::models::CapabilityValue;
1155
1156 let bytes = Bytes::from(vec![
1158 0x04, 0x00, 0x01, 0x00, 0xb4, 0xc0, 0x00, 0x02, 0x01, 0x04, 0x02, 0x02, 0x06, 0x00, ]);
1168
1169 let msg = parse_bgp_open_message(&mut bytes.clone()).unwrap();
1170 assert_eq!(msg.version, 4);
1171 assert_eq!(msg.asn, Asn::new_16bit(1));
1172 assert_eq!(msg.opt_params.len(), 1);
1173
1174 if let ParamValue::Capacities(cap) = &msg.opt_params[0].param_value {
1176 assert_eq!(cap[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1177 if let CapabilityValue::BgpExtendedMessage(_) = &cap[0].value {
1178 } else {
1180 panic!("Expected BgpExtendedMessage capability value");
1181 }
1182 } else {
1183 panic!("Expected capability parameter");
1184 }
1185 }
1186
1187 #[test]
1188 fn test_rfc8654_edge_cases() {
1189 let bytes = Bytes::from_static(&[
1191 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x03, 0x06, 0x00, ]);
1201 let mut data = bytes.clone();
1202 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1204 if let Err(ParserError::ParseError(msg)) = result {
1206 assert!(!msg.contains("invalid BGP message length"));
1207 assert!(!msg.contains("exceeds maximum allowed 4096 bytes"));
1208 }
1209
1210 let open_data = vec![
1212 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, ];
1219 let bytes = Bytes::from(open_data);
1220 let mut data = bytes.clone();
1221 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1222 if let Err(ParserError::ParseError(msg)) = result {
1224 assert!(!msg.contains("exceeds maximum allowed 4096 bytes"));
1225 }
1226
1227 let bytes = Bytes::from_static(&[
1229 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x02, ]);
1236 let mut data = bytes.clone();
1237 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1238 if let Err(ParserError::ParseError(msg)) = result {
1240 assert!(!msg.contains("invalid BGP message length"));
1241 }
1242 }
1243
1244 #[test]
1245 fn test_rfc8654_capability_encoding_path() {
1246 use crate::models::capabilities::BgpExtendedMessageCapability;
1247
1248 let capability_value =
1251 CapabilityValue::BgpExtendedMessage(BgpExtendedMessageCapability::new());
1252 let capability = Capability {
1253 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1254 value: capability_value,
1255 };
1256
1257 let opt_param = OptParam {
1258 param_type: 2, param_len: 2,
1260 param_value: ParamValue::Capacities(vec![capability]),
1261 };
1262
1263 let msg = BgpOpenMessage {
1264 version: 4,
1265 asn: Asn::new_16bit(65001),
1266 hold_time: 180,
1267 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
1268 extended_length: false,
1269 opt_params: vec![opt_param],
1270 };
1271
1272 let encoded = msg.encode();
1274 assert!(!encoded.is_empty());
1275
1276 let parsed = parse_bgp_open_message(&mut encoded.clone()).unwrap();
1278 assert_eq!(parsed.opt_params.len(), 1);
1279 if let ParamValue::Capacities(cap) = &parsed.opt_params[0].param_value {
1280 assert_eq!(cap[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1281 }
1282 }
1283
1284 #[test]
1285 fn test_rfc8654_error_message_formatting() {
1286 let bytes = Bytes::from_static(&[
1291 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x01, ]);
1298 let mut data = bytes.clone();
1299 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1300 assert!(result.is_err());
1301 if let Err(ParserError::ParseError(msg)) = result {
1302 assert!(msg.contains("BGP OPEN message length"));
1303 assert!(msg.contains("exceeds maximum allowed 4096 bytes"));
1304 }
1305
1306 let bytes = Bytes::from_static(&[
1308 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x04, ]);
1315 let mut data = bytes.clone();
1316 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1317 assert!(result.is_err());
1318 if let Err(ParserError::ParseError(msg)) = result {
1319 assert!(msg.contains("BGP KEEPALIVE message length"));
1320 assert!(msg.contains("exceeds maximum allowed 4096 bytes"));
1321 }
1322 }
1323
1324 #[test]
1325 fn test_encode_bgp_open_message_with_extended_message_capability() {
1326 use crate::models::capabilities::BgpExtendedMessageCapability;
1327
1328 let extended_msg_capability = BgpExtendedMessageCapability::new();
1330
1331 let msg = BgpOpenMessage {
1332 version: 4,
1333 asn: Asn::new_16bit(65001),
1334 hold_time: 180,
1335 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
1336 extended_length: false,
1337 opt_params: vec![OptParam {
1338 param_type: 2, param_len: 2, param_value: ParamValue::Capacities(vec![Capability {
1341 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1342 value: CapabilityValue::BgpExtendedMessage(extended_msg_capability),
1343 }]),
1344 }],
1345 };
1346
1347 let encoded = msg.encode();
1348
1349 let parsed = parse_bgp_open_message(&mut encoded.clone()).unwrap();
1351 assert_eq!(parsed.version, msg.version);
1352 assert_eq!(parsed.asn, msg.asn);
1353 assert_eq!(parsed.hold_time, msg.hold_time);
1354 assert_eq!(parsed.bgp_identifier, msg.bgp_identifier);
1355 assert_eq!(parsed.opt_params.len(), 1);
1356
1357 if let ParamValue::Capacities(cap) = &parsed.opt_params[0].param_value {
1359 assert_eq!(cap[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1360 if let CapabilityValue::BgpExtendedMessage(_) = &cap[0].value {
1361 } else {
1363 panic!("Expected BgpExtendedMessage capability value after round trip");
1364 }
1365 } else {
1366 panic!("Expected capability parameter after round trip");
1367 }
1368 }
1369
1370 #[test]
1371 fn test_encode_bgp_open_message_with_extended_next_hop_capability() {
1372 use crate::models::capabilities::{ExtendedNextHopCapability, ExtendedNextHopEntry};
1373 use crate::models::{Afi, Safi};
1374
1375 let entries = vec![
1377 ExtendedNextHopEntry {
1378 nlri_afi: Afi::Ipv4,
1379 nlri_safi: Safi::Unicast,
1380 nexthop_afi: Afi::Ipv6,
1381 },
1382 ExtendedNextHopEntry {
1383 nlri_afi: Afi::Ipv4,
1384 nlri_safi: Safi::MplsVpn,
1385 nexthop_afi: Afi::Ipv6,
1386 },
1387 ];
1388 let enh_capability = ExtendedNextHopCapability::new(entries);
1389
1390 let msg = BgpOpenMessage {
1391 version: 4,
1392 asn: Asn::new_16bit(65001),
1393 hold_time: 180,
1394 bgp_identifier: Ipv4Addr::new(192, 0, 2, 1),
1395 extended_length: false,
1396 opt_params: vec![OptParam {
1397 param_type: 2, param_len: 14, param_value: ParamValue::Capacities(vec![Capability {
1400 ty: BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING,
1401 value: CapabilityValue::ExtendedNextHop(enh_capability),
1402 }]),
1403 }],
1404 };
1405
1406 let encoded = msg.encode();
1407
1408 let parsed = parse_bgp_open_message(&mut encoded.clone()).unwrap();
1410 assert_eq!(parsed.version, msg.version);
1411 assert_eq!(parsed.asn, msg.asn);
1412 assert_eq!(parsed.hold_time, msg.hold_time);
1413 assert_eq!(parsed.bgp_identifier, msg.bgp_identifier);
1414 assert_eq!(parsed.extended_length, msg.extended_length);
1415 assert_eq!(parsed.opt_params.len(), 1);
1416
1417 if let ParamValue::Capacities(cap) = &parsed.opt_params[0].param_value {
1419 assert_eq!(cap[0].ty, BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING);
1420 if let CapabilityValue::ExtendedNextHop(enh_cap) = &cap[0].value {
1421 assert_eq!(enh_cap.entries.len(), 2);
1422 assert!(enh_cap.supports(Afi::Ipv4, Safi::Unicast, Afi::Ipv6));
1423 assert!(enh_cap.supports(Afi::Ipv4, Safi::MplsVpn, Afi::Ipv6));
1424 } else {
1425 panic!("Expected ExtendedNextHop capability value after round trip");
1426 }
1427 } else {
1428 panic!("Expected capability parameter after round trip");
1429 }
1430 }
1431
1432 #[test]
1433 fn test_parse_bgp_open_message_with_multiple_capabilities() {
1434 let extended_msg_cap = Capability {
1439 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1440 value: CapabilityValue::BgpExtendedMessage(BgpExtendedMessageCapability {}),
1441 };
1442
1443 let route_refresh_cap = Capability {
1444 ty: BgpCapabilityType::ROUTE_REFRESH_CAPABILITY_FOR_BGP_4,
1445 value: CapabilityValue::RouteRefresh(RouteRefreshCapability {}),
1446 };
1447
1448 let four_octet_as_cap = Capability {
1449 ty: BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY,
1450 value: CapabilityValue::FourOctetAs(FourOctetAsCapability { asn: 65536 }),
1451 };
1452
1453 let msg = BgpOpenMessage {
1455 version: 4,
1456 asn: Asn::new_32bit(65000),
1457 hold_time: 180,
1458 bgp_identifier: "10.0.0.1".parse().unwrap(),
1459 extended_length: false,
1460 opt_params: vec![OptParam {
1461 param_type: 2, param_len: 10, param_value: ParamValue::Capacities(vec![
1464 extended_msg_cap,
1465 route_refresh_cap,
1466 four_octet_as_cap,
1467 ]),
1468 }],
1469 };
1470
1471 let encoded = msg.encode();
1473
1474 let mut encoded_bytes = encoded.clone();
1476 let parsed = parse_bgp_open_message(&mut encoded_bytes).unwrap();
1477
1478 assert_eq!(parsed.version, 4);
1480 assert_eq!(parsed.asn, Asn::new_32bit(65000));
1481 assert_eq!(parsed.hold_time, 180);
1482 assert_eq!(
1483 parsed.bgp_identifier,
1484 "10.0.0.1".parse::<std::net::Ipv4Addr>().unwrap()
1485 );
1486 assert_eq!(parsed.opt_params.len(), 1);
1487
1488 if let ParamValue::Capacities(caps) = &parsed.opt_params[0].param_value {
1490 assert_eq!(caps.len(), 3, "Should have 3 capabilities");
1491
1492 assert_eq!(caps[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1494 assert!(matches!(
1495 caps[0].value,
1496 CapabilityValue::BgpExtendedMessage(_)
1497 ));
1498
1499 assert_eq!(
1501 caps[1].ty,
1502 BgpCapabilityType::ROUTE_REFRESH_CAPABILITY_FOR_BGP_4
1503 );
1504 assert!(matches!(caps[1].value, CapabilityValue::RouteRefresh(_)));
1505
1506 assert_eq!(
1508 caps[2].ty,
1509 BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY
1510 );
1511 if let CapabilityValue::FourOctetAs(foa) = &caps[2].value {
1512 assert_eq!(foa.asn, 65536);
1513 } else {
1514 panic!("Expected FourOctetAs capability value");
1515 }
1516 } else {
1517 panic!("Expected Capacities parameter");
1518 }
1519 }
1520
1521 #[test]
1522 fn test_parse_bgp_open_message_with_multiple_capability_parameters() {
1523 let msg = BgpOpenMessage {
1527 version: 4,
1528 asn: Asn::new_32bit(65001),
1529 hold_time: 90,
1530 bgp_identifier: "192.168.1.1".parse().unwrap(),
1531 extended_length: false,
1532 opt_params: vec![
1533 OptParam {
1534 param_type: 2, param_len: 2,
1536 param_value: ParamValue::Capacities(vec![Capability {
1537 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1538 value: CapabilityValue::BgpExtendedMessage(BgpExtendedMessageCapability {}),
1539 }]),
1540 },
1541 OptParam {
1542 param_type: 2, param_len: 6,
1544 param_value: ParamValue::Capacities(vec![Capability {
1545 ty: BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY,
1546 value: CapabilityValue::FourOctetAs(FourOctetAsCapability {
1547 asn: 4200000000,
1548 }),
1549 }]),
1550 },
1551 ],
1552 };
1553
1554 let encoded = msg.encode();
1556 let mut encoded_bytes = encoded.clone();
1557 let parsed = parse_bgp_open_message(&mut encoded_bytes).unwrap();
1558
1559 assert_eq!(parsed.opt_params.len(), 2);
1561
1562 if let ParamValue::Capacities(caps) = &parsed.opt_params[0].param_value {
1564 assert_eq!(caps.len(), 1);
1565 assert_eq!(caps[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1566 } else {
1567 panic!("Expected Capacities in first parameter");
1568 }
1569
1570 if let ParamValue::Capacities(caps) = &parsed.opt_params[1].param_value {
1572 assert_eq!(caps.len(), 1);
1573 assert_eq!(
1574 caps[0].ty,
1575 BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY
1576 );
1577 if let CapabilityValue::FourOctetAs(foa) = &caps[0].value {
1578 assert_eq!(foa.asn, 4200000000);
1579 }
1580 } else {
1581 panic!("Expected Capacities in second parameter");
1582 }
1583 }
1584}