From 7e7a9ca2e63351c7fe1068e0f94c8d47d42c38e2 Mon Sep 17 00:00:00 2001 From: asxalex Date: Mon, 20 Apr 2026 16:30:54 +0800 Subject: [PATCH] route add --- Cargo.toml | 2 +- src/bin/punchnet/main.rs | 201 +++++++++++--------- src/network/arp.rs | 39 ++-- src/network/route.rs | 81 +++++--- src/network/tun_win.rs | 372 ++++++++++++++++++++----------------- src/network/tuntap.rs | 63 +++++-- src/tcp/quic.rs | 116 +++++++----- src/utils/system_action.rs | 63 ++++++- 8 files changed, 568 insertions(+), 369 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a872477..e2b6763 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -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"} diff --git a/src/bin/punchnet/main.rs b/src/bin/punchnet/main.rs index 9c02d07..c97052b 100755 --- a/src/bin/punchnet/main.rs +++ b/src/bin/punchnet/main.rs @@ -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"; @@ -96,11 +95,11 @@ fn parse_login_result(res: Result) -> LoginData { }; if let Err(_e) = set_access_token(&CachedLoginInfo { - access_token: data.access_token.clone(), - username: data.username.clone(), - user_type: data.user_type.clone(), - audit: data.audit, - network_id: data.network_id, + access_token: data.access_token.clone(), + username: data.username.clone(), + user_type: data.user_type.clone(), + audit: data.audit, + network_id: data.network_id, network_name: data.network_name.clone(), network_domain: data.network_domain.clone(), }) { @@ -113,7 +112,7 @@ fn parse_login_result(res: Result) -> LoginData { async fn daemonize_me( allow_routing: bool, - connect_info: ConnectData, + connect_info: ConnectData, remembered: CachedLoginInfo, client_id: String, route_file: String, @@ -148,7 +147,7 @@ async fn daemonize_me( Some(cmd.hostname) }; */ - /* + /* let hostname = if cmd.hostname.len() == 0 { None } else { @@ -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,17 +223,20 @@ 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( - remembered.access_token.clone(), - // String::new(), - remembered.network_id, - &remembered.network_domain, - ip_net, - connect_info.mask_len, - connect_info.identity_id, - // 0, - None, - ).await { + if let Err(e) = edge + .start_without_feedback( + remembered.access_token.clone(), + // String::new(), + remembered.network_id, + &remembered.network_domain, + ip_net, + connect_info.mask_len, + connect_info.identity_id, + // 0, + None, + ) + .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::Stop => { - - } + ExitNodeCmd::Start(info) => {} + 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,49 +436,71 @@ 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 { - let remembered_token = get_access_token(); - if remembered_token.is_none() { - eprintln!("not logged in, should login with user/pass or token first"); - process::exit(-2); - } - let remembered = remembered_token.unwrap(); - let connect_info = parse_connect_result( - connect(TEST_PREFIX, &client_id, &remembered.access_token).await + 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"); + process::exit(-2); + } + let remembered = remembered_token.unwrap(); + let connect_info = parse_connect_result( + 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 { + 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, ); - 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 - ); - remembered_token = Some(CachedLoginInfo{ - access_token: data.access_token, - username: data.username, - user_type: data.user_type, - audit: data.audit, - network_id: data.network_id, - network_name: data.network_name, - network_domain: data.network_domain, - }); - } + remembered_token = Some(CachedLoginInfo { + access_token: data.access_token, + username: data.username, + user_type: data.user_type, + audit: data.audit, + network_id: data.network_id, + network_name: data.network_name, + network_domain: data.network_domain, + }); + } - let remembered = remembered_token.unwrap(); + let remembered = remembered_token.unwrap(); - let connect_info = parse_connect_result( - 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; - }) - } + let connect_info = parse_connect_result( + 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; + }), other => { eprintln!("should not comes here"); diff --git a/src/network/arp.rs b/src/network/arp.rs index eec98de..9d7de48 100755 --- a/src/network/arp.rs +++ b/src/network/arp.rs @@ -2,7 +2,10 @@ use std::{ collections::HashMap, - sync::{Arc, atomic::{AtomicU8, Ordering}}, + sync::{ + atomic::{AtomicU8, Ordering}, + Arc, + }, time::{Duration, Instant}, }; @@ -11,17 +14,27 @@ 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 = OnceCell::new(); pub fn init_arp() { init_arp_wait_list(); @@ -164,8 +177,6 @@ impl ArpEntry { } */ - - pub struct ArpTable { entries: Arc>, 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); } @@ -219,7 +231,7 @@ impl ArpTable { } } -/* +/* pub struct ArpInfo { // host_ip: AtomicU32, // ip representation of mask @@ -484,7 +496,6 @@ pub fn generate_arp_request(srcmac: [u8; 6], dstip: u32, srcip: u32) -> Vec 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 { @@ -547,8 +556,8 @@ impl ArpWaitList { let pkt_size = packet.len(); let Ok(encrypted) = edge.encryptor.load().encrypt(&packet) else { - // let Ok(encrypted) = edge.encryptor.read().unwrap().encrypt(&packet) else { - // let Ok(encrypted) = aes_encrypt(&encrypt_key, &packet) else { + // let Ok(encrypted) = edge.encryptor.read().unwrap().encrypt(&packet) else { + // let Ok(encrypted) = aes_encrypt(&encrypt_key, &packet) else { error!("failed to encrypt packet request"); return; }; @@ -567,4 +576,4 @@ impl ArpWaitList { send_packet_to_net(edge, mac, &msg, pkt_size as u64).await; } } -} \ No newline at end of file +} diff --git a/src/network/route.rs b/src/network/route.rs index b4570ec..e00551f 100755 --- a/src/network/route.rs +++ b/src/network/route.rs @@ -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,21 +118,38 @@ 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 + // should add to system } } } @@ -125,7 +160,7 @@ impl RouteTable2 { pub fn load_route_file(filename: &str) -> Result> { let mut result = HashMap::new(); let fp = fs::File::open(filename)?; - + let buf = BufReader::new(fp); for line in buf.lines() { let line = line?; @@ -150,7 +185,7 @@ pub fn parse_a_route(route: &str) -> Result<(Ipv4Net, Ipv4Addr)> { }; let cidr = route_info[0]; - let Ok(net )= cidr.parse::() else { + let Ok(net) = cidr.parse::() else { error!("failed to parse cidr: {}, skipping", cidr); return Err(SDLanError::IOError("failed to parse cidr".to_string())); }; diff --git a/src/network/tun_win.rs b/src/network/tun_win.rs index d9a8690..c35f9b6 100755 --- a/src/network/tun_win.rs +++ b/src/network/tun_win.rs @@ -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 { 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; @@ -192,7 +197,7 @@ impl TunTapPacketHandler for Iface { edge.arp_table.set(from_ip, arp.shwaddr); - /* + /* use crate::network::{ARP_REPLY, ArpRequestInfo, send_arp_request}; send_arp_request(ArpRequestInfo::Set { @@ -247,10 +252,9 @@ impl TunTapPacketHandler for Iface { } } ARP_REPLY => { - debug!("mac {:?} is at {:?}", arp.shwaddr, from_ip.to_be_bytes()); if dest_ip == self_ip { - /* + /* use crate::network::{ArpRequestInfo, arp_arrived, send_arp_request}; send_arp_request(ArpRequestInfo::Set { @@ -316,140 +320,137 @@ impl TunTapPacketHandler for Iface { } // async fn handle_packet_from_device( - // &self, - // data: BytesMut, - // // encrypt_key: &[u8], + // &self, + // data: BytesMut, + // // encrypt_key: &[u8], // ) -> std::io::Result<()> { - // let eee = get_edge(); + // let eee = get_edge(); - // let src_mac = eee.device_config.get_mac(); + // let src_mac = eee.device_config.get_mac(); - // match IpHeaders::from_slice(&data) { - // Ok((iphdr, _payload)) => { - // let Some(ipv4hdr) = iphdr.ipv4() else { - // debug!("ipv6 packet ignored"); - // return Ok(()); - // }; - // let dstip = u32::from_be_bytes(ipv4hdr.0.destination); - // debug!("packet dst ip: {:?}", ipv4hdr.0.destination); - // let src = u32::from_be_bytes(ipv4hdr.0.source); - // debug!("packet src ip: {:?}", ipv4hdr.0.source); - // // 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()) { - // info!("dropping routed packet"); - // return Ok(()); - // } - // if !eee.is_authorized() { - // debug!("drop tun packet due to not authed"); - // return Ok(()); - // } - // if dstip == DNS_IP { - // // println!("request for dns"); - // let addr = format!("{}:15353", eee.server_ip); - // // println!("send dns to {}", addr); - // if let Err(e) = eee.udp_sock_for_dns.send_to(&data, &addr).await { - // error!("failed to send request to 15353: {}", e); - // } - // return Ok(()); - // } - // match send_arp_request(ArpRequestInfo::Lookup { ip: dstip }).await { - // ArpResponse::LookupResp { - // mac, - // ip, - // do_arp_request, - // } => { - // if do_arp_request { - // add_to_arp_wait_list(dstip, data); + // match IpHeaders::from_slice(&data) { + // Ok((iphdr, _payload)) => { + // let Some(ipv4hdr) = iphdr.ipv4() else { + // debug!("ipv6 packet ignored"); + // return Ok(()); + // }; + // let dstip = u32::from_be_bytes(ipv4hdr.0.destination); + // debug!("packet dst ip: {:?}", ipv4hdr.0.destination); + // let src = u32::from_be_bytes(ipv4hdr.0.source); + // debug!("packet src ip: {:?}", ipv4hdr.0.source); + // // 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()) { + // info!("dropping routed packet"); + // return Ok(()); + // } + // if !eee.is_authorized() { + // debug!("drop tun packet due to not authed"); + // return Ok(()); + // } + // if dstip == DNS_IP { + // // println!("request for dns"); + // let addr = format!("{}:15353", eee.server_ip); + // // println!("send dns to {}", addr); + // if let Err(e) = eee.udp_sock_for_dns.send_to(&data, &addr).await { + // error!("failed to send request to 15353: {}", e); + // } + // return Ok(()); + // } + // match send_arp_request(ArpRequestInfo::Lookup { ip: dstip }).await { + // ArpResponse::LookupResp { + // mac, + // ip, + // do_arp_request, + // } => { + // if do_arp_request { + // add_to_arp_wait_list(dstip, data); - // info!( - // "find ip: {:?} => {:?}", - // src.to_be_bytes(), - // dstip.to_be_bytes() - // ); - // let arp_msg = - // generate_arp_request(src_mac, ip, eee.device_config.get_ip()); - - // let Ok(encrypted) = eee.encryptor.load().encrypt(&arp_msg) else { - // // let Ok(encrypted) = aes_encrypt(&encrypt_key, &arp_msg) else { - // error!("failed to encrypt arp request"); - // return Ok(()); - // }; - // // println!("arp_msg: {:?}", arp_msg); - // let data = SdlData { - // network_id: eee.network_id.load(Ordering::Relaxed), - // src_mac: Vec::from(src_mac), - // dst_mac: Vec::from([0xff; 6]), - // is_p2p: true, - // ttl: SDLAN_DEFAULT_TTL as u32, - // data: Bytes::from(encrypted), + // info!( + // "find ip: {:?} => {:?}", + // src.to_be_bytes(), + // dstip.to_be_bytes() + // ); + // let arp_msg = + // generate_arp_request(src_mac, ip, eee.device_config.get_ip()); - // session_token: eee.session_token.get(), - // identity_id: eee.identity_id.load(), - // }; - // let data = - // encode_to_udp_message(Some(data), PacketType::Data as u8).unwrap(); - // debug!("sending arp"); - // // let data = marshal_message(&data); - // send_packet_to_net(eee, BROADCAST_MAC, &data, arp_msg.len() as u64) - // .await; - // // edge.sock.send(data).await; - // // println!("should send arp"); - // return Ok(()); - // } + // let Ok(encrypted) = eee.encryptor.load().encrypt(&arp_msg) else { + // // let Ok(encrypted) = aes_encrypt(&encrypt_key, &arp_msg) else { + // error!("failed to encrypt arp request"); + // return Ok(()); + // }; + // // println!("arp_msg: {:?}", arp_msg); + // let data = SdlData { + // network_id: eee.network_id.load(Ordering::Relaxed), + // src_mac: Vec::from(src_mac), + // dst_mac: Vec::from([0xff; 6]), + // is_p2p: true, + // ttl: SDLAN_DEFAULT_TTL as u32, + // data: Bytes::from(encrypted), - // let packet = form_ethernet_packet(src_mac, mac, &data); - // // prepend the ether header - // /* - // let mut etherheader = Ethernet2Header::default(); - // etherheader.destination = mac; - // etherheader.ether_type = etherparse::EtherType::IPV4; - // etherheader.source = src_mac; - // let mut packet = Vec::with_capacity(14 + data.len() + 4); - // packet.extend_from_slice(ðerheader.to_bytes()[..]); - // packet.extend_from_slice(&data); - // */ - // // let crc = CRC_HASH.checksum(&packet); - // // packet.extend_from_slice(&crc.to_be_bytes()); - - // let pkt_size = packet.len(); - // // println!("sending data with mac"); - - // // let Ok(encrypted) = aes_encrypt(&encrypt_key, &packet) else { - // let Ok(encrypted) = eee.encryptor.load().encrypt(&packet) else { - // error!("failed to encrypt packet request"); - // return Ok(()); - // }; - // let data = SdlData { - // is_p2p: true, - // network_id: eee.network_id.load(Ordering::Relaxed), - // ttl: SDLAN_DEFAULT_TTL as u32, - // src_mac: Vec::from(src_mac), - // dst_mac: Vec::from(mac), - // data: Bytes::from(encrypted), - // session_token: eee.session_token.get(), - // identity_id: eee.identity_id.load(), - // }; - // let msg = - // encode_to_udp_message(Some(data), PacketType::Data as u8).unwrap(); - // let size = msg.len(); - // send_packet_to_net(eee, mac, &msg, pkt_size as u64).await; - // // let dstip = u32::from_be_bytes(ipv4hdr.0.destination); - // } - // _ => {} - // } - // } - // Err(e) => { - // error!("failed to parse ip packet: {}", e.to_string()); - // } - // } - // Ok(()) + // session_token: eee.session_token.get(), + // identity_id: eee.identity_id.load(), + // }; + // let data = + // encode_to_udp_message(Some(data), PacketType::Data as u8).unwrap(); + // debug!("sending arp"); + // // let data = marshal_message(&data); + // send_packet_to_net(eee, BROADCAST_MAC, &data, arp_msg.len() as u64) + // .await; + // // edge.sock.send(data).await; + // // println!("should send arp"); + // return Ok(()); // } - async fn handle_packet_from_device( - &self, - mut header: BytesMut, - ) -> std::io::Result<()> { + // let packet = form_ethernet_packet(src_mac, mac, &data); + // // prepend the ether header + // /* + // let mut etherheader = Ethernet2Header::default(); + // etherheader.destination = mac; + // etherheader.ether_type = etherparse::EtherType::IPV4; + // etherheader.source = src_mac; + // let mut packet = Vec::with_capacity(14 + data.len() + 4); + // packet.extend_from_slice(ðerheader.to_bytes()[..]); + // packet.extend_from_slice(&data); + // */ + // // let crc = CRC_HASH.checksum(&packet); + // // packet.extend_from_slice(&crc.to_be_bytes()); + + // let pkt_size = packet.len(); + // // println!("sending data with mac"); + + // // let Ok(encrypted) = aes_encrypt(&encrypt_key, &packet) else { + // let Ok(encrypted) = eee.encryptor.load().encrypt(&packet) else { + // error!("failed to encrypt packet request"); + // return Ok(()); + // }; + // let data = SdlData { + // is_p2p: true, + // network_id: eee.network_id.load(Ordering::Relaxed), + // ttl: SDLAN_DEFAULT_TTL as u32, + // src_mac: Vec::from(src_mac), + // dst_mac: Vec::from(mac), + // data: Bytes::from(encrypted), + // session_token: eee.session_token.get(), + // identity_id: eee.identity_id.load(), + // }; + // let msg = + // encode_to_udp_message(Some(data), PacketType::Data as u8).unwrap(); + // let size = msg.len(); + // send_packet_to_net(eee, mac, &msg, pkt_size as u64).await; + // // let dstip = u32::from_be_bytes(ipv4hdr.0.destination); + // } + // _ => {} + // } + // } + // Err(e) => { + // error!("failed to parse ip packet: {}", e.to_string()); + // } + // } + // Ok(()) + // } + + 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,39 +559,43 @@ 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)) { - let _ = eee.send_arp_request(dstip, dstip).await; + 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, mut header: BytesMut, @@ -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; -} \ No newline at end of file +} diff --git a/src/network/tuntap.rs b/src/network/tuntap.rs index 13de57c..8eef9ff 100755 --- a/src/network/tuntap.rs +++ b/src/network/tuntap.rs @@ -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,22 +23,21 @@ 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) -> Result<()>{ +pub fn set_route_from_net(routes: Vec) -> 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(()) } -/* +/* static ARP_WAIT_LIST: OnceCell = OnceCell::new(); pub fn init_arp_wait_list() { @@ -149,7 +147,6 @@ pub fn get_dns_gateway(edge: &Node, payload: &[u8]) -> Option { 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 { 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); } } @@ -200,4 +225,4 @@ pub async fn parse_dns_payload(edge: &Node, layer7: &[u8], layer3: &[u8], source error!("failed to parse dns packet"); } } -} \ No newline at end of file +} diff --git a/src/tcp/quic.rs b/src/tcp/quic.rs index 7e79e47..c3dd878 100644 --- a/src/tcp/quic.rs +++ b/src/tcp/quic.rs @@ -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 = OnceLock::new(); @@ -69,11 +99,11 @@ impl ReadWriterHandle { tokio::spawn(async move { actor .run( - true, - to_tcp, - // on_connected, - // on_disconnected, - start_stop_chan + true, + to_tcp, + // on_connected, + // on_disconnected, + 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,20 +167,22 @@ 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 { error!("no dev_addr is specified"); return; @@ -164,7 +195,7 @@ async fn handle_tcp_message(msg: SdlanTcp) { debug!("assigned ip: {}", ip); // let hostname = edge.hostname.read().unwrap().clone(); // println!("network is: {}.{}", hostname, dev.network_domain); - /* + /* edge.device_config .ip .net_addr @@ -180,7 +211,7 @@ async fn handle_tcp_message(msg: SdlanTcp) { }; */ // *edge.device_config.mac.write().unwrap() = mac; - /* + /* edge.device_config .ip .net_bit_len @@ -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); @@ -238,7 +266,7 @@ async fn handle_tcp_message(msg: SdlanTcp) { let Ok(_nak) = SdlRegisterSuperNak::decode(&msg.current_packet[..]) else { error!("failed to decode REGISTER_SUPER_NAK"); - /* + /* edge.send_register_super_feedback( msg._packet_id, RegisterSuperFeedback { @@ -319,7 +347,7 @@ async fn handle_tcp_message(msg: SdlanTcp) { error!("malformed COMMAND received"); return; } - handle_tcp_command(edge, &msg.current_packet[..]).await; + handle_tcp_command(edge, &msg.current_packet[..]).await; } PacketType::Event => { if msg.current_packet.len() < 1 { @@ -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>, ipv6_network_restarter: Option>, ) - // T2: Fn(SdlanTcp) -> F + Send + 'static, - // F: Future + Send, +// T2: Fn(SdlanTcp) -> F + Send + 'static, +// F: Future + 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,12 +793,9 @@ async fn on_connected_callback(local_ip: Option, 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()); } -} \ No newline at end of file +} diff --git a/src/utils/system_action.rs b/src/utils/system_action.rs index 8b46d97..a154bb4 100644 --- a/src/utils/system_action.rs +++ b/src/utils/system_action.rs @@ -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::().unwrap(), + format!("192.168.{}.1", i).parse::().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, } @@ -70,11 +115,11 @@ pub struct RouteTableTrie { impl RouteTableTrie { pub fn new() -> Self { Self { - trie: ArcSwap::new(Arc::new(IpTrie::default())) + trie: ArcSwap::new(Arc::new(IpTrie::default())), } } - pub fn clear(&self) { + pub fn clear(&self) { self.trie.store(Arc::new(IpTrie::default())); } @@ -90,4 +135,4 @@ impl RouteTableTrie { new_trie.insert(prefix, prefix_len, nexthop); self.trie.store(Arc::new(new_trie)); } -} \ No newline at end of file +}