Add the packet2pcap utility.
parent
6b3f103c05
commit
d4fa764b23
|
@ -42,6 +42,11 @@ default = [
|
||||||
"socket-raw", "socket-icmp", "socket-udp", "socket-tcp"
|
"socket-raw", "socket-icmp", "socket-udp", "socket-tcp"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[example]]
|
||||||
|
name = "packet2pcap"
|
||||||
|
path = "utils/packet2pcap.rs"
|
||||||
|
required-features = ["std"]
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "tcpdump"
|
name = "tcpdump"
|
||||||
required-features = ["std", "phy-raw_socket", "proto-ipv4"]
|
required-features = ["std", "phy-raw_socket", "proto-ipv4"]
|
||||||
|
|
|
@ -92,15 +92,15 @@ impl<T: AsRef<PcapSink>> PcapSink for T {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl<T: AsMut<Write>> PcapSink for RefCell<T> {
|
impl<T: Write> PcapSink for RefCell<T> {
|
||||||
fn write(&self, data: &[u8]) {
|
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]) {
|
fn packet(&self, timestamp: u64, packet: &[u8]) {
|
||||||
self.packet_header(timestamp, packet.len());
|
self.packet_header(timestamp, packet.len());
|
||||||
PcapSink::write(self, packet);
|
PcapSink::write(self, packet);
|
||||||
self.borrow_mut().as_mut().flush().expect("cannot flush")
|
self.borrow_mut().flush().expect("cannot flush")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue