diff options
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 112 |
1 files changed, 110 insertions, 2 deletions
diff --git a/src/main.rs b/src/main.rs index e7a11a9..299e0c4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,111 @@ -fn main() { - println!("Hello, world!"); +use std::io::Read; +use std::net::{SocketAddr, UdpSocket}; +use std::os::fd::{AsRawFd, RawFd}; +use std::sync::{Arc, Mutex}; +use std::thread; +use std::time::Duration; + +use pcap::Capture; +use ringbuf::{HeapRb, Rb}; +use rsdsl_netlinkd::link; +use rsdsl_udpdumpd::Result; + +fn main() -> Result<()> { + let devices = [ + "wlan0", "eth0", "eth0.10", "eth0.20", "eth0.30", "eth0.40", "eth1", "ppp0", "dslite0", + "he6in4", + ]; + + let clt = Arc::new(Mutex::new(None)); + let rb = Arc::new(Mutex::new(HeapRb::new(2000))); + + let sock = UdpSocket::bind("[::]:5555")?; + + let (mut r, w) = os_pipe::pipe()?; + let fd = w.as_raw_fd(); + + for dev in devices { + thread::spawn(move || loop { + if let Err(e) = link::wait_up(dev.to_owned()) { + println!("can't wait for {}: {}", dev, e); + + thread::sleep(Duration::from_secs(8)); + continue; + } + + match capture(dev, fd) { + Ok(_) => unreachable!(), + Err(e) => println!("can't capture on {}: {}", dev, e), + } + + thread::sleep(Duration::from_secs(8)); + }); + } + + let sock2 = sock.try_clone()?; + let clt2 = clt.clone(); + let rb2 = rb.clone(); + thread::spawn(move || loop { + match recv_ctl(&sock2, clt2.clone(), rb2.clone()) { + Ok(_) => {} + Err(e) => println!("can't recv control packets: {}", e), + } + }); + + loop { + let mut buf = [0; 1600]; + let n = r.read(&mut buf)?; + let buf = &buf[..n]; + + rb.lock() + .expect("packet ring buffer mutex is poisoned") + .push_overwrite(buf.to_vec()); + + let mut clt = clt.lock().expect("client address mutex is poisoned"); + if let Some(addr) = *clt { + match sock.send_to(buf, addr) { + Ok(_) => {} + Err(e) => { + *clt = None; + println!("can't send pcap pkt: {}", e); + } + } + } + } +} + +fn recv_ctl( + sock: &UdpSocket, + clt: Arc<Mutex<Option<SocketAddr>>>, + rb: Arc<Mutex<HeapRb<Vec<u8>>>>, +) -> Result<()> { + let mut buf = [0; 0]; + let (_, raddr) = sock.recv_from(&mut buf)?; + + for pkt in rb + .lock() + .expect("packet ring buffer mutex is poisoned") + .iter() + { + sock.send_to(pkt, raddr)?; + } + + *clt.lock().expect("client address mutex is poisoned") = Some(raddr); + + println!("connect {}", raddr); + Ok(()) +} + +fn capture(dev: &str, fd: RawFd) -> Result<()> { + println!("capturing on {}", dev); + + let mut cap = Capture::from_device(dev)?.immediate_mode(true).open()?; + let mut savefile = unsafe { cap.savefile_raw_fd(fd)? }; + + loop { + let pkt = cap.next_packet()?; + + savefile.write(&pkt); + savefile.flush()?; + } } |