Skip to content

Commit e0232b0

Browse files
gcsbtchifflier
authored andcommitted
add support for PCAP "modified" format
1 parent bccce2d commit e0232b0

File tree

4 files changed

+67
-5
lines changed

4 files changed

+67
-5
lines changed

assets/modified-format.pcap

146 Bytes
Binary file not shown.

src/capture_pcap.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ use crate::capture::Capture;
33
use crate::error::PcapError;
44
use crate::linktype::Linktype;
55
use crate::pcap::{
6-
parse_pcap_frame, parse_pcap_frame_be, parse_pcap_header, LegacyPcapBlock, PcapHeader,
6+
parse_pcap_frame, parse_pcap_frame_be, parse_pcap_frame_modified, parse_pcap_header,
7+
LegacyPcapBlock, PcapHeader,
78
};
89
use crate::traits::PcapReaderIterator;
910
use circular::Buffer;
@@ -108,10 +109,14 @@ where
108109
Err(nom::Err::Incomplete(Needed::Size(n))) => Err(PcapError::Incomplete(n.into())),
109110
Err(nom::Err::Incomplete(Needed::Unknown)) => Err(PcapError::Incomplete(0)),
110111
}?;
111-
let parse = if header.is_bigendian() {
112-
parse_pcap_frame_be
112+
let parse = if !header.is_modified_format() {
113+
if header.is_bigendian() {
114+
parse_pcap_frame_be
115+
} else {
116+
parse_pcap_frame
117+
}
113118
} else {
114-
parse_pcap_frame
119+
parse_pcap_frame_modified
115120
};
116121
// do not consume
117122
Ok(LegacyPcapReader {

src/pcap.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ impl PcapHeader {
6464
(self.magic_number & 0xFFFF) == 0xb2a1 // works for both nanosecond and microsecond resolution timestamps
6565
}
6666

67+
pub fn is_modified_format(&self) -> bool {
68+
self.magic_number == 0xa1b2_cd34
69+
}
70+
6771
pub fn is_nanosecond_precision(&self) -> bool {
6872
self.magic_number == 0xa1b2_3c4d || self.magic_number == 0x4d3c_b2a1
6973
}
@@ -131,13 +135,36 @@ pub fn parse_pcap_frame_be(i: &[u8]) -> IResult<&[u8], LegacyPcapBlock, PcapErro
131135
Ok((i, block))
132136
}
133137

138+
/// Read a PCAP record header and data ("modified" pcap format)
139+
///
140+
/// Each PCAP record starts with a small header, and is followed by packet data.
141+
/// The packet data format depends on the LinkType.
142+
pub fn parse_pcap_frame_modified(i: &[u8]) -> IResult<&[u8], LegacyPcapBlock, PcapError<&[u8]>> {
143+
if i.len() < 24 {
144+
return Err(nom::Err::Incomplete(nom::Needed::new(24 - i.len())));
145+
}
146+
let ts_sec = u32::from_le_bytes(*array_ref4(i, 0));
147+
let ts_usec = u32::from_le_bytes(*array_ref4(i, 4));
148+
let caplen = u32::from_le_bytes(*array_ref4(i, 8));
149+
let origlen = u32::from_le_bytes(*array_ref4(i, 12));
150+
let (i, data) = take(caplen as usize)(&i[24..])?;
151+
let block = LegacyPcapBlock {
152+
ts_sec,
153+
ts_usec,
154+
caplen,
155+
origlen,
156+
data,
157+
};
158+
Ok((i, block))
159+
}
160+
134161
/// Read the PCAP global header
135162
///
136163
/// The global header contains the PCAP description and options
137164
pub fn parse_pcap_header(i: &[u8]) -> IResult<&[u8], PcapHeader, PcapError<&[u8]>> {
138165
let (i, magic_number) = le_u32(i)?;
139166
match magic_number {
140-
0xa1b2_c3d4 | 0xa1b2_3c4d => {
167+
0xa1b2_c3d4 | 0xa1b2_3c4d | 0xa1b2_cd34 => {
141168
let (i, version_major) = le_u16(i)?;
142169
let (i, version_minor) = le_u16(i)?;
143170
let (i, thiszone) = le_i32(i)?;

tests/pcap.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,33 @@ fn test_truncated_pcap() {
7676
}
7777
}
7878
}
79+
80+
#[test]
81+
fn test_modified_format() {
82+
let path = "assets/modified-format.pcap";
83+
let file = File::open(path).unwrap();
84+
let buffered = BufReader::new(file);
85+
let mut num_blocks = 0;
86+
let mut reader = LegacyPcapReader::new(65536, buffered).expect("LegacyPcapReader");
87+
loop {
88+
match reader.next() {
89+
Ok((offset, block)) => {
90+
num_blocks += 1;
91+
match block {
92+
PcapBlockOwned::LegacyHeader(_) => (),
93+
PcapBlockOwned::Legacy(b) => {
94+
assert_eq!(b.caplen, 98);
95+
}
96+
PcapBlockOwned::NG(_) => panic!("unexpected NG data"),
97+
}
98+
reader.consume(offset);
99+
}
100+
Err(PcapError::Eof) => break,
101+
Err(PcapError::Incomplete(_)) => {
102+
reader.refill().unwrap();
103+
}
104+
Err(e) => panic!("error while reading: {:?}", e),
105+
}
106+
}
107+
assert_eq!(num_blocks, 2);
108+
}

0 commit comments

Comments
 (0)