删除无用代码

This commit is contained in:
xiuting.xu
2026-05-27 13:44:31 +08:00
parent cdf9372929
commit 13f29843db
6 changed files with 47 additions and 437 deletions

View File

@@ -1,304 +0,0 @@
use std::fs;
use std::net::IpAddr;
use std::path::Path;
use std::str::FromStr;
use anyhow::{Context, Result, anyhow};
use crate::data_model::resources::as_resources::Asn;
use crate::data_model::resources::ip_resources::{IPAddress, IPAddressPrefix};
use crate::rtr::payload::{Aspa, Payload, RouteOrigin, RouterKey, Ski};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParsedVrp {
pub prefix_addr: IpAddr,
pub prefix_len: u8,
pub max_len: u8,
pub asn: u32,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParsedAspa {
pub customer_asn: u32,
pub provider_asns: Vec<u32>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParsedRouterKey {
pub ski: [u8; 20],
pub asn: u32,
pub spki: Vec<u8>,
}
/// 从文本文件中加载 VRP,并转换成 RTR Payload::RouteOrigin。
///
/// 文件格式:
///
/// ```text
/// # prefix,max_len,asn
/// 10.0.0.0/24,24,65001
/// 10.0.1.0/24,24,65002
/// 2001:db8::/32,48,65003
/// ```
pub fn load_vrps_from_file(path: impl AsRef<Path>) -> Result<Vec<Payload>> {
let path = path.as_ref();
let content = fs::read_to_string(path)
.with_context(|| format!("failed to read VRP file: {}", path.display()))?;
let mut payloads = Vec::new();
for (idx, raw_line) in content.lines().enumerate() {
let line_no = idx + 1;
let line = raw_line.trim();
if line.is_empty() || line.starts_with('#') {
continue;
}
let vrp = parse_vrp_line(line)
.with_context(|| format!("invalid VRP line {}: {}", line_no, raw_line))?;
payloads.push(Payload::RouteOrigin(build_route_origin(vrp)?));
}
Ok(payloads)
}
pub fn load_aspas_from_file(path: impl AsRef<Path>) -> Result<Vec<Payload>> {
let path = path.as_ref();
let content = fs::read_to_string(path)
.with_context(|| format!("failed to read ASPA file: {}", path.display()))?;
let mut payloads = Vec::new();
for (idx, raw_line) in content.lines().enumerate() {
let line_no = idx + 1;
let line = raw_line.trim();
if line.is_empty() || line.starts_with('#') {
continue;
}
let aspa = parse_aspa_line(line)
.with_context(|| format!("invalid ASPA line {}: {}", line_no, raw_line))?;
payloads.push(Payload::Aspa(build_aspa(aspa)?));
}
Ok(payloads)
}
pub fn load_router_keys_from_file(path: impl AsRef<Path>) -> Result<Vec<Payload>> {
let path = path.as_ref();
let content = fs::read_to_string(path)
.with_context(|| format!("failed to read Router Key file: {}", path.display()))?;
let mut payloads = Vec::new();
for (idx, raw_line) in content.lines().enumerate() {
let line_no = idx + 1;
let line = raw_line.trim();
if line.is_empty() || line.starts_with('#') {
continue;
}
let router_key = parse_router_key_line(line)
.with_context(|| format!("invalid Router Key line {}: {}", line_no, raw_line))?;
payloads.push(Payload::RouterKey(build_router_key(router_key)?));
}
Ok(payloads)
}
/// 解析单行 VRP。
///
/// 格式:
/// `prefix/prefix_len,max_len,asn`
///
/// 例如:
/// `10.0.0.0/24,24,65001`
pub fn parse_vrp_line(line: &str) -> Result<ParsedVrp> {
let parts: Vec<_> = line.split(',').map(|s| s.trim()).collect();
if parts.len() != 3 {
return Err(anyhow!(
"expected format: <prefix>/<prefix_len>,<max_len>,<asn>"
));
}
let prefix_part = parts[0];
let max_len =
u8::from_str(parts[1]).with_context(|| format!("invalid max_len: {}", parts[1]))?;
let asn = u32::from_str(parts[2]).with_context(|| format!("invalid asn: {}", parts[2]))?;
let (addr_str, prefix_len_str) = prefix_part
.split_once('/')
.ok_or_else(|| anyhow!("prefix must be in CIDR form, e.g. 10.0.0.0/24"))?;
let prefix_addr = IpAddr::from_str(addr_str.trim())
.with_context(|| format!("invalid IP address: {}", addr_str))?;
let prefix_len = u8::from_str(prefix_len_str.trim())
.with_context(|| format!("invalid prefix length: {}", prefix_len_str))?;
validate_vrp(prefix_addr, prefix_len, max_len)?;
Ok(ParsedVrp {
prefix_addr,
prefix_len,
max_len,
asn,
})
}
pub fn parse_aspa_line(line: &str) -> Result<ParsedAspa> {
let parts: Vec<_> = line.split(',').map(|s| s.trim()).collect();
if parts.len() != 2 {
return Err(anyhow!(
"expected format: <customer_asn>,<provider_asn> [provider_asn ...]"
));
}
let customer_asn =
u32::from_str(parts[0]).with_context(|| format!("invalid customer_asn: {}", parts[0]))?;
let provider_asns = parts[1]
.split_whitespace()
.map(|provider| {
u32::from_str(provider).with_context(|| format!("invalid provider_asn: {}", provider))
})
.collect::<Result<Vec<_>>>()?;
validate_aspa(customer_asn, &provider_asns)?;
Ok(ParsedAspa {
customer_asn,
provider_asns,
})
}
pub fn parse_router_key_line(line: &str) -> Result<ParsedRouterKey> {
let parts: Vec<_> = line.split(',').map(|s| s.trim()).collect();
if parts.len() != 3 {
return Err(anyhow!("expected format: <ski_hex>,<asn>,<spki_hex>"));
}
let ski_vec = decode_hex(parts[0]).with_context(|| format!("invalid SKI hex: {}", parts[0]))?;
if ski_vec.len() != 20 {
return Err(anyhow!("SKI must be exactly 20 bytes"));
}
let mut ski = [0u8; 20];
ski.copy_from_slice(&ski_vec);
let asn = u32::from_str(parts[1]).with_context(|| format!("invalid asn: {}", parts[1]))?;
let spki = decode_hex(parts[2]).with_context(|| format!("invalid SPKI hex: {}", parts[2]))?;
validate_router_key(asn, &spki)?;
Ok(ParsedRouterKey { ski, asn, spki })
}
fn validate_vrp(prefix_addr: IpAddr, prefix_len: u8, max_len: u8) -> Result<()> {
match prefix_addr {
IpAddr::V4(_) => {
if prefix_len > 32 {
return Err(anyhow!("IPv4 prefix length must be <= 32"));
}
if max_len > 32 {
return Err(anyhow!("IPv4 max_len must be <= 32"));
}
if max_len < prefix_len {
return Err(anyhow!("IPv4 max_len must be >= prefix length"));
}
}
IpAddr::V6(_) => {
if prefix_len > 128 {
return Err(anyhow!("IPv6 prefix length must be <= 128"));
}
if max_len > 128 {
return Err(anyhow!("IPv6 max_len must be <= 128"));
}
if max_len < prefix_len {
return Err(anyhow!("IPv6 max_len must be >= prefix length"));
}
}
}
Ok(())
}
fn validate_aspa(customer_asn: u32, provider_asns: &[u32]) -> Result<()> {
if customer_asn == 0 {
return Err(anyhow!("customer_asn must not be AS0"));
}
if provider_asns.is_empty() {
return Err(anyhow!("provider list must not be empty"));
}
if provider_asns.iter().any(|asn| *asn == 0)
&& !(provider_asns.len() == 1 && provider_asns[0] == 0)
{
return Err(anyhow!(
"provider list containing AS0 must be exactly [0]"
));
}
Ok(())
}
fn validate_router_key(asn: u32, spki: &[u8]) -> Result<()> {
crate::rtr::payload::RouterKey::new(Ski::default(), Asn::from(asn), spki.to_vec())
.validate()
.map_err(|err| anyhow!(err.to_string()))?;
Ok(())
}
pub fn build_route_origin(vrp: ParsedVrp) -> Result<RouteOrigin> {
let address = match vrp.prefix_addr {
IpAddr::V4(addr) => IPAddress::from_ipv4(addr),
IpAddr::V6(addr) => IPAddress::from_ipv6(addr),
};
let prefix = IPAddressPrefix::new(address, vrp.prefix_len);
let asn = Asn::from(vrp.asn);
Ok(RouteOrigin::new(prefix, vrp.max_len, asn))
}
pub fn build_aspa(aspa: ParsedAspa) -> Result<Aspa> {
let customer_asn = Asn::from(aspa.customer_asn);
let provider_asns = aspa
.provider_asns
.into_iter()
.map(Asn::from)
.collect::<Vec<_>>();
let aspa = Aspa::new(customer_asn, provider_asns);
aspa.validate_announcement()?;
Ok(aspa)
}
pub fn build_router_key(router_key: ParsedRouterKey) -> Result<RouterKey> {
let asn = Asn::from(router_key.asn);
let ski = Ski::from_bytes(router_key.ski);
let router_key = RouterKey::new(ski, asn, router_key.spki);
Ok(router_key)
}
fn decode_hex(input: &str) -> Result<Vec<u8>> {
let trimmed = input.trim();
if trimmed.len() % 2 != 0 {
return Err(anyhow!("hex string must have even length"));
}
(0..trimmed.len())
.step_by(2)
.map(|idx| {
u8::from_str_radix(&trimmed[idx..idx + 2], 16)
.map_err(|err| anyhow!("invalid hex at byte {}: {}", idx / 2, err))
})
.collect()
}

View File

@@ -1,6 +1,5 @@
pub mod cache;
pub mod error_type;
pub mod loader;
pub mod payload;
pub mod pdu;
pub mod server;