use ferranet::Channel;
#[tokio::main]
async fn main() -> ferranet::Result<()> {
let iface = std::env::args().nth(1).unwrap_or_else(|| {
eprintln!("usage: sniff <interface>");
std::process::exit(2);
});
let (_tx, mut rx) = Channel::builder(&iface).promiscuous(true).build_async()?;
println!("sniffing {iface} (Ctrl-C to stop)…");
loop {
let block = rx.recv_block().await?;
for frame in block.frames() {
let data = frame.data();
let dst = data.get(0..6).map(hex).unwrap_or_default();
let src = data.get(6..12).map(hex).unwrap_or_default();
println!(
"{:5} bytes {} -> {} type={:?} vlan={:?}",
frame.data().len(),
src,
dst,
frame.packet_type(),
frame.vlan(),
);
}
}
}
fn hex(bytes: &[u8]) -> String {
bytes.iter().map(|b| format!("{b:02x}")).collect::<Vec<_>>().join(":")
}