1use nom::bytes::streaming::take;
2use nom::combinator::map;
3use nom::error::*;
4use nom::number::streaming::{be_u32, le_u32};
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<'a> Block<'a> {
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)(i),
60 IDB_MAGIC => map(
61 parse_interfacedescriptionblock_le,
62 Block::InterfaceDescription,
63 )(i),
64 SPB_MAGIC => map(parse_simplepacketblock_le, Block::SimplePacket)(i),
65 EPB_MAGIC => map(parse_enhancedpacketblock_le, Block::EnhancedPacket)(i),
66 NRB_MAGIC => map(parse_nameresolutionblock_le, Block::NameResolution)(i),
67 ISB_MAGIC => map(
68 parse_interfacestatisticsblock_le,
69 Block::InterfaceStatistics,
70 )(i),
71 SJE_MAGIC => map(
72 parse_systemdjournalexportblock_le,
73 Block::SystemdJournalExport,
74 )(i),
75 DSB_MAGIC => map(parse_decryptionsecretsblock_le, Block::DecryptionSecrets)(i),
76 CB_MAGIC => map(parse_customblock_le, Block::Custom)(i),
77 DCB_MAGIC => map(parse_dcb_le, Block::Custom)(i),
78 PIB_MAGIC => map(parse_processinformationblock_le, Block::ProcessInformation)(i),
79 _ => map(parse_unknownblock_le, Block::Unknown)(i),
80 },
81 Err(e) => Err(e),
82 }
83}
84
85pub fn parse_block_be(i: &[u8]) -> IResult<&[u8], Block, PcapError<&[u8]>> {
90 match be_u32(i) {
91 Ok((_, id)) => match id {
92 SHB_MAGIC => map(parse_sectionheaderblock, Block::SectionHeader)(i),
93 IDB_MAGIC => map(
94 parse_interfacedescriptionblock_be,
95 Block::InterfaceDescription,
96 )(i),
97 SPB_MAGIC => map(parse_simplepacketblock_be, Block::SimplePacket)(i),
98 EPB_MAGIC => map(parse_enhancedpacketblock_be, Block::EnhancedPacket)(i),
99 NRB_MAGIC => map(parse_nameresolutionblock_be, Block::NameResolution)(i),
100 ISB_MAGIC => map(
101 parse_interfacestatisticsblock_be,
102 Block::InterfaceStatistics,
103 )(i),
104 SJE_MAGIC => map(
105 parse_systemdjournalexportblock_be,
106 Block::SystemdJournalExport,
107 )(i),
108 DSB_MAGIC => map(parse_decryptionsecretsblock_be, Block::DecryptionSecrets)(i),
109 CB_MAGIC => map(parse_customblock_be, Block::Custom)(i),
110 DCB_MAGIC => map(parse_dcb_be, Block::Custom)(i),
111 PIB_MAGIC => map(parse_processinformationblock_be, Block::ProcessInformation)(i),
112 _ => map(parse_unknownblock_be, Block::Unknown)(i),
113 },
114 Err(e) => Err(e),
115 }
116}
117
118pub(crate) trait PcapNGBlockParser<'a, En: PcapEndianness, O: 'a> {
119 const HDR_SZ: usize;
121 const MAGIC: u32;
123
124 fn inner_parse<E: ParseError<&'a [u8]>>(
126 block_type: u32,
127 block_len1: u32,
128 i: &'a [u8],
129 block_len2: u32,
130 ) -> IResult<&'a [u8], O, E>;
131}
132
133pub(crate) fn ng_block_parser<'a, P, En, O, E>() -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], O, E>
135where
136 P: PcapNGBlockParser<'a, En, O>,
137 En: PcapEndianness,
138 O: 'a,
139 E: ParseError<&'a [u8]>,
140{
141 move |i: &[u8]| {
142 if i.len() < P::HDR_SZ {
145 return Err(Err::Incomplete(nom::Needed::new(P::HDR_SZ - i.len())));
146 }
147 let (i, block_type) = le_u32(i)?;
148 let (i, block_len1) = En::parse_u32(i)?;
149 if block_len1 < P::HDR_SZ as u32 {
150 return Err(Err::Error(E::from_error_kind(i, ErrorKind::Verify)));
151 }
152 if P::MAGIC != 0 && En::native_u32(block_type) != P::MAGIC {
153 return Err(Err::Error(E::from_error_kind(i, ErrorKind::Verify)));
154 }
155 let (i, block_content) = take(block_len1 - 12)(i)?;
157 let (i, block_len2) = En::parse_u32(i)?;
158 let (_, b) = P::inner_parse(block_type, block_len1, block_content, block_len2)?;
160 Ok((i, b))
162 }
163}