use std::io;
use super::def;
use super::PcapError;
use super::CapturedPacket;
use bytepack::Unpacker;
pub struct PcapReader<R: io::Read> {
reader: R,
network: u32,
state: Option<PcapState>,
}
struct PcapState {
file_header: def::PcapFileHeader,
packet_buffer: Vec<u8>,
}
impl<R: io::Read> PcapReader<R> {
pub fn new(mut reader: R) -> Result<Self, PcapError> {
let fh = reader.unpack::<def::PcapFileHeaderInFile>()?;
let fh = def::PcapFileHeader::try_from(fh).ok_or(PcapError::InvalidFileHeader)?;
let buffer = vec![0; fh.snaplen.into()];
Ok(PcapReader {
reader: reader,
network: fh.network,
state: Some(PcapState {
file_header: fh,
packet_buffer: buffer,
}),
})
}
pub fn get_linktype(&self) -> u32 {
self.network
}
pub fn get_snaplen(&self) -> usize {
match self.state.as_ref() {
None => 0,
Some(state) => state.packet_buffer.len(),
}
}
#[allow(unknown_lints,should_implement_trait)]
pub fn next(&mut self) -> Result<Option<CapturedPacket>, PcapError> {
if self.state.is_none() {
return Ok(None);
}
let rh = self.reader.unpack::<def::PcapRecordHeader>();
if let Err(e) = rh {
return if e.kind() == io::ErrorKind::UnexpectedEof {
self.state = None;
Ok(None)
} else {
Err(e.into())
};
}
let mut rh = rh.unwrap();
let state = self.state.as_mut().unwrap();
rh.swap_bytes(&state.file_header);
let mut toread = rh.incl_len as usize;
if state.packet_buffer.capacity() < toread {
while toread > state.packet_buffer.capacity() {
let cnt = self.reader.read(state.packet_buffer.as_mut_slice())?;
if cnt == 0 {
return Err(PcapError::InvalidPacketSize);
}
toread -= cnt;
}
self.reader.read_exact(&mut state.packet_buffer[..toread])?;
return Err(PcapError::InvalidPacketSize);
}
let buf = &mut state.packet_buffer[..toread];
self.reader.read_exact(buf)?;
let orig_len = rh.orig_len as usize;
if orig_len as u32 != rh.orig_len {
return Err(PcapError::InvalidPacketSize);
}
if let Some(t) = rh.get_time(&state.file_header) {
Ok(Some(CapturedPacket {
time: t,
data: buf,
orig_len: orig_len,
}))
} else {
Err(PcapError::InvalidDate)
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn format_variations() {
let be_us = [0xa1, 0xb2, 0x3c, 0x4d, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x65, 0x56, 0x50,
0x6e, 0x1a, 0x18, 0x2b, 0x0a, 0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x3c, 0x44, 0x41, 0x54, 0x41];
let be_ns = [0xa1, 0xb2, 0xc3, 0xd4, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x65, 0x56, 0x50,
0x6e, 0x1a, 0x00, 0x06, 0x2f, 0xe2, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x3c, 0x44, 0x41, 0x54, 0x41];
let le_us = [0xd4, 0xc3, 0xb2, 0xa1, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x1a, 0x6e,
0x50, 0x56, 0xe2, 0x2f, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00,
0x00, 0x44, 0x41, 0x54, 0x41];
let le_ns: [u8; 44] = [0x4d, 0x3c, 0xb2, 0xa1, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x65, 0x00,
0x00, 0x00, 0x1a, 0x6e, 0x50, 0x56, 0xd0, 0x0a, 0x2b, 0x18, 0x04,
0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x44, 0x41, 0x54, 0x41];
let raw_pcaps = [be_ns, be_us, le_ns, le_us];
let mut readers: Vec<PcapReader<&[u8]>> = raw_pcaps.iter()
.map(|pcap| PcapReader::new(pcap as &[u8]).unwrap())
.collect();
{
let mut packets = readers.iter_mut().map(|r| r.next().unwrap().unwrap());
let first: CapturedPacket = packets.next().unwrap();
for packet in packets {
assert_eq!(first, packet);
}
}
for r in &mut readers {
assert_eq!(r.next().unwrap(), None);
}
}
}