1use std::borrow::Cow;
2use std::io::Write;
3use std::time::Duration;
4
5use byteorder_slice::byteorder::WriteBytesExt;
6use byteorder_slice::result::ReadSlice;
7use byteorder_slice::ByteOrder;
8use derive_into_owned::IntoOwned;
9
10use crate::errors::*;
11use crate::TsResolution;
12
13#[derive(Clone, Debug, IntoOwned)]
17pub struct PcapPacket<'a> {
18 pub timestamp: Duration,
20 pub orig_len: u32,
22 pub data: Cow<'a, [u8]>,
24}
25
26impl<'a> PcapPacket<'a> {
27 pub fn new(timestamp: Duration, orig_len: u32, data: &'a [u8]) -> PcapPacket<'a> {
29 PcapPacket { timestamp, orig_len, data: Cow::Borrowed(data) }
30 }
31
32 pub fn new_owned(timestamp: Duration, orig_len: u32, data: Vec<u8>) -> PcapPacket<'static> {
34 PcapPacket { timestamp, orig_len, data: Cow::Owned(data) }
35 }
36
37 pub fn from_slice<B: ByteOrder>(slice: &'a [u8], ts_resolution: TsResolution, snap_len: u32) -> PcapResult<(&'a [u8], PcapPacket<'a>)> {
39 let (rem, raw_packet) = RawPcapPacket::from_slice::<B>(slice)?;
40 let s = Self::try_from_raw_packet(raw_packet, ts_resolution, snap_len)?;
41
42 Ok((rem, s))
43 }
44
45 pub fn write_to<W: Write, B: ByteOrder>(&self, writer: &mut W, ts_resolution: TsResolution, snap_len: u32) -> PcapResult<usize> {
47 let ts_sec = self
49 .timestamp
50 .as_secs()
51 .try_into()
52 .map_err(|_| PcapError::InvalidField("PcapPacket: timestamp_secs > u32::MAX"))?;
53
54 let mut ts_frac = self.timestamp.subsec_nanos();
55 if ts_resolution == TsResolution::MicroSecond {
56 ts_frac /= 1000;
57 }
58
59 let incl_len = self.data.len().try_into().map_err(|_| PcapError::InvalidField("PcapPacket: incl_len > u32::MAX"))?;
61 let orig_len = self.orig_len;
62
63 if incl_len > snap_len {
64 return Err(PcapError::InvalidField("PcapPacket: incl_len > snap_len"));
65 }
66
67 if incl_len > orig_len {
68 return Err(PcapError::InvalidField("PcapPacket: incl_len > orig_len"));
69 }
70
71 let raw_packet = RawPcapPacket { ts_sec, ts_frac, incl_len, orig_len, data: Cow::Borrowed(&self.data[..]) };
72
73 raw_packet.write_to::<_, B>(writer)
74 }
75
76 pub fn try_from_raw_packet(raw: RawPcapPacket<'a>, ts_resolution: TsResolution, snap_len: u32) -> PcapResult<Self> {
78 let ts_sec = raw.ts_sec;
80 let mut ts_nsec = raw.ts_frac;
81 if ts_resolution == TsResolution::MicroSecond {
82 ts_nsec = ts_nsec.checked_mul(1000).ok_or(PcapError::InvalidField("PacketHeader ts_nanosecond is invalid"))?;
83 }
84 if ts_nsec >= 1_000_000_000 {
85 return Err(PcapError::InvalidField("PacketHeader ts_nanosecond >= 1_000_000_000"));
86 }
87
88 let incl_len = raw.incl_len;
90 let orig_len = raw.orig_len;
91
92 if incl_len > snap_len {
93 return Err(PcapError::InvalidField("PacketHeader incl_len > snap_len"));
94 }
95
96 if incl_len > orig_len {
97 return Err(PcapError::InvalidField("PacketHeader incl_len > orig_len"));
98 }
99
100 Ok(PcapPacket { timestamp: Duration::new(ts_sec as u64, ts_nsec), orig_len, data: raw.data })
101 }
102}
103
104
105#[derive(Clone, Debug, IntoOwned)]
109pub struct RawPcapPacket<'a> {
110 pub ts_sec: u32,
112 pub ts_frac: u32,
114 pub incl_len: u32,
116 pub orig_len: u32,
118 pub data: Cow<'a, [u8]>,
120}
121
122impl<'a> RawPcapPacket<'a> {
123 pub fn from_slice<B: ByteOrder>(mut slice: &'a [u8]) -> PcapResult<(&'a [u8], Self)> {
125 if slice.len() < 16 {
127 return Err(PcapError::IncompleteBuffer);
128 }
129
130 let ts_sec = slice.read_u32::<B>().unwrap();
133 let ts_frac = slice.read_u32::<B>().unwrap();
134 let incl_len = slice.read_u32::<B>().unwrap();
135 let orig_len = slice.read_u32::<B>().unwrap();
136
137 let pkt_len = incl_len as usize;
138 if slice.len() < pkt_len {
139 return Err(PcapError::IncompleteBuffer);
140 }
141
142 let packet = RawPcapPacket { ts_sec, ts_frac, incl_len, orig_len, data: Cow::Borrowed(&slice[..pkt_len]) };
143 let rem = &slice[pkt_len..];
144
145 Ok((rem, packet))
146 }
147
148 pub fn write_to<W: Write, B: ByteOrder>(&self, writer: &mut W) -> PcapResult<usize> {
151 writer.write_u32::<B>(self.ts_sec).map_err(PcapError::IoError)?;
152 writer.write_u32::<B>(self.ts_frac).map_err(PcapError::IoError)?;
153 writer.write_u32::<B>(self.incl_len).map_err(PcapError::IoError)?;
154 writer.write_u32::<B>(self.orig_len).map_err(PcapError::IoError)?;
155 writer.write_all(&self.data).map_err(PcapError::IoError)?;
156
157 Ok(16 + self.data.len())
158 }
159
160 pub fn try_into_pcap_packet(self, ts_resolution: TsResolution, snap_len: u32) -> PcapResult<PcapPacket<'a>> {
162 PcapPacket::try_from_raw_packet(self, ts_resolution, snap_len)
163 }
164}