1use crate::models::*;
2use bytes::{Buf, BufMut, Bytes, BytesMut};
3use std::convert::TryFrom;
4
5use crate::error::ParserError;
6use crate::models::capabilities::BgpCapabilityType;
7use crate::models::error::BgpError;
8use crate::parser::bgp::attributes::parse_attributes;
9use crate::parser::{encode_ipaddr, encode_nlri_prefixes, parse_nlri_list, ReadUtils};
10use log::warn;
11
12pub fn parse_bgp_message(
31 data: &mut Bytes,
32 add_path: bool,
33 asn_len: &AsnLength,
34) -> Result<BgpMessage, ParserError> {
35 let total_size = data.len();
36 data.has_n_remaining(19)?;
37 data.advance(16);
38 let length = data.get_u16();
50 if !(19..=4096).contains(&length) {
51 return Err(ParserError::ParseError(format!(
52 "invalid BGP message length {}",
53 length
54 )));
55 }
56
57 let bgp_msg_length = if (length as usize) > total_size {
58 total_size - 19
59 } else {
60 length as usize - 19
61 };
62
63 let msg_type: BgpMessageType = match BgpMessageType::try_from(data.get_u8()) {
64 Ok(t) => t,
65 Err(_) => {
66 return Err(ParserError::ParseError(
67 "Unknown BGP Message Type".to_string(),
68 ))
69 }
70 };
71
72 if data.remaining() != bgp_msg_length {
73 warn!(
74 "BGP message length {} does not match the actual length {}",
75 bgp_msg_length,
76 data.remaining()
77 );
78 }
79 data.has_n_remaining(bgp_msg_length)?;
80 let mut msg_data = data.split_to(bgp_msg_length);
81
82 Ok(match msg_type {
83 BgpMessageType::OPEN => BgpMessage::Open(parse_bgp_open_message(&mut msg_data)?),
84 BgpMessageType::UPDATE => {
85 BgpMessage::Update(parse_bgp_update_message(msg_data, add_path, asn_len)?)
86 }
87 BgpMessageType::NOTIFICATION => {
88 BgpMessage::Notification(parse_bgp_notification_message(msg_data)?)
89 }
90 BgpMessageType::KEEPALIVE => BgpMessage::KeepAlive,
91 })
92}
93
94pub fn parse_bgp_notification_message(
101 mut input: Bytes,
102) -> Result<BgpNotificationMessage, ParserError> {
103 let error_code = input.read_u8()?;
104 let error_subcode = input.read_u8()?;
105
106 Ok(BgpNotificationMessage {
107 error: BgpError::new(error_code, error_subcode),
108 data: input.read_n_bytes(input.len())?,
109 })
110}
111
112impl BgpNotificationMessage {
113 pub fn encode(&self) -> Bytes {
114 let mut buf = BytesMut::new();
115 let (code, subcode) = self.error.get_codes();
116 buf.put_u8(code);
117 buf.put_u8(subcode);
118 buf.put_slice(&self.data);
119 buf.freeze()
120 }
121}
122
123pub fn parse_bgp_open_message(input: &mut Bytes) -> Result<BgpOpenMessage, ParserError> {
127 input.has_n_remaining(10)?;
128 let version = input.get_u8();
129 let asn = Asn::new_16bit(input.get_u16());
130 let hold_time = input.get_u16();
131
132 let sender_ip = input.read_ipv4_address()?;
133 let mut opt_params_len: u16 = input.get_u8() as u16;
134
135 let mut extended_length = false;
136 let mut first = true;
137
138 let mut params: Vec<OptParam> = vec![];
139 while input.remaining() >= 2 {
140 let mut param_type = input.get_u8();
141 if first {
142 if opt_params_len == 255 && param_type == 255 {
144 extended_length = true;
165 opt_params_len = input.read_u16()?;
166 if opt_params_len == 0 {
167 break;
168 }
169 if input.remaining() != opt_params_len as usize {
171 warn!(
172 "BGP open message length {} does not match the actual length {}",
173 opt_params_len,
174 input.remaining()
175 );
176 }
177
178 param_type = input.read_u8()?;
179 }
180 first = false;
181 }
182 let param_len = match extended_length {
185 true => input.read_u16()?,
186 false => input.read_u8()? as u16,
187 };
188 let param_value = match param_type {
192 2 => {
193 let code = input.read_u8()?;
196 let len = match extended_length {
197 true => input.read_u16()?,
198 false => input.read_u8()? as u16,
199 };
200
201 ParamValue::Capability(Capability {
202 ty: BgpCapabilityType::from(code),
203 value: input.read_n_bytes(len as usize)?,
204 })
205 }
206 _ => {
207 let bytes = input.read_n_bytes(param_len as usize)?;
209 ParamValue::Raw(bytes)
210 }
211 };
212 params.push(OptParam {
213 param_type,
214 param_len,
215 param_value,
216 });
217 }
218
219 Ok(BgpOpenMessage {
220 version,
221 asn,
222 hold_time,
223 sender_ip,
224 extended_length,
225 opt_params: params,
226 })
227}
228
229impl BgpOpenMessage {
230 pub fn encode(&self) -> Bytes {
231 let mut buf = BytesMut::new();
232 buf.put_u8(self.version);
233 buf.put_u16(self.asn.into());
234 buf.put_u16(self.hold_time);
235 buf.extend(encode_ipaddr(&self.sender_ip.into()));
236 buf.put_u8(self.opt_params.len() as u8);
237 for param in &self.opt_params {
238 buf.put_u8(param.param_type);
239 buf.put_u8(param.param_len as u8);
240 match ¶m.param_value {
241 ParamValue::Capability(cap) => {
242 buf.put_u8(cap.ty.into());
243 buf.put_u8(cap.value.len() as u8);
244 buf.extend(&cap.value);
245 }
246 ParamValue::Raw(bytes) => {
247 buf.extend(bytes);
248 }
249 }
250 }
251 buf.freeze()
252 }
253}
254
255fn read_nlri(
257 mut input: Bytes,
258 afi: &Afi,
259 add_path: bool,
260) -> Result<Vec<NetworkPrefix>, ParserError> {
261 let length = input.len();
262 if length == 0 {
263 return Ok(vec![]);
264 }
265 if length == 1 {
266 warn!("seeing strange one-byte NLRI field");
268 input.advance(1); return Ok(vec![]);
270 }
271
272 parse_nlri_list(input, add_path, afi)
273}
274
275pub fn parse_bgp_update_message(
279 mut input: Bytes,
280 add_path: bool,
281 asn_len: &AsnLength,
282) -> Result<BgpUpdateMessage, ParserError> {
283 let afi = Afi::Ipv4;
285
286 let withdrawn_bytes_length = input.read_u16()? as usize;
288 input.has_n_remaining(withdrawn_bytes_length)?;
289 let withdrawn_bytes = input.split_to(withdrawn_bytes_length);
290 let withdrawn_prefixes = read_nlri(withdrawn_bytes, &afi, add_path)?;
291
292 let attribute_length = input.read_u16()? as usize;
294
295 input.has_n_remaining(attribute_length)?;
296 let attr_data_slice = input.split_to(attribute_length);
297 let attributes = parse_attributes(attr_data_slice, asn_len, add_path, None, None, None)?;
298
299 let announced_prefixes = read_nlri(input, &afi, add_path)?;
302
303 Ok(BgpUpdateMessage {
304 withdrawn_prefixes,
305 attributes,
306 announced_prefixes,
307 })
308}
309
310impl BgpUpdateMessage {
311 pub fn encode(&self, add_path: bool, asn_len: AsnLength) -> Bytes {
312 let mut bytes = BytesMut::new();
313
314 let withdrawn_bytes = encode_nlri_prefixes(&self.withdrawn_prefixes, add_path);
316 bytes.put_u16(withdrawn_bytes.len() as u16);
317 bytes.put_slice(&withdrawn_bytes);
318
319 let attr_bytes = self.attributes.encode(add_path, asn_len);
321
322 bytes.put_u16(attr_bytes.len() as u16);
323 bytes.put_slice(&attr_bytes);
324
325 bytes.extend(encode_nlri_prefixes(&self.announced_prefixes, add_path));
326 bytes.freeze()
327 }
328
329 pub fn is_end_of_rib(&self) -> bool {
334 if !self.announced_prefixes.is_empty() || !self.withdrawn_prefixes.is_empty() {
339 return false;
343 }
344
345 if self.attributes.inner.is_empty() {
346 return true;
349 }
350
351 if self.attributes.inner.len() > 1 {
354 return false;
356 }
357
358 if let AttributeValue::MpUnreachNlri(nlri) = &self.attributes.inner.first().unwrap().value {
360 if nlri.prefixes.is_empty() {
361 return true;
364 }
365 }
366
367 false
369 }
370}
371
372impl BgpMessage {
373 pub fn encode(&self, add_path: bool, asn_len: AsnLength) -> Bytes {
374 let mut bytes = BytesMut::new();
375 bytes.put_u32(0); bytes.put_u32(0); bytes.put_u32(0); bytes.put_u32(0); let (msg_type, msg_bytes) = match self {
381 BgpMessage::Open(msg) => (BgpMessageType::OPEN, msg.encode()),
382 BgpMessage::Update(msg) => (BgpMessageType::UPDATE, msg.encode(add_path, asn_len)),
383 BgpMessage::Notification(msg) => (BgpMessageType::NOTIFICATION, msg.encode()),
384 BgpMessage::KeepAlive => (BgpMessageType::KEEPALIVE, Bytes::new()),
385 };
386
387 bytes.put_u16(msg_bytes.len() as u16 + 16 + 2 + 1);
389 bytes.put_u8(msg_type as u8);
390 bytes.put_slice(&msg_bytes);
391 bytes.freeze()
392 }
393}
394
395impl From<&BgpElem> for BgpUpdateMessage {
396 fn from(elem: &BgpElem) -> Self {
397 BgpUpdateMessage {
398 withdrawn_prefixes: vec![],
399 attributes: Attributes::from(elem),
400 announced_prefixes: vec![],
401 }
402 }
403}
404
405impl From<BgpUpdateMessage> for BgpMessage {
406 fn from(value: BgpUpdateMessage) -> Self {
407 BgpMessage::Update(value)
408 }
409}
410
411#[cfg(test)]
412mod tests {
413 use super::*;
414 use std::net::Ipv4Addr;
415 use std::str::FromStr;
416
417 #[test]
418 fn test_end_of_rib() {
419 let attrs = Attributes::default();
421 let msg = BgpUpdateMessage {
422 withdrawn_prefixes: vec![],
423 attributes: attrs,
424 announced_prefixes: vec![],
425 };
426 assert!(msg.is_end_of_rib());
427
428 let attrs = Attributes::from_iter(vec![AttributeValue::MpUnreachNlri(Nlri {
430 afi: Afi::Ipv4,
431 safi: Safi::Unicast,
432 next_hop: None,
433 prefixes: vec![],
434 })]);
435 let msg = BgpUpdateMessage {
436 withdrawn_prefixes: vec![],
437 attributes: attrs,
438 announced_prefixes: vec![],
439 };
440 assert!(msg.is_end_of_rib());
441
442 let prefix = NetworkPrefix::from_str("192.168.1.0/24").unwrap();
444 let attrs = Attributes::default();
445 let msg = BgpUpdateMessage {
446 withdrawn_prefixes: vec![],
447 attributes: attrs,
448 announced_prefixes: vec![prefix],
449 };
450 assert!(!msg.is_end_of_rib());
451
452 let prefix = NetworkPrefix::from_str("192.168.1.0/24").unwrap();
454 let attrs = Attributes::default();
455 let msg = BgpUpdateMessage {
456 withdrawn_prefixes: vec![prefix],
457 attributes: attrs,
458 announced_prefixes: vec![],
459 };
460 assert!(!msg.is_end_of_rib());
461
462 let attrs = Attributes::from_iter(vec![AttributeValue::MpReachNlri(Nlri {
464 afi: Afi::Ipv4,
465 safi: Safi::Unicast,
466 next_hop: None,
467 prefixes: vec![],
468 })]);
469 let msg = BgpUpdateMessage {
470 withdrawn_prefixes: vec![],
471 attributes: attrs,
472 announced_prefixes: vec![],
473 };
474 assert!(!msg.is_end_of_rib());
475
476 let attrs = Attributes::from_iter(vec![AttributeValue::MpReachNlri(Nlri {
478 afi: Afi::Ipv4,
479 safi: Safi::Unicast,
480 next_hop: None,
481 prefixes: vec![prefix],
482 })]);
483 let msg = BgpUpdateMessage {
484 withdrawn_prefixes: vec![],
485 attributes: attrs,
486 announced_prefixes: vec![],
487 };
488 assert!(!msg.is_end_of_rib());
489
490 let attrs = Attributes::from_iter(vec![AttributeValue::MpUnreachNlri(Nlri {
492 afi: Afi::Ipv4,
493 safi: Safi::Unicast,
494 next_hop: None,
495 prefixes: vec![prefix],
496 })]);
497 let msg = BgpUpdateMessage {
498 withdrawn_prefixes: vec![],
499 attributes: attrs,
500 announced_prefixes: vec![],
501 };
502 assert!(!msg.is_end_of_rib());
503
504 let attrs = Attributes::from_iter(vec![
506 AttributeValue::MpUnreachNlri(Nlri {
507 afi: Afi::Ipv4,
508 safi: Safi::Unicast,
509 next_hop: None,
510 prefixes: vec![],
511 }),
512 AttributeValue::AtomicAggregate,
513 ]);
514 let msg = BgpUpdateMessage {
515 withdrawn_prefixes: vec![],
516 attributes: attrs,
517 announced_prefixes: vec![],
518 };
519 assert!(!msg.is_end_of_rib());
520 }
521
522 #[test]
523 fn test_invlaid_length() {
524 let bytes = Bytes::from_static(&[
525 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, ]);
532 let mut data = bytes.clone();
533 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_err());
534
535 let bytes = Bytes::from_static(&[
536 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x05, ]);
543 let mut data = bytes.clone();
544 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_err());
545 }
546
547 #[test]
548 fn test_invlaid_type() {
549 let bytes = Bytes::from_static(&[
550 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x05, ]);
557 let mut data = bytes.clone();
558 assert!(parse_bgp_message(&mut data, false, &AsnLength::Bits16).is_err());
559 }
560
561 #[test]
562 fn test_parse_bgp_notification_message() {
563 let bytes = Bytes::from_static(&[
564 0x01, 0x02, 0x00, 0x00, ]);
568 let msg = parse_bgp_notification_message(bytes).unwrap();
569 matches!(
570 msg.error,
571 BgpError::MessageHeaderError(MessageHeaderError::BAD_MESSAGE_LENGTH)
572 );
573 assert_eq!(msg.data, Bytes::from_static(&[0x00, 0x00]));
574 }
575
576 #[test]
577 fn test_encode_bgp_notification_messsage() {
578 let msg = BgpNotificationMessage {
579 error: BgpError::MessageHeaderError(MessageHeaderError::BAD_MESSAGE_LENGTH),
580 data: vec![0x00, 0x00],
581 };
582 let bytes = msg.encode();
583 assert_eq!(bytes, Bytes::from_static(&[0x01, 0x02, 0x00, 0x00]));
584 }
585
586 #[test]
587 fn test_parse_bgp_open_message() {
588 let bytes = Bytes::from_static(&[
589 0x04, 0x00, 0x01, 0x00, 0xb4, 0xc0, 0x00, 0x02, 0x01, 0x00, ]);
595 let msg = parse_bgp_open_message(&mut bytes.clone()).unwrap();
596 assert_eq!(msg.version, 4);
597 assert_eq!(msg.asn, Asn::new_16bit(1));
598 assert_eq!(msg.hold_time, 180);
599 assert_eq!(msg.sender_ip, Ipv4Addr::new(192, 0, 2, 1));
600 assert!(!msg.extended_length);
601 assert_eq!(msg.opt_params.len(), 0);
602 }
603
604 #[test]
605 fn test_encode_bgp_open_message() {
606 let msg = BgpOpenMessage {
607 version: 4,
608 asn: Asn::new_16bit(1),
609 hold_time: 180,
610 sender_ip: Ipv4Addr::new(192, 0, 2, 1),
611 extended_length: false,
612 opt_params: vec![],
613 };
614 let bytes = msg.encode();
615 assert_eq!(
616 bytes,
617 Bytes::from_static(&[
618 0x04, 0x00, 0x01, 0x00, 0xb4, 0xc0, 0x00, 0x02, 0x01, 0x00, ])
624 );
625 }
626
627 #[test]
628 fn test_encode_bgp_notification_message() {
629 let bgp_message = BgpMessage::Notification(BgpNotificationMessage {
630 error: BgpError::MessageHeaderError(MessageHeaderError::BAD_MESSAGE_LENGTH),
631 data: vec![0x00, 0x00],
632 });
633 let bytes = bgp_message.encode(false, AsnLength::Bits16);
634 assert_eq!(
635 bytes,
636 Bytes::from_static(&[
637 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638 0x00, 0x00, 0x00, 0x17, 0x03, 0x01, 0x02, 0x00, 0x00
639 ])
640 );
641 }
642
643 #[test]
644 fn test_bgp_message_from_bgp_update_message() {
645 let msg = BgpMessage::from(BgpUpdateMessage::default());
646 assert!(matches!(msg, BgpMessage::Update(_)));
647 }
648}