1use crate::models::*;
2use bytes::{Buf, BufMut, Bytes, BytesMut};
3use std::convert::TryFrom;
4
5use crate::error::ParserError;
6use crate::models::capabilities::{
7 AddPathCapability, BgpCapabilityType, BgpExtendedMessageCapability, BgpRoleCapability,
8 ExtendedNextHopCapability, FourOctetAsCapability, GracefulRestartCapability,
9 MultiprotocolExtensionsCapability, RouteRefreshCapability,
10};
11use crate::models::error::BgpError;
12use crate::parser::bgp::attributes::parse_attributes;
13use crate::parser::{encode_ipaddr, encode_nlri_prefixes, parse_nlri_list, ReadUtils};
14use log::warn;
15
16pub fn parse_bgp_message(
35 data: &mut Bytes,
36 add_path: bool,
37 asn_len: &AsnLength,
38) -> Result<BgpMessage, ParserError> {
39 let total_size = data.len();
40 data.has_n_remaining(19)?;
41 data.advance(16);
42 let length = data.read_u16()?;
54
55 let max_length = 65535; if !(19..=max_length).contains(&length) {
63 return Err(ParserError::ParseError(format!(
64 "invalid BGP message length {length}"
65 )));
66 }
67
68 let bgp_msg_length = if (length as usize) > total_size {
69 total_size - 19
70 } else {
71 length as usize - 19
72 };
73
74 let msg_type: BgpMessageType = match BgpMessageType::try_from(data.read_u8()?) {
75 Ok(t) => t,
76 Err(_) => {
77 return Err(ParserError::ParseError(
78 "Unknown BGP Message Type".to_string(),
79 ))
80 }
81 };
82
83 match msg_type {
86 BgpMessageType::OPEN | BgpMessageType::KEEPALIVE => {
87 if length > 4096 {
88 return Err(ParserError::ParseError(format!(
89 "BGP {} message length {} exceeds maximum allowed 4096 bytes (RFC 8654)",
90 match msg_type {
91 BgpMessageType::OPEN => "OPEN",
92 BgpMessageType::KEEPALIVE => "KEEPALIVE",
93 _ => unreachable!(),
94 },
95 length
96 )));
97 }
98 }
99 BgpMessageType::UPDATE | BgpMessageType::NOTIFICATION => {
100 }
103 }
104
105 if data.remaining() != bgp_msg_length {
106 warn!(
107 "BGP message length {} does not match the actual length {}",
108 bgp_msg_length,
109 data.remaining()
110 );
111 }
112 data.has_n_remaining(bgp_msg_length)?;
113 let mut msg_data = data.split_to(bgp_msg_length);
114
115 Ok(match msg_type {
116 BgpMessageType::OPEN => BgpMessage::Open(parse_bgp_open_message(&mut msg_data)?),
117 BgpMessageType::UPDATE => {
118 BgpMessage::Update(parse_bgp_update_message(msg_data, add_path, asn_len)?)
119 }
120 BgpMessageType::NOTIFICATION => {
121 BgpMessage::Notification(parse_bgp_notification_message(msg_data)?)
122 }
123 BgpMessageType::KEEPALIVE => BgpMessage::KeepAlive,
124 })
125}
126
127pub fn parse_bgp_notification_message(
134 mut input: Bytes,
135) -> Result<BgpNotificationMessage, ParserError> {
136 let error_code = input.read_u8()?;
137 let error_subcode = input.read_u8()?;
138
139 Ok(BgpNotificationMessage {
140 error: BgpError::new(error_code, error_subcode),
141 data: input.read_n_bytes(input.len())?,
142 })
143}
144
145impl BgpNotificationMessage {
146 pub fn encode(&self) -> Bytes {
147 let mut buf = BytesMut::new();
148 let (code, subcode) = self.error.get_codes();
149 buf.put_u8(code);
150 buf.put_u8(subcode);
151 buf.put_slice(&self.data);
152 buf.freeze()
153 }
154}
155
156pub fn parse_bgp_open_message(input: &mut Bytes) -> Result<BgpOpenMessage, ParserError> {
187 input.has_n_remaining(10)?;
188 let version = input.read_u8()?;
189 let asn = Asn::new_16bit(input.read_u16()?);
190 let hold_time = input.read_u16()?;
191
192 let sender_ip = input.read_ipv4_address()?;
193 let mut opt_params_len: u16 = input.read_u8()? as u16;
194
195 let mut extended_length = false;
196 let mut first = true;
197
198 let mut params: Vec<OptParam> = vec![];
199 while input.remaining() >= 2 {
200 let mut param_type = input.read_u8()?;
201 if first {
202 if opt_params_len == 0 && param_type == 255 {
203 return Err(ParserError::ParseError(
204 "RFC 9072 violation: Non-Extended Optional Parameters Length must not be 0 when using extended format".to_string()
205 ));
206 }
207 if opt_params_len != 0 && param_type == 255 {
209 extended_length = true;
231 opt_params_len = input.read_u16()?;
232 if opt_params_len == 0 {
233 break;
234 }
235 if input.remaining() != opt_params_len as usize {
237 warn!(
238 "BGP open message length {} does not match the actual length {}",
239 opt_params_len,
240 input.remaining()
241 );
242 }
243
244 param_type = input.read_u8()?;
245 }
246 first = false;
247 }
248 let param_len = match extended_length {
251 true => input.read_u16()?,
252 false => input.read_u8()? as u16,
253 };
254
255 let param_value = match param_type {
259 2 => {
260 let mut capacities = vec![];
261
262 input.has_n_remaining(param_len as usize)?;
264 let mut param_data = input.split_to(param_len as usize);
265
266 while param_data.remaining() >= 2 {
267 let code = param_data.read_u8()?;
270 let len = param_data.read_u8()? as u16; let capability_data = param_data.read_n_bytes(len as usize)?;
273 let capability_type = BgpCapabilityType::from(code);
274
275 macro_rules! parse_capability {
277 ($parser:path, $variant:ident) => {
278 match $parser(Bytes::from(capability_data.clone())) {
279 Ok(parsed) => CapabilityValue::$variant(parsed),
280 Err(_) => CapabilityValue::Raw(capability_data),
281 }
282 };
283 }
284
285 let capability_value = match capability_type {
286 BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4 => {
287 parse_capability!(
288 MultiprotocolExtensionsCapability::parse,
289 MultiprotocolExtensions
290 )
291 }
292 BgpCapabilityType::ROUTE_REFRESH_CAPABILITY_FOR_BGP_4 => {
293 parse_capability!(RouteRefreshCapability::parse, RouteRefresh)
294 }
295 BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING => {
296 parse_capability!(ExtendedNextHopCapability::parse, ExtendedNextHop)
297 }
298 BgpCapabilityType::GRACEFUL_RESTART_CAPABILITY => {
299 parse_capability!(GracefulRestartCapability::parse, GracefulRestart)
300 }
301 BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY => {
302 parse_capability!(FourOctetAsCapability::parse, FourOctetAs)
303 }
304 BgpCapabilityType::ADD_PATH_CAPABILITY => {
305 parse_capability!(AddPathCapability::parse, AddPath)
306 }
307 BgpCapabilityType::BGP_ROLE => {
308 parse_capability!(BgpRoleCapability::parse, BgpRole)
309 }
310 BgpCapabilityType::BGP_EXTENDED_MESSAGE => {
311 parse_capability!(
312 BgpExtendedMessageCapability::parse,
313 BgpExtendedMessage
314 )
315 }
316 _ => CapabilityValue::Raw(capability_data),
317 };
318
319 capacities.push(Capability {
320 ty: capability_type,
321 value: capability_value,
322 });
323 }
324
325 ParamValue::Capacities(capacities)
326 }
327 _ => {
328 let bytes = input.read_n_bytes(param_len as usize)?;
330 ParamValue::Raw(bytes)
331 }
332 };
333 params.push(OptParam {
334 param_type,
335 param_len,
336 param_value,
337 });
338 }
339
340 Ok(BgpOpenMessage {
341 version,
342 asn,
343 hold_time,
344 sender_ip,
345 extended_length,
346 opt_params: params,
347 })
348}
349
350impl BgpOpenMessage {
351 pub fn encode(&self) -> Bytes {
352 let mut buf = BytesMut::new();
353 buf.put_u8(self.version);
354 buf.put_u16(self.asn.into());
355 buf.put_u16(self.hold_time);
356 buf.extend(encode_ipaddr(&self.sender_ip.into()));
357 buf.put_u8(self.opt_params.len() as u8);
358 for param in &self.opt_params {
359 buf.put_u8(param.param_type);
360 buf.put_u8(param.param_len as u8);
361 match ¶m.param_value {
362 ParamValue::Capacities(capacities) => {
363 for cap in capacities {
364 buf.put_u8(cap.ty.into());
365 let encoded_value = match &cap.value {
366 CapabilityValue::MultiprotocolExtensions(mp) => mp.encode(),
367 CapabilityValue::RouteRefresh(rr) => rr.encode(),
368 CapabilityValue::ExtendedNextHop(enh) => enh.encode(),
369 CapabilityValue::GracefulRestart(gr) => gr.encode(),
370 CapabilityValue::FourOctetAs(foa) => foa.encode(),
371 CapabilityValue::AddPath(ap) => ap.encode(),
372 CapabilityValue::BgpRole(br) => br.encode(),
373 CapabilityValue::BgpExtendedMessage(bem) => bem.encode(),
374 CapabilityValue::Raw(raw) => Bytes::from(raw.clone()),
375 };
376 buf.put_u8(encoded_value.len() as u8);
377 buf.extend(&encoded_value);
378 }
379 }
380 ParamValue::Raw(bytes) => {
381 buf.extend(bytes);
382 }
383 }
384 }
385 buf.freeze()
386 }
387}
388
389fn read_nlri(
391 mut input: Bytes,
392 afi: &Afi,
393 add_path: bool,
394) -> Result<Vec<NetworkPrefix>, ParserError> {
395 let length = input.len();
396 if length == 0 {
397 return Ok(vec![]);
398 }
399 if length == 1 {
400 warn!("seeing strange one-byte NLRI field");
402 input.advance(1); return Ok(vec![]);
404 }
405
406 parse_nlri_list(input, add_path, afi)
407}
408
409pub fn parse_bgp_update_message(
413 mut input: Bytes,
414 add_path: bool,
415 asn_len: &AsnLength,
416) -> Result<BgpUpdateMessage, ParserError> {
417 let afi = Afi::Ipv4;
419
420 let withdrawn_bytes_length = input.read_u16()? as usize;
422 input.has_n_remaining(withdrawn_bytes_length)?;
423 let withdrawn_bytes = input.split_to(withdrawn_bytes_length);
424 let withdrawn_prefixes = read_nlri(withdrawn_bytes, &afi, add_path)?;
425
426 let attribute_length = input.read_u16()? as usize;
428
429 input.has_n_remaining(attribute_length)?;
430 let attr_data_slice = input.split_to(attribute_length);
431 let attributes = parse_attributes(attr_data_slice, asn_len, add_path, None, None, None)?;
432
433 let announced_prefixes = read_nlri(input, &afi, add_path)?;
436
437 Ok(BgpUpdateMessage {
438 withdrawn_prefixes,
439 attributes,
440 announced_prefixes,
441 })
442}
443
444impl BgpUpdateMessage {
445 pub fn encode(&self, asn_len: AsnLength) -> Bytes {
446 let mut bytes = BytesMut::new();
447
448 let withdrawn_bytes = encode_nlri_prefixes(&self.withdrawn_prefixes);
450 bytes.put_u16(withdrawn_bytes.len() as u16);
451 bytes.put_slice(&withdrawn_bytes);
452
453 let attr_bytes = self.attributes.encode(asn_len);
455
456 bytes.put_u16(attr_bytes.len() as u16);
457 bytes.put_slice(&attr_bytes);
458
459 bytes.extend(encode_nlri_prefixes(&self.announced_prefixes));
460 bytes.freeze()
461 }
462
463 pub fn is_end_of_rib(&self) -> bool {
468 if !self.announced_prefixes.is_empty() || !self.withdrawn_prefixes.is_empty() {
473 return false;
477 }
478
479 if self.attributes.inner.is_empty() {
480 return true;
483 }
484
485 if self.attributes.inner.len() > 1 {
488 return false;
490 }
491
492 if let AttributeValue::MpUnreachNlri(nlri) = &self.attributes.inner.first().unwrap().value {
494 if nlri.prefixes.is_empty() {
495 return true;
498 }
499 }
500
501 false
503 }
504}
505
506impl BgpMessage {
507 pub fn encode(&self, asn_len: AsnLength) -> Bytes {
508 let mut bytes = BytesMut::new();
509 bytes.put_u32(0); bytes.put_u32(0); bytes.put_u32(0); bytes.put_u32(0); let (msg_type, msg_bytes) = match self {
515 BgpMessage::Open(msg) => (BgpMessageType::OPEN, msg.encode()),
516 BgpMessage::Update(msg) => (BgpMessageType::UPDATE, msg.encode(asn_len)),
517 BgpMessage::Notification(msg) => (BgpMessageType::NOTIFICATION, msg.encode()),
518 BgpMessage::KeepAlive => (BgpMessageType::KEEPALIVE, Bytes::new()),
519 };
520
521 bytes.put_u16(msg_bytes.len() as u16 + 16 + 2 + 1);
523 bytes.put_u8(msg_type as u8);
524 bytes.put_slice(&msg_bytes);
525 bytes.freeze()
526 }
527}
528
529impl From<&BgpElem> for BgpUpdateMessage {
530 fn from(elem: &BgpElem) -> Self {
531 BgpUpdateMessage {
532 withdrawn_prefixes: vec![],
533 attributes: Attributes::from(elem),
534 announced_prefixes: vec![],
535 }
536 }
537}
538
539impl From<BgpUpdateMessage> for BgpMessage {
540 fn from(value: BgpUpdateMessage) -> Self {
541 BgpMessage::Update(value)
542 }
543}
544
545#[cfg(test)]
546mod tests {
547 use super::*;
548 use std::net::Ipv4Addr;
549 use std::str::FromStr;
550
551 #[test]
552 fn test_end_of_rib() {
553 let attrs = Attributes::default();
555 let msg = BgpUpdateMessage {
556 withdrawn_prefixes: vec![],
557 attributes: attrs,
558 announced_prefixes: vec![],
559 };
560 assert!(msg.is_end_of_rib());
561
562 let attrs = Attributes::from_iter(vec![AttributeValue::MpUnreachNlri(Nlri {
564 afi: Afi::Ipv4,
565 safi: Safi::Unicast,
566 next_hop: None,
567 prefixes: vec![],
568 link_state_nlris: None,
569 flowspec_nlris: None,
570 })]);
571 let msg = BgpUpdateMessage {
572 withdrawn_prefixes: vec![],
573 attributes: attrs,
574 announced_prefixes: vec![],
575 };
576 assert!(msg.is_end_of_rib());
577
578 let prefix = NetworkPrefix::from_str("192.168.1.0/24").unwrap();
580 let attrs = Attributes::default();
581 let msg = BgpUpdateMessage {
582 withdrawn_prefixes: vec![],
583 attributes: attrs,
584 announced_prefixes: vec![prefix],
585 };
586 assert!(!msg.is_end_of_rib());
587
588 let prefix = NetworkPrefix::from_str("192.168.1.0/24").unwrap();
590 let attrs = Attributes::default();
591 let msg = BgpUpdateMessage {
592 withdrawn_prefixes: vec![prefix],
593 attributes: attrs,
594 announced_prefixes: vec![],
595 };
596 assert!(!msg.is_end_of_rib());
597
598 let attrs = Attributes::from_iter(vec![AttributeValue::MpReachNlri(Nlri {
600 afi: Afi::Ipv4,
601 safi: Safi::Unicast,
602 next_hop: None,
603 prefixes: vec![],
604 link_state_nlris: None,
605 flowspec_nlris: None,
606 })]);
607 let msg = BgpUpdateMessage {
608 withdrawn_prefixes: vec![],
609 attributes: attrs,
610 announced_prefixes: vec![],
611 };
612 assert!(!msg.is_end_of_rib());
613
614 let attrs = Attributes::from_iter(vec![AttributeValue::MpReachNlri(Nlri {
616 afi: Afi::Ipv4,
617 safi: Safi::Unicast,
618 next_hop: None,
619 prefixes: vec![prefix],
620 link_state_nlris: None,
621 flowspec_nlris: None,
622 })]);
623 let msg = BgpUpdateMessage {
624 withdrawn_prefixes: vec![],
625 attributes: attrs,
626 announced_prefixes: vec![],
627 };
628 assert!(!msg.is_end_of_rib());
629
630 let attrs = Attributes::from_iter(vec![AttributeValue::MpUnreachNlri(Nlri {
632 afi: Afi::Ipv4,
633 safi: Safi::Unicast,
634 next_hop: None,
635 prefixes: vec![prefix],
636 link_state_nlris: None,
637 flowspec_nlris: None,
638 })]);
639 let msg = BgpUpdateMessage {
640 withdrawn_prefixes: vec![],
641 attributes: attrs,
642 announced_prefixes: vec![],
643 };
644 assert!(!msg.is_end_of_rib());
645
646 let attrs = Attributes::from_iter(vec![
648 AttributeValue::MpUnreachNlri(Nlri {
649 afi: Afi::Ipv4,
650 safi: Safi::Unicast,
651 next_hop: None,
652 prefixes: vec![],
653 link_state_nlris: None,
654 flowspec_nlris: None,
655 }),
656 AttributeValue::AtomicAggregate,
657 ]);
658 let msg = BgpUpdateMessage {
659 withdrawn_prefixes: vec![],
660 attributes: attrs,
661 announced_prefixes: vec![],
662 };
663 assert!(!msg.is_end_of_rib());
664 }
665
666 #[test]
667 fn test_invlaid_length() {
668 let bytes = Bytes::from_static(&[
669 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, ]);
676 let mut data = bytes.clone();
677 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_err());
678
679 let bytes = Bytes::from_static(&[
680 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x05, ]);
687 let mut data = bytes.clone();
688 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_err());
689 }
690
691 #[test]
692 fn test_invlaid_type() {
693 let bytes = Bytes::from_static(&[
694 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x05, ]);
701 let mut data = bytes.clone();
702 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_err());
703 }
704
705 #[test]
706 fn test_parse_bgp_notification_message() {
707 let bytes = Bytes::from_static(&[
708 0x01, 0x02, 0x00, 0x00, ]);
712 let msg = parse_bgp_notification_message(bytes).unwrap();
713 matches!(
714 msg.error,
715 BgpError::MessageHeaderError(MessageHeaderError::BAD_MESSAGE_LENGTH)
716 );
717 assert_eq!(msg.data, Bytes::from_static(&[0x00, 0x00]));
718 }
719
720 #[test]
721 fn test_encode_bgp_notification_messsage() {
722 let msg = BgpNotificationMessage {
723 error: BgpError::MessageHeaderError(MessageHeaderError::BAD_MESSAGE_LENGTH),
724 data: vec![0x00, 0x00],
725 };
726 let bytes = msg.encode();
727 assert_eq!(bytes, Bytes::from_static(&[0x01, 0x02, 0x00, 0x00]));
728 }
729
730 #[test]
731 fn test_parse_bgp_open_message() {
732 let bytes = Bytes::from_static(&[
733 0x04, 0x00, 0x01, 0x00, 0xb4, 0xc0, 0x00, 0x02, 0x01, 0x00, ]);
739 let msg = parse_bgp_open_message(&mut bytes.clone()).unwrap();
740 assert_eq!(msg.version, 4);
741 assert_eq!(msg.asn, Asn::new_16bit(1));
742 assert_eq!(msg.hold_time, 180);
743 assert_eq!(msg.sender_ip, Ipv4Addr::new(192, 0, 2, 1));
744 assert!(!msg.extended_length);
745 assert_eq!(msg.opt_params.len(), 0);
746 }
747
748 #[test]
749 fn test_encode_bgp_open_message() {
750 let msg = BgpOpenMessage {
751 version: 4,
752 asn: Asn::new_16bit(1),
753 hold_time: 180,
754 sender_ip: Ipv4Addr::new(192, 0, 2, 1),
755 extended_length: false,
756 opt_params: vec![],
757 };
758 let bytes = msg.encode();
759 assert_eq!(
760 bytes,
761 Bytes::from_static(&[
762 0x04, 0x00, 0x01, 0x00, 0xb4, 0xc0, 0x00, 0x02, 0x01, 0x00, ])
768 );
769 }
770
771 #[test]
772 fn test_encode_bgp_notification_message() {
773 let bgp_message = BgpMessage::Notification(BgpNotificationMessage {
774 error: BgpError::MessageHeaderError(MessageHeaderError::BAD_MESSAGE_LENGTH),
775 data: vec![0x00, 0x00],
776 });
777 let bytes = bgp_message.encode(AsnLength::Bits16);
778 assert_eq!(
779 bytes,
780 Bytes::from_static(&[
781 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
782 0x00, 0x00, 0x00, 0x17, 0x03, 0x01, 0x02, 0x00, 0x00
783 ])
784 );
785 }
786
787 #[test]
788 fn test_bgp_message_from_bgp_update_message() {
789 let msg = BgpMessage::from(BgpUpdateMessage::default());
790 assert!(matches!(msg, BgpMessage::Update(_)));
791 }
792
793 #[test]
794 fn test_parse_bgp_open_message_with_extended_next_hop_capability() {
795 use crate::models::{Afi, Safi};
796
797 let bytes = Bytes::from(vec![
803 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, ]);
819
820 let msg = parse_bgp_open_message(&mut bytes.clone()).unwrap();
821 assert_eq!(msg.version, 4);
822 assert_eq!(msg.asn, Asn::new_16bit(65001));
823 assert_eq!(msg.hold_time, 180);
824 assert_eq!(msg.sender_ip, Ipv4Addr::new(192, 0, 2, 1));
825 assert!(!msg.extended_length);
826 assert_eq!(msg.opt_params.len(), 1);
827
828 if let ParamValue::Capacities(cap) = &msg.opt_params[0].param_value {
830 assert_eq!(cap[0].ty, BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING);
831
832 if let CapabilityValue::ExtendedNextHop(enh_cap) = &cap[0].value {
833 assert_eq!(enh_cap.entries.len(), 2);
834
835 let entry1 = &enh_cap.entries[0];
837 assert_eq!(entry1.nlri_afi, Afi::Ipv4);
838 assert_eq!(entry1.nlri_safi, Safi::Unicast);
839 assert_eq!(entry1.nexthop_afi, Afi::Ipv6);
840
841 let entry2 = &enh_cap.entries[1];
843 assert_eq!(entry2.nlri_afi, Afi::Ipv4);
844 assert_eq!(entry2.nlri_safi, Safi::MplsVpn);
845 assert_eq!(entry2.nexthop_afi, Afi::Ipv6);
846
847 assert!(enh_cap.supports(Afi::Ipv4, Safi::Unicast, Afi::Ipv6));
849 assert!(enh_cap.supports(Afi::Ipv4, Safi::MplsVpn, Afi::Ipv6));
850 assert!(!enh_cap.supports(Afi::Ipv4, Safi::Multicast, Afi::Ipv6));
851 } else {
852 panic!("Expected ExtendedNextHop capability value");
853 }
854 } else {
855 panic!("Expected capability parameter");
856 }
857 }
858
859 #[test]
860 fn test_rfc8654_extended_message_length_validation() {
861 let bytes = Bytes::from_static(&[
863 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x00, 0x00,
871 0x00, ]);
874 let mut data = bytes.clone();
875 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_ok());
877
878 let bytes = Bytes::from_static(&[
880 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x01, ]);
887 let mut data = bytes.clone();
888 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
889 assert!(result.is_err());
890 if let Err(ParserError::ParseError(msg)) = result {
891 assert!(msg.contains("BGP OPEN message length"));
892 assert!(msg.contains("4096 bytes"));
893 }
894
895 let bytes = Bytes::from_static(&[
897 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x04, ]);
904 let mut data = bytes.clone();
905 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
906 assert!(result.is_err());
907 if let Err(ParserError::ParseError(msg)) = result {
908 assert!(msg.contains("BGP KEEPALIVE message length"));
909 assert!(msg.contains("4096 bytes"));
910 }
911
912 let bytes = Bytes::from_static(&[
914 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x02, ]);
921 let mut data = bytes.clone();
922 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
924 if let Err(ParserError::ParseError(msg)) = result {
925 assert!(!msg.contains("invalid BGP message length"));
927 }
928 }
929
930 #[test]
931 fn test_bgp_extended_message_capability_parsing() {
932 use crate::models::CapabilityValue;
933
934 let bytes = Bytes::from(vec![
936 0x04, 0x00, 0x01, 0x00, 0xb4, 0xc0, 0x00, 0x02, 0x01, 0x04, 0x02, 0x02, 0x06, 0x00, ]);
946
947 let msg = parse_bgp_open_message(&mut bytes.clone()).unwrap();
948 assert_eq!(msg.version, 4);
949 assert_eq!(msg.asn, Asn::new_16bit(1));
950 assert_eq!(msg.opt_params.len(), 1);
951
952 if let ParamValue::Capacities(cap) = &msg.opt_params[0].param_value {
954 assert_eq!(cap[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
955 if let CapabilityValue::BgpExtendedMessage(_) = &cap[0].value {
956 } else {
958 panic!("Expected BgpExtendedMessage capability value");
959 }
960 } else {
961 panic!("Expected capability parameter");
962 }
963 }
964
965 #[test]
966 fn test_rfc8654_edge_cases() {
967 let bytes = Bytes::from_static(&[
969 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x03, 0x06, 0x00, ]);
979 let mut data = bytes.clone();
980 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
982 if let Err(ParserError::ParseError(msg)) = result {
984 assert!(!msg.contains("invalid BGP message length"));
985 assert!(!msg.contains("exceeds maximum allowed 4096 bytes"));
986 }
987
988 let open_data = vec![
990 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, ];
997 let bytes = Bytes::from(open_data);
998 let mut data = bytes.clone();
999 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1000 if let Err(ParserError::ParseError(msg)) = result {
1002 assert!(!msg.contains("exceeds maximum allowed 4096 bytes"));
1003 }
1004
1005 let bytes = Bytes::from_static(&[
1007 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x02, ]);
1014 let mut data = bytes.clone();
1015 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1016 if let Err(ParserError::ParseError(msg)) = result {
1018 assert!(!msg.contains("invalid BGP message length"));
1019 }
1020 }
1021
1022 #[test]
1023 fn test_rfc8654_capability_encoding_path() {
1024 use crate::models::capabilities::BgpExtendedMessageCapability;
1025
1026 let capability_value =
1029 CapabilityValue::BgpExtendedMessage(BgpExtendedMessageCapability::new());
1030 let capability = Capability {
1031 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1032 value: capability_value,
1033 };
1034
1035 let opt_param = OptParam {
1036 param_type: 2, param_len: 2,
1038 param_value: ParamValue::Capacities(vec![capability]),
1039 };
1040
1041 let msg = BgpOpenMessage {
1042 version: 4,
1043 asn: Asn::new_16bit(65001),
1044 hold_time: 180,
1045 sender_ip: Ipv4Addr::new(192, 0, 2, 1),
1046 extended_length: false,
1047 opt_params: vec![opt_param],
1048 };
1049
1050 let encoded = msg.encode();
1052 assert!(!encoded.is_empty());
1053
1054 let parsed = parse_bgp_open_message(&mut encoded.clone()).unwrap();
1056 assert_eq!(parsed.opt_params.len(), 1);
1057 if let ParamValue::Capacities(cap) = &parsed.opt_params[0].param_value {
1058 assert_eq!(cap[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1059 }
1060 }
1061
1062 #[test]
1063 fn test_rfc8654_error_message_formatting() {
1064 let bytes = Bytes::from_static(&[
1069 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x01, ]);
1076 let mut data = bytes.clone();
1077 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1078 assert!(result.is_err());
1079 if let Err(ParserError::ParseError(msg)) = result {
1080 assert!(msg.contains("BGP OPEN message length"));
1081 assert!(msg.contains("exceeds maximum allowed 4096 bytes"));
1082 }
1083
1084 let bytes = Bytes::from_static(&[
1086 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x04, ]);
1093 let mut data = bytes.clone();
1094 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1095 assert!(result.is_err());
1096 if let Err(ParserError::ParseError(msg)) = result {
1097 assert!(msg.contains("BGP KEEPALIVE message length"));
1098 assert!(msg.contains("exceeds maximum allowed 4096 bytes"));
1099 }
1100 }
1101
1102 #[test]
1103 fn test_encode_bgp_open_message_with_extended_message_capability() {
1104 use crate::models::capabilities::BgpExtendedMessageCapability;
1105
1106 let extended_msg_capability = BgpExtendedMessageCapability::new();
1108
1109 let msg = BgpOpenMessage {
1110 version: 4,
1111 asn: Asn::new_16bit(65001),
1112 hold_time: 180,
1113 sender_ip: Ipv4Addr::new(192, 0, 2, 1),
1114 extended_length: false,
1115 opt_params: vec![OptParam {
1116 param_type: 2, param_len: 2, param_value: ParamValue::Capacities(vec![Capability {
1119 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1120 value: CapabilityValue::BgpExtendedMessage(extended_msg_capability),
1121 }]),
1122 }],
1123 };
1124
1125 let encoded = msg.encode();
1126
1127 let parsed = parse_bgp_open_message(&mut encoded.clone()).unwrap();
1129 assert_eq!(parsed.version, msg.version);
1130 assert_eq!(parsed.asn, msg.asn);
1131 assert_eq!(parsed.hold_time, msg.hold_time);
1132 assert_eq!(parsed.sender_ip, msg.sender_ip);
1133 assert_eq!(parsed.opt_params.len(), 1);
1134
1135 if let ParamValue::Capacities(cap) = &parsed.opt_params[0].param_value {
1137 assert_eq!(cap[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1138 if let CapabilityValue::BgpExtendedMessage(_) = &cap[0].value {
1139 } else {
1141 panic!("Expected BgpExtendedMessage capability value after round trip");
1142 }
1143 } else {
1144 panic!("Expected capability parameter after round trip");
1145 }
1146 }
1147
1148 #[test]
1149 fn test_encode_bgp_open_message_with_extended_next_hop_capability() {
1150 use crate::models::capabilities::{ExtendedNextHopCapability, ExtendedNextHopEntry};
1151 use crate::models::{Afi, Safi};
1152
1153 let entries = vec![
1155 ExtendedNextHopEntry {
1156 nlri_afi: Afi::Ipv4,
1157 nlri_safi: Safi::Unicast,
1158 nexthop_afi: Afi::Ipv6,
1159 },
1160 ExtendedNextHopEntry {
1161 nlri_afi: Afi::Ipv4,
1162 nlri_safi: Safi::MplsVpn,
1163 nexthop_afi: Afi::Ipv6,
1164 },
1165 ];
1166 let enh_capability = ExtendedNextHopCapability::new(entries);
1167
1168 let msg = BgpOpenMessage {
1169 version: 4,
1170 asn: Asn::new_16bit(65001),
1171 hold_time: 180,
1172 sender_ip: Ipv4Addr::new(192, 0, 2, 1),
1173 extended_length: false,
1174 opt_params: vec![OptParam {
1175 param_type: 2, param_len: 14, param_value: ParamValue::Capacities(vec![Capability {
1178 ty: BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING,
1179 value: CapabilityValue::ExtendedNextHop(enh_capability),
1180 }]),
1181 }],
1182 };
1183
1184 let encoded = msg.encode();
1185
1186 let parsed = parse_bgp_open_message(&mut encoded.clone()).unwrap();
1188 assert_eq!(parsed.version, msg.version);
1189 assert_eq!(parsed.asn, msg.asn);
1190 assert_eq!(parsed.hold_time, msg.hold_time);
1191 assert_eq!(parsed.sender_ip, msg.sender_ip);
1192 assert_eq!(parsed.extended_length, msg.extended_length);
1193 assert_eq!(parsed.opt_params.len(), 1);
1194
1195 if let ParamValue::Capacities(cap) = &parsed.opt_params[0].param_value {
1197 assert_eq!(cap[0].ty, BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING);
1198 if let CapabilityValue::ExtendedNextHop(enh_cap) = &cap[0].value {
1199 assert_eq!(enh_cap.entries.len(), 2);
1200 assert!(enh_cap.supports(Afi::Ipv4, Safi::Unicast, Afi::Ipv6));
1201 assert!(enh_cap.supports(Afi::Ipv4, Safi::MplsVpn, Afi::Ipv6));
1202 } else {
1203 panic!("Expected ExtendedNextHop capability value after round trip");
1204 }
1205 } else {
1206 panic!("Expected capability parameter after round trip");
1207 }
1208 }
1209
1210 #[test]
1211 fn test_parse_bgp_open_message_with_multiple_capabilities() {
1212 let extended_msg_cap = Capability {
1217 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1218 value: CapabilityValue::BgpExtendedMessage(BgpExtendedMessageCapability {}),
1219 };
1220
1221 let route_refresh_cap = Capability {
1222 ty: BgpCapabilityType::ROUTE_REFRESH_CAPABILITY_FOR_BGP_4,
1223 value: CapabilityValue::RouteRefresh(RouteRefreshCapability {}),
1224 };
1225
1226 let four_octet_as_cap = Capability {
1227 ty: BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY,
1228 value: CapabilityValue::FourOctetAs(FourOctetAsCapability { asn: 65536 }),
1229 };
1230
1231 let msg = BgpOpenMessage {
1233 version: 4,
1234 asn: Asn::new_32bit(65000),
1235 hold_time: 180,
1236 sender_ip: "10.0.0.1".parse().unwrap(),
1237 extended_length: false,
1238 opt_params: vec![OptParam {
1239 param_type: 2, param_len: 10, param_value: ParamValue::Capacities(vec![
1242 extended_msg_cap,
1243 route_refresh_cap,
1244 four_octet_as_cap,
1245 ]),
1246 }],
1247 };
1248
1249 let encoded = msg.encode();
1251
1252 let mut encoded_bytes = encoded.clone();
1254 let parsed = parse_bgp_open_message(&mut encoded_bytes).unwrap();
1255
1256 assert_eq!(parsed.version, 4);
1258 assert_eq!(parsed.asn, Asn::new_32bit(65000));
1259 assert_eq!(parsed.hold_time, 180);
1260 assert_eq!(
1261 parsed.sender_ip,
1262 "10.0.0.1".parse::<std::net::Ipv4Addr>().unwrap()
1263 );
1264 assert_eq!(parsed.opt_params.len(), 1);
1265
1266 if let ParamValue::Capacities(caps) = &parsed.opt_params[0].param_value {
1268 assert_eq!(caps.len(), 3, "Should have 3 capabilities");
1269
1270 assert_eq!(caps[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1272 assert!(matches!(
1273 caps[0].value,
1274 CapabilityValue::BgpExtendedMessage(_)
1275 ));
1276
1277 assert_eq!(
1279 caps[1].ty,
1280 BgpCapabilityType::ROUTE_REFRESH_CAPABILITY_FOR_BGP_4
1281 );
1282 assert!(matches!(caps[1].value, CapabilityValue::RouteRefresh(_)));
1283
1284 assert_eq!(
1286 caps[2].ty,
1287 BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY
1288 );
1289 if let CapabilityValue::FourOctetAs(foa) = &caps[2].value {
1290 assert_eq!(foa.asn, 65536);
1291 } else {
1292 panic!("Expected FourOctetAs capability value");
1293 }
1294 } else {
1295 panic!("Expected Capacities parameter");
1296 }
1297 }
1298
1299 #[test]
1300 fn test_parse_bgp_open_message_with_multiple_capability_parameters() {
1301 let msg = BgpOpenMessage {
1305 version: 4,
1306 asn: Asn::new_32bit(65001),
1307 hold_time: 90,
1308 sender_ip: "192.168.1.1".parse().unwrap(),
1309 extended_length: false,
1310 opt_params: vec![
1311 OptParam {
1312 param_type: 2, param_len: 2,
1314 param_value: ParamValue::Capacities(vec![Capability {
1315 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1316 value: CapabilityValue::BgpExtendedMessage(BgpExtendedMessageCapability {}),
1317 }]),
1318 },
1319 OptParam {
1320 param_type: 2, param_len: 6,
1322 param_value: ParamValue::Capacities(vec![Capability {
1323 ty: BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY,
1324 value: CapabilityValue::FourOctetAs(FourOctetAsCapability {
1325 asn: 4200000000,
1326 }),
1327 }]),
1328 },
1329 ],
1330 };
1331
1332 let encoded = msg.encode();
1334 let mut encoded_bytes = encoded.clone();
1335 let parsed = parse_bgp_open_message(&mut encoded_bytes).unwrap();
1336
1337 assert_eq!(parsed.opt_params.len(), 2);
1339
1340 if let ParamValue::Capacities(caps) = &parsed.opt_params[0].param_value {
1342 assert_eq!(caps.len(), 1);
1343 assert_eq!(caps[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1344 } else {
1345 panic!("Expected Capacities in first parameter");
1346 }
1347
1348 if let ParamValue::Capacities(caps) = &parsed.opt_params[1].param_value {
1350 assert_eq!(caps.len(), 1);
1351 assert_eq!(
1352 caps[0].ty,
1353 BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY
1354 );
1355 if let CapabilityValue::FourOctetAs(foa) = &caps[0].value {
1356 assert_eq!(foa.asn, 4200000000);
1357 }
1358 } else {
1359 panic!("Expected Capacities in second parameter");
1360 }
1361 }
1362}