use pnet::packet::ethernet::{EthernetPacket, EtherTypes};
use pnet::packet::ipv4::Ipv4Packet;
use pnet::packet::ipv6::Ipv6Packet;
use pnet::packet::tcp::TcpPacket;
use pnet::packet::udp::UdpPacket;
use pnet::packet::Packet;
use std::net::IpAddr;
use std::time::{SystemTime, UNIX_EPOCH};
#[derive(Debug)]
pub struct ParsedPacket {
pub timestamp: u64,
pub interface_name: String,
pub source_ip: Option<IpAddr>,
pub destination_ip: Option<IpAddr>,
pub source_port: Option<u16>,
pub destination_port: Option<u16>,
pub protocol: String,
pub packet_size: usize,
}
pub fn parse_packet(interface_name: String, packet: &[u8]) -> ParsedPacket {
let timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Time went backwards")
.as_nanos() as u64;
let packet_size = packet.len();
let mut parsed_packet = ParsedPacket {
timestamp,
interface_name,
source_ip: None,
destination_ip: None,
source_port: None,
destination_port: None,
protocol: "Other".to_string(),
packet_size,
};
if let Some(ethernet_packet) = EthernetPacket::new(packet) {
match ethernet_packet.get_ethertype() {
EtherTypes::Ipv4 => {
if let Some(ipv4_packet) = Ipv4Packet::new(ethernet_packet.payload()) {
parsed_packet.source_ip = Some(IpAddr::V4(ipv4_packet.get_source()));
parsed_packet.destination_ip = Some(IpAddr::V4(ipv4_packet.get_destination()));
let proto = ipv4_packet.get_next_level_protocol();
parsed_packet.protocol = format!("{:?}", proto);
match proto {
pnet::packet::ip::IpNextHeaderProtocols::Tcp => {
if let Some(tcp_packet) = TcpPacket::new(ipv4_packet.payload()) {
parsed_packet.source_port = Some(tcp_packet.get_source());
parsed_packet.destination_port = Some(tcp_packet.get_destination());
}
}
pnet::packet::ip::IpNextHeaderProtocols::Udp => {
if let Some(udp_packet) = UdpPacket::new(ipv4_packet.payload()) {
parsed_packet.source_port = Some(udp_packet.get_source());
parsed_packet.destination_port = Some(udp_packet.get_destination());
}
}
_ => {}
}
}
}
EtherTypes::Ipv6 => {
if let Some(ipv6_packet) = Ipv6Packet::new(ethernet_packet.payload()) {
parsed_packet.source_ip = Some(IpAddr::V6(ipv6_packet.get_source()));
parsed_packet.destination_ip = Some(IpAddr::V6(ipv6_packet.get_destination()));
let proto = ipv6_packet.get_next_header();
parsed_packet.protocol = format!("{:?}", proto);
match proto {
pnet::packet::ip::IpNextHeaderProtocols::Tcp => {
if let Some(tcp_packet) = TcpPacket::new(ipv6_packet.payload()) {
parsed_packet.source_port = Some(tcp_packet.get_source());
parsed_packet.destination_port = Some(tcp_packet.get_destination());
}
}
pnet::packet::ip::IpNextHeaderProtocols::Udp => {
if let Some(udp_packet) = UdpPacket::new(ipv6_packet.payload()) {
parsed_packet.source_port = Some(udp_packet.get_source());
parsed_packet.destination_port = Some(udp_packet.get_destination());
}
}
_ => {}
}
}
}
_ => {}
}
}
parsed_packet
}