pcap_parser/pcapng/interface_statistics.rs
1use nom::error::{ErrorKind, ParseError};
2use nom::{Err, IResult};
3
4use crate::endianness::{PcapBE, PcapEndianness, PcapLE};
5use crate::{opt_parse_options, PcapError, PcapNGOption, ISB_MAGIC};
6
7use super::*;
8
9#[derive(Debug)]
10pub struct InterfaceStatisticsBlock<'a> {
11 pub block_type: u32,
12 pub block_len1: u32,
13 pub if_id: u32,
14 pub ts_high: u32,
15 pub ts_low: u32,
16 pub options: Vec<PcapNGOption<'a>>,
17 pub block_len2: u32,
18}
19
20impl InterfaceStatisticsBlock<'_> {
21 /// Return the `isb_starttime` option value, if present
22 ///
23 /// The returned value is `(ts_high,ts_low)`. To convert to a full timestamp,
24 /// use the [build_ts] function with the `ts_offset` and `resolution` values from
25 /// the `InterfaceDescriptionBlock` matching `self.if_id`.
26 ///
27 /// If the option is present multiple times, the first value is returned.
28 ///
29 /// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
30 /// or `Some(Err(_))` if value is present but invalid
31 pub fn isb_starttime(&self) -> Option<Result<(u32, u32), PcapNGOptionError>> {
32 options_get_as_ts(&self.options, OptionCode::IsbStartTime)
33 }
34
35 /// Return the `isb_endtime` option value, if present
36 ///
37 /// The returned value is `(ts_high,ts_low)`. To convert to a full timestamp,
38 /// use the [build_ts] function with the `ts_offset` and `resolution` values from
39 /// the `InterfaceDescriptionBlock` matching `self.if_id`.
40 ///
41 /// If the option is present multiple times, the first value is returned.
42 ///
43 /// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
44 /// or `Some(Err(_))` if value is present but invalid
45 pub fn isb_endtime(&self) -> Option<Result<(u32, u32), PcapNGOptionError>> {
46 options_get_as_ts(&self.options, OptionCode::IsbEndTime)
47 }
48
49 /// Return the `isb_ifrecv` option value, if present
50 ///
51 /// If the option is present multiple times, the first value is returned.
52 ///
53 /// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
54 /// or `Some(Err(_))` if value is present but invalid
55 pub fn isb_ifrecv(&self) -> Option<Result<u64, PcapNGOptionError>> {
56 options_get_as_u64_le(&self.options, OptionCode::IsbIfRecv)
57 }
58
59 /// Return the `isb_ifdrop` option value, if present
60 ///
61 /// If the option is present multiple times, the first value is returned.
62 ///
63 /// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
64 /// or `Some(Err(_))` if value is present but invalid
65 pub fn isb_ifdrop(&self) -> Option<Result<u64, PcapNGOptionError>> {
66 options_get_as_u64_le(&self.options, OptionCode::IsbIfDrop)
67 }
68
69 /// Return the `isb_filteraccept` option value, if present
70 ///
71 /// If the option is present multiple times, the first value is returned.
72 ///
73 /// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
74 /// or `Some(Err(_))` if value is present but invalid
75 pub fn isb_filteraccept(&self) -> Option<Result<u64, PcapNGOptionError>> {
76 options_get_as_u64_le(&self.options, OptionCode::IsbFilterAccept)
77 }
78
79 /// Return the `isb_osdrop` option value, if present
80 ///
81 /// If the option is present multiple times, the first value is returned.
82 ///
83 /// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
84 /// or `Some(Err(_))` if value is present but invalid
85 pub fn isb_osdrop(&self) -> Option<Result<u64, PcapNGOptionError>> {
86 options_get_as_u64_le(&self.options, OptionCode::IsbOsDrop)
87 }
88
89 /// Return the `isb_usrdeliv` option value, if present
90 ///
91 /// If the option is present multiple times, the first value is returned.
92 ///
93 /// Returns `None` if option is not present, `Some(Ok(value))` if the value is present and valid,
94 /// or `Some(Err(_))` if value is present but invalid
95 pub fn isb_usrdeliv(&self) -> Option<Result<u64, PcapNGOptionError>> {
96 options_get_as_u64_le(&self.options, OptionCode::IsbUsrDeliv)
97 }
98}
99
100impl<'a, En: PcapEndianness> PcapNGBlockParser<'a, En, InterfaceStatisticsBlock<'a>>
101 for InterfaceStatisticsBlock<'a>
102{
103 const HDR_SZ: usize = 24;
104 const MAGIC: u32 = ISB_MAGIC;
105
106 fn inner_parse<E: ParseError<&'a [u8]>>(
107 block_type: u32,
108 block_len1: u32,
109 i: &'a [u8],
110 block_len2: u32,
111 ) -> IResult<&'a [u8], InterfaceStatisticsBlock<'a>, E> {
112 // caller function already tested header type(magic) and length
113 // read end of header
114 let (i, if_id) = En::parse_u32(i)?;
115 let (i, ts_high) = En::parse_u32(i)?;
116 let (i, ts_low) = En::parse_u32(i)?;
117 // caller function already tested header type(magic) and length
118 // read options
119 let (i, options) = opt_parse_options::<En, E>(i, block_len1 as usize, 24)?;
120 if block_len2 != block_len1 {
121 return Err(Err::Error(E::from_error_kind(i, ErrorKind::Verify)));
122 }
123 let block = InterfaceStatisticsBlock {
124 block_type,
125 block_len1,
126 if_id,
127 ts_high,
128 ts_low,
129 options,
130 block_len2,
131 };
132 Ok((i, block))
133 }
134}
135
136/// Parse an InterfaceStatistics Block (little-endian)
137#[inline]
138pub fn parse_interfacestatisticsblock_le(
139 i: &[u8],
140) -> IResult<&[u8], InterfaceStatisticsBlock<'_>, PcapError<&[u8]>> {
141 ng_block_parser::<InterfaceStatisticsBlock, PcapLE, _, _>()(i)
142}
143
144/// Parse an InterfaceStatistics Block (big-endian)
145#[inline]
146pub fn parse_interfacestatisticsblock_be(
147 i: &[u8],
148) -> IResult<&[u8], InterfaceStatisticsBlock<'_>, PcapError<&[u8]>> {
149 ng_block_parser::<InterfaceStatisticsBlock, PcapBE, _, _>()(i)
150}