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}