From 60882e92544e38e5eecdffab14445550cdbc47f4 Mon Sep 17 00:00:00 2001 From: pythops Date: Wed, 11 Sep 2024 13:27:40 +0200 Subject: [PATCH] update parsing logic --- oryx-common/Cargo.toml | 3 + oryx-common/src/arp.rs | 47 +++++++ oryx-common/src/ip.rs | 83 ++++++++++++ oryx-common/src/lib.rs | 300 +++++++++++++++++++---------------------- 4 files changed, 270 insertions(+), 163 deletions(-) create mode 100644 oryx-common/src/arp.rs create mode 100644 oryx-common/src/ip.rs diff --git a/oryx-common/Cargo.toml b/oryx-common/Cargo.toml index 099e7b7..d557905 100644 --- a/oryx-common/Cargo.toml +++ b/oryx-common/Cargo.toml @@ -11,3 +11,6 @@ edition.workspace = true [lib] path = "src/lib.rs" + +[dependencies] +network-types = { git = "https://github.com/vadorovsky/network-types.git", rev = "e0ee8d5" } diff --git a/oryx-common/src/arp.rs b/oryx-common/src/arp.rs new file mode 100644 index 0000000..d224aec --- /dev/null +++ b/oryx-common/src/arp.rs @@ -0,0 +1,47 @@ +use core::fmt::Display; + +#[derive(Debug, Copy, Clone)] +pub struct ArpPacket { + pub arp_type: ArpType, + pub src_mac: MacAddr, + pub dst_mac: MacAddr, +} + +impl Display for ArpPacket { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{} {} ARP", self.src_mac, self.dst_mac) + } +} + +#[derive(Debug, Copy, Clone)] +pub enum ArpType { + Request, + Reply, +} + +impl Display for ArpType { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::Request => write!(f, "Arp Request"), + Self::Reply => write!(f, "Arp Reply"), + } + } +} + +#[derive(Debug, Copy, Clone)] +pub struct MacAddr(pub [u8; 6]); + +impl Display for MacAddr { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!( + f, + "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}", + self.0[0].to_be(), + self.0[1].to_be(), + self.0[2].to_be(), + self.0[3].to_be(), + self.0[4].to_be(), + self.0[5].to_be() + ) + } +} diff --git a/oryx-common/src/ip.rs b/oryx-common/src/ip.rs new file mode 100644 index 0000000..ecdcf3e --- /dev/null +++ b/oryx-common/src/ip.rs @@ -0,0 +1,83 @@ +use core::{fmt::Display, net::IpAddr}; + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct TcpPacket { + pub dst_port: u16, + pub src_port: u16, + pub dst_ip: IpAddr, + pub src_ip: IpAddr, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct UdpPacket { + pub dst_port: u16, + pub src_port: u16, + pub dst_ip: IpAddr, + pub src_ip: IpAddr, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct IcmpPacket { + pub icmp_type: IcmpType, + pub dst_ip: IpAddr, + pub src_ip: IpAddr, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub enum IcmpType { + EchoRequest, + EchoReply, + DestinationUnreachable, +} + +impl Display for IcmpType { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + IcmpType::EchoReply => { + write!(f, "Echo Reply") + } + IcmpType::EchoRequest => { + write!(f, "Echo Request") + } + IcmpType::DestinationUnreachable => { + write!(f, "Destination Unreachable") + } + } + } +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub enum IpPacket { + Tcp(TcpPacket), + Udp(UdpPacket), + Icmp(IcmpPacket), +} + +impl Display for IpPacket { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + IpPacket::Tcp(p) => { + write!( + f, + "{} {} {} {} TCP", + p.src_ip, p.src_port, p.dst_ip, p.dst_port + ) + } + IpPacket::Udp(p) => { + write!( + f, + "{} {} {} {} UDP", + p.src_ip, p.src_port, p.dst_ip, p.dst_port + ) + } + IpPacket::Icmp(p) => { + write!(f, "{} {} ICMP", p.src_ip, p.dst_ip) + } + } + } +} diff --git a/oryx-common/src/lib.rs b/oryx-common/src/lib.rs index bf24a28..bada2f7 100644 --- a/oryx-common/src/lib.rs +++ b/oryx-common/src/lib.rs @@ -2,192 +2,166 @@ use core::{ fmt::Display, - net::{IpAddr, Ipv4Addr, Ipv6Addr}, + mem, + net::{IpAddr, Ipv4Addr}, }; -impl From<[u8; 40]> for IpPacket { - fn from(value: [u8; 40]) -> Self { - match value[0] { - // TCP - 0 => { - let (src_ip, dst_ip) = if value[6] == 0 { - let dst_ip: [u8; 4] = value[7..11].try_into().unwrap(); - let dst_ip = IpAddr::V4(Ipv4Addr::from(dst_ip)); - - let src_ip: [u8; 4] = value[24..28].try_into().unwrap(); - let src_ip = IpAddr::V4(Ipv4Addr::from(src_ip)); - - (src_ip, dst_ip) - } else { - let dst_ip: [u8; 16] = value[7..23].try_into().unwrap(); - let dst_ip = IpAddr::V6(Ipv6Addr::from(dst_ip)); - - let src_ip: [u8; 16] = value[24..40].try_into().unwrap(); - let src_ip = IpAddr::V6(Ipv6Addr::from(src_ip)); - (src_ip, dst_ip) - }; - - let src_port = u16::from_be_bytes([value[5], value[4]]); - let dst_port = u16::from_be_bytes([value[3], value[2]]); - - IpPacket::Tcp(TcpPacket { - src_ip, - dst_ip, - src_port, - dst_port, - }) - } - - // UDP - 1 => { - let (src_ip, dst_ip) = if value[6] == 0 { - let dst_ip: [u8; 4] = value[7..11].try_into().unwrap(); - let dst_ip = IpAddr::V4(Ipv4Addr::from(dst_ip)); - - let src_ip: [u8; 4] = value[24..28].try_into().unwrap(); - let src_ip = IpAddr::V4(Ipv4Addr::from(src_ip)); - - (src_ip, dst_ip) - } else { - let dst_ip: [u8; 16] = value[7..23].try_into().unwrap(); - let dst_ip = IpAddr::V6(Ipv6Addr::from(dst_ip)); - - let src_ip: [u8; 16] = value[24..40].try_into().unwrap(); - let src_ip = IpAddr::V6(Ipv6Addr::from(src_ip)); - (src_ip, dst_ip) - }; - let src_port = u16::from_be_bytes([value[5], value[4]]); - let dst_port = u16::from_be_bytes([value[3], value[2]]); - - IpPacket::Udp(UdpPacket { - src_ip, - dst_ip, - src_port, - dst_port, - }) - } - - // ICMP - 2 => { - let (src_ip, dst_ip) = if value[2] == 0 { - let dst_ip: [u8; 4] = value[3..7].try_into().unwrap(); - let dst_ip = IpAddr::V4(Ipv4Addr::from(dst_ip)); - - let src_ip: [u8; 4] = value[20..24].try_into().unwrap(); - let src_ip = IpAddr::V4(Ipv4Addr::from(src_ip)); - - (src_ip, dst_ip) - } else { - let dst_ip: [u8; 16] = value[3..19].try_into().unwrap(); - let dst_ip = IpAddr::V6(Ipv6Addr::from(dst_ip)); +use arp::{ArpPacket, ArpType, MacAddr}; +use ip::{IcmpPacket, IcmpType, IpPacket, TcpPacket, UdpPacket}; +use network_types::{ + arp::ArpHdr, + icmp::IcmpHdr, + ip::{IpHdr, IpProto, Ipv4Hdr}, + tcp::TcpHdr, + udp::UdpHdr, +}; - let src_ip: [u8; 16] = value[20..36].try_into().unwrap(); - let src_ip = IpAddr::V6(Ipv6Addr::from(src_ip)); - (src_ip, dst_ip) - }; - let icmp_type = match value[1] { - 0 => IcmpType::EchoRequest, - 1 => IcmpType::EchoReply, - _ => IcmpType::DestinationUnreachable, - }; +pub mod arp; +pub mod ip; - IpPacket::Icmp(IcmpPacket { - src_ip, - dst_ip, - icmp_type, - }) - } - _ => { - panic!("Error: unknown IP packet type") - } - } - } -} - -#[derive(Debug, Copy, Clone)] #[repr(C)] -pub struct TcpPacket { - pub dst_port: u16, - pub src_port: u16, - pub dst_ip: IpAddr, - pub src_ip: IpAddr, +pub enum RawPacket { + Ip(IpHdr), + Arp(ArpHdr), } -#[derive(Debug, Copy, Clone)] -#[repr(C)] -pub struct UdpPacket { - pub dst_port: u16, - pub src_port: u16, - pub dst_ip: IpAddr, - pub src_ip: IpAddr, +impl RawPacket { + pub const LEN: usize = mem::size_of::(); } #[derive(Debug, Copy, Clone)] #[repr(C)] -pub struct IcmpPacket { - pub icmp_type: IcmpType, - pub dst_ip: IpAddr, - pub src_ip: IpAddr, +pub enum AppPacket { + Ip(IpPacket), + Arp(ArpPacket), } -#[derive(Debug, Copy, Clone)] -#[repr(u8)] -pub enum IcmpType { - EchoRequest, - EchoReply, - DestinationUnreachable, +impl AppPacket { + pub const LEN: usize = mem::size_of::(); } -impl Display for IcmpType { +impl Display for AppPacket { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { - IcmpType::EchoReply => { - write!(f, "Echo Reply") - } - IcmpType::EchoRequest => { - write!(f, "Echo Request") - } - IcmpType::DestinationUnreachable => { - write!(f, "Destination Unreachable") - } + Self::Arp(packet) => write!(f, "{}", packet), + Self::Ip(packet) => write!(f, "{}", packet), } } } -#[derive(Debug, Copy, Clone)] -#[repr(u8)] -pub enum IpPacket { - Tcp(TcpPacket), - Udp(UdpPacket), - Icmp(IcmpPacket), -} +impl From<[u8; RawPacket::LEN]> for AppPacket { + fn from(value: [u8; RawPacket::LEN]) -> Self { + let raw_packet = value.as_ptr() as *const RawPacket; + match unsafe { &*raw_packet } { + RawPacket::Ip(packet) => match packet { + IpHdr::V4(ipv4_packet) => match ipv4_packet.proto { + IpProto::Tcp => { + //FIX: This does not work + let tcphdr = + unsafe { raw_packet.add(mem::size_of::()) } as *const TcpHdr; + + let tcp_packet = TcpPacket { + src_ip: IpAddr::V4(Ipv4Addr::from(u32::from_be(ipv4_packet.src_addr))), + src_port: u16::from_be(unsafe { (*tcphdr).source }), + dst_ip: IpAddr::V4(Ipv4Addr::from(u32::from_be(ipv4_packet.dst_addr))), + dst_port: u16::from_be(unsafe { (*tcphdr).dest }), + }; + AppPacket::Ip(IpPacket::Tcp(tcp_packet)) + } + IpProto::Udp => { + let udphdr = unsafe { + raw_packet.offset(Ipv4Hdr::LEN.try_into().unwrap()) as *const UdpHdr + }; + + let udp_packet = UdpPacket { + src_ip: IpAddr::V4(Ipv4Addr::from(u32::from_be(ipv4_packet.src_addr))), + src_port: u16::from_be(unsafe { (*udphdr).source }), + dst_ip: IpAddr::V4(Ipv4Addr::from(u32::from_be(ipv4_packet.dst_addr))), + dst_port: u16::from_be(unsafe { (*udphdr).dest }), + }; + Self::Ip(IpPacket::Udp(udp_packet)) + } + IpProto::Icmp => { + let icmphdr = unsafe { + raw_packet.offset(Ipv4Hdr::LEN.try_into().unwrap()) as *const IcmpHdr + }; + + let icmp_type = match unsafe { (*icmphdr).type_ } { + 0 => IcmpType::EchoRequest, + 1 => IcmpType::EchoReply, + _ => IcmpType::DestinationUnreachable, + }; + + let icmp_packet = IcmpPacket { + src_ip: IpAddr::V4(Ipv4Addr::from(u32::from_be(ipv4_packet.src_addr))), + dst_ip: IpAddr::V4(Ipv4Addr::from(u32::from_be(ipv4_packet.dst_addr))), + icmp_type, + }; + Self::Ip(IpPacket::Icmp(icmp_packet)) + } + _ => unreachable!(), + }, + IpHdr::V6(ipv6_packet) => match ipv6_packet.next_hdr { + IpProto::Tcp => { + let tcphdr = unsafe { + raw_packet.offset(Ipv4Hdr::LEN.try_into().unwrap()) as *const TcpHdr + }; + + let tcp_packet = TcpPacket { + src_ip: IpAddr::V6(ipv6_packet.src_addr()), + src_port: u16::from_be(unsafe { (*tcphdr).source }), + dst_ip: IpAddr::V6(ipv6_packet.dst_addr()), + dst_port: u16::from_be(unsafe { (*tcphdr).dest }), + }; + Self::Ip(IpPacket::Tcp(tcp_packet)) + } + IpProto::Udp => { + let udphdr = unsafe { + raw_packet.offset(Ipv4Hdr::LEN.try_into().unwrap()) as *const UdpHdr + }; + + let udp_packet = UdpPacket { + src_ip: IpAddr::V6(ipv6_packet.src_addr()), + src_port: u16::from_be(unsafe { (*udphdr).source }), + dst_ip: IpAddr::V6(ipv6_packet.dst_addr()), + dst_port: u16::from_be(unsafe { (*udphdr).dest }), + }; + Self::Ip(IpPacket::Udp(udp_packet)) + } + IpProto::Icmp => { + let icmphdr = unsafe { + raw_packet.offset(Ipv4Hdr::LEN.try_into().unwrap()) as *const IcmpHdr + }; + + let icmp_type = match unsafe { (*icmphdr).type_ } { + 0 => IcmpType::EchoRequest, + 1 => IcmpType::EchoReply, + _ => IcmpType::DestinationUnreachable, + }; + + let icmp_packet = IcmpPacket { + src_ip: IpAddr::V6(ipv6_packet.src_addr()), + dst_ip: IpAddr::V6(ipv6_packet.dst_addr()), + icmp_type, + }; + Self::Ip(IpPacket::Icmp(icmp_packet)) + } + _ => unreachable!(), + }, + }, + RawPacket::Arp(packet) => { + let arp_type = match u16::from_be(packet.oper) { + 1 => ArpType::Request, + 2 => ArpType::Reply, + _ => unreachable!(), + }; -impl Display for IpPacket { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - IpPacket::Tcp(p) => { - write!( - f, - "{} {} {} {} TCP", - p.src_ip, p.src_port, p.dst_ip, p.dst_port - ) - } - IpPacket::Udp(p) => { - write!( - f, - "{} {} {} {} UDP", - p.src_ip, p.src_port, p.dst_ip, p.dst_port - ) - } - IpPacket::Icmp(p) => { - write!(f, "{} {} ICMP", p.src_ip, p.dst_ip) + Self::Arp(ArpPacket { + arp_type, + src_mac: MacAddr(packet.sha), + dst_mac: MacAddr(packet.tha), + }) } } } } - -#[derive(Debug, Copy, Clone)] -#[repr(u8)] -pub enum Packet { - Ip(IpPacket), -}