// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE // Version 2, December 2004 // // Copyleft (ↄ) meh. | http://meh.schizofreni.co // // Everyone is permitted to copy and distribute verbatim or modified // copies of this license document, and changing it is allowed as long // as the name is changed. // // DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE // TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION // // 0. You just DO WHAT THE FUCK YOU WANT TO. use packet::{builder::Builder, icmp, ip, Packet}; use std::io::{Read, Write}; use std::sync::mpsc::Receiver; use tun2::BoxError; fn main() -> Result<(), BoxError> { env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("trace")).init(); let (tx, rx) = std::sync::mpsc::channel(); let handle = ctrlc2::set_handler(move || { tx.send(()).expect("Signal error."); true }) .expect("Error setting Ctrl-C handler"); main_entry(rx)?; handle.join().unwrap(); Ok(()) } fn main_entry(quit: Receiver<()>) -> Result<(), BoxError> { let mut config = tun2::Configuration::default(); config .address((10, 0, 0, 9)) .netmask((255, 255, 255, 0)) .destination((10, 0, 0, 1)) .up(); #[cfg(target_os = "linux")] config.platform_config(|config| { config.ensure_root_privileges(true); }); let dev = tun2::create(&config)?; let (mut reader, mut writer) = dev.split(); let (tx, rx) = std::sync::mpsc::channel(); let _t1 = std::thread::spawn(move || { let mut buf = [0; 4096]; loop { let size = reader.read(&mut buf)?; let pkt = &buf[..size]; use std::io::{Error, ErrorKind::Other}; tx.send(pkt.to_vec()).map_err(|e| Error::new(Other, e))?; } #[allow(unreachable_code)] Ok::<(), std::io::Error>(()) }); let _t2 = std::thread::spawn(move || { loop { if let Ok(pkt) = rx.recv() { match ip::Packet::new(pkt.as_slice()) { Ok(ip::Packet::V4(pkt)) => { if let Ok(icmp) = icmp::Packet::new(pkt.payload()) { if let Ok(icmp) = icmp.echo() { println!("{:?} - {:?}", icmp.sequence(), pkt.destination()); let reply = ip::v4::Builder::default() .id(0x42)? .ttl(64)? .source(pkt.destination())? .destination(pkt.source())? .icmp()? .echo()? .reply()? .identifier(icmp.identifier())? .sequence(icmp.sequence())? .payload(icmp.payload())? .build()?; writer.write_all(&reply[..])?; } } } Err(err) => println!("Received an invalid packet: {:?}", err), _ => { println!("receive pkt {:?}", pkt); } } } } #[allow(unreachable_code)] Ok::<(), packet::Error>(()) }); quit.recv().expect("Quit error."); Ok(()) }