1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use crate::pcapng::blocks::opts_from_slice;
use crate::errors::PcapError;
use byteorder::{ByteOrder, ReadBytesExt};
use crate::pcapng::{CustomUtf8Option, CustomBinaryOption, UnknownOption};
#[derive(Clone, Debug)]
pub struct PacketBlock<'a> {
pub interface_id: u16,
pub drop_count: u16,
pub timestamp: u64,
pub captured_len: u32,
pub original_len: u32,
pub data: &'a [u8],
pub options: Vec<PacketOption<'a>>
}
impl<'a> PacketBlock<'a> {
pub fn from_slice<B: ByteOrder>(mut slice: &'a [u8]) -> Result<(&'a [u8], Self), PcapError> {
if slice.len() < 20 {
return Err(PcapError::InvalidField("EnhancedPacketBlock: block length length < 20"));
}
let interface_id = slice.read_u16::<B>()?;
let drop_count = slice.read_u16::<B>()?;
let timestamp = slice.read_u64::<B>()?;
let captured_len = slice.read_u32::<B>()?;
let original_len = slice.read_u32::<B>()?;
let pad_len = (4 - (captured_len as usize % 4)) % 4;
let tot_len = captured_len as usize + pad_len;
if slice.len() < tot_len {
return Err(PcapError::InvalidField("EnhancedPacketBlock: captured_len + padding > block length"));
}
let data = &slice[..captured_len as usize];
slice = &slice[tot_len..];
let (slice, options) = PacketOption::from_slice::<B>(slice)?;
let block = PacketBlock {
interface_id,
drop_count,
timestamp,
captured_len,
original_len,
data,
options
};
Ok((slice, block))
}
}
#[derive(Clone, Debug)]
pub enum PacketOption<'a> {
Comment(&'a str),
Flags(u32),
Hash(&'a [u8]),
CustomBinary(CustomBinaryOption<'a>),
CustomUtf8(CustomUtf8Option<'a>),
Unknown(UnknownOption<'a>)
}
impl<'a> PacketOption<'a> {
pub fn from_slice<B:ByteOrder>(slice: &'a [u8]) -> Result<(&'a[u8], Vec<Self>), PcapError> {
opts_from_slice::<B, _, _>(slice, |mut slice, code, length| {
let opt = match code {
1 => PacketOption::Comment(std::str::from_utf8(slice)?),
2 => {
if slice.len() != 4 {
return Err(PcapError::InvalidField("PacketOption: Flags length != 4"))
}
PacketOption::Flags(slice.read_u32::<B>()?)
},
3 => PacketOption::Hash(slice),
2988 | 19372 => PacketOption::CustomUtf8(CustomUtf8Option::from_slice::<B>(code, slice)?),
2989 | 19373 => PacketOption::CustomBinary(CustomBinaryOption::from_slice::<B>(code, slice)?),
_ => PacketOption::Unknown(UnknownOption::new(code, length, slice))
};
Ok(opt)
})
}
}