pcap_parser/pcapng/
enhanced_packet.rs1use nom::bytes::streaming::take;
2use nom::error::{ErrorKind, ParseError};
3use nom::{Err, IResult};
4use rusticata_macros::align32;
5
6use crate::endianness::{PcapBE, PcapEndianness, PcapLE};
7use crate::traits::PcapNGPacketBlock;
8use crate::utils::array_ref4;
9use crate::{build_ts, build_ts_f64, opt_parse_options, PcapError, PcapNGOption, EPB_MAGIC};
10
11use super::*;
12
13#[derive(Debug)]
37pub struct EnhancedPacketBlock<'a> {
38 pub block_type: u32,
41 pub block_len1: u32,
42 pub if_id: u32,
43 pub ts_high: u32,
44 pub ts_low: u32,
45 pub caplen: u32,
47 pub origlen: u32,
49 pub data: &'a [u8],
51 pub options: Vec<PcapNGOption<'a>>,
52 pub block_len2: u32,
53}
54
55impl EnhancedPacketBlock<'_> {
56 #[inline]
64 pub fn decode_ts(&self, ts_offset: u64, resolution: u64) -> (u32, u32) {
65 build_ts(self.ts_high, self.ts_low, ts_offset, resolution)
66 }
67
68 #[inline]
74 pub fn decode_ts_f64(&self, ts_offset: u64, resolution: u64) -> f64 {
75 build_ts_f64(self.ts_high, self.ts_low, ts_offset, resolution)
76 }
77}
78
79impl PcapNGPacketBlock for EnhancedPacketBlock<'_> {
80 fn big_endian(&self) -> bool {
81 self.block_type != EPB_MAGIC
82 }
83 fn truncated(&self) -> bool {
84 self.origlen != self.caplen
85 }
86 fn orig_len(&self) -> u32 {
87 self.origlen
88 }
89 fn raw_packet_data(&self) -> &[u8] {
90 self.data
91 }
92 fn packet_data(&self) -> &[u8] {
93 let caplen = self.caplen as usize;
94 if caplen < self.data.len() {
95 &self.data[..caplen]
96 } else {
97 self.data
98 }
99 }
100}
101
102impl<'a, En: PcapEndianness> PcapNGBlockParser<'a, En, EnhancedPacketBlock<'a>>
103 for EnhancedPacketBlock<'a>
104{
105 const HDR_SZ: usize = 32;
106 const MAGIC: u32 = EPB_MAGIC;
107
108 fn inner_parse<E: ParseError<&'a [u8]>>(
109 block_type: u32,
110 block_len1: u32,
111 i: &'a [u8],
112 block_len2: u32,
113 ) -> IResult<&'a [u8], EnhancedPacketBlock<'a>, E> {
114 let (b_hdr, packet_data) = i.split_at(20);
117 let if_id = En::u32_from_bytes(*array_ref4(b_hdr, 0));
118 let ts_high = En::u32_from_bytes(*array_ref4(b_hdr, 4));
119 let ts_low = En::u32_from_bytes(*array_ref4(b_hdr, 8));
120 let caplen = En::u32_from_bytes(*array_ref4(b_hdr, 12));
121 let origlen = En::u32_from_bytes(*array_ref4(b_hdr, 16));
122 if caplen >= u32::MAX - 4 {
125 return Err(Err::Error(E::from_error_kind(i, ErrorKind::Verify)));
126 }
127 let padded_length = align32!(caplen);
128 let (i, data) = take(padded_length)(packet_data)?;
129 let current_offset = (32 + padded_length) as usize;
131 let (i, options) = opt_parse_options::<En, E>(i, block_len1 as usize, current_offset)?;
132 if block_len2 != block_len1 {
133 return Err(Err::Error(E::from_error_kind(i, ErrorKind::Verify)));
134 }
135 let block = EnhancedPacketBlock {
136 block_type,
137 block_len1,
138 if_id,
139 ts_high,
140 ts_low,
141 caplen,
142 origlen,
143 data,
144 options,
145 block_len2,
146 };
147 Ok((i, block))
148 }
149}
150
151pub fn parse_enhancedpacketblock_le(
153 i: &[u8],
154) -> IResult<&[u8], EnhancedPacketBlock<'_>, PcapError<&[u8]>> {
155 ng_block_parser::<EnhancedPacketBlock, PcapLE, _, _>()(i)
156}
157
158pub fn parse_enhancedpacketblock_be(
160 i: &[u8],
161) -> IResult<&[u8], EnhancedPacketBlock<'_>, PcapError<&[u8]>> {
162 ng_block_parser::<EnhancedPacketBlock, PcapBE, _, _>()(i)
163}