pcap_parser/pcapng/
section.rs

1use nom::{
2    combinator::complete,
3    error::{make_error, ErrorKind},
4    multi::{many0, many1},
5    Err, IResult, Parser as _,
6};
7
8use crate::{PcapBlock, PcapError};
9
10use super::*;
11
12/// A Section (including all blocks) from a PcapNG file
13pub struct Section<'a> {
14    /// The list of blocks
15    pub blocks: Vec<Block<'a>>,
16    /// True if encoding is big-endian
17    pub big_endian: bool,
18}
19
20impl<'a> Section<'a> {
21    /// Returns the section header
22    pub fn header(&self) -> Option<&SectionHeaderBlock<'_>> {
23        if let Some(Block::SectionHeader(ref b)) = self.blocks.first() {
24            Some(b)
25        } else {
26            None
27        }
28    }
29
30    /// Returns an iterator over the section blocks
31    pub fn iter(&'a self) -> SectionBlockIterator<'a> {
32        SectionBlockIterator {
33            section: self,
34            index_block: 0,
35        }
36    }
37
38    /// Returns an iterator over the interface description blocks
39    pub fn iter_interfaces(&'a self) -> InterfaceBlockIterator<'a> {
40        InterfaceBlockIterator {
41            section: self,
42            index_block: 0,
43        }
44    }
45}
46
47// Non-consuming iterator over blocks of a Section
48pub struct SectionBlockIterator<'a> {
49    section: &'a Section<'a>,
50    index_block: usize,
51}
52
53impl<'a> Iterator for SectionBlockIterator<'a> {
54    type Item = PcapBlock<'a>;
55
56    fn next(&mut self) -> Option<PcapBlock<'a>> {
57        let block = self.section.blocks.get(self.index_block);
58        self.index_block += 1;
59        block.map(PcapBlock::from)
60    }
61}
62
63// Non-consuming iterator over interface description blocks of a Section
64pub struct InterfaceBlockIterator<'a> {
65    section: &'a Section<'a>,
66    index_block: usize,
67}
68
69impl<'a> Iterator for InterfaceBlockIterator<'a> {
70    type Item = &'a InterfaceDescriptionBlock<'a>;
71
72    fn next(&mut self) -> Option<&'a InterfaceDescriptionBlock<'a>> {
73        if self.index_block >= self.section.blocks.len() {
74            return None;
75        }
76        for block in &self.section.blocks[self.index_block..] {
77            self.index_block += 1;
78            if let Block::InterfaceDescription(ref idb) = block {
79                return Some(idb);
80            }
81        }
82        None
83    }
84}
85
86/// Parse any block from a section (little-endian)
87pub fn parse_section_content_block_le(i: &[u8]) -> IResult<&[u8], Block<'_>, PcapError<&[u8]>> {
88    let (rem, block) = parse_block_le(i)?;
89    match block {
90        Block::SectionHeader(_) => Err(Err::Error(make_error(i, ErrorKind::Tag))),
91        _ => Ok((rem, block)),
92    }
93}
94
95/// Parse any block from a section (big-endian)
96pub fn parse_section_content_block_be(i: &[u8]) -> IResult<&[u8], Block<'_>, PcapError<&[u8]>> {
97    let (rem, block) = parse_block_be(i)?;
98    match block {
99        Block::SectionHeader(_) => Err(Err::Error(make_error(i, ErrorKind::Tag))),
100        _ => Ok((rem, block)),
101    }
102}
103
104/// Parse one section (little or big endian)
105pub fn parse_section(i: &[u8]) -> IResult<&[u8], Section<'_>, PcapError<&[u8]>> {
106    let (rem, shb) = parse_sectionheaderblock(i)?;
107    let big_endian = shb.big_endian();
108    let (rem, mut b) = if big_endian {
109        many0(complete(parse_section_content_block_be)).parse(rem)?
110    } else {
111        many0(complete(parse_section_content_block_le)).parse(rem)?
112    };
113    let mut blocks = Vec::with_capacity(b.len() + 1);
114    blocks.push(Block::SectionHeader(shb));
115    blocks.append(&mut b);
116    let section = Section { blocks, big_endian };
117    Ok((rem, section))
118}
119
120/// Parse multiple sections (little or big endian)
121#[inline]
122pub fn parse_sections(i: &[u8]) -> IResult<&[u8], Vec<Section<'_>>, PcapError<&[u8]>> {
123    many1(complete(parse_section)).parse(i)
124}