#[cfg(not(feature = "tun"))] use bytes::BytesMut; #[cfg(feature = "tun")] use bytes::{Bytes, BytesMut}; use etherparse::{Ethernet2Header}; use ipnet::Ipv4Net; use sdlan_sn_rs::config::SDLAN_DEFAULT_TTL; use sdlan_sn_rs::utils::{ ip_to_string, is_ipv6_multicast, net_bit_len_to_mask, SDLanError, }; use std::ffi::CStr; use std::ffi::{c_char, c_int}; use std::fs::{self, OpenOptions}; use std::net::Ipv4Addr; use std::os::unix::fs::{MetadataExt, PermissionsExt}; use std::path::Path; use std::ptr::null_mut; use std::sync::atomic::Ordering; use sdlan_sn_rs::utils::Result; use std::io::{BufRead, BufReader, Read, Write}; use std::os::fd::AsRawFd; use std::process::Command; use tracing::{debug, error, info}; #[cfg(feature = "tun")] use crate::caculate_crc; use crate::get_edge; #[cfg(not(feature = "tun"))] use crate::network::{ARP_REPLY, ArpHdr, EthHdr}; use crate::network::{Node, send_packet_to_net}; #[cfg(not(feature = "tun"))] use crate::pb::SdlArpResponse; #[cfg(feature = "tun")] use crate::pb::SdlArpResponse; use crate::pb::{encode_to_udp_message, SdlData}; use crate::tcp::PacketType; use super::device::{DeviceConfig, Mode}; use super::TunTapPacketHandler; const RESOLV_FILE: &'static str = "/etc/resolv.conf"; const RESOLV_FILE_BACKUP: &'static str = "/etc/resolv.conf.punchnet.bak"; use crate::network::DNS_IP; // #[link(name = "tuntap", kind="static")] #[link(name = "tuntap")] extern "C" { fn tuntap_setup(fd: c_int, name: *mut u8, mode: c_int, packet_info: c_int) -> c_int; } #[allow(unused)] pub struct Iface { fd: std::fs::File, mode: Mode, name: String, has_resolvectl: bool, } pub fn new_iface(tunname: &str, mode: Mode) -> Iface { match Iface::without_packet_info(tunname, mode) { Err(e) => { panic!("failed to create tun: {}", e.as_str()); } Ok(iface) => iface, } } impl Iface { #[allow(unused)] pub fn with_packet_info(ifname: &str, mode: Mode) -> Result { Iface::open_tun(ifname, mode, true) } pub fn without_packet_info(ifname: &str, mode: Mode) -> Result { Iface::open_tun(ifname, mode, false) } fn open_tun(ifname: &str, mode: Mode, need_packet_info: bool) -> Result { let fs = match OpenOptions::new() .read(true) .write(true) .open("/dev/net/tun") { Ok(fs) => fs, Err(e) => panic!("failed to open tun: {}", e), }; let mut name_ptr: *mut u8 = null_mut(); let mut success = false; let mut _name = Vec::new(); for i in 0..16 { _name.clear(); _name.extend_from_slice(ifname.as_bytes()); _name.extend_from_slice(i.to_string().as_bytes()); _name.extend_from_slice(&[0; 33]); name_ptr = _name.as_mut_ptr(); let result = unsafe { tuntap_setup( fs.as_raw_fd(), name_ptr, mode as c_int, if need_packet_info { 1 } else { 0 }, ) }; if result >= 0 { success = true; break; } } if success { let name = unsafe { CStr::from_ptr(name_ptr as *const c_char) .to_string_lossy() .into_owned() }; let has_resolvectl = check_has_resolvectl(); Ok(Iface { fd: fs, mode, name, has_resolvectl }) } else { Err(SDLanError::NormalError("failed to setup tun")) } } pub fn reload_config(&self, node: &Node, device_config: &DeviceConfig, network_domain: &str) { let netbit = device_config.get_net_bit(); let ip = device_config.get_ip(); if netbit == 0 || ip == 0 { error!("reload config's ip is 0"); return; } let mask = net_bit_len_to_mask(netbit); let mut default_gw = (ip & mask) + 1; if default_gw == ip { default_gw += 1; } let ip = ip_to_string(&ip); let netbit = ip_to_string(&net_bit_len_to_mask(netbit)); if cfg!(not(feature = "tun")) { info!("set tap device"); let mac = device_config.get_mac(); let res = Command::new("ifconfig") .arg(&self.name) .arg(ip) .arg("netmask") .arg(&netbit) .arg("hw") .arg("ether") .arg(format!( "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] )) .arg("mtu") .arg(format!("{}", device_config.mtu)) .arg("up") .output(); match res { Ok(_) => { debug!("ifconfig ok"); } Err(e) => { error!("failed to run ifconfig: {}", e.to_string()); } } node.route_table.apply_system(); if node.config.allow_routing.load(Ordering::Relaxed) { set_allow_routing(); } // TODO: set dns should be opened /* if let Err(e) = set_dns(self, &self.name, network_domain, &ip_to_string(&default_gw)) { error!("failed to set dns: {}", e.as_str()); } */ } else { info!("set tun device"); let res = Command::new("ifconfig") .arg(&self.name) .arg(ip) .arg("netmask") .arg(&netbit) .arg("mtu") .arg(format!("{}", device_config.mtu)) .arg("up") .output(); match res { Ok(_) => { debug!("ifconfig ok"); } Err(e) => { error!("failed to run ifconfig: {}", e.to_string()); } } if let Err(e) = set_dns(self, &self.name, network_domain, &ip_to_string(&default_gw)) { error!("failed to set dns: {}", e.as_str()); } } } pub fn recv(&self, buf: &mut [u8]) -> std::io::Result { (&self.fd).read(buf) } pub fn send(&self, content: &[u8]) -> std::io::Result { (&self.fd).write(content) } } #[cfg(not(feature = "tun"))] impl TunTapPacketHandler for Iface { async fn handle_packet_from_net(&self, data: &[u8]) -> std::io::Result<()> { // debug!("in tap mode, got data: {:?}", data); match self.send(data) { Err(e) => { error!("failed to write to tap: {}", e.to_string()); return Err(e); } Ok(_) => return Ok(()), } } async fn handle_packet_from_device( &self, data: BytesMut, // encrypt_key: &[u8], ) -> std::io::Result<()> { use etherparse::PacketHeaders; debug!("in tap mode2"); let edge = get_edge(); let Ok(headers) = PacketHeaders::from_ethernet_slice(&data) else { error!("failed to parse packet"); return Ok(()); }; if let Some(eth) = headers.link { use etherparse::EtherType; if let Some(hdr) = eth.ethernet2() { use bytes::Bytes; if hdr.ether_type == EtherType::ARP { use crate::network::{ARP_REQUEST, ArpHdr}; let arp = ArpHdr::from_slice(&data); match arp.opcode { ARP_REQUEST => { let dest_ip = ((arp.dipaddr[0] as u32) << 16) + arp.dipaddr[1] as u32; if edge.device_config.contains(&Ipv4Addr::from_bits(dest_ip)) { let _ = edge.send_arp_request(dest_ip, dest_ip).await; } else { if let Some((_, real_ip)) = edge.route_table.lookup(dest_ip) { let real_ip = u32::from_be_bytes(real_ip.octets()); let _ = edge.send_arp_request(dest_ip, real_ip).await; } } /* let request = SdlArpRequest { pkt_id: edge.get_next_packet_id(), target_ip: dest_ip, }; let req = encode_to_tcp_message(Some(request), PacketType::ArpRequest as u8).unwrap(); let conn = get_quic_write_conn(); debug!("sending arp request"); let _ = conn.send(req).await; */ return Ok(()); } _other => { // just do the following logic } } } if let Some(ip) = headers.net { match ip { etherparse::NetHeaders::Ipv4(ipv4, _) => { use crate::FiveTuple; use etherparse::IpNumber; if let Some(transport) = headers.transport { match ipv4.protocol { IpNumber::TCP => { let tcp = transport.tcp().unwrap(); let out_five_tuple = FiveTuple { src_ip: ipv4.source.into(), dst_ip: ipv4.destination.into(), src_port: tcp.source_port, dst_port: tcp.destination_port, proto: IpNumber::TCP.0, }; edge.rule_cache.touch_packet(out_five_tuple); // is tcp } IpNumber::UDP => { let udp = transport.udp().unwrap(); let out_five_tuple = FiveTuple { src_ip: ipv4.source.into(), dst_ip: ipv4.destination.into(), src_port: udp.source_port, dst_port: udp.destination_port, proto: IpNumber::UDP.0, }; edge.rule_cache.touch_packet(out_five_tuple); } _other => { } } } if u32::from_be_bytes(ipv4.destination) == DNS_IP { // should send to dns if let Err(e) = edge.udp_sock_for_dns.send_to(&data[14..], format!("{}:15353", edge.server_ip)).await { error!("failed to send request to 15353: {}", e); } // edge.udp_sock_for_dns.send_to() return Ok(()) } } _other => { // just ignore } } } let target = hdr.destination; if is_ipv6_multicast(&target) { return Ok(()); } let size = data.len(); let Ok(encrypted) = edge.encryptor.load().encrypt(&data) else { // let Ok(encrypted) = edge.encryptor.read().unwrap().encrypt(&data) else { // let Ok(encrypted) = aes_encrypt(encrypt_key, &data) else { error!("failed to encrypt packet request"); return Ok(()); }; let data_bytes = Bytes::from(encrypted); let data = SdlData { is_p2p: true, network_id: edge.network_id.load(Ordering::Relaxed), ttl: SDLAN_DEFAULT_TTL as u32, src_mac: Vec::from(edge.device_config.get_mac()), dst_mac: Vec::from(target), 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, target, &msg, size as u64).await; } else { error!("erro 2"); } } else { error!("erro 1"); } Ok(()) } } #[cfg(feature = "tun")] impl TunTapPacketHandler for Iface { async fn handle_packet_from_net(&self, data: &[u8]) -> std::io::Result<()> { debug!("in tun mode"); // 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(()); } // 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 = caculate_crc(&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 && !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) ); return Ok(()); } if hdr.ether_type == ARP { use crate::network::ArpHdr; 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] { debug!("ARP REQUEST not broadcast"); return Ok(()); } if dest_ip == self_ip { use bytes::Bytes; use sdlan_sn_rs::utils::mac_to_string; use crate::network::ARP_REPLY; edge.arp_table.set(from_ip, arp.shwaddr); /* use crate::network::{ARP_REPLY, ArpRequestInfo, send_arp_request}; 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 { let Ok(encrypted) = edge.encryptor.load().encrypt(&data) else { error!("failed to encrypt arp reply"); return Ok(()); }; let data_bytes = Bytes::from(encrypted); 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: data_bytes, session_token: edge.session_token.get(), identity_id: edge.identity_id.load(), }; let v = encode_to_udp_message(Some(data), PacketType::Data as u8) .unwrap(); debug!( "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 => { 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, }) .await; */ // use crate::network::arp_arrived; edge.arp_table.set(from_ip, arp.shwaddr); edge.arp_table.arp_arrived(from_ip, arp.shwaddr).await; } } _other => { error!("unknown arp type info"); } } } else { use etherparse::IpHeaders; 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) { //use crate::network::{ArpRequestInfo, send_arp_request}; edge.arp_table.set(ip, mac); // send_arp_request(ArpRequestInfo::Set { ip, mac }).await; } } Err(_) => { 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 tun packet: {}", e); return Ok(()); } } Ok(()) } async fn handle_packet_from_device( &self, mut header: BytesMut, ) -> std::io::Result<()> { use etherparse::IpHeaders; let eee = get_edge(); let src_mac = eee.device_config.get_mac(); let data = header.split_off(14); 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(()); }; let dstip = u32::from_be_bytes(ipv4hdr.0.destination); debug!("packet dst ip: {:?}", ipv4hdr.0.destination); let src = u32::from_be_bytes(ipv4hdr.0.source); debug!("packet src ip: {:?}", ipv4hdr.0.source); // packet should be sent to dev debug!("got {} bytes from tun", data.len()); if (!eee.config.allow_routing.load(Ordering::Relaxed)) && (src != eee.device_config.get_ip()) { info!("dropping routed packet"); return Ok(()); } if !eee.is_authorized() { 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 eee.arp_table.get(dstip) { Some(mac) => { let pkt_size = data.len() + 14; let mut etherheader = Ethernet2Header::default(); etherheader.destination = mac; etherheader.ether_type = etherparse::EtherType::IPV4; etherheader.source = src_mac; // let mut packet = Vec::with_capacity(14 + data.len() + 4); header.copy_from_slice(ðerheader.to_bytes()[..]); let crc = caculate_crc(&data); header.unsplit(data); // packet.extend_from_slice(ðerheader.to_bytes()[..]); // packet.extend_from_slice(&data); header.extend_from_slice(&crc.to_be_bytes()); // packet.extend_from_slice(&crc.to_be_bytes()); // let pkt_size = packet.len(); // println!("sending data with mac"); // let Ok(encrypted) = aes_encrypt(&encrypt_key, &packet) else { let Ok(encrypted) = eee.encryptor.load().encrypt(&header) else { error!("failed to encrypt packet request"); return Ok(()); }; let data = SdlData { is_p2p: true, network_id: eee.network_id.load(Ordering::Relaxed), ttl: SDLAN_DEFAULT_TTL as u32, src_mac: Vec::from(src_mac), dst_mac: Vec::from(mac), data: Bytes::from(encrypted), session_token: eee.session_token.get(), identity_id: eee.identity_id.load(), }; let msg = encode_to_udp_message(Some(data), PacketType::Data as u8).unwrap(); let size = msg.len(); send_packet_to_net(eee, mac, &msg, pkt_size as u64).await; } None => { header.unsplit(data); eee.arp_table.add_to_arp_wait_list(dstip, header); debug!( "find ip: {:?} => {:?}", src.to_be_bytes(), dstip.to_be_bytes() ); debug!("no mac found for ip {:?}, sending arp request", dstip.to_be_bytes()); // let _ = eee.send_arp_request(dstip, dstip).await; if eee.device_config.contains(&Ipv4Addr::from_bits(dstip)) { let _ = eee.send_arp_request(dstip, dstip).await; } else { if let Some((_, real_ip)) = eee.route_table.lookup(dstip) { let real_ip = u32::from_be_bytes(real_ip.octets()); let _ = eee.send_arp_request(dstip, real_ip).await; } } } } } Err(e) => { error!("failed to parse ip packet: {}", e.to_string()); } } Ok(()) } } pub fn get_install_channel() -> String { "linux".to_owned() } fn check_has_resolvectl() -> bool { let res = Command::new("resolvectl") .arg("status") .output(); if let Ok(_) = res { true } else { false } } fn add_dns_route(gw: &str) -> Result<()>{ Command::new("route") .arg("add") .arg("-host") .arg("100.100.100.100") .arg("gw") .arg(gw) .output()?; Ok(()) } fn add_resolvectl( name: &str, network_domain: &str, ) -> Result<()>{ Command::new("resolvectl") .arg("dns") .arg(name) .arg("100.100.100.100") .output()?; Command::new("resolvectl") .arg("domain") .arg(name) .arg(format!("~{}", network_domain)) .output()?; Ok(()) } fn set_dns( iface: &Iface, name: &str, network_domain: &str, gw: &str ) -> Result<()> { if iface.has_resolvectl { add_resolvectl(name, network_domain)?; } else { backup_resolv_conf()?; modify_resolv_conf(&vec!["100.100.100.100".to_owned()], network_domain, true)?; } add_dns_route(gw)?; Ok(()) } pub fn restore_dns() -> Result<()> { let eee = get_edge(); if !eee.device.has_resolvectl { // should restore /etc/resolv.conf restore_resolv_conf()?; } Ok(()) } /// 修改 /etc/resolv.conf 中的 nameserver 条目 /// /// - `new_nameservers`: 新的 nameserver 列表(IPv4/IPv6 字符串) /// - `keep_other_ns`: 是否保留原有的 nameserver(true = 追加到新列表后,false = 完全替换) pub fn modify_resolv_conf(new_nameservers: &[String], search_domain: &str, keep_other_ns: bool) -> Result<()> { let path = Path::new(RESOLV_FILE); if !path.exists() { return Err(SDLanError::IOError(format!("{} does not exists", RESOLV_FILE))); } // 读取原文件权限和元数据 let metadata = fs::metadata(path)?; let perms = fs::Permissions::from_mode(metadata.mode()); let uid = metadata.uid(); let gid = metadata.gid(); // 读取所有行 let file = fs::File::open(path)?; let reader = BufReader::new(file); let mut lines = Vec::new(); let mut inserted = false; let mut encounted_nameserver = false; let mut search_added = false; for line in reader.lines() { let line = line?; let trimmed = line.trim(); if trimmed.starts_with("nameserver ") { // 提取 IP encounted_nameserver = true; if keep_other_ns { lines.push(line); } // 如果不保留原有 nameserver,就不加入 lines } else { if encounted_nameserver { if !inserted { inserted = true; for new in new_nameservers { lines.push(format!("nameserver {}", new.clone())); } } } // 保留非 nameserver 行(注释、search、options 等) if trimmed.starts_with("search ") { lines.push(format!("{} {}", trimmed, search_domain)); search_added = true; } else { lines.push(line); } } } if !search_added { lines.push(format!("search {}", search_domain)); } // 原子写入:先写临时文件 let tmp_dir = Path::new("/etc"); let tmp_path = tmp_dir.join("resolv.conf.tmp"); let mut tmp_file = fs::File::create(&tmp_path)?; for l in &lines { writeln!(tmp_file, "{}", l)?; } tmp_file.flush()?; // 设置权限 fs::set_permissions(&tmp_path, perms)?; #[cfg(unix)] { use std::os::unix::fs::chown; chown(&tmp_path, Some(uid), Some(gid))?; } // 原子替换 fs::rename(&tmp_path, path)?; Ok(()) } /// 备份 /etc/resolv.conf 到指定路径 fn backup_resolv_conf() -> Result<()> { let src = Path::new(RESOLV_FILE); let dst = Path::new(RESOLV_FILE_BACKUP); if !src.exists() { return Err(SDLanError::IOError(format!("{} does not exists", RESOLV_FILE))); // anyhow::bail!("Source /etc/resolv.conf does not exist"); } // 如果目标已存在,可选择覆盖或跳过(这里覆盖) if dst.exists() { fs::remove_file(dst)?; } fs::copy(src, dst)?; // 保留原权限 let metadata = fs::metadata(src)?; let permissions = fs::Permissions::from_mode(metadata.mode()); fs::set_permissions(dst, permissions)?; // 保留所有者(需要 root 权限,否则会失败) #[cfg(unix)] { use std::os::unix::fs::chown; let uid = metadata.uid(); let gid = metadata.gid(); chown(dst, Some(uid), Some(gid))?; } Ok(()) } /// 从备份路径恢复 /etc/resolv.conf fn restore_resolv_conf() -> Result<()> { let src = Path::new(RESOLV_FILE_BACKUP); let dst = Path::new(RESOLV_FILE); if !src.exists() { return Err(SDLanError::IOError(format!("{} does not exists", RESOLV_FILE_BACKUP))); } // 如果目标是符号链接,先删除链接再复制(避免写入到链接指向位置) if dst.is_symlink() { fs::remove_file(dst)?; } else if dst.exists() { fs::remove_file(dst)?; } fs::copy(src, dst)?; // 保留备份文件的权限 let metadata = fs::metadata(src)?; let permissions = fs::Permissions::from_mode(metadata.mode()); fs::set_permissions(dst, permissions)?; #[cfg(unix)] { use std::os::unix::fs::chown; let uid = metadata.uid(); let gid = metadata.gid(); chown(dst, Some(uid), Some(gid))?; } Ok(()) } pub fn del_route(net: &Ipv4Net, gw: &Ipv4Addr) -> Result<()> { let res = Command::new("route") .arg("del") .arg("-net") .arg(net.to_string()) .arg("gw") .arg(gw.to_string()) .output()?; Ok(()) } pub fn add_route(net: &Ipv4Net, gw: &Ipv4Addr) -> Result<()> { let res = Command::new("route") .arg("add") .arg("-net") .arg(net.to_string()) .arg("gw") .arg(gw.to_string()) .output()?; Ok(()) } pub fn set_disallow_routing() { let _ = Command::new("sysctl") .arg("-w") .arg("net.ipv4.ip_forward=0") .output(); let _ = Command::new("iptables") .arg("-t") .arg("nat") .arg("-D") .arg("POSTROUTING") .arg("-j") .arg("MASQUERADE") .output(); } pub fn set_allow_routing() { let _ = Command::new("sysctl") .arg("-w") .arg("net.ipv4.ip_forward=1") .output(); let _ = Command::new("iptables") .arg("-t") .arg("nat") .arg("-D") .arg("POSTROUTING") .arg("-j") .arg("MASQUERADE") .output(); let _ = Command::new("iptables") .arg("-t") .arg("nat") .arg("-A") .arg("POSTROUTING") .arg("-j") .arg("MASQUERADE") .output(); } #[cfg(feature = "tun")] pub async fn arp_reply_arrived(edge: &Node, data: SdlArpResponse) { debug!("got arp response: {:?}", data); if data.target_mac.len() != 6 { // invalid target_mac error!("invalid target_mac: {:?}, ip={}", data.target_mac, ip_to_string(&data.target_ip)); return; } let ip = data.target_ip; let mac = data.target_mac.try_into().unwrap(); edge.arp_table.arp_arrived(ip, mac).await; } #[cfg(not(feature = "tun"))] pub async fn arp_reply_arrived(edge: &Node, data: SdlArpResponse) { debug!("got arp response: {:?}", data); if data.target_mac.len() != 6 { // invalid target_mac error!("invalid target_mac: {:?}, ip={}", data.target_mac, ip_to_string(&data.target_ip)); return; } // TODO: construct the arp reply, and write to tun; let src_mac = data.target_mac.try_into().unwrap(); let dst_mac = edge.device_config.get_mac(); let dst_ip = edge.device_config.get_ip(); let src_ip = data.origin_ip; let hdr = ArpHdr{ ethhdr: EthHdr { dest: dst_mac, src: src_mac, eth_type: 0x0806, }, hwtype: 0x0001, protocol: 0x0800, hwlen: 6, protolen: 4, opcode: ARP_REPLY, shwaddr: src_mac, sipaddr: [((src_ip >> 16) as u16) & 0xffff, (src_ip as u16) & 0xffff], dhwaddr: dst_mac, dipaddr: [((dst_ip >> 16) & 0x0000ffff) as u16, (dst_ip & 0x0000ffff) as u16] }; let data = hdr.marshal_to_bytes(); if let Err(_e) = edge.device.send(&data) { error!("failed to write arp response to device"); } }