84 lines
2.7 KiB
Rust
Executable File
84 lines
2.7 KiB
Rust
Executable File
use std::{collections::HashMap, net::Ipv4Addr, sync::atomic::{AtomicBool, Ordering}, time::Duration};
|
|
|
|
use ahash::RandomState;
|
|
use dashmap::{DashMap};
|
|
use ipnet::Ipv4Net;
|
|
use sdlan_sn_rs::utils::{Result, SDLanError};
|
|
|
|
use tokio::sync::oneshot::{Receiver, Sender, channel};
|
|
use tracing::{debug, error};
|
|
|
|
use crate::{RouteTableTrie, network::tun::add_route, pb::{SdlArpResponse, SdlStunReply}};
|
|
|
|
|
|
pub struct RouteTable2 {
|
|
pub cache_table: DashMap<(Ipv4Net, Ipv4Addr), AtomicBool, RandomState>,
|
|
pub route_table: RouteTableTrie,
|
|
}
|
|
|
|
impl RouteTable2 {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
cache_table: DashMap::with_hasher(RandomState::new()),
|
|
route_table: RouteTableTrie::new(),
|
|
}
|
|
}
|
|
|
|
pub fn parse_and_add_route(&self, route_str: &str) -> Result<()> {
|
|
let routes = parse_route(route_str);
|
|
for route in routes.keys() {
|
|
if self.cache_table.get(route).is_some() {
|
|
error!("route {} {} has been added", route.0.to_string(), route.1);
|
|
return Err(SDLanError::IOError(format!("route {} already added", route.0.to_string())));
|
|
}
|
|
}
|
|
|
|
for route in routes.keys() {
|
|
self.cache_table.insert(*route, AtomicBool::new(false));
|
|
self.route_table.insert(route.0.addr().into(), route.0.prefix_len(), route.1);
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
pub fn apply_system(&self) {
|
|
for route in &self.cache_table {
|
|
let origin = route.fetch_or(true, Ordering::Relaxed);
|
|
if !origin {
|
|
// should add to system
|
|
add_route(route.key().0, route.key().1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ip, mask, gateway, cidr gateway,cidr2 gateway2
|
|
pub fn parse_route(route: &str) -> HashMap<(Ipv4Net, Ipv4Addr), bool> {
|
|
let mut result = HashMap::new();
|
|
// let routes: Vec<_> = route.split(",").collect();
|
|
|
|
for route in route.trim().split(",") {
|
|
let route_info: Vec<_> = route.trim().split_whitespace().collect();
|
|
if route_info.len() != 2 {
|
|
error!("route info format error: {}", route);
|
|
continue;
|
|
}
|
|
debug!("got route info: {:?}", route_info);
|
|
|
|
let Ok(gateway) = route_info[1].parse::<Ipv4Addr>() else {
|
|
error!("failed to parse gw: {}", route_info[1]);
|
|
continue;
|
|
};
|
|
|
|
let cidr = route_info[0];
|
|
let Ok(net )= cidr.parse::<Ipv4Net>() else {
|
|
error!("failed to parse cidr: {}, skipping", cidr);
|
|
continue;
|
|
};
|
|
let origin = result.insert((net, gateway), true);
|
|
if origin.is_some() {
|
|
error!("{} {} already added", net.to_string(), gateway.to_string());
|
|
}
|
|
}
|
|
result
|
|
}
|