1use nom::bytes::streaming::take;
2use nom::combinator::map;
3use nom::number::streaming::{be_u32, le_u32};
4use nom::{error::*, Parser as _};
5use nom::{Err, IResult};
6
7use crate::endianness::PcapEndianness;
8use crate::PcapError;
9
10use super::*;
11
12#[derive(Debug)]
14pub enum Block<'a> {
15 SectionHeader(SectionHeaderBlock<'a>),
16 InterfaceDescription(InterfaceDescriptionBlock<'a>),
17 EnhancedPacket(EnhancedPacketBlock<'a>),
18 SimplePacket(SimplePacketBlock<'a>),
19 NameResolution(NameResolutionBlock<'a>),
20 InterfaceStatistics(InterfaceStatisticsBlock<'a>),
21 SystemdJournalExport(SystemdJournalExportBlock<'a>),
22 DecryptionSecrets(DecryptionSecretsBlock<'a>),
23 ProcessInformation(ProcessInformationBlock<'a>),
24 Custom(CustomBlock<'a>),
25 Unknown(UnknownBlock<'a>),
26}
27
28impl Block<'_> {
29 pub fn is_data_block(&self) -> bool {
31 matches!(self, &Block::EnhancedPacket(_) | &Block::SimplePacket(_))
32 }
33
34 pub fn magic(&self) -> u32 {
36 match self {
37 Block::SectionHeader(_) => SHB_MAGIC,
38 Block::InterfaceDescription(_) => IDB_MAGIC,
39 Block::EnhancedPacket(_) => EPB_MAGIC,
40 Block::SimplePacket(_) => SPB_MAGIC,
41 Block::NameResolution(_) => NRB_MAGIC,
42 Block::InterfaceStatistics(_) => ISB_MAGIC,
43 Block::SystemdJournalExport(_) => SJE_MAGIC,
44 Block::DecryptionSecrets(_) => DSB_MAGIC,
45 Block::ProcessInformation(_) => PIB_MAGIC,
46 Block::Custom(cb) => cb.block_type,
47 Block::Unknown(ub) => ub.block_type,
48 }
49 }
50}
51
52pub fn parse_block_le(i: &[u8]) -> IResult<&[u8], Block<'_>, PcapError<&[u8]>> {
57 match le_u32(i) {
58 Ok((_, id)) => match id {
59 SHB_MAGIC => map(parse_sectionheaderblock, Block::SectionHeader).parse(i),
60 IDB_MAGIC => map(
61 parse_interfacedescriptionblock_le,
62 Block::InterfaceDescription,
63 )
64 .parse(i),
65 SPB_MAGIC => map(parse_simplepacketblock_le, Block::SimplePacket).parse(i),
66 EPB_MAGIC => map(parse_enhancedpacketblock_le, Block::EnhancedPacket).parse(i),
67 NRB_MAGIC => map(parse_nameresolutionblock_le, Block::NameResolution).parse(i),
68 ISB_MAGIC => map(
69 parse_interfacestatisticsblock_le,
70 Block::InterfaceStatistics,
71 )
72 .parse(i),
73 SJE_MAGIC => map(
74 parse_systemdjournalexportblock_le,
75 Block::SystemdJournalExport,
76 )
77 .parse(i),
78 DSB_MAGIC => map(parse_decryptionsecretsblock_le, Block::DecryptionSecrets).parse(i),
79 CB_MAGIC => map(parse_customblock_le, Block::Custom).parse(i),
80 DCB_MAGIC => map(parse_dcb_le, Block::Custom).parse(i),
81 PIB_MAGIC => map(parse_processinformationblock_le, Block::ProcessInformation).parse(i),
82 _ => map(parse_unknownblock_le, Block::Unknown).parse(i),
83 },
84 Err(e) => Err(e),
85 }
86}
87
88pub fn parse_block_be(i: &[u8]) -> IResult<&[u8], Block<'_>, PcapError<&[u8]>> {
93 match be_u32(i) {
94 Ok((_, id)) => match id {
95 SHB_MAGIC => map(parse_sectionheaderblock, Block::SectionHeader).parse(i),
96 IDB_MAGIC => map(
97 parse_interfacedescriptionblock_be,
98 Block::InterfaceDescription,
99 )
100 .parse(i),
101 SPB_MAGIC => map(parse_simplepacketblock_be, Block::SimplePacket).parse(i),
102 EPB_MAGIC => map(parse_enhancedpacketblock_be, Block::EnhancedPacket).parse(i),
103 NRB_MAGIC => map(parse_nameresolutionblock_be, Block::NameResolution).parse(i),
104 ISB_MAGIC => map(
105 parse_interfacestatisticsblock_be,
106 Block::InterfaceStatistics,
107 )
108 .parse(i),
109 SJE_MAGIC => map(
110 parse_systemdjournalexportblock_be,
111 Block::SystemdJournalExport,
112 )
113 .parse(i),
114 DSB_MAGIC => map(parse_decryptionsecretsblock_be, Block::DecryptionSecrets).parse(i),
115 CB_MAGIC => map(parse_customblock_be, Block::Custom).parse(i),
116 DCB_MAGIC => map(parse_dcb_be, Block::Custom).parse(i),
117 PIB_MAGIC => map(parse_processinformationblock_be, Block::ProcessInformation).parse(i),
118 _ => map(parse_unknownblock_be, Block::Unknown).parse(i),
119 },
120 Err(e) => Err(e),
121 }
122}
123
124pub(crate) trait PcapNGBlockParser<'a, En: PcapEndianness, O: 'a> {
125 const HDR_SZ: usize;
127 const MAGIC: u32;
129
130 fn inner_parse<E: ParseError<&'a [u8]>>(
132 block_type: u32,
133 block_len1: u32,
134 i: &'a [u8],
135 block_len2: u32,
136 ) -> IResult<&'a [u8], O, E>;
137}
138
139pub(crate) fn ng_block_parser<'a, P, En, O, E>() -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], O, E>
141where
142 P: PcapNGBlockParser<'a, En, O>,
143 En: PcapEndianness,
144 O: 'a,
145 E: ParseError<&'a [u8]>,
146{
147 move |i: &[u8]| {
148 if i.len() < P::HDR_SZ {
151 return Err(Err::Incomplete(nom::Needed::new(P::HDR_SZ - i.len())));
152 }
153 let (i, block_type) = le_u32(i)?;
154 let (i, block_len1) = En::parse_u32(i)?;
155 if block_len1 < P::HDR_SZ as u32 {
156 return Err(Err::Error(E::from_error_kind(i, ErrorKind::Verify)));
157 }
158 if P::MAGIC != 0 && En::native_u32(block_type) != P::MAGIC {
159 return Err(Err::Error(E::from_error_kind(i, ErrorKind::Verify)));
160 }
161 let (i, block_content) = take(block_len1 - 12)(i)?;
163 let (i, block_len2) = En::parse_u32(i)?;
164 let (_, b) = P::inner_parse(block_type, block_len1, block_content, block_len2)?;
166 Ok((i, b))
168 }
169}