diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..80d7c65 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "rust-analyzer.cargo.target": null, + "rust-analyzer.cargo.features": ["tun"] +} \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 6f5b9e1..cef3862 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -1524,11 +1524,10 @@ dependencies = [ [[package]] name = "num-bigint-dig" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" dependencies = [ - "byteorder", "lazy_static", "libm", "num-integer", @@ -2092,9 +2091,9 @@ dependencies = [ [[package]] name = "rsa" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" +checksum = "40a0376c50d0358279d9d643e4bf7b7be212f1f4ff1da9070a7b54d22ef75c88" dependencies = [ "const-oid", "digest", diff --git a/src/network/arp.rs b/src/network/arp.rs index 112e5f2..84b1429 100755 --- a/src/network/arp.rs +++ b/src/network/arp.rs @@ -9,12 +9,14 @@ use std::{ use tracing::error; 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::{ mpsc::{channel, Receiver, Sender}, oneshot, }; +use crate::network::tun::DNS_IP; + use super::{get_edge, get_route_table, init_arp_wait_list, init_route}; static GLOBAL_ARP: OnceCell = OnceCell::new(); @@ -168,9 +170,9 @@ pub struct 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 { - return (BROADCAST_MAC, ip, false); + return Some((BROADCAST_MAC, ip, false)); } let edge = get_edge(); let netbit = edge.device_config.get_net_bit(); @@ -178,7 +180,7 @@ impl ArpInfo { let host_netmask_reverse = !host_netmask; 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; @@ -187,7 +189,7 @@ impl ArpInfo { multi[3] = (ip >> 16) as u8 & 0x7f; multi[4] = (ip >> 8) as u8 & 0xff; multi[5] = (ip) as u8 & 0xff; - return (multi, ip, false); + return Some((multi, ip, false)); } let mut target_ip = 0; @@ -204,10 +206,11 @@ impl ArpInfo { } } 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) { - return (entry.hw_addr, target_ip, false); + return Some((entry.hw_addr, target_ip, false)); } /* 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) { @@ -352,7 +355,9 @@ async fn loop_arp_info(mut rx: Receiver) { if let Some(d) = data { match d.req { 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 { mac: mac.0, ip: mac.1, do_arp_request: mac.2 } ) { diff --git a/src/network/async_main.rs b/src/network/async_main.rs index 1d0d7f1..11aff9a 100755 --- a/src/network/async_main.rs +++ b/src/network/async_main.rs @@ -578,6 +578,8 @@ async fn loop_tap(eee: &'static Node, cancel: CancellationToken) { packet.push(0x08); packet.push(0x00); packet.extend_from_slice(&reply); + + /// TODO: check the packet should if let Err(_e) = eee.device.handle_packet_from_net(&packet, &Vec::new()).await { error!("failed to write dns packet to device"); } diff --git a/src/network/tun_linux.rs b/src/network/tun_linux.rs index 424cd91..d8737a2 100755 --- a/src/network/tun_linux.rs +++ b/src/network/tun_linux.rs @@ -27,7 +27,7 @@ use crate::tcp::PacketType; use super::device::{DeviceConfig, Mode}; 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_BACKUP: &'static str = "/etc/resolv.conf.punchnet.bak"; @@ -274,9 +274,16 @@ impl TunTapPacketHandler for Iface { impl TunTapPacketHandler for Iface { async fn handle_packet_from_net(&self, data: &[u8], key: &[u8]) -> std::io::Result<()> { debug!("in tun mode"); + + if key.len() == 0 { + // got layer2 packet, just write to interface; + } // got layer 2 frame match Ethernet2Header::from_slice(&data) { Ok((hdr, rest)) => { + use etherparse::ether_type::ARP; + use sdlan_sn_rs::utils::is_multi_broadcast; + if rest.len() < 4 { error!("payload length error"); return Ok(()); @@ -294,6 +301,8 @@ impl TunTapPacketHandler for Iface { let self_mac = edge.device_config.get_mac(); if hdr.destination != self_mac && !is_multi_broadcast(&hdr.destination) { + use sdlan_sn_rs::utils::mac_to_string; + error!( "packet to [{:?}] not direct to us", mac_to_string(&hdr.destination) @@ -302,6 +311,8 @@ impl TunTapPacketHandler for Iface { } if hdr.ether_type == ARP { + use crate::network::ArpHdr; + let mut arp = ArpHdr::from_slice(&data); let self_ip = edge.device_config.get_ip(); @@ -320,6 +331,10 @@ impl TunTapPacketHandler for Iface { return Ok(()); } 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 { ip: from_ip, mac: arp.shwaddr, @@ -369,6 +384,8 @@ impl TunTapPacketHandler for Iface { 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 { ip: from_ip, mac: arp.shwaddr, @@ -382,6 +399,8 @@ impl TunTapPacketHandler for Iface { } } } else { + use etherparse::IpHeaders; + match IpHeaders::from_slice(rest) { Ok((iphdr, _)) => { let Some(ipv4) = iphdr.ipv4() else { @@ -391,6 +410,8 @@ impl TunTapPacketHandler for Iface { let ip = u32::from_be_bytes(ipv4.0.source); let mac = hdr.source; if !is_multi_broadcast(&mac) { + use crate::network::{ArpRequestInfo, send_arp_request}; + send_arp_request(ArpRequestInfo::Set { ip, mac }).await; } } @@ -427,12 +448,16 @@ impl TunTapPacketHandler for Iface { data: Vec, encrypt_key: &[u8], ) -> std::io::Result<()> { + use etherparse::IpHeaders; + let eee = get_edge(); let src_mac = eee.device_config.get_mac(); match IpHeaders::from_slice(&data) { Ok((iphdr, _payload)) => { + use crate::network::{ArpRequestInfo, ArpResponse, send_arp_request}; + let Some(ipv4hdr) = iphdr.ipv4() else { debug!("ipv6 packet ignored"); return Ok(()); @@ -451,13 +476,29 @@ impl TunTapPacketHandler for Iface { debug!("drop tun packet due to not authed"); 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 { ArpResponse::LookupResp { mac, ip, do_arp_request, } => { + use crate::utils::caculate_crc; + 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); debug!( "find ip: {:?} => {:?}", diff --git a/src/network/tun_win.rs b/src/network/tun_win.rs index 3f3368d..f584f81 100755 --- a/src/network/tun_win.rs +++ b/src/network/tun_win.rs @@ -58,7 +58,7 @@ impl Iface { 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 ip = device_config.get_ip(); if netbit == 0 || ip == 0 { @@ -113,6 +113,13 @@ impl Iface { 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 { "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() { + +} \ No newline at end of file