pub mod common;
pub mod file;
pub mod flow;
pub mod global_header;
pub mod layer2;
pub mod layer3;
pub mod layer4;
pub mod errors;
pub mod record;
pub use errors::Error as Error;
pub use file::CaptureFile as CaptureFile;
pub use global_header::GlobalHeader as GlobalHeader;
pub use record::{PcapRecord as PcapRecord, PcapRecords as PcapRecords};
pub fn parse<'a>(data: &'a [u8]) -> Result<(&'a [u8], CaptureFile<'a>), Error> {
CaptureFile::parse(data)
}
#[cfg(test)]
pub mod tests {
use crate::{flow::FlowExtraction, CaptureFile};
use nom::Endianness;
use std::io::prelude::*;
use std::path::PathBuf;
pub mod util {
use regex::Regex;
#[test]
fn test_hex_dump() {
let bytes = parse_hex_dump(r"
# Comment line
0090 34 35 36 37 4567
").expect("Failed to parse bytes");
assert_eq!(bytes.len(), 4)
}
pub fn parse_hex_dump(input: &str) -> Result<Vec<u8>, hex::FromHexError> {
let hex_reg: Regex = Regex::new(r"(?m)^\s*[0-9a-fA-F]{3,}\s+((?:[0-9a-fA-F]{2}\s){1,16}).*?$").unwrap();
let mut response = vec!();
for cap in hex_reg.captures_iter(input) {
let c = Vec::from(cap[1].replace(" ", ""));
let mut decode = hex::decode(c)?;
response.append(&mut decode);
}
Ok(response)
}
}
const RAW_DATA: &'static [u8] = &[
0x4du8, 0x3c, 0x2b, 0x1au8, 0x00u8, 0x04u8, 0x00u8, 0x02u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x04u8, 0x00u8, 0x00u8, 0x06u8, 0x13u8, 0x00u8, 0x00u8, 0x00u8, 0x02u8, 0x5Bu8, 0x11u8, 0x6Du8, 0xE3u8, 0x00u8, 0x02u8, 0x51u8, 0xF5u8, 0x00u8, 0x00u8, 0x00u8,
0x56u8, 0x00u8, 0x00u8, 0x04u8, 0xD0u8, 0x01u8, 0x02u8, 0x03u8, 0x04u8, 0x05u8, 0x06u8, 0xFFu8, 0xFEu8, 0xFDu8, 0xFCu8, 0xFBu8, 0xFAu8, 0x08u8, 0x00u8, 0x45u8, 0x00u8, 0x00u8, 0x48u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x64u8, 0x06u8, 0x00u8, 0x00u8, 0x01u8, 0x02u8, 0x03u8, 0x04u8, 0x0Au8, 0x0Bu8, 0x0Cu8, 0x0Du8, 0xC6u8, 0xB7u8, 0x00u8, 0x50u8, 0x00u8, 0x00u8, 0x00u8, 0x01u8, 0x00u8, 0x00u8, 0x00u8, 0x02u8, 0x50u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x01u8, 0x02u8, 0x03u8, 0x04u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8,
0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8,
0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0x00u8, 0xfcu8, 0xfdu8, 0xfeu8,
0xffu8, ];
#[test]
fn file_bytes_parse() {
let _ = env_logger::try_init();
let (rem, f) =
CaptureFile::parse(RAW_DATA).expect("Failed to parse");
assert!(rem.is_empty());
assert_eq!(f.global_header.endianness, Endianness::Big);
assert_eq!(f.records.len(), 1);
}
#[test]
fn convert_packet() {
let _ = env_logger::try_init();
let (rem, f) =
CaptureFile::parse(RAW_DATA).expect("Failed to parse");
assert!(rem.is_empty());
let record = f.records.into_inner().pop().unwrap();
let flow = record.extract_flow().expect("Failed to extract flow");
assert_eq!(flow.source.port, 50871);
assert_eq!(flow.destination.port, 80);
}
#[test]
fn file_parse() {
let _ = env_logger::try_init();
let pcap_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("resources")
.join("4SICS-GeekLounge-151020.pcap");
let pcap_reader = std::fs::File::open(pcap_path.clone())
.expect(&format!("Failed to open pcap path {:?}", pcap_path));
let bytes = pcap_reader
.bytes()
.map(|b| b.unwrap())
.collect::<std::vec::Vec<u8>>();
let (_, f) = CaptureFile::parse(&bytes).expect("Failed to parse");
assert_eq!(f.global_header.endianness, Endianness::Little);
assert_eq!(f.records.len(), 246137);
}
}