From faddf64307558d7c24fb3a9ad583417086b6b7a7 Mon Sep 17 00:00:00 2001 From: gurkenhabicht Date: Thu, 11 Jun 2020 18:24:09 +0200 Subject: [PATCH] implemented data_link() for device_parse(), implemented serializable MacAddress, clean up --- src/parser/mod.rs | 128 ++++++----------------------------- src/parser/packet_handler.rs | 20 +++--- src/serializer/mod.rs | 4 +- 3 files changed, 32 insertions(+), 120 deletions(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index a095abc..648b3cc 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -2,8 +2,7 @@ extern crate bitfield; extern crate byteorder; extern crate eui48; mod packet_handler; -use eui48::{MacAddress}; -use pcap::Capture; +use pcap::{Capture, Linktype}; use regex::bytes::Regex; use std::str; //use std::thread::{spawn, JoinHandle}; @@ -18,14 +17,6 @@ const UDP: usize = 0x11; const ETH_P_ARP: usize = 0x0608; const ETH_P_RARP: usize = 0x3580; -fn build_ether() -> packet_handler::EtherHeader { - packet_handler::EtherHeader { - ether_dhost: MacAddress::new([0;6]), - ether_shost: MacAddress::new([0;6]), - ether_type: 0, - } -} - /* 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. @@ -40,7 +31,7 @@ pub struct QryData { pub id: i32, pub time: f64, pub data: Option>, - pub ether_header: packet_handler::EtherHeader, + pub ether_header: Option, pub ipv4_header: Option, pub ipv6_header: Option, pub tcp_header: Option, @@ -50,12 +41,11 @@ pub struct QryData { } fn init_qrydata( ) -> Result { - let ether_init = build_ether(); Ok(QryData { id: 0, time: 0.0, data: None, - ether_header: ether_init, + ether_header: None::, ipv4_header: None::, ipv6_header: None::, tcp_header: None::, @@ -66,9 +56,9 @@ fn init_qrydata( ) -> Result { } -enum EncapsulationType { - ETHER = 1, - RAWIP = 107, +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 { @@ -76,14 +66,12 @@ impl QryData { // This will get modularized into subfunctions fn encap_ether( packet_data: &[u8] ) -> Option { let mut pkg: QryData = init_qrydata().unwrap(); - pkg.ether_header = packet_handler::ethernet_handler(packet_data); - match pkg.ether_header.ether_type as usize { + pkg.ether_header = Some(packet_handler::ethernet_handler(packet_data)).unwrap(); + match pkg.ether_header.unwrap().ether_type as usize { ETH_P_IP => { - //pkg.ipv6_header = None::; pkg.ipv4_header = Some(packet_handler::ip_handler(packet_data)).unwrap(); match pkg.ipv4_header.unwrap().ip_protocol as usize { - TCP => { - // pkg.udp_header = None::; + TCP => { pkg.tcp_header = Some(packet_handler::tcp_handler( pkg.ipv4_header.unwrap().ip_ihl, packet_data, @@ -96,7 +84,6 @@ impl QryData { )).unwrap(); } UDP => { - // pkg.tcp_header = None::; pkg.udp_header = Some(packet_handler::udp_handler( pkg.ipv4_header.unwrap().ip_ihl, packet_data, @@ -112,11 +99,9 @@ impl QryData { } } ETH_P_IPV6 => { - //pkg.ipv4_header = None::; pkg.ipv6_header = Some(packet_handler::ipv6_handler(packet_data)).unwrap(); match pkg.ipv6_header.unwrap().next_header as usize { TCP => { - // pkg.udp_header = None::; pkg.tcp_header = Some(packet_handler::tcp_handler(10, packet_data)).unwrap(); pkg.data = Some(packet_handler::payload_handler( 10, @@ -125,7 +110,6 @@ impl QryData { )).unwrap(); } UDP => { - // pkg.tcp_header = None::; pkg.udp_header = Some(packet_handler::udp_handler(10, packet_data)).unwrap(); pkg.data = Some(packet_handler::payload_handler(10, 7, packet_data)).unwrap(); } @@ -134,7 +118,6 @@ impl QryData { } ETH_P_ARP | ETH_P_RARP => { pkg.arp_header = Some(packet_handler::arp_handler(packet_data)).unwrap(); - pkg.data = None; } _ => println!("Network protocol not implemented"), } @@ -143,12 +126,9 @@ impl QryData { fn encap_rawip ( packet_data: &[u8] ) -> Option { let mut pkg: QryData = init_qrydata().unwrap(); - //pkg.ether_header = None::; - //pkg.ipv6_header = None::; pkg.ipv4_header = Some(packet_handler::ip_handler(packet_data)).unwrap(); match pkg.ipv4_header.unwrap().ip_protocol as usize { TCP => { - pkg.udp_header = None::; pkg.tcp_header = Some(packet_handler::tcp_handler( pkg.ipv4_header.unwrap().ip_ihl, packet_data, @@ -160,8 +140,7 @@ impl QryData { packet_data, )).unwrap(); } - UDP => { - pkg.tcp_header = None::; + UDP => { pkg.udp_header = Some(packet_handler::udp_handler( pkg.ipv4_header.unwrap().ip_ihl, packet_data, @@ -207,8 +186,8 @@ pub fn parse(parse_file: &std::path::Path, filter_str: &str, regex_filter: &str, match encap { // Syntax is clunky, but no num_derive + num_traits dependencies. - encap if encap == EncapsulationType::ETHER as u16 => me = QryData::encap_ether(packet.data).unwrap(), - encap if encap == EncapsulationType::RAWIP as u16 => me = QryData::encap_rawip(packet.data).unwrap(), + encap if encap == EncapsulationType::EN10MB as u16 => me = QryData::encap_ether(packet.data).unwrap(), + encap if encap == EncapsulationType::RAW as u16 => me = QryData::encap_rawip(packet.data).unwrap(), _ => (), }; @@ -227,83 +206,20 @@ pub fn parse_device(parse_device: &str, filter_str: &str, insert_max: &usize, re 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() { - me.time = (packet.header.ts.tv_usec as f64 / 1000000.0) + packet.header.ts.tv_sec as f64; - me.data = Some(packet.data.to_vec()); - me.reg_res = flag_carnage(&re, packet.data); - me.ether_header = packet_handler::ethernet_handler(packet.data); - match me.ether_header.ether_type as usize { - ETH_P_IP => { - me.ipv6_header = None::; - me.ipv4_header = Some(packet_handler::ip_handler(packet.data)).unwrap(); - match me.ipv4_header.unwrap().ip_protocol as usize { - TCP => { - me.tcp_header = Some(packet_handler::tcp_handler( - me.ipv4_header.unwrap().ip_ihl, - packet.data, - )) - .unwrap(); - me.data = Some(packet_handler::payload_handler( - me.ipv4_header.unwrap().ip_ihl, - me.tcp_header.unwrap().data_offset, - packet.data, - )).unwrap(); - } - UDP => { - me.udp_header = Some(packet_handler::udp_handler( - me.ipv4_header.unwrap().ip_ihl, - packet.data, - )) - .unwrap(); - me.data = Some(packet_handler::payload_handler( - me.ipv4_header.unwrap().ip_ihl, - 7, - packet.data, - )).unwrap(); - } - _ => println!("network protocol not implemented"), - } - } - ETH_P_IPV6 => { - me.ipv4_header = None::; - me.ipv6_header = Some(packet_handler::ipv6_handler(packet.data)).unwrap(); - match me.ipv6_header.unwrap().next_header as usize { - TCP => { - me.tcp_header = Some(packet_handler::tcp_handler(10, packet.data)).unwrap(); - me.data = Some(packet_handler::payload_handler( - 10, - me.tcp_header.unwrap().data_offset, - packet.data, - )).unwrap(); - } - UDP => { - me.udp_header = Some(packet_handler::udp_handler(10, packet.data)).unwrap(); - me.data = Some(packet_handler::payload_handler(10, 7, packet.data)).unwrap(); - } - _ => println!("network protocol not implemented"), - } - } - ETH_P_ARP | ETH_P_RARP => { - me.arp_header = Some(packet_handler::arp_handler(packet.data)).unwrap(); - me.data = None; - } - _ => println!("network protocol not implemented"), + match linktype { + Linktype(1) => me = QryData::encap_ether(packet.data).unwrap(), + Linktype(101) => me = QryData::encap_rawip(packet.data).unwrap(), + _ => (), } - 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, - }); + 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); + + v.push(me.clone()); + if &v.len() >= insert_max { break 'parse; } diff --git a/src/parser/packet_handler.rs b/src/parser/packet_handler.rs index b8aa69b..b721b06 100644 --- a/src/parser/packet_handler.rs +++ b/src/parser/packet_handler.rs @@ -16,7 +16,7 @@ const ETH_TLEN: usize = 2; const ETHER_HDRLEN: usize = 14; -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy,Serialize, Deserialize)] pub struct EtherHeader { pub ether_dhost: MacAddress, pub ether_shost: MacAddress, @@ -24,7 +24,7 @@ pub struct EtherHeader { } // TODO: implement optional ethernet vlan shim header fields -pub fn ethernet_handler(packet_data: &[u8]) -> EtherHeader { +pub fn ethernet_handler(packet_data: &[u8]) -> Option { let mut _ether_dhost: [u8; ETH_ALEN] = [0; ETH_ALEN]; let mut _ether_shost: [u8; ETH_ALEN] = [0; ETH_ALEN]; let mut _ether_type: u16 = 0; @@ -33,11 +33,11 @@ pub fn ethernet_handler(packet_data: &[u8]) -> EtherHeader { _ether_shost.clone_from_slice(&packet_data[ETH_ALEN..ETH_ALEN * 2]); _ether_type = LittleEndian::read_u16(&packet_data[ETH_ALEN * 2..(ETH_ALEN * 2) + ETH_TLEN]); - EtherHeader { + Some(EtherHeader { ether_dhost: (MacAddress::new(_ether_dhost as Eui48)), ether_shost: (MacAddress::new(_ether_shost as Eui48)), ether_type: _ether_type as i32, - } + }) } /* ip */ @@ -224,9 +224,9 @@ pub struct ArpHeader { pub hlen: u8, pub plen: u8, pub oper: u16, - pub sha: Eui48, + pub sha: MacAddress, pub spa: IpAddr, - pub tha: Eui48, + pub tha: MacAddress, pub tpa: IpAddr, } @@ -248,12 +248,10 @@ pub fn arp_handler(packet_data: &[u8]) -> Option { hlen: raw_hdr[4], plen: raw_hdr[5], oper: BigEndian::read_u16(&raw_hdr[6..8]), - //sha: MacAddress::new(_sha as Eui48).to_hex_string().to_owned(), - sha: _sha, + sha: MacAddress::new(_sha as Eui48), spa: IpAddr::V4(Ipv4Addr::from(BigEndian::read_u32(&raw_hdr[14..18]))), - //tha: MacAddress::new( _tha as Eui48 ).to_hex_string().to_owned(), - tha: _tha, - tpa: IpAddr::V4(Ipv4Addr::from(BigEndian::read_u32(&raw_hdr[24..28]))), + tha: MacAddress::new( _tha as Eui48 ), + tpa: IpAddr::V4(Ipv4Addr::from(BigEndian::read_u32(&raw_hdr[24..28]))), }) } diff --git a/src/serializer/mod.rs b/src/serializer/mod.rs index 152e42f..c9eb3ae 100644 --- a/src/serializer/mod.rs +++ b/src/serializer/mod.rs @@ -14,9 +14,7 @@ impl Serialize for parser::QryData { { let mut state = serializer.serialize_struct("parser::QryData", 11)?; state.serialize_field("time", &self.time)?; - state.serialize_field("ether_header.ether_dhost", &self.ether_header.ether_dhost.to_hex_string())?; - state.serialize_field("ether_header.ether_shost", &self.ether_header.ether_shost.to_hex_string())?; - state.serialize_field("ether_header.ether_type", &self.ether_header.ether_type)?; + state.serialize_field("ether_header", &self.ether_header)?; state.serialize_field("ipv4_header", &self.ipv4_header)?; state.serialize_field("ipv6_header", &self.ipv6_header)?; state.serialize_field("tcp_header", &self.tcp_header)?;