From 4e86759c68b18e0ee9ce496ce66c9bf40f20a22b Mon Sep 17 00:00:00 2001 From: gurkenhabicht Date: Sun, 14 Jun 2020 04:14:06 +0200 Subject: [PATCH] clean up + restucturing --- src/parser/mod.rs | 98 ++++++++----- src/parser/mod.rs_bkp | 268 +++++++++++++++++++++++++++++++++++ src/parser/packet_handler.rs | 9 +- src/parser_selfed | 268 +++++++++++++++++++++++++++++++++++ 4 files changed, 606 insertions(+), 37 deletions(-) create mode 100644 src/parser/mod.rs_bkp create mode 100644 src/parser_selfed diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 209b328..c93c26c 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -16,7 +16,15 @@ const TCP: usize = 0x06; const UDP: usize = 0x11; const ETH_P_ARP: usize = 0x0608; const ETH_P_RARP: usize = 0x3580; -const ETHER_HDRLEN: usize = 14; + +/* Protocol header sizes */ +const ETHER_HDRLEN: usize = 0xE; +const NO_PREDECESSOR: usize = 0x0; +const IPV6_HDRLEN: u32 = 0xA; // I know, this will get changed. It works for now. + +/* random constants */ +const IPV4: usize = 0x4; +const IPV6: usize = 0x6; /* QryData could be written in the sense of QryData{ ... frame: .., packet: .., segment:.. } @@ -70,24 +78,33 @@ impl QryData { } fn encap_en10mb(&mut self, packet_data: &[u8]) -> Result<(), core::fmt::Error> { - //let mut pkg: QryData = new().unwrap(); self.ether_header = Some(packet_handler::ethernet_handler(packet_data)).unwrap(); match self.ether_header.unwrap().ether_type as usize { ETH_P_IP => { - self.ipv4_header = Some(packet_handler::ip_handler(packet_data, ETHER_HDRLEN)).unwrap(); - let protocol_type = self.ipv4_header.unwrap().ip_protocol as usize; - let l3_header_length = self.ipv4_header.unwrap().ip_ihl; - self.transport_layer(packet_data, protocol_type, l3_header_length, ETHER_HDRLEN) - .unwrap(); + self.ipv4_header = + Some(packet_handler::ip_handler(packet_data, ETHER_HDRLEN)).unwrap(); + self.transport_layer( + packet_data, + self.ipv4_header.unwrap().ip_protocol as usize, + self.ipv4_header.unwrap().ip_ihl, + ETHER_HDRLEN, + ) + .unwrap(); } ETH_P_IPV6 => { - self.ipv6_header = Some(packet_handler::ipv6_handler(packet_data, ETHER_HDRLEN)).unwrap(); - let protocol_type = self.ipv6_header.unwrap().next_header as usize; - self.transport_layer(packet_data, protocol_type, 10, ETHER_HDRLEN) - .unwrap(); + self.ipv6_header = + Some(packet_handler::ipv6_handler(packet_data, ETHER_HDRLEN)).unwrap(); + self.transport_layer( + packet_data, + self.ipv6_header.unwrap().next_header as usize, + IPV6_HDRLEN, + ETHER_HDRLEN, + ) + .unwrap(); } ETH_P_ARP | ETH_P_RARP => { - self.arp_header = Some(packet_handler::arp_handler(packet_data, ETHER_HDRLEN)).unwrap(); + self.arp_header = + Some(packet_handler::arp_handler(packet_data, ETHER_HDRLEN)).unwrap(); } _ => println!("Network protocol not implemented"), } @@ -95,24 +112,29 @@ impl QryData { } fn encap_raw(&mut self, packet_data: &[u8]) -> Result<(), core::fmt::Error> { - // let mut pkg: QryData = new().unwrap(); let ip_version: usize = ((packet_data[0] & 0xf0) >> 4).try_into().unwrap(); - //println!("{:?}", &ip_version); match ip_version { - 4 => { - //println!("v4"); - self.ipv4_header = Some(packet_handler::ip_handler(packet_data, 0)).unwrap(); - let protocol_type = self.ipv4_header.unwrap().ip_protocol as usize; - let l3_header_length = self.ipv4_header.unwrap().ip_ihl; - self.transport_layer(packet_data, protocol_type, l3_header_length, 0) - .unwrap(); + IPV4 => { + self.ipv4_header = + Some(packet_handler::ip_handler(packet_data, NO_PREDECESSOR)).unwrap(); + self.transport_layer( + packet_data, + self.ipv4_header.unwrap().ip_protocol as usize, + self.ipv4_header.unwrap().ip_ihl, + NO_PREDECESSOR, + ) + .unwrap(); } - 6 => { - //println!("v6"); - self.ipv6_header = Some(packet_handler::ipv6_handler(packet_data, 0)).unwrap(); - let protocol_type = self.ipv6_header.unwrap().next_header as usize; - self.transport_layer(packet_data, protocol_type, 10, 0) - .unwrap(); + IPV6 => { + self.ipv6_header = + Some(packet_handler::ipv6_handler(packet_data, NO_PREDECESSOR)).unwrap(); + self.transport_layer( + packet_data, + self.ipv6_header.unwrap().next_header as usize, + IPV6_HDRLEN, + NO_PREDECESSOR, + ) + .unwrap(); } _ => println!("Network Protocol not implemented"), } @@ -129,24 +151,32 @@ impl QryData { ) -> Result<(), core::fmt::Error> { match protocol_type { TCP => { - self.tcp_header = - Some(packet_handler::tcp_handler(l3_header_length, packet_data, ether_hdrlen)).unwrap(); + self.tcp_header = Some(packet_handler::tcp_handler( + l3_header_length, + packet_data, + ether_hdrlen, + )) + .unwrap(); self.data = Some(packet_handler::payload_handler( l3_header_length, self.tcp_header.unwrap().data_offset, packet_data, - ether_hdrlen + ether_hdrlen, )) .unwrap(); } UDP => { - self.udp_header = - Some(packet_handler::udp_handler(l3_header_length, packet_data, ether_hdrlen)).unwrap(); + self.udp_header = Some(packet_handler::udp_handler( + l3_header_length, + packet_data, + ether_hdrlen, + )) + .unwrap(); self.data = Some(packet_handler::payload_handler( l3_header_length, 7, packet_data, - ether_hdrlen + ether_hdrlen, )) .unwrap(); } @@ -173,9 +203,7 @@ fn flag_carnage(re: &Regex, payload: &[u8]) -> Option { } pub fn parse(parse_file: &std::path::Path, filter_str: &str, regex_filter: &str) -> Vec { - //let mut me: QryData = QryData::new(); let mut v: Vec = Vec::new(); - let mut cap = Capture::from_file(parse_file).unwrap(); Capture::filter(&mut cap, &filter_str).unwrap(); let linktype = cap.get_datalink(); diff --git a/src/parser/mod.rs_bkp b/src/parser/mod.rs_bkp new file mode 100644 index 0000000..d9aad28 --- /dev/null +++ b/src/parser/mod.rs_bkp @@ -0,0 +1,268 @@ +extern crate bitfield; +extern crate byteorder; +extern crate eui48; +mod packet_handler; +use pcap::{Capture, Linktype}; +use regex::bytes::Regex; +use std::convert::TryInto; +use std::str; +//use std::thread::{spawn, JoinHandle}; +//use std::sync::mpsc::{channel, Receiver}; + +/* protocol ids, LittleEndian */ +const ETH_P_IPV6: usize = 0xDD86; +const ETH_P_IP: usize = 0x08; +const TCP: usize = 0x06; +const UDP: usize = 0x11; +const ETH_P_ARP: usize = 0x0608; +const ETH_P_RARP: usize = 0x3580; + +/* Protocol header sizes */ +const ETHER_HDRLEN: usize = 14; +const NO_PREDECESSOR: usize = 0; +const IPV6_HDRLEN: u32 = 10; // I know, this will get changed. It works for now. + +/* + QryData could be written in the sense of QryData{ ... frame: .., packet: .., segment:.. } + On the one hand, only the actual type of frame/packet/segment would be contained in the resulting struct. + So, increased benefit in serialization/cpu time, could result in less data to be serialized, depending on layout. + On the other hand, each datagram::type needs to implement traits which would need to be dynamically dispatched by returning any of these types per iso level from a single function each. The result would be a performance decrease. + See: https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits + See: https://doc.rust-lang.org/book/ch17-02-trait-objects.html#trait-objects-perform-dynamic-dispatch + Then again, parser logic would be fewer lines + more unified using the latter method. Maybe better optimizable as well? Maybe this is a nice tradeoff? + TODO: Implement and benchmark dynamically dispatched packet data in conjunction with restructured QryData. +*/ +#[derive(Debug, Clone)] +pub struct QryData { + pub id: i32, + pub time: f64, + pub data: Option>, + pub ether_header: Option, + pub ipv4_header: Option, + pub ipv6_header: Option, + pub tcp_header: Option, + pub udp_header: Option, + pub arp_header: Option, + pub reg_res: Option, +} + +#[allow(dead_code)] +enum EncapsulationType { + // pcap::Linktype::get_name() is unsafe. + EN10MB = 1, // See: https://docs.rs/pcap/0.7.0/src/pcap/lib.rs.html#247-261 + RAW = 101, // Would this be an issue? +} + +impl QryData { + // This is not cool! + // Implementing objectoriented is slower by 3-10%. Variance is all over the place. It's awful but modular! + // Guess I'll do a roolback and do a different approach + + fn new() -> QryData { + QryData { + id: 0, + time: 0.0, + data: None, + ether_header: None::, + ipv4_header: None::, + ipv6_header: None::, + tcp_header: None::, + udp_header: None::, + arp_header: None::, + reg_res: None::, + } + } + + fn encap_en10mb(mut self, packet_data: &[u8]) -> Self { + //let mut pkg: QryData = new().unwrap(); + self.ether_header = Some(packet_handler::ethernet_handler(packet_data)).unwrap(); + match self.ether_header.unwrap().ether_type as usize { + ETH_P_IP => { + self.ipv4_header = Some(packet_handler::ip_handler(packet_data, ETHER_HDRLEN)).unwrap(); + self.transport_layer(packet_data, self.ipv4_header.unwrap().ip_protocol as usize, self.ipv4_header.unwrap().ip_ihl, ETHER_HDRLEN) + .unwrap(); + self + } + ETH_P_IPV6 => { + self.ipv6_header = Some(packet_handler::ipv6_handler(packet_data, ETHER_HDRLEN)).unwrap(); + self.transport_layer(packet_data, self.ipv6_header.unwrap().next_header as usize, IPV6_HDRLEN, ETHER_HDRLEN) + .unwrap(); + self + } + ETH_P_ARP | ETH_P_RARP => { + self.arp_header = Some(packet_handler::arp_handler(packet_data, ETHER_HDRLEN)).unwrap(); + self + } + _ => self + + } + + } + + fn encap_raw(mut self, packet_data: &[u8]) -> Self { + let ip_version: usize = ((packet_data[0] & 0xf0) >> 4).try_into().unwrap(); + match ip_version { + 4 => { + self.ipv4_header = Some(packet_handler::ip_handler(packet_data, NO_PREDECESSOR)).unwrap(); + self.transport_layer(packet_data, self.ipv4_header.unwrap().ip_protocol as usize, self.ipv4_header.unwrap().ip_ihl, NO_PREDECESSOR) + .unwrap(); + self + } + 6 => { + self.ipv6_header = Some(packet_handler::ipv6_handler(packet_data, NO_PREDECESSOR)).unwrap(); + self.transport_layer(packet_data, self.ipv6_header.unwrap().next_header as usize, IPV6_HDRLEN, NO_PREDECESSOR) + .unwrap(); + self + } + _ => self + } + } + + // TODO: impl correct Err type and use in Result + fn transport_layer( + &mut self, + packet_data: &[u8], + protocol_type: usize, + l3_header_length: u32, + ether_hdrlen: usize, + ) -> Result<(), core::fmt::Error> { + match protocol_type { + TCP => { + self.tcp_header = + Some(packet_handler::tcp_handler(l3_header_length, packet_data, ether_hdrlen)).unwrap(); + self.data = Some(packet_handler::payload_handler( + l3_header_length, + self.tcp_header.unwrap().data_offset, + packet_data, + ether_hdrlen + )) + .unwrap(); + } + UDP => { + self.udp_header = + Some(packet_handler::udp_handler(l3_header_length, packet_data, ether_hdrlen)).unwrap(); + self.data = Some(packet_handler::payload_handler( + l3_header_length, + 7, + packet_data, + ether_hdrlen + )) + .unwrap(); + } + _ => println!("Transport layer protocol not implemented"), + } + Ok(()) + } + + fn regex_parse(&mut self, re: &Regex, packet_data: &[u8]) -> Result<(), regex::Error> { + self.reg_res = flag_carnage(&re, packet_data); + Ok(()) + } + + + fn time(mut self, tv_usec: f64, tv_sec: f64) -> Self { + self.time = (tv_usec as f64 / 1000000.0) + tv_sec as f64; + self + } +} + +/* Regex parse _complete_ package */ +fn flag_carnage(re: &Regex, payload: &[u8]) -> Option { + let mut flags: String = String::new(); + for mat in re.find_iter(payload) { + // TODO: Test benchmark format! vs. push_str() + // flags.push_str(&format!("{} ",std::str::from_utf8(mat.as_bytes()).unwrap())); + // See: https://github.com/hoodie/concatenation_benchmarks-rs + flags.push_str(std::str::from_utf8(mat.as_bytes()).unwrap()); + flags.push_str(";"); + } + match 0 < flags.len() { + false => None, + true => Some(flags), + } +} + +pub fn parse(parse_file: &std::path::Path, filter_str: &str, regex_filter: &str) -> Vec { + let mut v: Vec = Vec::new(); + + let mut cap = Capture::from_file(parse_file).unwrap(); + Capture::filter(&mut cap, &filter_str).unwrap(); + let linktype = cap.get_datalink(); + println!("{:?}", &linktype); + let re = Regex::new(regex_filter).unwrap(); + while let Ok(packet) = cap.next() { + let mut me = QryData::new(); + match linktype { + Linktype(1) => me.encap_en10mb(packet.data), //me = QryData::encap_en10mb(packet.data).unwrap(), // EN10MB + Linktype(12) => me.encap_raw(packet.data), //me = QryData::encap_raw(packet.data).unwrap(), // RAW + _ => QryData::new(), + }; + + //me.time = (packet.header.ts.tv_usec as f64 / 1000000.0) + packet.header.ts.tv_sec as f64; + //me.reg_res = flag_carnage(&re, packet.data).unwrap(); // Regex overhead is between 4-9% --single threaded-- on complete packet [u8] data + me.time(packet.header.ts.tv_usec as f64, packet.header.ts.tv_sec as f64); + me.regex_parse(&re, packet.data).unwrap(); + + v.push(me.clone()); +// v.push(QryData { +// id: 0, +// time: me.time, +// data: me.data, +// ether_header: me.ether_header, +// ipv4_header: me.ipv4_header, +// ipv6_header: me.ipv6_header, +// tcp_header: me.tcp_header, +// udp_header: me.udp_header, +// arp_header: me.arp_header, +// reg_res: me.reg_res, +// }); + } + v +} + +/* This could need some love */ +pub fn parse_device( + parse_device: &str, + filter_str: &str, + insert_max: &usize, + regex_filter: &str, +) -> Vec { + //let mut me: QryData = QryData::new ( ); + let mut v: Vec = Vec::new(); + let mut cap = Capture::from_device(parse_device).unwrap().open().unwrap(); + Capture::filter(&mut cap, &filter_str).unwrap(); + let linktype = cap.get_datalink(); + let re = Regex::new(regex_filter).unwrap(); + 'parse: while let Ok(packet) = cap.next() { + let mut me = QryData::new(); + match linktype { + Linktype(1) => me.encap_en10mb(packet.data), //me = QryData::encap_en10mb(packet.data).unwrap(), + Linktype(12) => me.encap_raw(packet.data), //me = QryData::encap_raw(packet.data).unwrap(), + _ => QryData::new(), + }; + + me.time = (packet.header.ts.tv_usec as f64 / 1000000.0) + packet.header.ts.tv_sec as f64; +// &mut me.reg_res = flag_carnage(&re, packet.data).unwrap(); + me.time(packet.header.ts.tv_usec as f64, packet.header.ts.tv_sec as f64); + me.regex_parse(&re, packet.data).unwrap(); + + v.push(me.clone()); + +// v.push(QryData { +// id: 0, +// time: me.time, +// data: me.data, +// ether_header: me.ether_header, +// ipv4_header: me.ipv4_header, +// ipv6_header: me.ipv6_header, +// tcp_header: me.tcp_header, +// udp_header: me.udp_header, +// arp_header: me.arp_header, +// reg_res: me.reg_res, +// }); + if &v.len() >= insert_max { + break 'parse; + } + } + v +} diff --git a/src/parser/packet_handler.rs b/src/parser/packet_handler.rs index a01c862..c187612 100644 --- a/src/parser/packet_handler.rs +++ b/src/parser/packet_handler.rs @@ -189,7 +189,7 @@ bitfield! { pub fn tcp_handler(ip_hlen: u32, packet_data: &[u8], ether_hdrlen: usize) -> Option { let mut raw_hdr: [u8; 20] = [0; 20]; raw_hdr.copy_from_slice( - &packet_data[ether_hdrlen + ip_hlen as usize * 4..ether_hdrlen+ ip_hlen as usize * 4 + 20], + &packet_data[ether_hdrlen + ip_hlen as usize * 4..ether_hdrlen + ip_hlen as usize * 4 + 20], ); let tcp_header = BitfieldTcpHeader(raw_hdr); @@ -276,7 +276,12 @@ pub fn udp_handler(ip_hlen: u32, packet_data: &[u8], ether_hdrlen: usize) -> Opt } /* payload */ -pub fn payload_handler(ip_hlen: u32, data_offset: u32, packet_data: &[u8], ether_hdrlen: usize) -> Option> { +pub fn payload_handler( + ip_hlen: u32, + data_offset: u32, + packet_data: &[u8], + ether_hdrlen: usize, +) -> Option> { let (_head, tail) = packet_data.split_at(ether_hdrlen + ip_hlen as usize * 4 + data_offset as usize * 4); Some(tail.to_vec()) diff --git a/src/parser_selfed b/src/parser_selfed new file mode 100644 index 0000000..d9aad28 --- /dev/null +++ b/src/parser_selfed @@ -0,0 +1,268 @@ +extern crate bitfield; +extern crate byteorder; +extern crate eui48; +mod packet_handler; +use pcap::{Capture, Linktype}; +use regex::bytes::Regex; +use std::convert::TryInto; +use std::str; +//use std::thread::{spawn, JoinHandle}; +//use std::sync::mpsc::{channel, Receiver}; + +/* protocol ids, LittleEndian */ +const ETH_P_IPV6: usize = 0xDD86; +const ETH_P_IP: usize = 0x08; +const TCP: usize = 0x06; +const UDP: usize = 0x11; +const ETH_P_ARP: usize = 0x0608; +const ETH_P_RARP: usize = 0x3580; + +/* Protocol header sizes */ +const ETHER_HDRLEN: usize = 14; +const NO_PREDECESSOR: usize = 0; +const IPV6_HDRLEN: u32 = 10; // I know, this will get changed. It works for now. + +/* + QryData could be written in the sense of QryData{ ... frame: .., packet: .., segment:.. } + On the one hand, only the actual type of frame/packet/segment would be contained in the resulting struct. + So, increased benefit in serialization/cpu time, could result in less data to be serialized, depending on layout. + On the other hand, each datagram::type needs to implement traits which would need to be dynamically dispatched by returning any of these types per iso level from a single function each. The result would be a performance decrease. + See: https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits + See: https://doc.rust-lang.org/book/ch17-02-trait-objects.html#trait-objects-perform-dynamic-dispatch + Then again, parser logic would be fewer lines + more unified using the latter method. Maybe better optimizable as well? Maybe this is a nice tradeoff? + TODO: Implement and benchmark dynamically dispatched packet data in conjunction with restructured QryData. +*/ +#[derive(Debug, Clone)] +pub struct QryData { + pub id: i32, + pub time: f64, + pub data: Option>, + pub ether_header: Option, + pub ipv4_header: Option, + pub ipv6_header: Option, + pub tcp_header: Option, + pub udp_header: Option, + pub arp_header: Option, + pub reg_res: Option, +} + +#[allow(dead_code)] +enum EncapsulationType { + // pcap::Linktype::get_name() is unsafe. + EN10MB = 1, // See: https://docs.rs/pcap/0.7.0/src/pcap/lib.rs.html#247-261 + RAW = 101, // Would this be an issue? +} + +impl QryData { + // This is not cool! + // Implementing objectoriented is slower by 3-10%. Variance is all over the place. It's awful but modular! + // Guess I'll do a roolback and do a different approach + + fn new() -> QryData { + QryData { + id: 0, + time: 0.0, + data: None, + ether_header: None::, + ipv4_header: None::, + ipv6_header: None::, + tcp_header: None::, + udp_header: None::, + arp_header: None::, + reg_res: None::, + } + } + + fn encap_en10mb(mut self, packet_data: &[u8]) -> Self { + //let mut pkg: QryData = new().unwrap(); + self.ether_header = Some(packet_handler::ethernet_handler(packet_data)).unwrap(); + match self.ether_header.unwrap().ether_type as usize { + ETH_P_IP => { + self.ipv4_header = Some(packet_handler::ip_handler(packet_data, ETHER_HDRLEN)).unwrap(); + self.transport_layer(packet_data, self.ipv4_header.unwrap().ip_protocol as usize, self.ipv4_header.unwrap().ip_ihl, ETHER_HDRLEN) + .unwrap(); + self + } + ETH_P_IPV6 => { + self.ipv6_header = Some(packet_handler::ipv6_handler(packet_data, ETHER_HDRLEN)).unwrap(); + self.transport_layer(packet_data, self.ipv6_header.unwrap().next_header as usize, IPV6_HDRLEN, ETHER_HDRLEN) + .unwrap(); + self + } + ETH_P_ARP | ETH_P_RARP => { + self.arp_header = Some(packet_handler::arp_handler(packet_data, ETHER_HDRLEN)).unwrap(); + self + } + _ => self + + } + + } + + fn encap_raw(mut self, packet_data: &[u8]) -> Self { + let ip_version: usize = ((packet_data[0] & 0xf0) >> 4).try_into().unwrap(); + match ip_version { + 4 => { + self.ipv4_header = Some(packet_handler::ip_handler(packet_data, NO_PREDECESSOR)).unwrap(); + self.transport_layer(packet_data, self.ipv4_header.unwrap().ip_protocol as usize, self.ipv4_header.unwrap().ip_ihl, NO_PREDECESSOR) + .unwrap(); + self + } + 6 => { + self.ipv6_header = Some(packet_handler::ipv6_handler(packet_data, NO_PREDECESSOR)).unwrap(); + self.transport_layer(packet_data, self.ipv6_header.unwrap().next_header as usize, IPV6_HDRLEN, NO_PREDECESSOR) + .unwrap(); + self + } + _ => self + } + } + + // TODO: impl correct Err type and use in Result + fn transport_layer( + &mut self, + packet_data: &[u8], + protocol_type: usize, + l3_header_length: u32, + ether_hdrlen: usize, + ) -> Result<(), core::fmt::Error> { + match protocol_type { + TCP => { + self.tcp_header = + Some(packet_handler::tcp_handler(l3_header_length, packet_data, ether_hdrlen)).unwrap(); + self.data = Some(packet_handler::payload_handler( + l3_header_length, + self.tcp_header.unwrap().data_offset, + packet_data, + ether_hdrlen + )) + .unwrap(); + } + UDP => { + self.udp_header = + Some(packet_handler::udp_handler(l3_header_length, packet_data, ether_hdrlen)).unwrap(); + self.data = Some(packet_handler::payload_handler( + l3_header_length, + 7, + packet_data, + ether_hdrlen + )) + .unwrap(); + } + _ => println!("Transport layer protocol not implemented"), + } + Ok(()) + } + + fn regex_parse(&mut self, re: &Regex, packet_data: &[u8]) -> Result<(), regex::Error> { + self.reg_res = flag_carnage(&re, packet_data); + Ok(()) + } + + + fn time(mut self, tv_usec: f64, tv_sec: f64) -> Self { + self.time = (tv_usec as f64 / 1000000.0) + tv_sec as f64; + self + } +} + +/* Regex parse _complete_ package */ +fn flag_carnage(re: &Regex, payload: &[u8]) -> Option { + let mut flags: String = String::new(); + for mat in re.find_iter(payload) { + // TODO: Test benchmark format! vs. push_str() + // flags.push_str(&format!("{} ",std::str::from_utf8(mat.as_bytes()).unwrap())); + // See: https://github.com/hoodie/concatenation_benchmarks-rs + flags.push_str(std::str::from_utf8(mat.as_bytes()).unwrap()); + flags.push_str(";"); + } + match 0 < flags.len() { + false => None, + true => Some(flags), + } +} + +pub fn parse(parse_file: &std::path::Path, filter_str: &str, regex_filter: &str) -> Vec { + let mut v: Vec = Vec::new(); + + let mut cap = Capture::from_file(parse_file).unwrap(); + Capture::filter(&mut cap, &filter_str).unwrap(); + let linktype = cap.get_datalink(); + println!("{:?}", &linktype); + let re = Regex::new(regex_filter).unwrap(); + while let Ok(packet) = cap.next() { + let mut me = QryData::new(); + match linktype { + Linktype(1) => me.encap_en10mb(packet.data), //me = QryData::encap_en10mb(packet.data).unwrap(), // EN10MB + Linktype(12) => me.encap_raw(packet.data), //me = QryData::encap_raw(packet.data).unwrap(), // RAW + _ => QryData::new(), + }; + + //me.time = (packet.header.ts.tv_usec as f64 / 1000000.0) + packet.header.ts.tv_sec as f64; + //me.reg_res = flag_carnage(&re, packet.data).unwrap(); // Regex overhead is between 4-9% --single threaded-- on complete packet [u8] data + me.time(packet.header.ts.tv_usec as f64, packet.header.ts.tv_sec as f64); + me.regex_parse(&re, packet.data).unwrap(); + + v.push(me.clone()); +// v.push(QryData { +// id: 0, +// time: me.time, +// data: me.data, +// ether_header: me.ether_header, +// ipv4_header: me.ipv4_header, +// ipv6_header: me.ipv6_header, +// tcp_header: me.tcp_header, +// udp_header: me.udp_header, +// arp_header: me.arp_header, +// reg_res: me.reg_res, +// }); + } + v +} + +/* This could need some love */ +pub fn parse_device( + parse_device: &str, + filter_str: &str, + insert_max: &usize, + regex_filter: &str, +) -> Vec { + //let mut me: QryData = QryData::new ( ); + let mut v: Vec = Vec::new(); + let mut cap = Capture::from_device(parse_device).unwrap().open().unwrap(); + Capture::filter(&mut cap, &filter_str).unwrap(); + let linktype = cap.get_datalink(); + let re = Regex::new(regex_filter).unwrap(); + 'parse: while let Ok(packet) = cap.next() { + let mut me = QryData::new(); + match linktype { + Linktype(1) => me.encap_en10mb(packet.data), //me = QryData::encap_en10mb(packet.data).unwrap(), + Linktype(12) => me.encap_raw(packet.data), //me = QryData::encap_raw(packet.data).unwrap(), + _ => QryData::new(), + }; + + me.time = (packet.header.ts.tv_usec as f64 / 1000000.0) + packet.header.ts.tv_sec as f64; +// &mut me.reg_res = flag_carnage(&re, packet.data).unwrap(); + me.time(packet.header.ts.tv_usec as f64, packet.header.ts.tv_sec as f64); + me.regex_parse(&re, packet.data).unwrap(); + + v.push(me.clone()); + +// v.push(QryData { +// id: 0, +// time: me.time, +// data: me.data, +// ether_header: me.ether_header, +// ipv4_header: me.ipv4_header, +// ipv6_header: me.ipv6_header, +// tcp_header: me.tcp_header, +// udp_header: me.udp_header, +// arp_header: me.arp_header, +// reg_res: me.reg_res, +// }); + if &v.len() >= insert_max { + break 'parse; + } + } + v +}