1use 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#[derive(Clone, Debug, IntoOwned, Eq, PartialEq)]
18pub struct InterfaceStatisticsBlock<'a> {
19 pub interface_id: u32,
24
25 pub timestamp: u64,
30
31 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#[derive(Clone, Debug, IntoOwned, Eq, PartialEq)]
66pub enum InterfaceStatisticsOption<'a> {
67 Comment(Cow<'a, str>),
70
71 IsbStartTime(u64),
73
74 IsbEndTime(u64),
76
77 IsbIfRecv(u64),
80
81 IsbIfDrop(u64),
84
85 IsbFilterAccept(u64),
88
89 IsbOsDrop(u64),
92
93 IsbUsrDeliv(u64),
96
97 CustomBinary(CustomBinaryOption<'a>),
99
100 CustomUtf8(CustomUtf8Option<'a>),
102
103 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}