1 use getopts::Options;
2 use smoltcp::phy::{PcapLinkType, PcapSink};
3 use smoltcp::time::Instant;
4 use std::env;
5 use std::fs::File;
6 use std::io::{self, Read};
7 use std::path::Path;
8 use std::process::exit;
9
convert( packet_filename: &Path, pcap_filename: &Path, link_type: PcapLinkType, ) -> io::Result<()>10 fn convert(
11 packet_filename: &Path,
12 pcap_filename: &Path,
13 link_type: PcapLinkType,
14 ) -> io::Result<()> {
15 let mut packet_file = File::open(packet_filename)?;
16 let mut packet = Vec::new();
17 packet_file.read_to_end(&mut packet)?;
18
19 let mut pcap_file = File::create(pcap_filename)?;
20 PcapSink::global_header(&mut pcap_file, link_type);
21 PcapSink::packet(&mut pcap_file, Instant::from_millis(0), &packet[..]);
22
23 Ok(())
24 }
25
print_usage(program: &str, opts: Options)26 fn print_usage(program: &str, opts: Options) {
27 let brief = format!("Usage: {program} [options] INPUT OUTPUT");
28 print!("{}", opts.usage(&brief));
29 }
30
main()31 fn main() {
32 let args: Vec<String> = env::args().collect();
33 let program = args[0].clone();
34
35 let mut opts = Options::new();
36 opts.optflag("h", "help", "print this help menu");
37 opts.optopt(
38 "t",
39 "link-type",
40 "set link type (one of: ethernet ip)",
41 "TYPE",
42 );
43
44 let matches = match opts.parse(&args[1..]) {
45 Ok(m) => m,
46 Err(e) => {
47 eprintln!("{e}");
48 return;
49 }
50 };
51
52 let link_type = match matches.opt_str("t").as_ref().map(|s| &s[..]) {
53 Some("ethernet") => Some(PcapLinkType::Ethernet),
54 Some("ip") => Some(PcapLinkType::Ip),
55 _ => None,
56 };
57
58 if matches.opt_present("h") || matches.free.len() != 2 || link_type.is_none() {
59 print_usage(&program, opts);
60 return;
61 }
62
63 match convert(
64 Path::new(&matches.free[0]),
65 Path::new(&matches.free[1]),
66 link_type.unwrap(),
67 ) {
68 Ok(()) => (),
69 Err(e) => {
70 eprintln!("Cannot convert packet to pcap: {e}");
71 exit(1);
72 }
73 }
74 }
75