pcap_parser/pcapng/
section_header.rs

1use nom::error::ParseError;
2use nom::number::streaming::{be_i64, be_u16, le_i64, le_u16, le_u32};
3use nom::{Err, IResult};
4
5use crate::endianness::{PcapBE, PcapLE};
6use crate::utils::array_ref4;
7use crate::{opt_parse_options, PcapError, PcapNGOption, SHB_MAGIC};
8
9use super::*;
10
11/// The Section Header Block (SHB) identifies the
12/// beginning of a section of the capture capture file.
13///
14/// The
15/// Section Header Block does not contain data but it rather identifies a
16/// list of blocks (interfaces, packets) that are logically correlated.
17#[derive(Debug)]
18pub struct SectionHeaderBlock<'a> {
19    pub block_type: u32,
20    pub block_len1: u32,
21    /// Byte-order magic
22    pub bom: u32,
23    pub major_version: u16,
24    pub minor_version: u16,
25    pub section_len: i64,
26    pub options: Vec<PcapNGOption<'a>>,
27    pub block_len2: u32,
28}
29
30impl<'a> SectionHeaderBlock<'a> {
31    pub fn big_endian(&self) -> bool {
32        self.bom != BOM_MAGIC
33    }
34}
35
36impl<'a> PcapNGBlockParser<'a, PcapBE, SectionHeaderBlock<'a>> for SectionHeaderBlock<'a> {
37    const HDR_SZ: usize = 28;
38    const MAGIC: u32 = SHB_MAGIC;
39
40    fn inner_parse<E: ParseError<&'a [u8]>>(
41        block_type: u32,
42        block_len1: u32,
43        i: &'a [u8],
44        block_len2: u32,
45    ) -> IResult<&'a [u8], SectionHeaderBlock<'a>, E> {
46        // caller function already tested header type(magic) and length
47        // read end of header
48        let (i, bom) = le_u32(i)?;
49        let (i, major_version) = be_u16(i)?;
50        let (i, minor_version) = be_u16(i)?;
51        let (i, section_len) = be_i64(i)?;
52        let (i, options) = opt_parse_options::<PcapBE, E>(i, block_len1 as usize, 28)?;
53        let block = SectionHeaderBlock {
54            block_type,
55            block_len1,
56            bom,
57            major_version,
58            minor_version,
59            section_len,
60            options,
61            block_len2,
62        };
63        Ok((i, block))
64    }
65}
66
67impl<'a> PcapNGBlockParser<'a, PcapLE, SectionHeaderBlock<'a>> for SectionHeaderBlock<'a> {
68    const HDR_SZ: usize = 28;
69    const MAGIC: u32 = SHB_MAGIC;
70
71    fn inner_parse<E: ParseError<&'a [u8]>>(
72        block_type: u32,
73        block_len1: u32,
74        i: &'a [u8],
75        block_len2: u32,
76    ) -> IResult<&'a [u8], SectionHeaderBlock<'a>, E> {
77        // caller function already tested header type(magic) and length
78        // read end of header
79        let (i, bom) = le_u32(i)?;
80        let (i, major_version) = le_u16(i)?;
81        let (i, minor_version) = le_u16(i)?;
82        let (i, section_len) = le_i64(i)?;
83        let (i, options) = opt_parse_options::<PcapLE, E>(i, block_len1 as usize, 28)?;
84        let block = SectionHeaderBlock {
85            block_type,
86            block_len1,
87            bom,
88            major_version,
89            minor_version,
90            section_len,
91            options,
92            block_len2,
93        };
94        Ok((i, block))
95    }
96}
97
98/// Parse a Section Header Block (little endian)
99pub fn parse_sectionheaderblock_le(
100    i: &[u8],
101) -> IResult<&[u8], SectionHeaderBlock, PcapError<&[u8]>> {
102    ng_block_parser::<SectionHeaderBlock, PcapLE, _, _>()(i)
103}
104
105/// Parse a Section Header Block (big endian)
106pub fn parse_sectionheaderblock_be(
107    i: &[u8],
108) -> IResult<&[u8], SectionHeaderBlock, PcapError<&[u8]>> {
109    ng_block_parser::<SectionHeaderBlock, PcapBE, _, _>()(i)
110}
111
112/// Parse a SectionHeaderBlock (little or big endian)
113pub fn parse_sectionheaderblock(i: &[u8]) -> IResult<&[u8], SectionHeaderBlock, PcapError<&[u8]>> {
114    if i.len() < 12 {
115        return Err(Err::Incomplete(nom::Needed::new(12 - i.len())));
116    }
117    let bom = u32::from_le_bytes(*array_ref4(i, 8));
118    if bom == BOM_MAGIC {
119        parse_sectionheaderblock_le(i)
120    } else if bom == u32::from_be(BOM_MAGIC) {
121        parse_sectionheaderblock_be(i)
122    } else {
123        Err(Err::Error(PcapError::HeaderNotRecognized))
124    }
125}