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, PcapNGOptionError, SHB_MAGIC};
8
9use super::*;
10
11#[derive(Debug)]
18pub struct SectionHeaderBlock<'a> {
19 pub block_type: u32,
20 pub block_len1: u32,
21 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 SectionHeaderBlock<'_> {
31 pub fn big_endian(&self) -> bool {
32 self.bom != BOM_MAGIC
33 }
34
35 pub fn shb_hardware(&self) -> Option<Result<&str, PcapNGOptionError>> {
42 options_get_as_str(&self.options, OptionCode::ShbHardware)
43 }
44
45 pub fn shb_os(&self) -> Option<Result<&str, PcapNGOptionError>> {
52 options_get_as_str(&self.options, OptionCode::ShbOs)
53 }
54
55 pub fn shb_userappl(&self) -> Option<Result<&str, PcapNGOptionError>> {
62 options_get_as_str(&self.options, OptionCode::ShbUserAppl)
63 }
64}
65
66impl<'a> PcapNGBlockParser<'a, PcapBE, SectionHeaderBlock<'a>> for SectionHeaderBlock<'a> {
67 const HDR_SZ: usize = 28;
68 const MAGIC: u32 = SHB_MAGIC;
69
70 fn inner_parse<E: ParseError<&'a [u8]>>(
71 block_type: u32,
72 block_len1: u32,
73 i: &'a [u8],
74 block_len2: u32,
75 ) -> IResult<&'a [u8], SectionHeaderBlock<'a>, E> {
76 let (i, bom) = le_u32(i)?;
79 let (i, major_version) = be_u16(i)?;
80 let (i, minor_version) = be_u16(i)?;
81 let (i, section_len) = be_i64(i)?;
82 let (i, options) = opt_parse_options::<PcapBE, E>(i, block_len1 as usize, 28)?;
83 let block = SectionHeaderBlock {
84 block_type,
85 block_len1,
86 bom,
87 major_version,
88 minor_version,
89 section_len,
90 options,
91 block_len2,
92 };
93 Ok((i, block))
94 }
95}
96
97impl<'a> PcapNGBlockParser<'a, PcapLE, SectionHeaderBlock<'a>> for SectionHeaderBlock<'a> {
98 const HDR_SZ: usize = 28;
99 const MAGIC: u32 = SHB_MAGIC;
100
101 fn inner_parse<E: ParseError<&'a [u8]>>(
102 block_type: u32,
103 block_len1: u32,
104 i: &'a [u8],
105 block_len2: u32,
106 ) -> IResult<&'a [u8], SectionHeaderBlock<'a>, E> {
107 let (i, bom) = le_u32(i)?;
110 let (i, major_version) = le_u16(i)?;
111 let (i, minor_version) = le_u16(i)?;
112 let (i, section_len) = le_i64(i)?;
113 let (i, options) = opt_parse_options::<PcapLE, E>(i, block_len1 as usize, 28)?;
114 let block = SectionHeaderBlock {
115 block_type,
116 block_len1,
117 bom,
118 major_version,
119 minor_version,
120 section_len,
121 options,
122 block_len2,
123 };
124 Ok((i, block))
125 }
126}
127
128pub fn parse_sectionheaderblock_le(
130 i: &[u8],
131) -> IResult<&[u8], SectionHeaderBlock<'_>, PcapError<&[u8]>> {
132 ng_block_parser::<SectionHeaderBlock, PcapLE, _, _>()(i)
133}
134
135pub fn parse_sectionheaderblock_be(
137 i: &[u8],
138) -> IResult<&[u8], SectionHeaderBlock<'_>, PcapError<&[u8]>> {
139 ng_block_parser::<SectionHeaderBlock, PcapBE, _, _>()(i)
140}
141
142pub fn parse_sectionheaderblock(
144 i: &[u8],
145) -> IResult<&[u8], SectionHeaderBlock<'_>, PcapError<&[u8]>> {
146 if i.len() < 12 {
147 return Err(Err::Incomplete(nom::Needed::new(12 - i.len())));
148 }
149 let bom = u32::from_le_bytes(*array_ref4(i, 8));
150 if bom == BOM_MAGIC {
151 parse_sectionheaderblock_le(i)
152 } else if bom == u32::from_be(BOM_MAGIC) {
153 parse_sectionheaderblock_be(i)
154 } else {
155 Err(Err::Error(PcapError::HeaderNotRecognized))
156 }
157}