use std::collections::BTreeMap;
use ipnet::IpNet;
use serde::{Deserialize, Serialize};
use crate::irr::extract;
use crate::{BgpkitCommonsError, Result};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct IrrAttribute {
pub name: String,
pub value: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct IrrRecord {
pub object_type: String,
pub attributes: Vec<IrrAttribute>,
}
impl IrrRecord {
pub fn to_typed(&self) -> Result<Option<IrrObject>> {
let mut text = String::new();
for attribute in &self.attributes {
let mut values = attribute.value.split('\n');
let first = values.next().unwrap_or_default();
text.push_str(&attribute.name);
text.push_str(": ");
text.push_str(first);
text.push('\n');
for continuation in values {
text.push(' ');
text.push_str(continuation);
text.push('\n');
}
}
text.push('\n');
let parsed = rpsl::parse_object(&text).map_err(|error| {
BgpkitCommonsError::invalid_format("RPSL object", &self.object_type, error.to_string())
})?;
extract::extract(&parsed)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum IrrObjectType {
AutNum,
Route,
Route6,
AsSet,
RouteSet,
Mntner,
Organisation,
}
impl IrrObjectType {
pub fn key_attr(&self) -> &'static str {
match self {
IrrObjectType::AutNum => "aut-num",
IrrObjectType::Route => "route",
IrrObjectType::Route6 => "route6",
IrrObjectType::AsSet => "as-set",
IrrObjectType::RouteSet => "route-set",
IrrObjectType::Mntner => "mntner",
IrrObjectType::Organisation => "organisation",
}
}
pub fn from_first_attr(name: &str) -> Option<Self> {
match name {
"aut-num" => Some(IrrObjectType::AutNum),
"route" => Some(IrrObjectType::Route),
"route6" => Some(IrrObjectType::Route6),
"as-set" => Some(IrrObjectType::AsSet),
"route-set" => Some(IrrObjectType::RouteSet),
"mntner" => Some(IrrObjectType::Mntner),
"organisation" | "org" => Some(IrrObjectType::Organisation),
_ => None,
}
}
pub fn all() -> &'static [IrrObjectType] {
&[
IrrObjectType::AutNum,
IrrObjectType::Route,
IrrObjectType::Route6,
IrrObjectType::AsSet,
IrrObjectType::RouteSet,
IrrObjectType::Mntner,
IrrObjectType::Organisation,
]
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AutNum {
pub asn: u32,
pub as_name: String,
pub descr: Vec<String>,
pub source: String,
pub extra: BTreeMap<String, Vec<String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Route {
pub prefix: IpNet,
pub origin: u32,
pub descr: Vec<String>,
pub source: String,
pub extra: BTreeMap<String, Vec<String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AsSet {
pub name: String,
pub members: Vec<u32>,
pub set_members: Vec<String>,
pub descr: Vec<String>,
pub source: String,
pub extra: BTreeMap<String, Vec<String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RouteSet {
pub name: String,
pub members: Vec<IpNet>,
pub set_members: Vec<String>,
pub descr: Vec<String>,
pub source: String,
pub extra: BTreeMap<String, Vec<String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Mntner {
pub name: String,
pub auth: Vec<String>,
pub upd_to: Vec<String>,
pub mnt_nfy: Vec<String>,
pub source: String,
pub extra: BTreeMap<String, Vec<String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Organisation {
pub id: String,
pub name: String,
pub org_type: Option<String>,
pub address: Vec<String>,
pub country: Option<String>,
pub abuse_c: Option<String>,
pub source: String,
pub extra: BTreeMap<String, Vec<String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum IrrObject {
AutNum(AutNum),
Route(Route),
Route6(Route),
AsSet(AsSet),
RouteSet(RouteSet),
Mntner(Mntner),
Organisation(Organisation),
}
impl IrrObject {
pub fn source(&self) -> &str {
match self {
IrrObject::AutNum(o) => &o.source,
IrrObject::Route(o) | IrrObject::Route6(o) => &o.source,
IrrObject::AsSet(o) => &o.source,
IrrObject::RouteSet(o) => &o.source,
IrrObject::Mntner(o) => &o.source,
IrrObject::Organisation(o) => &o.source,
}
}
}