linux is ok for tun and tap

This commit is contained in:
alex 2025-12-24 22:15:52 +08:00
parent 0300eb9ade
commit 2096c3faac
6 changed files with 100 additions and 16 deletions

4
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,4 @@
{
"rust-analyzer.cargo.target": null,
"rust-analyzer.cargo.features": ["tun"]
}

9
Cargo.lock generated
View File

@ -1524,11 +1524,10 @@ dependencies = [
[[package]] [[package]]
name = "num-bigint-dig" name = "num-bigint-dig"
version = "0.8.4" version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7"
dependencies = [ dependencies = [
"byteorder",
"lazy_static", "lazy_static",
"libm", "libm",
"num-integer", "num-integer",
@ -2092,9 +2091,9 @@ dependencies = [
[[package]] [[package]]
name = "rsa" name = "rsa"
version = "0.9.8" version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" checksum = "40a0376c50d0358279d9d643e4bf7b7be212f1f4ff1da9070a7b54d22ef75c88"
dependencies = [ dependencies = [
"const-oid", "const-oid",
"digest", "digest",

View File

@ -9,12 +9,14 @@ use std::{
use tracing::error; use tracing::error;
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use sdlan_sn_rs::utils::{net_bit_len_to_mask, Mac, BROADCAST_MAC, MULTICAST_MAC}; use sdlan_sn_rs::utils::{BROADCAST_MAC, MULTICAST_MAC, Mac, ip_to_string, net_bit_len_to_mask};
use tokio::sync::{ use tokio::sync::{
mpsc::{channel, Receiver, Sender}, mpsc::{channel, Receiver, Sender},
oneshot, oneshot,
}; };
use crate::network::tun::DNS_IP;
use super::{get_edge, get_route_table, init_arp_wait_list, init_route}; use super::{get_edge, get_route_table, init_arp_wait_list, init_route};
static GLOBAL_ARP: OnceCell<ArpActor> = OnceCell::new(); static GLOBAL_ARP: OnceCell<ArpActor> = OnceCell::new();
@ -168,9 +170,9 @@ pub struct ArpInfo {
} }
impl ArpInfo { impl ArpInfo {
fn lookup_ip_mac(&self, ip: u32) -> ([u8; 6], u32, bool) { fn lookup_ip_mac(&self, ip: u32) -> Option<([u8; 6], u32, bool)> {
if ip == BROADCAST_IPADDR { if ip == BROADCAST_IPADDR {
return (BROADCAST_MAC, ip, false); return Some((BROADCAST_MAC, ip, false));
} }
let edge = get_edge(); let edge = get_edge();
let netbit = edge.device_config.get_net_bit(); let netbit = edge.device_config.get_net_bit();
@ -178,7 +180,7 @@ impl ArpInfo {
let host_netmask_reverse = !host_netmask; let host_netmask_reverse = !host_netmask;
if (ip & host_netmask_reverse) == host_netmask_reverse { if (ip & host_netmask_reverse) == host_netmask_reverse {
return (BROADCAST_MAC, ip, false); return Some((BROADCAST_MAC, ip, false));
} }
let first_ip = (ip >> 24) as u8 & 0xff; let first_ip = (ip >> 24) as u8 & 0xff;
@ -187,7 +189,7 @@ impl ArpInfo {
multi[3] = (ip >> 16) as u8 & 0x7f; multi[3] = (ip >> 16) as u8 & 0x7f;
multi[4] = (ip >> 8) as u8 & 0xff; multi[4] = (ip >> 8) as u8 & 0xff;
multi[5] = (ip) as u8 & 0xff; multi[5] = (ip) as u8 & 0xff;
return (multi, ip, false); return Some((multi, ip, false));
} }
let mut target_ip = 0; let mut target_ip = 0;
@ -204,10 +206,11 @@ impl ArpInfo {
} }
} }
if target_ip == 0 { if target_ip == 0 {
panic!("target should not route to me"); error!("target should not route to me: ip = {}", ip_to_string(&ip));
return None;
} }
if let Some(entry) = self.entry.get(&target_ip) { if let Some(entry) = self.entry.get(&target_ip) {
return (entry.hw_addr, target_ip, false); return Some((entry.hw_addr, target_ip, false));
} }
/* /*
for i in 0..ARP_TABLE_SIZE { for i in 0..ARP_TABLE_SIZE {
@ -217,7 +220,7 @@ impl ArpInfo {
} }
} }
*/ */
return (BROADCAST_MAC, target_ip, true); return Some((BROADCAST_MAC, target_ip, true));
} }
fn set_arp(&mut self, mac: [u8; 6], ip: u32) { fn set_arp(&mut self, mac: [u8; 6], ip: u32) {
@ -352,7 +355,9 @@ async fn loop_arp_info(mut rx: Receiver<ArpRequest>) {
if let Some(d) = data { if let Some(d) = data {
match d.req { match d.req {
ArpRequestInfo::Lookup{ip} => { ArpRequestInfo::Lookup{ip} => {
let mac = arp.lookup_ip_mac(ip); let Some(mac) = arp.lookup_ip_mac(ip) else {
continue;
};
if let Err(e) = d.tx.send(ArpResponse::LookupResp { if let Err(e) = d.tx.send(ArpResponse::LookupResp {
mac: mac.0, ip: mac.1, do_arp_request: mac.2 } mac: mac.0, ip: mac.1, do_arp_request: mac.2 }
) { ) {

View File

@ -578,6 +578,8 @@ async fn loop_tap(eee: &'static Node, cancel: CancellationToken) {
packet.push(0x08); packet.push(0x08);
packet.push(0x00); packet.push(0x00);
packet.extend_from_slice(&reply); packet.extend_from_slice(&reply);
/// TODO: check the packet should
if let Err(_e) = eee.device.handle_packet_from_net(&packet, &Vec::new()).await { if let Err(_e) = eee.device.handle_packet_from_net(&packet, &Vec::new()).await {
error!("failed to write dns packet to device"); error!("failed to write dns packet to device");
} }

View File

@ -27,7 +27,7 @@ use crate::tcp::PacketType;
use super::device::{DeviceConfig, Mode}; use super::device::{DeviceConfig, Mode};
use super::TunTapPacketHandler; use super::TunTapPacketHandler;
const DNS_IP: u32 = (100<<24) + (100<<16) + (100<<8) + 100; pub const DNS_IP: u32 = (100<<24) + (100<<16) + (100<<8) + 100;
const RESOLV_FILE: &'static str = "/etc/resolv.conf"; const RESOLV_FILE: &'static str = "/etc/resolv.conf";
const RESOLV_FILE_BACKUP: &'static str = "/etc/resolv.conf.punchnet.bak"; const RESOLV_FILE_BACKUP: &'static str = "/etc/resolv.conf.punchnet.bak";
@ -274,9 +274,16 @@ impl TunTapPacketHandler for Iface {
impl TunTapPacketHandler for Iface { impl TunTapPacketHandler for Iface {
async fn handle_packet_from_net(&self, data: &[u8], key: &[u8]) -> std::io::Result<()> { async fn handle_packet_from_net(&self, data: &[u8], key: &[u8]) -> std::io::Result<()> {
debug!("in tun mode"); debug!("in tun mode");
if key.len() == 0 {
// got layer2 packet, just write to interface;
}
// got layer 2 frame // got layer 2 frame
match Ethernet2Header::from_slice(&data) { match Ethernet2Header::from_slice(&data) {
Ok((hdr, rest)) => { Ok((hdr, rest)) => {
use etherparse::ether_type::ARP;
use sdlan_sn_rs::utils::is_multi_broadcast;
if rest.len() < 4 { if rest.len() < 4 {
error!("payload length error"); error!("payload length error");
return Ok(()); return Ok(());
@ -294,6 +301,8 @@ impl TunTapPacketHandler for Iface {
let self_mac = edge.device_config.get_mac(); let self_mac = edge.device_config.get_mac();
if hdr.destination != self_mac && !is_multi_broadcast(&hdr.destination) { if hdr.destination != self_mac && !is_multi_broadcast(&hdr.destination) {
use sdlan_sn_rs::utils::mac_to_string;
error!( error!(
"packet to [{:?}] not direct to us", "packet to [{:?}] not direct to us",
mac_to_string(&hdr.destination) mac_to_string(&hdr.destination)
@ -302,6 +311,8 @@ impl TunTapPacketHandler for Iface {
} }
if hdr.ether_type == ARP { if hdr.ether_type == ARP {
use crate::network::ArpHdr;
let mut arp = ArpHdr::from_slice(&data); let mut arp = ArpHdr::from_slice(&data);
let self_ip = edge.device_config.get_ip(); let self_ip = edge.device_config.get_ip();
@ -320,6 +331,10 @@ impl TunTapPacketHandler for Iface {
return Ok(()); return Ok(());
} }
if dest_ip == self_ip { if dest_ip == self_ip {
use sdlan_sn_rs::utils::mac_to_string;
use crate::network::{ARP_REPLY, ArpRequestInfo, send_arp_request};
send_arp_request(ArpRequestInfo::Set { send_arp_request(ArpRequestInfo::Set {
ip: from_ip, ip: from_ip,
mac: arp.shwaddr, mac: arp.shwaddr,
@ -369,6 +384,8 @@ impl TunTapPacketHandler for Iface {
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 {
use crate::network::{ArpRequestInfo, arp_arrived, send_arp_request};
send_arp_request(ArpRequestInfo::Set { send_arp_request(ArpRequestInfo::Set {
ip: from_ip, ip: from_ip,
mac: arp.shwaddr, mac: arp.shwaddr,
@ -382,6 +399,8 @@ impl TunTapPacketHandler for Iface {
} }
} }
} else { } else {
use etherparse::IpHeaders;
match IpHeaders::from_slice(rest) { match IpHeaders::from_slice(rest) {
Ok((iphdr, _)) => { Ok((iphdr, _)) => {
let Some(ipv4) = iphdr.ipv4() else { let Some(ipv4) = iphdr.ipv4() else {
@ -391,6 +410,8 @@ impl TunTapPacketHandler for Iface {
let ip = u32::from_be_bytes(ipv4.0.source); let ip = u32::from_be_bytes(ipv4.0.source);
let mac = hdr.source; let mac = hdr.source;
if !is_multi_broadcast(&mac) { if !is_multi_broadcast(&mac) {
use crate::network::{ArpRequestInfo, send_arp_request};
send_arp_request(ArpRequestInfo::Set { ip, mac }).await; send_arp_request(ArpRequestInfo::Set { ip, mac }).await;
} }
} }
@ -427,12 +448,16 @@ impl TunTapPacketHandler for Iface {
data: Vec<u8>, data: Vec<u8>,
encrypt_key: &[u8], encrypt_key: &[u8],
) -> std::io::Result<()> { ) -> std::io::Result<()> {
use etherparse::IpHeaders;
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) { match IpHeaders::from_slice(&data) {
Ok((iphdr, _payload)) => { Ok((iphdr, _payload)) => {
use crate::network::{ArpRequestInfo, ArpResponse, send_arp_request};
let Some(ipv4hdr) = iphdr.ipv4() else { let Some(ipv4hdr) = iphdr.ipv4() else {
debug!("ipv6 packet ignored"); debug!("ipv6 packet ignored");
return Ok(()); return Ok(());
@ -451,13 +476,29 @@ impl TunTapPacketHandler for Iface {
debug!("drop tun packet due to not authed"); debug!("drop tun packet due to not authed");
return Ok(()); return Ok(());
} }
if dstip == DNS_IP {
// should do the dns request
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 { match send_arp_request(ArpRequestInfo::Lookup { ip: dstip }).await {
ArpResponse::LookupResp { ArpResponse::LookupResp {
mac, mac,
ip, ip,
do_arp_request, do_arp_request,
} => { } => {
use crate::utils::caculate_crc;
if do_arp_request { if do_arp_request {
use sdlan_sn_rs::utils::BROADCAST_MAC;
use crate::network::{add_to_arp_wait_list, generate_arp_request};
add_to_arp_wait_list(dstip, data); add_to_arp_wait_list(dstip, data);
debug!( debug!(
"find ip: {:?} => {:?}", "find ip: {:?} => {:?}",

View File

@ -58,7 +58,7 @@ impl Iface {
Ok(content.len()) Ok(content.len())
} }
pub fn reload_config(&self, device_config: &DeviceConfig) { pub fn reload_config(&self, device_config: &DeviceConfig, network_domain: &str) {
let netbit = device_config.get_net_bit(); let netbit = device_config.get_net_bit();
let ip = device_config.get_ip(); let ip = device_config.get_ip();
if netbit == 0 || ip == 0 { if netbit == 0 || ip == 0 {
@ -113,6 +113,13 @@ impl Iface {
error!("failed to run netsh2: {}", e.to_string()); error!("failed to run netsh2: {}", e.to_string());
} }
} }
/*
if let Err(e) = set_dns(&self.name, network_domain) {
println!("failed to set dns: {:?}", e);
}
*/
} }
} }
@ -405,3 +412,29 @@ pub fn new_iface(name: &str, _mode: Mode) -> Iface {
pub fn get_install_channel() -> String { pub fn get_install_channel() -> String {
"windows".to_owned() "windows".to_owned()
} }
pub fn set_dns(name: &str, network_domain: &str) -> std::io::Result<()>{
Command::new("netsh")
.arg("dnsclient")
.arg("set")
.arg("dnsserver")
.arg(&format!("name=\"{}\"", name))
.arg("source=static")
.arg("address=100.100.100.100")
.arg("validate=yes").output()?;
Command::new("netsh")
.arg("interface")
.arg("ipv4")
.arg("set")
.arg("dns")
.arg("suffix")
.arg(&format!("name=\"{}\"", name))
.arg(&format!("suffix=\"{}\"", network_domain))
.output()?;
Ok(())
}
pub fn restore_dns() {
}