Browse Source

Add the packet2pcap utility.

whitequark 7 years ago
parent
commit
08186129cd
3 changed files with 79 additions and 3 deletions
  1. 5 0
      Cargo.toml
  2. 3 3
      src/phy/pcap_writer.rs
  3. 71 0
      utils/packet2pcap.rs

+ 5 - 0
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"]

+ 3 - 3
src/phy/pcap_writer.rs

@@ -92,15 +92,15 @@ impl<T: AsRef<PcapSink>> PcapSink for T {
 }
 
 #[cfg(feature = "std")]
-impl<T: AsMut<Write>> PcapSink for RefCell<T> {
+impl<T: Write> PcapSink for RefCell<T> {
     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")
     }
 }
 

+ 71 - 0
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<String> = 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);
+        }
+    }
+}