use std::fmt::Debug; use std::io; use std::time::Duration; use serde::{Deserialize, Serialize}; use crate::data_model::resources::as_resources::Asn; use crate::data_model::resources::ip_resources::IPAddressPrefix; use x509_parser::prelude::FromDer; use x509_parser::x509::SubjectPublicKeyInfo; #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)] enum PayloadPduType { Ipv4Prefix = 4, Ipv6Prefix = 6, RouterKey = 9, Aspa = 11, } #[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq, Ord, PartialOrd, Serialize, Deserialize)] pub struct Ski([u8; 20]); impl AsRef<[u8]> for Ski { fn as_ref(&self) -> &[u8] { &self.0 } } impl Ski { pub fn from_bytes(bytes: [u8; 20]) -> Self { Self(bytes) } } #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)] pub struct RouteOrigin { prefix: IPAddressPrefix, max_length: u8, asn: Asn, } impl RouteOrigin { pub fn new(prefix: IPAddressPrefix, max_length: u8, asn: Asn) -> Self { Self { prefix, max_length, asn, } } pub fn prefix(&self) -> &IPAddressPrefix { &self.prefix } pub fn max_length(&self) -> u8 { self.max_length } pub fn asn(&self) -> Asn { self.asn } } #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)] pub struct RouterKey { subject_key_identifier: Ski, asn: Asn, subject_public_key_info: Vec, } impl RouterKey { pub fn new(subject_key_identifier: Ski, asn: Asn, subject_public_key_info: Vec) -> Self { Self { subject_key_identifier, asn, subject_public_key_info, } } pub fn ski(&self) -> Ski { self.subject_key_identifier } pub fn asn(&self) -> Asn { self.asn } pub fn spki(&self) -> &[u8] { &self.subject_public_key_info } pub fn validate(&self) -> Result<(), io::Error> { if self.asn.into_u32() == 0 { return Err(io::Error::new( io::ErrorKind::InvalidData, "RouterKey ASN must not be AS0", )); } if self.subject_public_key_info.is_empty() { return Err(io::Error::new( io::ErrorKind::InvalidData, "RouterKey SPKI must not be empty", )); } let (rem, _) = SubjectPublicKeyInfo::from_der(&self.subject_public_key_info) .map_err(|err| { io::Error::new( io::ErrorKind::InvalidData, format!("RouterKey SPKI is not valid DER: {err}"), ) })?; if !rem.is_empty() { return Err(io::Error::new( io::ErrorKind::InvalidData, format!( "RouterKey SPKI DER has trailing bytes: {}", rem.len() ), )); } Ok(()) } } #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)] pub struct Aspa { customer_asn: Asn, provider_asns: Vec, } impl Aspa { pub fn new(customer_asn: Asn, mut provider_asns: Vec) -> Self { provider_asns.sort(); provider_asns.dedup(); Self { customer_asn, provider_asns, } } pub fn customer_asn(&self) -> Asn { self.customer_asn } pub fn provider_asns(&self) -> &[Asn] { &self.provider_asns } pub fn validate_announcement(&self) -> Result<(), io::Error> { if self.customer_asn.into_u32() == 0 { return Err(io::Error::new( io::ErrorKind::InvalidData, "ASPA customer ASN must not be AS0", )); } if self.provider_asns.is_empty() { return Err(io::Error::new( io::ErrorKind::InvalidData, "ASPA announcement must contain at least one provider ASN", )); } if self.provider_asns.iter().any(|asn| asn.into_u32() == 0) { return Err(io::Error::new( io::ErrorKind::InvalidData, "ASPA provider list must not contain AS0", )); } Ok(()) } } #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] pub enum Payload { /// A route origin. RouteOrigin(RouteOrigin), /// A BGPsec router key. RouterKey(RouterKey), /// An ASPA unit. Aspa(Aspa), } // Timing #[derive(Clone, Copy, Debug)] pub struct Timing { /// The number of seconds until a client should refresh its data. pub refresh: u32, /// The number of seconds a client whould wait before retrying to connect. pub retry: u32, /// The number of secionds before data expires if not refreshed. pub expire: u32 } impl Timing { pub const MIN_REFRESH: u32 = 1; pub const MAX_REFRESH: u32 = 86_400; pub const MIN_RETRY: u32 = 1; pub const MAX_RETRY: u32 = 7_200; pub const MIN_EXPIRE: u32 = 600; pub const MAX_EXPIRE: u32 = 172_800; pub const fn new(refresh: u32, retry: u32, expire: u32) -> Self { Self { refresh, retry, expire } } pub fn validate(self) -> Result<(), io::Error> { if !(Self::MIN_REFRESH..=Self::MAX_REFRESH).contains(&self.refresh) { return Err(io::Error::new( io::ErrorKind::InvalidData, format!( "refresh interval {} out of range {}..={}", self.refresh, Self::MIN_REFRESH, Self::MAX_REFRESH ), )); } if !(Self::MIN_RETRY..=Self::MAX_RETRY).contains(&self.retry) { return Err(io::Error::new( io::ErrorKind::InvalidData, format!( "retry interval {} out of range {}..={}", self.retry, Self::MIN_RETRY, Self::MAX_RETRY ), )); } if !(Self::MIN_EXPIRE..=Self::MAX_EXPIRE).contains(&self.expire) { return Err(io::Error::new( io::ErrorKind::InvalidData, format!( "expire interval {} out of range {}..={}", self.expire, Self::MIN_EXPIRE, Self::MAX_EXPIRE ), )); } if self.expire <= self.refresh { return Err(io::Error::new( io::ErrorKind::InvalidData, format!( "expire interval {} must be greater than refresh interval {}", self.expire, self.refresh ), )); } if self.expire <= self.retry { return Err(io::Error::new( io::ErrorKind::InvalidData, format!( "expire interval {} must be greater than retry interval {}", self.expire, self.retry ), )); } Ok(()) } pub fn refresh(self) -> Duration { Duration::from_secs(u64::from(self.refresh)) } pub fn retry(self) -> Duration { Duration::from_secs(u64::from(self.retry)) } pub fn expire(self) -> Duration { Duration::from_secs(u64::from(self.expire)) } } impl Default for Timing { fn default() -> Self { Self { refresh: 3600, retry: 600, expire: 7200, } } }