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}