From d4fa764b235300eebcfa84054c2fc492bb4c3def Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 30 Jan 2018 03:13:11 +0000 Subject: [PATCH] Add the packet2pcap utility. --- Cargo.toml | 5 +++ src/phy/pcap_writer.rs | 6 ++-- utils/packet2pcap.rs | 71 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 utils/packet2pcap.rs diff --git a/Cargo.toml b/Cargo.toml index 27eabf9..9284e7d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,6 +42,11 @@ default = [ "socket-raw", "socket-icmp", "socket-udp", "socket-tcp" ] +[[example]] +name = "packet2pcap" +path = "utils/packet2pcap.rs" +required-features = ["std"] + [[example]] name = "tcpdump" required-features = ["std", "phy-raw_socket", "proto-ipv4"] diff --git a/src/phy/pcap_writer.rs b/src/phy/pcap_writer.rs index 3a217c8..20778d9 100644 --- a/src/phy/pcap_writer.rs +++ b/src/phy/pcap_writer.rs @@ -92,15 +92,15 @@ impl> PcapSink for T { } #[cfg(feature = "std")] -impl> PcapSink for RefCell { +impl PcapSink for RefCell { fn write(&self, data: &[u8]) { - self.borrow_mut().as_mut().write_all(data).expect("cannot write") + self.borrow_mut().write_all(data).expect("cannot write") } fn packet(&self, timestamp: u64, packet: &[u8]) { self.packet_header(timestamp, packet.len()); PcapSink::write(self, packet); - self.borrow_mut().as_mut().flush().expect("cannot flush") + self.borrow_mut().flush().expect("cannot flush") } } diff --git a/utils/packet2pcap.rs b/utils/packet2pcap.rs new file mode 100644 index 0000000..87c8f66 --- /dev/null +++ b/utils/packet2pcap.rs @@ -0,0 +1,71 @@ +extern crate smoltcp; +extern crate getopts; + +use std::cell::RefCell; +use std::io::{self, Read, Write}; +use std::path::Path; +use std::fs::File; +use std::env; +use std::process::exit; +use smoltcp::phy::{PcapLinkType, PcapSink}; +use getopts::Options; + +fn convert(packet_filename: &Path, pcap_filename: &Path, link_type: PcapLinkType) + -> io::Result<()> { + let mut packet_file = File::open(packet_filename)?; + let mut packet = Vec::new(); + packet_file.read_to_end(&mut packet)?; + + let pcap = RefCell::new(Vec::new()); + PcapSink::global_header(&pcap, link_type); + PcapSink::packet(&pcap, 0, &packet[..]); + + let mut pcap_file = File::create(pcap_filename)?; + pcap_file.write_all(&pcap.borrow()[..])?; + + Ok(()) +} + +fn print_usage(program: &str, opts: Options) { + let brief = format!("Usage: {} [options] INPUT OUTPUT", program); + print!("{}", opts.usage(&brief)); +} + +fn main() { + let args: Vec = env::args().collect(); + let program = args[0].clone(); + + let mut opts = Options::new(); + opts.optflag("h", "help", "print this help menu"); + opts.optopt("t", "link-type", "set link type (one of: ethernet ip)", "TYPE"); + + let matches = match opts.parse(&args[1..]) { + Ok(m) => m, + Err(e) => { + eprintln!("{}", e); + return + } + }; + + let link_type = + match matches.opt_str("t").as_ref().map(|s| &s[..]) { + Some("ethernet") => Some(PcapLinkType::Ethernet), + Some("ip") => Some(PcapLinkType::Ip), + _ => None + }; + + if matches.opt_present("h") || matches.free.len() != 2 || link_type.is_none() { + print_usage(&program, opts); + return + } + + match convert(Path::new(&matches.free[0]), + Path::new(&matches.free[1]), + link_type.unwrap()) { + Ok(()) => (), + Err(e) => { + eprintln!("Cannot convert packet to pcap: {}", e); + exit(1); + } + } +}