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 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<Vec<u8>>,
pub ether_header: packet_handler::EtherHeader,
pub ether_header: Option<packet_handler::EtherHeader>,
pub ipv4_header: Option<packet_handler::IpV4Header>,
pub ipv6_header: Option<packet_handler::IpV6Header>,
pub tcp_header: Option<packet_handler::TcpHeader>,
@ -50,12 +41,11 @@ pub struct QryData {
}
fn init_qrydata( ) -> Result<QryData, core::fmt::Error> {
let ether_init = build_ether();
Ok(QryData {
id: 0,
time: 0.0,
data: None,
ether_header: ether_init,
ether_header: None::<packet_handler::EtherHeader>,
ipv4_header: None::<packet_handler::IpV4Header>,
ipv6_header: None::<packet_handler::IpV6Header>,
tcp_header: None::<packet_handler::TcpHeader>,
@ -66,9 +56,9 @@ fn init_qrydata( ) -> Result<QryData, core::fmt::Error> {
}
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<QryData> {
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::<packet_handler::IpV6Header>;
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::<packet_handler::UdpHeader>;
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::<packet_handler::TcpHeader>;
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::<packet_handler::IpV4Header>;
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::<packet_handler::UdpHeader>;
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::<packet_handler::TcpHeader>;
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<QryData> {
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();
match pkg.ipv4_header.unwrap().ip_protocol as usize {
TCP => {
pkg.udp_header = None::<packet_handler::UdpHeader>;
pkg.tcp_header = Some(packet_handler::tcp_handler(
pkg.ipv4_header.unwrap().ip_ihl,
packet_data,
@ -161,7 +141,6 @@ impl QryData {
)).unwrap();
}
UDP => {
pkg.tcp_header = None::<packet_handler::TcpHeader>;
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,82 +206,19 @@ pub fn parse_device(parse_device: &str, filter_str: &str, insert_max: &usize, re
let mut v: Vec<QryData> = 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() {
match linktype {
Linktype(1) => me = QryData::encap_ether(packet.data).unwrap(),
Linktype(101) => me = QryData::encap_rawip(packet.data).unwrap(),
_ => (),
}
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::<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,
});
v.push(me.clone());
if &v.len() >= insert_max {
break 'parse;

View File

@ -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<EtherHeader> {
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,11 +248,9 @@ pub fn arp_handler(packet_data: &[u8]) -> Option<ArpHeader> {
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,
tha: MacAddress::new( _tha as Eui48 ),
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)?;
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)?;