From 7c4bb64bd413b43cc6fe3a2a4504f4c1be69bdd9 Mon Sep 17 00:00:00 2001 From: asxalex Date: Wed, 23 Oct 2024 16:22:52 +0800 Subject: [PATCH] changed to handle_packet --- src/network/mod.rs | 3 + src/network/node.rs | 1 + src/network/packet.rs | 26 +++++- src/network/tun_linux.rs | 168 ++++++++++++++++++++++++++++++++++++++- src/network/tuntap.rs | 3 + 5 files changed, 197 insertions(+), 4 deletions(-) create mode 100644 src/network/tuntap.rs diff --git a/src/network/mod.rs b/src/network/mod.rs index 639801b..99ca253 100644 --- a/src/network/mod.rs +++ b/src/network/mod.rs @@ -15,6 +15,9 @@ pub use arp::*; mod route; pub use route::*; +mod tuntap; +pub use tuntap::*; + #[cfg_attr(target_os = "linux", path = "tun_linux.rs")] #[cfg_attr(target_os = "windows", path = "tun_win.rs")] mod tun; diff --git a/src/network/node.rs b/src/network/node.rs index dc3e55b..d81bc45 100644 --- a/src/network/node.rs +++ b/src/network/node.rs @@ -367,6 +367,7 @@ impl Node { pub async fn send_nat_probe_reply(&self, cookie: u32, buf: SdlStunProbeReply) { if let Some((_key, chan)) = self.cookie_match.remove(&cookie) { let _ = chan.send(buf); + return; } error!("failed to get such cookie stun probe"); } diff --git a/src/network/packet.rs b/src/network/packet.rs index 60bf5e3..4601ee3 100644 --- a/src/network/packet.rs +++ b/src/network/packet.rs @@ -5,7 +5,7 @@ use std::{ }; use crate::{ - network::send_packet_to_net, + network::{send_packet_to_net, TunTapPacketHandler}, utils::{mac_to_string, CRC_HASH}, }; @@ -20,7 +20,7 @@ use crate::{ tcp::{get_tcp_conn, PacketType}, utils::{send_to_sock, Socket}, }; -use etherparse::{ether_type::ARP, Ethernet2Header, IpHeaders}; +use etherparse::{ether_type::ARP, Ethernet2Header, IpHeader, IpHeaders}; use prost::Message; use sdlan_sn_rs::{ config::{AF_INET, AF_INET6}, @@ -746,6 +746,8 @@ async fn handle_tun_packet( } let data = origin.unwrap(); debug!("ether size is {}", data.len()); + eee.device.handle_packet(&data, key.as_slice()).await; + /* let msg_size = data.len() as u64; let Ok(dst_mac) = pkt.dst_mac.try_into() else { @@ -776,6 +778,7 @@ async fn handle_tun_packet( } let crc_code = &rest[(rest.len() - 4)..rest.len()]; let rest = &rest[..(rest.len() - 4)]; + let crc_hash: crc::Crc = crc::Crc::::new(&crc::CRC_32_CKSUM); let ck = CRC_HASH.checksum(&data[..(data.len()) - 4]); let sent_ck = u32::from_be_bytes(crc_code.try_into().unwrap()); @@ -875,6 +878,24 @@ async fn handle_tun_packet( } } } else { + match IpHeaders::from_slice(rest) { + Ok((iphdr, _)) => { + let Some(ipv4) = iphdr.ipv4() else { + error!("not ipv4, dropping"); + return; + }; + let ip = u32::from_be_bytes(ipv4.0.source); + let mac = hdr.source; + if !is_multi_broadcast(&mac) { + send_arp_request(ArpRequestInfo::Set { ip, mac }).await; + } + } + Err(e) => { + error!("failed to parse ip header, dropping"); + return; + } + } + println!("got ip packet"); println!("got data: {:?}", rest); match edge.device.send(rest) { @@ -893,6 +914,7 @@ async fn handle_tun_packet( return; } } + */ } async fn send_register_ack(eee: &Node, orig_sender: &SdlanSock, reg: &SdlRegister) { diff --git a/src/network/tun_linux.rs b/src/network/tun_linux.rs index 958621a..caa025b 100644 --- a/src/network/tun_linux.rs +++ b/src/network/tun_linux.rs @@ -1,8 +1,13 @@ -use sdlan_sn_rs::utils::{ip_to_string, net_bit_len_to_mask, SDLanError}; +use etherparse::ether_type::ARP; +use etherparse::{Ethernet2Header, IpHeaders}; +use sdlan_sn_rs::utils::{ + aes_encrypt, ip_to_string, is_multi_broadcast, net_bit_len_to_mask, SDLanError, +}; use std::ffi::CStr; use std::ffi::{c_char, c_int}; use std::fs::OpenOptions; use std::ptr::null_mut; +use std::sync::atomic::Ordering; use sdlan_sn_rs::utils::Result; use std::io::{Read, Write}; @@ -11,7 +16,14 @@ use std::process::Command; use tracing::{debug, error}; +use crate::get_edge; +use crate::network::{send_arp_request, send_packet_to_net, ArpHdr, ArpRequestInfo, ARP_REPLY}; +use crate::pb::{encode_to_udp_message, SdlData}; +use crate::tcp::PacketType; +use crate::utils::{mac_to_string, CRC_HASH}; + use super::device::{DeviceConfig, Mode}; +use super::TunTapPacketHandler; #[link(name = "tuntap")] extern "C" { @@ -125,6 +137,158 @@ impl Iface { } } +impl TunTapPacketHandler for Iface { + async fn handle_packet(&self, data: &[u8], key: &[u8]) -> std::io::Result<()> { + // got layer 2 frame + match Ethernet2Header::from_slice(&data) { + Ok((hdr, rest)) => { + if rest.len() < 4 { + error!("payload length error"); + return Ok(()); + } + let crc_code = &rest[(rest.len() - 4)..rest.len()]; + let rest = &rest[..(rest.len() - 4)]; + + let crc_hash: crc::Crc = crc::Crc::::new(&crc::CRC_32_CKSUM); + let ck = CRC_HASH.checksum(&data[..(data.len()) - 4]); + let sent_ck = u32::from_be_bytes(crc_code.try_into().unwrap()); + debug!("ck = {}, sent_ck = {}", ck, sent_ck); + + debug!("ip size is {}", rest.len()); + let edge = get_edge(); + let self_mac = edge.device_config.get_mac(); + + /* + if hdr.destination != self_mac && hdr.destination != BROADCAST_MAC { + error!( + "packet to [{:?}] not direct to us", + mac_to_string(&hdr.destination) + ); + return; + } + */ + + if hdr.ether_type == ARP { + let mut arp = ArpHdr::from_slice(&data); + let self_ip = edge.device_config.get_ip(); + + println!("self_ip: {:?}", self_ip.to_be_bytes()); + let from_ip = ((arp.sipaddr[0] as u32) << 16) + arp.sipaddr[1] as u32; + println!("from_ip: {:?}", from_ip.to_be_bytes()); + let dest_ip = ((arp.dipaddr[0] as u32) << 16) + arp.dipaddr[1] as u32; + println!("dest_ip: {:?}", dest_ip.to_be_bytes()); + + match arp.opcode { + ARP_REQUEST => { + // handle ARP REQUEST + debug!("got ARP REQUEST"); + if arp.ethhdr.dest != [0xff; 6] { + println!("ARP REQUEST not broadcast"); + return Ok(()); + } + if dest_ip == self_ip { + send_arp_request(ArpRequestInfo::Set { + ip: from_ip, + mac: arp.shwaddr, + }) + .await; + // target to us + arp.opcode = ARP_REPLY; + arp.dhwaddr = arp.shwaddr; + arp.shwaddr = self_mac; + arp.ethhdr.src = self_mac; + arp.ethhdr.dest = arp.dhwaddr; + + arp.dipaddr = arp.sipaddr; + + arp.sipaddr = + [((self_ip >> 16) & 0xffff) as u16, (self_ip & 0xffff) as u16]; + + let data = arp.marshal_to_bytes(); + let Ok(encrypted) = aes_encrypt(key, &data) else { + error!("failed to encrypt arp reply"); + return Ok(()); + }; + + let data = SdlData { + is_p2p: true, + ttl: 2, + network_id: edge.network_id.load(Ordering::Relaxed), + src_mac: Vec::from(self_mac), + dst_mac: Vec::from(arp.dhwaddr), + data: encrypted, + }; + + let v = encode_to_udp_message(Some(data), PacketType::Data as u8) + .unwrap(); + println!( + "xxxx send arp reply to [{}], selfmac=[{}]", + mac_to_string(&arp.dhwaddr), + mac_to_string(&self_mac) + ); + send_packet_to_net(edge, arp.dhwaddr, &v, 0).await; + // send_to_sock(edge, &v, from_sock); + // edge.sock.send(v).await; + } + } + ARP_REPLY => { + println!("got arp reply",); + + println!("mac {:?} is at {:?}", arp.shwaddr, from_ip.to_be_bytes()); + if dest_ip == self_ip { + send_arp_request(ArpRequestInfo::Set { + ip: from_ip, + mac: arp.shwaddr, + }) + .await; + } + } + other => { + println!("unknown arp type info"); + } + } + } else { + match IpHeaders::from_slice(rest) { + Ok((iphdr, _)) => { + let Some(ipv4) = iphdr.ipv4() else { + error!("not ipv4, dropping"); + return Ok(()); + }; + let ip = u32::from_be_bytes(ipv4.0.source); + let mac = hdr.source; + if !is_multi_broadcast(&mac) { + send_arp_request(ArpRequestInfo::Set { ip, mac }).await; + } + } + Err(e) => { + error!("failed to parse ip header, dropping"); + return Ok(()); + } + } + + println!("got ip packet"); + println!("got data: {:?}", rest); + match edge.device.send(rest) { + Ok(size) => { + debug!("send to tun {} bytes", size); + } + Err(e) => { + error!("failed to send to device: {}", e.to_string()); + } + } + // edge.tun.send_data_to_tun(Vec::from(hdr.1)).await; + } + } + Err(e) => { + error!("failed to parse tap packet: {}", e); + return Ok(()); + } + } + + Ok(()) + } +} + pub fn get_install_channel() -> String { "linux".to_owned() -} \ No newline at end of file +} diff --git a/src/network/tuntap.rs b/src/network/tuntap.rs new file mode 100644 index 0000000..07e97ae --- /dev/null +++ b/src/network/tuntap.rs @@ -0,0 +1,3 @@ +pub trait TunTapPacketHandler { + async fn handle_packet(&self, data: &[u8], key: &[u8]) -> std::io::Result<()>; +}