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
128
129
130
131
132
133
134
135
136
137
138
139
use std::io::Write;
use byteorder_slice::byteorder::WriteBytesExt;
use byteorder_slice::result::ReadSlice;
use byteorder_slice::{BigEndian, ByteOrder, LittleEndian};
use crate::errors::*;
use crate::{DataLink, Endianness, TsResolution};
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct PcapHeader {
pub version_major: u16,
pub version_minor: u16,
pub ts_correction: i32,
pub ts_accuracy: u32,
pub snaplen: u32,
pub datalink: DataLink,
pub ts_resolution: TsResolution,
pub endianness: Endianness,
}
impl PcapHeader {
pub fn from_slice(mut slice: &[u8]) -> PcapResult<(&[u8], PcapHeader)> {
if slice.len() < 24 {
return Err(PcapError::IncompleteBuffer);
}
let magic_number = slice.read_u32::<BigEndian>().unwrap();
match magic_number {
0xA1B2C3D4 => return init_pcap_header::<BigEndian>(slice, TsResolution::MicroSecond, Endianness::Big),
0xA1B23C4D => return init_pcap_header::<BigEndian>(slice, TsResolution::NanoSecond, Endianness::Big),
0xD4C3B2A1 => return init_pcap_header::<LittleEndian>(slice, TsResolution::MicroSecond, Endianness::Little),
0x4D3CB2A1 => return init_pcap_header::<LittleEndian>(slice, TsResolution::NanoSecond, Endianness::Little),
_ => return Err(PcapError::InvalidField("PcapHeader: wrong magic number")),
};
fn init_pcap_header<B: ByteOrder>(
mut src: &[u8],
ts_resolution: TsResolution,
endianness: Endianness,
) -> PcapResult<(&[u8], PcapHeader)> {
let header = PcapHeader {
version_major: src.read_u16::<B>().unwrap(),
version_minor: src.read_u16::<B>().unwrap(),
ts_correction: src.read_i32::<B>().unwrap(),
ts_accuracy: src.read_u32::<B>().unwrap(),
snaplen: src.read_u32::<B>().unwrap(),
datalink: DataLink::from(src.read_u32::<B>().unwrap()),
ts_resolution,
endianness,
};
Ok((src, header))
}
}
pub fn write_to<W: Write>(&self, writer: &mut W) -> PcapResult<usize> {
return match self.endianness {
Endianness::Big => write_header::<_, BigEndian>(self, writer),
Endianness::Little => write_header::<_, LittleEndian>(self, writer),
};
fn write_header<W: Write, B: ByteOrder>(header: &PcapHeader, writer: &mut W) -> PcapResult<usize> {
let magic_number = match header.ts_resolution {
TsResolution::MicroSecond => 0xA1B2C3D4,
TsResolution::NanoSecond => 0xA1B23C4D,
};
writer.write_u32::<B>(magic_number).map_err(PcapError::IoError)?;
writer.write_u16::<B>(header.version_major).map_err(PcapError::IoError)?;
writer.write_u16::<B>(header.version_minor).map_err(PcapError::IoError)?;
writer.write_i32::<B>(header.ts_correction).map_err(PcapError::IoError)?;
writer.write_u32::<B>(header.ts_accuracy).map_err(PcapError::IoError)?;
writer.write_u32::<B>(header.snaplen).map_err(PcapError::IoError)?;
writer.write_u32::<B>(header.datalink.into()).map_err(PcapError::IoError)?;
Ok(24)
}
}
}
impl Default for PcapHeader {
fn default() -> Self {
PcapHeader {
version_major: 2,
version_minor: 4,
ts_correction: 0,
ts_accuracy: 0,
snaplen: 65535,
datalink: DataLink::ETHERNET,
ts_resolution: TsResolution::MicroSecond,
endianness: Endianness::Big,
}
}
}