Skip to content

Commit

Permalink
add support for PCAP "modified" format
Browse files Browse the repository at this point in the history
  • Loading branch information
gcsbt committed Apr 11, 2024
1 parent a6e6744 commit 1a8c632
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 5 deletions.
Binary file added assets/modified-format.pcap
Binary file not shown.
13 changes: 9 additions & 4 deletions src/capture_pcap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use crate::capture::Capture;
use crate::error::PcapError;
use crate::linktype::Linktype;
use crate::pcap::{
parse_pcap_frame, parse_pcap_frame_be, parse_pcap_header, LegacyPcapBlock, PcapHeader,
parse_pcap_frame, parse_pcap_frame_be, parse_pcap_frame_modified, parse_pcap_header,
LegacyPcapBlock, PcapHeader,
};
use crate::traits::PcapReaderIterator;
use circular::Buffer;
Expand Down Expand Up @@ -108,10 +109,14 @@ where
Err(nom::Err::Incomplete(Needed::Size(n))) => Err(PcapError::Incomplete(n.into())),
Err(nom::Err::Incomplete(Needed::Unknown)) => Err(PcapError::Incomplete(0)),
}?;
let parse = if header.is_bigendian() {
parse_pcap_frame_be
let parse = if !header.is_modified_format() {
if header.is_bigendian() {
parse_pcap_frame_be
} else {
parse_pcap_frame
}
} else {
parse_pcap_frame
parse_pcap_frame_modified
};
// do not consume
Ok(LegacyPcapReader {
Expand Down
29 changes: 28 additions & 1 deletion src/pcap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ impl PcapHeader {
(self.magic_number & 0xFFFF) == 0xb2a1 // works for both nanosecond and microsecond resolution timestamps
}

pub fn is_modified_format(&self) -> bool {
self.magic_number == 0xa1b2_cd34
}

pub fn is_nanosecond_precision(&self) -> bool {
self.magic_number == 0xa1b2_3c4d || self.magic_number == 0x4d3c_b2a1
}
Expand Down Expand Up @@ -131,13 +135,36 @@ pub fn parse_pcap_frame_be(i: &[u8]) -> IResult<&[u8], LegacyPcapBlock, PcapErro
Ok((i, block))
}

/// Read a PCAP record header and data ("modified" pcap format)
///
/// Each PCAP record starts with a small header, and is followed by packet data.
/// The packet data format depends on the LinkType.
pub fn parse_pcap_frame_modified(i: &[u8]) -> IResult<&[u8], LegacyPcapBlock, PcapError<&[u8]>> {
if i.len() < 24 {
return Err(nom::Err::Incomplete(nom::Needed::new(24 - i.len())));
}
let ts_sec = u32::from_le_bytes(*array_ref4(i, 0));
let ts_usec = u32::from_le_bytes(*array_ref4(i, 4));
let caplen = u32::from_le_bytes(*array_ref4(i, 8));
let origlen = u32::from_le_bytes(*array_ref4(i, 12));
let (i, data) = take(caplen as usize)(&i[24..])?;
let block = LegacyPcapBlock {
ts_sec,
ts_usec,
caplen,
origlen,
data,
};
Ok((i, block))
}

/// Read the PCAP global header
///
/// The global header contains the PCAP description and options
pub fn parse_pcap_header(i: &[u8]) -> IResult<&[u8], PcapHeader, PcapError<&[u8]>> {
let (i, magic_number) = le_u32(i)?;
match magic_number {
0xa1b2_c3d4 | 0xa1b2_3c4d => {
0xa1b2_c3d4 | 0xa1b2_3c4d | 0xa1b2_cd34 => {
let (i, version_major) = le_u16(i)?;
let (i, version_minor) = le_u16(i)?;
let (i, thiszone) = le_i32(i)?;
Expand Down
30 changes: 30 additions & 0 deletions tests/pcap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,33 @@ fn test_truncated_pcap() {
}
}
}

#[test]
fn test_modified_format() {
let path = "assets/modified-format.pcap";
let file = File::open(path).unwrap();
let buffered = BufReader::new(file);
let mut num_blocks = 0;
let mut reader = LegacyPcapReader::new(65536, buffered).expect("LegacyPcapReader");
loop {
match reader.next() {
Ok((offset, block)) => {
num_blocks += 1;
match block {
PcapBlockOwned::LegacyHeader(_) => (),
PcapBlockOwned::Legacy(b) => {
assert_eq!(b.caplen, 98);
}
PcapBlockOwned::NG(_) => panic!("unexpected NG data"),
}
reader.consume(offset);
}
Err(PcapError::Eof) => break,
Err(PcapError::Incomplete(_)) => {
reader.refill().unwrap();
}
Err(e) => panic!("error while reading: {:?}", e),
}
}
assert_eq!(num_blocks, 2);
}

0 comments on commit 1a8c632

Please sign in to comment.