1use std::io::Write;
2
3use byteorder_slice::byteorder::WriteBytesExt;
4use byteorder_slice::result::ReadSlice;
5use byteorder_slice::{BigEndian, ByteOrder, LittleEndian};
6
7use crate::errors::*;
8use crate::{DataLink, Endianness, TsResolution};
9
10
11#[derive(Copy, Clone, Debug, Eq, PartialEq)]
13pub struct PcapHeader {
14 pub version_major: u16,
16
17 pub version_minor: u16,
19
20 pub ts_correction: i32,
22
23 pub ts_accuracy: u32,
25
26 pub snaplen: u32,
28
29 pub datalink: DataLink,
31
32 pub ts_resolution: TsResolution,
34
35 pub endianness: Endianness,
37}
38
39impl PcapHeader {
40 pub fn from_slice(mut slice: &[u8]) -> PcapResult<(&[u8], PcapHeader)> {
47 if slice.len() < 24 {
49 return Err(PcapError::IncompleteBuffer);
50 }
51
52 let magic_number = slice.read_u32::<BigEndian>().unwrap();
53
54 match magic_number {
55 0xA1B2C3D4 => return init_pcap_header::<BigEndian>(slice, TsResolution::MicroSecond, Endianness::Big),
56 0xA1B23C4D => return init_pcap_header::<BigEndian>(slice, TsResolution::NanoSecond, Endianness::Big),
57 0xD4C3B2A1 => return init_pcap_header::<LittleEndian>(slice, TsResolution::MicroSecond, Endianness::Little),
58 0x4D3CB2A1 => return init_pcap_header::<LittleEndian>(slice, TsResolution::NanoSecond, Endianness::Little),
59 _ => return Err(PcapError::InvalidField("PcapHeader: wrong magic number")),
60 };
61
62 fn init_pcap_header<B: ByteOrder>(
65 mut src: &[u8],
66 ts_resolution: TsResolution,
67 endianness: Endianness,
68 ) -> PcapResult<(&[u8], PcapHeader)> {
69 let header = PcapHeader {
70 version_major: src.read_u16::<B>().unwrap(),
71 version_minor: src.read_u16::<B>().unwrap(),
72 ts_correction: src.read_i32::<B>().unwrap(),
73 ts_accuracy: src.read_u32::<B>().unwrap(),
74 snaplen: src.read_u32::<B>().unwrap(),
75 datalink: DataLink::from(src.read_u32::<B>().unwrap()),
76 ts_resolution,
77 endianness,
78 };
79
80 Ok((src, header))
81 }
82 }
83
84 pub fn write_to<W: Write>(&self, writer: &mut W) -> PcapResult<usize> {
88 return match self.endianness {
89 Endianness::Big => write_header::<_, BigEndian>(self, writer),
90 Endianness::Little => write_header::<_, LittleEndian>(self, writer),
91 };
92
93 fn write_header<W: Write, B: ByteOrder>(header: &PcapHeader, writer: &mut W) -> PcapResult<usize> {
94 let magic_number = match header.ts_resolution {
95 TsResolution::MicroSecond => 0xA1B2C3D4,
96 TsResolution::NanoSecond => 0xA1B23C4D,
97 };
98
99 writer.write_u32::<B>(magic_number).map_err(PcapError::IoError)?;
100 writer.write_u16::<B>(header.version_major).map_err(PcapError::IoError)?;
101 writer.write_u16::<B>(header.version_minor).map_err(PcapError::IoError)?;
102 writer.write_i32::<B>(header.ts_correction).map_err(PcapError::IoError)?;
103 writer.write_u32::<B>(header.ts_accuracy).map_err(PcapError::IoError)?;
104 writer.write_u32::<B>(header.snaplen).map_err(PcapError::IoError)?;
105 writer.write_u32::<B>(header.datalink.into()).map_err(PcapError::IoError)?;
106
107 Ok(24)
108 }
109 }
110}
111
112impl Default for PcapHeader {
127 fn default() -> Self {
128 PcapHeader {
129 version_major: 2,
130 version_minor: 4,
131 ts_correction: 0,
132 ts_accuracy: 0,
133 snaplen: 65535,
134 datalink: DataLink::ETHERNET,
135 ts_resolution: TsResolution::MicroSecond,
136 endianness: Endianness::Big,
137 }
138 }
139}