use nom::number::streaming::{be_i32, be_u16, be_u32, le_i32, le_u16, le_u32};
use nom::IResult;
use crate::linktype::Linktype;
use crate::PcapError;
#[derive(Clone, Debug)]
pub struct PcapHeader {
pub magic_number: u32,
pub version_major: u16,
pub version_minor: u16,
pub thiszone: i32,
pub sigfigs: u32,
pub snaplen: u32,
pub network: Linktype,
}
impl PcapHeader {
pub fn new() -> PcapHeader {
PcapHeader {
magic_number: 0xa1b2_c3d4, version_major: 2,
version_minor: 4,
thiszone: 0,
sigfigs: 0,
snaplen: 0,
network: Linktype(1), }
}
pub const fn size(&self) -> usize {
24
}
pub fn is_bigendian(&self) -> bool {
(self.magic_number & 0xFFFF) == 0xb2a1 }
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
}
}
impl Default for PcapHeader {
fn default() -> Self {
PcapHeader::new()
}
}
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_cd34 => {
let (i, version_major) = le_u16(i)?;
let (i, version_minor) = le_u16(i)?;
let (i, thiszone) = le_i32(i)?;
let (i, sigfigs) = le_u32(i)?;
let (i, snaplen) = le_u32(i)?;
let (i, network) = le_i32(i)?;
let header = PcapHeader {
magic_number,
version_major,
version_minor,
thiszone,
sigfigs,
snaplen,
network: Linktype(network),
};
Ok((i, header))
}
0xd4c3_b2a1 | 0x4d3c_b2a1 => {
let (i, version_major) = be_u16(i)?;
let (i, version_minor) = be_u16(i)?;
let (i, thiszone) = be_i32(i)?;
let (i, sigfigs) = be_u32(i)?;
let (i, snaplen) = be_u32(i)?;
let (i, network) = be_i32(i)?;
let header = PcapHeader {
magic_number,
version_major,
version_minor,
thiszone,
sigfigs,
snaplen,
network: Linktype(network),
};
Ok((i, header))
}
_ => Err(nom::Err::Error(PcapError::HeaderNotRecognized)),
}
}