pcap_parser/pcapng/
reader.rs

1use crate::blocks::PcapBlockOwned;
2use crate::error::PcapError;
3use crate::pcapng::*;
4use crate::traits::PcapReaderIterator;
5use circular::Buffer;
6use nom::{Needed, Offset};
7use std::io::Read;
8
9/// Parsing iterator over pcap-ng data (streaming version)
10///
11/// ## Pcap-NG Reader
12///
13/// This reader is a streaming parser based on a circular buffer, which means memory
14/// usage is constant, and that it can be used to parse huge files or infinite streams.
15/// It creates an abstraction over any input providing the `Read` trait, and takes care
16/// of managing the circular buffer to provide an iterator-like interface.
17///
18/// The first call to `next` should return the a Section Header Block (SHB), marking the start of a
19/// new section.
20/// For each section, calls to `next` will return blocks, some of them containing data (SPB, EPB),
21/// and others containing information (IDB, NRB, etc.).
22///
23/// Some information must be stored (for ex. the data link type from the IDB) to be able to parse
24/// following block contents. Usually, a list of interfaces must be stored, with the data link type
25/// and capture length, for each section. These values are used when parsing Enhanced Packet Blocks
26/// (which gives an interface ID - the index, starting from 0) and Simple Packet Blocks (which
27/// assume an interface index of 0).
28///
29/// The size of the circular buffer has to be big enough for at least one complete block. Using a
30/// larger value (at least 65k) is advised to avoid frequent reads and buffer shifts.
31///
32/// **There are precautions to take when reading multiple blocks before consuming data. See
33/// [`PcapReaderIterator`] for details.**
34///
35/// ## Example
36///
37/// ```rust
38/// use pcap_parser::*;
39/// use pcap_parser::traits::PcapReaderIterator;
40/// use std::fs::File;
41///
42/// # let path = "assets/test001-le.pcapng";
43/// let file = File::open(path).unwrap();
44/// let mut num_blocks = 0;
45/// let mut reader = PcapNGReader::new(65536, file).expect("PcapNGReader");
46/// let mut if_linktypes = Vec::new();
47/// let mut last_incomplete_index = 0;
48/// loop {
49///     match reader.next() {
50///         Ok((offset, block)) => {
51///             println!("got new block");
52///             num_blocks += 1;
53///             match block {
54///             PcapBlockOwned::NG(Block::SectionHeader(ref _shb)) => {
55///                 // starting a new section, clear known interfaces
56///                 if_linktypes = Vec::new();
57///             },
58///             PcapBlockOwned::NG(Block::InterfaceDescription(ref idb)) => {
59///                 if_linktypes.push(idb.linktype);
60///             },
61///             PcapBlockOwned::NG(Block::EnhancedPacket(ref epb)) => {
62///                 assert!((epb.if_id as usize) < if_linktypes.len());
63///                 let linktype = if_linktypes[epb.if_id as usize];
64///                 #[cfg(feature="data")]
65///                 let res = pcap_parser::data::get_packetdata(epb.data, linktype, epb.caplen as usize);
66///             },
67///             PcapBlockOwned::NG(Block::SimplePacket(ref spb)) => {
68///                 assert!(if_linktypes.len() > 0);
69///                 let linktype = if_linktypes[0];
70///                 let blen = (spb.block_len1 - 16) as usize;
71///                 #[cfg(feature="data")]
72///                 let res = pcap_parser::data::get_packetdata(spb.data, linktype, blen);
73///             },
74///             PcapBlockOwned::NG(_) => {
75///                 // can be statistics (ISB), name resolution (NRB), etc.
76///                 eprintln!("unsupported block");
77///             },
78///             PcapBlockOwned::Legacy(_)
79///             | PcapBlockOwned::LegacyHeader(_) => unreachable!(),
80///             }
81///             reader.consume(offset);
82///         },
83///         Err(PcapError::Eof) => break,
84///         Err(PcapError::Incomplete(_)) => {
85///             if last_incomplete_index == num_blocks {
86///                 eprintln!("Could not read complete data block.");
87///                 eprintln!("Hint: the reader buffer size may be too small, or the input file may be truncated.");
88///                 break;
89///             }
90///             last_incomplete_index = num_blocks;
91///             reader.refill().expect("Could not refill reader");
92///             continue;
93///         },
94///         Err(e) => panic!("error while reading: {:?}", e),
95///     }
96/// }
97/// println!("num_blocks: {}", num_blocks);
98/// ```
99pub struct PcapNGReader<R>
100where
101    R: Read,
102{
103    info: CurrentSectionInfo,
104    reader: R,
105    buffer: Buffer,
106    consumed: usize,
107    reader_exhausted: bool,
108}
109
110impl<R> PcapNGReader<R>
111where
112    R: Read,
113{
114    /// Creates a new `PcapNGReader<R>` with the provided buffer capacity.
115    pub fn new(capacity: usize, reader: R) -> Result<PcapNGReader<R>, PcapError<&'static [u8]>> {
116        let buffer = Buffer::with_capacity(capacity);
117        Self::from_buffer(buffer, reader)
118    }
119    /// Creates a new `PcapNGReader<R>` using the provided `Buffer`.
120    pub fn from_buffer(
121        mut buffer: Buffer,
122        mut reader: R,
123    ) -> Result<PcapNGReader<R>, PcapError<&'static [u8]>> {
124        let sz = reader.read(buffer.space()).or(Err(PcapError::ReadError))?;
125        buffer.fill(sz);
126        // just check that first block is a valid one
127        let (_rem, _shb) = match parse_sectionheaderblock(buffer.data()) {
128            Ok((r, h)) => Ok((r, h)),
129            Err(nom::Err::Error(e)) | Err(nom::Err::Failure(e)) => Err(e.to_owned_vec()),
130            Err(nom::Err::Incomplete(Needed::Size(n))) => Err(PcapError::Incomplete(n.into())),
131            Err(nom::Err::Incomplete(Needed::Unknown)) => Err(PcapError::Incomplete(0)),
132        }?;
133        let info = CurrentSectionInfo::default();
134        // do not consume
135        Ok(PcapNGReader {
136            info,
137            reader,
138            buffer,
139            consumed: 0,
140            reader_exhausted: false,
141        })
142    }
143}
144
145impl<R> PcapReaderIterator for PcapNGReader<R>
146where
147    R: Read,
148{
149    fn next(&mut self) -> Result<(usize, PcapBlockOwned<'_>), PcapError<&[u8]>> {
150        // Return EOF if
151        // 1) all bytes have been read
152        // 2) no more data is available
153        if self.buffer.available_data() == 0
154            && (self.buffer.position() == 0 && self.reader_exhausted)
155        {
156            return Err(PcapError::Eof);
157        }
158        let data = self.buffer.data();
159        let parse = if self.info.big_endian {
160            parse_block_be
161        } else {
162            parse_block_le
163        };
164        match parse(data) {
165            Ok((rem, b)) => {
166                let offset = data.offset(rem);
167                if let Block::SectionHeader(ref shb) = b {
168                    self.info.big_endian = shb.big_endian();
169                }
170                Ok((offset, PcapBlockOwned::from(b)))
171            }
172            Err(nom::Err::Error(e)) | Err(nom::Err::Failure(e)) => Err(e),
173            Err(nom::Err::Incomplete(n)) => {
174                if self.reader_exhausted {
175                    // expected more bytes but reader is EOF, truncated pcap?
176                    Err(PcapError::UnexpectedEof)
177                } else {
178                    match n {
179                        Needed::Size(n) => {
180                            if self.buffer.available_data() + usize::from(n)
181                                >= self.buffer.capacity()
182                            {
183                                Err(PcapError::BufferTooSmall)
184                            } else {
185                                Err(PcapError::Incomplete(n.into()))
186                            }
187                        }
188                        Needed::Unknown => Err(PcapError::Incomplete(0)),
189                    }
190                }
191            }
192        }
193    }
194    fn consume(&mut self, offset: usize) {
195        self.consumed += offset;
196        self.buffer.consume(offset);
197    }
198    fn consume_noshift(&mut self, offset: usize) {
199        self.consumed += offset;
200        self.buffer.consume_noshift(offset);
201    }
202    fn consumed(&self) -> usize {
203        self.consumed
204    }
205    fn refill(&mut self) -> Result<(), PcapError<&[u8]>> {
206        self.buffer.shift();
207        let space = self.buffer.space();
208        // check if available space is empty, so we can distinguish
209        // a read() returning 0 because of EOF or because we requested 0
210        if space.is_empty() {
211            return Ok(());
212        }
213        let sz = self.reader.read(space).or(Err(PcapError::ReadError))?;
214        self.reader_exhausted = sz == 0;
215        self.buffer.fill(sz);
216        Ok(())
217    }
218    fn position(&self) -> usize {
219        self.buffer.position()
220    }
221    fn grow(&mut self, new_size: usize) -> bool {
222        self.buffer.grow(new_size)
223    }
224    fn data(&self) -> &[u8] {
225        self.buffer.data()
226    }
227    fn reader_exhausted(&self) -> bool {
228        self.reader_exhausted
229    }
230}