implemented data_link() for device_parse(), implemented serializable MacAddress, clean up

This commit is contained in:
gurkenhabicht 2020-06-11 18:24:09 +02:00
parent 7aff006aed
commit faddf64307
3 changed files with 32 additions and 120 deletions

View File

@ -2,8 +2,7 @@ extern crate bitfield;
extern crate byteorder; extern crate byteorder;
extern crate eui48; extern crate eui48;
mod packet_handler; mod packet_handler;
use eui48::{MacAddress}; use pcap::{Capture, Linktype};
use pcap::Capture;
use regex::bytes::Regex; use regex::bytes::Regex;
use std::str; use std::str;
//use std::thread::{spawn, JoinHandle}; //use std::thread::{spawn, JoinHandle};
@ -18,14 +17,6 @@ const UDP: usize = 0x11;
const ETH_P_ARP: usize = 0x0608; const ETH_P_ARP: usize = 0x0608;
const ETH_P_RARP: usize = 0x3580; 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:.. } 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. 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 id: i32,
pub time: f64, pub time: f64,
pub data: Option<Vec<u8>>, pub data: Option<Vec<u8>>,
pub ether_header: packet_handler::EtherHeader, pub ether_header: Option<packet_handler::EtherHeader>,
pub ipv4_header: Option<packet_handler::IpV4Header>, pub ipv4_header: Option<packet_handler::IpV4Header>,
pub ipv6_header: Option<packet_handler::IpV6Header>, pub ipv6_header: Option<packet_handler::IpV6Header>,
pub tcp_header: Option<packet_handler::TcpHeader>, pub tcp_header: Option<packet_handler::TcpHeader>,
@ -50,12 +41,11 @@ pub struct QryData {
} }
fn init_qrydata( ) -> Result<QryData, core::fmt::Error> { fn init_qrydata( ) -> Result<QryData, core::fmt::Error> {
let ether_init = build_ether();
Ok(QryData { Ok(QryData {
id: 0, id: 0,
time: 0.0, time: 0.0,
data: None, data: None,
ether_header: ether_init, ether_header: None::<packet_handler::EtherHeader>,
ipv4_header: None::<packet_handler::IpV4Header>, ipv4_header: None::<packet_handler::IpV4Header>,
ipv6_header: None::<packet_handler::IpV6Header>, ipv6_header: None::<packet_handler::IpV6Header>,
tcp_header: None::<packet_handler::TcpHeader>, tcp_header: None::<packet_handler::TcpHeader>,
@ -66,9 +56,9 @@ fn init_qrydata( ) -> Result<QryData, core::fmt::Error> {
} }
enum EncapsulationType { enum EncapsulationType { // pcap::Linktype::get_name() is unsafe.
ETHER = 1, EN10MB = 1, // See: https://docs.rs/pcap/0.7.0/src/pcap/lib.rs.html#247-261
RAWIP = 107, RAW = 101, // Would this be an issue?
} }
impl QryData { impl QryData {
@ -76,14 +66,12 @@ impl QryData {
// This will get modularized into subfunctions // This will get modularized into subfunctions
fn encap_ether( packet_data: &[u8] ) -> Option<QryData> { fn encap_ether( packet_data: &[u8] ) -> Option<QryData> {
let mut pkg: QryData = init_qrydata().unwrap(); let mut pkg: QryData = init_qrydata().unwrap();
pkg.ether_header = packet_handler::ethernet_handler(packet_data); pkg.ether_header = Some(packet_handler::ethernet_handler(packet_data)).unwrap();
match pkg.ether_header.ether_type as usize { match pkg.ether_header.unwrap().ether_type as usize {
ETH_P_IP => { ETH_P_IP => {
//pkg.ipv6_header = None::<packet_handler::IpV6Header>;
pkg.ipv4_header = Some(packet_handler::ip_handler(packet_data)).unwrap(); pkg.ipv4_header = Some(packet_handler::ip_handler(packet_data)).unwrap();
match pkg.ipv4_header.unwrap().ip_protocol as usize { match pkg.ipv4_header.unwrap().ip_protocol as usize {
TCP => { TCP => {
// pkg.udp_header = None::<packet_handler::UdpHeader>;
pkg.tcp_header = Some(packet_handler::tcp_handler( pkg.tcp_header = Some(packet_handler::tcp_handler(
pkg.ipv4_header.unwrap().ip_ihl, pkg.ipv4_header.unwrap().ip_ihl,
packet_data, packet_data,
@ -96,7 +84,6 @@ impl QryData {
)).unwrap(); )).unwrap();
} }
UDP => { UDP => {
// pkg.tcp_header = None::<packet_handler::TcpHeader>;
pkg.udp_header = Some(packet_handler::udp_handler( pkg.udp_header = Some(packet_handler::udp_handler(
pkg.ipv4_header.unwrap().ip_ihl, pkg.ipv4_header.unwrap().ip_ihl,
packet_data, packet_data,
@ -112,11 +99,9 @@ impl QryData {
} }
} }
ETH_P_IPV6 => { ETH_P_IPV6 => {
//pkg.ipv4_header = None::<packet_handler::IpV4Header>;
pkg.ipv6_header = Some(packet_handler::ipv6_handler(packet_data)).unwrap(); pkg.ipv6_header = Some(packet_handler::ipv6_handler(packet_data)).unwrap();
match pkg.ipv6_header.unwrap().next_header as usize { match pkg.ipv6_header.unwrap().next_header as usize {
TCP => { TCP => {
// pkg.udp_header = None::<packet_handler::UdpHeader>;
pkg.tcp_header = Some(packet_handler::tcp_handler(10, packet_data)).unwrap(); pkg.tcp_header = Some(packet_handler::tcp_handler(10, packet_data)).unwrap();
pkg.data = Some(packet_handler::payload_handler( pkg.data = Some(packet_handler::payload_handler(
10, 10,
@ -125,7 +110,6 @@ impl QryData {
)).unwrap(); )).unwrap();
} }
UDP => { UDP => {
// pkg.tcp_header = None::<packet_handler::TcpHeader>;
pkg.udp_header = Some(packet_handler::udp_handler(10, packet_data)).unwrap(); pkg.udp_header = Some(packet_handler::udp_handler(10, packet_data)).unwrap();
pkg.data = Some(packet_handler::payload_handler(10, 7, 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 => { ETH_P_ARP | ETH_P_RARP => {
pkg.arp_header = Some(packet_handler::arp_handler(packet_data)).unwrap(); pkg.arp_header = Some(packet_handler::arp_handler(packet_data)).unwrap();
pkg.data = None;
} }
_ => println!("Network protocol not implemented"), _ => println!("Network protocol not implemented"),
} }
@ -143,12 +126,9 @@ impl QryData {
fn encap_rawip ( packet_data: &[u8] ) -> Option<QryData> { fn encap_rawip ( packet_data: &[u8] ) -> Option<QryData> {
let mut pkg: QryData = init_qrydata().unwrap(); let mut pkg: QryData = init_qrydata().unwrap();
//pkg.ether_header = None::<packet_handler::EtherHeader>;
//pkg.ipv6_header = None::<packet_handler::IpV6Header>;
pkg.ipv4_header = Some(packet_handler::ip_handler(packet_data)).unwrap(); pkg.ipv4_header = Some(packet_handler::ip_handler(packet_data)).unwrap();
match pkg.ipv4_header.unwrap().ip_protocol as usize { match pkg.ipv4_header.unwrap().ip_protocol as usize {
TCP => { TCP => {
pkg.udp_header = None::<packet_handler::UdpHeader>;
pkg.tcp_header = Some(packet_handler::tcp_handler( pkg.tcp_header = Some(packet_handler::tcp_handler(
pkg.ipv4_header.unwrap().ip_ihl, pkg.ipv4_header.unwrap().ip_ihl,
packet_data, packet_data,
@ -160,8 +140,7 @@ impl QryData {
packet_data, packet_data,
)).unwrap(); )).unwrap();
} }
UDP => { UDP => {
pkg.tcp_header = None::<packet_handler::TcpHeader>;
pkg.udp_header = Some(packet_handler::udp_handler( pkg.udp_header = Some(packet_handler::udp_handler(
pkg.ipv4_header.unwrap().ip_ihl, pkg.ipv4_header.unwrap().ip_ihl,
packet_data, packet_data,
@ -207,8 +186,8 @@ pub fn parse(parse_file: &std::path::Path, filter_str: &str, regex_filter: &str,
match encap { match encap {
// Syntax is clunky, but no num_derive + num_traits dependencies. // 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::EN10MB 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::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<QryData> = Vec::new(); let mut v: Vec<QryData> = Vec::new();
let mut cap = Capture::from_device(parse_device).unwrap().open().unwrap(); let mut cap = Capture::from_device(parse_device).unwrap().open().unwrap();
Capture::filter(&mut cap, &filter_str).unwrap(); Capture::filter(&mut cap, &filter_str).unwrap();
let linktype = cap.get_datalink();
let re = Regex::new(regex_filter).unwrap(); let re = Regex::new(regex_filter).unwrap();
'parse: while let Ok(packet) = cap.next() { '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; match linktype {
me.data = Some(packet.data.to_vec()); Linktype(1) => me = QryData::encap_ether(packet.data).unwrap(),
me.reg_res = flag_carnage(&re, packet.data); Linktype(101) => me = QryData::encap_rawip(packet.data).unwrap(),
me.ether_header = packet_handler::ethernet_handler(packet.data); _ => (),
match me.ether_header.ether_type as usize {
ETH_P_IP => {
me.ipv6_header = None::<packet_handler::IpV6Header>;
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::<packet_handler::IpV4Header>;
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"),
} }
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 { if &v.len() >= insert_max {
break 'parse; break 'parse;
} }

View File

@ -16,7 +16,7 @@ const ETH_TLEN: usize = 2;
const ETHER_HDRLEN: usize = 14; const ETHER_HDRLEN: usize = 14;
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy,Serialize, Deserialize)]
pub struct EtherHeader { pub struct EtherHeader {
pub ether_dhost: MacAddress, pub ether_dhost: MacAddress,
pub ether_shost: MacAddress, pub ether_shost: MacAddress,
@ -24,7 +24,7 @@ pub struct EtherHeader {
} }
// TODO: implement optional ethernet vlan shim header fields // TODO: implement optional ethernet vlan shim header fields
pub fn ethernet_handler(packet_data: &[u8]) -> EtherHeader { pub fn ethernet_handler(packet_data: &[u8]) -> Option<EtherHeader> {
let mut _ether_dhost: [u8; ETH_ALEN] = [0; ETH_ALEN]; let mut _ether_dhost: [u8; ETH_ALEN] = [0; ETH_ALEN];
let mut _ether_shost: [u8; ETH_ALEN] = [0; ETH_ALEN]; let mut _ether_shost: [u8; ETH_ALEN] = [0; ETH_ALEN];
let mut _ether_type: u16 = 0; 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_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]); _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_dhost: (MacAddress::new(_ether_dhost as Eui48)),
ether_shost: (MacAddress::new(_ether_shost as Eui48)), ether_shost: (MacAddress::new(_ether_shost as Eui48)),
ether_type: _ether_type as i32, ether_type: _ether_type as i32,
} })
} }
/* ip */ /* ip */
@ -224,9 +224,9 @@ pub struct ArpHeader {
pub hlen: u8, pub hlen: u8,
pub plen: u8, pub plen: u8,
pub oper: u16, pub oper: u16,
pub sha: Eui48, pub sha: MacAddress,
pub spa: IpAddr, pub spa: IpAddr,
pub tha: Eui48, pub tha: MacAddress,
pub tpa: IpAddr, pub tpa: IpAddr,
} }
@ -248,12 +248,10 @@ pub fn arp_handler(packet_data: &[u8]) -> Option<ArpHeader> {
hlen: raw_hdr[4], hlen: raw_hdr[4],
plen: raw_hdr[5], plen: raw_hdr[5],
oper: BigEndian::read_u16(&raw_hdr[6..8]), oper: BigEndian::read_u16(&raw_hdr[6..8]),
//sha: MacAddress::new(_sha as Eui48).to_hex_string().to_owned(), sha: MacAddress::new(_sha as Eui48),
sha: _sha,
spa: IpAddr::V4(Ipv4Addr::from(BigEndian::read_u32(&raw_hdr[14..18]))), spa: IpAddr::V4(Ipv4Addr::from(BigEndian::read_u32(&raw_hdr[14..18]))),
//tha: MacAddress::new( _tha as Eui48 ).to_hex_string().to_owned(), tha: MacAddress::new( _tha as Eui48 ),
tha: _tha, tpa: IpAddr::V4(Ipv4Addr::from(BigEndian::read_u32(&raw_hdr[24..28]))),
tpa: IpAddr::V4(Ipv4Addr::from(BigEndian::read_u32(&raw_hdr[24..28]))),
}) })
} }

View File

@ -14,9 +14,7 @@ impl Serialize for parser::QryData {
{ {
let mut state = serializer.serialize_struct("parser::QryData", 11)?; let mut state = serializer.serialize_struct("parser::QryData", 11)?;
state.serialize_field("time", &self.time)?; 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", &self.ether_header)?;
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("ipv4_header", &self.ipv4_header)?; state.serialize_field("ipv4_header", &self.ipv4_header)?;
state.serialize_field("ipv6_header", &self.ipv6_header)?; state.serialize_field("ipv6_header", &self.ipv6_header)?;
state.serialize_field("tcp_header", &self.tcp_header)?; state.serialize_field("tcp_header", &self.tcp_header)?;