extern crate bytepack;
#[macro_use]
extern crate bytepack_derive;
mod def;
pub mod read;
pub mod write;
pub use def::Linktype;
use std::time::SystemTime;
use std::error;
use std::error::Error;
use std::fmt;
use std::io;
#[derive(Eq,PartialEq,Debug)]
pub struct CapturedPacket<'a> {
pub time: SystemTime,
pub data: &'a [u8],
pub orig_len: usize,
}
#[derive(Debug)]
pub enum PcapError {
Io(io::Error),
InvalidPacketSize,
InvalidDate,
InvalidFileHeader,
}
impl From<io::Error> for PcapError {
fn from(err: io::Error) -> PcapError {
PcapError::Io(err)
}
}
impl From<std::time::SystemTimeError> for PcapError {
fn from(_: std::time::SystemTimeError) -> PcapError {
PcapError::InvalidDate
}
}
impl fmt::Display for PcapError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.description())
}
}
impl error::Error for PcapError {
fn description(&self) -> &str {
match *self {
PcapError::Io(ref err) => err.description(),
PcapError::InvalidPacketSize => "Parsed packet has an invalid size.",
PcapError::InvalidDate => "Parsed packet has an invalid date.",
PcapError::InvalidFileHeader => "The pcap file has an invalid/unknown file header.",
}
}
fn cause(&self) -> Option<&error::Error> {
match *self {
PcapError::Io(ref err) => Some(err),
_ => None,
}
}
}
#[cfg(test)]
mod test {
use std::io::Write;
use super::write::{PcapWriter, WriteOptions};
use super::read::PcapReader;
use super::{CapturedPacket, Linktype};
use ::std::time::{Duration, UNIX_EPOCH};
extern crate rand;
use self::rand::Rng;
fn gen_packet_data() -> Vec<Vec<u8>> {
let mut rng = rand::thread_rng();
(0..10)
.map(|_| {
let size = rng.gen_range::<usize>(0, 2000);
rng.gen_iter::<u8>().take(size).collect()
})
.collect()
}
fn gen_packets<'a>(contents: &'a Vec<Vec<u8>>, snaplen: usize) -> Vec<CapturedPacket<'a>> {
let mut rng = rand::thread_rng();
contents.iter()
.map(|data| {
let s = rng.gen_range::<u64>(0, u64::from(u32::max_value()) + 1);
let ns = rng.gen_range::<u32>(0, 1_000_000_000);
CapturedPacket {
time: UNIX_EPOCH + Duration::new(s, ns),
data: &data.chunks(snaplen).next().unwrap(),
orig_len: data.len(),
}
})
.collect()
}
fn write_packets<W: Write>(mut writer: PcapWriter<W>, packets: &[CapturedPacket]) -> W {
for p in &packets[..5] {
writer.write(&p).unwrap();
}
writer.take_writer()
}
#[test]
fn read_write() {
let contents = gen_packet_data();
let packets = gen_packets(&contents, 1000);
let opts = WriteOptions {
snaplen: 1000,
linktype: Linktype::NULL.into(),
};
let mut buf = write_packets(PcapWriter::new(Vec::new(), opts).unwrap(), &packets[..5]);
buf = write_packets(PcapWriter::append(buf, opts).unwrap(), &packets[5..]);
let mut reader = PcapReader::new(buf.as_slice()).unwrap();
assert_eq!(reader.get_linktype(), Linktype::NULL.into());
assert_eq!(reader.get_snaplen(), 1000);
let mut i = 0;
while let Some(packet) = reader.next().unwrap() {
assert_eq!(packet, packets[i]);
i += 1;
}
assert_eq!(i, packets.len());
}
}