route add
This commit is contained in:
parent
c3355db8ee
commit
7e7a9ca2e6
@ -16,7 +16,7 @@ once_cell = "1.19.0"
|
||||
prost = "0.12.6"
|
||||
prost-build = "0.12.6"
|
||||
rand = "0.8.5"
|
||||
reqwest = { version = "0.12.24", default_features = false, features = ["json", "rustls-tls"] }
|
||||
reqwest = { version = "0.12.24", default-features = false, features = ["json", "rustls-tls"] }
|
||||
rsa = "0.9.6"
|
||||
# sdlan-sn-rs = { git = "ssh://git@git2.asxalex.pw/sdlan-v2/sdlan-rs.git" }
|
||||
sdlan-sn-rs = {git = "https://gitea.s5s8.com/punchnet/sdlan-rs.git"}
|
||||
|
||||
@ -5,8 +5,8 @@ use std::fs;
|
||||
use std::fs::OpenOptions;
|
||||
use std::process;
|
||||
|
||||
use std::env;
|
||||
use clap::Parser;
|
||||
use std::env;
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
use daemonize::Daemonize;
|
||||
@ -14,11 +14,7 @@ use daemonize::Daemonize;
|
||||
use futures_util::io;
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
use libc::{SIGTERM, kill};
|
||||
use punchnet::CachedLoginInfo;
|
||||
use punchnet::CommandLineInput2;
|
||||
use punchnet::Commands;
|
||||
use punchnet::ExitNodeCmd;
|
||||
use libc::{kill, SIGTERM};
|
||||
use punchnet::get_access_token;
|
||||
use punchnet::get_base_dir;
|
||||
use punchnet::get_edge;
|
||||
@ -28,31 +24,34 @@ use punchnet::restore_dns;
|
||||
use punchnet::run_sdlan;
|
||||
use punchnet::set_access_token;
|
||||
use punchnet::set_base_dir;
|
||||
use punchnet::CachedLoginInfo;
|
||||
use punchnet::CommandLine;
|
||||
use punchnet::CommandLineInput2;
|
||||
use punchnet::Commands;
|
||||
use punchnet::ExitNodeCmd;
|
||||
use sdlan_sn_rs::log;
|
||||
|
||||
use sdlan_sn_rs::utils::create_or_load_uuid;
|
||||
use sdlan_sn_rs::utils::Mac;
|
||||
use sdlan_sn_rs::utils::Result;
|
||||
use sdlan_sn_rs::utils::create_or_load_uuid;
|
||||
use tokio::runtime::Runtime;
|
||||
use tracing::debug;
|
||||
use tracing::error;
|
||||
|
||||
use std::net::ToSocketAddrs;
|
||||
|
||||
use crate::api::connect;
|
||||
use crate::api::login_with_token;
|
||||
use crate::api::login_with_user_pass;
|
||||
use crate::api::ConnectData;
|
||||
use crate::api::ConnectResponse;
|
||||
use crate::api::LoginData;
|
||||
use crate::api::LoginResponse;
|
||||
use crate::api::TEST_PREFIX;
|
||||
use crate::api::connect;
|
||||
use crate::api::login_with_token;
|
||||
use crate::api::login_with_user_pass;
|
||||
use crate::local_udp_info::handle_query_for_info_info;
|
||||
use crate::local_udp_info::query_for_exit_node_list;
|
||||
use crate::local_udp_info::query_for_info;
|
||||
|
||||
|
||||
const APP_USER_ENV_NAME: &str = "PUNCH_USER";
|
||||
const APP_PASS_ENV_NAME: &str = "PUNCH_PASS";
|
||||
const APP_TOKEN_ENV_NAME: &str = "PUNCH_TOKEN";
|
||||
@ -162,12 +161,12 @@ async fn daemonize_me(
|
||||
client_id,
|
||||
mac,
|
||||
CommandLine {
|
||||
sn: server.clone()+":1365",
|
||||
sn: server.clone() + ":1365",
|
||||
quic: server.clone() + ":443",
|
||||
quic_domain: hostname,
|
||||
nat_server1: server.clone() +":1365",
|
||||
nat_server1: server.clone() + ":1365",
|
||||
// nat_server2: "47.98.178.3:1265".to_owned(),
|
||||
nat_server2: server.clone() +":1366",
|
||||
nat_server2: server.clone() + ":1366",
|
||||
allow_routing: allow_routing,
|
||||
_drop_multicast: true,
|
||||
register_ttl: 1,
|
||||
@ -224,7 +223,8 @@ async fn daemonize_me(
|
||||
eprintln!("got ip from network is invlid: {}", connect_info.ip);
|
||||
process::exit(-5);
|
||||
};
|
||||
if let Err(e) = edge.start_without_feedback(
|
||||
if let Err(e) = edge
|
||||
.start_without_feedback(
|
||||
remembered.access_token.clone(),
|
||||
// String::new(),
|
||||
remembered.network_id,
|
||||
@ -234,7 +234,9 @@ async fn daemonize_me(
|
||||
connect_info.identity_id,
|
||||
// 0,
|
||||
None,
|
||||
).await {
|
||||
)
|
||||
.await
|
||||
{
|
||||
error!("failed to start: {:?}", e);
|
||||
}
|
||||
|
||||
@ -277,7 +279,6 @@ async fn daemonize_me(
|
||||
// started = !started;
|
||||
// */
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
@ -285,13 +286,11 @@ const SYSTEM: &'static str = "windows";
|
||||
#[cfg(target_os = "windows")]
|
||||
const DEFAULT_BASE_DIR: &'static str = ".";
|
||||
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
const SYSTEM: &'static str = "linux";
|
||||
#[cfg(target_os = "linux")]
|
||||
const DEFAULT_BASE_DIR: &'static str = "/usr/local/punchnet";
|
||||
|
||||
|
||||
fn main() {
|
||||
set_base_dir(DEFAULT_BASE_DIR);
|
||||
// let _guard = log::init_log(&format!("{}/.output", get_base_dir()));
|
||||
@ -313,9 +312,18 @@ fn main() {
|
||||
match &cmd.cmd {
|
||||
Commands::Login(user) => {
|
||||
let rt = Runtime::new().unwrap();
|
||||
rt.block_on( async move {
|
||||
rt.block_on(async move {
|
||||
let _ = parse_login_result(
|
||||
login_with_user_pass(TEST_PREFIX, &client_id, &user.username, &user.password, mac, system, version).await
|
||||
login_with_user_pass(
|
||||
TEST_PREFIX,
|
||||
&client_id,
|
||||
&user.username,
|
||||
&user.password,
|
||||
mac,
|
||||
system,
|
||||
version,
|
||||
)
|
||||
.await,
|
||||
);
|
||||
});
|
||||
process::exit(0);
|
||||
@ -325,7 +333,8 @@ fn main() {
|
||||
let rt = Runtime::new().unwrap();
|
||||
rt.block_on(async move {
|
||||
let _ = parse_login_result(
|
||||
login_with_token(TEST_PREFIX, &client_id, &tk.token, mac, system, version).await
|
||||
login_with_token(TEST_PREFIX, &client_id, &tk.token, mac, system, version)
|
||||
.await,
|
||||
);
|
||||
});
|
||||
process::exit(0);
|
||||
@ -338,14 +347,9 @@ fn main() {
|
||||
ExitNodeCmd::List => {
|
||||
query_for_exit_node_list().await;
|
||||
}
|
||||
ExitNodeCmd::Start(info) => {
|
||||
|
||||
ExitNodeCmd::Start(info) => {}
|
||||
ExitNodeCmd::Stop => {}
|
||||
}
|
||||
ExitNodeCmd::Stop => {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
process::exit(0);
|
||||
}
|
||||
@ -399,12 +403,14 @@ fn main() {
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.write(true)
|
||||
.open("/tmp/punchnet.out").unwrap();
|
||||
.open("/tmp/punchnet.out")
|
||||
.unwrap();
|
||||
let err = OpenOptions::new()
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.write(true)
|
||||
.open("/tmp/punchnet.err").unwrap();
|
||||
.open("/tmp/punchnet.err")
|
||||
.unwrap();
|
||||
|
||||
let daemonize = Daemonize::new()
|
||||
.pid_file("/tmp/punchnet.pid")
|
||||
@ -412,8 +418,7 @@ fn main() {
|
||||
.working_directory(get_base_dir())
|
||||
.stdout(out)
|
||||
.stderr(err)
|
||||
.privileged_action(|| {
|
||||
});
|
||||
.privileged_action(|| {});
|
||||
|
||||
match daemonize.start() {
|
||||
Ok(_) => {
|
||||
@ -431,11 +436,17 @@ fn main() {
|
||||
run_it(cmd, client_id, allow_routing, mac, system, version);
|
||||
}
|
||||
|
||||
fn run_it(cmd: CommandLineInput2, client_id: String, allow_routing: bool, mac: Mac, system: &str, version: &str) {
|
||||
fn run_it(
|
||||
cmd: CommandLineInput2,
|
||||
client_id: String,
|
||||
allow_routing: bool,
|
||||
mac: Mac,
|
||||
system: &str,
|
||||
version: &str,
|
||||
) {
|
||||
let rt = Runtime::new().unwrap();
|
||||
match &cmd.cmd {
|
||||
Commands::Start(rtinfo) => {
|
||||
rt.block_on(async move {
|
||||
Commands::Start(rtinfo) => rt.block_on(async move {
|
||||
let remembered_token = get_access_token();
|
||||
if remembered_token.is_none() {
|
||||
eprintln!("not logged in, should login with user/pass or token first");
|
||||
@ -443,19 +454,27 @@ fn run_it(cmd: CommandLineInput2, client_id: String, allow_routing: bool, mac: M
|
||||
}
|
||||
let remembered = remembered_token.unwrap();
|
||||
let connect_info = parse_connect_result(
|
||||
connect(TEST_PREFIX, &client_id, &remembered.access_token).await
|
||||
connect(TEST_PREFIX, &client_id, &remembered.access_token).await,
|
||||
);
|
||||
daemonize_me(rtinfo.allow_routing || allow_routing, connect_info, remembered, client_id, rtinfo.route_file.clone(), rtinfo.route.clone(), mac).await;
|
||||
})
|
||||
}
|
||||
Commands::AutoRun(tk) => {
|
||||
rt.block_on(async move {
|
||||
daemonize_me(
|
||||
rtinfo.allow_routing || allow_routing,
|
||||
connect_info,
|
||||
remembered,
|
||||
client_id,
|
||||
rtinfo.route_file.clone(),
|
||||
rtinfo.route.clone(),
|
||||
mac,
|
||||
)
|
||||
.await;
|
||||
}),
|
||||
Commands::AutoRun(tk) => rt.block_on(async move {
|
||||
let mut remembered_token = get_access_token();
|
||||
if remembered_token.is_none() {
|
||||
let data = parse_login_result(
|
||||
login_with_token(TEST_PREFIX, &client_id, &tk.token, mac, system, version).await
|
||||
login_with_token(TEST_PREFIX, &client_id, &tk.token, mac, system, version)
|
||||
.await,
|
||||
);
|
||||
remembered_token = Some(CachedLoginInfo{
|
||||
remembered_token = Some(CachedLoginInfo {
|
||||
access_token: data.access_token,
|
||||
username: data.username,
|
||||
user_type: data.user_type,
|
||||
@ -469,11 +488,19 @@ fn run_it(cmd: CommandLineInput2, client_id: String, allow_routing: bool, mac: M
|
||||
let remembered = remembered_token.unwrap();
|
||||
|
||||
let connect_info = parse_connect_result(
|
||||
connect(TEST_PREFIX, &client_id, &remembered.access_token).await
|
||||
connect(TEST_PREFIX, &client_id, &remembered.access_token).await,
|
||||
);
|
||||
daemonize_me(tk.allow_routing || allow_routing, connect_info, remembered, client_id, tk.route_file.clone(), tk.route.clone(), mac).await;
|
||||
})
|
||||
}
|
||||
daemonize_me(
|
||||
tk.allow_routing || allow_routing,
|
||||
connect_info,
|
||||
remembered,
|
||||
client_id,
|
||||
tk.route_file.clone(),
|
||||
tk.route.clone(),
|
||||
mac,
|
||||
)
|
||||
.await;
|
||||
}),
|
||||
|
||||
other => {
|
||||
eprintln!("should not comes here");
|
||||
|
||||
@ -2,7 +2,10 @@
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
sync::{Arc, atomic::{AtomicU8, Ordering}},
|
||||
sync::{
|
||||
atomic::{AtomicU8, Ordering},
|
||||
Arc,
|
||||
},
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
@ -11,15 +14,25 @@ use dashmap::DashMap;
|
||||
use tracing::{debug, error};
|
||||
|
||||
use once_cell::sync::OnceCell;
|
||||
use sdlan_sn_rs::{config::SDLAN_DEFAULT_TTL, utils::{BROADCAST_MAC, MULTICAST_MAC, Mac, get_current_timestamp, ip_to_string, mac_to_string, net_bit_len_to_mask}};
|
||||
use sdlan_sn_rs::{
|
||||
config::SDLAN_DEFAULT_TTL,
|
||||
utils::{
|
||||
get_current_timestamp, ip_to_string, mac_to_string, net_bit_len_to_mask, Mac,
|
||||
BROADCAST_MAC, MULTICAST_MAC,
|
||||
},
|
||||
};
|
||||
use tokio::sync::{
|
||||
mpsc::{channel, Receiver, Sender},
|
||||
oneshot,
|
||||
};
|
||||
|
||||
use crate::{network::{form_ethernet_packet, send_packet_to_net}, pb::{SdlData, encode_to_udp_message}, tcp::PacketType};
|
||||
use crate::{
|
||||
network::{form_ethernet_packet, send_packet_to_net},
|
||||
pb::{encode_to_udp_message, SdlData},
|
||||
tcp::PacketType,
|
||||
};
|
||||
|
||||
use super::{get_edge};
|
||||
use super::get_edge;
|
||||
|
||||
/*
|
||||
static GLOBAL_ARP: OnceCell<ArpActor> = OnceCell::new();
|
||||
@ -164,8 +177,6 @@ impl ArpEntry {
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
pub struct ArpTable {
|
||||
entries: Arc<DashMap<u32, ArpEntry>>,
|
||||
ttl: Duration,
|
||||
@ -181,7 +192,7 @@ impl ArpTable {
|
||||
pending_packet_buffer: ArpWaitList::new(),
|
||||
};
|
||||
|
||||
let mut bytes = BytesMut::with_capacity(1024+20);
|
||||
let mut bytes = BytesMut::with_capacity(1024 + 20);
|
||||
|
||||
let ttl = res.ttl;
|
||||
tokio::spawn(async move {
|
||||
@ -199,6 +210,7 @@ impl ArpTable {
|
||||
self.pending_packet_buffer.arp_arrived(ip, mac).await;
|
||||
}
|
||||
|
||||
/// origin_data is layer3(ip) packet
|
||||
pub fn add_to_arp_wait_list(&self, ip: u32, origin_data: BytesMut) {
|
||||
self.pending_packet_buffer.add_to_wait_list(ip, origin_data);
|
||||
}
|
||||
@ -484,7 +496,6 @@ pub fn generate_arp_request(srcmac: [u8; 6], dstip: u32, srcip: u32) -> Vec<u8>
|
||||
arphdr.marshal_to_bytes()
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ArpWaitInfo {
|
||||
timestamp: u64,
|
||||
@ -492,7 +503,6 @@ pub struct ArpWaitInfo {
|
||||
origin_data: BytesMut,
|
||||
}
|
||||
|
||||
|
||||
pub const MAX_WAIT_PACKETS: usize = 100;
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -507,7 +517,6 @@ impl ArpWaitList {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn add_to_wait_list(&self, ip: u32, origin_data: BytesMut) {
|
||||
let mut entry = self.content.entry(ip).or_insert(vec![]);
|
||||
if entry.len() < MAX_WAIT_PACKETS {
|
||||
|
||||
@ -1,15 +1,32 @@
|
||||
use std::{collections::HashMap, fs, io::{BufRead, BufReader}, net::Ipv4Addr, sync::{Arc, atomic::{AtomicBool, Ordering}}, time::Duration};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fs,
|
||||
io::{BufRead, BufReader},
|
||||
net::Ipv4Addr,
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc,
|
||||
},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use ahash::RandomState;
|
||||
use arc_swap::ArcSwap;
|
||||
use dashmap::{DashMap};
|
||||
use dashmap::DashMap;
|
||||
use ipnet::Ipv4Net;
|
||||
use sdlan_sn_rs::utils::{Result, SDLanError};
|
||||
|
||||
use tokio::{io::ReadBuf, sync::oneshot::{Receiver, Sender, channel}};
|
||||
use tracing::{debug, error};
|
||||
use tokio::{
|
||||
io::ReadBuf,
|
||||
sync::oneshot::{channel, Receiver, Sender},
|
||||
};
|
||||
use tracing::{debug, error, warn};
|
||||
|
||||
use crate::{RouteTableTrie, network::tun::{add_route, del_route}, pb::{SdlArpResponse, SdlStunReply}};
|
||||
use crate::{
|
||||
network::tun::{add_route, del_route},
|
||||
pb::{SdlArpResponse, SdlStunReply},
|
||||
RouteTableTrie,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RouteInfo {
|
||||
@ -51,6 +68,7 @@ impl RouteTable2 {
|
||||
if net.addr().to_bits() == 0 {
|
||||
// default gateway
|
||||
self.default_gw.store(Arc::new(Some(gw.clone())));
|
||||
continue;
|
||||
}
|
||||
if route.value().load(Ordering::Relaxed) {
|
||||
if let Err(e) = del_route(net, gw) {
|
||||
@ -62,8 +80,11 @@ impl RouteTable2 {
|
||||
self.route_table.clear();
|
||||
|
||||
for route in routes {
|
||||
self.cache_table.insert((route.net, route.gw), AtomicBool::new(false));
|
||||
self.route_table.insert(route.net.addr().into(), route.net.prefix_len(), route.gw);
|
||||
self.cache_table
|
||||
.insert((route.net, route.gw), AtomicBool::new(false));
|
||||
warn!("inserting route {} gw {}", route.net, route.gw);
|
||||
self.route_table
|
||||
.insert(route.net.addr().into(), route.net.prefix_len(), route.gw);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -71,20 +92,17 @@ impl RouteTable2 {
|
||||
/// parse the route_file or route_str and add to the route table.
|
||||
pub fn parse_and_add_route(&self, route_file: &str, route_str: &str) -> Result<()> {
|
||||
let routes = match true {
|
||||
_ if route_str.len() != 0 => {
|
||||
parse_route(route_str)
|
||||
}
|
||||
_ if route_file.len() != 0 => {
|
||||
load_route_file(route_file)
|
||||
}
|
||||
_ => {
|
||||
Ok(HashMap::new())
|
||||
}
|
||||
_ if route_str.len() != 0 => parse_route(route_str),
|
||||
_ if route_file.len() != 0 => load_route_file(route_file),
|
||||
_ => Ok(HashMap::new()),
|
||||
}?;
|
||||
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())));
|
||||
return Err(SDLanError::IOError(format!(
|
||||
"route {} already added",
|
||||
route.0.to_string()
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,18 +118,35 @@ impl RouteTable2 {
|
||||
self.route_table.clear();
|
||||
|
||||
for route in routes.keys() {
|
||||
debug!("got route: {} gw {}", route.0, route.1);
|
||||
self.cache_table.insert(*route, AtomicBool::new(false));
|
||||
self.route_table.insert(route.0.addr().into(), route.0.prefix_len(), route.1);
|
||||
|
||||
warn!(
|
||||
"inserting to route table: {} mask {} gw {}",
|
||||
route.0.addr(),
|
||||
route.0.prefix_len(),
|
||||
route.1
|
||||
);
|
||||
self.route_table.insert(
|
||||
u32::from_be_bytes(route.0.addr().octets()),
|
||||
route.0.prefix_len(),
|
||||
route.1,
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn apply_system(&self) {
|
||||
pub fn apply_system(&self, if_idx: u32) {
|
||||
debug!("applying system");
|
||||
for route in &self.cache_table {
|
||||
let (net, gw) = route.key();
|
||||
debug!("route is {} gw {}", net, gw);
|
||||
if !route.value().load(Ordering::Relaxed) {
|
||||
if let Err(e) = add_route(net, gw) {
|
||||
debug!("adding route: {} gw {}", net, gw);
|
||||
if let Err(e) = add_route(net, gw, if_idx) {
|
||||
error!("failed to add route: {}", e.as_str());
|
||||
} else {
|
||||
route.value().store(true, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
// should add to system
|
||||
@ -150,7 +185,7 @@ pub fn parse_a_route(route: &str) -> Result<(Ipv4Net, Ipv4Addr)> {
|
||||
};
|
||||
|
||||
let cidr = route_info[0];
|
||||
let Ok(net )= cidr.parse::<Ipv4Net>() else {
|
||||
let Ok(net) = cidr.parse::<Ipv4Net>() else {
|
||||
error!("failed to parse cidr: {}, skipping", cidr);
|
||||
return Err(SDLanError::IOError("failed to parse cidr".to_string()));
|
||||
};
|
||||
|
||||
@ -4,7 +4,7 @@ use etherparse::{Ethernet2Header, IpHeaders, NetSlice, SlicedPacket, TransportSl
|
||||
use ipnet::Ipv4Net;
|
||||
use sdlan_sn_rs::config::SDLAN_DEFAULT_TTL;
|
||||
use sdlan_sn_rs::utils::{
|
||||
BROADCAST_MAC, Result, aes_encrypt, ip_to_string, is_multi_broadcast, net_bit_len_to_mask
|
||||
aes_encrypt, ip_to_string, is_multi_broadcast, net_bit_len_to_mask, Result, BROADCAST_MAC,
|
||||
};
|
||||
use std::io::{Error, ErrorKind};
|
||||
use std::net::Ipv4Addr;
|
||||
@ -15,13 +15,14 @@ use std::sync::Arc;
|
||||
use tracing::{debug, error, info};
|
||||
use wintun;
|
||||
|
||||
use crate::{caculate_crc, get_edge};
|
||||
use crate::network::{
|
||||
ARP_REPLY, ARP_REQUEST, ArpHdr, DNS_IP, Node, form_ethernet_packet, generate_arp_request, parse_dns_payload, send_packet_to_net
|
||||
form_ethernet_packet, generate_arp_request, parse_dns_payload, send_packet_to_net, ArpHdr,
|
||||
Node, ARP_REPLY, ARP_REQUEST, DNS_IP,
|
||||
};
|
||||
use crate::pb::{SdlArpResponse, SdlData, encode_to_udp_message};
|
||||
use crate::pb::{encode_to_udp_message, SdlArpResponse, SdlData};
|
||||
use crate::tcp::PacketType;
|
||||
use crate::utils::mac_to_string;
|
||||
use crate::{caculate_crc, get_edge};
|
||||
|
||||
use super::device::{DeviceConfig, Mode};
|
||||
use super::TunTapPacketHandler;
|
||||
@ -34,6 +35,10 @@ pub struct Iface {
|
||||
}
|
||||
|
||||
impl Iface {
|
||||
pub fn get_if_idx(&self) -> u32 {
|
||||
self.if_idx
|
||||
}
|
||||
|
||||
pub fn recv(&self, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||
let Ok(pkt) = self.session.receive_blocking() else {
|
||||
return Err(Error::new(ErrorKind::Other, "failed to receive"));
|
||||
@ -124,15 +129,15 @@ impl Iface {
|
||||
if let Err(e) = set_dns(&self.name, network_domain, &ip, self.if_idx) {
|
||||
error!("failed to set dns: {:?}", e);
|
||||
} else {
|
||||
error!("set dns ok");
|
||||
debug!("set dns ok");
|
||||
}
|
||||
|
||||
node.route_table.apply_system(self.if_idx);
|
||||
}
|
||||
}
|
||||
|
||||
impl TunTapPacketHandler for Iface {
|
||||
async fn handle_packet_from_net(&self, data: &[u8]) -> std::io::Result<()> {
|
||||
|
||||
match Ethernet2Header::from_slice(&data) {
|
||||
Ok((hdr, rest)) => {
|
||||
use etherparse::ether_type::ARP;
|
||||
@ -247,7 +252,6 @@ impl TunTapPacketHandler for Iface {
|
||||
}
|
||||
}
|
||||
ARP_REPLY => {
|
||||
|
||||
debug!("mac {:?} is at {:?}", arp.shwaddr, from_ip.to_be_bytes());
|
||||
if dest_ip == self_ip {
|
||||
/*
|
||||
@ -446,10 +450,7 @@ impl TunTapPacketHandler for Iface {
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
async fn handle_packet_from_device(
|
||||
&self,
|
||||
mut header: BytesMut,
|
||||
) -> std::io::Result<()> {
|
||||
async fn handle_packet_from_device(&self, mut header: BytesMut) -> std::io::Result<()> {
|
||||
use etherparse::IpHeaders;
|
||||
|
||||
let eee = get_edge();
|
||||
@ -467,10 +468,8 @@ impl TunTapPacketHandler for Iface {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
|
||||
match net {
|
||||
NetSlice::Ipv4(ipv4) => {
|
||||
|
||||
let dstip = u32::from_be_bytes(ipv4.header().destination());
|
||||
// let dstip = u32::from_be_bytes(ipv4hdr.0.destination);
|
||||
debug!("packet dst ip: {:?}", ip_to_string(&dstip));
|
||||
@ -479,7 +478,9 @@ impl TunTapPacketHandler for Iface {
|
||||
debug!("packet src ip: {:?}", ip_to_string(&src));
|
||||
// packet should be sent to dev
|
||||
debug!("got {} bytes from tun", data.len());
|
||||
if (!eee.config.allow_routing.load(Ordering::Relaxed)) && (src != eee.device_config.get_ip()) {
|
||||
if (!eee.config.allow_routing.load(Ordering::Relaxed))
|
||||
&& (src != eee.device_config.get_ip())
|
||||
{
|
||||
info!("dropping routed packet");
|
||||
return Ok(());
|
||||
}
|
||||
@ -498,14 +499,19 @@ impl TunTapPacketHandler for Iface {
|
||||
// should do the dns request
|
||||
// println!("request for dns");
|
||||
|
||||
parse_dns_payload(eee, udp.payload(), &data, src, udp.source_port()).await;
|
||||
parse_dns_payload(
|
||||
eee,
|
||||
udp.payload(),
|
||||
&data,
|
||||
src,
|
||||
udp.source_port(),
|
||||
)
|
||||
.await;
|
||||
// edge.udp_sock_for_dns.send_to()
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
_other => {
|
||||
|
||||
}
|
||||
_other => {}
|
||||
}
|
||||
|
||||
match eee.arp_table.get(dstip) {
|
||||
@ -522,7 +528,6 @@ impl TunTapPacketHandler for Iface {
|
||||
let crc = caculate_crc(&data);
|
||||
header.unsplit(data);
|
||||
|
||||
|
||||
// packet.extend_from_slice(ðerheader.to_bytes()[..]);
|
||||
// packet.extend_from_slice(&data);
|
||||
header.extend_from_slice(&crc.to_be_bytes());
|
||||
@ -554,38 +559,42 @@ impl TunTapPacketHandler for Iface {
|
||||
}
|
||||
None => {
|
||||
header.unsplit(data);
|
||||
eee.arp_table.add_to_arp_wait_list(dstip, header);
|
||||
debug!(
|
||||
"find ip: {:?} => {:?}",
|
||||
src.to_be_bytes(),
|
||||
dstip.to_be_bytes()
|
||||
);
|
||||
debug!("no mac found for ip {:?}, sending arp request", dstip.to_be_bytes());
|
||||
debug!(
|
||||
"no mac found for ip {:?}, sending arp request",
|
||||
dstip.to_be_bytes()
|
||||
);
|
||||
// let _ = eee.send_arp_request(dstip, dstip).await;
|
||||
|
||||
if eee.device_config.contains(&Ipv4Addr::from_bits(dstip)) {
|
||||
debug!("contains dst ip {}", ip_to_string(&dstip));
|
||||
eee.arp_table.add_to_arp_wait_list(dstip, header);
|
||||
let _ = eee.send_arp_request(dstip, dstip).await;
|
||||
} else {
|
||||
debug!("try to lookup ip: {}", ip_to_string(&dstip));
|
||||
if let Some((_, real_ip)) = eee.route_table.lookup(dstip) {
|
||||
eee.arp_table.add_to_arp_wait_list(
|
||||
u32::from_be_bytes(real_ip.octets()),
|
||||
header,
|
||||
);
|
||||
error!("got target route: {}", real_ip);
|
||||
let real_ip = u32::from_be_bytes(real_ip.octets());
|
||||
let _ = eee.send_arp_request(dstip, real_ip).await;
|
||||
let _ = eee.send_arp_request(real_ip, dstip).await;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
NetSlice::Ipv6(ipv6) => {
|
||||
|
||||
}
|
||||
NetSlice::Ipv6(ipv6) => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
async fn handle_packet_from_device(
|
||||
&self,
|
||||
@ -717,7 +726,9 @@ fn create_wintun(path: &str, name: &str) -> Iface {
|
||||
Err(_e) => wintun::Adapter::create(&wt, name, "Example", None)
|
||||
.expect("failed to create tun adapter"),
|
||||
};
|
||||
let idx = adapter.get_adapter_index().expect("failed to get adapter index");
|
||||
let idx = adapter
|
||||
.get_adapter_index()
|
||||
.expect("failed to get adapter index");
|
||||
// println!("idx = {}", idx);
|
||||
let session = Arc::new(adapter.start_session(wintun::MAX_RING_CAPACITY).unwrap());
|
||||
Iface {
|
||||
@ -737,7 +748,7 @@ pub fn get_install_channel() -> String {
|
||||
"windows".to_owned()
|
||||
}
|
||||
|
||||
pub fn set_dns(name: &str, _network_domain: &str, gw: &str, ifidx: u32) -> std::io::Result<()>{
|
||||
pub fn set_dns(name: &str, _network_domain: &str, gw: &str, ifidx: u32) -> std::io::Result<()> {
|
||||
let res = Command::new("ROUTE")
|
||||
.arg("ADD")
|
||||
.arg("100.100.100.100")
|
||||
@ -769,11 +780,10 @@ pub fn set_dns(name: &str, _network_domain: &str, gw: &str, ifidx: u32) -> std::
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn restore_dns() {
|
||||
|
||||
}
|
||||
pub fn restore_dns() {}
|
||||
|
||||
pub fn del_route(net: &Ipv4Net, gw: &Ipv4Addr) -> Result<()> {
|
||||
error!("deleting route: {} gw {}", net, gw);
|
||||
let mask = net.netmask().to_string();
|
||||
let network = net.network().to_string();
|
||||
let res = Command::new("route")
|
||||
@ -783,32 +793,54 @@ pub fn del_route(net: &Ipv4Net, gw: &Ipv4Addr) -> Result<()> {
|
||||
.arg(gw.to_string())
|
||||
.output()?;
|
||||
Ok(())
|
||||
|
||||
}
|
||||
|
||||
pub fn add_route(net: &Ipv4Net, gw: &Ipv4Addr) -> Result<()> {
|
||||
pub fn add_route(net: &Ipv4Net, gw: &Ipv4Addr, if_idx: u32) -> Result<()> {
|
||||
let mask = net.netmask().to_string();
|
||||
let network = net.network().to_string();
|
||||
let res = Command::new("route")
|
||||
match Command::new("route")
|
||||
.arg("add")
|
||||
.arg(network)
|
||||
.arg("MASK")
|
||||
.arg(mask)
|
||||
.arg(gw.to_string())
|
||||
.output()?;
|
||||
Ok(())
|
||||
}
|
||||
.arg("if")
|
||||
.arg(format!("{}", if_idx))
|
||||
.output()
|
||||
{
|
||||
Err(e) => {
|
||||
error!("failed to add route: {}", e);
|
||||
Err(e.into())
|
||||
}
|
||||
|
||||
Ok(value) => {
|
||||
debug!(
|
||||
"add route ok: {}, out={:?}, err={}",
|
||||
value.status,
|
||||
String::from_utf8_lossy(value.stdout.as_slice()),
|
||||
String::from_utf8_lossy(value.stderr.as_slice()),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn arp_reply_arrived(edge: &Node, data: SdlArpResponse) {
|
||||
debug!("got arp response: {:?}", data);
|
||||
if data.target_mac.len() != 6 {
|
||||
// invalid target_mac
|
||||
error!("invalid target_mac: {:?}, ip={}", data.target_mac, ip_to_string(&data.target_ip));
|
||||
error!(
|
||||
"invalid target_mac: {:?}, ip={}",
|
||||
data.target_mac,
|
||||
ip_to_string(&data.target_ip)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let ip = data.target_ip;
|
||||
let ip = data.origin_ip;
|
||||
let mac = data.target_mac.try_into().unwrap();
|
||||
|
||||
debug!("setting mac {:?} for {}", mac, ip_to_string(&ip));
|
||||
edge.arp_table.set(ip, mac);
|
||||
edge.arp_table.arp_arrived(ip, mac).await;
|
||||
}
|
||||
@ -1,4 +1,3 @@
|
||||
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use bytes::{Bytes, BytesMut};
|
||||
@ -6,7 +5,7 @@ use dashmap::DashMap;
|
||||
use once_cell::sync::OnceCell;
|
||||
use sdlan_sn_rs::{
|
||||
config::SDLAN_DEFAULT_TTL,
|
||||
utils::{Mac, Result, get_current_timestamp, ip_to_string},
|
||||
utils::{get_current_timestamp, ip_to_string, Mac, Result},
|
||||
};
|
||||
|
||||
use tracing::{debug, warn};
|
||||
@ -14,8 +13,8 @@ use tracing::{debug, warn};
|
||||
use tracing::error;
|
||||
|
||||
use crate::{
|
||||
network::{Node, RouteInfo, form_ethernet_packet, send_packet_to_net},
|
||||
pb::{SdlData, encode_to_udp_message},
|
||||
network::{form_ethernet_packet, send_packet_to_net, Node, RouteInfo},
|
||||
pb::{encode_to_udp_message, SdlData},
|
||||
tcp::PacketType,
|
||||
utils::mac_to_string,
|
||||
};
|
||||
@ -24,18 +23,17 @@ use super::get_edge;
|
||||
|
||||
pub const MAX_WAIT_PACKETS: usize = 100;
|
||||
|
||||
const DEFAULT_DNS_SERVER: u32 = (223<<24) + (5<<16) + (5<<8) + 5; // ali dns
|
||||
const DEFAULT_DNS_SERVER: u32 = (223 << 24) + (5 << 16) + (5 << 8) + 5; // ali dns
|
||||
|
||||
pub trait TunTapPacketHandler {
|
||||
async fn handle_packet_from_net(&self, data: &[u8]) -> std::io::Result<()>;
|
||||
async fn handle_packet_from_device(&self, data: BytesMut) -> std::io::Result<()>;
|
||||
}
|
||||
|
||||
|
||||
pub fn set_route_from_net(routes: Vec<RouteInfo>) -> Result<()>{
|
||||
pub fn set_route_from_net(routes: Vec<RouteInfo>) -> Result<()> {
|
||||
let eee = get_edge();
|
||||
eee.route_table.clear_and_add_routes(routes)?;
|
||||
eee.route_table.apply_system();
|
||||
eee.route_table.apply_system(eee.device.get_if_idx());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -149,7 +147,6 @@ pub fn get_dns_gateway(edge: &Node, payload: &[u8]) -> Option<String> {
|
||||
Ok(p) => p,
|
||||
};
|
||||
|
||||
|
||||
let mut target_dns: &str = "";
|
||||
if !dns_packet.has_flags(simple_dns::PacketFlag::RESPONSE) && !dns_packet.questions.is_empty() {
|
||||
let question = &dns_packet.questions[0];
|
||||
@ -168,27 +165,55 @@ pub fn get_dns_gateway(edge: &Node, payload: &[u8]) -> Option<String> {
|
||||
return None;
|
||||
}
|
||||
|
||||
pub async fn parse_dns_payload(edge: &Node, layer7: &[u8], layer3: &[u8], source_ip: u32, source_port: u16) {
|
||||
pub async fn parse_dns_payload(
|
||||
edge: &Node,
|
||||
layer7: &[u8],
|
||||
layer3: &[u8],
|
||||
source_ip: u32,
|
||||
source_port: u16,
|
||||
) {
|
||||
match simple_dns::Packet::parse(layer7) {
|
||||
Ok(mut dns) => {
|
||||
if !dns.has_flags(simple_dns::PacketFlag::RESPONSE) && !dns.questions.is_empty() {
|
||||
let question = &dns.questions[0];
|
||||
let qname = question.qname.to_string();
|
||||
if qname.ends_with(edge.network_domain.load().as_str()) {
|
||||
warn!("question 15353 for {} from {}:{} with transaction_id = {}",
|
||||
qname, ip_to_string(&source_ip), source_port, dns.id());
|
||||
warn!(
|
||||
"question 15353 for {} from {}:{} with transaction_id = {}",
|
||||
qname,
|
||||
ip_to_string(&source_ip),
|
||||
source_port,
|
||||
dns.id()
|
||||
);
|
||||
// should send to our socket
|
||||
if let Err(e) = edge.udp_sock_for_dns.send_to(layer3, format!("{}:15353", edge.server_ip)).await {
|
||||
if let Err(e) = edge
|
||||
.udp_sock_for_dns
|
||||
.send_to(layer3, format!("{}:15353", edge.server_ip))
|
||||
.await
|
||||
{
|
||||
error!("failed to send request to 15353: {}", e);
|
||||
}
|
||||
} else {
|
||||
let origin_transaction_id = dns.id();
|
||||
let transaction_id = edge.dns_matcher.generate_transaction_id(source_ip, source_port, origin_transaction_id);
|
||||
let transaction_id = edge.dns_matcher.generate_transaction_id(
|
||||
source_ip,
|
||||
source_port,
|
||||
origin_transaction_id,
|
||||
);
|
||||
dns.set_id(transaction_id);
|
||||
warn!("question 223.5.5.5 for {} from {}:{} with transaction_id = {}",
|
||||
qname, ip_to_string(&source_ip), source_port, dns.id());
|
||||
warn!(
|
||||
"question 223.5.5.5 for {} from {}:{} with transaction_id = {}",
|
||||
qname,
|
||||
ip_to_string(&source_ip),
|
||||
source_port,
|
||||
dns.id()
|
||||
);
|
||||
if let Ok(res) = dns.build_bytes_vec() {
|
||||
if let Err(e) = edge.udp_sock_for_global_dns.send_to(&res, "223.5.5.5:53").await {
|
||||
if let Err(e) = edge
|
||||
.udp_sock_for_global_dns
|
||||
.send_to(&res, "223.5.5.5:53")
|
||||
.await
|
||||
{
|
||||
error!("failed to query for global dns: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,17 +1,47 @@
|
||||
use std::{net::IpAddr, sync::{Arc, OnceLock, atomic::{AtomicBool, AtomicU64, Ordering}}, time::Duration};
|
||||
use std::{
|
||||
net::IpAddr,
|
||||
sync::{
|
||||
atomic::{AtomicBool, AtomicU64, Ordering},
|
||||
Arc, OnceLock,
|
||||
},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use futures_util::pin_mut;
|
||||
use prost::Message;
|
||||
use quinn::SendStream;
|
||||
use sdlan_sn_rs::{config::AF_INET, peer::{SdlanSock, V6Info}, utils::{Result, SDLanError, get_current_timestamp, ip_to_string, rsa_decrypt}};
|
||||
use tokio::{sync::mpsc::{Receiver, Sender, channel}, time::sleep};
|
||||
use sdlan_sn_rs::{
|
||||
config::AF_INET,
|
||||
peer::{SdlanSock, V6Info},
|
||||
utils::{get_current_timestamp, ip_to_string, rsa_decrypt, Result, SDLanError},
|
||||
};
|
||||
use tokio::{
|
||||
sync::mpsc::{channel, Receiver, Sender},
|
||||
time::sleep,
|
||||
};
|
||||
|
||||
use tokio_util::sync::CancellationToken;
|
||||
use tracing::{debug, error, warn, info};
|
||||
use tracing::{debug, error, info, warn};
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
use crate::network::{set_allow_routing, set_disallow_routing};
|
||||
use crate::{AesEncryptor, Chacha20Encryptor, ConnectionInfo, ConnectionState, MyEncryptor, RuleFromServer, config::{NULL_MAC, TCP_PING_TIME}, get_edge, load_configuration, network::{ARP_REPLY, ArpHdr, EthHdr, Node, RegisterSuperFeedback, StartStopInfo, arp_reply_arrived, check_peer_registration_needed, handle_packet_peer_info}, pb::{SdlArpResponse, SdlCommand, SdlCommandAck, SdlEvent, SdlPolicyResponse, SdlRegisterSuper, SdlRegisterSuperAck, SdlRegisterSuperNak, encode_to_tcp_message, sdl_command, sdl_event::{self, Event, SendRegister}}, store_configuration, tcp::{EventType, NakMsgCode, NatType, PacketType, SdlanTcp, read_a_packet, send_stun_request}};
|
||||
use crate::{
|
||||
config::{NULL_MAC, TCP_PING_TIME},
|
||||
get_edge, load_configuration,
|
||||
network::{
|
||||
arp_reply_arrived, check_peer_registration_needed, handle_packet_peer_info, ArpHdr, EthHdr,
|
||||
Node, RegisterSuperFeedback, StartStopInfo, ARP_REPLY,
|
||||
},
|
||||
pb::{
|
||||
encode_to_tcp_message, sdl_command,
|
||||
sdl_event::{self, Event, SendRegister},
|
||||
SdlArpResponse, SdlCommand, SdlCommandAck, SdlEvent, SdlPolicyResponse, SdlRegisterSuper,
|
||||
SdlRegisterSuperAck, SdlRegisterSuperNak,
|
||||
},
|
||||
store_configuration,
|
||||
tcp::{read_a_packet, send_stun_request, EventType, NakMsgCode, NatType, PacketType, SdlanTcp},
|
||||
AesEncryptor, Chacha20Encryptor, ConnectionInfo, ConnectionState, MyEncryptor, RuleFromServer,
|
||||
};
|
||||
|
||||
static GLOBAL_QUIC_HANDLE: OnceLock<ReadWriterHandle> = OnceLock::new();
|
||||
|
||||
@ -73,7 +103,7 @@ impl ReadWriterHandle {
|
||||
to_tcp,
|
||||
// on_connected,
|
||||
// on_disconnected,
|
||||
start_stop_chan
|
||||
start_stop_chan,
|
||||
)
|
||||
.await
|
||||
});
|
||||
@ -106,7 +136,6 @@ pub fn get_quic_write_conn() -> &'static ReadWriterHandle {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async fn handle_tcp_message(msg: SdlanTcp) {
|
||||
let edge = get_edge();
|
||||
|
||||
@ -138,18 +167,20 @@ async fn handle_tcp_message(msg: SdlanTcp) {
|
||||
|
||||
match ack.algorithm.to_ascii_lowercase().as_str() {
|
||||
"chacha20" => {
|
||||
edge.encryptor.store(Arc::new(MyEncryptor::ChaChao20(Chacha20Encryptor::new(key, ack.region_id))))
|
||||
edge.encryptor
|
||||
.store(Arc::new(MyEncryptor::ChaChao20(Chacha20Encryptor::new(
|
||||
key,
|
||||
ack.region_id,
|
||||
))))
|
||||
// *edge.encryptor.write().unwrap() = MyEncryptor::ChaChao20(Chacha20Encryptor::new(key, ack.region_id));
|
||||
}
|
||||
"aes" => {
|
||||
edge.encryptor.store(Arc::new(MyEncryptor::Aes(AesEncryptor::new(key))))
|
||||
edge.encryptor
|
||||
.store(Arc::new(MyEncryptor::Aes(AesEncryptor::new(key))))
|
||||
// *edge.encryptor.write().unwrap() = MyEncryptor::Aes(AesEncryptor::new(key));
|
||||
}
|
||||
_other => {
|
||||
|
||||
_other => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
let Some(dev) = ack.dev_addr else {
|
||||
@ -188,7 +219,8 @@ async fn handle_tcp_message(msg: SdlanTcp) {
|
||||
edge.network_id.store(dev.network_id, Ordering::Relaxed);
|
||||
*/
|
||||
// edge.device.reload_config(&edge.device_config, &dev.network_domain);
|
||||
edge.device.reload_config(edge, &edge.device_config, &edge.network_domain.load());
|
||||
edge.device
|
||||
.reload_config(edge, &edge.device_config, &edge.network_domain.load());
|
||||
|
||||
edge.set_authorized(true);
|
||||
|
||||
@ -205,7 +237,6 @@ async fn handle_tcp_message(msg: SdlanTcp) {
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
arp_reply_arrived(edge, res).await;
|
||||
return;
|
||||
}
|
||||
@ -222,13 +253,10 @@ async fn handle_tcp_message(msg: SdlanTcp) {
|
||||
break;
|
||||
}
|
||||
let proto = policy.rules[start];
|
||||
let port = u16::from_be_bytes([policy.rules[start+1], policy.rules[start+2]]);
|
||||
let port = u16::from_be_bytes([policy.rules[start + 1], policy.rules[start + 2]]);
|
||||
start += 3;
|
||||
|
||||
infos.push(RuleFromServer{
|
||||
proto,
|
||||
port,
|
||||
});
|
||||
infos.push(RuleFromServer { proto, port });
|
||||
}
|
||||
|
||||
edge.rule_cache.set_identity_cache(identity, infos);
|
||||
@ -342,7 +370,6 @@ async fn handle_tcp_message(msg: SdlanTcp) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async fn handle_tcp_command(edge: &Node, cmdprotobuf: &[u8]) {
|
||||
let Ok(cmd) = SdlCommand::decode(cmdprotobuf) else {
|
||||
error!("failed to decode SdlCommand");
|
||||
@ -362,7 +389,10 @@ async fn handle_tcp_command(edge: &Node, cmdprotobuf: &[u8]) {
|
||||
// std::process::exit(0);
|
||||
if node.action == 0 {
|
||||
// stop
|
||||
let origin = edge.config.allow_routing.fetch_and(false, Ordering::Relaxed);
|
||||
let origin = edge
|
||||
.config
|
||||
.allow_routing
|
||||
.fetch_and(false, Ordering::Relaxed);
|
||||
let mut config = load_configuration();
|
||||
config.allow_routing = Some(false);
|
||||
let _ = store_configuration(&config);
|
||||
@ -382,7 +412,7 @@ async fn handle_tcp_command(edge: &Node, cmdprotobuf: &[u8]) {
|
||||
}
|
||||
}
|
||||
|
||||
let ack = SdlCommandAck{
|
||||
let ack = SdlCommandAck {
|
||||
pkt_id,
|
||||
code: 0,
|
||||
message: "ok".to_owned(),
|
||||
@ -396,7 +426,6 @@ async fn handle_tcp_command(edge: &Node, cmdprotobuf: &[u8]) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async fn handle_tcp_event(edge: &'static Node, eventprotobuf: &[u8]) {
|
||||
@ -455,10 +484,8 @@ async fn handle_tcp_event(edge: &'static Node, eventprotobuf: &[u8]) {
|
||||
debug!("unhandled event {:?}", other);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
pub fn init_quic_conn(
|
||||
cancel: CancellationToken,
|
||||
addr: &str,
|
||||
@ -472,8 +499,8 @@ pub fn init_quic_conn(
|
||||
connecting_chan: Option<Sender<ConnectionInfo>>,
|
||||
ipv6_network_restarter: Option<Sender<bool>>,
|
||||
)
|
||||
// T2: Fn(SdlanTcp) -> F + Send + 'static,
|
||||
// F: Future<Output = ()> + Send,
|
||||
// T2: Fn(SdlanTcp) -> F + Send + 'static,
|
||||
// F: Future<Output = ()> + Send,
|
||||
{
|
||||
let tcp_handle = ReadWriterHandle::new(
|
||||
cancel,
|
||||
@ -577,7 +604,10 @@ impl ReadWriteActor {
|
||||
|
||||
debug!("try connecting to {}", self.domain);
|
||||
|
||||
let conn = match edge.quic_endpoint.connect(self.remote.parse().unwrap(), &self.domain) {
|
||||
let conn = match edge
|
||||
.quic_endpoint
|
||||
.connect(self.remote.parse().unwrap(), &self.domain)
|
||||
{
|
||||
Ok(conn) => conn,
|
||||
Err(e) => {
|
||||
error!("failed to connect: {}", e);
|
||||
@ -589,7 +619,6 @@ impl ReadWriteActor {
|
||||
continue;
|
||||
}
|
||||
return;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@ -764,11 +793,8 @@ async fn on_connected_callback(local_ip: Option<IpAddr>, stream: &mut SendStream
|
||||
|
||||
// debug!("send register super: {:?}", register_super);
|
||||
// let packet_id = edge.get_next_packet_id();
|
||||
let data = encode_to_tcp_message(
|
||||
Some(register_super),
|
||||
PacketType::RegisterSuper as u8,
|
||||
)
|
||||
.unwrap();
|
||||
let data =
|
||||
encode_to_tcp_message(Some(register_super), PacketType::RegisterSuper as u8).unwrap();
|
||||
if let Err(e) = stream.write(&data).await {
|
||||
error!("failed to write to tcp: {}", e.to_string());
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ struct IpTrie {
|
||||
impl IpTrie {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
root: TrieNode::default()
|
||||
root: TrieNode::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,17 +28,16 @@ impl IpTrie {
|
||||
|
||||
let mut node = &mut self.root;
|
||||
for i in 0..prefix_len {
|
||||
let bit = ((prefix >> (31-i)) & 1) as usize;
|
||||
let bit = ((prefix >> (31 - i)) & 1) as usize;
|
||||
node = node.child[bit].get_or_insert_with(|| Box::new(TrieNode::default()));
|
||||
|
||||
}
|
||||
if prefix_len > node.prefix_len {
|
||||
if prefix_len >= node.prefix_len {
|
||||
node.prefix_len = prefix_len;
|
||||
node.nexthop = Some(nexthop);
|
||||
}
|
||||
}
|
||||
|
||||
fn lookup(&self, ip: u32) -> Option<(u8, Ipv4Addr)>{
|
||||
fn lookup(&self, ip: u32) -> Option<(u8, Ipv4Addr)> {
|
||||
let mut node = &self.root;
|
||||
let mut best = None;
|
||||
|
||||
@ -46,7 +45,8 @@ impl IpTrie {
|
||||
if node.nexthop.is_some() {
|
||||
best = Some((node.prefix_len, node.nexthop.unwrap()));
|
||||
}
|
||||
let bit = ((ip>>(31-i)) & 1) as usize;
|
||||
let bit = ((ip >> (31 - i)) & 1) as usize;
|
||||
// println!("to find bit {} => {}", i, bit);
|
||||
match &node.child[bit] {
|
||||
Some(child) => {
|
||||
node = child;
|
||||
@ -63,6 +63,51 @@ impl IpTrie {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
use crate::{network::RouteTable2, TrieNode};
|
||||
|
||||
#[test]
|
||||
fn test_trie() {
|
||||
let trie = RouteTable2::new();
|
||||
|
||||
let mut ips: Vec<(Ipv4Addr, Ipv4Addr)> = vec![];
|
||||
for i in 1..254u32 {
|
||||
ips.push((
|
||||
format!("192.168.{}.0", i).parse::<Ipv4Addr>().unwrap(),
|
||||
format!("192.168.{}.1", i).parse::<Ipv4Addr>().unwrap(),
|
||||
));
|
||||
}
|
||||
for ip in &ips {
|
||||
trie.route_table
|
||||
.insert(u32::from_be_bytes(ip.0.octets()), 24, ip.1);
|
||||
}
|
||||
|
||||
for ip in &ips {
|
||||
let origin = ip.0;
|
||||
let mut query = origin.octets();
|
||||
query[3] = 123;
|
||||
let query = Ipv4Addr::from_octets(query);
|
||||
|
||||
println!("query for {}", query);
|
||||
let result = ip.1;
|
||||
let Some((prefix, target)) =
|
||||
trie.route_table.lookup(u32::from_be_bytes(query.octets()))
|
||||
else {
|
||||
panic!("failed to lookup: {} for {}", query, result);
|
||||
};
|
||||
if prefix != 24 {
|
||||
panic!("prefix is not 24: {}", prefix);
|
||||
}
|
||||
if target != result {
|
||||
panic!("gateway is not match, {} expected {}", target, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RouteTableTrie {
|
||||
trie: ArcSwap<IpTrie>,
|
||||
}
|
||||
@ -70,7 +115,7 @@ pub struct RouteTableTrie {
|
||||
impl RouteTableTrie {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
trie: ArcSwap::new(Arc::new(IpTrie::default()))
|
||||
trie: ArcSwap::new(Arc::new(IpTrie::default())),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user