use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct NetworkPacket {
pub timestamp: DateTime<Utc>,
pub ethernet_layer: EthernetFrame,
pub ip_layer: IPv4Packet,
pub tcp_layer: TCPSegment,
pub application_layer: ApplicationData,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct EthernetFrame {
pub source_mac: [u8; 6],
pub destination_mac: [u8; 6],
pub ethertype: u16, pub frame_check_sequence: u32,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct IPv4Packet {
pub version: u8, pub ihl: u8, pub dscp: u8, pub ecn: u8, pub total_length: u16,
pub identification: u16,
pub flags: IPv4Flags,
pub fragment_offset: u16,
pub ttl: u8, pub protocol: u8, pub header_checksum: u16,
pub source_ip: [u8; 4],
pub destination_ip: [u8; 4],
pub options: Vec<u8>, }
#[derive(Debug, Serialize, Deserialize)]
pub struct IPv4Flags {
pub reserved: bool, pub dont_fragment: bool,
pub more_fragments: bool,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct TCPSegment {
pub source_port: u16,
pub destination_port: u16,
pub sequence_number: u32,
pub acknowledgment_number: u32,
pub data_offset: u8, pub flags: TCPFlags,
pub window_size: u16,
pub checksum: u16,
pub urgent_pointer: u16,
pub options: Vec<TCPOption>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct TCPFlags {
pub fin: bool, pub syn: bool, pub rst: bool, pub psh: bool, pub ack: bool, pub urg: bool, pub ece: bool, pub cwr: bool, }
#[derive(Debug, Serialize, Deserialize)]
pub struct TCPOption {
pub kind: u8,
pub length: u8,
pub data: Vec<u8>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ApplicationData {
pub protocol: ApplicationProtocol,
pub payload: Vec<u8>,
}
#[derive(Debug, Serialize, Deserialize)]
pub enum ApplicationProtocol {
HTTP,
HTTPS,
FTP,
SSH,
SMTP,
DNS,
Custom(String),
}
impl NetworkPacket {
pub fn total_size(&self) -> usize {
14 + 20 + self.ip_layer.options.len() + 20 + self.tcp_layer.options.iter().map(|opt| opt.length as usize).sum::<usize>() + self.application_layer.payload.len() }
pub fn is_handshake(&self) -> bool {
self.tcp_layer.flags.syn || self.tcp_layer.flags.fin
}
pub fn get_protocol_string(&self) -> String {
match &self.application_layer.protocol {
ApplicationProtocol::HTTP => "HTTP".to_string(),
ApplicationProtocol::HTTPS => "HTTPS".to_string(),
ApplicationProtocol::FTP => "FTP".to_string(),
ApplicationProtocol::SSH => "SSH".to_string(),
ApplicationProtocol::SMTP => "SMTP".to_string(),
ApplicationProtocol::DNS => "DNS".to_string(),
ApplicationProtocol::Custom(proto) => proto.clone(),
}
}
}