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.get_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.get_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.get_u8();
189 let asn = Asn::new_16bit(input.get_u16());
190 let hold_time = input.get_u16();
191
192 let sender_ip = input.read_ipv4_address()?;
193 let mut opt_params_len: u16 = input.get_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.get_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 let mut param_data = input.split_to(param_len as usize);
264
265 while param_data.remaining() >= 2 {
266 let code = param_data.read_u8()?;
269 let len = param_data.read_u8()? as u16; let capability_data = param_data.read_n_bytes(len as usize)?;
272 let capability_type = BgpCapabilityType::from(code);
273
274 macro_rules! parse_capability {
276 ($parser:path, $variant:ident) => {
277 match $parser(Bytes::from(capability_data.clone())) {
278 Ok(parsed) => CapabilityValue::$variant(parsed),
279 Err(_) => CapabilityValue::Raw(capability_data),
280 }
281 };
282 }
283
284 let capability_value = match capability_type {
285 BgpCapabilityType::MULTIPROTOCOL_EXTENSIONS_FOR_BGP_4 => {
286 parse_capability!(
287 MultiprotocolExtensionsCapability::parse,
288 MultiprotocolExtensions
289 )
290 }
291 BgpCapabilityType::ROUTE_REFRESH_CAPABILITY_FOR_BGP_4 => {
292 parse_capability!(RouteRefreshCapability::parse, RouteRefresh)
293 }
294 BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING => {
295 parse_capability!(ExtendedNextHopCapability::parse, ExtendedNextHop)
296 }
297 BgpCapabilityType::GRACEFUL_RESTART_CAPABILITY => {
298 parse_capability!(GracefulRestartCapability::parse, GracefulRestart)
299 }
300 BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY => {
301 parse_capability!(FourOctetAsCapability::parse, FourOctetAs)
302 }
303 BgpCapabilityType::ADD_PATH_CAPABILITY => {
304 parse_capability!(AddPathCapability::parse, AddPath)
305 }
306 BgpCapabilityType::BGP_ROLE => {
307 parse_capability!(BgpRoleCapability::parse, BgpRole)
308 }
309 BgpCapabilityType::BGP_EXTENDED_MESSAGE => {
310 parse_capability!(
311 BgpExtendedMessageCapability::parse,
312 BgpExtendedMessage
313 )
314 }
315 _ => CapabilityValue::Raw(capability_data),
316 };
317
318 capacities.push(Capability {
319 ty: capability_type,
320 value: capability_value,
321 });
322 }
323
324 ParamValue::Capacities(capacities)
325 }
326 _ => {
327 let bytes = input.read_n_bytes(param_len as usize)?;
329 ParamValue::Raw(bytes)
330 }
331 };
332 params.push(OptParam {
333 param_type,
334 param_len,
335 param_value,
336 });
337 }
338
339 Ok(BgpOpenMessage {
340 version,
341 asn,
342 hold_time,
343 sender_ip,
344 extended_length,
345 opt_params: params,
346 })
347}
348
349impl BgpOpenMessage {
350 pub fn encode(&self) -> Bytes {
351 let mut buf = BytesMut::new();
352 buf.put_u8(self.version);
353 buf.put_u16(self.asn.into());
354 buf.put_u16(self.hold_time);
355 buf.extend(encode_ipaddr(&self.sender_ip.into()));
356 buf.put_u8(self.opt_params.len() as u8);
357 for param in &self.opt_params {
358 buf.put_u8(param.param_type);
359 buf.put_u8(param.param_len as u8);
360 match ¶m.param_value {
361 ParamValue::Capacities(capacities) => {
362 for cap in capacities {
363 buf.put_u8(cap.ty.into());
364 let encoded_value = match &cap.value {
365 CapabilityValue::MultiprotocolExtensions(mp) => mp.encode(),
366 CapabilityValue::RouteRefresh(rr) => rr.encode(),
367 CapabilityValue::ExtendedNextHop(enh) => enh.encode(),
368 CapabilityValue::GracefulRestart(gr) => gr.encode(),
369 CapabilityValue::FourOctetAs(foa) => foa.encode(),
370 CapabilityValue::AddPath(ap) => ap.encode(),
371 CapabilityValue::BgpRole(br) => br.encode(),
372 CapabilityValue::BgpExtendedMessage(bem) => bem.encode(),
373 CapabilityValue::Raw(raw) => Bytes::from(raw.clone()),
374 };
375 buf.put_u8(encoded_value.len() as u8);
376 buf.extend(&encoded_value);
377 }
378 }
379 ParamValue::Raw(bytes) => {
380 buf.extend(bytes);
381 }
382 }
383 }
384 buf.freeze()
385 }
386}
387
388fn read_nlri(
390 mut input: Bytes,
391 afi: &Afi,
392 add_path: bool,
393) -> Result<Vec<NetworkPrefix>, ParserError> {
394 let length = input.len();
395 if length == 0 {
396 return Ok(vec![]);
397 }
398 if length == 1 {
399 warn!("seeing strange one-byte NLRI field");
401 input.advance(1); return Ok(vec![]);
403 }
404
405 parse_nlri_list(input, add_path, afi)
406}
407
408pub fn parse_bgp_update_message(
412 mut input: Bytes,
413 add_path: bool,
414 asn_len: &AsnLength,
415) -> Result<BgpUpdateMessage, ParserError> {
416 let afi = Afi::Ipv4;
418
419 let withdrawn_bytes_length = input.read_u16()? as usize;
421 input.has_n_remaining(withdrawn_bytes_length)?;
422 let withdrawn_bytes = input.split_to(withdrawn_bytes_length);
423 let withdrawn_prefixes = read_nlri(withdrawn_bytes, &afi, add_path)?;
424
425 let attribute_length = input.read_u16()? as usize;
427
428 input.has_n_remaining(attribute_length)?;
429 let attr_data_slice = input.split_to(attribute_length);
430 let attributes = parse_attributes(attr_data_slice, asn_len, add_path, None, None, None)?;
431
432 let announced_prefixes = read_nlri(input, &afi, add_path)?;
435
436 Ok(BgpUpdateMessage {
437 withdrawn_prefixes,
438 attributes,
439 announced_prefixes,
440 })
441}
442
443impl BgpUpdateMessage {
444 pub fn encode(&self, asn_len: AsnLength) -> Bytes {
445 let mut bytes = BytesMut::new();
446
447 let withdrawn_bytes = encode_nlri_prefixes(&self.withdrawn_prefixes);
449 bytes.put_u16(withdrawn_bytes.len() as u16);
450 bytes.put_slice(&withdrawn_bytes);
451
452 let attr_bytes = self.attributes.encode(asn_len);
454
455 bytes.put_u16(attr_bytes.len() as u16);
456 bytes.put_slice(&attr_bytes);
457
458 bytes.extend(encode_nlri_prefixes(&self.announced_prefixes));
459 bytes.freeze()
460 }
461
462 pub fn is_end_of_rib(&self) -> bool {
467 if !self.announced_prefixes.is_empty() || !self.withdrawn_prefixes.is_empty() {
472 return false;
476 }
477
478 if self.attributes.inner.is_empty() {
479 return true;
482 }
483
484 if self.attributes.inner.len() > 1 {
487 return false;
489 }
490
491 if let AttributeValue::MpUnreachNlri(nlri) = &self.attributes.inner.first().unwrap().value {
493 if nlri.prefixes.is_empty() {
494 return true;
497 }
498 }
499
500 false
502 }
503}
504
505impl BgpMessage {
506 pub fn encode(&self, asn_len: AsnLength) -> Bytes {
507 let mut bytes = BytesMut::new();
508 bytes.put_u32(0); bytes.put_u32(0); bytes.put_u32(0); bytes.put_u32(0); let (msg_type, msg_bytes) = match self {
514 BgpMessage::Open(msg) => (BgpMessageType::OPEN, msg.encode()),
515 BgpMessage::Update(msg) => (BgpMessageType::UPDATE, msg.encode(asn_len)),
516 BgpMessage::Notification(msg) => (BgpMessageType::NOTIFICATION, msg.encode()),
517 BgpMessage::KeepAlive => (BgpMessageType::KEEPALIVE, Bytes::new()),
518 };
519
520 bytes.put_u16(msg_bytes.len() as u16 + 16 + 2 + 1);
522 bytes.put_u8(msg_type as u8);
523 bytes.put_slice(&msg_bytes);
524 bytes.freeze()
525 }
526}
527
528impl From<&BgpElem> for BgpUpdateMessage {
529 fn from(elem: &BgpElem) -> Self {
530 BgpUpdateMessage {
531 withdrawn_prefixes: vec![],
532 attributes: Attributes::from(elem),
533 announced_prefixes: vec![],
534 }
535 }
536}
537
538impl From<BgpUpdateMessage> for BgpMessage {
539 fn from(value: BgpUpdateMessage) -> Self {
540 BgpMessage::Update(value)
541 }
542}
543
544#[cfg(test)]
545mod tests {
546 use super::*;
547 use std::net::Ipv4Addr;
548 use std::str::FromStr;
549
550 #[test]
551 fn test_end_of_rib() {
552 let attrs = Attributes::default();
554 let msg = BgpUpdateMessage {
555 withdrawn_prefixes: vec![],
556 attributes: attrs,
557 announced_prefixes: vec![],
558 };
559 assert!(msg.is_end_of_rib());
560
561 let attrs = Attributes::from_iter(vec![AttributeValue::MpUnreachNlri(Nlri {
563 afi: Afi::Ipv4,
564 safi: Safi::Unicast,
565 next_hop: None,
566 prefixes: vec![],
567 link_state_nlris: None,
568 flowspec_nlris: None,
569 })]);
570 let msg = BgpUpdateMessage {
571 withdrawn_prefixes: vec![],
572 attributes: attrs,
573 announced_prefixes: vec![],
574 };
575 assert!(msg.is_end_of_rib());
576
577 let prefix = NetworkPrefix::from_str("192.168.1.0/24").unwrap();
579 let attrs = Attributes::default();
580 let msg = BgpUpdateMessage {
581 withdrawn_prefixes: vec![],
582 attributes: attrs,
583 announced_prefixes: vec![prefix],
584 };
585 assert!(!msg.is_end_of_rib());
586
587 let prefix = NetworkPrefix::from_str("192.168.1.0/24").unwrap();
589 let attrs = Attributes::default();
590 let msg = BgpUpdateMessage {
591 withdrawn_prefixes: vec![prefix],
592 attributes: attrs,
593 announced_prefixes: vec![],
594 };
595 assert!(!msg.is_end_of_rib());
596
597 let attrs = Attributes::from_iter(vec![AttributeValue::MpReachNlri(Nlri {
599 afi: Afi::Ipv4,
600 safi: Safi::Unicast,
601 next_hop: None,
602 prefixes: vec![],
603 link_state_nlris: None,
604 flowspec_nlris: None,
605 })]);
606 let msg = BgpUpdateMessage {
607 withdrawn_prefixes: vec![],
608 attributes: attrs,
609 announced_prefixes: vec![],
610 };
611 assert!(!msg.is_end_of_rib());
612
613 let attrs = Attributes::from_iter(vec![AttributeValue::MpReachNlri(Nlri {
615 afi: Afi::Ipv4,
616 safi: Safi::Unicast,
617 next_hop: None,
618 prefixes: vec![prefix],
619 link_state_nlris: None,
620 flowspec_nlris: None,
621 })]);
622 let msg = BgpUpdateMessage {
623 withdrawn_prefixes: vec![],
624 attributes: attrs,
625 announced_prefixes: vec![],
626 };
627 assert!(!msg.is_end_of_rib());
628
629 let attrs = Attributes::from_iter(vec![AttributeValue::MpUnreachNlri(Nlri {
631 afi: Afi::Ipv4,
632 safi: Safi::Unicast,
633 next_hop: None,
634 prefixes: vec![prefix],
635 link_state_nlris: None,
636 flowspec_nlris: None,
637 })]);
638 let msg = BgpUpdateMessage {
639 withdrawn_prefixes: vec![],
640 attributes: attrs,
641 announced_prefixes: vec![],
642 };
643 assert!(!msg.is_end_of_rib());
644
645 let attrs = Attributes::from_iter(vec![
647 AttributeValue::MpUnreachNlri(Nlri {
648 afi: Afi::Ipv4,
649 safi: Safi::Unicast,
650 next_hop: None,
651 prefixes: vec![],
652 link_state_nlris: None,
653 flowspec_nlris: None,
654 }),
655 AttributeValue::AtomicAggregate,
656 ]);
657 let msg = BgpUpdateMessage {
658 withdrawn_prefixes: vec![],
659 attributes: attrs,
660 announced_prefixes: vec![],
661 };
662 assert!(!msg.is_end_of_rib());
663 }
664
665 #[test]
666 fn test_invlaid_length() {
667 let bytes = Bytes::from_static(&[
668 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, ]);
675 let mut data = bytes.clone();
676 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_err());
677
678 let bytes = Bytes::from_static(&[
679 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x05, ]);
686 let mut data = bytes.clone();
687 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_err());
688 }
689
690 #[test]
691 fn test_invlaid_type() {
692 let bytes = Bytes::from_static(&[
693 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x05, ]);
700 let mut data = bytes.clone();
701 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_err());
702 }
703
704 #[test]
705 fn test_parse_bgp_notification_message() {
706 let bytes = Bytes::from_static(&[
707 0x01, 0x02, 0x00, 0x00, ]);
711 let msg = parse_bgp_notification_message(bytes).unwrap();
712 matches!(
713 msg.error,
714 BgpError::MessageHeaderError(MessageHeaderError::BAD_MESSAGE_LENGTH)
715 );
716 assert_eq!(msg.data, Bytes::from_static(&[0x00, 0x00]));
717 }
718
719 #[test]
720 fn test_encode_bgp_notification_messsage() {
721 let msg = BgpNotificationMessage {
722 error: BgpError::MessageHeaderError(MessageHeaderError::BAD_MESSAGE_LENGTH),
723 data: vec![0x00, 0x00],
724 };
725 let bytes = msg.encode();
726 assert_eq!(bytes, Bytes::from_static(&[0x01, 0x02, 0x00, 0x00]));
727 }
728
729 #[test]
730 fn test_parse_bgp_open_message() {
731 let bytes = Bytes::from_static(&[
732 0x04, 0x00, 0x01, 0x00, 0xb4, 0xc0, 0x00, 0x02, 0x01, 0x00, ]);
738 let msg = parse_bgp_open_message(&mut bytes.clone()).unwrap();
739 assert_eq!(msg.version, 4);
740 assert_eq!(msg.asn, Asn::new_16bit(1));
741 assert_eq!(msg.hold_time, 180);
742 assert_eq!(msg.sender_ip, Ipv4Addr::new(192, 0, 2, 1));
743 assert!(!msg.extended_length);
744 assert_eq!(msg.opt_params.len(), 0);
745 }
746
747 #[test]
748 fn test_encode_bgp_open_message() {
749 let msg = BgpOpenMessage {
750 version: 4,
751 asn: Asn::new_16bit(1),
752 hold_time: 180,
753 sender_ip: Ipv4Addr::new(192, 0, 2, 1),
754 extended_length: false,
755 opt_params: vec![],
756 };
757 let bytes = msg.encode();
758 assert_eq!(
759 bytes,
760 Bytes::from_static(&[
761 0x04, 0x00, 0x01, 0x00, 0xb4, 0xc0, 0x00, 0x02, 0x01, 0x00, ])
767 );
768 }
769
770 #[test]
771 fn test_encode_bgp_notification_message() {
772 let bgp_message = BgpMessage::Notification(BgpNotificationMessage {
773 error: BgpError::MessageHeaderError(MessageHeaderError::BAD_MESSAGE_LENGTH),
774 data: vec![0x00, 0x00],
775 });
776 let bytes = bgp_message.encode(AsnLength::Bits16);
777 assert_eq!(
778 bytes,
779 Bytes::from_static(&[
780 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
781 0x00, 0x00, 0x00, 0x17, 0x03, 0x01, 0x02, 0x00, 0x00
782 ])
783 );
784 }
785
786 #[test]
787 fn test_bgp_message_from_bgp_update_message() {
788 let msg = BgpMessage::from(BgpUpdateMessage::default());
789 assert!(matches!(msg, BgpMessage::Update(_)));
790 }
791
792 #[test]
793 fn test_parse_bgp_open_message_with_extended_next_hop_capability() {
794 use crate::models::{Afi, Safi};
795
796 let bytes = Bytes::from(vec![
802 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, ]);
818
819 let msg = parse_bgp_open_message(&mut bytes.clone()).unwrap();
820 assert_eq!(msg.version, 4);
821 assert_eq!(msg.asn, Asn::new_16bit(65001));
822 assert_eq!(msg.hold_time, 180);
823 assert_eq!(msg.sender_ip, Ipv4Addr::new(192, 0, 2, 1));
824 assert!(!msg.extended_length);
825 assert_eq!(msg.opt_params.len(), 1);
826
827 if let ParamValue::Capacities(cap) = &msg.opt_params[0].param_value {
829 assert_eq!(cap[0].ty, BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING);
830
831 if let CapabilityValue::ExtendedNextHop(enh_cap) = &cap[0].value {
832 assert_eq!(enh_cap.entries.len(), 2);
833
834 let entry1 = &enh_cap.entries[0];
836 assert_eq!(entry1.nlri_afi, Afi::Ipv4);
837 assert_eq!(entry1.nlri_safi, Safi::Unicast);
838 assert_eq!(entry1.nexthop_afi, Afi::Ipv6);
839
840 let entry2 = &enh_cap.entries[1];
842 assert_eq!(entry2.nlri_afi, Afi::Ipv4);
843 assert_eq!(entry2.nlri_safi, Safi::MplsVpn);
844 assert_eq!(entry2.nexthop_afi, Afi::Ipv6);
845
846 assert!(enh_cap.supports(Afi::Ipv4, Safi::Unicast, Afi::Ipv6));
848 assert!(enh_cap.supports(Afi::Ipv4, Safi::MplsVpn, Afi::Ipv6));
849 assert!(!enh_cap.supports(Afi::Ipv4, Safi::Multicast, Afi::Ipv6));
850 } else {
851 panic!("Expected ExtendedNextHop capability value");
852 }
853 } else {
854 panic!("Expected capability parameter");
855 }
856 }
857
858 #[test]
859 fn test_rfc8654_extended_message_length_validation() {
860 let bytes = Bytes::from_static(&[
862 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x00, 0x00,
870 0x00, ]);
873 let mut data = bytes.clone();
874 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_ok());
876
877 let bytes = Bytes::from_static(&[
879 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x01, ]);
886 let mut data = bytes.clone();
887 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
888 assert!(result.is_err());
889 if let Err(ParserError::ParseError(msg)) = result {
890 assert!(msg.contains("BGP OPEN message length"));
891 assert!(msg.contains("4096 bytes"));
892 }
893
894 let bytes = Bytes::from_static(&[
896 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x04, ]);
903 let mut data = bytes.clone();
904 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
905 assert!(result.is_err());
906 if let Err(ParserError::ParseError(msg)) = result {
907 assert!(msg.contains("BGP KEEPALIVE message length"));
908 assert!(msg.contains("4096 bytes"));
909 }
910
911 let bytes = Bytes::from_static(&[
913 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x02, ]);
920 let mut data = bytes.clone();
921 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
923 if let Err(ParserError::ParseError(msg)) = result {
924 assert!(!msg.contains("invalid BGP message length"));
926 }
927 }
928
929 #[test]
930 fn test_bgp_extended_message_capability_parsing() {
931 use crate::models::CapabilityValue;
932
933 let bytes = Bytes::from(vec![
935 0x04, 0x00, 0x01, 0x00, 0xb4, 0xc0, 0x00, 0x02, 0x01, 0x04, 0x02, 0x02, 0x06, 0x00, ]);
945
946 let msg = parse_bgp_open_message(&mut bytes.clone()).unwrap();
947 assert_eq!(msg.version, 4);
948 assert_eq!(msg.asn, Asn::new_16bit(1));
949 assert_eq!(msg.opt_params.len(), 1);
950
951 if let ParamValue::Capacities(cap) = &msg.opt_params[0].param_value {
953 assert_eq!(cap[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
954 if let CapabilityValue::BgpExtendedMessage(_) = &cap[0].value {
955 } else {
957 panic!("Expected BgpExtendedMessage capability value");
958 }
959 } else {
960 panic!("Expected capability parameter");
961 }
962 }
963
964 #[test]
965 fn test_rfc8654_edge_cases() {
966 let bytes = Bytes::from_static(&[
968 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x03, 0x06, 0x00, ]);
978 let mut data = bytes.clone();
979 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
981 if let Err(ParserError::ParseError(msg)) = result {
983 assert!(!msg.contains("invalid BGP message length"));
984 assert!(!msg.contains("exceeds maximum allowed 4096 bytes"));
985 }
986
987 let open_data = vec![
989 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, ];
996 let bytes = Bytes::from(open_data);
997 let mut data = bytes.clone();
998 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
999 if let Err(ParserError::ParseError(msg)) = result {
1001 assert!(!msg.contains("exceeds maximum allowed 4096 bytes"));
1002 }
1003
1004 let bytes = Bytes::from_static(&[
1006 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x02, ]);
1013 let mut data = bytes.clone();
1014 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1015 if let Err(ParserError::ParseError(msg)) = result {
1017 assert!(!msg.contains("invalid BGP message length"));
1018 }
1019 }
1020
1021 #[test]
1022 fn test_rfc8654_capability_encoding_path() {
1023 use crate::models::capabilities::BgpExtendedMessageCapability;
1024
1025 let capability_value =
1028 CapabilityValue::BgpExtendedMessage(BgpExtendedMessageCapability::new());
1029 let capability = Capability {
1030 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1031 value: capability_value,
1032 };
1033
1034 let opt_param = OptParam {
1035 param_type: 2, param_len: 2,
1037 param_value: ParamValue::Capacities(vec![capability]),
1038 };
1039
1040 let msg = BgpOpenMessage {
1041 version: 4,
1042 asn: Asn::new_16bit(65001),
1043 hold_time: 180,
1044 sender_ip: Ipv4Addr::new(192, 0, 2, 1),
1045 extended_length: false,
1046 opt_params: vec![opt_param],
1047 };
1048
1049 let encoded = msg.encode();
1051 assert!(!encoded.is_empty());
1052
1053 let parsed = parse_bgp_open_message(&mut encoded.clone()).unwrap();
1055 assert_eq!(parsed.opt_params.len(), 1);
1056 if let ParamValue::Capacities(cap) = &parsed.opt_params[0].param_value {
1057 assert_eq!(cap[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1058 }
1059 }
1060
1061 #[test]
1062 fn test_rfc8654_error_message_formatting() {
1063 let bytes = Bytes::from_static(&[
1068 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x01, ]);
1075 let mut data = bytes.clone();
1076 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1077 assert!(result.is_err());
1078 if let Err(ParserError::ParseError(msg)) = result {
1079 assert!(msg.contains("BGP OPEN message length"));
1080 assert!(msg.contains("exceeds maximum allowed 4096 bytes"));
1081 }
1082
1083 let bytes = Bytes::from_static(&[
1085 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x04, ]);
1092 let mut data = bytes.clone();
1093 let result = parse_bgp_message(&mut data, false, &AsnLength::Bits16);
1094 assert!(result.is_err());
1095 if let Err(ParserError::ParseError(msg)) = result {
1096 assert!(msg.contains("BGP KEEPALIVE message length"));
1097 assert!(msg.contains("exceeds maximum allowed 4096 bytes"));
1098 }
1099 }
1100
1101 #[test]
1102 fn test_encode_bgp_open_message_with_extended_message_capability() {
1103 use crate::models::capabilities::BgpExtendedMessageCapability;
1104
1105 let extended_msg_capability = BgpExtendedMessageCapability::new();
1107
1108 let msg = BgpOpenMessage {
1109 version: 4,
1110 asn: Asn::new_16bit(65001),
1111 hold_time: 180,
1112 sender_ip: Ipv4Addr::new(192, 0, 2, 1),
1113 extended_length: false,
1114 opt_params: vec![OptParam {
1115 param_type: 2, param_len: 2, param_value: ParamValue::Capacities(vec![Capability {
1118 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1119 value: CapabilityValue::BgpExtendedMessage(extended_msg_capability),
1120 }]),
1121 }],
1122 };
1123
1124 let encoded = msg.encode();
1125
1126 let parsed = parse_bgp_open_message(&mut encoded.clone()).unwrap();
1128 assert_eq!(parsed.version, msg.version);
1129 assert_eq!(parsed.asn, msg.asn);
1130 assert_eq!(parsed.hold_time, msg.hold_time);
1131 assert_eq!(parsed.sender_ip, msg.sender_ip);
1132 assert_eq!(parsed.opt_params.len(), 1);
1133
1134 if let ParamValue::Capacities(cap) = &parsed.opt_params[0].param_value {
1136 assert_eq!(cap[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1137 if let CapabilityValue::BgpExtendedMessage(_) = &cap[0].value {
1138 } else {
1140 panic!("Expected BgpExtendedMessage capability value after round trip");
1141 }
1142 } else {
1143 panic!("Expected capability parameter after round trip");
1144 }
1145 }
1146
1147 #[test]
1148 fn test_encode_bgp_open_message_with_extended_next_hop_capability() {
1149 use crate::models::capabilities::{ExtendedNextHopCapability, ExtendedNextHopEntry};
1150 use crate::models::{Afi, Safi};
1151
1152 let entries = vec![
1154 ExtendedNextHopEntry {
1155 nlri_afi: Afi::Ipv4,
1156 nlri_safi: Safi::Unicast,
1157 nexthop_afi: Afi::Ipv6,
1158 },
1159 ExtendedNextHopEntry {
1160 nlri_afi: Afi::Ipv4,
1161 nlri_safi: Safi::MplsVpn,
1162 nexthop_afi: Afi::Ipv6,
1163 },
1164 ];
1165 let enh_capability = ExtendedNextHopCapability::new(entries);
1166
1167 let msg = BgpOpenMessage {
1168 version: 4,
1169 asn: Asn::new_16bit(65001),
1170 hold_time: 180,
1171 sender_ip: Ipv4Addr::new(192, 0, 2, 1),
1172 extended_length: false,
1173 opt_params: vec![OptParam {
1174 param_type: 2, param_len: 14, param_value: ParamValue::Capacities(vec![Capability {
1177 ty: BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING,
1178 value: CapabilityValue::ExtendedNextHop(enh_capability),
1179 }]),
1180 }],
1181 };
1182
1183 let encoded = msg.encode();
1184
1185 let parsed = parse_bgp_open_message(&mut encoded.clone()).unwrap();
1187 assert_eq!(parsed.version, msg.version);
1188 assert_eq!(parsed.asn, msg.asn);
1189 assert_eq!(parsed.hold_time, msg.hold_time);
1190 assert_eq!(parsed.sender_ip, msg.sender_ip);
1191 assert_eq!(parsed.extended_length, msg.extended_length);
1192 assert_eq!(parsed.opt_params.len(), 1);
1193
1194 if let ParamValue::Capacities(cap) = &parsed.opt_params[0].param_value {
1196 assert_eq!(cap[0].ty, BgpCapabilityType::EXTENDED_NEXT_HOP_ENCODING);
1197 if let CapabilityValue::ExtendedNextHop(enh_cap) = &cap[0].value {
1198 assert_eq!(enh_cap.entries.len(), 2);
1199 assert!(enh_cap.supports(Afi::Ipv4, Safi::Unicast, Afi::Ipv6));
1200 assert!(enh_cap.supports(Afi::Ipv4, Safi::MplsVpn, Afi::Ipv6));
1201 } else {
1202 panic!("Expected ExtendedNextHop capability value after round trip");
1203 }
1204 } else {
1205 panic!("Expected capability parameter after round trip");
1206 }
1207 }
1208
1209 #[test]
1210 fn test_parse_bgp_open_message_with_multiple_capabilities() {
1211 let extended_msg_cap = Capability {
1216 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1217 value: CapabilityValue::BgpExtendedMessage(BgpExtendedMessageCapability {}),
1218 };
1219
1220 let route_refresh_cap = Capability {
1221 ty: BgpCapabilityType::ROUTE_REFRESH_CAPABILITY_FOR_BGP_4,
1222 value: CapabilityValue::RouteRefresh(RouteRefreshCapability {}),
1223 };
1224
1225 let four_octet_as_cap = Capability {
1226 ty: BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY,
1227 value: CapabilityValue::FourOctetAs(FourOctetAsCapability { asn: 65536 }),
1228 };
1229
1230 let msg = BgpOpenMessage {
1232 version: 4,
1233 asn: Asn::new_32bit(65000),
1234 hold_time: 180,
1235 sender_ip: "10.0.0.1".parse().unwrap(),
1236 extended_length: false,
1237 opt_params: vec![OptParam {
1238 param_type: 2, param_len: 10, param_value: ParamValue::Capacities(vec![
1241 extended_msg_cap,
1242 route_refresh_cap,
1243 four_octet_as_cap,
1244 ]),
1245 }],
1246 };
1247
1248 let encoded = msg.encode();
1250
1251 let mut encoded_bytes = encoded.clone();
1253 let parsed = parse_bgp_open_message(&mut encoded_bytes).unwrap();
1254
1255 assert_eq!(parsed.version, 4);
1257 assert_eq!(parsed.asn, Asn::new_32bit(65000));
1258 assert_eq!(parsed.hold_time, 180);
1259 assert_eq!(
1260 parsed.sender_ip,
1261 "10.0.0.1".parse::<std::net::Ipv4Addr>().unwrap()
1262 );
1263 assert_eq!(parsed.opt_params.len(), 1);
1264
1265 if let ParamValue::Capacities(caps) = &parsed.opt_params[0].param_value {
1267 assert_eq!(caps.len(), 3, "Should have 3 capabilities");
1268
1269 assert_eq!(caps[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1271 assert!(matches!(
1272 caps[0].value,
1273 CapabilityValue::BgpExtendedMessage(_)
1274 ));
1275
1276 assert_eq!(
1278 caps[1].ty,
1279 BgpCapabilityType::ROUTE_REFRESH_CAPABILITY_FOR_BGP_4
1280 );
1281 assert!(matches!(caps[1].value, CapabilityValue::RouteRefresh(_)));
1282
1283 assert_eq!(
1285 caps[2].ty,
1286 BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY
1287 );
1288 if let CapabilityValue::FourOctetAs(foa) = &caps[2].value {
1289 assert_eq!(foa.asn, 65536);
1290 } else {
1291 panic!("Expected FourOctetAs capability value");
1292 }
1293 } else {
1294 panic!("Expected Capacities parameter");
1295 }
1296 }
1297
1298 #[test]
1299 fn test_parse_bgp_open_message_with_multiple_capability_parameters() {
1300 let msg = BgpOpenMessage {
1304 version: 4,
1305 asn: Asn::new_32bit(65001),
1306 hold_time: 90,
1307 sender_ip: "192.168.1.1".parse().unwrap(),
1308 extended_length: false,
1309 opt_params: vec![
1310 OptParam {
1311 param_type: 2, param_len: 2,
1313 param_value: ParamValue::Capacities(vec![Capability {
1314 ty: BgpCapabilityType::BGP_EXTENDED_MESSAGE,
1315 value: CapabilityValue::BgpExtendedMessage(BgpExtendedMessageCapability {}),
1316 }]),
1317 },
1318 OptParam {
1319 param_type: 2, param_len: 6,
1321 param_value: ParamValue::Capacities(vec![Capability {
1322 ty: BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY,
1323 value: CapabilityValue::FourOctetAs(FourOctetAsCapability {
1324 asn: 4200000000,
1325 }),
1326 }]),
1327 },
1328 ],
1329 };
1330
1331 let encoded = msg.encode();
1333 let mut encoded_bytes = encoded.clone();
1334 let parsed = parse_bgp_open_message(&mut encoded_bytes).unwrap();
1335
1336 assert_eq!(parsed.opt_params.len(), 2);
1338
1339 if let ParamValue::Capacities(caps) = &parsed.opt_params[0].param_value {
1341 assert_eq!(caps.len(), 1);
1342 assert_eq!(caps[0].ty, BgpCapabilityType::BGP_EXTENDED_MESSAGE);
1343 } else {
1344 panic!("Expected Capacities in first parameter");
1345 }
1346
1347 if let ParamValue::Capacities(caps) = &parsed.opt_params[1].param_value {
1349 assert_eq!(caps.len(), 1);
1350 assert_eq!(
1351 caps[0].ty,
1352 BgpCapabilityType::SUPPORT_FOR_4_OCTET_AS_NUMBER_CAPABILITY
1353 );
1354 if let CapabilityValue::FourOctetAs(foa) = &caps[0].value {
1355 assert_eq!(foa.asn, 4200000000);
1356 }
1357 } else {
1358 panic!("Expected Capacities in second parameter");
1359 }
1360 }
1361}