diff --git a/src/bgp/attributes.rs b/src/bgp/attributes.rs index ea9bb04..216b586 100644 --- a/src/bgp/attributes.rs +++ b/src/bgp/attributes.rs @@ -175,7 +175,6 @@ impl AsPath { self.segments.iter().map(AsPathSegment::count_asns).sum() } - /// Construct AsPath from AS_PATH and AS4_PATH /// /// https://datatracker.ietf.org/doc/html/rfc6793#section-4.2.3 diff --git a/src/bgp/elem.rs b/src/bgp/elem.rs index 5736fcb..5e00920 100644 --- a/src/bgp/elem.rs +++ b/src/bgp/elem.rs @@ -1,5 +1,6 @@ use std::fmt::{Display, Formatter}; use std::net::IpAddr; +use std::str::FromStr; use itertools::Itertools; use crate::bgp::attributes::{AsPath, AtomicAggregate, Community, Origin}; use crate::network::{Asn, NetworkPrefix}; @@ -38,6 +39,29 @@ pub struct BgpElem { pub aggr_asn: Option, pub aggr_ip: Option, } + +impl Default for BgpElem { + fn default() -> Self { + BgpElem { + timestamp: 0.0, + elem_type: ElemType::ANNOUNCE, + peer_ip: IpAddr::from_str("0.0.0.0").unwrap(), + peer_asn: 0, + prefix: NetworkPrefix::from_str("0.0.0.0/0").unwrap(), + next_hop: None, + as_path: None, + origin_asns: None, + origin: None, + local_pref: None, + med: None, + communities: None, + atomic: None, + aggr_asn: None, + aggr_ip: None + } + } +} + #[inline(always)] pub fn option_to_string(o: &Option) -> String where @@ -86,3 +110,22 @@ impl Display for BgpElem { } } +#[cfg(test)] +mod tests { + use std::str::FromStr; + use std::default::Default; + use super::*; + + #[test] + fn test_default() { + let elem = BgpElem{ + timestamp: 0.0, + elem_type: ElemType::ANNOUNCE, + peer_ip: IpAddr::from_str("192.168.1.1").unwrap(), + peer_asn: 0, + prefix: NetworkPrefix::from_str("8.8.8.0/24").unwrap(), + ..Default::default() + }; + dbg!(elem); + } +} \ No newline at end of file diff --git a/src/err.rs b/src/err.rs new file mode 100644 index 0000000..2782e02 --- /dev/null +++ b/src/err.rs @@ -0,0 +1,26 @@ +use std::error::Error; +use std::fmt::{Display, Formatter}; +use ipnetwork::IpNetworkError; + +#[derive(Debug)] +pub enum BgpModelsError { + PrefixParsingError(String), +} + +impl Display for BgpModelsError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self{ + BgpModelsError::PrefixParsingError(msg) => { + write!(f, "cannot convert str to IP prefix: {}", msg) + } + } + } +} + +impl Error for BgpModelsError{} + +impl From for BgpModelsError { + fn from(err: IpNetworkError) -> Self { + BgpModelsError::PrefixParsingError(err.to_string()) + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index aa42f26..cb36121 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,6 +18,7 @@ pub mod bgp; pub mod network; pub mod mrt; pub mod prelude; +pub mod err; #[macro_use] extern crate enum_primitive_derive; \ No newline at end of file diff --git a/src/network.rs b/src/network.rs index 3f8ba69..396a8ac 100644 --- a/src/network.rs +++ b/src/network.rs @@ -2,7 +2,9 @@ use std::fmt::{Display, Formatter}; use std::net::{Ipv4Addr, Ipv6Addr}; +use std::str::FromStr; use ipnetwork::IpNetwork; +use crate::err::BgpModelsError; /// Meta information for an address/prefix. /// @@ -64,6 +66,20 @@ pub struct NetworkPrefix { pub path_id: u32, } +impl FromStr for NetworkPrefix { + type Err = BgpModelsError; + + fn from_str(s: &str) -> Result { + let prefix = IpNetwork::from_str(s)?; + Ok( + NetworkPrefix{ + prefix, + path_id: 0, + } + ) + } +} + impl NetworkPrefix { pub fn new(prefix: IpNetwork, path_id: u32) -> NetworkPrefix { NetworkPrefix { prefix, path_id } diff --git a/src/prelude.rs b/src/prelude.rs index e11e8d9..b23ebc8 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,3 +1,4 @@ pub use crate::bgp::*; pub use crate::mrt::*; -pub use crate::network::*; \ No newline at end of file +pub use crate::network::*; +pub use crate::err::BgpModelsError; \ No newline at end of file