tpcpr/src/configure/mod.rs

115 lines
4.5 KiB
Rust

// 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<Config> {
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<std::collections::HashMap<std::path::PathBuf, FileInfo>> {
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)
}