pcap_file/pcapng/blocks/
interface_statistics.rs

1//! Interface Statistics Block.
2
3use std::borrow::Cow;
4use std::io::{Result as IoResult, Write};
5
6use byteorder_slice::byteorder::WriteBytesExt;
7use byteorder_slice::result::ReadSlice;
8use byteorder_slice::ByteOrder;
9use derive_into_owned::IntoOwned;
10
11use super::block_common::{Block, PcapNgBlock};
12use super::opt_common::{CustomBinaryOption, CustomUtf8Option, PcapNgOption, UnknownOption, WriteOptTo};
13use crate::errors::PcapError;
14
15
16/// The Interface Statistics Block contains the capture statistics for a given interface and it is optional.
17#[derive(Clone, Debug, IntoOwned, Eq, PartialEq)]
18pub struct InterfaceStatisticsBlock<'a> {
19    /// Specifies the interface these statistics refers to.
20    /// 
21    /// The correct interface will be the one whose Interface Description Block (within the current Section of the file)
22    /// is identified by same number of this field.
23    pub interface_id: u32,
24
25    /// Time this statistics refers to.
26    /// 
27    /// The format of the timestamp is the same already defined in the Enhanced Packet Block.
28    /// The length of a unit of time is specified by the 'if_tsresol' option of the Interface Description Block referenced by this packet.
29    pub timestamp: u64,
30
31    /// Options
32    pub options: Vec<InterfaceStatisticsOption<'a>>,
33}
34
35impl<'a> PcapNgBlock<'a> for InterfaceStatisticsBlock<'a> {
36    fn from_slice<B: ByteOrder>(mut slice: &'a [u8]) -> Result<(&[u8], Self), PcapError> {
37        if slice.len() < 12 {
38            return Err(PcapError::InvalidField("InterfaceStatisticsBlock: block length < 12"));
39        }
40
41        let interface_id = slice.read_u32::<B>().unwrap();
42        let timestamp = slice.read_u64::<B>().unwrap();
43        let (slice, options) = InterfaceStatisticsOption::opts_from_slice::<B>(slice)?;
44
45        let block = InterfaceStatisticsBlock { interface_id, timestamp, options };
46
47        Ok((slice, block))
48    }
49
50    fn write_to<B: ByteOrder, W: Write>(&self, writer: &mut W) -> IoResult<usize> {
51        writer.write_u32::<B>(self.interface_id)?;
52        writer.write_u64::<B>(self.timestamp)?;
53
54        let opt_len = InterfaceStatisticsOption::write_opts_to::<B, _>(&self.options, writer)?;
55        Ok(12 + opt_len)
56    }
57
58    fn into_block(self) -> Block<'a> {
59        Block::InterfaceStatistics(self)
60    }
61}
62
63
64/// The Interface Statistics Block options
65#[derive(Clone, Debug, IntoOwned, Eq, PartialEq)]
66pub enum InterfaceStatisticsOption<'a> {
67    /// The opt_comment option is a UTF-8 string containing human-readable comment text
68    /// that is associated to the current block.
69    Comment(Cow<'a, str>),
70
71    /// The isb_starttime option specifies the time the capture started.
72    IsbStartTime(u64),
73
74    /// The isb_endtime option specifies the time the capture ended.
75    IsbEndTime(u64),
76
77    /// The isb_ifrecv option specifies the 64-bit unsigned integer number of packets received from the physical interface
78    /// starting from the beginning of the capture.
79    IsbIfRecv(u64),
80
81    /// The isb_ifdrop option specifies the 64-bit unsigned integer number of packets dropped by the interface
82    /// due to lack of resources starting from the beginning of the capture.
83    IsbIfDrop(u64),
84
85    /// The isb_filteraccept option specifies the 64-bit unsigned integer number of packets accepted
86    /// by filter starting from the beginning of the capture.
87    IsbFilterAccept(u64),
88
89    /// The isb_osdrop option specifies the 64-bit unsigned integer number of packets dropped
90    /// by the operating system starting from the beginning of the capture.
91    IsbOsDrop(u64),
92
93    /// The isb_usrdeliv option specifies the 64-bit unsigned integer number of packets delivered
94    /// to the user starting from the beginning of the capture.
95    IsbUsrDeliv(u64),
96
97    /// Custom option containing binary octets in the Custom Data portion
98    CustomBinary(CustomBinaryOption<'a>),
99
100    /// Custom option containing a UTF-8 string in the Custom Data portion
101    CustomUtf8(CustomUtf8Option<'a>),
102
103    /// Unknown option
104    Unknown(UnknownOption<'a>),
105}
106
107impl<'a> PcapNgOption<'a> for InterfaceStatisticsOption<'a> {
108    fn from_slice<B: ByteOrder>(code: u16, length: u16, mut slice: &'a [u8]) -> Result<Self, PcapError> {
109        let opt = match code {
110            1 => InterfaceStatisticsOption::Comment(Cow::Borrowed(std::str::from_utf8(slice)?)),
111            2 => InterfaceStatisticsOption::IsbStartTime(slice.read_u64::<B>().map_err(|_| PcapError::IncompleteBuffer)?),
112            3 => InterfaceStatisticsOption::IsbEndTime(slice.read_u64::<B>().map_err(|_| PcapError::IncompleteBuffer)?),
113            4 => InterfaceStatisticsOption::IsbIfRecv(slice.read_u64::<B>().map_err(|_| PcapError::IncompleteBuffer)?),
114            5 => InterfaceStatisticsOption::IsbIfDrop(slice.read_u64::<B>().map_err(|_| PcapError::IncompleteBuffer)?),
115            6 => InterfaceStatisticsOption::IsbFilterAccept(slice.read_u64::<B>().map_err(|_| PcapError::IncompleteBuffer)?),
116            7 => InterfaceStatisticsOption::IsbOsDrop(slice.read_u64::<B>().map_err(|_| PcapError::IncompleteBuffer)?),
117            8 => InterfaceStatisticsOption::IsbUsrDeliv(slice.read_u64::<B>().map_err(|_| PcapError::IncompleteBuffer)?),
118
119            2988 | 19372 => InterfaceStatisticsOption::CustomUtf8(CustomUtf8Option::from_slice::<B>(code, slice)?),
120            2989 | 19373 => InterfaceStatisticsOption::CustomBinary(CustomBinaryOption::from_slice::<B>(code, slice)?),
121
122            _ => InterfaceStatisticsOption::Unknown(UnknownOption::new(code, length, slice)),
123        };
124
125        Ok(opt)
126    }
127
128    fn write_to<B: ByteOrder, W: Write>(&self, writer: &mut W) -> IoResult<usize> {
129        match self {
130            InterfaceStatisticsOption::Comment(a) => a.write_opt_to::<B, W>(1, writer),
131            InterfaceStatisticsOption::IsbStartTime(a) => a.write_opt_to::<B, W>(2, writer),
132            InterfaceStatisticsOption::IsbEndTime(a) => a.write_opt_to::<B, W>(3, writer),
133            InterfaceStatisticsOption::IsbIfRecv(a) => a.write_opt_to::<B, W>(4, writer),
134            InterfaceStatisticsOption::IsbIfDrop(a) => a.write_opt_to::<B, W>(5, writer),
135            InterfaceStatisticsOption::IsbFilterAccept(a) => a.write_opt_to::<B, W>(6, writer),
136            InterfaceStatisticsOption::IsbOsDrop(a) => a.write_opt_to::<B, W>(7, writer),
137            InterfaceStatisticsOption::IsbUsrDeliv(a) => a.write_opt_to::<B, W>(8, writer),
138            InterfaceStatisticsOption::CustomBinary(a) => a.write_opt_to::<B, W>(a.code, writer),
139            InterfaceStatisticsOption::CustomUtf8(a) => a.write_opt_to::<B, W>(a.code, writer),
140            InterfaceStatisticsOption::Unknown(a) => a.write_opt_to::<B, W>(a.code, writer),
141        }
142    }
143}