pcap_parser/
capture.rs

1use crate::blocks::PcapBlock;
2use crate::error::PcapError;
3use crate::linktype::Linktype;
4use crate::pcap::parse_pcap_header;
5use crate::pcapng::parse_sectionheaderblock;
6use crate::traits::PcapReaderIterator;
7use crate::{LegacyPcapReader, PcapNGReader};
8use circular::Buffer;
9use nom::Needed;
10use std::io::Read;
11
12/// Generic interface for PCAP or PCAPNG file access
13pub trait Capture {
14    fn get_datalink(&self) -> Linktype;
15
16    fn get_snaplen(&self) -> u32;
17
18    fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = PcapBlock<'a>> + 'a>;
19}
20
21/// Get a generic `PcapReaderIterator`, given a `Read` input. The input is probed for pcap-ng first,
22/// then pcap.
23///
24/// ```rust
25/// # use pcap_parser::*;
26/// # use std::fs::File;
27/// #
28/// # let path = "assets/ntp.pcap";
29/// let file = File::open(path).expect("File open failed");
30/// let mut reader = create_reader(65536, file).expect("LegacyPcapReader");
31/// let _ = reader.next();
32/// ```
33pub fn create_reader<'b, R>(
34    capacity: usize,
35    mut reader: R,
36) -> Result<Box<dyn PcapReaderIterator + Send + 'b>, PcapError<&'static [u8]>>
37where
38    R: Read + Send + 'b,
39{
40    let mut buffer = Buffer::with_capacity(capacity);
41    let sz = reader.read(buffer.space()).or(Err(PcapError::ReadError))?;
42    if sz == 0 {
43        return Err(PcapError::Eof);
44    }
45    buffer.fill(sz);
46    // just check that first block is a valid one
47    if parse_sectionheaderblock(buffer.data()).is_ok() {
48        return PcapNGReader::from_buffer(buffer, reader)
49            .map(|r| Box::new(r) as Box<dyn PcapReaderIterator + Send>);
50    }
51    match parse_pcap_header(buffer.data()) {
52        Ok(_) => LegacyPcapReader::from_buffer(buffer, reader)
53            .map(|r| Box::new(r) as Box<dyn PcapReaderIterator + Send>),
54        Err(nom::Err::Incomplete(Needed::Size(n))) => Err(PcapError::Incomplete(n.into())),
55        Err(nom::Err::Incomplete(Needed::Unknown)) => Err(PcapError::Incomplete(0)),
56        _ => Err(PcapError::HeaderNotRecognized),
57    }
58}