// Init of configuration files could also be done via Config crate. // But at this point of development it seems like unjustified overhead. extern crate serde_json; use std::fs::File; use byteorder::{ByteOrder, LittleEndian}; use std::collections::HashMap; use std::fs; use std::io::prelude::*; //use std::thread::{spawn, JoinHandle}; //use std::sync::mpsc::{channel, Receiver}; const PCAPNG_SIGNATURE: [u8; 4] = [0x0a, 0x0d, 0x0d, 0x0a]; const PCAP_SIGNATURE: [u8; 4] = [0xd4, 0xc3, 0xb2, 0xa1]; const PCAP_SIGNATURE_BE: [u8; 4] = [0xa1, 0xb2, 0xc3, 0xa1]; pub struct Config { pub filter: String, pub regex_filter: String, pub insert_max: usize, pub pcap_file: String, pub connection: String, pub device: String, pub is_device: bool, pub pcap_dir: String, } #[derive(Debug)] pub struct FileInfo { pub encapsulation_type: u16, pub file_size: u64, pub metadata: std::fs::Metadata, } impl FileInfo { fn new(file: std::path::PathBuf, encapsulation_type: u16) -> FileInfo { FileInfo { encapsulation_type: encapsulation_type, file_size: fs::metadata(&file).unwrap().len(), metadata: fs::metadata(&file).unwrap(), } } } pub fn from_json_file() -> Option { let config_file = File::open("parser.json").expect("file should open read only"); let json: serde_json::Value = serde_json::from_reader(config_file).unwrap(); Some(Config { filter: json.get("filter").unwrap().as_str().unwrap().to_owned(), regex_filter: json.get("regex_filter").unwrap().as_str().unwrap().to_owned(), insert_max: json.get("insert_max").unwrap().as_u64().unwrap() as usize, pcap_file: json.get("pcap_file").unwrap().as_str().unwrap().to_owned(), connection: format!( "host={} user={} password={}", json.get("database_host").unwrap().as_str().unwrap(), json.get("database_user").unwrap().as_str().unwrap(), json.get("database_password").unwrap().as_str().unwrap(), ), device: json .get("parse_device") .unwrap() .as_str() .unwrap() .to_owned(), is_device: json.get("from_device").unwrap().as_bool().unwrap(), pcap_dir: json.get("pcap_dir").unwrap().as_str().unwrap().to_owned(), }) } /* File signature and encapsulation type from file See: https://www.tcpdump.org/linktypes.html */ // Futher:file.len() is included in metadata() but only shows up if called explicitly. Maybe this is not needed at all in the end // This would be needed for comparability over time. print metadata and you will see fn bytes_from_file( entry: std::path::PathBuf ) -> Result<([u8;4], u16, u16), std::io::Error> { let mut magic_number: [u8;4] = [0;4]; let mut buffer: [u8;32] = [0;32]; let mut _file = File::open(entry.to_owned())?; _file.read_exact(&mut buffer)?; magic_number.clone_from_slice(&buffer[0..4]); let enc_pcap: u16 = LittleEndian::read_u16(&buffer[20..22]); let enc_pcapng: u16 = LittleEndian::read_u16(&buffer[12..14]); Ok((magic_number, enc_pcap, enc_pcapng)) } pub fn map_pcap_dir ( pcap_dir: &str ) -> Option> { let mut pcap_map = HashMap::new(); if let Ok(entries) = fs::read_dir(pcap_dir) { for entry in entries { if let Ok(entry) = entry { if let Ok(_file_type) = entry.file_type() { if entry.metadata().unwrap().is_file() { let (magic_number, enc_pcap, enc_pcapng) = bytes_from_file(entry.path()).unwrap(); match magic_number { PCAPNG_SIGNATURE => pcap_map.insert(entry.path(), FileInfo::new(entry.path(), enc_pcapng) ), PCAP_SIGNATURE | PCAP_SIGNATURE_BE => pcap_map.insert(entry.path(), FileInfo::new(entry.path(), enc_pcap)), // TEST: Endiannes for SIGNATURE_BE may be incorrect after introducing fn bytes_from_file() _ => None, }; // println!("{:?}", &entry.metadata().unwrap().modified()); } } else { println!("Couldn't get file type for {:?}", entry.path()); } } } } Some(pcap_map) }