diff --git a/Makefile b/Makefile index 3f31ef2..4a2d3e8 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,9 @@ linux: linux-tun: RUSTFLAGS="-L ." cargo build --release +win: + cargo build --release + pb: cargo run --bin build_pb mv src/pb/_.rs src/pb/message.rs diff --git a/src/network/async_main.rs b/src/network/async_main.rs index e24fe6d..ad24f6d 100644 --- a/src/network/async_main.rs +++ b/src/network/async_main.rs @@ -583,10 +583,10 @@ async fn read_and_parse_tun_packet(eee: &'static Node, buf: Vec) { */ // buf.truncate(size); - edge_send_packet_to_net(eee, &buf).await; + edge_send_packet_to_net(eee, buf).await; } -async fn edge_send_packet_to_net(eee: &Node, data: &[u8]) { +async fn edge_send_packet_to_net(eee: &Node, data: Vec) { debug!("edge send packet to net({} bytes): {:?}", data.len(), data); let encrypt_key = eee.get_encrypt_key(); diff --git a/src/network/packet.rs b/src/network/packet.rs index 4ae1a5e..1fa0b12 100644 --- a/src/network/packet.rs +++ b/src/network/packet.rs @@ -11,6 +11,7 @@ use crate::{ tcp::{get_tcp_conn, PacketType}, utils::{send_to_sock, Socket}, }; +use etherparse::Ethernet2Header; use prost::Message; use sdlan_sn_rs::{ config::{AF_INET, AF_INET6}, @@ -1101,3 +1102,14 @@ pub async fn update_supernode_reg(eee: &Node) { register_with_local_peers(eee).await; } */ + +pub fn form_ethernet_packet(src_mac: Mac, dst_mac: Mac, data: &[u8]) -> Vec { + let mut etherheader = Ethernet2Header::default(); + etherheader.destination = dst_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); + packet +} diff --git a/src/network/tun_win.rs b/src/network/tun_win.rs index 3d80001..5ca0e85 100644 --- a/src/network/tun_win.rs +++ b/src/network/tun_win.rs @@ -14,8 +14,8 @@ use wintun; use crate::get_edge; use crate::network::{ - generate_arp_request, send_arp_request, send_packet_to_net, ArpHdr, ArpRequestInfo, - ArpResponse, ARP_REPLY, ARP_REQUEST, + add_to_arp_wait_list, form_ethernet_packet, generate_arp_request, send_arp_request, + send_packet_to_net, ArpHdr, ArpRequestInfo, ArpResponse, ARP_REPLY, ARP_REQUEST, }; use crate::pb::{encode_to_udp_message, SdlData}; use crate::tcp::PacketType; @@ -247,7 +247,7 @@ impl TunTapPacketHandler for Iface { async fn handle_packet_from_device( &self, - data: &[u8], + data: Vec, encrypt_key: &[u8], ) -> std::io::Result<()> { let eee = get_edge(); @@ -281,6 +281,8 @@ impl TunTapPacketHandler for Iface { do_arp_request, } => { if do_arp_request { + add_to_arp_wait_list(dstip, data); + println!( "find ip: {:?} => {:?}", src.to_be_bytes(), @@ -312,7 +314,9 @@ impl TunTapPacketHandler for Iface { return Ok(()); } + 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; @@ -320,6 +324,7 @@ impl TunTapPacketHandler for Iface { 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()); diff --git a/src/network/tuntap.rs b/src/network/tuntap.rs index cada2f0..574768f 100644 --- a/src/network/tuntap.rs +++ b/src/network/tuntap.rs @@ -1,4 +1,115 @@ +use std::sync::atomic::Ordering; + +use dashmap::DashMap; +use etherparse::Ethernet2Header; +use once_cell::sync::OnceCell; +use sdlan_sn_rs::{ + config::SDLAN_DEFAULT_TTL, + utils::{aes_encrypt, get_current_timestamp, Mac}, +}; + +use tracing::error; + +use crate::{ + network::{form_ethernet_packet, send_packet_to_net}, + pb::{encode_to_udp_message, SdlData}, + tcp::PacketType, +}; + +use super::get_edge; + +pub const MAX_WAIT_PACKETS: usize = 100; + pub trait TunTapPacketHandler { async fn handle_packet_from_net(&self, data: &[u8], key: &[u8]) -> std::io::Result<()>; - async fn handle_packet_from_device(&self, data: &[u8], key: &[u8]) -> std::io::Result<()>; + async fn handle_packet_from_device(&self, data: Vec, key: &[u8]) -> std::io::Result<()>; +} + +static ARP_WAIT_LIST: OnceCell = OnceCell::new(); + +pub fn init_arp_wait_list() { + let waitlist = ArpWaitList { + content: DashMap::new(), + }; + ARP_WAIT_LIST.set(waitlist).unwrap(); +} + +#[derive(Debug)] +pub struct ArpWaitInfo { + timestamp: u64, + // origin data is from the tun or tap device + origin_data: Vec, +} + +#[derive(Debug)] +pub struct ArpWaitList { + content: DashMap>, +} + +impl ArpWaitList { + fn add_to_wait_list(&self, ip: u32, origin_data: Vec) { + let mut entry = self.content.entry(ip).or_insert(vec![]); + if entry.len() < MAX_WAIT_PACKETS { + entry.push(ArpWaitInfo { + timestamp: get_current_timestamp(), + origin_data, + }) + } + } + + async fn arp_arrived(&self, ip: u32, mac: Mac) { + let Some(items) = self.content.remove(&ip) else { + return; + }; + let edge = get_edge(); + // just remove the items + if !edge.is_authorized() { + return; + } + + let encrypt_key = edge.get_encrypt_key(); + let network_id = edge.network_id.load(Ordering::Relaxed); + + let src_mac = edge.device_config.get_mac(); + let now = get_current_timestamp(); + for item in items.1 { + if (now - item.timestamp) > 5 { + continue; + } + let packet = form_ethernet_packet(src_mac, mac, &item.origin_data); + + let pkt_size = packet.len(); + + let Ok(encrypted) = aes_encrypt(&encrypt_key, &packet) else { + error!("failed to encrypt packet request"); + return; + }; + let data = SdlData { + is_p2p: true, + network_id, + ttl: SDLAN_DEFAULT_TTL as u32, + src_mac: Vec::from(src_mac), + dst_mac: Vec::from(mac), + data: Vec::from(encrypted), + }; + let msg = encode_to_udp_message(Some(data), PacketType::Data as u8).unwrap(); + send_packet_to_net(edge, mac, &msg, pkt_size as u64).await; + } + } +} + +pub fn add_to_arp_wait_list(ip: u32, origin_data: Vec) { + let waitlist = ARP_WAIT_LIST + .get() + .expect("ARP_WAIT_LIST has not been inited"); + + waitlist.add_to_wait_list(ip, origin_data); +} + +pub async fn arp_arrived(ip: u32, mac: Mac) { + let waitlist = ARP_WAIT_LIST + .get() + .expect("ARP_WAIT_LIST has not been inited"); + + waitlist.arp_arrived(ip, mac).await; } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index d26c5b0..d4c9aeb 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -12,6 +12,7 @@ pub use pid_recorder::PidRecorder; // pub const CRC_HASH: crc::Crc = crc::Crc::::new(&crc::CRC_32_XFER); +#[allow(unused)] pub fn caculate_crc(data: &[u8]) -> u32 { let res = crc32fast::hash(data); res