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 = "0.12.6"
|
||||||
prost-build = "0.12.6"
|
prost-build = "0.12.6"
|
||||||
rand = "0.8.5"
|
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"
|
rsa = "0.9.6"
|
||||||
# sdlan-sn-rs = { git = "ssh://git@git2.asxalex.pw/sdlan-v2/sdlan-rs.git" }
|
# 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"}
|
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::fs::OpenOptions;
|
||||||
use std::process;
|
use std::process;
|
||||||
|
|
||||||
use std::env;
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
use std::env;
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
use daemonize::Daemonize;
|
use daemonize::Daemonize;
|
||||||
@ -14,11 +14,7 @@ use daemonize::Daemonize;
|
|||||||
use futures_util::io;
|
use futures_util::io;
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
use libc::{SIGTERM, kill};
|
use libc::{kill, SIGTERM};
|
||||||
use punchnet::CachedLoginInfo;
|
|
||||||
use punchnet::CommandLineInput2;
|
|
||||||
use punchnet::Commands;
|
|
||||||
use punchnet::ExitNodeCmd;
|
|
||||||
use punchnet::get_access_token;
|
use punchnet::get_access_token;
|
||||||
use punchnet::get_base_dir;
|
use punchnet::get_base_dir;
|
||||||
use punchnet::get_edge;
|
use punchnet::get_edge;
|
||||||
@ -28,31 +24,34 @@ use punchnet::restore_dns;
|
|||||||
use punchnet::run_sdlan;
|
use punchnet::run_sdlan;
|
||||||
use punchnet::set_access_token;
|
use punchnet::set_access_token;
|
||||||
use punchnet::set_base_dir;
|
use punchnet::set_base_dir;
|
||||||
|
use punchnet::CachedLoginInfo;
|
||||||
use punchnet::CommandLine;
|
use punchnet::CommandLine;
|
||||||
|
use punchnet::CommandLineInput2;
|
||||||
|
use punchnet::Commands;
|
||||||
|
use punchnet::ExitNodeCmd;
|
||||||
use sdlan_sn_rs::log;
|
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::Mac;
|
||||||
use sdlan_sn_rs::utils::Result;
|
use sdlan_sn_rs::utils::Result;
|
||||||
use sdlan_sn_rs::utils::create_or_load_uuid;
|
|
||||||
use tokio::runtime::Runtime;
|
use tokio::runtime::Runtime;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
|
|
||||||
use std::net::ToSocketAddrs;
|
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::ConnectData;
|
||||||
use crate::api::ConnectResponse;
|
use crate::api::ConnectResponse;
|
||||||
use crate::api::LoginData;
|
use crate::api::LoginData;
|
||||||
use crate::api::LoginResponse;
|
use crate::api::LoginResponse;
|
||||||
use crate::api::TEST_PREFIX;
|
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::handle_query_for_info_info;
|
||||||
use crate::local_udp_info::query_for_exit_node_list;
|
use crate::local_udp_info::query_for_exit_node_list;
|
||||||
use crate::local_udp_info::query_for_info;
|
use crate::local_udp_info::query_for_info;
|
||||||
|
|
||||||
|
|
||||||
const APP_USER_ENV_NAME: &str = "PUNCH_USER";
|
const APP_USER_ENV_NAME: &str = "PUNCH_USER";
|
||||||
const APP_PASS_ENV_NAME: &str = "PUNCH_PASS";
|
const APP_PASS_ENV_NAME: &str = "PUNCH_PASS";
|
||||||
const APP_TOKEN_ENV_NAME: &str = "PUNCH_TOKEN";
|
const APP_TOKEN_ENV_NAME: &str = "PUNCH_TOKEN";
|
||||||
@ -224,7 +223,8 @@ async fn daemonize_me(
|
|||||||
eprintln!("got ip from network is invlid: {}", connect_info.ip);
|
eprintln!("got ip from network is invlid: {}", connect_info.ip);
|
||||||
process::exit(-5);
|
process::exit(-5);
|
||||||
};
|
};
|
||||||
if let Err(e) = edge.start_without_feedback(
|
if let Err(e) = edge
|
||||||
|
.start_without_feedback(
|
||||||
remembered.access_token.clone(),
|
remembered.access_token.clone(),
|
||||||
// String::new(),
|
// String::new(),
|
||||||
remembered.network_id,
|
remembered.network_id,
|
||||||
@ -234,7 +234,9 @@ async fn daemonize_me(
|
|||||||
connect_info.identity_id,
|
connect_info.identity_id,
|
||||||
// 0,
|
// 0,
|
||||||
None,
|
None,
|
||||||
).await {
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
error!("failed to start: {:?}", e);
|
error!("failed to start: {:?}", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,7 +279,6 @@ async fn daemonize_me(
|
|||||||
// started = !started;
|
// started = !started;
|
||||||
// */
|
// */
|
||||||
// }
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
@ -285,13 +286,11 @@ const SYSTEM: &'static str = "windows";
|
|||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
const DEFAULT_BASE_DIR: &'static str = ".";
|
const DEFAULT_BASE_DIR: &'static str = ".";
|
||||||
|
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
const SYSTEM: &'static str = "linux";
|
const SYSTEM: &'static str = "linux";
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
const DEFAULT_BASE_DIR: &'static str = "/usr/local/punchnet";
|
const DEFAULT_BASE_DIR: &'static str = "/usr/local/punchnet";
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
set_base_dir(DEFAULT_BASE_DIR);
|
set_base_dir(DEFAULT_BASE_DIR);
|
||||||
// let _guard = log::init_log(&format!("{}/.output", get_base_dir()));
|
// let _guard = log::init_log(&format!("{}/.output", get_base_dir()));
|
||||||
@ -315,7 +314,16 @@ fn main() {
|
|||||||
let rt = Runtime::new().unwrap();
|
let rt = Runtime::new().unwrap();
|
||||||
rt.block_on(async move {
|
rt.block_on(async move {
|
||||||
let _ = parse_login_result(
|
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);
|
process::exit(0);
|
||||||
@ -325,7 +333,8 @@ fn main() {
|
|||||||
let rt = Runtime::new().unwrap();
|
let rt = Runtime::new().unwrap();
|
||||||
rt.block_on(async move {
|
rt.block_on(async move {
|
||||||
let _ = parse_login_result(
|
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);
|
process::exit(0);
|
||||||
@ -338,14 +347,9 @@ fn main() {
|
|||||||
ExitNodeCmd::List => {
|
ExitNodeCmd::List => {
|
||||||
query_for_exit_node_list().await;
|
query_for_exit_node_list().await;
|
||||||
}
|
}
|
||||||
ExitNodeCmd::Start(info) => {
|
ExitNodeCmd::Start(info) => {}
|
||||||
|
ExitNodeCmd::Stop => {}
|
||||||
}
|
}
|
||||||
ExitNodeCmd::Stop => {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
});
|
||||||
process::exit(0);
|
process::exit(0);
|
||||||
}
|
}
|
||||||
@ -399,12 +403,14 @@ fn main() {
|
|||||||
.create(true)
|
.create(true)
|
||||||
.truncate(true)
|
.truncate(true)
|
||||||
.write(true)
|
.write(true)
|
||||||
.open("/tmp/punchnet.out").unwrap();
|
.open("/tmp/punchnet.out")
|
||||||
|
.unwrap();
|
||||||
let err = OpenOptions::new()
|
let err = OpenOptions::new()
|
||||||
.create(true)
|
.create(true)
|
||||||
.truncate(true)
|
.truncate(true)
|
||||||
.write(true)
|
.write(true)
|
||||||
.open("/tmp/punchnet.err").unwrap();
|
.open("/tmp/punchnet.err")
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let daemonize = Daemonize::new()
|
let daemonize = Daemonize::new()
|
||||||
.pid_file("/tmp/punchnet.pid")
|
.pid_file("/tmp/punchnet.pid")
|
||||||
@ -412,8 +418,7 @@ fn main() {
|
|||||||
.working_directory(get_base_dir())
|
.working_directory(get_base_dir())
|
||||||
.stdout(out)
|
.stdout(out)
|
||||||
.stderr(err)
|
.stderr(err)
|
||||||
.privileged_action(|| {
|
.privileged_action(|| {});
|
||||||
});
|
|
||||||
|
|
||||||
match daemonize.start() {
|
match daemonize.start() {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
@ -431,11 +436,17 @@ fn main() {
|
|||||||
run_it(cmd, client_id, allow_routing, mac, system, version);
|
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();
|
let rt = Runtime::new().unwrap();
|
||||||
match &cmd.cmd {
|
match &cmd.cmd {
|
||||||
Commands::Start(rtinfo) => {
|
Commands::Start(rtinfo) => rt.block_on(async move {
|
||||||
rt.block_on(async move {
|
|
||||||
let remembered_token = get_access_token();
|
let remembered_token = get_access_token();
|
||||||
if remembered_token.is_none() {
|
if remembered_token.is_none() {
|
||||||
eprintln!("not logged in, should login with user/pass or token first");
|
eprintln!("not logged in, should login with user/pass or token first");
|
||||||
@ -443,17 +454,25 @@ fn run_it(cmd: CommandLineInput2, client_id: String, allow_routing: bool, mac: M
|
|||||||
}
|
}
|
||||||
let remembered = remembered_token.unwrap();
|
let remembered = remembered_token.unwrap();
|
||||||
let connect_info = parse_connect_result(
|
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;
|
daemonize_me(
|
||||||
})
|
rtinfo.allow_routing || allow_routing,
|
||||||
}
|
connect_info,
|
||||||
Commands::AutoRun(tk) => {
|
remembered,
|
||||||
rt.block_on(async move {
|
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();
|
let mut remembered_token = get_access_token();
|
||||||
if remembered_token.is_none() {
|
if remembered_token.is_none() {
|
||||||
let data = parse_login_result(
|
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,
|
access_token: data.access_token,
|
||||||
@ -469,11 +488,19 @@ fn run_it(cmd: CommandLineInput2, client_id: String, allow_routing: bool, mac: M
|
|||||||
let remembered = remembered_token.unwrap();
|
let remembered = remembered_token.unwrap();
|
||||||
|
|
||||||
let connect_info = parse_connect_result(
|
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 => {
|
other => {
|
||||||
eprintln!("should not comes here");
|
eprintln!("should not comes here");
|
||||||
|
|||||||
@ -2,7 +2,10 @@
|
|||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
sync::{Arc, atomic::{AtomicU8, Ordering}},
|
sync::{
|
||||||
|
atomic::{AtomicU8, Ordering},
|
||||||
|
Arc,
|
||||||
|
},
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -11,15 +14,25 @@ use dashmap::DashMap;
|
|||||||
use tracing::{debug, error};
|
use tracing::{debug, error};
|
||||||
|
|
||||||
use once_cell::sync::OnceCell;
|
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::{
|
use tokio::sync::{
|
||||||
mpsc::{channel, Receiver, Sender},
|
mpsc::{channel, Receiver, Sender},
|
||||||
oneshot,
|
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();
|
static GLOBAL_ARP: OnceCell<ArpActor> = OnceCell::new();
|
||||||
@ -164,8 +177,6 @@ impl ArpEntry {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pub struct ArpTable {
|
pub struct ArpTable {
|
||||||
entries: Arc<DashMap<u32, ArpEntry>>,
|
entries: Arc<DashMap<u32, ArpEntry>>,
|
||||||
ttl: Duration,
|
ttl: Duration,
|
||||||
@ -199,6 +210,7 @@ impl ArpTable {
|
|||||||
self.pending_packet_buffer.arp_arrived(ip, mac).await;
|
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) {
|
pub fn add_to_arp_wait_list(&self, ip: u32, origin_data: BytesMut) {
|
||||||
self.pending_packet_buffer.add_to_wait_list(ip, origin_data);
|
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()
|
arphdr.marshal_to_bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ArpWaitInfo {
|
pub struct ArpWaitInfo {
|
||||||
timestamp: u64,
|
timestamp: u64,
|
||||||
@ -492,7 +503,6 @@ pub struct ArpWaitInfo {
|
|||||||
origin_data: BytesMut,
|
origin_data: BytesMut,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub const MAX_WAIT_PACKETS: usize = 100;
|
pub const MAX_WAIT_PACKETS: usize = 100;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -507,7 +517,6 @@ impl ArpWaitList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn add_to_wait_list(&self, ip: u32, origin_data: BytesMut) {
|
fn add_to_wait_list(&self, ip: u32, origin_data: BytesMut) {
|
||||||
let mut entry = self.content.entry(ip).or_insert(vec![]);
|
let mut entry = self.content.entry(ip).or_insert(vec![]);
|
||||||
if entry.len() < MAX_WAIT_PACKETS {
|
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 ahash::RandomState;
|
||||||
use arc_swap::ArcSwap;
|
use arc_swap::ArcSwap;
|
||||||
use dashmap::{DashMap};
|
use dashmap::DashMap;
|
||||||
use ipnet::Ipv4Net;
|
use ipnet::Ipv4Net;
|
||||||
use sdlan_sn_rs::utils::{Result, SDLanError};
|
use sdlan_sn_rs::utils::{Result, SDLanError};
|
||||||
|
|
||||||
use tokio::{io::ReadBuf, sync::oneshot::{Receiver, Sender, channel}};
|
use tokio::{
|
||||||
use tracing::{debug, error};
|
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)]
|
#[derive(Debug)]
|
||||||
pub struct RouteInfo {
|
pub struct RouteInfo {
|
||||||
@ -51,6 +68,7 @@ impl RouteTable2 {
|
|||||||
if net.addr().to_bits() == 0 {
|
if net.addr().to_bits() == 0 {
|
||||||
// default gateway
|
// default gateway
|
||||||
self.default_gw.store(Arc::new(Some(gw.clone())));
|
self.default_gw.store(Arc::new(Some(gw.clone())));
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
if route.value().load(Ordering::Relaxed) {
|
if route.value().load(Ordering::Relaxed) {
|
||||||
if let Err(e) = del_route(net, gw) {
|
if let Err(e) = del_route(net, gw) {
|
||||||
@ -62,8 +80,11 @@ impl RouteTable2 {
|
|||||||
self.route_table.clear();
|
self.route_table.clear();
|
||||||
|
|
||||||
for route in routes {
|
for route in routes {
|
||||||
self.cache_table.insert((route.net, route.gw), AtomicBool::new(false));
|
self.cache_table
|
||||||
self.route_table.insert(route.net.addr().into(), route.net.prefix_len(), route.gw);
|
.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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -71,20 +92,17 @@ impl RouteTable2 {
|
|||||||
/// parse the route_file or route_str and add to the route table.
|
/// 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<()> {
|
pub fn parse_and_add_route(&self, route_file: &str, route_str: &str) -> Result<()> {
|
||||||
let routes = match true {
|
let routes = match true {
|
||||||
_ if route_str.len() != 0 => {
|
_ if route_str.len() != 0 => parse_route(route_str),
|
||||||
parse_route(route_str)
|
_ if route_file.len() != 0 => load_route_file(route_file),
|
||||||
}
|
_ => Ok(HashMap::new()),
|
||||||
_ if route_file.len() != 0 => {
|
|
||||||
load_route_file(route_file)
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
Ok(HashMap::new())
|
|
||||||
}
|
|
||||||
}?;
|
}?;
|
||||||
for route in routes.keys() {
|
for route in routes.keys() {
|
||||||
if self.cache_table.get(route).is_some() {
|
if self.cache_table.get(route).is_some() {
|
||||||
error!("route {} {} has been added", route.0.to_string(), route.1);
|
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();
|
self.route_table.clear();
|
||||||
|
|
||||||
for route in routes.keys() {
|
for route in routes.keys() {
|
||||||
|
debug!("got route: {} gw {}", route.0, route.1);
|
||||||
self.cache_table.insert(*route, AtomicBool::new(false));
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_system(&self) {
|
pub fn apply_system(&self, if_idx: u32) {
|
||||||
|
debug!("applying system");
|
||||||
for route in &self.cache_table {
|
for route in &self.cache_table {
|
||||||
let (net, gw) = route.key();
|
let (net, gw) = route.key();
|
||||||
|
debug!("route is {} gw {}", net, gw);
|
||||||
if !route.value().load(Ordering::Relaxed) {
|
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());
|
error!("failed to add route: {}", e.as_str());
|
||||||
|
} else {
|
||||||
|
route.value().store(true, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// should add to system
|
// should add to system
|
||||||
|
|||||||
@ -4,7 +4,7 @@ use etherparse::{Ethernet2Header, IpHeaders, NetSlice, SlicedPacket, TransportSl
|
|||||||
use ipnet::Ipv4Net;
|
use ipnet::Ipv4Net;
|
||||||
use sdlan_sn_rs::config::SDLAN_DEFAULT_TTL;
|
use sdlan_sn_rs::config::SDLAN_DEFAULT_TTL;
|
||||||
use sdlan_sn_rs::utils::{
|
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::io::{Error, ErrorKind};
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
@ -15,13 +15,14 @@ use std::sync::Arc;
|
|||||||
use tracing::{debug, error, info};
|
use tracing::{debug, error, info};
|
||||||
use wintun;
|
use wintun;
|
||||||
|
|
||||||
use crate::{caculate_crc, get_edge};
|
|
||||||
use crate::network::{
|
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::tcp::PacketType;
|
||||||
use crate::utils::mac_to_string;
|
use crate::utils::mac_to_string;
|
||||||
|
use crate::{caculate_crc, get_edge};
|
||||||
|
|
||||||
use super::device::{DeviceConfig, Mode};
|
use super::device::{DeviceConfig, Mode};
|
||||||
use super::TunTapPacketHandler;
|
use super::TunTapPacketHandler;
|
||||||
@ -34,6 +35,10 @@ pub struct Iface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Iface {
|
impl Iface {
|
||||||
|
pub fn get_if_idx(&self) -> u32 {
|
||||||
|
self.if_idx
|
||||||
|
}
|
||||||
|
|
||||||
pub fn recv(&self, buf: &mut [u8]) -> std::io::Result<usize> {
|
pub fn recv(&self, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||||
let Ok(pkt) = self.session.receive_blocking() else {
|
let Ok(pkt) = self.session.receive_blocking() else {
|
||||||
return Err(Error::new(ErrorKind::Other, "failed to receive"));
|
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) {
|
if let Err(e) = set_dns(&self.name, network_domain, &ip, self.if_idx) {
|
||||||
error!("failed to set dns: {:?}", e);
|
error!("failed to set dns: {:?}", e);
|
||||||
} else {
|
} else {
|
||||||
error!("set dns ok");
|
debug!("set dns ok");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node.route_table.apply_system(self.if_idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TunTapPacketHandler for Iface {
|
impl TunTapPacketHandler for Iface {
|
||||||
async fn handle_packet_from_net(&self, data: &[u8]) -> std::io::Result<()> {
|
async fn handle_packet_from_net(&self, data: &[u8]) -> std::io::Result<()> {
|
||||||
|
|
||||||
match Ethernet2Header::from_slice(&data) {
|
match Ethernet2Header::from_slice(&data) {
|
||||||
Ok((hdr, rest)) => {
|
Ok((hdr, rest)) => {
|
||||||
use etherparse::ether_type::ARP;
|
use etherparse::ether_type::ARP;
|
||||||
@ -247,7 +252,6 @@ impl TunTapPacketHandler for Iface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ARP_REPLY => {
|
ARP_REPLY => {
|
||||||
|
|
||||||
debug!("mac {:?} is at {:?}", arp.shwaddr, from_ip.to_be_bytes());
|
debug!("mac {:?} is at {:?}", arp.shwaddr, from_ip.to_be_bytes());
|
||||||
if dest_ip == self_ip {
|
if dest_ip == self_ip {
|
||||||
/*
|
/*
|
||||||
@ -446,10 +450,7 @@ impl TunTapPacketHandler for Iface {
|
|||||||
// Ok(())
|
// Ok(())
|
||||||
// }
|
// }
|
||||||
|
|
||||||
async fn handle_packet_from_device(
|
async fn handle_packet_from_device(&self, mut header: BytesMut) -> std::io::Result<()> {
|
||||||
&self,
|
|
||||||
mut header: BytesMut,
|
|
||||||
) -> std::io::Result<()> {
|
|
||||||
use etherparse::IpHeaders;
|
use etherparse::IpHeaders;
|
||||||
|
|
||||||
let eee = get_edge();
|
let eee = get_edge();
|
||||||
@ -467,10 +468,8 @@ impl TunTapPacketHandler for Iface {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
match net {
|
match net {
|
||||||
NetSlice::Ipv4(ipv4) => {
|
NetSlice::Ipv4(ipv4) => {
|
||||||
|
|
||||||
let dstip = u32::from_be_bytes(ipv4.header().destination());
|
let dstip = u32::from_be_bytes(ipv4.header().destination());
|
||||||
// let dstip = u32::from_be_bytes(ipv4hdr.0.destination);
|
// let dstip = u32::from_be_bytes(ipv4hdr.0.destination);
|
||||||
debug!("packet dst ip: {:?}", ip_to_string(&dstip));
|
debug!("packet dst ip: {:?}", ip_to_string(&dstip));
|
||||||
@ -479,7 +478,9 @@ impl TunTapPacketHandler for Iface {
|
|||||||
debug!("packet src ip: {:?}", ip_to_string(&src));
|
debug!("packet src ip: {:?}", ip_to_string(&src));
|
||||||
// packet should be sent to dev
|
// packet should be sent to dev
|
||||||
debug!("got {} bytes from tun", data.len());
|
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");
|
info!("dropping routed packet");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@ -498,14 +499,19 @@ impl TunTapPacketHandler for Iface {
|
|||||||
// should do the dns request
|
// should do the dns request
|
||||||
// println!("request for dns");
|
// 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()
|
// edge.udp_sock_for_dns.send_to()
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_other => {
|
_other => {}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match eee.arp_table.get(dstip) {
|
match eee.arp_table.get(dstip) {
|
||||||
@ -522,7 +528,6 @@ impl TunTapPacketHandler for Iface {
|
|||||||
let crc = caculate_crc(&data);
|
let crc = caculate_crc(&data);
|
||||||
header.unsplit(data);
|
header.unsplit(data);
|
||||||
|
|
||||||
|
|
||||||
// packet.extend_from_slice(ðerheader.to_bytes()[..]);
|
// packet.extend_from_slice(ðerheader.to_bytes()[..]);
|
||||||
// packet.extend_from_slice(&data);
|
// packet.extend_from_slice(&data);
|
||||||
header.extend_from_slice(&crc.to_be_bytes());
|
header.extend_from_slice(&crc.to_be_bytes());
|
||||||
@ -554,38 +559,42 @@ impl TunTapPacketHandler for Iface {
|
|||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
header.unsplit(data);
|
header.unsplit(data);
|
||||||
eee.arp_table.add_to_arp_wait_list(dstip, header);
|
|
||||||
debug!(
|
debug!(
|
||||||
"find ip: {:?} => {:?}",
|
"find ip: {:?} => {:?}",
|
||||||
src.to_be_bytes(),
|
src.to_be_bytes(),
|
||||||
dstip.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;
|
// let _ = eee.send_arp_request(dstip, dstip).await;
|
||||||
|
|
||||||
if eee.device_config.contains(&Ipv4Addr::from_bits(dstip)) {
|
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;
|
let _ = eee.send_arp_request(dstip, dstip).await;
|
||||||
} else {
|
} else {
|
||||||
|
debug!("try to lookup ip: {}", ip_to_string(&dstip));
|
||||||
if let Some((_, real_ip)) = eee.route_table.lookup(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 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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
async fn handle_packet_from_device(
|
async fn handle_packet_from_device(
|
||||||
&self,
|
&self,
|
||||||
@ -717,7 +726,9 @@ fn create_wintun(path: &str, name: &str) -> Iface {
|
|||||||
Err(_e) => wintun::Adapter::create(&wt, name, "Example", None)
|
Err(_e) => wintun::Adapter::create(&wt, name, "Example", None)
|
||||||
.expect("failed to create tun adapter"),
|
.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);
|
// println!("idx = {}", idx);
|
||||||
let session = Arc::new(adapter.start_session(wintun::MAX_RING_CAPACITY).unwrap());
|
let session = Arc::new(adapter.start_session(wintun::MAX_RING_CAPACITY).unwrap());
|
||||||
Iface {
|
Iface {
|
||||||
@ -769,11 +780,10 @@ pub fn set_dns(name: &str, _network_domain: &str, gw: &str, ifidx: u32) -> std::
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn restore_dns() {
|
pub fn restore_dns() {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn del_route(net: &Ipv4Net, gw: &Ipv4Addr) -> Result<()> {
|
pub fn del_route(net: &Ipv4Net, gw: &Ipv4Addr) -> Result<()> {
|
||||||
|
error!("deleting route: {} gw {}", net, gw);
|
||||||
let mask = net.netmask().to_string();
|
let mask = net.netmask().to_string();
|
||||||
let network = net.network().to_string();
|
let network = net.network().to_string();
|
||||||
let res = Command::new("route")
|
let res = Command::new("route")
|
||||||
@ -783,32 +793,54 @@ pub fn del_route(net: &Ipv4Net, gw: &Ipv4Addr) -> Result<()> {
|
|||||||
.arg(gw.to_string())
|
.arg(gw.to_string())
|
||||||
.output()?;
|
.output()?;
|
||||||
Ok(())
|
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 mask = net.netmask().to_string();
|
||||||
let network = net.network().to_string();
|
let network = net.network().to_string();
|
||||||
let res = Command::new("route")
|
match Command::new("route")
|
||||||
.arg("add")
|
.arg("add")
|
||||||
.arg(network)
|
.arg(network)
|
||||||
|
.arg("MASK")
|
||||||
.arg(mask)
|
.arg(mask)
|
||||||
.arg(gw.to_string())
|
.arg(gw.to_string())
|
||||||
.output()?;
|
.arg("if")
|
||||||
Ok(())
|
.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) {
|
pub async fn arp_reply_arrived(edge: &Node, data: SdlArpResponse) {
|
||||||
debug!("got arp response: {:?}", data);
|
debug!("got arp response: {:?}", data);
|
||||||
if data.target_mac.len() != 6 {
|
if data.target_mac.len() != 6 {
|
||||||
// invalid target_mac
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let ip = data.target_ip;
|
let ip = data.origin_ip;
|
||||||
let mac = data.target_mac.try_into().unwrap();
|
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;
|
edge.arp_table.arp_arrived(ip, mac).await;
|
||||||
}
|
}
|
||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
|
|
||||||
use bytes::{Bytes, BytesMut};
|
use bytes::{Bytes, BytesMut};
|
||||||
@ -6,7 +5,7 @@ use dashmap::DashMap;
|
|||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use sdlan_sn_rs::{
|
use sdlan_sn_rs::{
|
||||||
config::SDLAN_DEFAULT_TTL,
|
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};
|
use tracing::{debug, warn};
|
||||||
@ -14,8 +13,8 @@ use tracing::{debug, warn};
|
|||||||
use tracing::error;
|
use tracing::error;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
network::{Node, RouteInfo, form_ethernet_packet, send_packet_to_net},
|
network::{form_ethernet_packet, send_packet_to_net, Node, RouteInfo},
|
||||||
pb::{SdlData, encode_to_udp_message},
|
pb::{encode_to_udp_message, SdlData},
|
||||||
tcp::PacketType,
|
tcp::PacketType,
|
||||||
utils::mac_to_string,
|
utils::mac_to_string,
|
||||||
};
|
};
|
||||||
@ -31,11 +30,10 @@ pub trait TunTapPacketHandler {
|
|||||||
async fn handle_packet_from_device(&self, data: BytesMut) -> 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();
|
let eee = get_edge();
|
||||||
eee.route_table.clear_and_add_routes(routes)?;
|
eee.route_table.clear_and_add_routes(routes)?;
|
||||||
eee.route_table.apply_system();
|
eee.route_table.apply_system(eee.device.get_if_idx());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,7 +147,6 @@ pub fn get_dns_gateway(edge: &Node, payload: &[u8]) -> Option<String> {
|
|||||||
Ok(p) => p,
|
Ok(p) => p,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
let mut target_dns: &str = "";
|
let mut target_dns: &str = "";
|
||||||
if !dns_packet.has_flags(simple_dns::PacketFlag::RESPONSE) && !dns_packet.questions.is_empty() {
|
if !dns_packet.has_flags(simple_dns::PacketFlag::RESPONSE) && !dns_packet.questions.is_empty() {
|
||||||
let question = &dns_packet.questions[0];
|
let question = &dns_packet.questions[0];
|
||||||
@ -168,27 +165,55 @@ pub fn get_dns_gateway(edge: &Node, payload: &[u8]) -> Option<String> {
|
|||||||
return None;
|
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) {
|
match simple_dns::Packet::parse(layer7) {
|
||||||
Ok(mut dns) => {
|
Ok(mut dns) => {
|
||||||
if !dns.has_flags(simple_dns::PacketFlag::RESPONSE) && !dns.questions.is_empty() {
|
if !dns.has_flags(simple_dns::PacketFlag::RESPONSE) && !dns.questions.is_empty() {
|
||||||
let question = &dns.questions[0];
|
let question = &dns.questions[0];
|
||||||
let qname = question.qname.to_string();
|
let qname = question.qname.to_string();
|
||||||
if qname.ends_with(edge.network_domain.load().as_str()) {
|
if qname.ends_with(edge.network_domain.load().as_str()) {
|
||||||
warn!("question 15353 for {} from {}:{} with transaction_id = {}",
|
warn!(
|
||||||
qname, ip_to_string(&source_ip), source_port, dns.id());
|
"question 15353 for {} from {}:{} with transaction_id = {}",
|
||||||
|
qname,
|
||||||
|
ip_to_string(&source_ip),
|
||||||
|
source_port,
|
||||||
|
dns.id()
|
||||||
|
);
|
||||||
// should send to our socket
|
// 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);
|
error!("failed to send request to 15353: {}", e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let origin_transaction_id = dns.id();
|
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);
|
dns.set_id(transaction_id);
|
||||||
warn!("question 223.5.5.5 for {} from {}:{} with transaction_id = {}",
|
warn!(
|
||||||
qname, ip_to_string(&source_ip), source_port, dns.id());
|
"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 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);
|
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 futures_util::pin_mut;
|
||||||
use prost::Message;
|
use prost::Message;
|
||||||
use quinn::SendStream;
|
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 sdlan_sn_rs::{
|
||||||
use tokio::{sync::mpsc::{Receiver, Sender, channel}, time::sleep};
|
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 tokio_util::sync::CancellationToken;
|
||||||
use tracing::{debug, error, warn, info};
|
use tracing::{debug, error, info, warn};
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
use crate::network::{set_allow_routing, set_disallow_routing};
|
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();
|
static GLOBAL_QUIC_HANDLE: OnceLock<ReadWriterHandle> = OnceLock::new();
|
||||||
|
|
||||||
@ -73,7 +103,7 @@ impl ReadWriterHandle {
|
|||||||
to_tcp,
|
to_tcp,
|
||||||
// on_connected,
|
// on_connected,
|
||||||
// on_disconnected,
|
// on_disconnected,
|
||||||
start_stop_chan
|
start_stop_chan,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
});
|
});
|
||||||
@ -106,7 +136,6 @@ pub fn get_quic_write_conn() -> &'static ReadWriterHandle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async fn handle_tcp_message(msg: SdlanTcp) {
|
async fn handle_tcp_message(msg: SdlanTcp) {
|
||||||
let edge = get_edge();
|
let edge = get_edge();
|
||||||
|
|
||||||
@ -138,18 +167,20 @@ async fn handle_tcp_message(msg: SdlanTcp) {
|
|||||||
|
|
||||||
match ack.algorithm.to_ascii_lowercase().as_str() {
|
match ack.algorithm.to_ascii_lowercase().as_str() {
|
||||||
"chacha20" => {
|
"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));
|
// *edge.encryptor.write().unwrap() = MyEncryptor::ChaChao20(Chacha20Encryptor::new(key, ack.region_id));
|
||||||
}
|
}
|
||||||
"aes" => {
|
"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));
|
// *edge.encryptor.write().unwrap() = MyEncryptor::Aes(AesEncryptor::new(key));
|
||||||
}
|
}
|
||||||
_other => {
|
_other => {}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
let Some(dev) = ack.dev_addr else {
|
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.network_id.store(dev.network_id, Ordering::Relaxed);
|
||||||
*/
|
*/
|
||||||
// edge.device.reload_config(&edge.device_config, &dev.network_domain);
|
// 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);
|
edge.set_authorized(true);
|
||||||
|
|
||||||
@ -205,7 +237,6 @@ async fn handle_tcp_message(msg: SdlanTcp) {
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
arp_reply_arrived(edge, res).await;
|
arp_reply_arrived(edge, res).await;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -225,10 +256,7 @@ async fn handle_tcp_message(msg: SdlanTcp) {
|
|||||||
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;
|
start += 3;
|
||||||
|
|
||||||
infos.push(RuleFromServer{
|
infos.push(RuleFromServer { proto, port });
|
||||||
proto,
|
|
||||||
port,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
edge.rule_cache.set_identity_cache(identity, infos);
|
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]) {
|
async fn handle_tcp_command(edge: &Node, cmdprotobuf: &[u8]) {
|
||||||
let Ok(cmd) = SdlCommand::decode(cmdprotobuf) else {
|
let Ok(cmd) = SdlCommand::decode(cmdprotobuf) else {
|
||||||
error!("failed to decode SdlCommand");
|
error!("failed to decode SdlCommand");
|
||||||
@ -362,7 +389,10 @@ async fn handle_tcp_command(edge: &Node, cmdprotobuf: &[u8]) {
|
|||||||
// std::process::exit(0);
|
// std::process::exit(0);
|
||||||
if node.action == 0 {
|
if node.action == 0 {
|
||||||
// stop
|
// 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();
|
let mut config = load_configuration();
|
||||||
config.allow_routing = Some(false);
|
config.allow_routing = Some(false);
|
||||||
let _ = store_configuration(&config);
|
let _ = store_configuration(&config);
|
||||||
@ -396,7 +426,6 @@ async fn handle_tcp_command(edge: &Node, cmdprotobuf: &[u8]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_tcp_event(edge: &'static Node, eventprotobuf: &[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);
|
debug!("unhandled event {:?}", other);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn init_quic_conn(
|
pub fn init_quic_conn(
|
||||||
cancel: CancellationToken,
|
cancel: CancellationToken,
|
||||||
addr: &str,
|
addr: &str,
|
||||||
@ -577,7 +604,10 @@ impl ReadWriteActor {
|
|||||||
|
|
||||||
debug!("try connecting to {}", self.domain);
|
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,
|
Ok(conn) => conn,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("failed to connect: {}", e);
|
error!("failed to connect: {}", e);
|
||||||
@ -589,7 +619,6 @@ impl ReadWriteActor {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -764,11 +793,8 @@ async fn on_connected_callback(local_ip: Option<IpAddr>, stream: &mut SendStream
|
|||||||
|
|
||||||
// debug!("send register super: {:?}", register_super);
|
// debug!("send register super: {:?}", register_super);
|
||||||
// let packet_id = edge.get_next_packet_id();
|
// let packet_id = edge.get_next_packet_id();
|
||||||
let data = encode_to_tcp_message(
|
let data =
|
||||||
Some(register_super),
|
encode_to_tcp_message(Some(register_super), PacketType::RegisterSuper as u8).unwrap();
|
||||||
PacketType::RegisterSuper as u8,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
if let Err(e) = stream.write(&data).await {
|
if let Err(e) = stream.write(&data).await {
|
||||||
error!("failed to write to tcp: {}", e.to_string());
|
error!("failed to write to tcp: {}", e.to_string());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,7 @@ struct IpTrie {
|
|||||||
impl IpTrie {
|
impl IpTrie {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
root: TrieNode::default()
|
root: TrieNode::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,9 +30,8 @@ impl IpTrie {
|
|||||||
for i in 0..prefix_len {
|
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()));
|
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.prefix_len = prefix_len;
|
||||||
node.nexthop = Some(nexthop);
|
node.nexthop = Some(nexthop);
|
||||||
}
|
}
|
||||||
@ -47,6 +46,7 @@ impl IpTrie {
|
|||||||
best = Some((node.prefix_len, node.nexthop.unwrap()));
|
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] {
|
match &node.child[bit] {
|
||||||
Some(child) => {
|
Some(child) => {
|
||||||
node = 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 {
|
pub struct RouteTableTrie {
|
||||||
trie: ArcSwap<IpTrie>,
|
trie: ArcSwap<IpTrie>,
|
||||||
}
|
}
|
||||||
@ -70,7 +115,7 @@ pub struct RouteTableTrie {
|
|||||||
impl RouteTableTrie {
|
impl RouteTableTrie {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
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