#![allow(unused)] use std::{ collections::HashMap, sync::{Arc, atomic::{AtomicU8, Ordering}}, time::{Duration, Instant}, }; use bytes::{Bytes, BytesMut}; 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 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 super::{get_edge}; /* static GLOBAL_ARP: OnceCell = OnceCell::new(); pub fn init_arp() { init_arp_wait_list(); let actor = ArpActor::new(); GLOBAL_ARP.set(actor).unwrap(); } pub fn get_arp() -> &'static ArpActor { GLOBAL_ARP.get().unwrap() } */ const ETHER_TYPE_ARP: u16 = 0x0806; const ETHER_TYPE_IP: u16 = 0x0800; #[allow(unused)] const ETHER_TYPE_IP6: u16 = 0x86dd; const ARP_MAX_AGE: u8 = 128; const ARP_HWTYPE_ETH: u16 = 1; pub const ARP_REQUEST: u16 = 1; pub const ARP_REPLY: u16 = 2; #[repr(C)] pub struct EthHdr { pub dest: [u8; 6], pub src: [u8; 6], pub eth_type: u16, } #[repr(C)] pub struct ArpHdr { pub ethhdr: EthHdr, pub hwtype: u16, pub protocol: u16, pub hwlen: u8, pub protolen: u8, pub opcode: u16, pub shwaddr: [u8; 6], pub sipaddr: [u16; 2], pub dhwaddr: [u8; 6], pub dipaddr: [u16; 2], } impl ArpHdr { pub fn from_slice(data: &[u8]) -> Self { if data.len() < 42 { panic!("data size error"); } Self { ethhdr: EthHdr { dest: data[0..6].try_into().unwrap(), src: data[6..12].try_into().unwrap(), eth_type: u16::from_be_bytes(data[12..14].try_into().unwrap()), }, hwtype: u16::from_be_bytes(data[14..16].try_into().unwrap()), protocol: u16::from_be_bytes(data[16..18].try_into().unwrap()), hwlen: data[18], protolen: data[19], opcode: u16::from_be_bytes(data[20..22].try_into().unwrap()), shwaddr: data[22..28].try_into().unwrap(), sipaddr: [ u16::from_be_bytes(data[28..30].try_into().unwrap()), u16::from_be_bytes(data[30..32].try_into().unwrap()), ], dhwaddr: data[32..38].try_into().unwrap(), dipaddr: [ u16::from_be_bytes(data[38..40].try_into().unwrap()), u16::from_be_bytes(data[40..42].try_into().unwrap()), ], } } pub fn marshal_to_bytes(&self) -> Vec { let mut result = Vec::with_capacity(64); result.extend_from_slice(&self.ethhdr.dest); result.extend_from_slice(&self.ethhdr.src); result.extend_from_slice(&self.ethhdr.eth_type.to_be_bytes()); result.extend_from_slice(&self.hwtype.to_be_bytes()); result.extend_from_slice(&self.protocol.to_be_bytes()); result.push(self.hwlen); result.push(self.protolen); result.extend_from_slice(&self.opcode.to_be_bytes()); result.extend_from_slice(&self.shwaddr); result.extend_from_slice(&self.sipaddr[0].to_be_bytes()); result.extend_from_slice(&self.sipaddr[1].to_be_bytes()); result.extend_from_slice(&self.dhwaddr); result.extend_from_slice(&self.dipaddr[0].to_be_bytes()); result.extend_from_slice(&self.dipaddr[1].to_be_bytes()); // result.extend_from_slice(&[0; 18]); // let crc = CRC_HASH.checksum(&result).to_be_bytes(); // result.extend_from_slice(&crc); result } pub fn new() -> Self { Self { ethhdr: EthHdr { dest: [0; 6], src: [0; 6], eth_type: ETHER_TYPE_ARP, }, hwtype: ARP_HWTYPE_ETH, protocol: ETHER_TYPE_IP, hwlen: 6, protolen: 4, opcode: ARP_REQUEST, shwaddr: [0; 6], sipaddr: [0; 2], dhwaddr: [0; 6], dipaddr: [0; 2], } } } // const ARP_TABLE_SIZE: usize = 8; static ARPTIME: AtomicU8 = AtomicU8::new(0); const BROADCAST_IPADDR: u32 = 0xffffffff; #[derive(Debug)] #[allow(unused)] pub struct ArpEntry { // ip_addr: u32, last_seen: Instant, hw_addr: Mac, } /* impl ArpEntry { pub fn new() -> Self { Self { ip_addr: 0, arptime: 0, hw_addr: [0; 6], } } } */ pub struct ArpTable { entries: Arc>, ttl: Duration, pending_packet_buffer: ArpWaitList, } impl ArpTable { pub fn new() -> Self { let entries = Arc::new(DashMap::new()); let res = Self { entries: entries.clone(), ttl: Duration::from_secs(60), pending_packet_buffer: ArpWaitList::new(), }; let mut bytes = BytesMut::with_capacity(1024+20); let ttl = res.ttl; tokio::spawn(async move { loop { tokio::time::sleep(Duration::from_secs(30)).await; let now = Instant::now(); entries.retain(|_, entry| now.duration_since(entry.last_seen) < ttl); } }); res } pub async fn arp_arrived(&self, ip: u32, mac: Mac) { self.pending_packet_buffer.arp_arrived(ip, mac).await; } pub fn add_to_arp_wait_list(&self, ip: u32, origin_data: BytesMut) { self.pending_packet_buffer.add_to_wait_list(ip, origin_data); } #[inline] pub fn get(&self, ip: u32) -> Option { self.entries.get(&ip).map(|entry| entry.hw_addr) } pub fn set(&self, ip: u32, mac: Mac) { self.entries.insert( ip, ArpEntry { last_seen: Instant::now(), hw_addr: mac, }, ); } } /* pub struct ArpInfo { // host_ip: AtomicU32, // ip representation of mask // host_netmask: AtomicU32, entry: HashMap, // entry: [ArpEntry; ARP_TABLE_SIZE], } impl ArpInfo { fn lookup_ip_mac(&self, ip: u32) -> Option<([u8; 6], u32, bool)> { if ip == BROADCAST_IPADDR { return Some((BROADCAST_MAC, ip, false)); } let edge = get_edge(); let netbit = edge.device_config.get_net_bit(); let host_netmask = net_bit_len_to_mask(netbit); let host_netmask_reverse = !host_netmask; if (ip & host_netmask_reverse) == host_netmask_reverse { return Some((BROADCAST_MAC, ip, false)); } let first_ip = (ip >> 24) as u8 & 0xff; if first_ip >= 224 && first_ip <= 239 { let mut multi = MULTICAST_MAC; multi[3] = (ip >> 16) as u8 & 0x7f; multi[4] = (ip >> 8) as u8 & 0xff; multi[5] = (ip) as u8 & 0xff; return Some((multi, ip, false)); } let mut target_ip = 0; let host_ip = edge.device_config.get_ip(); if (ip & host_netmask) == (host_ip & host_netmask) { target_ip = ip; } if target_ip == 0 { // let route_table = get_route_table(); if let Some((_prefix, gateway_ip)) = edge.route_table.route_table.lookup(ip) { // if let Some(gateway_ip) = route_table.get_gateway_ip(ip) { target_ip = gateway_ip.into(); } } if target_ip == 0 { error!("target should not route to me: ip = {}", ip_to_string(&ip)); return None; } if let Some(entry) = self.entry.get(&target_ip) { return Some((entry.hw_addr, target_ip, false)); } /* for i in 0..ARP_TABLE_SIZE { let item = &self.entry[i]; if item.ip_addr == target_ip { return (item.hw_addr, target_ip, false); } } */ return Some((BROADCAST_MAC, target_ip, true)); } fn set_arp(&mut self, mac: [u8; 6], ip: u32) { // println!("setting ip: {:?} is at {:?}", ip.to_be_bytes(), mac); let nowage = ARPTIME.load(Ordering::Relaxed); self.entry.insert( ip, ArpEntry { ip_addr: ip, hw_addr: mac, arptime: nowage, }, ); /* for i in 0..ARP_TABLE_SIZE { let item = &mut self.entry[i]; if item.ip_addr != 0 { if item.ip_addr == ip { item.hw_addr = mac; let nowage = ARPTIME.load(Ordering::Relaxed); item.arptime = nowage; return; } } } */ /* println!("set_arp 1"); let mut itemindex = ARP_TABLE_SIZE; for i in 0..ARP_TABLE_SIZE { let temp = &self.entry[i]; println!("set arp 2"); if temp.ip_addr == 0 { itemindex = i; println!("set arp 3: itemindex = {}", itemindex); break; } } let arptime = ARPTIME.load(Ordering::Relaxed); if itemindex == ARP_TABLE_SIZE { println!("set_arp 4"); let mut tmpage = 0; let mut idx = 0; for i in 0..ARP_TABLE_SIZE { let temp = &self.entry[i]; if (arptime - temp.arptime) > tmpage { tmpage = arptime - temp.arptime; idx = i; } } itemindex = idx; } println!("set_arp 5"); let temp = &mut self.entry[itemindex]; temp.arptime = arptime; temp.ip_addr = ip; temp.hw_addr = mac; println!("set arp 6: idx={} => {:?}", itemindex, temp); */ } fn timer(&mut self) { let timer = ARPTIME.fetch_add(1, Ordering::Relaxed); let mut todelete = vec![]; for (ip, entry) in &self.entry { if (timer - entry.arptime) >= ARP_MAX_AGE { todelete.push(*ip); } } for ip in todelete { self.entry.remove(&ip); } /* for i in 0..ARP_TABLE_SIZE { let item = &mut self.entry[i]; if item.ip_addr != 0 && (timer - item.arptime) >= ARP_MAX_AGE { item.ip_addr = 0; } } */ } } */ /* pub enum ArpRequestInfo { Lookup { ip: u32 }, Set { ip: u32, mac: Mac }, } pub struct ArpRequest { req: ArpRequestInfo, tx: oneshot::Sender, } #[derive(Debug)] #[allow(unused)] pub enum ArpResponse { LookupResp { mac: Mac, ip: u32, do_arp_request: bool, }, SetResp { ok: bool, }, ArpRespError { msg: String, }, } #[derive(Debug)] pub struct ArpActor { pub tx: Sender, } impl ArpActor { pub fn new() -> Self { let (tx, rx) = channel(20); tokio::spawn(loop_arp_info(rx)); Self { tx } } } async fn loop_arp_info(mut rx: Receiver) { let mut arp = ArpInfo { // entry: array::from_fn(|_i| ArpEntry::new()), entry: HashMap::new(), }; loop { tokio::select! { data = rx.recv() => { if let Some(d) = data { match d.req { ArpRequestInfo::Lookup{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 } ) { error!("failed to send back arp lookup feedback: {:?}", e); }; } ArpRequestInfo::Set{ip, mac} => { arp.set_arp(mac, ip); if let Err(e) = d.tx.send(ArpResponse::SetResp { ok: true }) { error!("failed to send back arp set feedback: {:?}", e); } } } } } _ = tokio::time::sleep(Duration::from_secs(10)) => { arp.timer(); } } } } pub async fn send_arp_request(data: ArpRequestInfo) -> ArpResponse { let (tx, rx) = oneshot::channel(); let arp = get_arp(); if let Err(e) = arp.tx.send(ArpRequest { tx, req: data }).await { error!("failed to send arp request: {}", e); return ArpResponse::ArpRespError { msg: "failed to send arp request".to_owned(), }; } match rx.await { Ok(res) => res, Err(e) => ArpResponse::ArpRespError { msg: e.to_string() }, } } */ pub fn generate_arp_request(srcmac: [u8; 6], dstip: u32, srcip: u32) -> Vec { let mut arphdr = ArpHdr::new(); arphdr.ethhdr.dest = [0xff; 6]; arphdr.dhwaddr = [0; 6]; arphdr.ethhdr.src = srcmac; arphdr.shwaddr = srcmac; arphdr.dipaddr = [(dstip >> 16) as u16, (dstip & 0xffff) as u16]; arphdr.sipaddr = [(srcip >> 16) as u16, (srcip & 0xffff) as u16]; /* println!( "arphdr.sipaddr: {:?}, {:?}", arphdr.sipaddr[0].to_be_bytes(), arphdr.sipaddr[1].to_be_bytes() ); println!( "arphdr.dipaddr: {:?}, {:?}", arphdr.dipaddr[0].to_be_bytes(), arphdr.dipaddr[1].to_be_bytes() ); */ arphdr.marshal_to_bytes() } #[derive(Debug)] pub struct ArpWaitInfo { timestamp: u64, // origin data is from the tun or tap device origin_data: BytesMut, } pub const MAX_WAIT_PACKETS: usize = 100; #[derive(Debug)] pub struct ArpWaitList { content: DashMap>, } impl ArpWaitList { fn new() -> Self { Self { content: DashMap::new(), } } 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 { entry.push(ArpWaitInfo { timestamp: get_current_timestamp(), origin_data, }) } } async fn arp_arrived(&self, ip: u32, mac: Mac) { debug!( "arp for {} arrived: {}", ip_to_string(&ip), mac_to_string(&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) = 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 { error!("failed to encrypt packet request"); return; }; let data_bytes = Bytes::from(encrypted); 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: data_bytes, identity_id: edge.identity_id.load(), session_token: edge.session_token.get(), }; 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; } } }