1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
use std::io;
use std::time::UNIX_EPOCH;
use super::def;
use super::PcapError;
use super::CapturedPacket;
use bytepack::Packer;
#[derive(Copy,Clone)]
pub struct WriteOptions {
pub snaplen: usize,
pub linktype: u32,
}
pub struct PcapWriter<W: io::Write> {
writer: W,
opts: WriteOptions,
}
impl<W: io::Write> PcapWriter<W> {
pub fn new(mut writer: W, opts: WriteOptions) -> Result<Self, PcapError> {
let fh = def::PcapFileHeaderInFile::new(opts.snaplen, opts.linktype)
.ok_or(PcapError::InvalidFileHeader)?;
writer.pack(fh)?;
PcapWriter::append(writer, opts)
}
pub fn append(writer: W, opts: WriteOptions) -> Result<Self, PcapError> {
Ok(PcapWriter {
writer: writer,
opts: opts,
})
}
pub fn write(&mut self, packet: &CapturedPacket) -> Result<(), PcapError> {
let duration = packet.time.duration_since(UNIX_EPOCH)?;
let sec = duration.as_secs() as u32;
let nsec = duration.subsec_nanos();
if sec as u64 != duration.as_secs() {
return Err(PcapError::InvalidDate);
}
let len = packet.data.len() as u32;
let orig_len = packet.orig_len as u32;
if packet.data.len() > self.opts.snaplen || len as usize != packet.data.len() ||
orig_len as usize != packet.orig_len {
return Err(PcapError::InvalidPacketSize);
}
let record_header = def::PcapRecordHeader {
ts_sec: sec,
ts_usec: nsec,
incl_len: len,
orig_len: orig_len,
};
self.writer.pack(record_header)?;
self.writer.write_all(packet.data).map_err(PcapError::from)
}
pub fn flush(&mut self) -> Result<(), io::Error> {
self.writer.flush()
}
pub fn take_writer(self) -> W {
self.writer
}
pub fn get_options(&self) -> WriteOptions {
self.opts
}
}