bgp_rs/lib.rs
1#![deny(missing_docs)]
2
3//! The `bgp-rs` crate provides functionality to parse BGP-formatted streams.
4//!
5//! # Examples
6//!
7//! ## Reading a MRT file containing BPG4MP messages
8//! ```
9//! use std::fs::File;
10//! use std::io::Cursor;
11//! use std::io::Read;
12//! use std::io::BufReader;
13//! use libflate::gzip::Decoder;
14//! use bgp_rs::{Identifier, PathAttribute};
15//! use mrt_rs::Record;
16//! use mrt_rs::bgp4mp::BGP4MP;
17//!
18//! // Download an update message.
19//! let file = File::open("res/mrt/updates.20190101.0000.gz").unwrap();
20//!
21//! // Decode the GZIP stream.
22//! let mut decoder = Decoder::new(BufReader::new(file)).unwrap();
23//!
24//! // Keep reading MRT (Header, Record) tuples till the end of the file has been reached.
25//! while let Ok(Some((_, record))) = mrt_rs::read(&mut decoder) {
26//!
27//! // Extract BGP4MP::MESSAGE_AS4 entries.
28//! if let Record::BGP4MP(BGP4MP::MESSAGE_AS4(x)) = record {
29//!
30//! // Read each BGP (Header, Message)
31//! let cursor = Cursor::new(x.message);
32//! let mut reader = bgp_rs::Reader::new(cursor);
33//! let (_, message) = reader.read().unwrap();
34//!
35//! // If this is an UPDATE message that contains announcements, extract its origin.
36//! if let bgp_rs::Message::Update(x) = message {
37//! if x.is_announcement() {
38//! if let PathAttribute::AS_PATH(path) = x.get(Identifier::AS_PATH).unwrap()
39//! {
40//! // Test the path.origin() method.
41//! let origin = path.origin();
42//!
43//! // Do other stuff ...
44//! }
45//! }
46//! }
47//! }
48//! }
49//! ```
50//!
51//! ## Reading a MRT file containing TABLE_DUMP_V2 messages
52//! ```
53//! use std::fs::File;
54//! use std::io::Cursor;
55//! use std::io::Read;
56//! use std::io::BufReader;
57//! use libflate::gzip::Decoder;
58//! use bgp_rs::{Identifier, PathAttribute, Capabilities};
59//! use mrt_rs::records::tabledump::TABLE_DUMP_V2;
60//! use mrt_rs::Record;
61//! use mrt_rs::bgp4mp::BGP4MP;
62//!
63//! // Download an update message.
64//! let file = File::open("res/mrt/bview.20100101.0759.gz").unwrap();
65//!
66//! // Decode the GZIP stream.
67//! let mut decoder = Decoder::new(BufReader::new(file)).unwrap();
68//!
69//! // Keep reading MRT (Header, Record) tuples till the end of the file has been reached.
70//! while let Ok(Some((_, record))) = mrt_rs::read(&mut decoder) {
71//!
72//! // Extract TABLE_DUMP_V2::RIB_IPV4_UNICAST entries.
73//! if let Record::TABLE_DUMP_V2(TABLE_DUMP_V2::RIB_IPV4_UNICAST(x)) = record {
74//!
75//! // Loop over each route for this particular prefix.
76//! for mut entry in x.entries {
77//! let length = entry.attributes.len() as u64;
78//! let mut cursor = Cursor::new(entry.attributes);
79//!
80//! // Parse each PathAttribute in each route.
81//! while cursor.position() < length {
82//! PathAttribute::parse(&mut cursor, &Default::default()).unwrap();
83//! }
84//! }
85//! }
86//! }
87//! ```
88/// Contains the OPEN Message implementation
89pub mod open;
90pub use crate::open::*;
91/// Contains the NOTIFICATION Message implementation
92pub mod notification;
93pub use crate::notification::*;
94/// Contains the UPDATE Message implementation
95pub mod update;
96pub use crate::update::*;
97
98mod util;
99
100use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
101
102use std::convert::TryFrom;
103use std::fmt::{Debug, Display, Formatter};
104use std::io::{Error, ErrorKind, Read, Write};
105
106// RFC 4271: 4.1
107const BGP_MIN_MESSAGE_SIZE: usize = 19;
108const BGP_MAX_MESSAGE_SIZE: usize = 4096;
109
110/// Represents an Address Family Identifier. Currently only IPv4 and IPv6 are supported.
111/// Currently only IPv4, IPv6, and L2VPN are supported.
112#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
113#[repr(u16)]
114pub enum AFI {
115 /// Internet Protocol version 4 (32 bits)
116 IPV4 = 0x01,
117 /// Internet Protocol version 6 (128 bits)
118 IPV6 = 0x02,
119 /// L2VPN
120 L2VPN = 0x19,
121 /// BGPLS
122 BGPLS = 0x4004,
123}
124
125impl AFI {
126 fn empty_buffer(&self) -> Vec<u8> {
127 match self {
128 AFI::IPV4 => vec![0u8; 4],
129 AFI::IPV6 => vec![0u8; 16],
130 _ => unimplemented!(),
131 }
132 }
133}
134
135/// Convert u16 to AFI
136/// ```
137/// use std::convert::TryFrom;
138/// use bgp_rs::AFI;
139/// let val = 2u16;
140/// let afi = AFI::try_from(val).unwrap();
141/// assert_eq!(afi, AFI::IPV6);
142/// ```
143impl TryFrom<u16> for AFI {
144 type Error = Error;
145 fn try_from(v: u16) -> Result<Self, Self::Error> {
146 match v {
147 0x01 => Ok(AFI::IPV4),
148 0x02 => Ok(AFI::IPV6),
149 0x19 => Ok(AFI::L2VPN),
150 0x4004 => Ok(AFI::BGPLS),
151 _ => Err(Error::new(
152 ErrorKind::Other,
153 format!("Not a supported AFI: '{}'", v),
154 )),
155 }
156 }
157}
158
159/// Display AFI in a human-friendly format
160/// ```
161/// use bgp_rs::AFI;
162/// let afi = AFI::IPV6;
163/// assert_eq!(&afi.to_string(), "IPv6");
164/// ```
165impl Display for AFI {
166 fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> {
167 use AFI::*;
168 let s = match self {
169 IPV4 => "IPv4",
170 IPV6 => "IPv6",
171 L2VPN => "L2VPN",
172 BGPLS => "BGPLS",
173 };
174 write!(f, "{}", s)
175 }
176}
177
178/// Represents an Subsequent Address Family Identifier. Currently only Unicast and Multicast are
179/// supported.
180#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
181#[repr(u8)]
182pub enum SAFI {
183 /// Unicast Forwarding [RFC4760]
184 Unicast = 1,
185 /// Multicast Forwarding [RFC4760]
186 Multicast = 2,
187 /// MPLS Labels [RFC3107]
188 Mpls = 4,
189 /// Multicast VPN
190 MulticastVpn = 5,
191 /// VPLS [draft-ietf-l2vpn-evpn]
192 Vpls = 65,
193 /// EVPN [draft-ietf-l2vpn-evpn]
194 Evpn = 70,
195 /// BGP LS [RFC7752]
196 BgpLs = 71,
197 /// BGP LS VPN [RFC7752]
198 BgpLsVpn = 72,
199 /// RTC [RFC4684]
200 Rtc = 132,
201 /// MPLS VPN [RFC4364]
202 MplsVpn = 128,
203 /// Flowspec Unicast
204 Flowspec = 133,
205 /// Flowspec Unicast
206 FlowspecVPN = 134,
207}
208
209/// Convert u8 to SAFI
210/// ```
211/// use std::convert::TryFrom;
212/// use bgp_rs::SAFI;
213/// let val = 1u8;
214/// let safi = SAFI::try_from(val).unwrap();
215/// assert_eq!(safi, SAFI::Unicast);
216/// ```
217impl TryFrom<u8> for SAFI {
218 type Error = Error;
219
220 fn try_from(v: u8) -> Result<Self, Self::Error> {
221 match v {
222 1 => Ok(SAFI::Unicast),
223 2 => Ok(SAFI::Multicast),
224 4 => Ok(SAFI::Mpls),
225 5 => Ok(SAFI::MulticastVpn),
226 65 => Ok(SAFI::Vpls),
227 70 => Ok(SAFI::Evpn),
228 71 => Ok(SAFI::BgpLs),
229 72 => Ok(SAFI::BgpLsVpn),
230 128 => Ok(SAFI::MplsVpn),
231 132 => Ok(SAFI::Rtc),
232 133 => Ok(SAFI::Flowspec),
233 134 => Ok(SAFI::FlowspecVPN),
234 _ => Err(std::io::Error::new(
235 std::io::ErrorKind::Other,
236 format!("Not a supported SAFI: '{}'", v),
237 )),
238 }
239 }
240}
241
242/// Display SAFI in a human-friendly format
243/// ```
244/// use bgp_rs::SAFI;
245/// let safi = SAFI::Flowspec;
246/// assert_eq!(&safi.to_string(), "Flowspec");
247/// ```
248impl Display for SAFI {
249 fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> {
250 use SAFI::*;
251 let s = match self {
252 Unicast => "Unicast",
253 Multicast => "Multicast",
254 Mpls => "MPLS",
255 MulticastVpn => "Multicast VPN",
256 Vpls => "VPLS",
257 Evpn => "EVPN",
258 BgpLs => "BGPLS",
259 BgpLsVpn => "BGPLSVPN",
260 Rtc => "RTC",
261 MplsVpn => "MPLS VPN",
262 Flowspec => "Flowspec",
263 FlowspecVPN => "Flowspec VPN",
264 };
265 write!(f, "{}", s)
266 }
267}
268
269/// Represents the BGP header accompanying every BGP message.
270#[derive(Clone, Debug)]
271pub struct Header {
272 /// Predefined marker, must be set to all ones.
273 pub marker: [u8; 16],
274
275 /// Indicates the total length of the message, including the header in bytes.
276 pub length: u16,
277
278 /// Indicates the type of message that follows the header.
279 pub record_type: u8,
280}
281
282impl Header {
283 /// parse
284 pub fn parse(stream: &mut impl Read) -> Result<Header, Error> {
285 let mut marker = [0u8; 16];
286 stream.read_exact(&mut marker)?;
287
288 let length = stream.read_u16::<BigEndian>()?;
289 let record_type = stream.read_u8()?;
290
291 Ok(Header {
292 marker,
293 length,
294 record_type,
295 })
296 }
297
298 /// Writes self into the stream, including the length and record type.
299 pub fn encode(&self, buf: &mut impl Write) -> Result<(), Error> {
300 buf.write_all(&self.marker)?;
301 buf.write_u16::<BigEndian>(self.length)?;
302 buf.write_u8(self.record_type)
303 }
304}
305
306/// Represents a single BGP message.
307#[derive(Clone, Debug)]
308pub enum Message {
309 /// Represent a BGP OPEN message.
310 Open(Open),
311
312 /// Represent a BGP UPDATE message.
313 Update(Update),
314
315 /// Represent a BGP NOTIFICATION message.
316 Notification(Notification),
317
318 /// Represent a BGP KEEPALIVE message.
319 KeepAlive,
320
321 /// Represent a BGP ROUTE_REFRESH message.
322 RouteRefresh(RouteRefresh),
323}
324
325impl Message {
326 fn encode_noheader(&self, buf: &mut impl Write) -> Result<(), Error> {
327 match self {
328 Message::Open(open) => open.encode(buf),
329 Message::Update(update) => update.encode(buf),
330 Message::Notification(notification) => notification.encode(buf),
331 Message::KeepAlive => Ok(()),
332 Message::RouteRefresh(refresh) => refresh.encode(buf),
333 }
334 }
335
336 /// Writes message into the stream, including the appropriate header.
337 pub fn encode(&self, buf: &mut impl Write) -> Result<(), Error> {
338 let mut message_buf: Vec<u8> = Vec::with_capacity(BGP_MIN_MESSAGE_SIZE); // Start with minimum size
339 self.encode_noheader(&mut message_buf)?;
340 let message_length = message_buf.len();
341 if (message_length + BGP_MIN_MESSAGE_SIZE) > BGP_MAX_MESSAGE_SIZE {
342 return Err(Error::new(
343 ErrorKind::Other,
344 format!("Cannot encode message of length {}", message_length),
345 ));
346 }
347 let header = Header {
348 marker: [0xff; 16],
349 length: (message_length + BGP_MIN_MESSAGE_SIZE) as u16,
350 record_type: match self {
351 Message::Open(_) => 1,
352 Message::Update(_) => 2,
353 Message::Notification(_) => 3,
354 Message::KeepAlive => 4,
355 Message::RouteRefresh(_) => 5,
356 },
357 };
358 header.encode(buf)?;
359 buf.write_all(&message_buf)
360 }
361}
362
363/// Represents a BGP Route Refresh message.
364#[derive(Clone, Debug)]
365pub struct RouteRefresh {
366 /// Address Family being requested
367 pub afi: AFI,
368 /// Subsequent Address Family being requested
369 pub safi: SAFI,
370 /// This can be a subtype or RESERVED=0 for older senders
371 pub subtype: u8,
372}
373
374impl RouteRefresh {
375 fn parse(stream: &mut impl Read) -> Result<RouteRefresh, Error> {
376 let afi = AFI::try_from(stream.read_u16::<BigEndian>()?)?;
377 let subtype = stream.read_u8()?;
378 let safi = SAFI::try_from(stream.read_u8()?)?;
379
380 Ok(RouteRefresh { afi, safi, subtype })
381 }
382
383 /// Encode RouteRefresh to bytes
384 pub fn encode(&self, buf: &mut impl Write) -> Result<(), Error> {
385 buf.write_u16::<BigEndian>(self.afi as u16)?;
386 buf.write_u8(self.subtype)?;
387 buf.write_u8(self.safi as u8)
388 }
389}
390
391/// An abstract way of getting a reference to a Capabilities struct.
392/// This is used in Reader to allow use of either an owned Capabilites or a reference to one.
393pub trait CapabilitiesRef {
394 /// Gets a reference to the Capabilities
395 fn get_ref(&self) -> &Capabilities;
396}
397impl CapabilitiesRef for Capabilities {
398 fn get_ref(&self) -> &Capabilities {
399 self
400 }
401}
402impl<'a> CapabilitiesRef for &'a Capabilities {
403 fn get_ref(&self) -> &Capabilities {
404 self
405 }
406}
407
408/// The BGPReader can read BGP messages from a BGP-formatted stream.
409pub struct Reader<T, C>
410where
411 T: Read,
412 C: CapabilitiesRef,
413{
414 /// The stream from which BGP messages will be read.
415 pub stream: T,
416
417 /// Capability parameters that distinguish how BGP messages should be parsed.
418 pub capabilities: C,
419}
420
421impl<T, C> Reader<T, C>
422where
423 T: Read,
424 C: CapabilitiesRef,
425{
426 ///
427 /// Reads the next BGP message in the stream.
428 ///
429 /// # Panics
430 /// This function does not panic.
431 ///
432 /// # Errors
433 /// Any IO error will be returned while reading from the stream.
434 /// If an ill-formatted stream provided behavior will be undefined.
435 ///
436 /// # Safety
437 /// This function does not make use of unsafe code.
438 ///
439 pub fn read(&mut self) -> Result<(Header, Message), Error> {
440 // Parse the header.
441 let mut marker: [u8; 16] = [0; 16];
442 self.stream.read_exact(&mut marker)?;
443
444 let header = Header {
445 marker,
446 length: self.stream.read_u16::<BigEndian>()?,
447 record_type: self.stream.read_u8()?,
448 };
449
450 match header.record_type {
451 1 => Ok((header, Message::Open(Open::parse(&mut self.stream)?))),
452 2 => {
453 let attribute = Message::Update(Update::parse(
454 &header,
455 &mut self.stream,
456 self.capabilities.get_ref(),
457 )?);
458 Ok((header, attribute))
459 }
460 3 => {
461 let attribute =
462 Message::Notification(Notification::parse(&header, &mut self.stream)?);
463 Ok((header, attribute))
464 }
465 4 => Ok((header, Message::KeepAlive)),
466 5 => Ok((
467 header,
468 Message::RouteRefresh(RouteRefresh::parse(&mut self.stream)?),
469 )),
470 _ => Err(Error::new(
471 ErrorKind::Other,
472 "Unknown BGP message type found in BGPHeader",
473 )),
474 }
475 }
476}
477
478impl<T> Reader<T, Capabilities>
479where
480 T: Read,
481{
482 ///
483 /// Constructs a BGPReader with default parameters.
484 ///
485 /// # Panics
486 /// This function does not panic.
487 ///
488 /// # Errors
489 /// Any IO error will be returned while reading from the stream.
490 /// If an ill-formatted stream provided behavior will be undefined.
491 ///
492 /// # Safety
493 /// This function does not make use of unsafe code.
494 ///
495 ///
496 pub fn new(stream: T) -> Self
497 where
498 T: Read,
499 {
500 Reader::<T, Capabilities> {
501 stream,
502 capabilities: Default::default(),
503 }
504 }
505}